Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Ondřej Hruška | 2e0e9aedd0 | 2 years ago |
@ -0,0 +1,2 @@ |
|||||||
|
# Classify all '.function' files as C for syntax highlighting purposes |
||||||
|
*.function linguist-language=C |
@ -0,0 +1,35 @@ |
|||||||
|
--- |
||||||
|
name: Bug report |
||||||
|
about: To report a bug, please fill this form. |
||||||
|
title: '' |
||||||
|
labels: '' |
||||||
|
assignees: '' |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
### Summary |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### System information |
||||||
|
|
||||||
|
Mbed TLS version (number or commit id): |
||||||
|
Operating system and version: |
||||||
|
Configuration (if not default, please attach `mbedtls_config.h`): |
||||||
|
Compiler and options (if you used a pre-built binary, please indicate how you obtained it): |
||||||
|
Additional environment information: |
||||||
|
|
||||||
|
### Expected behavior |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Actual behavior |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Steps to reproduce |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Additional information |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
blank_issues_enabled: false |
||||||
|
contact_links: |
||||||
|
- name: Mbed TLS security team |
||||||
|
url: mailto:mbed-tls-security@lists.trustedfirmware.org |
||||||
|
about: Report a security vulnerability. |
||||||
|
- name: Mbed TLS mailing list |
||||||
|
url: https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org |
||||||
|
about: Mbed TLS community support and general discussion. |
@ -0,0 +1,17 @@ |
|||||||
|
--- |
||||||
|
name: Enhancement request |
||||||
|
about: To request an enhancement, please fill this form. |
||||||
|
title: '' |
||||||
|
labels: '' |
||||||
|
assignees: '' |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
### Suggested enhancement |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Justification |
||||||
|
|
||||||
|
Mbed TLS needs this because |
||||||
|
|
@ -0,0 +1,19 @@ |
|||||||
|
## Description |
||||||
|
|
||||||
|
Please write a few sentences describing the overall goals of the pull request's commits. |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Gatekeeper checklist |
||||||
|
|
||||||
|
- [ ] **changelog** provided, or not required |
||||||
|
- [ ] **backport** done, or not required |
||||||
|
- [ ] **tests** provided, or not required |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Notes for the submitter |
||||||
|
|
||||||
|
Please refer to the [contributing guidelines](https://github.com/Mbed-TLS/mbedtls/blob/development/CONTRIBUTING.md), especially the |
||||||
|
checklist for PR contributors. |
||||||
|
|
@ -0,0 +1,59 @@ |
|||||||
|
# Random seed file created by test scripts and sample programs |
||||||
|
seedfile |
||||||
|
|
||||||
|
# CMake build artifacts: |
||||||
|
CMakeCache.txt |
||||||
|
CMakeFiles |
||||||
|
CTestTestfile.cmake |
||||||
|
cmake_install.cmake |
||||||
|
Testing |
||||||
|
# CMake generates *.dir/ folders for in-tree builds (used by MSVC projects), ignore all of those: |
||||||
|
*.dir/ |
||||||
|
# MSVC files generated by CMake: |
||||||
|
/*.sln |
||||||
|
/*.vcxproj |
||||||
|
/*.filters |
||||||
|
|
||||||
|
# Test coverage build artifacts: |
||||||
|
Coverage |
||||||
|
*.gcno |
||||||
|
*.gcda |
||||||
|
coverage-summary.txt |
||||||
|
|
||||||
|
# generated by scripts/memory.sh |
||||||
|
massif-* |
||||||
|
|
||||||
|
# Eclipse project files |
||||||
|
.cproject |
||||||
|
.project |
||||||
|
/.settings |
||||||
|
|
||||||
|
# MSVC build artifacts: |
||||||
|
*.exe |
||||||
|
*.pdb |
||||||
|
*.ilk |
||||||
|
*.lib |
||||||
|
|
||||||
|
# Python build artifacts: |
||||||
|
*.pyc |
||||||
|
|
||||||
|
# CMake generates *.dir/ folders for in-tree builds (used by MSVC projects), ignore all of those: |
||||||
|
*.dir/ |
||||||
|
|
||||||
|
# Microsoft CMake extension for Visual Studio Code generates a build directory by default |
||||||
|
/build/ |
||||||
|
|
||||||
|
# Generated documentation: |
||||||
|
/apidoc |
||||||
|
|
||||||
|
# PSA Crypto compliance test repo, cloned by test_psa_compliance.py |
||||||
|
/psa-arch-tests |
||||||
|
|
||||||
|
# Editor navigation files: |
||||||
|
/GPATH |
||||||
|
/GRTAGS |
||||||
|
/GSYMS |
||||||
|
/GTAGS |
||||||
|
/TAGS |
||||||
|
/cscope*.out |
||||||
|
/tags |
@ -0,0 +1,3 @@ |
|||||||
|
default:\ |
||||||
|
:langmap=c\:.c.h.function:\ |
||||||
|
|
@ -0,0 +1,4 @@ |
|||||||
|
[mypy] |
||||||
|
mypy_path = scripts |
||||||
|
namespace_packages = True |
||||||
|
warn_unused_configs = True |
@ -0,0 +1,79 @@ |
|||||||
|
[MASTER] |
||||||
|
init-hook='import sys; sys.path.append("scripts")' |
||||||
|
|
||||||
|
[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 |
||||||
|
|
||||||
|
# No upper limit on method names. Pylint <2.1.0 has an upper limit of 30. |
||||||
|
# [invalid-name] |
||||||
|
method-rgx=[a-z_][a-z0-9_]{2,}$ |
||||||
|
|
||||||
|
# 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=_.* |
||||||
|
|
||||||
|
[SIMILARITIES] |
||||||
|
# Ignore imports when computing similarities. |
||||||
|
ignore-imports=yes |
@ -0,0 +1,104 @@ |
|||||||
|
# Declare python as our language. This way we get our chosen Python version, |
||||||
|
# and pip is available. Gcc and clang are available anyway. |
||||||
|
language: python |
||||||
|
python: 3.5 |
||||||
|
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 |
||||||
|
- gcc-arm-linux-gnueabi |
||||||
|
- libc6-dev-armel-cross |
||||||
|
script: |
||||||
|
- tests/scripts/all.sh -k 'check_*' |
||||||
|
- tests/scripts/all.sh -k test_default_out_of_box |
||||||
|
- tests/scripts/all.sh -k test_ref_configs |
||||||
|
- tests/scripts/all.sh -k build_arm_linux_gnueabi_gcc_arm5vte build_arm_none_eabi_gcc_m0plus |
||||||
|
|
||||||
|
- name: full configuration |
||||||
|
os: linux |
||||||
|
dist: focal |
||||||
|
addons: |
||||||
|
apt: |
||||||
|
packages: |
||||||
|
- clang-10 |
||||||
|
- gnutls-bin |
||||||
|
script: |
||||||
|
# Do a manual build+test sequence rather than using all.sh, |
||||||
|
# because there's no all.sh component that does what we want, |
||||||
|
# which is a build with Clang >= 10 and ASan, running all the SSL |
||||||
|
# testing. |
||||||
|
# - The clang executable in the default PATH is Clang 7 on |
||||||
|
# Travis's focal instances, but we want Clang >= 10. |
||||||
|
# - Running all the SSL testing requires a specific set of |
||||||
|
# OpenSSL and GnuTLS versions and we don't want to bother |
||||||
|
# with those on Travis. |
||||||
|
# So we explicitly select clang-10 as the compiler, and we |
||||||
|
# have ad hoc restrictions on SSL testing based on what is |
||||||
|
# passing at the time of writing. We will remove these limitations |
||||||
|
# gradually. |
||||||
|
- make generated_files |
||||||
|
- make CC=clang-10 CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all -O2' LDFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all' |
||||||
|
- make test |
||||||
|
- programs/test/selftest |
||||||
|
- tests/scripts/test_psa_constant_names.py |
||||||
|
- tests/ssl-opt.sh |
||||||
|
# Modern OpenSSL does not support fixed ECDH or null ciphers. |
||||||
|
- tests/compat.sh -p OpenSSL -e 'NULL\|ECDH-' |
||||||
|
- tests/scripts/travis-log-failure.sh |
||||||
|
# GnuTLS supports CAMELLIA but compat.sh doesn't properly enable it. |
||||||
|
- tests/compat.sh -p GnuTLS -e 'CAMELLIA' |
||||||
|
- tests/scripts/travis-log-failure.sh |
||||||
|
- tests/context-info.sh |
||||||
|
|
||||||
|
- name: Windows |
||||||
|
os: windows |
||||||
|
# The language 'python' is currently unsupported on the |
||||||
|
# Windows Build Environment. And 'generic' causes the job to get stuck |
||||||
|
# on "Booting virtual machine". |
||||||
|
language: c |
||||||
|
before_install: |
||||||
|
- choco install python --version=3.5.4 |
||||||
|
env: |
||||||
|
# Add the directory where the Choco packages go |
||||||
|
- PATH=/c/Python35:/c/Python35/Scripts:$PATH |
||||||
|
- PYTHON=python.exe |
||||||
|
script: |
||||||
|
- type perl; perl --version |
||||||
|
- type python; python --version |
||||||
|
- scripts/make_generated_files.bat |
||||||
|
# Logs appear out of sequence on Windows. Give time to catch up. |
||||||
|
- sleep 5 |
||||||
|
- scripts/windows_msbuild.bat v141 # Visual Studio 2017 |
||||||
|
|
||||||
|
after_failure: |
||||||
|
- tests/scripts/travis-log-failure.sh |
||||||
|
|
||||||
|
env: |
||||||
|
global: |
||||||
|
- SEED=1 |
||||||
|
- secure: "JECCru6HASpKZ0OLfHh8f/KXhKkdrCwjquZghd/qbA4ksxsWImjR7KEPERcaPndXEilzhDbKwuFvJiQX2duVgTGoq745YGhLZIjzo1i8tySkceCVd48P8WceYGz+F/bmY7r+m6fFNuxDSoGGSVeA4Lnjvmm8PFUP45YodDV9no4=" |
||||||
|
|
||||||
|
install: |
||||||
|
- $PYTHON scripts/min_requirements.py |
||||||
|
|
||||||
|
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 |
@ -0,0 +1 @@ |
|||||||
|
/Makefile |
@ -0,0 +1,5 @@ |
|||||||
|
execute_process(COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/mbedtls_config.h get MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED RESULT_VARIABLE result) |
||||||
|
|
||||||
|
if(${result} EQUAL 0) |
||||||
|
add_subdirectory(everest) |
||||||
|
endif() |
@ -0,0 +1,2 @@ |
|||||||
|
THIRDPARTY_DIR = $(dir $(lastword $(MAKEFILE_LIST))) |
||||||
|
include $(THIRDPARTY_DIR)/everest/Makefile.inc |
@ -0,0 +1,2 @@ |
|||||||
|
*.o |
||||||
|
Makefile |
@ -0,0 +1,27 @@ |
|||||||
|
add_library(everest |
||||||
|
library/everest.c |
||||||
|
library/x25519.c |
||||||
|
library/Hacl_Curve25519_joined.c) |
||||||
|
|
||||||
|
target_include_directories(everest |
||||||
|
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> |
||||||
|
$<BUILD_INTERFACE:${MBEDTLS_DIR}/include> |
||||||
|
$<INSTALL_INTERFACE:include> |
||||||
|
PRIVATE include/everest |
||||||
|
include/everest/kremlib |
||||||
|
${MBEDTLS_DIR}/library/) |
||||||
|
|
||||||
|
if(INSTALL_MBEDTLS_HEADERS) |
||||||
|
|
||||||
|
install(DIRECTORY include/everest |
||||||
|
DESTINATION include |
||||||
|
FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ |
||||||
|
DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE |
||||||
|
FILES_MATCHING PATTERN "*.h") |
||||||
|
|
||||||
|
endif(INSTALL_MBEDTLS_HEADERS) |
||||||
|
|
||||||
|
install(TARGETS everest |
||||||
|
EXPORT MbedTLSTargets |
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR} |
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) |
@ -0,0 +1,6 @@ |
|||||||
|
THIRDPARTY_INCLUDES+=-I../3rdparty/everest/include -I../3rdparty/everest/include/everest -I../3rdparty/everest/include/everest/kremlib |
||||||
|
|
||||||
|
THIRDPARTY_CRYPTO_OBJECTS+= \ |
||||||
|
../3rdparty/everest/library/everest.o \ |
||||||
|
../3rdparty/everest/library/x25519.o \ |
||||||
|
../3rdparty/everest/library/Hacl_Curve25519_joined.o |
@ -0,0 +1,5 @@ |
|||||||
|
The files in this directory stem from [Project Everest](https://project-everest.github.io/) and are distributed under the Apache 2.0 license. |
||||||
|
|
||||||
|
This is a formally verified implementation of Curve25519-based handshakes. The C code is automatically derived from the (verified) [original implementation](https://github.com/project-everest/hacl-star/tree/master/code/curve25519) in the [F* language](https://github.com/fstarlang/fstar) by [KreMLin](https://github.com/fstarlang/kremlin). In addition to the improved safety and security of the implementation, it is also significantly faster than the default implementation of Curve25519 in mbedTLS. |
||||||
|
|
||||||
|
The caveat is that not all platforms are supported, although the version in `everest/library/legacy` should work on most systems. The main issue is that some platforms do not provide a 128-bit integer type and KreMLin therefore has to use additional (also verified) code to simulate them, resulting in less of a performance gain overall. Explicitly supported platforms are currently `x86` and `x86_64` using gcc or clang, and Visual C (2010 and later). |
@ -0,0 +1,21 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>
|
||||||
|
* KreMLin invocation: /mnt/e/everest/verify/kremlin/krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -fbuiltin-uint128 -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -I /mnt/e/everest/verify/hacl-star/code/lib/kremlin -I /mnt/e/everest/verify/kremlin/kremlib/compat -I /mnt/e/everest/verify/hacl-star/specs -I /mnt/e/everest/verify/hacl-star/specs/old -I . -ccopt -march=native -verbose -ldopt -flto -tmpdir x25519-c -I ../bignum -bundle Hacl.Curve25519=* -minimal -add-include "kremlib.h" -skip-compilation x25519-c/out.krml -o x25519-c/Hacl_Curve25519.c |
||||||
|
* F* version: 059db0c8 |
||||||
|
* KreMLin version: 916c37ac |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __Hacl_Curve25519_H |
||||||
|
#define __Hacl_Curve25519_H |
||||||
|
|
||||||
|
|
||||||
|
#include "kremlib.h" |
||||||
|
|
||||||
|
void Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint); |
||||||
|
|
||||||
|
#define __Hacl_Curve25519_H_DEFINED |
||||||
|
#endif |
@ -0,0 +1,234 @@ |
|||||||
|
/*
|
||||||
|
* Interface to code from Project Everest |
||||||
|
* |
||||||
|
* Copyright 2016-2018 INRIA and Microsoft Corporation |
||||||
|
* 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_EVEREST_H |
||||||
|
#define MBEDTLS_EVEREST_H |
||||||
|
|
||||||
|
#include "everest/x25519.h" |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the source of the imported EC key. |
||||||
|
*/ |
||||||
|
typedef enum |
||||||
|
{ |
||||||
|
MBEDTLS_EVEREST_ECDH_OURS, /**< Our key. */ |
||||||
|
MBEDTLS_EVEREST_ECDH_THEIRS, /**< The key of the peer. */ |
||||||
|
} mbedtls_everest_ecdh_side; |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
mbedtls_x25519_context ctx; |
||||||
|
} mbedtls_ecdh_context_everest; |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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. |
||||||
|
* \param grp_id The group id of the group to set up the context for. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
*/ |
||||||
|
int mbedtls_everest_setup( mbedtls_ecdh_context_everest *ctx, int grp_id ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function frees a context. |
||||||
|
* |
||||||
|
* \param ctx The context to free. |
||||||
|
*/ |
||||||
|
void mbedtls_everest_free( mbedtls_ecdh_context_everest *ctx ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function generates a public key and a TLS |
||||||
|
* ServerKeyExchange payload. |
||||||
|
* |
||||||
|
* This is the second function used by a TLS server for ECDHE |
||||||
|
* ciphersuites. (It is called after mbedtls_ecdh_setup().) |
||||||
|
* |
||||||
|
* \note This function assumes that the ECP group (grp) of the |
||||||
|
* \p ctx context has already been properly set, |
||||||
|
* for example, using mbedtls_ecp_group_load(). |
||||||
|
* |
||||||
|
* \see ecp.h |
||||||
|
* |
||||||
|
* \param ctx The ECDH context. |
||||||
|
* \param olen The number of characters written. |
||||||
|
* \param buf The destination buffer. |
||||||
|
* \param blen The length of the destination buffer. |
||||||
|
* \param f_rng The RNG function. |
||||||
|
* \param p_rng The RNG context. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
*/ |
||||||
|
int mbedtls_everest_make_params( mbedtls_ecdh_context_everest *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 a TLS ServerKeyExchange |
||||||
|
* payload. |
||||||
|
* |
||||||
|
* This is the first function used by a TLS client for ECDHE |
||||||
|
* ciphersuites. |
||||||
|
* |
||||||
|
* \see ecp.h |
||||||
|
* |
||||||
|
* \param ctx The ECDH context. |
||||||
|
* \param buf The pointer to the start of the input buffer. |
||||||
|
* \param end The address for one Byte past the end of the buffer. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
* |
||||||
|
*/ |
||||||
|
int mbedtls_everest_read_params( mbedtls_ecdh_context_everest *ctx, |
||||||
|
const unsigned char **buf, const unsigned char *end ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function parses and processes a TLS ServerKeyExchange |
||||||
|
* payload. |
||||||
|
* |
||||||
|
* This is the first function used by a TLS client for ECDHE |
||||||
|
* ciphersuites. |
||||||
|
* |
||||||
|
* \see ecp.h |
||||||
|
* |
||||||
|
* \param ctx The ECDH context. |
||||||
|
* \param buf The pointer to the start of the input buffer. |
||||||
|
* \param end The address for one Byte past the end of the buffer. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
* |
||||||
|
*/ |
||||||
|
int mbedtls_everest_read_params( mbedtls_ecdh_context_everest *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. |
||||||
|
* \param key The EC key to use. |
||||||
|
* \param side Defines the source of the key: 1: Our key, or |
||||||
|
* 0: The key of the peer. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
* |
||||||
|
*/ |
||||||
|
int mbedtls_everest_get_params( mbedtls_ecdh_context_everest *ctx, const mbedtls_ecp_keypair *key, |
||||||
|
mbedtls_everest_ecdh_side side ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function generates a public key and 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. |
||||||
|
* \param olen The number of Bytes written. |
||||||
|
* \param buf The destination buffer. |
||||||
|
* \param blen The size of the destination buffer. |
||||||
|
* \param f_rng The RNG function. |
||||||
|
* \param p_rng The RNG context. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
*/ |
||||||
|
int mbedtls_everest_make_public( mbedtls_ecdh_context_everest *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 a TLS ClientKeyExchange |
||||||
|
* payload. |
||||||
|
* |
||||||
|
* 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. |
||||||
|
* \param buf The start of the input buffer. |
||||||
|
* \param blen The length of the input buffer. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
*/ |
||||||
|
int mbedtls_everest_read_public( mbedtls_ecdh_context_everest *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. |
||||||
|
* \param olen The number of Bytes written. |
||||||
|
* \param buf The destination buffer. |
||||||
|
* \param blen The length of the destination buffer. |
||||||
|
* \param f_rng The RNG function. |
||||||
|
* \param p_rng The RNG context. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
*/ |
||||||
|
int mbedtls_everest_calc_secret( mbedtls_ecdh_context_everest *ctx, size_t *olen, |
||||||
|
unsigned char *buf, size_t blen, |
||||||
|
int( *f_rng )( void *, unsigned char *, size_t ), |
||||||
|
void *p_rng ); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif /* MBEDTLS_EVEREST_H */ |
@ -0,0 +1,29 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2016-2018 INRIA and Microsoft Corporation |
||||||
|
* |
||||||
|
* 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) and
|
||||||
|
* originated from Project Everest (https://project-everest.github.io/)
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __KREMLIB_H |
||||||
|
#define __KREMLIB_H |
||||||
|
|
||||||
|
#include "kremlin/internal/target.h" |
||||||
|
#include "kremlin/internal/types.h" |
||||||
|
#include "kremlin/c_endianness.h" |
||||||
|
|
||||||
|
#endif /* __KREMLIB_H */ |
@ -0,0 +1,124 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>
|
||||||
|
* KreMLin invocation: ../krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrB9w -minimal -fparentheses -fcurly-braces -fno-shadow -header copyright-header.txt -minimal -tmpdir dist/uint128 -skip-compilation -extract-uints -add-include <inttypes.h> -add-include <stdbool.h> -add-include "kremlin/internal/types.h" -bundle FStar.UInt128=* extracted/prims.krml extracted/FStar_Pervasives_Native.krml extracted/FStar_Pervasives.krml extracted/FStar_Mul.krml extracted/FStar_Squash.krml extracted/FStar_Classical.krml extracted/FStar_StrongExcludedMiddle.krml extracted/FStar_FunctionalExtensionality.krml extracted/FStar_List_Tot_Base.krml extracted/FStar_List_Tot_Properties.krml extracted/FStar_List_Tot.krml extracted/FStar_Seq_Base.krml extracted/FStar_Seq_Properties.krml extracted/FStar_Seq.krml extracted/FStar_Math_Lib.krml extracted/FStar_Math_Lemmas.krml extracted/FStar_BitVector.krml extracted/FStar_UInt.krml extracted/FStar_UInt32.krml extracted/FStar_Int.krml extracted/FStar_Int16.krml extracted/FStar_Preorder.krml extracted/FStar_Ghost.krml extracted/FStar_ErasedLogic.krml extracted/FStar_UInt64.krml extracted/FStar_Set.krml extracted/FStar_PropositionalExtensionality.krml extracted/FStar_PredicateExtensionality.krml extracted/FStar_TSet.krml extracted/FStar_Monotonic_Heap.krml extracted/FStar_Heap.krml extracted/FStar_Map.krml extracted/FStar_Monotonic_HyperHeap.krml extracted/FStar_Monotonic_HyperStack.krml extracted/FStar_HyperStack.krml extracted/FStar_Monotonic_Witnessed.krml extracted/FStar_HyperStack_ST.krml extracted/FStar_HyperStack_All.krml extracted/FStar_Date.krml extracted/FStar_Universe.krml extracted/FStar_GSet.krml extracted/FStar_ModifiesGen.krml extracted/LowStar_Monotonic_Buffer.krml extracted/LowStar_Buffer.krml extracted/Spec_Loops.krml extracted/LowStar_BufferOps.krml extracted/C_Loops.krml extracted/FStar_UInt8.krml extracted/FStar_Kremlin_Endianness.krml extracted/FStar_UInt63.krml extracted/FStar_Exn.krml extracted/FStar_ST.krml extracted/FStar_All.krml extracted/FStar_Dyn.krml extracted/FStar_Int63.krml extracted/FStar_Int64.krml extracted/FStar_Int32.krml extracted/FStar_Int8.krml extracted/FStar_UInt16.krml extracted/FStar_Int_Cast.krml extracted/FStar_UInt128.krml extracted/C_Endianness.krml extracted/FStar_List.krml extracted/FStar_Float.krml extracted/FStar_IO.krml extracted/C.krml extracted/FStar_Char.krml extracted/FStar_String.krml extracted/LowStar_Modifies.krml extracted/C_String.krml extracted/FStar_Bytes.krml extracted/FStar_HyperStack_IO.krml extracted/C_Failure.krml extracted/TestLib.krml extracted/FStar_Int_Cast_Full.krml |
||||||
|
* F* version: 059db0c8 |
||||||
|
* KreMLin version: 916c37ac |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __FStar_UInt128_H |
||||||
|
#define __FStar_UInt128_H |
||||||
|
|
||||||
|
|
||||||
|
#include <inttypes.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include "kremlin/internal/types.h" |
||||||
|
|
||||||
|
uint64_t FStar_UInt128___proj__Mkuint128__item__low(FStar_UInt128_uint128 projectee); |
||||||
|
|
||||||
|
uint64_t FStar_UInt128___proj__Mkuint128__item__high(FStar_UInt128_uint128 projectee); |
||||||
|
|
||||||
|
typedef FStar_UInt128_uint128 FStar_UInt128_t; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_add_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_sub_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s); |
||||||
|
|
||||||
|
bool FStar_UInt128_eq(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
bool FStar_UInt128_gt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
bool FStar_UInt128_lt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
bool FStar_UInt128_gte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
bool FStar_UInt128_lte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a); |
||||||
|
|
||||||
|
uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Plus_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Plus_Question_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Plus_Percent_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Subtraction_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Subtraction_Question_Hat)( |
||||||
|
FStar_UInt128_uint128 x0, |
||||||
|
FStar_UInt128_uint128 x1 |
||||||
|
); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Subtraction_Percent_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Amp_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Hat_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Bar_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Less_Less_Hat)(FStar_UInt128_uint128 x0, uint32_t x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Greater_Greater_Hat)(FStar_UInt128_uint128 x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool (*FStar_UInt128_op_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern bool |
||||||
|
(*FStar_UInt128_op_Greater_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern bool (*FStar_UInt128_op_Less_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern bool |
||||||
|
(*FStar_UInt128_op_Greater_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern bool |
||||||
|
(*FStar_UInt128_op_Less_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_mul32(uint64_t x, uint32_t y); |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y); |
||||||
|
|
||||||
|
#define __FStar_UInt128_H_DEFINED |
||||||
|
#endif |
@ -0,0 +1,280 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>
|
||||||
|
* KreMLin invocation: ../krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrB9w -minimal -fparentheses -fcurly-braces -fno-shadow -header copyright-header.txt -minimal -tmpdir dist/minimal -skip-compilation -extract-uints -add-include <inttypes.h> -add-include <stdbool.h> -add-include "kremlin/internal/compat.h" -add-include "kremlin/internal/types.h" -bundle FStar.UInt64+FStar.UInt32+FStar.UInt16+FStar.UInt8=* extracted/prims.krml extracted/FStar_Pervasives_Native.krml extracted/FStar_Pervasives.krml extracted/FStar_Mul.krml extracted/FStar_Squash.krml extracted/FStar_Classical.krml extracted/FStar_StrongExcludedMiddle.krml extracted/FStar_FunctionalExtensionality.krml extracted/FStar_List_Tot_Base.krml extracted/FStar_List_Tot_Properties.krml extracted/FStar_List_Tot.krml extracted/FStar_Seq_Base.krml extracted/FStar_Seq_Properties.krml extracted/FStar_Seq.krml extracted/FStar_Math_Lib.krml extracted/FStar_Math_Lemmas.krml extracted/FStar_BitVector.krml extracted/FStar_UInt.krml extracted/FStar_UInt32.krml extracted/FStar_Int.krml extracted/FStar_Int16.krml extracted/FStar_Preorder.krml extracted/FStar_Ghost.krml extracted/FStar_ErasedLogic.krml extracted/FStar_UInt64.krml extracted/FStar_Set.krml extracted/FStar_PropositionalExtensionality.krml extracted/FStar_PredicateExtensionality.krml extracted/FStar_TSet.krml extracted/FStar_Monotonic_Heap.krml extracted/FStar_Heap.krml extracted/FStar_Map.krml extracted/FStar_Monotonic_HyperHeap.krml extracted/FStar_Monotonic_HyperStack.krml extracted/FStar_HyperStack.krml extracted/FStar_Monotonic_Witnessed.krml extracted/FStar_HyperStack_ST.krml extracted/FStar_HyperStack_All.krml extracted/FStar_Date.krml extracted/FStar_Universe.krml extracted/FStar_GSet.krml extracted/FStar_ModifiesGen.krml extracted/LowStar_Monotonic_Buffer.krml extracted/LowStar_Buffer.krml extracted/Spec_Loops.krml extracted/LowStar_BufferOps.krml extracted/C_Loops.krml extracted/FStar_UInt8.krml extracted/FStar_Kremlin_Endianness.krml extracted/FStar_UInt63.krml extracted/FStar_Exn.krml extracted/FStar_ST.krml extracted/FStar_All.krml extracted/FStar_Dyn.krml extracted/FStar_Int63.krml extracted/FStar_Int64.krml extracted/FStar_Int32.krml extracted/FStar_Int8.krml extracted/FStar_UInt16.krml extracted/FStar_Int_Cast.krml extracted/FStar_UInt128.krml extracted/C_Endianness.krml extracted/FStar_List.krml extracted/FStar_Float.krml extracted/FStar_IO.krml extracted/C.krml extracted/FStar_Char.krml extracted/FStar_String.krml extracted/LowStar_Modifies.krml extracted/C_String.krml extracted/FStar_Bytes.krml extracted/FStar_HyperStack_IO.krml extracted/C_Failure.krml extracted/TestLib.krml extracted/FStar_Int_Cast_Full.krml |
||||||
|
* F* version: 059db0c8 |
||||||
|
* KreMLin version: 916c37ac |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8_H |
||||||
|
#define __FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8_H |
||||||
|
|
||||||
|
|
||||||
|
#include <inttypes.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include "kremlin/internal/compat.h" |
||||||
|
#include "kremlin/internal/types.h" |
||||||
|
|
||||||
|
extern Prims_int FStar_UInt64_n; |
||||||
|
|
||||||
|
extern Prims_int FStar_UInt64_v(uint64_t x0); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_uint_to_t(Prims_int x0); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_add(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_add_underspec(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_add_mod(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_sub(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_sub_underspec(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_sub_mod(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_mul(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_mul_underspec(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_mul_mod(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_mul_div(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_div(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_rem(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_logand(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_logxor(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_logor(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_lognot(uint64_t x0); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_shift_right(uint64_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_shift_left(uint64_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt64_eq(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt64_gt(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt64_gte(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt64_lt(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt64_lte(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_minus(uint64_t x0); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt64_n_minus_one; |
||||||
|
|
||||||
|
uint64_t FStar_UInt64_eq_mask(uint64_t a, uint64_t b); |
||||||
|
|
||||||
|
uint64_t FStar_UInt64_gte_mask(uint64_t a, uint64_t b); |
||||||
|
|
||||||
|
extern Prims_string FStar_UInt64_to_string(uint64_t x0); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_of_string(Prims_string x0); |
||||||
|
|
||||||
|
extern Prims_int FStar_UInt32_n; |
||||||
|
|
||||||
|
extern Prims_int FStar_UInt32_v(uint32_t x0); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_uint_to_t(Prims_int x0); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_add(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_add_underspec(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_add_mod(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_sub(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_sub_underspec(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_sub_mod(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_mul(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_mul_underspec(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_mul_mod(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_mul_div(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_div(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_rem(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_logand(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_logxor(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_logor(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_lognot(uint32_t x0); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_shift_right(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_shift_left(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt32_eq(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt32_gt(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt32_gte(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt32_lt(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt32_lte(uint32_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_minus(uint32_t x0); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_n_minus_one; |
||||||
|
|
||||||
|
uint32_t FStar_UInt32_eq_mask(uint32_t a, uint32_t b); |
||||||
|
|
||||||
|
uint32_t FStar_UInt32_gte_mask(uint32_t a, uint32_t b); |
||||||
|
|
||||||
|
extern Prims_string FStar_UInt32_to_string(uint32_t x0); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt32_of_string(Prims_string x0); |
||||||
|
|
||||||
|
extern Prims_int FStar_UInt16_n; |
||||||
|
|
||||||
|
extern Prims_int FStar_UInt16_v(uint16_t x0); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_uint_to_t(Prims_int x0); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_add(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_add_underspec(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_add_mod(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_sub(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_sub_underspec(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_sub_mod(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_mul(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_mul_underspec(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_mul_mod(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_mul_div(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_div(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_rem(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_logand(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_logxor(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_logor(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_lognot(uint16_t x0); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_shift_right(uint16_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_shift_left(uint16_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt16_eq(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt16_gt(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt16_gte(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt16_lt(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt16_lte(uint16_t x0, uint16_t x1); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_minus(uint16_t x0); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt16_n_minus_one; |
||||||
|
|
||||||
|
uint16_t FStar_UInt16_eq_mask(uint16_t a, uint16_t b); |
||||||
|
|
||||||
|
uint16_t FStar_UInt16_gte_mask(uint16_t a, uint16_t b); |
||||||
|
|
||||||
|
extern Prims_string FStar_UInt16_to_string(uint16_t x0); |
||||||
|
|
||||||
|
extern uint16_t FStar_UInt16_of_string(Prims_string x0); |
||||||
|
|
||||||
|
extern Prims_int FStar_UInt8_n; |
||||||
|
|
||||||
|
extern Prims_int FStar_UInt8_v(uint8_t x0); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_uint_to_t(Prims_int x0); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_add(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_add_underspec(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_add_mod(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_sub(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_sub_underspec(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_sub_mod(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_mul(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_mul_underspec(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_mul_mod(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_mul_div(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_div(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_rem(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_logand(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_logxor(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_logor(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_lognot(uint8_t x0); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_shift_right(uint8_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_shift_left(uint8_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt8_eq(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt8_gt(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt8_gte(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt8_lt(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern bool FStar_UInt8_lte(uint8_t x0, uint8_t x1); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_minus(uint8_t x0); |
||||||
|
|
||||||
|
extern uint32_t FStar_UInt8_n_minus_one; |
||||||
|
|
||||||
|
uint8_t FStar_UInt8_eq_mask(uint8_t a, uint8_t b); |
||||||
|
|
||||||
|
uint8_t FStar_UInt8_gte_mask(uint8_t a, uint8_t b); |
||||||
|
|
||||||
|
extern Prims_string FStar_UInt8_to_string(uint8_t x0); |
||||||
|
|
||||||
|
extern uint8_t FStar_UInt8_of_string(Prims_string x0); |
||||||
|
|
||||||
|
typedef uint8_t FStar_UInt8_byte; |
||||||
|
|
||||||
|
#define __FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8_H_DEFINED |
||||||
|
#endif |
@ -0,0 +1,204 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
#ifndef __KREMLIN_ENDIAN_H |
||||||
|
#define __KREMLIN_ENDIAN_H |
||||||
|
|
||||||
|
#include <string.h> |
||||||
|
#include <inttypes.h> |
||||||
|
|
||||||
|
/******************************************************************************/ |
||||||
|
/* Implementing C.fst (part 2: endian-ness macros) */ |
||||||
|
/******************************************************************************/ |
||||||
|
|
||||||
|
/* ... for Linux */ |
||||||
|
#if defined(__linux__) || defined(__CYGWIN__) |
||||||
|
# include <endian.h> |
||||||
|
|
||||||
|
/* ... for OSX */ |
||||||
|
#elif defined(__APPLE__) |
||||||
|
# include <libkern/OSByteOrder.h> |
||||||
|
# define htole64(x) OSSwapHostToLittleInt64(x) |
||||||
|
# define le64toh(x) OSSwapLittleToHostInt64(x) |
||||||
|
# define htobe64(x) OSSwapHostToBigInt64(x) |
||||||
|
# define be64toh(x) OSSwapBigToHostInt64(x) |
||||||
|
|
||||||
|
# define htole16(x) OSSwapHostToLittleInt16(x) |
||||||
|
# define le16toh(x) OSSwapLittleToHostInt16(x) |
||||||
|
# define htobe16(x) OSSwapHostToBigInt16(x) |
||||||
|
# define be16toh(x) OSSwapBigToHostInt16(x) |
||||||
|
|
||||||
|
# define htole32(x) OSSwapHostToLittleInt32(x) |
||||||
|
# define le32toh(x) OSSwapLittleToHostInt32(x) |
||||||
|
# define htobe32(x) OSSwapHostToBigInt32(x) |
||||||
|
# define be32toh(x) OSSwapBigToHostInt32(x) |
||||||
|
|
||||||
|
/* ... for Solaris */ |
||||||
|
#elif defined(__sun__) |
||||||
|
# include <sys/byteorder.h> |
||||||
|
# define htole64(x) LE_64(x) |
||||||
|
# define le64toh(x) LE_64(x) |
||||||
|
# define htobe64(x) BE_64(x) |
||||||
|
# define be64toh(x) BE_64(x) |
||||||
|
|
||||||
|
# define htole16(x) LE_16(x) |
||||||
|
# define le16toh(x) LE_16(x) |
||||||
|
# define htobe16(x) BE_16(x) |
||||||
|
# define be16toh(x) BE_16(x) |
||||||
|
|
||||||
|
# define htole32(x) LE_32(x) |
||||||
|
# define le32toh(x) LE_32(x) |
||||||
|
# define htobe32(x) BE_32(x) |
||||||
|
# define be32toh(x) BE_32(x) |
||||||
|
|
||||||
|
/* ... for the BSDs */ |
||||||
|
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) |
||||||
|
# include <sys/endian.h> |
||||||
|
#elif defined(__OpenBSD__) |
||||||
|
# include <endian.h> |
||||||
|
|
||||||
|
/* ... for Windows (MSVC)... not targeting XBOX 360! */ |
||||||
|
#elif defined(_MSC_VER) |
||||||
|
|
||||||
|
# include <stdlib.h> |
||||||
|
# define htobe16(x) _byteswap_ushort(x) |
||||||
|
# define htole16(x) (x) |
||||||
|
# define be16toh(x) _byteswap_ushort(x) |
||||||
|
# define le16toh(x) (x) |
||||||
|
|
||||||
|
# define htobe32(x) _byteswap_ulong(x) |
||||||
|
# define htole32(x) (x) |
||||||
|
# define be32toh(x) _byteswap_ulong(x) |
||||||
|
# define le32toh(x) (x) |
||||||
|
|
||||||
|
# define htobe64(x) _byteswap_uint64(x) |
||||||
|
# define htole64(x) (x) |
||||||
|
# define be64toh(x) _byteswap_uint64(x) |
||||||
|
# define le64toh(x) (x) |
||||||
|
|
||||||
|
/* ... for Windows (GCC-like, e.g. mingw or clang) */ |
||||||
|
#elif (defined(_WIN32) || defined(_WIN64)) && \ |
||||||
|
(defined(__GNUC__) || defined(__clang__)) |
||||||
|
|
||||||
|
# define htobe16(x) __builtin_bswap16(x) |
||||||
|
# define htole16(x) (x) |
||||||
|
# define be16toh(x) __builtin_bswap16(x) |
||||||
|
# define le16toh(x) (x) |
||||||
|
|
||||||
|
# define htobe32(x) __builtin_bswap32(x) |
||||||
|
# define htole32(x) (x) |
||||||
|
# define be32toh(x) __builtin_bswap32(x) |
||||||
|
# define le32toh(x) (x) |
||||||
|
|
||||||
|
# define htobe64(x) __builtin_bswap64(x) |
||||||
|
# define htole64(x) (x) |
||||||
|
# define be64toh(x) __builtin_bswap64(x) |
||||||
|
# define le64toh(x) (x) |
||||||
|
|
||||||
|
/* ... generic big-endian fallback code */ |
||||||
|
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
||||||
|
|
||||||
|
/* byte swapping code inspired by:
|
||||||
|
* https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h
|
||||||
|
* */ |
||||||
|
|
||||||
|
# define htobe32(x) (x) |
||||||
|
# define be32toh(x) (x) |
||||||
|
# define htole32(x) \ |
||||||
|
(__extension__({ \
|
||||||
|
uint32_t _temp = (x); \
|
||||||
|
((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \
|
||||||
|
((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \
|
||||||
|
})) |
||||||
|
# define le32toh(x) (htole32((x))) |
||||||
|
|
||||||
|
# define htobe64(x) (x) |
||||||
|
# define be64toh(x) (x) |
||||||
|
# define htole64(x) \ |
||||||
|
(__extension__({ \
|
||||||
|
uint64_t __temp = (x); \
|
||||||
|
uint32_t __low = htobe32((uint32_t)__temp); \
|
||||||
|
uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
|
||||||
|
(((uint64_t)__low) << 32) | __high; \
|
||||||
|
})) |
||||||
|
# define le64toh(x) (htole64((x))) |
||||||
|
|
||||||
|
/* ... generic little-endian fallback code */ |
||||||
|
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
||||||
|
|
||||||
|
# define htole32(x) (x) |
||||||
|
# define le32toh(x) (x) |
||||||
|
# define htobe32(x) \ |
||||||
|
(__extension__({ \
|
||||||
|
uint32_t _temp = (x); \
|
||||||
|
((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \
|
||||||
|
((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \
|
||||||
|
})) |
||||||
|
# define be32toh(x) (htobe32((x))) |
||||||
|
|
||||||
|
# define htole64(x) (x) |
||||||
|
# define le64toh(x) (x) |
||||||
|
# define htobe64(x) \ |
||||||
|
(__extension__({ \
|
||||||
|
uint64_t __temp = (x); \
|
||||||
|
uint32_t __low = htobe32((uint32_t)__temp); \
|
||||||
|
uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
|
||||||
|
(((uint64_t)__low) << 32) | __high; \
|
||||||
|
})) |
||||||
|
# define be64toh(x) (htobe64((x))) |
||||||
|
|
||||||
|
/* ... couldn't determine endian-ness of the target platform */ |
||||||
|
#else |
||||||
|
# error "Please define __BYTE_ORDER__!" |
||||||
|
|
||||||
|
#endif /* defined(__linux__) || ... */ |
||||||
|
|
||||||
|
/* Loads and stores. These avoid undefined behavior due to unaligned memory
|
||||||
|
* accesses, via memcpy. */ |
||||||
|
|
||||||
|
inline static uint16_t load16(uint8_t *b) { |
||||||
|
uint16_t x; |
||||||
|
memcpy(&x, b, 2); |
||||||
|
return x; |
||||||
|
} |
||||||
|
|
||||||
|
inline static uint32_t load32(uint8_t *b) { |
||||||
|
uint32_t x; |
||||||
|
memcpy(&x, b, 4); |
||||||
|
return x; |
||||||
|
} |
||||||
|
|
||||||
|
inline static uint64_t load64(uint8_t *b) { |
||||||
|
uint64_t x; |
||||||
|
memcpy(&x, b, 8); |
||||||
|
return x; |
||||||
|
} |
||||||
|
|
||||||
|
inline static void store16(uint8_t *b, uint16_t i) { |
||||||
|
memcpy(b, &i, 2); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void store32(uint8_t *b, uint32_t i) { |
||||||
|
memcpy(b, &i, 4); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void store64(uint8_t *b, uint64_t i) { |
||||||
|
memcpy(b, &i, 8); |
||||||
|
} |
||||||
|
|
||||||
|
#define load16_le(b) (le16toh(load16(b))) |
||||||
|
#define store16_le(b, i) (store16(b, htole16(i))) |
||||||
|
#define load16_be(b) (be16toh(load16(b))) |
||||||
|
#define store16_be(b, i) (store16(b, htobe16(i))) |
||||||
|
|
||||||
|
#define load32_le(b) (le32toh(load32(b))) |
||||||
|
#define store32_le(b, i) (store32(b, htole32(i))) |
||||||
|
#define load32_be(b) (be32toh(load32(b))) |
||||||
|
#define store32_be(b, i) (store32(b, htobe32(i))) |
||||||
|
|
||||||
|
#define load64_le(b) (le64toh(load64(b))) |
||||||
|
#define store64_le(b, i) (store64(b, htole64(i))) |
||||||
|
#define load64_be(b) (be64toh(load64(b))) |
||||||
|
#define store64_be(b, i) (store64(b, htobe64(i))) |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,16 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
#ifndef __KREMLIN_BUILTIN_H |
||||||
|
#define __KREMLIN_BUILTIN_H |
||||||
|
|
||||||
|
/* For alloca, when using KreMLin's -falloca */ |
||||||
|
#if (defined(_WIN32) || defined(_WIN64)) |
||||||
|
# include <malloc.h> |
||||||
|
#endif |
||||||
|
|
||||||
|
/* If some globals need to be initialized before the main, then kremlin will
|
||||||
|
* generate and try to link last a function with this type: */ |
||||||
|
void kremlinit_globals(void); |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,46 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
#ifndef __KREMLIN_CALLCONV_H |
||||||
|
#define __KREMLIN_CALLCONV_H |
||||||
|
|
||||||
|
/******************************************************************************/ |
||||||
|
/* Some macros to ease compatibility */ |
||||||
|
/******************************************************************************/ |
||||||
|
|
||||||
|
/* We want to generate __cdecl safely without worrying about it being undefined.
|
||||||
|
* When using MSVC, these are always defined. When using MinGW, these are |
||||||
|
* defined too. They have no meaning for other platforms, so we define them to |
||||||
|
* be empty macros in other situations. */ |
||||||
|
#ifndef _MSC_VER |
||||||
|
#ifndef __cdecl |
||||||
|
#define __cdecl |
||||||
|
#endif |
||||||
|
#ifndef __stdcall |
||||||
|
#define __stdcall |
||||||
|
#endif |
||||||
|
#ifndef __fastcall |
||||||
|
#define __fastcall |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
|
||||||
|
/* Since KreMLin emits the inline keyword unconditionally, we follow the
|
||||||
|
* guidelines at https://gcc.gnu.org/onlinedocs/gcc/Inline.html and make this
|
||||||
|
* __inline__ to ensure the code compiles with -std=c90 and earlier. */ |
||||||
|
#ifdef __GNUC__ |
||||||
|
# define inline __inline__ |
||||||
|
#endif |
||||||
|
|
||||||
|
/* GCC-specific attribute syntax; everyone else gets the standard C inline
|
||||||
|
* attribute. */ |
||||||
|
#ifdef __GNU_C__ |
||||||
|
# ifndef __clang__ |
||||||
|
# define force_inline inline __attribute__((always_inline)) |
||||||
|
# else |
||||||
|
# define force_inline inline |
||||||
|
# endif |
||||||
|
#else |
||||||
|
# define force_inline inline |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,34 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
#ifndef KRML_COMPAT_H |
||||||
|
#define KRML_COMPAT_H |
||||||
|
|
||||||
|
#include <inttypes.h> |
||||||
|
|
||||||
|
/* A series of macros that define C implementations of types that are not Low*,
|
||||||
|
* to facilitate porting programs to Low*. */ |
||||||
|
|
||||||
|
typedef const char *Prims_string; |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
uint32_t length; |
||||||
|
const char *data; |
||||||
|
} FStar_Bytes_bytes; |
||||||
|
|
||||||
|
typedef int32_t Prims_pos, Prims_nat, Prims_nonzero, Prims_int, |
||||||
|
krml_checked_int_t; |
||||||
|
|
||||||
|
#define RETURN_OR(x) \ |
||||||
|
do { \
|
||||||
|
int64_t __ret = x; \
|
||||||
|
if (__ret < INT32_MIN || INT32_MAX < __ret) { \
|
||||||
|
KRML_HOST_PRINTF( \
|
||||||
|
"Prims.{int,nat,pos} integer overflow at %s:%d\n", __FILE__, \
|
||||||
|
__LINE__); \
|
||||||
|
KRML_HOST_EXIT(252); \
|
||||||
|
} \
|
||||||
|
return (int32_t)__ret; \
|
||||||
|
} while (0) |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,57 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
#ifndef __KREMLIN_DEBUG_H |
||||||
|
#define __KREMLIN_DEBUG_H |
||||||
|
|
||||||
|
#include <inttypes.h> |
||||||
|
|
||||||
|
#include "kremlin/internal/target.h" |
||||||
|
|
||||||
|
/******************************************************************************/ |
||||||
|
/* Debugging helpers - intended only for KreMLin developers */ |
||||||
|
/******************************************************************************/ |
||||||
|
|
||||||
|
/* In support of "-wasm -d force-c": we might need this function to be
|
||||||
|
* forward-declared, because the dependency on WasmSupport appears very late, |
||||||
|
* after SimplifyWasm, and sadly, after the topological order has been done. */ |
||||||
|
void WasmSupport_check_buffer_size(uint32_t s); |
||||||
|
|
||||||
|
/* A series of GCC atrocities to trace function calls (kremlin's [-d c-calls]
|
||||||
|
* option). Useful when trying to debug, say, Wasm, to compare traces. */ |
||||||
|
/* clang-format off */ |
||||||
|
#ifdef __GNUC__ |
||||||
|
#define KRML_FORMAT(X) _Generic((X), \ |
||||||
|
uint8_t : "0x%08" PRIx8, \
|
||||||
|
uint16_t: "0x%08" PRIx16, \
|
||||||
|
uint32_t: "0x%08" PRIx32, \
|
||||||
|
uint64_t: "0x%08" PRIx64, \
|
||||||
|
int8_t : "0x%08" PRIx8, \
|
||||||
|
int16_t : "0x%08" PRIx16, \
|
||||||
|
int32_t : "0x%08" PRIx32, \
|
||||||
|
int64_t : "0x%08" PRIx64, \
|
||||||
|
default : "%s") |
||||||
|
|
||||||
|
#define KRML_FORMAT_ARG(X) _Generic((X), \ |
||||||
|
uint8_t : X, \
|
||||||
|
uint16_t: X, \
|
||||||
|
uint32_t: X, \
|
||||||
|
uint64_t: X, \
|
||||||
|
int8_t : X, \
|
||||||
|
int16_t : X, \
|
||||||
|
int32_t : X, \
|
||||||
|
int64_t : X, \
|
||||||
|
default : "unknown") |
||||||
|
/* clang-format on */ |
||||||
|
|
||||||
|
# define KRML_DEBUG_RETURN(X) \ |
||||||
|
({ \
|
||||||
|
__auto_type _ret = (X); \
|
||||||
|
KRML_HOST_PRINTF("returning: "); \
|
||||||
|
KRML_HOST_PRINTF(KRML_FORMAT(_ret), KRML_FORMAT_ARG(_ret)); \
|
||||||
|
KRML_HOST_PRINTF(" \n"); \
|
||||||
|
_ret; \
|
||||||
|
}) |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,102 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
#ifndef __KREMLIN_TARGET_H |
||||||
|
#define __KREMLIN_TARGET_H |
||||||
|
|
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <inttypes.h> |
||||||
|
#include <limits.h> |
||||||
|
|
||||||
|
#include "kremlin/internal/callconv.h" |
||||||
|
|
||||||
|
/******************************************************************************/ |
||||||
|
/* Macros that KreMLin will generate. */ |
||||||
|
/******************************************************************************/ |
||||||
|
|
||||||
|
/* For "bare" targets that do not have a C stdlib, the user might want to use
|
||||||
|
* [-add-early-include '"mydefinitions.h"'] and override these. */ |
||||||
|
#ifndef KRML_HOST_PRINTF |
||||||
|
# define KRML_HOST_PRINTF printf |
||||||
|
#endif |
||||||
|
|
||||||
|
#if ( \ |
||||||
|
(defined __STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||||
|
(!(defined KRML_HOST_EPRINTF))) |
||||||
|
# define KRML_HOST_EPRINTF(...) fprintf(stderr, __VA_ARGS__) |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef KRML_HOST_EXIT |
||||||
|
# define KRML_HOST_EXIT exit |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef KRML_HOST_MALLOC |
||||||
|
# define KRML_HOST_MALLOC malloc |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef KRML_HOST_CALLOC |
||||||
|
# define KRML_HOST_CALLOC calloc |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef KRML_HOST_FREE |
||||||
|
# define KRML_HOST_FREE free |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef KRML_HOST_TIME |
||||||
|
|
||||||
|
# include <time.h> |
||||||
|
|
||||||
|
/* Prims_nat not yet in scope */ |
||||||
|
inline static int32_t krml_time() { |
||||||
|
return (int32_t)time(NULL); |
||||||
|
} |
||||||
|
|
||||||
|
# define KRML_HOST_TIME krml_time |
||||||
|
#endif |
||||||
|
|
||||||
|
/* In statement position, exiting is easy. */ |
||||||
|
#define KRML_EXIT \ |
||||||
|
do { \
|
||||||
|
KRML_HOST_PRINTF("Unimplemented function at %s:%d\n", __FILE__, __LINE__); \
|
||||||
|
KRML_HOST_EXIT(254); \
|
||||||
|
} while (0) |
||||||
|
|
||||||
|
/* In expression position, use the comma-operator and a malloc to return an
|
||||||
|
* expression of the right size. KreMLin passes t as the parameter to the macro. |
||||||
|
*/ |
||||||
|
#define KRML_EABORT(t, msg) \ |
||||||
|
(KRML_HOST_PRINTF("KreMLin abort at %s:%d\n%s\n", __FILE__, __LINE__, msg), \
|
||||||
|
KRML_HOST_EXIT(255), *((t *)KRML_HOST_MALLOC(sizeof(t)))) |
||||||
|
|
||||||
|
/* In FStar.Buffer.fst, the size of arrays is uint32_t, but it's a number of
|
||||||
|
* *elements*. Do an ugly, run-time check (some of which KreMLin can eliminate). |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifdef __GNUC__ |
||||||
|
# define _KRML_CHECK_SIZE_PRAGMA \ |
||||||
|
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"") |
||||||
|
#else |
||||||
|
# define _KRML_CHECK_SIZE_PRAGMA |
||||||
|
#endif |
||||||
|
|
||||||
|
#define KRML_CHECK_SIZE(size_elt, sz) \ |
||||||
|
do { \
|
||||||
|
_KRML_CHECK_SIZE_PRAGMA \
|
||||||
|
if (((size_t)(sz)) > ((size_t)(SIZE_MAX / (size_elt)))) { \
|
||||||
|
KRML_HOST_PRINTF( \
|
||||||
|
"Maximum allocatable size exceeded, aborting before overflow at " \
|
||||||
|
"%s:%d\n", \
|
||||||
|
__FILE__, __LINE__); \
|
||||||
|
KRML_HOST_EXIT(253); \
|
||||||
|
} \
|
||||||
|
} while (0) |
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900 |
||||||
|
# define KRML_HOST_SNPRINTF(buf, sz, fmt, arg) _snprintf_s(buf, sz, _TRUNCATE, fmt, arg) |
||||||
|
#else |
||||||
|
# define KRML_HOST_SNPRINTF(buf, sz, fmt, arg) snprintf(buf, sz, fmt, arg) |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,61 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
#ifndef KRML_TYPES_H |
||||||
|
#define KRML_TYPES_H |
||||||
|
|
||||||
|
#include <inttypes.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
/* Types which are either abstract, meaning that have to be implemented in C, or
|
||||||
|
* which are models, meaning that they are swapped out at compile-time for |
||||||
|
* hand-written C types (in which case they're marked as noextract). */ |
||||||
|
|
||||||
|
typedef uint64_t FStar_UInt64_t, FStar_UInt64_t_; |
||||||
|
typedef int64_t FStar_Int64_t, FStar_Int64_t_; |
||||||
|
typedef uint32_t FStar_UInt32_t, FStar_UInt32_t_; |
||||||
|
typedef int32_t FStar_Int32_t, FStar_Int32_t_; |
||||||
|
typedef uint16_t FStar_UInt16_t, FStar_UInt16_t_; |
||||||
|
typedef int16_t FStar_Int16_t, FStar_Int16_t_; |
||||||
|
typedef uint8_t FStar_UInt8_t, FStar_UInt8_t_; |
||||||
|
typedef int8_t FStar_Int8_t, FStar_Int8_t_; |
||||||
|
|
||||||
|
/* Only useful when building Kremlib, because it's in the dependency graph of
|
||||||
|
* FStar.Int.Cast. */ |
||||||
|
typedef uint64_t FStar_UInt63_t, FStar_UInt63_t_; |
||||||
|
typedef int64_t FStar_Int63_t, FStar_Int63_t_; |
||||||
|
|
||||||
|
typedef double FStar_Float_float; |
||||||
|
typedef uint32_t FStar_Char_char; |
||||||
|
typedef FILE *FStar_IO_fd_read, *FStar_IO_fd_write; |
||||||
|
|
||||||
|
typedef void *FStar_Dyn_dyn; |
||||||
|
|
||||||
|
typedef const char *C_String_t, *C_String_t_; |
||||||
|
|
||||||
|
typedef int exit_code; |
||||||
|
typedef FILE *channel; |
||||||
|
|
||||||
|
typedef unsigned long long TestLib_cycles; |
||||||
|
|
||||||
|
typedef uint64_t FStar_Date_dateTime, FStar_Date_timeSpan; |
||||||
|
|
||||||
|
/* The uint128 type is a special case since we offer several implementations of
|
||||||
|
* it, depending on the compiler and whether the user wants the verified |
||||||
|
* implementation or not. */ |
||||||
|
#if !defined(KRML_VERIFIED_UINT128) && defined(_MSC_VER) && defined(_M_X64) |
||||||
|
# include <emmintrin.h> |
||||||
|
typedef __m128i FStar_UInt128_uint128; |
||||||
|
#elif !defined(KRML_VERIFIED_UINT128) && !defined(_MSC_VER) |
||||||
|
typedef unsigned __int128 FStar_UInt128_uint128; |
||||||
|
#else |
||||||
|
typedef struct FStar_UInt128_uint128_s { |
||||||
|
uint64_t low; |
||||||
|
uint64_t high; |
||||||
|
} FStar_UInt128_uint128; |
||||||
|
#endif |
||||||
|
|
||||||
|
typedef FStar_UInt128_uint128 FStar_UInt128_t, FStar_UInt128_t_, uint128_t; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,5 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file is automatically included when compiling with -wasm -d force-c */ |
||||||
|
#define WasmSupport_check_buffer_size(X) |
@ -0,0 +1,21 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>
|
||||||
|
* KreMLin invocation: /mnt/e/everest/verify/kremlin/krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -I /mnt/e/everest/verify/hacl-star/code/lib/kremlin -I /mnt/e/everest/verify/kremlin/kremlib/compat -I /mnt/e/everest/verify/hacl-star/specs -I /mnt/e/everest/verify/hacl-star/specs/old -I . -ccopt -march=native -verbose -ldopt -flto -tmpdir x25519-c -I ../bignum -bundle Hacl.Curve25519=* -minimal -add-include "kremlib.h" -skip-compilation x25519-c/out.krml -o x25519-c/Hacl_Curve25519.c |
||||||
|
* F* version: 059db0c8 |
||||||
|
* KreMLin version: 916c37ac |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __Hacl_Curve25519_H |
||||||
|
#define __Hacl_Curve25519_H |
||||||
|
|
||||||
|
|
||||||
|
#include "kremlib.h" |
||||||
|
|
||||||
|
void Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint); |
||||||
|
|
||||||
|
#define __Hacl_Curve25519_H_DEFINED |
||||||
|
#endif |
@ -0,0 +1,36 @@ |
|||||||
|
/*
|
||||||
|
* Custom inttypes.h for VS2010 KreMLin requires these definitions, |
||||||
|
* but VS2010 doesn't provide them. |
||||||
|
* |
||||||
|
* Copyright 2016-2018 INRIA and Microsoft Corporation |
||||||
|
* 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 _INTTYPES_H_VS2010 |
||||||
|
#define _INTTYPES_H_VS2010 |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#ifdef _MSC_VER |
||||||
|
#define inline __inline |
||||||
|
#endif |
||||||
|
|
||||||
|
/* VS2010 unsigned long == 8 bytes */ |
||||||
|
|
||||||
|
#define PRIu64 "I64u" |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,31 @@ |
|||||||
|
/*
|
||||||
|
* Custom stdbool.h for VS2010 KreMLin requires these definitions, |
||||||
|
* but VS2010 doesn't provide them. |
||||||
|
* |
||||||
|
* Copyright 2016-2018 INRIA and Microsoft Corporation |
||||||
|
* 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 _STDBOOL_H_VS2010 |
||||||
|
#define _STDBOOL_H_VS2010 |
||||||
|
|
||||||
|
typedef int bool; |
||||||
|
|
||||||
|
static bool true = 1; |
||||||
|
static bool false = 0; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,190 @@ |
|||||||
|
/*
|
||||||
|
* ECDH with curve-optimized implementation multiplexing |
||||||
|
* |
||||||
|
* Copyright 2016-2018 INRIA and Microsoft Corporation |
||||||
|
* 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_X25519_H |
||||||
|
#define MBEDTLS_X25519_H |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
#define MBEDTLS_ECP_TLS_CURVE25519 0x1d |
||||||
|
#define MBEDTLS_X25519_KEY_SIZE_BYTES 32 |
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the source of the imported EC key. |
||||||
|
*/ |
||||||
|
typedef enum |
||||||
|
{ |
||||||
|
MBEDTLS_X25519_ECDH_OURS, /**< Our key. */ |
||||||
|
MBEDTLS_X25519_ECDH_THEIRS, /**< The key of the peer. */ |
||||||
|
} mbedtls_x25519_ecdh_side; |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The x25519 context structure. |
||||||
|
*/ |
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
unsigned char our_secret[MBEDTLS_X25519_KEY_SIZE_BYTES]; |
||||||
|
unsigned char peer_point[MBEDTLS_X25519_KEY_SIZE_BYTES]; |
||||||
|
} mbedtls_x25519_context; |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function initializes an x25519 context. |
||||||
|
* |
||||||
|
* \param ctx The x25519 context to initialize. |
||||||
|
*/ |
||||||
|
void mbedtls_x25519_init( mbedtls_x25519_context *ctx ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function frees a context. |
||||||
|
* |
||||||
|
* \param ctx The context to free. |
||||||
|
*/ |
||||||
|
void mbedtls_x25519_free( mbedtls_x25519_context *ctx ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function generates a public key and a TLS |
||||||
|
* ServerKeyExchange payload. |
||||||
|
* |
||||||
|
* This is the first function used by a TLS server for x25519. |
||||||
|
* |
||||||
|
* |
||||||
|
* \param ctx The x25519 context. |
||||||
|
* \param olen The number of characters written. |
||||||
|
* \param buf The destination buffer. |
||||||
|
* \param blen The length of the destination buffer. |
||||||
|
* \param f_rng The RNG function. |
||||||
|
* \param p_rng The RNG context. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
*/ |
||||||
|
int mbedtls_x25519_make_params( mbedtls_x25519_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 a TLS ServerKeyExchange |
||||||
|
* payload. |
||||||
|
* |
||||||
|
* |
||||||
|
* \param ctx The x25519 context. |
||||||
|
* \param buf The pointer to the start of the input buffer. |
||||||
|
* \param end The address for one Byte past the end of the buffer. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
* |
||||||
|
*/ |
||||||
|
int mbedtls_x25519_read_params( mbedtls_x25519_context *ctx, |
||||||
|
const unsigned char **buf, const unsigned char *end ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function sets up an x25519 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 x25519 context to set up. |
||||||
|
* \param key The EC key to use. |
||||||
|
* \param side Defines the source of the key: 1: Our key, or |
||||||
|
* 0: The key of the peer. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
* |
||||||
|
*/ |
||||||
|
int mbedtls_x25519_get_params( mbedtls_x25519_context *ctx, const mbedtls_ecp_keypair *key, |
||||||
|
mbedtls_x25519_ecdh_side side ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function derives and exports the shared secret. |
||||||
|
* |
||||||
|
* This is the last function used by both TLS client |
||||||
|
* and servers. |
||||||
|
* |
||||||
|
* |
||||||
|
* \param ctx The x25519 context. |
||||||
|
* \param olen The number of Bytes written. |
||||||
|
* \param buf The destination buffer. |
||||||
|
* \param blen The length of the destination buffer. |
||||||
|
* \param f_rng The RNG function. |
||||||
|
* \param p_rng The RNG context. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
*/ |
||||||
|
int mbedtls_x25519_calc_secret( mbedtls_x25519_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 generates a public key and a TLS |
||||||
|
* ClientKeyExchange payload. |
||||||
|
* |
||||||
|
* This is the second function used by a TLS client for x25519. |
||||||
|
* |
||||||
|
* \see ecp.h |
||||||
|
* |
||||||
|
* \param ctx The x25519 context. |
||||||
|
* \param olen The number of Bytes written. |
||||||
|
* \param buf The destination buffer. |
||||||
|
* \param blen The size of the destination buffer. |
||||||
|
* \param f_rng The RNG function. |
||||||
|
* \param p_rng The RNG context. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
*/ |
||||||
|
int mbedtls_x25519_make_public( mbedtls_x25519_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 a TLS ClientKeyExchange |
||||||
|
* payload. |
||||||
|
* |
||||||
|
* This is the second function used by a TLS server for x25519. |
||||||
|
* |
||||||
|
* \see ecp.h |
||||||
|
* |
||||||
|
* \param ctx The x25519 context. |
||||||
|
* \param buf The start of the input buffer. |
||||||
|
* \param blen The length of the input buffer. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. |
||||||
|
*/ |
||||||
|
int mbedtls_x25519_read_public( mbedtls_x25519_context *ctx, |
||||||
|
const unsigned char *buf, size_t blen ); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif /* x25519.h */ |
@ -0,0 +1,760 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>
|
||||||
|
* KreMLin invocation: /mnt/e/everest/verify/kremlin/krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -fbuiltin-uint128 -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -I /mnt/e/everest/verify/hacl-star/code/lib/kremlin -I /mnt/e/everest/verify/kremlin/kremlib/compat -I /mnt/e/everest/verify/hacl-star/specs -I /mnt/e/everest/verify/hacl-star/specs/old -I . -ccopt -march=native -verbose -ldopt -flto -tmpdir x25519-c -I ../bignum -bundle Hacl.Curve25519=* -minimal -add-include "kremlib.h" -skip-compilation x25519-c/out.krml -o x25519-c/Hacl_Curve25519.c |
||||||
|
* F* version: 059db0c8 |
||||||
|
* KreMLin version: 916c37ac |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#include "Hacl_Curve25519.h" |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_eq_mask(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_gte_mask(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint128_t FStar_UInt128_add(uint128_t x0, uint128_t x1); |
||||||
|
|
||||||
|
extern uint128_t FStar_UInt128_add_mod(uint128_t x0, uint128_t x1); |
||||||
|
|
||||||
|
extern uint128_t FStar_UInt128_logand(uint128_t x0, uint128_t x1); |
||||||
|
|
||||||
|
extern uint128_t FStar_UInt128_shift_right(uint128_t x0, uint32_t x1); |
||||||
|
|
||||||
|
extern uint128_t FStar_UInt128_uint64_to_uint128(uint64_t x0); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt128_uint128_to_uint64(uint128_t x0); |
||||||
|
|
||||||
|
extern uint128_t FStar_UInt128_mul_wide(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
static void Hacl_Bignum_Modulo_carry_top(uint64_t *b) |
||||||
|
{ |
||||||
|
uint64_t b4 = b[4U]; |
||||||
|
uint64_t b0 = b[0U]; |
||||||
|
uint64_t b4_ = b4 & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t b0_ = b0 + (uint64_t)19U * (b4 >> (uint32_t)51U); |
||||||
|
b[4U] = b4_; |
||||||
|
b[0U] = b0_; |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fproduct_copy_from_wide_(uint64_t *output, uint128_t *input) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint128_t xi = input[i]; |
||||||
|
output[i] = (uint64_t)xi; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void |
||||||
|
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(uint128_t *output, uint64_t *input, uint64_t s) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint128_t xi = output[i]; |
||||||
|
uint64_t yi = input[i]; |
||||||
|
output[i] = xi + (uint128_t)yi * s; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fproduct_carry_wide_(uint128_t *tmp) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint32_t ctr = i; |
||||||
|
uint128_t tctr = tmp[ctr]; |
||||||
|
uint128_t tctrp1 = tmp[ctr + (uint32_t)1U]; |
||||||
|
uint64_t r0 = (uint64_t)tctr & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint128_t c = tctr >> (uint32_t)51U; |
||||||
|
tmp[ctr] = (uint128_t)r0; |
||||||
|
tmp[ctr + (uint32_t)1U] = tctrp1 + c; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fmul_shift_reduce(uint64_t *output) |
||||||
|
{ |
||||||
|
uint64_t tmp = output[4U]; |
||||||
|
uint64_t b0; |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint32_t ctr = (uint32_t)5U - i - (uint32_t)1U; |
||||||
|
uint64_t z = output[ctr - (uint32_t)1U]; |
||||||
|
output[ctr] = z; |
||||||
|
} |
||||||
|
} |
||||||
|
output[0U] = tmp; |
||||||
|
b0 = output[0U]; |
||||||
|
output[0U] = (uint64_t)19U * b0; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_Bignum_Fmul_mul_shift_reduce_(uint128_t *output, uint64_t *input, uint64_t *input2) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
uint64_t input2i; |
||||||
|
{ |
||||||
|
uint32_t i0; |
||||||
|
for (i0 = (uint32_t)0U; i0 < (uint32_t)4U; i0 = i0 + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint64_t input2i0 = input2[i0]; |
||||||
|
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i0); |
||||||
|
Hacl_Bignum_Fmul_shift_reduce(input); |
||||||
|
} |
||||||
|
} |
||||||
|
i = (uint32_t)4U; |
||||||
|
input2i = input2[i]; |
||||||
|
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fmul_fmul(uint64_t *output, uint64_t *input, uint64_t *input2) |
||||||
|
{ |
||||||
|
uint64_t tmp[5U] = { 0U }; |
||||||
|
memcpy(tmp, input, (uint32_t)5U * sizeof input[0U]); |
||||||
|
KRML_CHECK_SIZE(sizeof (uint128_t), (uint32_t)5U); |
||||||
|
{ |
||||||
|
uint128_t t[5U]; |
||||||
|
{ |
||||||
|
uint32_t _i; |
||||||
|
for (_i = 0U; _i < (uint32_t)5U; ++_i) |
||||||
|
t[_i] = (uint128_t)(uint64_t)0U; |
||||||
|
} |
||||||
|
{ |
||||||
|
uint128_t b4; |
||||||
|
uint128_t b0; |
||||||
|
uint128_t b4_; |
||||||
|
uint128_t b0_; |
||||||
|
uint64_t i0; |
||||||
|
uint64_t i1; |
||||||
|
uint64_t i0_; |
||||||
|
uint64_t i1_; |
||||||
|
Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input2); |
||||||
|
Hacl_Bignum_Fproduct_carry_wide_(t); |
||||||
|
b4 = t[4U]; |
||||||
|
b0 = t[0U]; |
||||||
|
b4_ = b4 & (uint128_t)(uint64_t)0x7ffffffffffffU; |
||||||
|
b0_ = b0 + (uint128_t)(uint64_t)19U * (uint64_t)(b4 >> (uint32_t)51U); |
||||||
|
t[4U] = b4_; |
||||||
|
t[0U] = b0_; |
||||||
|
Hacl_Bignum_Fproduct_copy_from_wide_(output, t); |
||||||
|
i0 = output[0U]; |
||||||
|
i1 = output[1U]; |
||||||
|
i0_ = i0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
i1_ = i1 + (i0 >> (uint32_t)51U); |
||||||
|
output[0U] = i0_; |
||||||
|
output[1U] = i1_; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fsquare_fsquare__(uint128_t *tmp, uint64_t *output) |
||||||
|
{ |
||||||
|
uint64_t r0 = output[0U]; |
||||||
|
uint64_t r1 = output[1U]; |
||||||
|
uint64_t r2 = output[2U]; |
||||||
|
uint64_t r3 = output[3U]; |
||||||
|
uint64_t r4 = output[4U]; |
||||||
|
uint64_t d0 = r0 * (uint64_t)2U; |
||||||
|
uint64_t d1 = r1 * (uint64_t)2U; |
||||||
|
uint64_t d2 = r2 * (uint64_t)2U * (uint64_t)19U; |
||||||
|
uint64_t d419 = r4 * (uint64_t)19U; |
||||||
|
uint64_t d4 = d419 * (uint64_t)2U; |
||||||
|
uint128_t s0 = (uint128_t)r0 * r0 + (uint128_t)d4 * r1 + (uint128_t)d2 * r3; |
||||||
|
uint128_t s1 = (uint128_t)d0 * r1 + (uint128_t)d4 * r2 + (uint128_t)(r3 * (uint64_t)19U) * r3; |
||||||
|
uint128_t s2 = (uint128_t)d0 * r2 + (uint128_t)r1 * r1 + (uint128_t)d4 * r3; |
||||||
|
uint128_t s3 = (uint128_t)d0 * r3 + (uint128_t)d1 * r2 + (uint128_t)r4 * d419; |
||||||
|
uint128_t s4 = (uint128_t)d0 * r4 + (uint128_t)d1 * r3 + (uint128_t)r2 * r2; |
||||||
|
tmp[0U] = s0; |
||||||
|
tmp[1U] = s1; |
||||||
|
tmp[2U] = s2; |
||||||
|
tmp[3U] = s3; |
||||||
|
tmp[4U] = s4; |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fsquare_fsquare_(uint128_t *tmp, uint64_t *output) |
||||||
|
{ |
||||||
|
uint128_t b4; |
||||||
|
uint128_t b0; |
||||||
|
uint128_t b4_; |
||||||
|
uint128_t b0_; |
||||||
|
uint64_t i0; |
||||||
|
uint64_t i1; |
||||||
|
uint64_t i0_; |
||||||
|
uint64_t i1_; |
||||||
|
Hacl_Bignum_Fsquare_fsquare__(tmp, output); |
||||||
|
Hacl_Bignum_Fproduct_carry_wide_(tmp); |
||||||
|
b4 = tmp[4U]; |
||||||
|
b0 = tmp[0U]; |
||||||
|
b4_ = b4 & (uint128_t)(uint64_t)0x7ffffffffffffU; |
||||||
|
b0_ = b0 + (uint128_t)(uint64_t)19U * (uint64_t)(b4 >> (uint32_t)51U); |
||||||
|
tmp[4U] = b4_; |
||||||
|
tmp[0U] = b0_; |
||||||
|
Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp); |
||||||
|
i0 = output[0U]; |
||||||
|
i1 = output[1U]; |
||||||
|
i0_ = i0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
i1_ = i1 + (i0 >> (uint32_t)51U); |
||||||
|
output[0U] = i0_; |
||||||
|
output[1U] = i1_; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_(uint64_t *input, uint128_t *tmp, uint32_t count1) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
Hacl_Bignum_Fsquare_fsquare_(tmp, input); |
||||||
|
for (i = (uint32_t)1U; i < count1; i = i + (uint32_t)1U) |
||||||
|
Hacl_Bignum_Fsquare_fsquare_(tmp, input); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(uint64_t *output, uint64_t *input, uint32_t count1) |
||||||
|
{ |
||||||
|
KRML_CHECK_SIZE(sizeof (uint128_t), (uint32_t)5U); |
||||||
|
{ |
||||||
|
uint128_t t[5U]; |
||||||
|
{ |
||||||
|
uint32_t _i; |
||||||
|
for (_i = 0U; _i < (uint32_t)5U; ++_i) |
||||||
|
t[_i] = (uint128_t)(uint64_t)0U; |
||||||
|
} |
||||||
|
memcpy(output, input, (uint32_t)5U * sizeof input[0U]); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fsquare_fsquare_times_inplace(uint64_t *output, uint32_t count1) |
||||||
|
{ |
||||||
|
KRML_CHECK_SIZE(sizeof (uint128_t), (uint32_t)5U); |
||||||
|
{ |
||||||
|
uint128_t t[5U]; |
||||||
|
{ |
||||||
|
uint32_t _i; |
||||||
|
for (_i = 0U; _i < (uint32_t)5U; ++_i) |
||||||
|
t[_i] = (uint128_t)(uint64_t)0U; |
||||||
|
} |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Crecip_crecip(uint64_t *out, uint64_t *z) |
||||||
|
{ |
||||||
|
uint64_t buf[20U] = { 0U }; |
||||||
|
uint64_t *a0 = buf; |
||||||
|
uint64_t *t00 = buf + (uint32_t)5U; |
||||||
|
uint64_t *b0 = buf + (uint32_t)10U; |
||||||
|
uint64_t *t01; |
||||||
|
uint64_t *b1; |
||||||
|
uint64_t *c0; |
||||||
|
uint64_t *a; |
||||||
|
uint64_t *t0; |
||||||
|
uint64_t *b; |
||||||
|
uint64_t *c; |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(a0, z, (uint32_t)1U); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t00, a0, (uint32_t)2U); |
||||||
|
Hacl_Bignum_Fmul_fmul(b0, t00, z); |
||||||
|
Hacl_Bignum_Fmul_fmul(a0, b0, a0); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t00, a0, (uint32_t)1U); |
||||||
|
Hacl_Bignum_Fmul_fmul(b0, t00, b0); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t00, b0, (uint32_t)5U); |
||||||
|
t01 = buf + (uint32_t)5U; |
||||||
|
b1 = buf + (uint32_t)10U; |
||||||
|
c0 = buf + (uint32_t)15U; |
||||||
|
Hacl_Bignum_Fmul_fmul(b1, t01, b1); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)10U); |
||||||
|
Hacl_Bignum_Fmul_fmul(c0, t01, b1); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t01, c0, (uint32_t)20U); |
||||||
|
Hacl_Bignum_Fmul_fmul(t01, t01, c0); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_inplace(t01, (uint32_t)10U); |
||||||
|
Hacl_Bignum_Fmul_fmul(b1, t01, b1); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)50U); |
||||||
|
a = buf; |
||||||
|
t0 = buf + (uint32_t)5U; |
||||||
|
b = buf + (uint32_t)10U; |
||||||
|
c = buf + (uint32_t)15U; |
||||||
|
Hacl_Bignum_Fmul_fmul(c, t0, b); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t0, c, (uint32_t)100U); |
||||||
|
Hacl_Bignum_Fmul_fmul(t0, t0, c); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)50U); |
||||||
|
Hacl_Bignum_Fmul_fmul(t0, t0, b); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)5U); |
||||||
|
Hacl_Bignum_Fmul_fmul(out, t0, a); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_fsum(uint64_t *a, uint64_t *b) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint64_t xi = a[i]; |
||||||
|
uint64_t yi = b[i]; |
||||||
|
a[i] = xi + yi; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_fdifference(uint64_t *a, uint64_t *b) |
||||||
|
{ |
||||||
|
uint64_t tmp[5U] = { 0U }; |
||||||
|
uint64_t b0; |
||||||
|
uint64_t b1; |
||||||
|
uint64_t b2; |
||||||
|
uint64_t b3; |
||||||
|
uint64_t b4; |
||||||
|
memcpy(tmp, b, (uint32_t)5U * sizeof b[0U]); |
||||||
|
b0 = tmp[0U]; |
||||||
|
b1 = tmp[1U]; |
||||||
|
b2 = tmp[2U]; |
||||||
|
b3 = tmp[3U]; |
||||||
|
b4 = tmp[4U]; |
||||||
|
tmp[0U] = b0 + (uint64_t)0x3fffffffffff68U; |
||||||
|
tmp[1U] = b1 + (uint64_t)0x3ffffffffffff8U; |
||||||
|
tmp[2U] = b2 + (uint64_t)0x3ffffffffffff8U; |
||||||
|
tmp[3U] = b3 + (uint64_t)0x3ffffffffffff8U; |
||||||
|
tmp[4U] = b4 + (uint64_t)0x3ffffffffffff8U; |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint64_t xi = a[i]; |
||||||
|
uint64_t yi = tmp[i]; |
||||||
|
a[i] = yi - xi; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_fscalar(uint64_t *output, uint64_t *b, uint64_t s) |
||||||
|
{ |
||||||
|
KRML_CHECK_SIZE(sizeof (uint128_t), (uint32_t)5U); |
||||||
|
{ |
||||||
|
uint128_t tmp[5U]; |
||||||
|
{ |
||||||
|
uint32_t _i; |
||||||
|
for (_i = 0U; _i < (uint32_t)5U; ++_i) |
||||||
|
tmp[_i] = (uint128_t)(uint64_t)0U; |
||||||
|
} |
||||||
|
{ |
||||||
|
uint128_t b4; |
||||||
|
uint128_t b0; |
||||||
|
uint128_t b4_; |
||||||
|
uint128_t b0_; |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint64_t xi = b[i]; |
||||||
|
tmp[i] = (uint128_t)xi * s; |
||||||
|
} |
||||||
|
} |
||||||
|
Hacl_Bignum_Fproduct_carry_wide_(tmp); |
||||||
|
b4 = tmp[4U]; |
||||||
|
b0 = tmp[0U]; |
||||||
|
b4_ = b4 & (uint128_t)(uint64_t)0x7ffffffffffffU; |
||||||
|
b0_ = b0 + (uint128_t)(uint64_t)19U * (uint64_t)(b4 >> (uint32_t)51U); |
||||||
|
tmp[4U] = b4_; |
||||||
|
tmp[0U] = b0_; |
||||||
|
Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_fmul(uint64_t *output, uint64_t *a, uint64_t *b) |
||||||
|
{ |
||||||
|
Hacl_Bignum_Fmul_fmul(output, a, b); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_crecip(uint64_t *output, uint64_t *input) |
||||||
|
{ |
||||||
|
Hacl_Bignum_Crecip_crecip(output, input); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Point_swap_conditional_step(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr) |
||||||
|
{ |
||||||
|
uint32_t i = ctr - (uint32_t)1U; |
||||||
|
uint64_t ai = a[i]; |
||||||
|
uint64_t bi = b[i]; |
||||||
|
uint64_t x = swap1 & (ai ^ bi); |
||||||
|
uint64_t ai1 = ai ^ x; |
||||||
|
uint64_t bi1 = bi ^ x; |
||||||
|
a[i] = ai1; |
||||||
|
b[i] = bi1; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Point_swap_conditional_(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr) |
||||||
|
{ |
||||||
|
if (!(ctr == (uint32_t)0U)) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
Hacl_EC_Point_swap_conditional_step(a, b, swap1, ctr); |
||||||
|
i = ctr - (uint32_t)1U; |
||||||
|
Hacl_EC_Point_swap_conditional_(a, b, swap1, i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Point_swap_conditional(uint64_t *a, uint64_t *b, uint64_t iswap) |
||||||
|
{ |
||||||
|
uint64_t swap1 = (uint64_t)0U - iswap; |
||||||
|
Hacl_EC_Point_swap_conditional_(a, b, swap1, (uint32_t)5U); |
||||||
|
Hacl_EC_Point_swap_conditional_(a + (uint32_t)5U, b + (uint32_t)5U, swap1, (uint32_t)5U); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Point_copy(uint64_t *output, uint64_t *input) |
||||||
|
{ |
||||||
|
memcpy(output, input, (uint32_t)5U * sizeof input[0U]); |
||||||
|
memcpy(output + (uint32_t)5U, |
||||||
|
input + (uint32_t)5U, |
||||||
|
(uint32_t)5U * sizeof (input + (uint32_t)5U)[0U]); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fexpand(uint64_t *output, uint8_t *input) |
||||||
|
{ |
||||||
|
uint64_t i0 = load64_le(input); |
||||||
|
uint8_t *x00 = input + (uint32_t)6U; |
||||||
|
uint64_t i1 = load64_le(x00); |
||||||
|
uint8_t *x01 = input + (uint32_t)12U; |
||||||
|
uint64_t i2 = load64_le(x01); |
||||||
|
uint8_t *x02 = input + (uint32_t)19U; |
||||||
|
uint64_t i3 = load64_le(x02); |
||||||
|
uint8_t *x0 = input + (uint32_t)24U; |
||||||
|
uint64_t i4 = load64_le(x0); |
||||||
|
uint64_t output0 = i0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t output1 = i1 >> (uint32_t)3U & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t output2 = i2 >> (uint32_t)6U & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t output3 = i3 >> (uint32_t)1U & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t output4 = i4 >> (uint32_t)12U & (uint64_t)0x7ffffffffffffU; |
||||||
|
output[0U] = output0; |
||||||
|
output[1U] = output1; |
||||||
|
output[2U] = output2; |
||||||
|
output[3U] = output3; |
||||||
|
output[4U] = output4; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_first_carry_pass(uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t t0 = input[0U]; |
||||||
|
uint64_t t1 = input[1U]; |
||||||
|
uint64_t t2 = input[2U]; |
||||||
|
uint64_t t3 = input[3U]; |
||||||
|
uint64_t t4 = input[4U]; |
||||||
|
uint64_t t1_ = t1 + (t0 >> (uint32_t)51U); |
||||||
|
uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U); |
||||||
|
uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U); |
||||||
|
uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U); |
||||||
|
uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
input[0U] = t0_; |
||||||
|
input[1U] = t1__; |
||||||
|
input[2U] = t2__; |
||||||
|
input[3U] = t3__; |
||||||
|
input[4U] = t4_; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_first_carry_full(uint64_t *input) |
||||||
|
{ |
||||||
|
Hacl_EC_Format_fcontract_first_carry_pass(input); |
||||||
|
Hacl_Bignum_Modulo_carry_top(input); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_second_carry_pass(uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t t0 = input[0U]; |
||||||
|
uint64_t t1 = input[1U]; |
||||||
|
uint64_t t2 = input[2U]; |
||||||
|
uint64_t t3 = input[3U]; |
||||||
|
uint64_t t4 = input[4U]; |
||||||
|
uint64_t t1_ = t1 + (t0 >> (uint32_t)51U); |
||||||
|
uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U); |
||||||
|
uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U); |
||||||
|
uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U); |
||||||
|
uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
input[0U] = t0_; |
||||||
|
input[1U] = t1__; |
||||||
|
input[2U] = t2__; |
||||||
|
input[3U] = t3__; |
||||||
|
input[4U] = t4_; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_second_carry_full(uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t i0; |
||||||
|
uint64_t i1; |
||||||
|
uint64_t i0_; |
||||||
|
uint64_t i1_; |
||||||
|
Hacl_EC_Format_fcontract_second_carry_pass(input); |
||||||
|
Hacl_Bignum_Modulo_carry_top(input); |
||||||
|
i0 = input[0U]; |
||||||
|
i1 = input[1U]; |
||||||
|
i0_ = i0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
i1_ = i1 + (i0 >> (uint32_t)51U); |
||||||
|
input[0U] = i0_; |
||||||
|
input[1U] = i1_; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_trim(uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t a0 = input[0U]; |
||||||
|
uint64_t a1 = input[1U]; |
||||||
|
uint64_t a2 = input[2U]; |
||||||
|
uint64_t a3 = input[3U]; |
||||||
|
uint64_t a4 = input[4U]; |
||||||
|
uint64_t mask0 = FStar_UInt64_gte_mask(a0, (uint64_t)0x7ffffffffffedU); |
||||||
|
uint64_t mask1 = FStar_UInt64_eq_mask(a1, (uint64_t)0x7ffffffffffffU); |
||||||
|
uint64_t mask2 = FStar_UInt64_eq_mask(a2, (uint64_t)0x7ffffffffffffU); |
||||||
|
uint64_t mask3 = FStar_UInt64_eq_mask(a3, (uint64_t)0x7ffffffffffffU); |
||||||
|
uint64_t mask4 = FStar_UInt64_eq_mask(a4, (uint64_t)0x7ffffffffffffU); |
||||||
|
uint64_t mask = (((mask0 & mask1) & mask2) & mask3) & mask4; |
||||||
|
uint64_t a0_ = a0 - ((uint64_t)0x7ffffffffffedU & mask); |
||||||
|
uint64_t a1_ = a1 - ((uint64_t)0x7ffffffffffffU & mask); |
||||||
|
uint64_t a2_ = a2 - ((uint64_t)0x7ffffffffffffU & mask); |
||||||
|
uint64_t a3_ = a3 - ((uint64_t)0x7ffffffffffffU & mask); |
||||||
|
uint64_t a4_ = a4 - ((uint64_t)0x7ffffffffffffU & mask); |
||||||
|
input[0U] = a0_; |
||||||
|
input[1U] = a1_; |
||||||
|
input[2U] = a2_; |
||||||
|
input[3U] = a3_; |
||||||
|
input[4U] = a4_; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_store(uint8_t *output, uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t t0 = input[0U]; |
||||||
|
uint64_t t1 = input[1U]; |
||||||
|
uint64_t t2 = input[2U]; |
||||||
|
uint64_t t3 = input[3U]; |
||||||
|
uint64_t t4 = input[4U]; |
||||||
|
uint64_t o0 = t1 << (uint32_t)51U | t0; |
||||||
|
uint64_t o1 = t2 << (uint32_t)38U | t1 >> (uint32_t)13U; |
||||||
|
uint64_t o2 = t3 << (uint32_t)25U | t2 >> (uint32_t)26U; |
||||||
|
uint64_t o3 = t4 << (uint32_t)12U | t3 >> (uint32_t)39U; |
||||||
|
uint8_t *b0 = output; |
||||||
|
uint8_t *b1 = output + (uint32_t)8U; |
||||||
|
uint8_t *b2 = output + (uint32_t)16U; |
||||||
|
uint8_t *b3 = output + (uint32_t)24U; |
||||||
|
store64_le(b0, o0); |
||||||
|
store64_le(b1, o1); |
||||||
|
store64_le(b2, o2); |
||||||
|
store64_le(b3, o3); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract(uint8_t *output, uint64_t *input) |
||||||
|
{ |
||||||
|
Hacl_EC_Format_fcontract_first_carry_full(input); |
||||||
|
Hacl_EC_Format_fcontract_second_carry_full(input); |
||||||
|
Hacl_EC_Format_fcontract_trim(input); |
||||||
|
Hacl_EC_Format_fcontract_store(output, input); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_scalar_of_point(uint8_t *scalar, uint64_t *point) |
||||||
|
{ |
||||||
|
uint64_t *x = point; |
||||||
|
uint64_t *z = point + (uint32_t)5U; |
||||||
|
uint64_t buf[10U] = { 0U }; |
||||||
|
uint64_t *zmone = buf; |
||||||
|
uint64_t *sc = buf + (uint32_t)5U; |
||||||
|
Hacl_Bignum_crecip(zmone, z); |
||||||
|
Hacl_Bignum_fmul(sc, x, zmone); |
||||||
|
Hacl_EC_Format_fcontract(scalar, sc); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_AddAndDouble_fmonty( |
||||||
|
uint64_t *pp, |
||||||
|
uint64_t *ppq, |
||||||
|
uint64_t *p, |
||||||
|
uint64_t *pq, |
||||||
|
uint64_t *qmqp |
||||||
|
) |
||||||
|
{ |
||||||
|
uint64_t *qx = qmqp; |
||||||
|
uint64_t *x2 = pp; |
||||||
|
uint64_t *z2 = pp + (uint32_t)5U; |
||||||
|
uint64_t *x3 = ppq; |
||||||
|
uint64_t *z3 = ppq + (uint32_t)5U; |
||||||
|
uint64_t *x = p; |
||||||
|
uint64_t *z = p + (uint32_t)5U; |
||||||
|
uint64_t *xprime = pq; |
||||||
|
uint64_t *zprime = pq + (uint32_t)5U; |
||||||
|
uint64_t buf[40U] = { 0U }; |
||||||
|
uint64_t *origx = buf; |
||||||
|
uint64_t *origxprime0 = buf + (uint32_t)5U; |
||||||
|
uint64_t *xxprime0 = buf + (uint32_t)25U; |
||||||
|
uint64_t *zzprime0 = buf + (uint32_t)30U; |
||||||
|
uint64_t *origxprime; |
||||||
|
uint64_t *xx0; |
||||||
|
uint64_t *zz0; |
||||||
|
uint64_t *xxprime; |
||||||
|
uint64_t *zzprime; |
||||||
|
uint64_t *zzzprime; |
||||||
|
uint64_t *zzz; |
||||||
|
uint64_t *xx; |
||||||
|
uint64_t *zz; |
||||||
|
uint64_t scalar; |
||||||
|
memcpy(origx, x, (uint32_t)5U * sizeof x[0U]); |
||||||
|
Hacl_Bignum_fsum(x, z); |
||||||
|
Hacl_Bignum_fdifference(z, origx); |
||||||
|
memcpy(origxprime0, xprime, (uint32_t)5U * sizeof xprime[0U]); |
||||||
|
Hacl_Bignum_fsum(xprime, zprime); |
||||||
|
Hacl_Bignum_fdifference(zprime, origxprime0); |
||||||
|
Hacl_Bignum_fmul(xxprime0, xprime, z); |
||||||
|
Hacl_Bignum_fmul(zzprime0, x, zprime); |
||||||
|
origxprime = buf + (uint32_t)5U; |
||||||
|
xx0 = buf + (uint32_t)15U; |
||||||
|
zz0 = buf + (uint32_t)20U; |
||||||
|
xxprime = buf + (uint32_t)25U; |
||||||
|
zzprime = buf + (uint32_t)30U; |
||||||
|
zzzprime = buf + (uint32_t)35U; |
||||||
|
memcpy(origxprime, xxprime, (uint32_t)5U * sizeof xxprime[0U]); |
||||||
|
Hacl_Bignum_fsum(xxprime, zzprime); |
||||||
|
Hacl_Bignum_fdifference(zzprime, origxprime); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(x3, xxprime, (uint32_t)1U); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(zzzprime, zzprime, (uint32_t)1U); |
||||||
|
Hacl_Bignum_fmul(z3, zzzprime, qx); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(xx0, x, (uint32_t)1U); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(zz0, z, (uint32_t)1U); |
||||||
|
zzz = buf + (uint32_t)10U; |
||||||
|
xx = buf + (uint32_t)15U; |
||||||
|
zz = buf + (uint32_t)20U; |
||||||
|
Hacl_Bignum_fmul(x2, xx, zz); |
||||||
|
Hacl_Bignum_fdifference(zz, xx); |
||||||
|
scalar = (uint64_t)121665U; |
||||||
|
Hacl_Bignum_fscalar(zzz, zz, scalar); |
||||||
|
Hacl_Bignum_fsum(zzz, xx); |
||||||
|
Hacl_Bignum_fmul(z2, zzz, zz); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step( |
||||||
|
uint64_t *nq, |
||||||
|
uint64_t *nqpq, |
||||||
|
uint64_t *nq2, |
||||||
|
uint64_t *nqpq2, |
||||||
|
uint64_t *q, |
||||||
|
uint8_t byt |
||||||
|
) |
||||||
|
{ |
||||||
|
uint64_t bit0 = (uint64_t)(byt >> (uint32_t)7U); |
||||||
|
uint64_t bit; |
||||||
|
Hacl_EC_Point_swap_conditional(nq, nqpq, bit0); |
||||||
|
Hacl_EC_AddAndDouble_fmonty(nq2, nqpq2, nq, nqpq, q); |
||||||
|
bit = (uint64_t)(byt >> (uint32_t)7U); |
||||||
|
Hacl_EC_Point_swap_conditional(nq2, nqpq2, bit); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step( |
||||||
|
uint64_t *nq, |
||||||
|
uint64_t *nqpq, |
||||||
|
uint64_t *nq2, |
||||||
|
uint64_t *nqpq2, |
||||||
|
uint64_t *q, |
||||||
|
uint8_t byt |
||||||
|
) |
||||||
|
{ |
||||||
|
uint8_t byt1; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq, nqpq, nq2, nqpq2, q, byt); |
||||||
|
byt1 = byt << (uint32_t)1U; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq2, nqpq2, nq, nqpq, q, byt1); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop( |
||||||
|
uint64_t *nq, |
||||||
|
uint64_t *nqpq, |
||||||
|
uint64_t *nq2, |
||||||
|
uint64_t *nqpq2, |
||||||
|
uint64_t *q, |
||||||
|
uint8_t byt, |
||||||
|
uint32_t i |
||||||
|
) |
||||||
|
{ |
||||||
|
if (!(i == (uint32_t)0U)) |
||||||
|
{ |
||||||
|
uint32_t i_ = i - (uint32_t)1U; |
||||||
|
uint8_t byt_; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(nq, nqpq, nq2, nqpq2, q, byt); |
||||||
|
byt_ = byt << (uint32_t)2U; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byt_, i_); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Ladder_BigLoop_cmult_big_loop( |
||||||
|
uint8_t *n1, |
||||||
|
uint64_t *nq, |
||||||
|
uint64_t *nqpq, |
||||||
|
uint64_t *nq2, |
||||||
|
uint64_t *nqpq2, |
||||||
|
uint64_t *q, |
||||||
|
uint32_t i |
||||||
|
) |
||||||
|
{ |
||||||
|
if (!(i == (uint32_t)0U)) |
||||||
|
{ |
||||||
|
uint32_t i1 = i - (uint32_t)1U; |
||||||
|
uint8_t byte = n1[i1]; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byte, (uint32_t)4U); |
||||||
|
Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, i1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Ladder_cmult(uint64_t *result, uint8_t *n1, uint64_t *q) |
||||||
|
{ |
||||||
|
uint64_t point_buf[40U] = { 0U }; |
||||||
|
uint64_t *nq = point_buf; |
||||||
|
uint64_t *nqpq = point_buf + (uint32_t)10U; |
||||||
|
uint64_t *nq2 = point_buf + (uint32_t)20U; |
||||||
|
uint64_t *nqpq2 = point_buf + (uint32_t)30U; |
||||||
|
Hacl_EC_Point_copy(nqpq, q); |
||||||
|
nq[0U] = (uint64_t)1U; |
||||||
|
Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, (uint32_t)32U); |
||||||
|
Hacl_EC_Point_copy(result, nq); |
||||||
|
} |
||||||
|
|
||||||
|
void Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint) |
||||||
|
{ |
||||||
|
uint64_t buf0[10U] = { 0U }; |
||||||
|
uint64_t *x0 = buf0; |
||||||
|
uint64_t *z = buf0 + (uint32_t)5U; |
||||||
|
uint64_t *q; |
||||||
|
Hacl_EC_Format_fexpand(x0, basepoint); |
||||||
|
z[0U] = (uint64_t)1U; |
||||||
|
q = buf0; |
||||||
|
{ |
||||||
|
uint8_t e[32U] = { 0U }; |
||||||
|
uint8_t e0; |
||||||
|
uint8_t e31; |
||||||
|
uint8_t e01; |
||||||
|
uint8_t e311; |
||||||
|
uint8_t e312; |
||||||
|
uint8_t *scalar; |
||||||
|
memcpy(e, secret, (uint32_t)32U * sizeof secret[0U]); |
||||||
|
e0 = e[0U]; |
||||||
|
e31 = e[31U]; |
||||||
|
e01 = e0 & (uint8_t)248U; |
||||||
|
e311 = e31 & (uint8_t)127U; |
||||||
|
e312 = e311 | (uint8_t)64U; |
||||||
|
e[0U] = e01; |
||||||
|
e[31U] = e312; |
||||||
|
scalar = e; |
||||||
|
{ |
||||||
|
uint64_t buf[15U] = { 0U }; |
||||||
|
uint64_t *nq = buf; |
||||||
|
uint64_t *x = nq; |
||||||
|
x[0U] = (uint64_t)1U; |
||||||
|
Hacl_EC_Ladder_cmult(nq, scalar, q); |
||||||
|
Hacl_EC_Format_scalar_of_point(mypublic, nq); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,50 @@ |
|||||||
|
/*
|
||||||
|
* Interface to code from Project Everest |
||||||
|
* |
||||||
|
* Copyright 2016-2018 INRIA and Microsoft Corporation |
||||||
|
* 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 _BSD_SOURCE |
||||||
|
/* Required to get htole64() from gcc/glibc's endian.h (older systems)
|
||||||
|
* when we compile with -std=c99 */ |
||||||
|
#define _BSD_SOURCE |
||||||
|
#endif |
||||||
|
#ifndef _DEFAULT_SOURCE |
||||||
|
/* (modern version of _BSD_SOURCE) */ |
||||||
|
#define _DEFAULT_SOURCE |
||||||
|
#endif |
||||||
|
|
||||||
|
#include "common.h" |
||||||
|
|
||||||
|
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) |
||||||
|
|
||||||
|
#if defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16) |
||||||
|
#define MBEDTLS_HAVE_INT128 |
||||||
|
#endif |
||||||
|
|
||||||
|
#if defined(MBEDTLS_HAVE_INT128) |
||||||
|
#include "Hacl_Curve25519.c" |
||||||
|
#else |
||||||
|
#define KRML_VERIFIED_UINT128 |
||||||
|
#include "kremlib/FStar_UInt128_extracted.c" |
||||||
|
#include "legacy/Hacl_Curve25519.c" |
||||||
|
#endif |
||||||
|
|
||||||
|
#include "kremlib/FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.c" |
||||||
|
|
||||||
|
#endif /* defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) */ |
||||||
|
|
@ -0,0 +1,102 @@ |
|||||||
|
/*
|
||||||
|
* Interface to code from Project Everest |
||||||
|
* |
||||||
|
* Copyright 2016-2018 INRIA and Microsoft Corporation |
||||||
|
* 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).
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include "common.h" |
||||||
|
|
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include "mbedtls/ecdh.h" |
||||||
|
|
||||||
|
#include "everest/x25519.h" |
||||||
|
#include "everest/everest.h" |
||||||
|
|
||||||
|
#include "mbedtls/platform.h" |
||||||
|
|
||||||
|
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) |
||||||
|
|
||||||
|
int mbedtls_everest_setup( mbedtls_ecdh_context_everest *ctx, int grp_id ) |
||||||
|
{ |
||||||
|
if( grp_id != MBEDTLS_ECP_DP_CURVE25519 ) |
||||||
|
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; |
||||||
|
mbedtls_x25519_init( &ctx->ctx ); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
void mbedtls_everest_free( mbedtls_ecdh_context_everest *ctx ) |
||||||
|
{ |
||||||
|
mbedtls_x25519_free( &ctx->ctx ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_everest_make_params( mbedtls_ecdh_context_everest *ctx, size_t *olen, |
||||||
|
unsigned char *buf, size_t blen, |
||||||
|
int( *f_rng )( void *, unsigned char *, size_t ), |
||||||
|
void *p_rng ) |
||||||
|
{ |
||||||
|
mbedtls_x25519_context *x25519_ctx = &ctx->ctx; |
||||||
|
return mbedtls_x25519_make_params( x25519_ctx, olen, buf, blen, f_rng, p_rng ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_everest_read_params( mbedtls_ecdh_context_everest *ctx, |
||||||
|
const unsigned char **buf, |
||||||
|
const unsigned char *end ) |
||||||
|
{ |
||||||
|
mbedtls_x25519_context *x25519_ctx = &ctx->ctx; |
||||||
|
return mbedtls_x25519_read_params( x25519_ctx, buf, end ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_everest_get_params( mbedtls_ecdh_context_everest *ctx, |
||||||
|
const mbedtls_ecp_keypair *key, |
||||||
|
mbedtls_everest_ecdh_side side ) |
||||||
|
{ |
||||||
|
mbedtls_x25519_context *x25519_ctx = &ctx->ctx; |
||||||
|
mbedtls_x25519_ecdh_side s = side == MBEDTLS_EVEREST_ECDH_OURS ? |
||||||
|
MBEDTLS_X25519_ECDH_OURS : |
||||||
|
MBEDTLS_X25519_ECDH_THEIRS; |
||||||
|
return mbedtls_x25519_get_params( x25519_ctx, key, s ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_everest_make_public( mbedtls_ecdh_context_everest *ctx, size_t *olen, |
||||||
|
unsigned char *buf, size_t blen, |
||||||
|
int( *f_rng )( void *, unsigned char *, size_t ), |
||||||
|
void *p_rng ) |
||||||
|
{ |
||||||
|
mbedtls_x25519_context *x25519_ctx = &ctx->ctx; |
||||||
|
return mbedtls_x25519_make_public( x25519_ctx, olen, buf, blen, f_rng, p_rng ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_everest_read_public( mbedtls_ecdh_context_everest *ctx, |
||||||
|
const unsigned char *buf, size_t blen ) |
||||||
|
{ |
||||||
|
mbedtls_x25519_context *x25519_ctx = &ctx->ctx; |
||||||
|
return mbedtls_x25519_read_public ( x25519_ctx, buf, blen ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_everest_calc_secret( mbedtls_ecdh_context_everest *ctx, size_t *olen, |
||||||
|
unsigned char *buf, size_t blen, |
||||||
|
int( *f_rng )( void *, unsigned char *, size_t ), |
||||||
|
void *p_rng ) |
||||||
|
{ |
||||||
|
mbedtls_x25519_context *x25519_ctx = &ctx->ctx; |
||||||
|
return mbedtls_x25519_calc_secret( x25519_ctx, olen, buf, blen, f_rng, p_rng ); |
||||||
|
} |
||||||
|
|
||||||
|
#endif /* MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */ |
||||||
|
|
@ -0,0 +1,413 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>
|
||||||
|
* KreMLin invocation: ../krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrB9w -minimal -fparentheses -fcurly-braces -fno-shadow -header copyright-header.txt -minimal -tmpdir extracted -warn-error +9+11 -skip-compilation -extract-uints -add-include <inttypes.h> -add-include "kremlib.h" -add-include "kremlin/internal/compat.h" extracted/prims.krml extracted/FStar_Pervasives_Native.krml extracted/FStar_Pervasives.krml extracted/FStar_Mul.krml extracted/FStar_Squash.krml extracted/FStar_Classical.krml extracted/FStar_StrongExcludedMiddle.krml extracted/FStar_FunctionalExtensionality.krml extracted/FStar_List_Tot_Base.krml extracted/FStar_List_Tot_Properties.krml extracted/FStar_List_Tot.krml extracted/FStar_Seq_Base.krml extracted/FStar_Seq_Properties.krml extracted/FStar_Seq.krml extracted/FStar_Math_Lib.krml extracted/FStar_Math_Lemmas.krml extracted/FStar_BitVector.krml extracted/FStar_UInt.krml extracted/FStar_UInt32.krml extracted/FStar_Int.krml extracted/FStar_Int16.krml extracted/FStar_Preorder.krml extracted/FStar_Ghost.krml extracted/FStar_ErasedLogic.krml extracted/FStar_UInt64.krml extracted/FStar_Set.krml extracted/FStar_PropositionalExtensionality.krml extracted/FStar_PredicateExtensionality.krml extracted/FStar_TSet.krml extracted/FStar_Monotonic_Heap.krml extracted/FStar_Heap.krml extracted/FStar_Map.krml extracted/FStar_Monotonic_HyperHeap.krml extracted/FStar_Monotonic_HyperStack.krml extracted/FStar_HyperStack.krml extracted/FStar_Monotonic_Witnessed.krml extracted/FStar_HyperStack_ST.krml extracted/FStar_HyperStack_All.krml extracted/FStar_Date.krml extracted/FStar_Universe.krml extracted/FStar_GSet.krml extracted/FStar_ModifiesGen.krml extracted/LowStar_Monotonic_Buffer.krml extracted/LowStar_Buffer.krml extracted/Spec_Loops.krml extracted/LowStar_BufferOps.krml extracted/C_Loops.krml extracted/FStar_UInt8.krml extracted/FStar_Kremlin_Endianness.krml extracted/FStar_UInt63.krml extracted/FStar_Exn.krml extracted/FStar_ST.krml extracted/FStar_All.krml extracted/FStar_Dyn.krml extracted/FStar_Int63.krml extracted/FStar_Int64.krml extracted/FStar_Int32.krml extracted/FStar_Int8.krml extracted/FStar_UInt16.krml extracted/FStar_Int_Cast.krml extracted/FStar_UInt128.krml extracted/C_Endianness.krml extracted/FStar_List.krml extracted/FStar_Float.krml extracted/FStar_IO.krml extracted/C.krml extracted/FStar_Char.krml extracted/FStar_String.krml extracted/LowStar_Modifies.krml extracted/C_String.krml extracted/FStar_Bytes.krml extracted/FStar_HyperStack_IO.krml extracted/C_Failure.krml extracted/TestLib.krml extracted/FStar_Int_Cast_Full.krml |
||||||
|
* F* version: 059db0c8 |
||||||
|
* KreMLin version: 916c37ac |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#include "FStar_UInt128.h" |
||||||
|
#include "kremlin/c_endianness.h" |
||||||
|
#include "FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.h" |
||||||
|
|
||||||
|
uint64_t FStar_UInt128___proj__Mkuint128__item__low(FStar_UInt128_uint128 projectee) |
||||||
|
{ |
||||||
|
return projectee.low; |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t FStar_UInt128___proj__Mkuint128__item__high(FStar_UInt128_uint128 projectee) |
||||||
|
{ |
||||||
|
return projectee.high; |
||||||
|
} |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_constant_time_carry(uint64_t a, uint64_t b) |
||||||
|
{ |
||||||
|
return (a ^ ((a ^ b) | ((a - b) ^ b))) >> (uint32_t)63U; |
||||||
|
} |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_carry(uint64_t a, uint64_t b) |
||||||
|
{ |
||||||
|
return FStar_UInt128_constant_time_carry(a, b); |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = { a.low + b.low, a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_add_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = { a.low + b.low, a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = { a.low + b.low, a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = { a.low - b.low, a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_sub_underspec(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = { a.low - b.low, a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
static FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_sub_mod_impl(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = { a.low - b.low, a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
return FStar_UInt128_sub_mod_impl(a, b); |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 flat = { a.low & b.low, a.high & b.high }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 flat = { a.low ^ b.low, a.high ^ b.high }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 flat = { a.low | b.low, a.high | b.high }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 flat = { ~a.low, ~a.high }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
static uint32_t FStar_UInt128_u32_64 = (uint32_t)64U; |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_add_u64_shift_left(uint64_t hi, uint64_t lo, uint32_t s) |
||||||
|
{ |
||||||
|
return (hi << s) + (lo >> (FStar_UInt128_u32_64 - s)); |
||||||
|
} |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_add_u64_shift_left_respec(uint64_t hi, uint64_t lo, uint32_t s) |
||||||
|
{ |
||||||
|
return FStar_UInt128_add_u64_shift_left(hi, lo, s); |
||||||
|
} |
||||||
|
|
||||||
|
static FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_shift_left_small(FStar_UInt128_uint128 a, uint32_t s) |
||||||
|
{ |
||||||
|
if (s == (uint32_t)0U) |
||||||
|
{ |
||||||
|
return a; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = { a.low << s, FStar_UInt128_add_u64_shift_left_respec(a.high, a.low, s) }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_shift_left_large(FStar_UInt128_uint128 a, uint32_t s) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 flat = { (uint64_t)0U, a.low << (s - FStar_UInt128_u32_64) }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s) |
||||||
|
{ |
||||||
|
if (s < FStar_UInt128_u32_64) |
||||||
|
{ |
||||||
|
return FStar_UInt128_shift_left_small(a, s); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return FStar_UInt128_shift_left_large(a, s); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_add_u64_shift_right(uint64_t hi, uint64_t lo, uint32_t s) |
||||||
|
{ |
||||||
|
return (lo >> s) + (hi << (FStar_UInt128_u32_64 - s)); |
||||||
|
} |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_add_u64_shift_right_respec(uint64_t hi, uint64_t lo, uint32_t s) |
||||||
|
{ |
||||||
|
return FStar_UInt128_add_u64_shift_right(hi, lo, s); |
||||||
|
} |
||||||
|
|
||||||
|
static FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_shift_right_small(FStar_UInt128_uint128 a, uint32_t s) |
||||||
|
{ |
||||||
|
if (s == (uint32_t)0U) |
||||||
|
{ |
||||||
|
return a; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = { FStar_UInt128_add_u64_shift_right_respec(a.high, a.low, s), a.high >> s }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_shift_right_large(FStar_UInt128_uint128 a, uint32_t s) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 flat = { a.high >> (s - FStar_UInt128_u32_64), (uint64_t)0U }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s) |
||||||
|
{ |
||||||
|
if (s < FStar_UInt128_u32_64) |
||||||
|
{ |
||||||
|
return FStar_UInt128_shift_right_small(a, s); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return FStar_UInt128_shift_right_large(a, s); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool FStar_UInt128_eq(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
return a.low == b.low && a.high == b.high; |
||||||
|
} |
||||||
|
|
||||||
|
bool FStar_UInt128_gt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
return a.high > b.high || (a.high == b.high && a.low > b.low); |
||||||
|
} |
||||||
|
|
||||||
|
bool FStar_UInt128_lt(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
return a.high < b.high || (a.high == b.high && a.low < b.low); |
||||||
|
} |
||||||
|
|
||||||
|
bool FStar_UInt128_gte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
return a.high > b.high || (a.high == b.high && a.low >= b.low); |
||||||
|
} |
||||||
|
|
||||||
|
bool FStar_UInt128_lte(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
return a.high < b.high || (a.high == b.high && a.low <= b.low); |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = |
||||||
|
{ |
||||||
|
FStar_UInt64_eq_mask(a.low, |
||||||
|
b.low) |
||||||
|
& FStar_UInt64_eq_mask(a.high, b.high), |
||||||
|
FStar_UInt64_eq_mask(a.low, |
||||||
|
b.low) |
||||||
|
& FStar_UInt64_eq_mask(a.high, b.high) |
||||||
|
}; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = |
||||||
|
{ |
||||||
|
(FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high)) |
||||||
|
| (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low)), |
||||||
|
(FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high)) |
||||||
|
| (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low)) |
||||||
|
}; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 flat = { a, (uint64_t)0U }; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a) |
||||||
|
{ |
||||||
|
return a.low; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Plus_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_add; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Plus_Question_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_add_underspec; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Plus_Percent_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_add_mod; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Subtraction_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_sub; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Subtraction_Question_Hat)( |
||||||
|
FStar_UInt128_uint128 x0, |
||||||
|
FStar_UInt128_uint128 x1 |
||||||
|
) = FStar_UInt128_sub_underspec; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Subtraction_Percent_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_sub_mod; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Amp_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_logand; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Hat_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_logxor; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Bar_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_logor; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Less_Less_Hat)(FStar_UInt128_uint128 x0, uint32_t x1) = |
||||||
|
FStar_UInt128_shift_left; |
||||||
|
|
||||||
|
FStar_UInt128_uint128 |
||||||
|
(*FStar_UInt128_op_Greater_Greater_Hat)(FStar_UInt128_uint128 x0, uint32_t x1) = |
||||||
|
FStar_UInt128_shift_right; |
||||||
|
|
||||||
|
bool |
||||||
|
(*FStar_UInt128_op_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_eq; |
||||||
|
|
||||||
|
bool |
||||||
|
(*FStar_UInt128_op_Greater_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_gt; |
||||||
|
|
||||||
|
bool |
||||||
|
(*FStar_UInt128_op_Less_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_lt; |
||||||
|
|
||||||
|
bool |
||||||
|
(*FStar_UInt128_op_Greater_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_gte; |
||||||
|
|
||||||
|
bool |
||||||
|
(*FStar_UInt128_op_Less_Equals_Hat)(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1) = |
||||||
|
FStar_UInt128_lte; |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_u64_mod_32(uint64_t a) |
||||||
|
{ |
||||||
|
return a & (uint64_t)0xffffffffU; |
||||||
|
} |
||||||
|
|
||||||
|
static uint32_t FStar_UInt128_u32_32 = (uint32_t)32U; |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_u32_combine(uint64_t hi, uint64_t lo) |
||||||
|
{ |
||||||
|
return lo + (hi << FStar_UInt128_u32_32); |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_mul32(uint64_t x, uint32_t y) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = |
||||||
|
{ |
||||||
|
FStar_UInt128_u32_combine((x >> FStar_UInt128_u32_32) |
||||||
|
* (uint64_t)y |
||||||
|
+ (FStar_UInt128_u64_mod_32(x) * (uint64_t)y >> FStar_UInt128_u32_32), |
||||||
|
FStar_UInt128_u64_mod_32(FStar_UInt128_u64_mod_32(x) * (uint64_t)y)), |
||||||
|
((x >> FStar_UInt128_u32_32) |
||||||
|
* (uint64_t)y |
||||||
|
+ (FStar_UInt128_u64_mod_32(x) * (uint64_t)y >> FStar_UInt128_u32_32)) |
||||||
|
>> FStar_UInt128_u32_32 |
||||||
|
}; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
typedef struct K___uint64_t_uint64_t_uint64_t_uint64_t_s |
||||||
|
{ |
||||||
|
uint64_t fst; |
||||||
|
uint64_t snd; |
||||||
|
uint64_t thd; |
||||||
|
uint64_t f3; |
||||||
|
} |
||||||
|
K___uint64_t_uint64_t_uint64_t_uint64_t; |
||||||
|
|
||||||
|
static K___uint64_t_uint64_t_uint64_t_uint64_t |
||||||
|
FStar_UInt128_mul_wide_impl_t_(uint64_t x, uint64_t y) |
||||||
|
{ |
||||||
|
K___uint64_t_uint64_t_uint64_t_uint64_t |
||||||
|
flat = |
||||||
|
{ |
||||||
|
FStar_UInt128_u64_mod_32(x), |
||||||
|
FStar_UInt128_u64_mod_32(FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y)), |
||||||
|
x |
||||||
|
>> FStar_UInt128_u32_32, |
||||||
|
(x >> FStar_UInt128_u32_32) |
||||||
|
* FStar_UInt128_u64_mod_32(y) |
||||||
|
+ (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32) |
||||||
|
}; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
static uint64_t FStar_UInt128_u32_combine_(uint64_t hi, uint64_t lo) |
||||||
|
{ |
||||||
|
return lo + (hi << FStar_UInt128_u32_32); |
||||||
|
} |
||||||
|
|
||||||
|
static FStar_UInt128_uint128 FStar_UInt128_mul_wide_impl(uint64_t x, uint64_t y) |
||||||
|
{ |
||||||
|
K___uint64_t_uint64_t_uint64_t_uint64_t scrut = FStar_UInt128_mul_wide_impl_t_(x, y); |
||||||
|
uint64_t u1 = scrut.fst; |
||||||
|
uint64_t w3 = scrut.snd; |
||||||
|
uint64_t x_ = scrut.thd; |
||||||
|
uint64_t t_ = scrut.f3; |
||||||
|
FStar_UInt128_uint128 |
||||||
|
flat = |
||||||
|
{ |
||||||
|
FStar_UInt128_u32_combine_(u1 * (y >> FStar_UInt128_u32_32) + FStar_UInt128_u64_mod_32(t_), |
||||||
|
w3), |
||||||
|
x_ |
||||||
|
* (y >> FStar_UInt128_u32_32) |
||||||
|
+ (t_ >> FStar_UInt128_u32_32) |
||||||
|
+ ((u1 * (y >> FStar_UInt128_u32_32) + FStar_UInt128_u64_mod_32(t_)) >> FStar_UInt128_u32_32) |
||||||
|
}; |
||||||
|
return flat; |
||||||
|
} |
||||||
|
|
||||||
|
FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y) |
||||||
|
{ |
||||||
|
return FStar_UInt128_mul_wide_impl(x, y); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,100 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>
|
||||||
|
* KreMLin invocation: ../krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrB9w -minimal -fparentheses -fcurly-braces -fno-shadow -header copyright-header.txt -minimal -tmpdir dist/minimal -skip-compilation -extract-uints -add-include <inttypes.h> -add-include <stdbool.h> -add-include "kremlin/internal/compat.h" -add-include "kremlin/internal/types.h" -bundle FStar.UInt64+FStar.UInt32+FStar.UInt16+FStar.UInt8=* extracted/prims.krml extracted/FStar_Pervasives_Native.krml extracted/FStar_Pervasives.krml extracted/FStar_Mul.krml extracted/FStar_Squash.krml extracted/FStar_Classical.krml extracted/FStar_StrongExcludedMiddle.krml extracted/FStar_FunctionalExtensionality.krml extracted/FStar_List_Tot_Base.krml extracted/FStar_List_Tot_Properties.krml extracted/FStar_List_Tot.krml extracted/FStar_Seq_Base.krml extracted/FStar_Seq_Properties.krml extracted/FStar_Seq.krml extracted/FStar_Math_Lib.krml extracted/FStar_Math_Lemmas.krml extracted/FStar_BitVector.krml extracted/FStar_UInt.krml extracted/FStar_UInt32.krml extracted/FStar_Int.krml extracted/FStar_Int16.krml extracted/FStar_Preorder.krml extracted/FStar_Ghost.krml extracted/FStar_ErasedLogic.krml extracted/FStar_UInt64.krml extracted/FStar_Set.krml extracted/FStar_PropositionalExtensionality.krml extracted/FStar_PredicateExtensionality.krml extracted/FStar_TSet.krml extracted/FStar_Monotonic_Heap.krml extracted/FStar_Heap.krml extracted/FStar_Map.krml extracted/FStar_Monotonic_HyperHeap.krml extracted/FStar_Monotonic_HyperStack.krml extracted/FStar_HyperStack.krml extracted/FStar_Monotonic_Witnessed.krml extracted/FStar_HyperStack_ST.krml extracted/FStar_HyperStack_All.krml extracted/FStar_Date.krml extracted/FStar_Universe.krml extracted/FStar_GSet.krml extracted/FStar_ModifiesGen.krml extracted/LowStar_Monotonic_Buffer.krml extracted/LowStar_Buffer.krml extracted/Spec_Loops.krml extracted/LowStar_BufferOps.krml extracted/C_Loops.krml extracted/FStar_UInt8.krml extracted/FStar_Kremlin_Endianness.krml extracted/FStar_UInt63.krml extracted/FStar_Exn.krml extracted/FStar_ST.krml extracted/FStar_All.krml extracted/FStar_Dyn.krml extracted/FStar_Int63.krml extracted/FStar_Int64.krml extracted/FStar_Int32.krml extracted/FStar_Int8.krml extracted/FStar_UInt16.krml extracted/FStar_Int_Cast.krml extracted/FStar_UInt128.krml extracted/C_Endianness.krml extracted/FStar_List.krml extracted/FStar_Float.krml extracted/FStar_IO.krml extracted/C.krml extracted/FStar_Char.krml extracted/FStar_String.krml extracted/LowStar_Modifies.krml extracted/C_String.krml extracted/FStar_Bytes.krml extracted/FStar_HyperStack_IO.krml extracted/C_Failure.krml extracted/TestLib.krml extracted/FStar_Int_Cast_Full.krml |
||||||
|
* F* version: 059db0c8 |
||||||
|
* KreMLin version: 916c37ac |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#include "FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.h" |
||||||
|
|
||||||
|
uint64_t FStar_UInt64_eq_mask(uint64_t a, uint64_t b) |
||||||
|
{ |
||||||
|
uint64_t x = a ^ b; |
||||||
|
uint64_t minus_x = ~x + (uint64_t)1U; |
||||||
|
uint64_t x_or_minus_x = x | minus_x; |
||||||
|
uint64_t xnx = x_or_minus_x >> (uint32_t)63U; |
||||||
|
return xnx - (uint64_t)1U; |
||||||
|
} |
||||||
|
|
||||||
|
uint64_t FStar_UInt64_gte_mask(uint64_t a, uint64_t b) |
||||||
|
{ |
||||||
|
uint64_t x = a; |
||||||
|
uint64_t y = b; |
||||||
|
uint64_t x_xor_y = x ^ y; |
||||||
|
uint64_t x_sub_y = x - y; |
||||||
|
uint64_t x_sub_y_xor_y = x_sub_y ^ y; |
||||||
|
uint64_t q = x_xor_y | x_sub_y_xor_y; |
||||||
|
uint64_t x_xor_q = x ^ q; |
||||||
|
uint64_t x_xor_q_ = x_xor_q >> (uint32_t)63U; |
||||||
|
return x_xor_q_ - (uint64_t)1U; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t FStar_UInt32_eq_mask(uint32_t a, uint32_t b) |
||||||
|
{ |
||||||
|
uint32_t x = a ^ b; |
||||||
|
uint32_t minus_x = ~x + (uint32_t)1U; |
||||||
|
uint32_t x_or_minus_x = x | minus_x; |
||||||
|
uint32_t xnx = x_or_minus_x >> (uint32_t)31U; |
||||||
|
return xnx - (uint32_t)1U; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t FStar_UInt32_gte_mask(uint32_t a, uint32_t b) |
||||||
|
{ |
||||||
|
uint32_t x = a; |
||||||
|
uint32_t y = b; |
||||||
|
uint32_t x_xor_y = x ^ y; |
||||||
|
uint32_t x_sub_y = x - y; |
||||||
|
uint32_t x_sub_y_xor_y = x_sub_y ^ y; |
||||||
|
uint32_t q = x_xor_y | x_sub_y_xor_y; |
||||||
|
uint32_t x_xor_q = x ^ q; |
||||||
|
uint32_t x_xor_q_ = x_xor_q >> (uint32_t)31U; |
||||||
|
return x_xor_q_ - (uint32_t)1U; |
||||||
|
} |
||||||
|
|
||||||
|
uint16_t FStar_UInt16_eq_mask(uint16_t a, uint16_t b) |
||||||
|
{ |
||||||
|
uint16_t x = a ^ b; |
||||||
|
uint16_t minus_x = ~x + (uint16_t)1U; |
||||||
|
uint16_t x_or_minus_x = x | minus_x; |
||||||
|
uint16_t xnx = x_or_minus_x >> (uint32_t)15U; |
||||||
|
return xnx - (uint16_t)1U; |
||||||
|
} |
||||||
|
|
||||||
|
uint16_t FStar_UInt16_gte_mask(uint16_t a, uint16_t b) |
||||||
|
{ |
||||||
|
uint16_t x = a; |
||||||
|
uint16_t y = b; |
||||||
|
uint16_t x_xor_y = x ^ y; |
||||||
|
uint16_t x_sub_y = x - y; |
||||||
|
uint16_t x_sub_y_xor_y = x_sub_y ^ y; |
||||||
|
uint16_t q = x_xor_y | x_sub_y_xor_y; |
||||||
|
uint16_t x_xor_q = x ^ q; |
||||||
|
uint16_t x_xor_q_ = x_xor_q >> (uint32_t)15U; |
||||||
|
return x_xor_q_ - (uint16_t)1U; |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t FStar_UInt8_eq_mask(uint8_t a, uint8_t b) |
||||||
|
{ |
||||||
|
uint8_t x = a ^ b; |
||||||
|
uint8_t minus_x = ~x + (uint8_t)1U; |
||||||
|
uint8_t x_or_minus_x = x | minus_x; |
||||||
|
uint8_t xnx = x_or_minus_x >> (uint32_t)7U; |
||||||
|
return xnx - (uint8_t)1U; |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t FStar_UInt8_gte_mask(uint8_t a, uint8_t b) |
||||||
|
{ |
||||||
|
uint8_t x = a; |
||||||
|
uint8_t y = b; |
||||||
|
uint8_t x_xor_y = x ^ y; |
||||||
|
uint8_t x_sub_y = x - y; |
||||||
|
uint8_t x_sub_y_xor_y = x_sub_y ^ y; |
||||||
|
uint8_t q = x_xor_y | x_sub_y_xor_y; |
||||||
|
uint8_t x_xor_q = x ^ q; |
||||||
|
uint8_t x_xor_q_ = x_xor_q >> (uint32_t)7U; |
||||||
|
return x_xor_q_ - (uint8_t)1U; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,805 @@ |
|||||||
|
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
||||||
|
Licensed under the Apache 2.0 License. */ |
||||||
|
|
||||||
|
/* This file was generated by KreMLin <https://github.com/FStarLang/kremlin>
|
||||||
|
* KreMLin invocation: /mnt/e/everest/verify/kremlin/krml -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -fc89 -fparentheses -fno-shadow -header /mnt/e/everest/verify/hdrcLh -minimal -I /mnt/e/everest/verify/hacl-star/code/lib/kremlin -I /mnt/e/everest/verify/kremlin/kremlib/compat -I /mnt/e/everest/verify/hacl-star/specs -I /mnt/e/everest/verify/hacl-star/specs/old -I . -ccopt -march=native -verbose -ldopt -flto -tmpdir x25519-c -I ../bignum -bundle Hacl.Curve25519=* -minimal -add-include "kremlib.h" -skip-compilation x25519-c/out.krml -o x25519-c/Hacl_Curve25519.c |
||||||
|
* F* version: 059db0c8 |
||||||
|
* KreMLin version: 916c37ac |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#include "Hacl_Curve25519.h" |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_eq_mask(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt64_gte_mask(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_add(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_add_mod(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 |
||||||
|
FStar_UInt128_logand(FStar_UInt128_uint128 x0, FStar_UInt128_uint128 x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 FStar_UInt128_shift_right(FStar_UInt128_uint128 x0, uint32_t x1); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t x0); |
||||||
|
|
||||||
|
extern uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 x0); |
||||||
|
|
||||||
|
extern FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x0, uint64_t x1); |
||||||
|
|
||||||
|
static void Hacl_Bignum_Modulo_carry_top(uint64_t *b) |
||||||
|
{ |
||||||
|
uint64_t b4 = b[4U]; |
||||||
|
uint64_t b0 = b[0U]; |
||||||
|
uint64_t b4_ = b4 & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t b0_ = b0 + (uint64_t)19U * (b4 >> (uint32_t)51U); |
||||||
|
b[4U] = b4_; |
||||||
|
b[0U] = b0_; |
||||||
|
} |
||||||
|
|
||||||
|
inline static void |
||||||
|
Hacl_Bignum_Fproduct_copy_from_wide_(uint64_t *output, FStar_UInt128_uint128 *input) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 xi = input[i]; |
||||||
|
output[i] = FStar_UInt128_uint128_to_uint64(xi); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void |
||||||
|
Hacl_Bignum_Fproduct_sum_scalar_multiplication_( |
||||||
|
FStar_UInt128_uint128 *output, |
||||||
|
uint64_t *input, |
||||||
|
uint64_t s |
||||||
|
) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 xi = output[i]; |
||||||
|
uint64_t yi = input[i]; |
||||||
|
output[i] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fproduct_carry_wide_(FStar_UInt128_uint128 *tmp) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint32_t ctr = i; |
||||||
|
FStar_UInt128_uint128 tctr = tmp[ctr]; |
||||||
|
FStar_UInt128_uint128 tctrp1 = tmp[ctr + (uint32_t)1U]; |
||||||
|
uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU; |
||||||
|
FStar_UInt128_uint128 c = FStar_UInt128_shift_right(tctr, (uint32_t)51U); |
||||||
|
tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0); |
||||||
|
tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fmul_shift_reduce(uint64_t *output) |
||||||
|
{ |
||||||
|
uint64_t tmp = output[4U]; |
||||||
|
uint64_t b0; |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)4U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint32_t ctr = (uint32_t)5U - i - (uint32_t)1U; |
||||||
|
uint64_t z = output[ctr - (uint32_t)1U]; |
||||||
|
output[ctr] = z; |
||||||
|
} |
||||||
|
} |
||||||
|
output[0U] = tmp; |
||||||
|
b0 = output[0U]; |
||||||
|
output[0U] = (uint64_t)19U * b0; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_Bignum_Fmul_mul_shift_reduce_( |
||||||
|
FStar_UInt128_uint128 *output, |
||||||
|
uint64_t *input, |
||||||
|
uint64_t *input2 |
||||||
|
) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
uint64_t input2i; |
||||||
|
{ |
||||||
|
uint32_t i0; |
||||||
|
for (i0 = (uint32_t)0U; i0 < (uint32_t)4U; i0 = i0 + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint64_t input2i0 = input2[i0]; |
||||||
|
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i0); |
||||||
|
Hacl_Bignum_Fmul_shift_reduce(input); |
||||||
|
} |
||||||
|
} |
||||||
|
i = (uint32_t)4U; |
||||||
|
input2i = input2[i]; |
||||||
|
Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fmul_fmul(uint64_t *output, uint64_t *input, uint64_t *input2) |
||||||
|
{ |
||||||
|
uint64_t tmp[5U] = { 0U }; |
||||||
|
memcpy(tmp, input, (uint32_t)5U * sizeof input[0U]); |
||||||
|
KRML_CHECK_SIZE(sizeof (FStar_UInt128_uint128), (uint32_t)5U); |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 t[5U]; |
||||||
|
{ |
||||||
|
uint32_t _i; |
||||||
|
for (_i = 0U; _i < (uint32_t)5U; ++_i) |
||||||
|
t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); |
||||||
|
} |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 b4; |
||||||
|
FStar_UInt128_uint128 b0; |
||||||
|
FStar_UInt128_uint128 b4_; |
||||||
|
FStar_UInt128_uint128 b0_; |
||||||
|
uint64_t i0; |
||||||
|
uint64_t i1; |
||||||
|
uint64_t i0_; |
||||||
|
uint64_t i1_; |
||||||
|
Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input2); |
||||||
|
Hacl_Bignum_Fproduct_carry_wide_(t); |
||||||
|
b4 = t[4U]; |
||||||
|
b0 = t[0U]; |
||||||
|
b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU)); |
||||||
|
b0_ = |
||||||
|
FStar_UInt128_add(b0, |
||||||
|
FStar_UInt128_mul_wide((uint64_t)19U, |
||||||
|
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U)))); |
||||||
|
t[4U] = b4_; |
||||||
|
t[0U] = b0_; |
||||||
|
Hacl_Bignum_Fproduct_copy_from_wide_(output, t); |
||||||
|
i0 = output[0U]; |
||||||
|
i1 = output[1U]; |
||||||
|
i0_ = i0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
i1_ = i1 + (i0 >> (uint32_t)51U); |
||||||
|
output[0U] = i0_; |
||||||
|
output[1U] = i1_; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fsquare_fsquare__(FStar_UInt128_uint128 *tmp, uint64_t *output) |
||||||
|
{ |
||||||
|
uint64_t r0 = output[0U]; |
||||||
|
uint64_t r1 = output[1U]; |
||||||
|
uint64_t r2 = output[2U]; |
||||||
|
uint64_t r3 = output[3U]; |
||||||
|
uint64_t r4 = output[4U]; |
||||||
|
uint64_t d0 = r0 * (uint64_t)2U; |
||||||
|
uint64_t d1 = r1 * (uint64_t)2U; |
||||||
|
uint64_t d2 = r2 * (uint64_t)2U * (uint64_t)19U; |
||||||
|
uint64_t d419 = r4 * (uint64_t)19U; |
||||||
|
uint64_t d4 = d419 * (uint64_t)2U; |
||||||
|
FStar_UInt128_uint128 |
||||||
|
s0 = |
||||||
|
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(r0, r0), |
||||||
|
FStar_UInt128_mul_wide(d4, r1)), |
||||||
|
FStar_UInt128_mul_wide(d2, r3)); |
||||||
|
FStar_UInt128_uint128 |
||||||
|
s1 = |
||||||
|
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r1), |
||||||
|
FStar_UInt128_mul_wide(d4, r2)), |
||||||
|
FStar_UInt128_mul_wide(r3 * (uint64_t)19U, r3)); |
||||||
|
FStar_UInt128_uint128 |
||||||
|
s2 = |
||||||
|
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r2), |
||||||
|
FStar_UInt128_mul_wide(r1, r1)), |
||||||
|
FStar_UInt128_mul_wide(d4, r3)); |
||||||
|
FStar_UInt128_uint128 |
||||||
|
s3 = |
||||||
|
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r3), |
||||||
|
FStar_UInt128_mul_wide(d1, r2)), |
||||||
|
FStar_UInt128_mul_wide(r4, d419)); |
||||||
|
FStar_UInt128_uint128 |
||||||
|
s4 = |
||||||
|
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r4), |
||||||
|
FStar_UInt128_mul_wide(d1, r3)), |
||||||
|
FStar_UInt128_mul_wide(r2, r2)); |
||||||
|
tmp[0U] = s0; |
||||||
|
tmp[1U] = s1; |
||||||
|
tmp[2U] = s2; |
||||||
|
tmp[3U] = s3; |
||||||
|
tmp[4U] = s4; |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fsquare_fsquare_(FStar_UInt128_uint128 *tmp, uint64_t *output) |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 b4; |
||||||
|
FStar_UInt128_uint128 b0; |
||||||
|
FStar_UInt128_uint128 b4_; |
||||||
|
FStar_UInt128_uint128 b0_; |
||||||
|
uint64_t i0; |
||||||
|
uint64_t i1; |
||||||
|
uint64_t i0_; |
||||||
|
uint64_t i1_; |
||||||
|
Hacl_Bignum_Fsquare_fsquare__(tmp, output); |
||||||
|
Hacl_Bignum_Fproduct_carry_wide_(tmp); |
||||||
|
b4 = tmp[4U]; |
||||||
|
b0 = tmp[0U]; |
||||||
|
b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU)); |
||||||
|
b0_ = |
||||||
|
FStar_UInt128_add(b0, |
||||||
|
FStar_UInt128_mul_wide((uint64_t)19U, |
||||||
|
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U)))); |
||||||
|
tmp[4U] = b4_; |
||||||
|
tmp[0U] = b0_; |
||||||
|
Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp); |
||||||
|
i0 = output[0U]; |
||||||
|
i1 = output[1U]; |
||||||
|
i0_ = i0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
i1_ = i1 + (i0 >> (uint32_t)51U); |
||||||
|
output[0U] = i0_; |
||||||
|
output[1U] = i1_; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_( |
||||||
|
uint64_t *input, |
||||||
|
FStar_UInt128_uint128 *tmp, |
||||||
|
uint32_t count1 |
||||||
|
) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
Hacl_Bignum_Fsquare_fsquare_(tmp, input); |
||||||
|
for (i = (uint32_t)1U; i < count1; i = i + (uint32_t)1U) |
||||||
|
Hacl_Bignum_Fsquare_fsquare_(tmp, input); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(uint64_t *output, uint64_t *input, uint32_t count1) |
||||||
|
{ |
||||||
|
KRML_CHECK_SIZE(sizeof (FStar_UInt128_uint128), (uint32_t)5U); |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 t[5U]; |
||||||
|
{ |
||||||
|
uint32_t _i; |
||||||
|
for (_i = 0U; _i < (uint32_t)5U; ++_i) |
||||||
|
t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); |
||||||
|
} |
||||||
|
memcpy(output, input, (uint32_t)5U * sizeof input[0U]); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Fsquare_fsquare_times_inplace(uint64_t *output, uint32_t count1) |
||||||
|
{ |
||||||
|
KRML_CHECK_SIZE(sizeof (FStar_UInt128_uint128), (uint32_t)5U); |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 t[5U]; |
||||||
|
{ |
||||||
|
uint32_t _i; |
||||||
|
for (_i = 0U; _i < (uint32_t)5U; ++_i) |
||||||
|
t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); |
||||||
|
} |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_Crecip_crecip(uint64_t *out, uint64_t *z) |
||||||
|
{ |
||||||
|
uint64_t buf[20U] = { 0U }; |
||||||
|
uint64_t *a0 = buf; |
||||||
|
uint64_t *t00 = buf + (uint32_t)5U; |
||||||
|
uint64_t *b0 = buf + (uint32_t)10U; |
||||||
|
uint64_t *t01; |
||||||
|
uint64_t *b1; |
||||||
|
uint64_t *c0; |
||||||
|
uint64_t *a; |
||||||
|
uint64_t *t0; |
||||||
|
uint64_t *b; |
||||||
|
uint64_t *c; |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(a0, z, (uint32_t)1U); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t00, a0, (uint32_t)2U); |
||||||
|
Hacl_Bignum_Fmul_fmul(b0, t00, z); |
||||||
|
Hacl_Bignum_Fmul_fmul(a0, b0, a0); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t00, a0, (uint32_t)1U); |
||||||
|
Hacl_Bignum_Fmul_fmul(b0, t00, b0); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t00, b0, (uint32_t)5U); |
||||||
|
t01 = buf + (uint32_t)5U; |
||||||
|
b1 = buf + (uint32_t)10U; |
||||||
|
c0 = buf + (uint32_t)15U; |
||||||
|
Hacl_Bignum_Fmul_fmul(b1, t01, b1); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)10U); |
||||||
|
Hacl_Bignum_Fmul_fmul(c0, t01, b1); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t01, c0, (uint32_t)20U); |
||||||
|
Hacl_Bignum_Fmul_fmul(t01, t01, c0); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_inplace(t01, (uint32_t)10U); |
||||||
|
Hacl_Bignum_Fmul_fmul(b1, t01, b1); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)50U); |
||||||
|
a = buf; |
||||||
|
t0 = buf + (uint32_t)5U; |
||||||
|
b = buf + (uint32_t)10U; |
||||||
|
c = buf + (uint32_t)15U; |
||||||
|
Hacl_Bignum_Fmul_fmul(c, t0, b); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(t0, c, (uint32_t)100U); |
||||||
|
Hacl_Bignum_Fmul_fmul(t0, t0, c); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)50U); |
||||||
|
Hacl_Bignum_Fmul_fmul(t0, t0, b); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)5U); |
||||||
|
Hacl_Bignum_Fmul_fmul(out, t0, a); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_fsum(uint64_t *a, uint64_t *b) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint64_t xi = a[i]; |
||||||
|
uint64_t yi = b[i]; |
||||||
|
a[i] = xi + yi; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_fdifference(uint64_t *a, uint64_t *b) |
||||||
|
{ |
||||||
|
uint64_t tmp[5U] = { 0U }; |
||||||
|
uint64_t b0; |
||||||
|
uint64_t b1; |
||||||
|
uint64_t b2; |
||||||
|
uint64_t b3; |
||||||
|
uint64_t b4; |
||||||
|
memcpy(tmp, b, (uint32_t)5U * sizeof b[0U]); |
||||||
|
b0 = tmp[0U]; |
||||||
|
b1 = tmp[1U]; |
||||||
|
b2 = tmp[2U]; |
||||||
|
b3 = tmp[3U]; |
||||||
|
b4 = tmp[4U]; |
||||||
|
tmp[0U] = b0 + (uint64_t)0x3fffffffffff68U; |
||||||
|
tmp[1U] = b1 + (uint64_t)0x3ffffffffffff8U; |
||||||
|
tmp[2U] = b2 + (uint64_t)0x3ffffffffffff8U; |
||||||
|
tmp[3U] = b3 + (uint64_t)0x3ffffffffffff8U; |
||||||
|
tmp[4U] = b4 + (uint64_t)0x3ffffffffffff8U; |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint64_t xi = a[i]; |
||||||
|
uint64_t yi = tmp[i]; |
||||||
|
a[i] = yi - xi; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_fscalar(uint64_t *output, uint64_t *b, uint64_t s) |
||||||
|
{ |
||||||
|
KRML_CHECK_SIZE(sizeof (FStar_UInt128_uint128), (uint32_t)5U); |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 tmp[5U]; |
||||||
|
{ |
||||||
|
uint32_t _i; |
||||||
|
for (_i = 0U; _i < (uint32_t)5U; ++_i) |
||||||
|
tmp[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); |
||||||
|
} |
||||||
|
{ |
||||||
|
FStar_UInt128_uint128 b4; |
||||||
|
FStar_UInt128_uint128 b0; |
||||||
|
FStar_UInt128_uint128 b4_; |
||||||
|
FStar_UInt128_uint128 b0_; |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
for (i = (uint32_t)0U; i < (uint32_t)5U; i = i + (uint32_t)1U) |
||||||
|
{ |
||||||
|
uint64_t xi = b[i]; |
||||||
|
tmp[i] = FStar_UInt128_mul_wide(xi, s); |
||||||
|
} |
||||||
|
} |
||||||
|
Hacl_Bignum_Fproduct_carry_wide_(tmp); |
||||||
|
b4 = tmp[4U]; |
||||||
|
b0 = tmp[0U]; |
||||||
|
b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU)); |
||||||
|
b0_ = |
||||||
|
FStar_UInt128_add(b0, |
||||||
|
FStar_UInt128_mul_wide((uint64_t)19U, |
||||||
|
FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U)))); |
||||||
|
tmp[4U] = b4_; |
||||||
|
tmp[0U] = b0_; |
||||||
|
Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_fmul(uint64_t *output, uint64_t *a, uint64_t *b) |
||||||
|
{ |
||||||
|
Hacl_Bignum_Fmul_fmul(output, a, b); |
||||||
|
} |
||||||
|
|
||||||
|
inline static void Hacl_Bignum_crecip(uint64_t *output, uint64_t *input) |
||||||
|
{ |
||||||
|
Hacl_Bignum_Crecip_crecip(output, input); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Point_swap_conditional_step(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr) |
||||||
|
{ |
||||||
|
uint32_t i = ctr - (uint32_t)1U; |
||||||
|
uint64_t ai = a[i]; |
||||||
|
uint64_t bi = b[i]; |
||||||
|
uint64_t x = swap1 & (ai ^ bi); |
||||||
|
uint64_t ai1 = ai ^ x; |
||||||
|
uint64_t bi1 = bi ^ x; |
||||||
|
a[i] = ai1; |
||||||
|
b[i] = bi1; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Point_swap_conditional_(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr) |
||||||
|
{ |
||||||
|
if (!(ctr == (uint32_t)0U)) |
||||||
|
{ |
||||||
|
uint32_t i; |
||||||
|
Hacl_EC_Point_swap_conditional_step(a, b, swap1, ctr); |
||||||
|
i = ctr - (uint32_t)1U; |
||||||
|
Hacl_EC_Point_swap_conditional_(a, b, swap1, i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Point_swap_conditional(uint64_t *a, uint64_t *b, uint64_t iswap) |
||||||
|
{ |
||||||
|
uint64_t swap1 = (uint64_t)0U - iswap; |
||||||
|
Hacl_EC_Point_swap_conditional_(a, b, swap1, (uint32_t)5U); |
||||||
|
Hacl_EC_Point_swap_conditional_(a + (uint32_t)5U, b + (uint32_t)5U, swap1, (uint32_t)5U); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Point_copy(uint64_t *output, uint64_t *input) |
||||||
|
{ |
||||||
|
memcpy(output, input, (uint32_t)5U * sizeof input[0U]); |
||||||
|
memcpy(output + (uint32_t)5U, |
||||||
|
input + (uint32_t)5U, |
||||||
|
(uint32_t)5U * sizeof (input + (uint32_t)5U)[0U]); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fexpand(uint64_t *output, uint8_t *input) |
||||||
|
{ |
||||||
|
uint64_t i0 = load64_le(input); |
||||||
|
uint8_t *x00 = input + (uint32_t)6U; |
||||||
|
uint64_t i1 = load64_le(x00); |
||||||
|
uint8_t *x01 = input + (uint32_t)12U; |
||||||
|
uint64_t i2 = load64_le(x01); |
||||||
|
uint8_t *x02 = input + (uint32_t)19U; |
||||||
|
uint64_t i3 = load64_le(x02); |
||||||
|
uint8_t *x0 = input + (uint32_t)24U; |
||||||
|
uint64_t i4 = load64_le(x0); |
||||||
|
uint64_t output0 = i0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t output1 = i1 >> (uint32_t)3U & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t output2 = i2 >> (uint32_t)6U & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t output3 = i3 >> (uint32_t)1U & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t output4 = i4 >> (uint32_t)12U & (uint64_t)0x7ffffffffffffU; |
||||||
|
output[0U] = output0; |
||||||
|
output[1U] = output1; |
||||||
|
output[2U] = output2; |
||||||
|
output[3U] = output3; |
||||||
|
output[4U] = output4; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_first_carry_pass(uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t t0 = input[0U]; |
||||||
|
uint64_t t1 = input[1U]; |
||||||
|
uint64_t t2 = input[2U]; |
||||||
|
uint64_t t3 = input[3U]; |
||||||
|
uint64_t t4 = input[4U]; |
||||||
|
uint64_t t1_ = t1 + (t0 >> (uint32_t)51U); |
||||||
|
uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U); |
||||||
|
uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U); |
||||||
|
uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U); |
||||||
|
uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
input[0U] = t0_; |
||||||
|
input[1U] = t1__; |
||||||
|
input[2U] = t2__; |
||||||
|
input[3U] = t3__; |
||||||
|
input[4U] = t4_; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_first_carry_full(uint64_t *input) |
||||||
|
{ |
||||||
|
Hacl_EC_Format_fcontract_first_carry_pass(input); |
||||||
|
Hacl_Bignum_Modulo_carry_top(input); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_second_carry_pass(uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t t0 = input[0U]; |
||||||
|
uint64_t t1 = input[1U]; |
||||||
|
uint64_t t2 = input[2U]; |
||||||
|
uint64_t t3 = input[3U]; |
||||||
|
uint64_t t4 = input[4U]; |
||||||
|
uint64_t t1_ = t1 + (t0 >> (uint32_t)51U); |
||||||
|
uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U); |
||||||
|
uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U); |
||||||
|
uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U); |
||||||
|
uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU; |
||||||
|
input[0U] = t0_; |
||||||
|
input[1U] = t1__; |
||||||
|
input[2U] = t2__; |
||||||
|
input[3U] = t3__; |
||||||
|
input[4U] = t4_; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_second_carry_full(uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t i0; |
||||||
|
uint64_t i1; |
||||||
|
uint64_t i0_; |
||||||
|
uint64_t i1_; |
||||||
|
Hacl_EC_Format_fcontract_second_carry_pass(input); |
||||||
|
Hacl_Bignum_Modulo_carry_top(input); |
||||||
|
i0 = input[0U]; |
||||||
|
i1 = input[1U]; |
||||||
|
i0_ = i0 & (uint64_t)0x7ffffffffffffU; |
||||||
|
i1_ = i1 + (i0 >> (uint32_t)51U); |
||||||
|
input[0U] = i0_; |
||||||
|
input[1U] = i1_; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_trim(uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t a0 = input[0U]; |
||||||
|
uint64_t a1 = input[1U]; |
||||||
|
uint64_t a2 = input[2U]; |
||||||
|
uint64_t a3 = input[3U]; |
||||||
|
uint64_t a4 = input[4U]; |
||||||
|
uint64_t mask0 = FStar_UInt64_gte_mask(a0, (uint64_t)0x7ffffffffffedU); |
||||||
|
uint64_t mask1 = FStar_UInt64_eq_mask(a1, (uint64_t)0x7ffffffffffffU); |
||||||
|
uint64_t mask2 = FStar_UInt64_eq_mask(a2, (uint64_t)0x7ffffffffffffU); |
||||||
|
uint64_t mask3 = FStar_UInt64_eq_mask(a3, (uint64_t)0x7ffffffffffffU); |
||||||
|
uint64_t mask4 = FStar_UInt64_eq_mask(a4, (uint64_t)0x7ffffffffffffU); |
||||||
|
uint64_t mask = (((mask0 & mask1) & mask2) & mask3) & mask4; |
||||||
|
uint64_t a0_ = a0 - ((uint64_t)0x7ffffffffffedU & mask); |
||||||
|
uint64_t a1_ = a1 - ((uint64_t)0x7ffffffffffffU & mask); |
||||||
|
uint64_t a2_ = a2 - ((uint64_t)0x7ffffffffffffU & mask); |
||||||
|
uint64_t a3_ = a3 - ((uint64_t)0x7ffffffffffffU & mask); |
||||||
|
uint64_t a4_ = a4 - ((uint64_t)0x7ffffffffffffU & mask); |
||||||
|
input[0U] = a0_; |
||||||
|
input[1U] = a1_; |
||||||
|
input[2U] = a2_; |
||||||
|
input[3U] = a3_; |
||||||
|
input[4U] = a4_; |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract_store(uint8_t *output, uint64_t *input) |
||||||
|
{ |
||||||
|
uint64_t t0 = input[0U]; |
||||||
|
uint64_t t1 = input[1U]; |
||||||
|
uint64_t t2 = input[2U]; |
||||||
|
uint64_t t3 = input[3U]; |
||||||
|
uint64_t t4 = input[4U]; |
||||||
|
uint64_t o0 = t1 << (uint32_t)51U | t0; |
||||||
|
uint64_t o1 = t2 << (uint32_t)38U | t1 >> (uint32_t)13U; |
||||||
|
uint64_t o2 = t3 << (uint32_t)25U | t2 >> (uint32_t)26U; |
||||||
|
uint64_t o3 = t4 << (uint32_t)12U | t3 >> (uint32_t)39U; |
||||||
|
uint8_t *b0 = output; |
||||||
|
uint8_t *b1 = output + (uint32_t)8U; |
||||||
|
uint8_t *b2 = output + (uint32_t)16U; |
||||||
|
uint8_t *b3 = output + (uint32_t)24U; |
||||||
|
store64_le(b0, o0); |
||||||
|
store64_le(b1, o1); |
||||||
|
store64_le(b2, o2); |
||||||
|
store64_le(b3, o3); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_fcontract(uint8_t *output, uint64_t *input) |
||||||
|
{ |
||||||
|
Hacl_EC_Format_fcontract_first_carry_full(input); |
||||||
|
Hacl_EC_Format_fcontract_second_carry_full(input); |
||||||
|
Hacl_EC_Format_fcontract_trim(input); |
||||||
|
Hacl_EC_Format_fcontract_store(output, input); |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Format_scalar_of_point(uint8_t *scalar, uint64_t *point) |
||||||
|
{ |
||||||
|
uint64_t *x = point; |
||||||
|
uint64_t *z = point + (uint32_t)5U; |
||||||
|
uint64_t buf[10U] = { 0U }; |
||||||
|
uint64_t *zmone = buf; |
||||||
|
uint64_t *sc = buf + (uint32_t)5U; |
||||||
|
Hacl_Bignum_crecip(zmone, z); |
||||||
|
Hacl_Bignum_fmul(sc, x, zmone); |
||||||
|
Hacl_EC_Format_fcontract(scalar, sc); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_AddAndDouble_fmonty( |
||||||
|
uint64_t *pp, |
||||||
|
uint64_t *ppq, |
||||||
|
uint64_t *p, |
||||||
|
uint64_t *pq, |
||||||
|
uint64_t *qmqp |
||||||
|
) |
||||||
|
{ |
||||||
|
uint64_t *qx = qmqp; |
||||||
|
uint64_t *x2 = pp; |
||||||
|
uint64_t *z2 = pp + (uint32_t)5U; |
||||||
|
uint64_t *x3 = ppq; |
||||||
|
uint64_t *z3 = ppq + (uint32_t)5U; |
||||||
|
uint64_t *x = p; |
||||||
|
uint64_t *z = p + (uint32_t)5U; |
||||||
|
uint64_t *xprime = pq; |
||||||
|
uint64_t *zprime = pq + (uint32_t)5U; |
||||||
|
uint64_t buf[40U] = { 0U }; |
||||||
|
uint64_t *origx = buf; |
||||||
|
uint64_t *origxprime0 = buf + (uint32_t)5U; |
||||||
|
uint64_t *xxprime0 = buf + (uint32_t)25U; |
||||||
|
uint64_t *zzprime0 = buf + (uint32_t)30U; |
||||||
|
uint64_t *origxprime; |
||||||
|
uint64_t *xx0; |
||||||
|
uint64_t *zz0; |
||||||
|
uint64_t *xxprime; |
||||||
|
uint64_t *zzprime; |
||||||
|
uint64_t *zzzprime; |
||||||
|
uint64_t *zzz; |
||||||
|
uint64_t *xx; |
||||||
|
uint64_t *zz; |
||||||
|
uint64_t scalar; |
||||||
|
memcpy(origx, x, (uint32_t)5U * sizeof x[0U]); |
||||||
|
Hacl_Bignum_fsum(x, z); |
||||||
|
Hacl_Bignum_fdifference(z, origx); |
||||||
|
memcpy(origxprime0, xprime, (uint32_t)5U * sizeof xprime[0U]); |
||||||
|
Hacl_Bignum_fsum(xprime, zprime); |
||||||
|
Hacl_Bignum_fdifference(zprime, origxprime0); |
||||||
|
Hacl_Bignum_fmul(xxprime0, xprime, z); |
||||||
|
Hacl_Bignum_fmul(zzprime0, x, zprime); |
||||||
|
origxprime = buf + (uint32_t)5U; |
||||||
|
xx0 = buf + (uint32_t)15U; |
||||||
|
zz0 = buf + (uint32_t)20U; |
||||||
|
xxprime = buf + (uint32_t)25U; |
||||||
|
zzprime = buf + (uint32_t)30U; |
||||||
|
zzzprime = buf + (uint32_t)35U; |
||||||
|
memcpy(origxprime, xxprime, (uint32_t)5U * sizeof xxprime[0U]); |
||||||
|
Hacl_Bignum_fsum(xxprime, zzprime); |
||||||
|
Hacl_Bignum_fdifference(zzprime, origxprime); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(x3, xxprime, (uint32_t)1U); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(zzzprime, zzprime, (uint32_t)1U); |
||||||
|
Hacl_Bignum_fmul(z3, zzzprime, qx); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(xx0, x, (uint32_t)1U); |
||||||
|
Hacl_Bignum_Fsquare_fsquare_times(zz0, z, (uint32_t)1U); |
||||||
|
zzz = buf + (uint32_t)10U; |
||||||
|
xx = buf + (uint32_t)15U; |
||||||
|
zz = buf + (uint32_t)20U; |
||||||
|
Hacl_Bignum_fmul(x2, xx, zz); |
||||||
|
Hacl_Bignum_fdifference(zz, xx); |
||||||
|
scalar = (uint64_t)121665U; |
||||||
|
Hacl_Bignum_fscalar(zzz, zz, scalar); |
||||||
|
Hacl_Bignum_fsum(zzz, xx); |
||||||
|
Hacl_Bignum_fmul(z2, zzz, zz); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step( |
||||||
|
uint64_t *nq, |
||||||
|
uint64_t *nqpq, |
||||||
|
uint64_t *nq2, |
||||||
|
uint64_t *nqpq2, |
||||||
|
uint64_t *q, |
||||||
|
uint8_t byt |
||||||
|
) |
||||||
|
{ |
||||||
|
uint64_t bit0 = (uint64_t)(byt >> (uint32_t)7U); |
||||||
|
uint64_t bit; |
||||||
|
Hacl_EC_Point_swap_conditional(nq, nqpq, bit0); |
||||||
|
Hacl_EC_AddAndDouble_fmonty(nq2, nqpq2, nq, nqpq, q); |
||||||
|
bit = (uint64_t)(byt >> (uint32_t)7U); |
||||||
|
Hacl_EC_Point_swap_conditional(nq2, nqpq2, bit); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step( |
||||||
|
uint64_t *nq, |
||||||
|
uint64_t *nqpq, |
||||||
|
uint64_t *nq2, |
||||||
|
uint64_t *nqpq2, |
||||||
|
uint64_t *q, |
||||||
|
uint8_t byt |
||||||
|
) |
||||||
|
{ |
||||||
|
uint8_t byt1; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq, nqpq, nq2, nqpq2, q, byt); |
||||||
|
byt1 = byt << (uint32_t)1U; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq2, nqpq2, nq, nqpq, q, byt1); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop( |
||||||
|
uint64_t *nq, |
||||||
|
uint64_t *nqpq, |
||||||
|
uint64_t *nq2, |
||||||
|
uint64_t *nqpq2, |
||||||
|
uint64_t *q, |
||||||
|
uint8_t byt, |
||||||
|
uint32_t i |
||||||
|
) |
||||||
|
{ |
||||||
|
if (!(i == (uint32_t)0U)) |
||||||
|
{ |
||||||
|
uint32_t i_ = i - (uint32_t)1U; |
||||||
|
uint8_t byt_; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(nq, nqpq, nq2, nqpq2, q, byt); |
||||||
|
byt_ = byt << (uint32_t)2U; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byt_, i_); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
Hacl_EC_Ladder_BigLoop_cmult_big_loop( |
||||||
|
uint8_t *n1, |
||||||
|
uint64_t *nq, |
||||||
|
uint64_t *nqpq, |
||||||
|
uint64_t *nq2, |
||||||
|
uint64_t *nqpq2, |
||||||
|
uint64_t *q, |
||||||
|
uint32_t i |
||||||
|
) |
||||||
|
{ |
||||||
|
if (!(i == (uint32_t)0U)) |
||||||
|
{ |
||||||
|
uint32_t i1 = i - (uint32_t)1U; |
||||||
|
uint8_t byte = n1[i1]; |
||||||
|
Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byte, (uint32_t)4U); |
||||||
|
Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, i1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void Hacl_EC_Ladder_cmult(uint64_t *result, uint8_t *n1, uint64_t *q) |
||||||
|
{ |
||||||
|
uint64_t point_buf[40U] = { 0U }; |
||||||
|
uint64_t *nq = point_buf; |
||||||
|
uint64_t *nqpq = point_buf + (uint32_t)10U; |
||||||
|
uint64_t *nq2 = point_buf + (uint32_t)20U; |
||||||
|
uint64_t *nqpq2 = point_buf + (uint32_t)30U; |
||||||
|
Hacl_EC_Point_copy(nqpq, q); |
||||||
|
nq[0U] = (uint64_t)1U; |
||||||
|
Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, (uint32_t)32U); |
||||||
|
Hacl_EC_Point_copy(result, nq); |
||||||
|
} |
||||||
|
|
||||||
|
void Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint) |
||||||
|
{ |
||||||
|
uint64_t buf0[10U] = { 0U }; |
||||||
|
uint64_t *x0 = buf0; |
||||||
|
uint64_t *z = buf0 + (uint32_t)5U; |
||||||
|
uint64_t *q; |
||||||
|
Hacl_EC_Format_fexpand(x0, basepoint); |
||||||
|
z[0U] = (uint64_t)1U; |
||||||
|
q = buf0; |
||||||
|
{ |
||||||
|
uint8_t e[32U] = { 0U }; |
||||||
|
uint8_t e0; |
||||||
|
uint8_t e31; |
||||||
|
uint8_t e01; |
||||||
|
uint8_t e311; |
||||||
|
uint8_t e312; |
||||||
|
uint8_t *scalar; |
||||||
|
memcpy(e, secret, (uint32_t)32U * sizeof secret[0U]); |
||||||
|
e0 = e[0U]; |
||||||
|
e31 = e[31U]; |
||||||
|
e01 = e0 & (uint8_t)248U; |
||||||
|
e311 = e31 & (uint8_t)127U; |
||||||
|
e312 = e311 | (uint8_t)64U; |
||||||
|
e[0U] = e01; |
||||||
|
e[31U] = e312; |
||||||
|
scalar = e; |
||||||
|
{ |
||||||
|
uint64_t buf[15U] = { 0U }; |
||||||
|
uint64_t *nq = buf; |
||||||
|
uint64_t *x = nq; |
||||||
|
x[0U] = (uint64_t)1U; |
||||||
|
Hacl_EC_Ladder_cmult(nq, scalar, q); |
||||||
|
Hacl_EC_Format_scalar_of_point(mypublic, nq); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,186 @@ |
|||||||
|
/*
|
||||||
|
* ECDH with curve-optimized implementation multiplexing |
||||||
|
* |
||||||
|
* Copyright 2016-2018 INRIA and Microsoft Corporation |
||||||
|
* 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)
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include "common.h" |
||||||
|
|
||||||
|
#if defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) |
||||||
|
|
||||||
|
#include <mbedtls/ecdh.h> |
||||||
|
|
||||||
|
#if !(defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16)) |
||||||
|
#define KRML_VERIFIED_UINT128 |
||||||
|
#endif |
||||||
|
|
||||||
|
#include <Hacl_Curve25519.h> |
||||||
|
#include <mbedtls/platform_util.h> |
||||||
|
|
||||||
|
#include "x25519.h" |
||||||
|
|
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize context |
||||||
|
*/ |
||||||
|
void mbedtls_x25519_init( mbedtls_x25519_context *ctx ) |
||||||
|
{ |
||||||
|
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x25519_context ) ); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Free context |
||||||
|
*/ |
||||||
|
void mbedtls_x25519_free( mbedtls_x25519_context *ctx ) |
||||||
|
{ |
||||||
|
if( ctx == NULL ) |
||||||
|
return; |
||||||
|
|
||||||
|
mbedtls_platform_zeroize( ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ); |
||||||
|
mbedtls_platform_zeroize( ctx->peer_point, MBEDTLS_X25519_KEY_SIZE_BYTES ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_x25519_make_params( mbedtls_x25519_context *ctx, size_t *olen, |
||||||
|
unsigned char *buf, size_t blen, |
||||||
|
int( *f_rng )(void *, unsigned char *, size_t), |
||||||
|
void *p_rng ) |
||||||
|
{ |
||||||
|
int ret = 0; |
||||||
|
|
||||||
|
uint8_t base[MBEDTLS_X25519_KEY_SIZE_BYTES] = {0}; |
||||||
|
|
||||||
|
if( ( ret = f_rng( p_rng, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ) ) != 0 ) |
||||||
|
return ret; |
||||||
|
|
||||||
|
*olen = MBEDTLS_X25519_KEY_SIZE_BYTES + 4; |
||||||
|
if( blen < *olen ) |
||||||
|
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
||||||
|
|
||||||
|
*buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; |
||||||
|
*buf++ = MBEDTLS_ECP_TLS_CURVE25519 >> 8; |
||||||
|
*buf++ = MBEDTLS_ECP_TLS_CURVE25519 & 0xFF; |
||||||
|
*buf++ = MBEDTLS_X25519_KEY_SIZE_BYTES; |
||||||
|
|
||||||
|
base[0] = 9; |
||||||
|
Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, base ); |
||||||
|
|
||||||
|
base[0] = 0; |
||||||
|
if( memcmp( buf, base, MBEDTLS_X25519_KEY_SIZE_BYTES) == 0 ) |
||||||
|
return MBEDTLS_ERR_ECP_RANDOM_FAILED; |
||||||
|
|
||||||
|
return( 0 ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_x25519_read_params( mbedtls_x25519_context *ctx, |
||||||
|
const unsigned char **buf, const unsigned char *end ) |
||||||
|
{ |
||||||
|
if( end - *buf < MBEDTLS_X25519_KEY_SIZE_BYTES + 1 ) |
||||||
|
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
||||||
|
|
||||||
|
if( ( *(*buf)++ != MBEDTLS_X25519_KEY_SIZE_BYTES ) ) |
||||||
|
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
||||||
|
|
||||||
|
memcpy( ctx->peer_point, *buf, MBEDTLS_X25519_KEY_SIZE_BYTES ); |
||||||
|
*buf += MBEDTLS_X25519_KEY_SIZE_BYTES; |
||||||
|
return( 0 ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_x25519_get_params( mbedtls_x25519_context *ctx, const mbedtls_ecp_keypair *key, |
||||||
|
mbedtls_x25519_ecdh_side side ) |
||||||
|
{ |
||||||
|
size_t olen = 0; |
||||||
|
|
||||||
|
switch( side ) { |
||||||
|
case MBEDTLS_X25519_ECDH_THEIRS: |
||||||
|
return mbedtls_ecp_point_write_binary( &key->grp, &key->Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, ctx->peer_point, MBEDTLS_X25519_KEY_SIZE_BYTES ); |
||||||
|
case MBEDTLS_X25519_ECDH_OURS: |
||||||
|
return mbedtls_mpi_write_binary_le( &key->d, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ); |
||||||
|
default: |
||||||
|
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_x25519_calc_secret( mbedtls_x25519_context *ctx, size_t *olen, |
||||||
|
unsigned char *buf, size_t blen, |
||||||
|
int( *f_rng )(void *, unsigned char *, size_t), |
||||||
|
void *p_rng ) |
||||||
|
{ |
||||||
|
/* f_rng and p_rng are not used here because this implementation does not
|
||||||
|
need blinding since it has constant trace. */ |
||||||
|
(( void )f_rng); |
||||||
|
(( void )p_rng); |
||||||
|
|
||||||
|
*olen = MBEDTLS_X25519_KEY_SIZE_BYTES; |
||||||
|
|
||||||
|
if( blen < *olen ) |
||||||
|
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); |
||||||
|
|
||||||
|
Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, ctx->peer_point); |
||||||
|
|
||||||
|
/* Wipe the DH secret and don't let the peer chose a small subgroup point */ |
||||||
|
mbedtls_platform_zeroize( ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ); |
||||||
|
|
||||||
|
if( memcmp( buf, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES) == 0 ) |
||||||
|
return MBEDTLS_ERR_ECP_RANDOM_FAILED; |
||||||
|
|
||||||
|
return( 0 ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_x25519_make_public( mbedtls_x25519_context *ctx, size_t *olen, |
||||||
|
unsigned char *buf, size_t blen, |
||||||
|
int( *f_rng )(void *, unsigned char *, size_t), |
||||||
|
void *p_rng ) |
||||||
|
{ |
||||||
|
int ret = 0; |
||||||
|
unsigned char base[MBEDTLS_X25519_KEY_SIZE_BYTES] = { 0 }; |
||||||
|
|
||||||
|
if( ctx == NULL ) |
||||||
|
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); |
||||||
|
|
||||||
|
if( ( ret = f_rng( p_rng, ctx->our_secret, MBEDTLS_X25519_KEY_SIZE_BYTES ) ) != 0 ) |
||||||
|
return ret; |
||||||
|
|
||||||
|
*olen = MBEDTLS_X25519_KEY_SIZE_BYTES + 1; |
||||||
|
if( blen < *olen ) |
||||||
|
return(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL); |
||||||
|
*buf++ = MBEDTLS_X25519_KEY_SIZE_BYTES; |
||||||
|
|
||||||
|
base[0] = 9; |
||||||
|
Hacl_Curve25519_crypto_scalarmult( buf, ctx->our_secret, base ); |
||||||
|
|
||||||
|
base[0] = 0; |
||||||
|
if( memcmp( buf, base, MBEDTLS_X25519_KEY_SIZE_BYTES ) == 0 ) |
||||||
|
return MBEDTLS_ERR_ECP_RANDOM_FAILED; |
||||||
|
|
||||||
|
return( ret ); |
||||||
|
} |
||||||
|
|
||||||
|
int mbedtls_x25519_read_public( mbedtls_x25519_context *ctx, |
||||||
|
const unsigned char *buf, size_t blen ) |
||||||
|
{ |
||||||
|
if( blen < MBEDTLS_X25519_KEY_SIZE_BYTES + 1 ) |
||||||
|
return(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL); |
||||||
|
if( (*buf++ != MBEDTLS_X25519_KEY_SIZE_BYTES) ) |
||||||
|
return(MBEDTLS_ERR_ECP_BAD_INPUT_DATA); |
||||||
|
memcpy( ctx->peer_point, buf, MBEDTLS_X25519_KEY_SIZE_BYTES ); |
||||||
|
return( 0 ); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_ECDH_C && MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */ |
@ -0,0 +1,106 @@ |
|||||||
|
# Maintained branches |
||||||
|
|
||||||
|
At any point in time, we have a number of maintained branches, currently consisting of: |
||||||
|
|
||||||
|
- The [`master`](https://github.com/Mbed-TLS/mbedtls/tree/master) branch: |
||||||
|
this always contains the latest release, including all publicly available |
||||||
|
security fixes. |
||||||
|
- The [`development`](https://github.com/Mbed-TLS/mbedtls/tree/development) branch: |
||||||
|
this is where the current major version of Mbed TLS (version 3.x) is being |
||||||
|
prepared. It has API changes that make it incompatible with Mbed TLS 2.x, |
||||||
|
as well as all the new features and bug fixes and security fixes. |
||||||
|
- One or more long-time support (LTS) branches: these only get bug fixes and |
||||||
|
security fixes. Currently, the only supported LTS branch is: |
||||||
|
[`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28). |
||||||
|
|
||||||
|
We retain a number of historical branches, whose names are prefixed by `archive/`, |
||||||
|
such as [`archive/mbedtls-2.7`](https://github.com/Mbed-TLS/mbedtls/tree/archive/mbedtls-2.7). |
||||||
|
These branches will not receive any changes or updates. |
||||||
|
|
||||||
|
We use [Semantic Versioning](https://semver.org/). In particular, we maintain |
||||||
|
API compatibility in the `master` branch across minor version changes (e.g. |
||||||
|
the API of 3.(x+1) is backward compatible with 3.x). We only break API |
||||||
|
compatibility on major version changes (e.g. from 3.x to 4.0). We also maintain |
||||||
|
ABI compatibility within LTS branches; see the next section for details. |
||||||
|
|
||||||
|
## Backwards Compatibility for application code |
||||||
|
|
||||||
|
We maintain API compatibility in released versions of Mbed TLS. If you have |
||||||
|
code that's working and secure with Mbed TLS x.y.z and does not rely on |
||||||
|
undocumented features, then you should be able to re-compile it without |
||||||
|
modification with any later release x.y'.z' with the same major version |
||||||
|
number, and your code will still build, be secure, and work. |
||||||
|
|
||||||
|
Note that this guarantee only applies if you either use the default |
||||||
|
compile-time configuration (`mbedtls/mbedtls_config.h`) or the same modified |
||||||
|
compile-time configuration. Changing compile-time configuration options can |
||||||
|
result in an incompatible API or ABI, although features will generally not |
||||||
|
affect unrelated features (for example, enabling or disabling a |
||||||
|
cryptographic algorithm does not break code that does not use that |
||||||
|
algorithm). |
||||||
|
|
||||||
|
Note that new releases of Mbed TLS may extend the API. Here are some |
||||||
|
examples of changes that are common in minor releases of Mbed TLS, and are |
||||||
|
not considered API compatibility breaks: |
||||||
|
|
||||||
|
* Adding or reordering fields in a structure or union. |
||||||
|
* Removing a field from a structure, unless the field is documented as public. |
||||||
|
* Adding items to an enum. |
||||||
|
* Returning an error code that was not previously documented for a function |
||||||
|
when a new error condition arises. |
||||||
|
* Changing which error code is returned in a case where multiple error |
||||||
|
conditions apply. |
||||||
|
* Changing the behavior of a function from failing to succeeding, when the |
||||||
|
change is a reasonable extension of the current behavior, i.e. the |
||||||
|
addition of a new feature. |
||||||
|
|
||||||
|
There are rare exceptions where we break API compatibility: code that was |
||||||
|
relying on something that became insecure in the meantime (for example, |
||||||
|
crypto that was found to be weak) may need to be changed. In case security |
||||||
|
comes in conflict with backwards compatibility, we will put security first, |
||||||
|
but always attempt to provide a compatibility option. |
||||||
|
|
||||||
|
## Backward compatibility for the key store |
||||||
|
|
||||||
|
We maintain backward compatibility with previous versions of the |
||||||
|
PSA Crypto persistent storage since Mbed TLS 2.25.0, provided that the |
||||||
|
storage backend (PSA ITS implementation) is configured in a compatible way. |
||||||
|
We intend to maintain this backward compatibility throughout a major version |
||||||
|
of Mbed TLS (for example, all Mbed TLS 3.y versions will be able to read |
||||||
|
keys written under any Mbed TLS 3.x with x <= y). |
||||||
|
|
||||||
|
Mbed TLS 3.x can also read keys written by Mbed TLS 2.25.0 through 2.28.x |
||||||
|
LTS, but future major version upgrades (for example from 2.28.x/3.x to 4.y) |
||||||
|
may require the use of an upgrade tool. |
||||||
|
|
||||||
|
Note that this guarantee does not currently fully extend to drivers, which |
||||||
|
are an experimental feature. We intend to maintain compatibility with the |
||||||
|
basic use of drivers from Mbed TLS 2.28.0 onwards, even if driver APIs |
||||||
|
change. However, for more experimental parts of the driver interface, such |
||||||
|
as the use of driver state, we do not yet guarantee backward compatibility. |
||||||
|
|
||||||
|
## Long-time support branches |
||||||
|
|
||||||
|
For the LTS branches, additionally we try very hard to also maintain ABI |
||||||
|
compatibility (same definition as API except with re-linking instead of |
||||||
|
re-compiling) and to avoid any increase in code size or RAM usage, or in the |
||||||
|
minimum version of tools needed to build the code. The only exception, as |
||||||
|
before, is in case those goals would conflict with fixing a security issue, we |
||||||
|
will put security first but provide a compatibility option. (So far we never |
||||||
|
had to break ABI compatibility in an LTS branch, but we occasionally had to |
||||||
|
increase code size for a security fix.) |
||||||
|
|
||||||
|
For contributors, see the [Backwards Compatibility section of |
||||||
|
CONTRIBUTING](CONTRIBUTING.md#backwards-compatibility). |
||||||
|
|
||||||
|
## Current Branches |
||||||
|
|
||||||
|
The following branches are currently maintained: |
||||||
|
|
||||||
|
- [master](https://github.com/Mbed-TLS/mbedtls/tree/master) |
||||||
|
- [`development`](https://github.com/Mbed-TLS/mbedtls/) |
||||||
|
- [`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28) |
||||||
|
maintained until at least the end of 2024, see |
||||||
|
<https://github.com/Mbed-TLS/mbedtls/releases/tag/v2.28.2>. |
||||||
|
|
||||||
|
Users are urged to always use the latest version of a maintained branch. |
@ -0,0 +1,20 @@ |
|||||||
|
## Known issues |
||||||
|
|
||||||
|
Known issues in Mbed TLS are [tracked on GitHub](https://github.com/Mbed-TLS/mbedtls/issues). |
||||||
|
|
||||||
|
## Reporting a bug |
||||||
|
|
||||||
|
If you think you've found a bug in Mbed TLS, please follow these steps: |
||||||
|
|
||||||
|
1. Make sure you're using the latest version of a |
||||||
|
[maintained branch](BRANCHES.md): `master`, `development`, |
||||||
|
or a long-time support branch. |
||||||
|
2. Check [GitHub](https://github.com/Mbed-TLS/mbedtls/issues) to see if |
||||||
|
your issue has already been reported. If not, … |
||||||
|
3. If the issue is a security risk (for example: buffer overflow, |
||||||
|
data leak), please report it confidentially as described in |
||||||
|
[`SECURITY.md`](SECURITY.md). If not, … |
||||||
|
4. Please [create an issue on on GitHub](https://github.com/Mbed-TLS/mbedtls/issues). |
||||||
|
|
||||||
|
Please do not use GitHub for support questions. If you want to know |
||||||
|
how to do something with Mbed TLS, please see [`SUPPORT.md`](SUPPORT.md) for available documentation and support channels. |
@ -0,0 +1,378 @@ |
|||||||
|
# |
||||||
|
# CMake build system design considerations: |
||||||
|
# |
||||||
|
# - Include directories: |
||||||
|
# + Do not define include directories globally using the include_directories |
||||||
|
# command but rather at the target level using the |
||||||
|
# target_include_directories command. That way, it is easier to guarantee |
||||||
|
# that targets are built using the proper list of include directories. |
||||||
|
# + Use the PUBLIC and PRIVATE keywords to specify the scope of include |
||||||
|
# directories. That way, a target linking to a library (using the |
||||||
|
# target_link_libraries command) inherits from the library PUBLIC include |
||||||
|
# directories and not from the PRIVATE ones. |
||||||
|
# - MBEDTLS_TARGET_PREFIX: CMake targets are designed to be alterable by calling |
||||||
|
# CMake in order to avoid target name clashes, via the use of |
||||||
|
# MBEDTLS_TARGET_PREFIX. The value of this variable is prefixed to the |
||||||
|
# mbedtls, mbedx509, mbedcrypto and apidoc targets. |
||||||
|
# |
||||||
|
|
||||||
|
# We specify a minimum requirement of 3.10.2, but for now use 3.5.1 here |
||||||
|
# until our infrastructure catches up. |
||||||
|
cmake_minimum_required(VERSION 3.5.1) |
||||||
|
|
||||||
|
include(CMakePackageConfigHelpers) |
||||||
|
|
||||||
|
# https://cmake.org/cmake/help/latest/policy/CMP0011.html |
||||||
|
# Setting this policy is required in CMake >= 3.18.0, otherwise a warning is generated. The OLD |
||||||
|
# policy setting is deprecated, and will be removed in future versions. |
||||||
|
cmake_policy(SET CMP0011 NEW) |
||||||
|
# https://cmake.org/cmake/help/latest/policy/CMP0012.html |
||||||
|
# Setting the CMP0012 policy to NEW is required for FindPython3 to work with CMake 3.18.2 |
||||||
|
# (there is a bug in this particular version), otherwise, setting the CMP0012 policy is required |
||||||
|
# for CMake versions >= 3.18.3 otherwise a deprecated warning is generated. The OLD policy setting |
||||||
|
# is deprecated and will be removed in future versions. |
||||||
|
cmake_policy(SET CMP0012 NEW) |
||||||
|
|
||||||
|
if(TEST_CPP) |
||||||
|
project("mbed TLS" C CXX) |
||||||
|
else() |
||||||
|
project("mbed TLS" C) |
||||||
|
endif() |
||||||
|
|
||||||
|
include(GNUInstallDirs) |
||||||
|
|
||||||
|
# Determine if mbed TLS is being built as a subproject using add_subdirectory() |
||||||
|
if(NOT DEFINED MBEDTLS_AS_SUBPROJECT) |
||||||
|
set(MBEDTLS_AS_SUBPROJECT ON) |
||||||
|
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) |
||||||
|
set(MBEDTLS_AS_SUBPROJECT OFF) |
||||||
|
endif() |
||||||
|
endif() |
||||||
|
|
||||||
|
# Set the project root directory. |
||||||
|
set(MBEDTLS_DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
||||||
|
|
||||||
|
option(ENABLE_PROGRAMS "Build mbed TLS programs." ON) |
||||||
|
|
||||||
|
option(UNSAFE_BUILD "Allow unsafe builds. These builds ARE NOT SECURE." OFF) |
||||||
|
option(MBEDTLS_FATAL_WARNINGS "Compiler warnings treated as errors" ON) |
||||||
|
if(CMAKE_HOST_WIN32) |
||||||
|
option(GEN_FILES "Generate the auto-generated files as needed" OFF) |
||||||
|
else() |
||||||
|
option(GEN_FILES "Generate the auto-generated files as needed" ON) |
||||||
|
endif() |
||||||
|
|
||||||
|
option(DISABLE_PACKAGE_CONFIG_AND_INSTALL "Disable package configuration, target export and installation" ${MBEDTLS_AS_SUBPROJECT}) |
||||||
|
|
||||||
|
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(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}") |
||||||
|
|
||||||
|
# Python 3 is only needed here to check for configuration warnings. |
||||||
|
if(NOT CMAKE_VERSION VERSION_LESS 3.15.0) |
||||||
|
set(Python3_FIND_STRATEGY LOCATION) |
||||||
|
find_package(Python3 COMPONENTS Interpreter) |
||||||
|
if(Python3_Interpreter_FOUND) |
||||||
|
set(MBEDTLS_PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) |
||||||
|
endif() |
||||||
|
else() |
||||||
|
find_package(PythonInterp 3) |
||||||
|
if(PYTHONINTERP_FOUND) |
||||||
|
set(MBEDTLS_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}) |
||||||
|
endif() |
||||||
|
endif() |
||||||
|
if(MBEDTLS_PYTHON_EXECUTABLE) |
||||||
|
|
||||||
|
# If 128-bit keys are configured for CTR_DRBG, display an appropriate warning |
||||||
|
execute_process(COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/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() |
||||||
|
|
||||||
|
endif() |
||||||
|
|
||||||
|
# If this is the root project add longer list of available CMAKE_BUILD_TYPE values |
||||||
|
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) |
||||||
|
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) |
||||||
|
endif() |
||||||
|
|
||||||
|
# Create a symbolic link from ${base_name} in the binary directory |
||||||
|
# to the corresponding path in the source directory. |
||||||
|
# Note: Copies the file(s) on Windows. |
||||||
|
function(link_to_source base_name) |
||||||
|
set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}") |
||||||
|
set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}") |
||||||
|
|
||||||
|
# Linking to non-existent file is not desirable. At best you will have a |
||||||
|
# dangling link, but when building in tree, this can create a symbolic link |
||||||
|
# to itself. |
||||||
|
if (EXISTS ${target} AND NOT EXISTS ${link}) |
||||||
|
if (CMAKE_HOST_UNIX) |
||||||
|
execute_process(COMMAND ln -s ${target} ${link} |
||||||
|
RESULT_VARIABLE result |
||||||
|
ERROR_VARIABLE output) |
||||||
|
|
||||||
|
if (NOT ${result} EQUAL 0) |
||||||
|
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}") |
||||||
|
endif() |
||||||
|
else() |
||||||
|
if (IS_DIRECTORY ${target}) |
||||||
|
file(GLOB_RECURSE files FOLLOW_SYMLINKS LIST_DIRECTORIES false RELATIVE ${target} "${target}/*") |
||||||
|
foreach(file IN LISTS files) |
||||||
|
configure_file("${target}/${file}" "${link}/${file}" COPYONLY) |
||||||
|
endforeach(file) |
||||||
|
else() |
||||||
|
configure_file(${target} ${link} COPYONLY) |
||||||
|
endif() |
||||||
|
endif() |
||||||
|
endif() |
||||||
|
endfunction(link_to_source) |
||||||
|
|
||||||
|
# Get the filename without the final extension (i.e. convert "a.b.c" to "a.b") |
||||||
|
function(get_name_without_last_ext dest_var full_name) |
||||||
|
# Split into a list on '.' (but a cmake list is just a ';'-separated string) |
||||||
|
string(REPLACE "." ";" ext_parts "${full_name}") |
||||||
|
# Remove the last item if there are more than one |
||||||
|
list(LENGTH ext_parts ext_parts_len) |
||||||
|
if (${ext_parts_len} GREATER "1") |
||||||
|
math(EXPR ext_parts_last_item "${ext_parts_len} - 1") |
||||||
|
list(REMOVE_AT ext_parts ${ext_parts_last_item}) |
||||||
|
endif() |
||||||
|
# Convert back to a string by replacing separators with '.' |
||||||
|
string(REPLACE ";" "." no_ext_name "${ext_parts}") |
||||||
|
# Copy into the desired variable |
||||||
|
set(${dest_var} ${no_ext_name} PARENT_SCOPE) |
||||||
|
endfunction(get_name_without_last_ext) |
||||||
|
|
||||||
|
string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}") |
||||||
|
|
||||||
|
include(CheckCCompilerFlag) |
||||||
|
|
||||||
|
set(CMAKE_C_EXTENSIONS OFF) |
||||||
|
set(CMAKE_C_STANDARD 99) |
||||||
|
|
||||||
|
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 -Wwrite-strings") |
||||||
|
if (GCC_VERSION VERSION_GREATER 3.0 OR GCC_VERSION VERSION_EQUAL 3.0) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat=2 -Wno-format-nonliteral") |
||||||
|
endif() |
||||||
|
if (GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wvla") |
||||||
|
endif() |
||||||
|
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() |
||||||
|
if (GCC_VERSION VERSION_GREATER 5.0) |
||||||
|
CHECK_C_COMPILER_FLAG("-Wformat-signedness" C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS) |
||||||
|
if(C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-signedness") |
||||||
|
endif() |
||||||
|
endif() |
||||||
|
if (GCC_VERSION VERSION_GREATER 7.0 OR GCC_VERSION VERSION_EQUAL 7.0) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-overflow=2 -Wformat-truncation") |
||||||
|
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 "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3") |
||||||
|
set(CMAKE_C_FLAGS_ASANDBG "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls") |
||||||
|
set(CMAKE_C_FLAGS_CHECK "-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 -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral") |
||||||
|
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 "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3") |
||||||
|
set(CMAKE_C_FLAGS_ASANDBG "-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 "-fsanitize=memory -O3") |
||||||
|
set(CMAKE_C_FLAGS_MEMSANDBG "-fsanitize=memory -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2") |
||||||
|
set(CMAKE_C_FLAGS_CHECK "-Os") |
||||||
|
endif(CMAKE_COMPILER_IS_CLANG) |
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_IAR) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts -Ohz") |
||||||
|
endif(CMAKE_COMPILER_IS_IAR) |
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_MSVC) |
||||||
|
# Strictest warnings, UTF-8 source and execution charset |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3 /utf-8") |
||||||
|
endif(CMAKE_COMPILER_IS_MSVC) |
||||||
|
|
||||||
|
if(MBEDTLS_FATAL_WARNINGS) |
||||||
|
if(CMAKE_COMPILER_IS_MSVC) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") |
||||||
|
endif(CMAKE_COMPILER_IS_MSVC) |
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_GNU) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") |
||||||
|
if(UNSAFE_BUILD) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=cpp") |
||||||
|
set(CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} -Wno-error=cpp") |
||||||
|
set(CMAKE_C_FLAGS_ASANDBG "${CMAKE_C_FLAGS_ASANDBG} -Wno-error=cpp") |
||||||
|
endif(UNSAFE_BUILD) |
||||||
|
endif(CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_GNU) |
||||||
|
|
||||||
|
if (CMAKE_COMPILER_IS_IAR) |
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warning_are_errors") |
||||||
|
endif(CMAKE_COMPILER_IS_IAR) |
||||||
|
endif(MBEDTLS_FATAL_WARNINGS) |
||||||
|
|
||||||
|
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) |
||||||
|
set(CMAKE_INSTALL_LIBDIR "${LIB_INSTALL_DIR}") |
||||||
|
endif() |
||||||
|
|
||||||
|
add_subdirectory(include) |
||||||
|
|
||||||
|
add_subdirectory(3rdparty) |
||||||
|
|
||||||
|
add_subdirectory(library) |
||||||
|
|
||||||
|
# |
||||||
|
# The C files in tests/src directory contain test code shared among test suites |
||||||
|
# and programs. This shared test code is compiled and linked to test suites and |
||||||
|
# programs objects as a set of compiled objects. The compiled objects are NOT |
||||||
|
# built into a library that the test suite and program objects would link |
||||||
|
# against as they link against the mbedcrypto, mbedx509 and mbedtls libraries. |
||||||
|
# The reason is that such library is expected to have mutual dependencies with |
||||||
|
# the aforementioned libraries and that there is as of today no portable way of |
||||||
|
# handling such dependencies (only toolchain specific solutions). |
||||||
|
# |
||||||
|
# Thus the below definition of the `mbedtls_test` CMake library of objects |
||||||
|
# target. This library of objects is used by tests and programs CMake files |
||||||
|
# to define the test executables. |
||||||
|
# |
||||||
|
if(ENABLE_TESTING OR ENABLE_PROGRAMS) |
||||||
|
file(GLOB MBEDTLS_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/drivers/*.c) |
||||||
|
add_library(mbedtls_test OBJECT ${MBEDTLS_TEST_FILES}) |
||||||
|
target_include_directories(mbedtls_test |
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include |
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include |
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library) |
||||||
|
endif() |
||||||
|
|
||||||
|
if(ENABLE_PROGRAMS) |
||||||
|
add_subdirectory(programs) |
||||||
|
endif() |
||||||
|
|
||||||
|
ADD_CUSTOM_TARGET(${MBEDTLS_TARGET_PREFIX}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() |
||||||
|
|
||||||
|
if(NOT DISABLE_PACKAGE_CONFIG_AND_INSTALL) |
||||||
|
configure_package_config_file( |
||||||
|
"cmake/MbedTLSConfig.cmake.in" |
||||||
|
"cmake/MbedTLSConfig.cmake" |
||||||
|
INSTALL_DESTINATION "cmake") |
||||||
|
|
||||||
|
write_basic_package_version_file( |
||||||
|
"cmake/MbedTLSConfigVersion.cmake" |
||||||
|
COMPATIBILITY SameMajorVersion |
||||||
|
VERSION 3.3.0) |
||||||
|
|
||||||
|
install( |
||||||
|
FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfig.cmake" |
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfigVersion.cmake" |
||||||
|
DESTINATION "cmake") |
||||||
|
|
||||||
|
export( |
||||||
|
EXPORT MbedTLSTargets |
||||||
|
NAMESPACE MbedTLS:: |
||||||
|
FILE "cmake/MbedTLSTargets.cmake") |
||||||
|
|
||||||
|
install( |
||||||
|
EXPORT MbedTLSTargets |
||||||
|
NAMESPACE MbedTLS:: |
||||||
|
DESTINATION "cmake" |
||||||
|
FILE "MbedTLSTargets.cmake") |
||||||
|
|
||||||
|
if(CMAKE_VERSION VERSION_GREATER 3.15 OR CMAKE_VERSION VERSION_EQUAL 3.15) |
||||||
|
# Do not export the package by default |
||||||
|
cmake_policy(SET CMP0090 NEW) |
||||||
|
|
||||||
|
# Make this package visible to the system |
||||||
|
export(PACKAGE MbedTLS) |
||||||
|
endif() |
||||||
|
endif() |
@ -0,0 +1,95 @@ |
|||||||
|
Contributing |
||||||
|
============ |
||||||
|
We gratefully accept bug reports and contributions from the community. All PRs are reviewed by the project team / community, and may need some modifications to |
||||||
|
be accepted. |
||||||
|
|
||||||
|
Quick Checklist for PR contributors |
||||||
|
----------------------------------- |
||||||
|
More details on all of these points may be found in the sections below. |
||||||
|
|
||||||
|
- [Sign-off](#license-and-copyright): all commits must be signed off. |
||||||
|
- [Tests](#tests): please ensure the PR includes adequate tests. |
||||||
|
- [Changelog](#documentation): if needed, please provide a changelog entry. |
||||||
|
- [Backports](#long-term-support-branches): provide a backport if needed (it's fine to wait until the main PR is accepted). |
||||||
|
|
||||||
|
Coding Standards |
||||||
|
---------------- |
||||||
|
- We would ask that contributions conform to [our coding standards](https://mbed-tls.readthedocs.io/en/latest/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/Mbed-TLS/mbedtls/issues) or [start a discussion](https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org) around a feature idea or a bug. |
||||||
|
1. Fork the [Mbed TLS repository on GitHub](https://github.com/Mbed-TLS/mbedtls) to start making your changes. As a general rule, you should use the ["development" branch](https://github.com/Mbed-TLS/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. |
||||||
|
|
||||||
|
Backwards 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, as described in [BRANCHES.md](BRANCHES.md). |
||||||
|
|
||||||
|
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. If there is an API change, the contribution, if accepted, will be merged only when there will be a major release. |
||||||
|
|
||||||
|
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/Mbed-TLS/mbedtls/tree/development) by contributors. |
||||||
|
|
||||||
|
The list of maintained branches can be found in the [Current Branches section |
||||||
|
of BRANCHES.md](BRANCHES.md#current-branches). |
||||||
|
|
||||||
|
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_rsa.c`). These files are generated from a `function file` (e.g. `suites/test_suite_rsa.function`) and a `data file` (e.g. `suites/test_suite_rsa.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://mbed-tls.readthedocs.io/en/latest/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/Mbed-TLS/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://mbed-tls.readthedocs.io/en/latest/kb/) article should be added, write this as a comment in the PR description. |
||||||
|
1. A [ChangeLog](https://github.com/Mbed-TLS/mbedtls/blob/development/ChangeLog.d/00README.md) entry should be added for this contribution. |
||||||
|
|
||||||
|
License and Copyright |
||||||
|
--------------------- |
||||||
|
|
||||||
|
All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible. For licensing details, please see the [License section of the README](README.md#License). |
||||||
|
|
||||||
|
The copyright on contributions is retained by the original authors of the code. Where possible for new files, this should be noted in a comment at the top of the file in the form: "Copyright The Mbed TLS Contributors". |
||||||
|
|
||||||
|
When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and be subject to the same Apache 2.0 license. This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line. |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,4 @@ |
|||||||
|
Site: localhost |
||||||
|
BuildName: mbed TLS-test |
||||||
|
CoverageCommand: /usr/bin/gcov |
||||||
|
MemoryCheckCommand: /usr/bin/valgrind |
@ -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. |
@ -0,0 +1,188 @@ |
|||||||
|
DESTDIR=/usr/local
|
||||||
|
PREFIX=mbedtls_
|
||||||
|
PERL ?= perl
|
||||||
|
|
||||||
|
.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 mbedtls_test |
||||||
|
$(MAKE) -C programs
|
||||||
|
|
||||||
|
lib: |
||||||
|
$(MAKE) -C library
|
||||||
|
|
||||||
|
tests: lib mbedtls_test |
||||||
|
$(MAKE) -C tests
|
||||||
|
|
||||||
|
mbedtls_test: |
||||||
|
$(MAKE) -C tests mbedtls_test
|
||||||
|
|
||||||
|
library/%: |
||||||
|
$(MAKE) -C library $*
|
||||||
|
programs/%: |
||||||
|
$(MAKE) -C programs $*
|
||||||
|
tests/%: |
||||||
|
$(MAKE) -C tests $*
|
||||||
|
|
||||||
|
.PHONY: generated_files |
||||||
|
generated_files: library/generated_files |
||||||
|
generated_files: programs/generated_files |
||||||
|
generated_files: tests/generated_files |
||||||
|
generated_files: visualc_files |
||||||
|
|
||||||
|
.PHONY: visualc_files |
||||||
|
VISUALC_FILES = visualc/VS2010/mbedTLS.sln visualc/VS2010/mbedTLS.vcxproj
|
||||||
|
# TODO: $(app).vcxproj for each $(app) in programs/
|
||||||
|
visualc_files: $(VISUALC_FILES) |
||||||
|
|
||||||
|
# Ensure that the .c files that generate_visualc_files.pl enumerates are
|
||||||
|
# present before it runs. It doesn't matter if the files aren't up-to-date,
|
||||||
|
# they just need to be present.
|
||||||
|
$(VISUALC_FILES): | library/generated_files |
||||||
|
$(VISUALC_FILES): scripts/generate_visualc_files.pl |
||||||
|
$(VISUALC_FILES): scripts/data_files/vs2010-app-template.vcxproj |
||||||
|
$(VISUALC_FILES): scripts/data_files/vs2010-main-template.vcxproj |
||||||
|
$(VISUALC_FILES): scripts/data_files/vs2010-sln-template.sln |
||||||
|
# TODO: also the list of .c and .h source files, but not their content
|
||||||
|
$(VISUALC_FILES): |
||||||
|
echo " Gen $@ ..."
|
||||||
|
$(PERL) scripts/generate_visualc_files.pl
|
||||||
|
|
||||||
|
ifndef WINDOWS |
||||||
|
install: no_test |
||||||
|
mkdir -p $(DESTDIR)/include/mbedtls
|
||||||
|
cp -rp include/mbedtls $(DESTDIR)/include
|
||||||
|
mkdir -p $(DESTDIR)/include/psa
|
||||||
|
cp -rp include/psa $(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 -rf $(DESTDIR)/include/psa
|
||||||
|
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_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.py get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY && ([ $$? -eq 0 ]) && \
|
||||||
|
echo '$(CTR_DRBG_128_BIT_KEY_WARNING)'
|
||||||
|
|
||||||
|
endif |
||||||
|
|
||||||
|
clean: clean_more_on_top |
||||||
|
$(MAKE) -C library clean
|
||||||
|
$(MAKE) -C programs clean
|
||||||
|
$(MAKE) -C tests clean
|
||||||
|
|
||||||
|
clean_more_on_top: |
||||||
|
ifndef WINDOWS |
||||||
|
find . \( -name \*.gcno -o -name \*.gcda -o -name \*.info \) -exec rm {} +
|
||||||
|
endif |
||||||
|
|
||||||
|
neat: clean_more_on_top |
||||||
|
$(MAKE) -C library neat
|
||||||
|
$(MAKE) -C programs neat
|
||||||
|
$(MAKE) -C tests neat
|
||||||
|
ifndef WINDOWS |
||||||
|
rm -f visualc/VS2010/*.vcxproj visualc/VS2010/mbedTLS.sln
|
||||||
|
else |
||||||
|
if exist visualc\VS2010\*.vcxproj del /Q /F visualc\VS2010\*.vcxproj
|
||||||
|
if exist visualc\VS2010\mbedTLS.sln del /Q /F visualc\VS2010\mbedTLS.sln
|
||||||
|
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 \
|
||||||
|
3rdparty/*/include/*/*.h 3rdparty/*/include/*/*/*.h 3rdparty/*/include/*/*/*/*.h \
|
||||||
|
3rdparty/*/*.c 3rdparty/*/*/*.c 3rdparty/*/*/*/*.c 3rdparty/*/*/*/*/*.c \
|
||||||
|
include/*/*.h \
|
||||||
|
library/*.[hc] \
|
||||||
|
programs/*/*.[hc] \
|
||||||
|
tests/include/*/*.h tests/include/*/*/*.h \
|
||||||
|
tests/src/*.c tests/src/*/*.c \
|
||||||
|
tests/suites/*.function \
|
||||||
|
) |
||||||
|
# Exuberant-ctags invocation. Other ctags implementations may require different options.
|
||||||
|
CTAGS = ctags --langmap=c:+.h.function --line-directives=no -o
|
||||||
|
tags: $(C_SOURCE_FILES) |
||||||
|
$(CTAGS) $@ $(C_SOURCE_FILES)
|
||||||
|
TAGS: $(C_SOURCE_FILES) |
||||||
|
etags --no-line-directive -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 |
@ -0,0 +1,315 @@ |
|||||||
|
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. |
||||||
|
|
||||||
|
Mbed TLS includes a reference implementation of the [PSA Cryptography API](#psa-cryptography-api). This is currently a preview for evaluation purposes only. |
||||||
|
|
||||||
|
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/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 Python 3 script `scripts/config.py` (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). |
||||||
|
|
||||||
|
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` |
||||||
|
|
||||||
|
Documentation |
||||||
|
------------- |
||||||
|
|
||||||
|
The main Mbed TLS documentation is available via [ReadTheDocs](https://mbed-tls.readthedocs.io/). |
||||||
|
|
||||||
|
Documentation for the PSA Cryptography API is available [on GitHub](https://arm-software.github.io/psa-api/crypto/). |
||||||
|
|
||||||
|
To generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration: |
||||||
|
|
||||||
|
1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed. |
||||||
|
1. Run `make apidoc`. |
||||||
|
1. Browse `apidoc/index.html` or `apidoc/modules.html`. |
||||||
|
|
||||||
|
For other sources of documentation, see the [SUPPORT](SUPPORT.md) document. |
||||||
|
|
||||||
|
Compiling |
||||||
|
--------- |
||||||
|
|
||||||
|
There are currently three active build systems used within Mbed TLS releases: |
||||||
|
|
||||||
|
- GNU Make |
||||||
|
- CMake |
||||||
|
- Microsoft Visual Studio |
||||||
|
|
||||||
|
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`. |
||||||
|
|
||||||
|
### Tool versions |
||||||
|
|
||||||
|
You need the following tools to build the library with the provided makefiles: |
||||||
|
|
||||||
|
* GNU Make 3.82 or a build tool that CMake supports. |
||||||
|
* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, IAR 8 and Visual Studio 2013. More recent versions should work. Slightly older versions may work. |
||||||
|
* Python 3.6 to generate the test code, and to generate sample programs in the development branch. |
||||||
|
* Perl to run the tests, and to generate some source files in the development branch. |
||||||
|
* CMake 3.10.2 or later (if using CMake). |
||||||
|
* Microsoft Visual Studio 2013 or later (if using Visual Studio). |
||||||
|
* Doxygen 1.8.11 or later (if building the documentation; slightly older versions should work). |
||||||
|
|
||||||
|
### Generated source files in the development branch |
||||||
|
|
||||||
|
The source code of Mbed TLS includes some files that are automatically generated by scripts and whose content depends only on the Mbed TLS source, not on the platform or on the library configuration. These files are not included in the development branch of Mbed TLS, but the generated files are included in official releases. This section explains how to generate the missing files in the development branch. |
||||||
|
|
||||||
|
The following tools are required: |
||||||
|
|
||||||
|
* Perl, for some library source files and for Visual Studio build files. |
||||||
|
* Python 3 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run |
||||||
|
``` |
||||||
|
python -m pip install -r scripts/basic.requirements.txt |
||||||
|
``` |
||||||
|
* A C compiler for the host platform, for some test data. |
||||||
|
|
||||||
|
If you are cross-compiling, you must set the `CC` environment variable to a C compiler for the host platform when generating the configuration-independent files. |
||||||
|
|
||||||
|
Any of the following methods are available to generate the configuration-independent files: |
||||||
|
|
||||||
|
* If not cross-compiling, running `make` with any target, or just `make`, will automatically generate required files. |
||||||
|
* On non-Windows systems, when not cross-compiling, CMake will generate the required files automatically. |
||||||
|
* Run `make generated_files` to generate all the configuration-independent files. |
||||||
|
* On Unix/POSIX systems, run `tests/scripts/check-generated-files.sh -u` to generate all the configuration-independent files. |
||||||
|
* On Windows, run `scripts\make_generated_files.bat` to generate all the configuration-independent files. |
||||||
|
|
||||||
|
### 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 -Wextra`), 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://mbed-tls.readthedocs.io/en/latest/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://mbed-tls.readthedocs.io/en/latest/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 |
||||||
|
cmake --build . |
||||||
|
|
||||||
|
In order to run the tests, enter: |
||||||
|
|
||||||
|
ctest |
||||||
|
|
||||||
|
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. |
||||||
|
|
||||||
|
#### Consuming Mbed TLS |
||||||
|
|
||||||
|
Mbed TLS provides a package config file for consumption as a dependency in other |
||||||
|
CMake projects. You can include Mbed TLS's CMake targets yourself with: |
||||||
|
|
||||||
|
find_package(MbedTLS) |
||||||
|
|
||||||
|
If prompted, set `MbedTLS_DIR` to `${YOUR_MBEDTLS_INSTALL_DIR}/cmake`. This |
||||||
|
creates the following targets: |
||||||
|
|
||||||
|
- `MbedTLS::mbedcrypto` (Crypto library) |
||||||
|
- `MbedTLS::mbedtls` (TLS library) |
||||||
|
- `MbedTLS::mbedx509` (X509 library) |
||||||
|
|
||||||
|
You can then use these directly through `target_link_libraries()`: |
||||||
|
|
||||||
|
add_executable(xyz) |
||||||
|
|
||||||
|
target_link_libraries(xyz |
||||||
|
PUBLIC MbedTLS::mbedtls |
||||||
|
MbedTLS::mbedcrypto |
||||||
|
MbedTLS::mbedx509) |
||||||
|
|
||||||
|
This will link the Mbed TLS libraries to your library or application, and add |
||||||
|
its include directories to your target (transitively, in the case of `PUBLIC` or |
||||||
|
`INTERFACE` link libraries). |
||||||
|
|
||||||
|
#### Mbed TLS as a subproject |
||||||
|
|
||||||
|
Mbed TLS supports being built as a CMake subproject. One can |
||||||
|
use `add_subdirectory()` from a parent CMake project to include Mbed TLS as a |
||||||
|
subproject. |
||||||
|
|
||||||
|
### 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. |
||||||
|
|
||||||
|
In the development branch of Mbed TLS, the Visual Studio solution files need to be generated first as described in [“Generated source files in the development branch”](#generated-source-files-in-the-development-branch). |
||||||
|
|
||||||
|
Example programs |
||||||
|
---------------- |
||||||
|
|
||||||
|
We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md). |
||||||
|
Please note that the goal of these sample programs is to demonstrate specific features of the library, and the code may need to be adapted to build a real-world application. |
||||||
|
|
||||||
|
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/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on. |
||||||
|
- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc). |
||||||
|
|
||||||
|
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://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS/) |
||||||
|
- [What external dependencies does Mbed TLS rely on?](https://mbed-tls.readthedocs.io/en/latest/kb/development/what-external-dependencies-does-mbedtls-rely-on/) |
||||||
|
- [How do I configure Mbed TLS](https://mbed-tls.readthedocs.io/en/latest/kb/compiling-and-building/how-do-i-configure-mbedtls/) |
||||||
|
|
||||||
|
Mbed TLS is mostly written in portable C99; however, it has a few platform requirements that go beyond the standard, but are met by most modern architectures: |
||||||
|
|
||||||
|
- Bytes must be 8 bits. |
||||||
|
- All-bits-zero must be a valid representation of a null pointer. |
||||||
|
- Signed integers must be represented using two's complement. |
||||||
|
- `int` and `size_t` must be at least 32 bits wide. |
||||||
|
- The types `uint8_t`, `uint16_t`, `uint32_t` and their signed equivalents must be available. |
||||||
|
|
||||||
|
PSA cryptography API |
||||||
|
-------------------- |
||||||
|
|
||||||
|
### PSA API |
||||||
|
|
||||||
|
Arm's [Platform Security Architecture (PSA)](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level. |
||||||
|
|
||||||
|
The [PSA cryptography API](https://arm-software.github.io/psa-api/crypto/) provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform. |
||||||
|
|
||||||
|
The design goals of the PSA cryptography API include: |
||||||
|
|
||||||
|
* The API distinguishes caller memory from internal memory, which allows the library to be implemented in an isolated space for additional security. Library calls can be implemented as direct function calls if isolation is not desired, and as remote procedure calls if isolation is desired. |
||||||
|
* The structure of internal data is hidden to the application, which allows substituting alternative implementations at build time or run time, for example, in order to take advantage of hardware accelerators. |
||||||
|
* All access to the keys happens through key identifiers, which allows support for external cryptoprocessors that is transparent to applications. |
||||||
|
* The interface to algorithms is generic, favoring algorithm agility. |
||||||
|
* The interface is designed to be easy to use and hard to accidentally misuse. |
||||||
|
|
||||||
|
Arm welcomes feedback on the design of the API. If you think something could be improved, please open an issue on our Github repository. Alternatively, if you prefer to provide your feedback privately, please email us at [`mbed-crypto@arm.com`](mailto:mbed-crypto@arm.com). All feedback received by email is treated confidentially. |
||||||
|
|
||||||
|
### PSA implementation in Mbed TLS |
||||||
|
|
||||||
|
Mbed TLS includes a reference implementation of the PSA Cryptography API. |
||||||
|
However, it does not aim to implement the whole specification; in particular it does not implement all the algorithms. |
||||||
|
|
||||||
|
The X.509 and TLS code can use PSA cryptography for most operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `mbedtls_config.h`. Note that TLS 1.3 uses PSA cryptography for most operations regardless of this option. See `docs/use-psa-crypto.md` for details. |
||||||
|
|
||||||
|
### Upcoming features |
||||||
|
|
||||||
|
Future releases of this library will include: |
||||||
|
|
||||||
|
* A driver programming interface, which makes it possible to use hardware accelerators instead of the default software implementation for chosen algorithms. |
||||||
|
* Support for external keys to be stored and manipulated exclusively in a separate cryptoprocessor. |
||||||
|
* A configuration mechanism to compile only the algorithms you need for your application. |
||||||
|
* A wider set of cryptographic algorithms. |
||||||
|
|
||||||
|
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) license. See the [LICENSE](LICENSE) file for the full text of this license. Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. This enables LTS (Long Term Support) branches of the software to be provided under either the Apache-2.0 OR 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. |
||||||
|
|
||||||
|
Contact |
||||||
|
------- |
||||||
|
|
||||||
|
* To report a security vulnerability in Mbed TLS, please email <mbed-tls-security@lists.trustedfirmware.org>. For more information, see [`SECURITY.md`](SECURITY.md). |
||||||
|
* To report a bug or request a feature in Mbed TLS, please [file an issue on GitHub](https://github.com/Mbed-TLS/mbedtls/issues/new/choose). |
||||||
|
* Please see [`SUPPORT.md`](SUPPORT.md) for other channels for discussion and support about Mbed TLS. |
@ -0,0 +1,20 @@ |
|||||||
|
## Reporting Vulnerabilities |
||||||
|
|
||||||
|
If you think you have found an Mbed TLS security vulnerability, then please |
||||||
|
send an email to the security team at |
||||||
|
<mbed-tls-security@lists.trustedfirmware.org>. |
||||||
|
|
||||||
|
## Security Incident Handling Process |
||||||
|
|
||||||
|
Our security process is detailed in our |
||||||
|
[security |
||||||
|
center](https://developer.trustedfirmware.org/w/mbed-tls/security-center/). |
||||||
|
|
||||||
|
Its primary goal is to ensure fixes are ready to be deployed when the issue |
||||||
|
goes public. |
||||||
|
|
||||||
|
## Maintained branches |
||||||
|
|
||||||
|
Only the maintained branches, as listed in [`BRANCHES.md`](BRANCHES.md), |
||||||
|
get security fixes. |
||||||
|
Users are urged to always use the latest version of a maintained branch. |
@ -0,0 +1,16 @@ |
|||||||
|
## Documentation |
||||||
|
|
||||||
|
Here are some useful sources of information about using Mbed TLS: |
||||||
|
|
||||||
|
- [ReadTheDocs](https://mbed-tls.readthedocs.io/); |
||||||
|
- API documentation, see the [Documentation section of the |
||||||
|
README](README.md#documentation); |
||||||
|
- the `docs` directory in the source tree; |
||||||
|
- the [Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/kb/); |
||||||
|
- the [Mbed TLS mailing-list |
||||||
|
archives](https://lists.trustedfirmware.org/archives/list/mbed-tls@lists.trustedfirmware.org/). |
||||||
|
|
||||||
|
## Asking Questions |
||||||
|
|
||||||
|
If you can't find your answer in the above sources, please use the [Mbed TLS |
||||||
|
mailing list](https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org). |
@ -0,0 +1,3 @@ |
|||||||
|
@PACKAGE_INIT@ |
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/MbedTLSTargets.cmake") |
@ -0,0 +1,24 @@ |
|||||||
|
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 mbedtls_config.h. To use one of |
||||||
|
them, you can pick one of the following methods: |
||||||
|
|
||||||
|
1. Replace the default file include/mbedtls/mbedtls_config.h with the chosen one. |
||||||
|
|
||||||
|
2. Define MBEDTLS_CONFIG_FILE and adjust the include path accordingly. |
||||||
|
For example, using make: |
||||||
|
|
||||||
|
CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE='<foo.h>'" make |
||||||
|
|
||||||
|
Or, using cmake: |
||||||
|
|
||||||
|
find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} + |
||||||
|
CFLAGS="-I$PWD/configs -DMBEDTLS_CONFIG_FILE='<foo.h>'" cmake . |
||||||
|
make |
||||||
|
|
||||||
|
Note that the second method also works if you want to keep your custom |
||||||
|
configuration file outside the mbed TLS tree. |
@ -0,0 +1,108 @@ |
|||||||
|
/**
|
||||||
|
* \file config-ccm-psk-dtls1_2.h |
||||||
|
* |
||||||
|
* \brief Small configuration for DTLS 1.2 with PSK and AES-CCM ciphersuites |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* Minimal configuration for DTLS 1.2 with PSK and AES-CCM ciphersuites |
||||||
|
* |
||||||
|
* Distinguishing features: |
||||||
|
* - Optimized for small code size, low bandwidth (on an unreliable transport), |
||||||
|
* and low RAM usage. |
||||||
|
* - No asymmetric cryptography (no certificates, no Diffie-Hellman key |
||||||
|
* exchange). |
||||||
|
* - Fully modern and secure (provided the pre-shared keys are generated and |
||||||
|
* stored securely). |
||||||
|
* - Very low record overhead with CCM-8. |
||||||
|
* - Includes several optional DTLS features typically used in IoT. |
||||||
|
* |
||||||
|
* See README.txt for usage instructions. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* System support */ |
||||||
|
//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
|
||||||
|
/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */ |
||||||
|
|
||||||
|
/* 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 |
||||||
|
/* The library does not currently support enabling SHA-224 without SHA-256.
|
||||||
|
* A future version of the library will have this option disabled |
||||||
|
* by default. */ |
||||||
|
#define MBEDTLS_SHA224_C |
||||||
|
#define MBEDTLS_SHA256_C |
||||||
|
#define MBEDTLS_SSL_CLI_C |
||||||
|
#define MBEDTLS_SSL_COOKIE_C |
||||||
|
#define MBEDTLS_SSL_SRV_C |
||||||
|
#define MBEDTLS_SSL_TLS_C |
||||||
|
#define MBEDTLS_TIMING_C |
||||||
|
|
||||||
|
/* TLS protocol feature support */ |
||||||
|
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED |
||||||
|
#define MBEDTLS_SSL_PROTO_TLS1_2 |
||||||
|
#define MBEDTLS_SSL_PROTO_DTLS |
||||||
|
#define MBEDTLS_SSL_DTLS_ANTI_REPLAY |
||||||
|
#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE |
||||||
|
#define MBEDTLS_SSL_DTLS_CONNECTION_ID |
||||||
|
#define MBEDTLS_SSL_DTLS_HELLO_VERIFY |
||||||
|
#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH |
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_IN_CONTENT_LEN 256 |
||||||
|
#define MBEDTLS_SSL_OUT_CONTENT_LEN 256 |
||||||
|
|
||||||
|
/* 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 |
||||||
|
|
||||||
|
/* These defines are present so that the config modifying scripts can enable
|
||||||
|
* them during tests/scripts/test-ref-configs.pl */ |
||||||
|
//#define MBEDTLS_USE_PSA_CRYPTO
|
||||||
|
//#define MBEDTLS_PSA_CRYPTO_C
|
||||||
|
|
||||||
|
/* Error messages and TLS debugging traces
|
||||||
|
* (huge code size increase, needed for tests/ssl-opt.sh) */ |
||||||
|
//#define MBEDTLS_DEBUG_C
|
||||||
|
//#define MBEDTLS_ERROR_C
|
@ -0,0 +1,99 @@ |
|||||||
|
/**
|
||||||
|
* \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 |
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites |
||||||
|
* |
||||||
|
* Distinguishing features: |
||||||
|
* - Optimized for small code size, low bandwidth (on a reliable transport), |
||||||
|
* and low RAM usage. |
||||||
|
* - No asymmetric cryptography (no certificates, no Diffie-Hellman key |
||||||
|
* exchange). |
||||||
|
* - Fully modern and secure (provided the pre-shared keys are generated and |
||||||
|
* stored securely). |
||||||
|
* - Very low record overhead with CCM-8. |
||||||
|
* |
||||||
|
* See README.txt for usage instructions. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* System support */ |
||||||
|
//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
|
||||||
|
/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */ |
||||||
|
|
||||||
|
/* 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 |
||||||
|
/* The library does not currently support enabling SHA-224 without SHA-256.
|
||||||
|
* A future version of the library will have this option disabled |
||||||
|
* by default. */ |
||||||
|
#define MBEDTLS_SHA224_C |
||||||
|
#define MBEDTLS_SHA256_C |
||||||
|
#define MBEDTLS_SSL_CLI_C |
||||||
|
#define MBEDTLS_SSL_SRV_C |
||||||
|
#define MBEDTLS_SSL_TLS_C |
||||||
|
|
||||||
|
/* TLS protocol feature support */ |
||||||
|
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED |
||||||
|
#define MBEDTLS_SSL_PROTO_TLS1_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_IN_CONTENT_LEN 1024 |
||||||
|
#define MBEDTLS_SSL_OUT_CONTENT_LEN 1024 |
||||||
|
|
||||||
|
/* 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 |
||||||
|
|
||||||
|
/* These defines are present so that the config modifying scripts can enable
|
||||||
|
* them during tests/scripts/test-ref-configs.pl */ |
||||||
|
//#define MBEDTLS_USE_PSA_CRYPTO
|
||||||
|
//#define MBEDTLS_PSA_CRYPTO_C
|
||||||
|
|
||||||
|
/* Error messages and TLS debugging traces
|
||||||
|
* (huge code size increase, needed for tests/ssl-opt.sh) */ |
||||||
|
//#define MBEDTLS_DEBUG_C
|
||||||
|
//#define MBEDTLS_ERROR_C
|
@ -0,0 +1,85 @@ |
|||||||
|
/**
|
||||||
|
* \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 |
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* Minimal configuration of features that do not require an entropy source |
||||||
|
* Distinguishing features: |
||||||
|
* - no entropy module |
||||||
|
* - no TLS protocol implementation available due to absence of an entropy |
||||||
|
* source |
||||||
|
* |
||||||
|
* See README.txt for usage instructions. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* 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_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 |
||||||
|
|
||||||
|
/* 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 |
||||||
|
/* The library does not currently support enabling SHA-224 without SHA-256.
|
||||||
|
* A future version of the library will have this option disabled |
||||||
|
* by default. */ |
||||||
|
#define MBEDTLS_SHA224_C |
||||||
|
#define MBEDTLS_SHA256_C |
||||||
|
#define MBEDTLS_SHA384_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 |
@ -0,0 +1,122 @@ |
|||||||
|
/**
|
||||||
|
* \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 |
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* 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 |
||||||
|
/* The library does not currently support enabling SHA-224 without SHA-256.
|
||||||
|
* A future version of the library will have this option disabled |
||||||
|
* by default. */ |
||||||
|
#define MBEDTLS_SHA224_C |
||||||
|
#define MBEDTLS_SHA256_C |
||||||
|
#define MBEDTLS_SHA384_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_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_MPI_MAX_SIZE 48 // 384-bit EC curve = 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 comments 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_IN_CONTENT_LEN 1024 |
||||||
|
#define MBEDTLS_SSL_OUT_CONTENT_LEN 1024 |
||||||
|
|
||||||
|
/* These defines are present so that the config modifying scripts can enable
|
||||||
|
* them during tests/scripts/test-ref-configs.pl */ |
||||||
|
//#define MBEDTLS_USE_PSA_CRYPTO
|
||||||
|
//#define MBEDTLS_PSA_CRYPTO_C
|
||||||
|
|
||||||
|
/* Error messages and TLS debugging traces
|
||||||
|
* (huge code size increase, needed for tests/ssl-opt.sh) */ |
||||||
|
//#define MBEDTLS_DEBUG_C
|
||||||
|
//#define MBEDTLS_ERROR_C
|
@ -0,0 +1,89 @@ |
|||||||
|
/**
|
||||||
|
* \file config-symmetric-only.h |
||||||
|
* |
||||||
|
* \brief Configuration without any asymmetric cryptography. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* System support */ |
||||||
|
//#define MBEDTLS_HAVE_ASM
|
||||||
|
#define MBEDTLS_HAVE_TIME |
||||||
|
#define MBEDTLS_HAVE_TIME_DATE |
||||||
|
|
||||||
|
/* Mbed Crypto feature support */ |
||||||
|
#define MBEDTLS_CIPHER_MODE_CBC |
||||||
|
#define MBEDTLS_CIPHER_MODE_CFB |
||||||
|
#define MBEDTLS_CIPHER_MODE_CTR |
||||||
|
#define MBEDTLS_CIPHER_MODE_OFB |
||||||
|
#define MBEDTLS_CIPHER_MODE_XTS |
||||||
|
#define MBEDTLS_CIPHER_PADDING_PKCS7 |
||||||
|
#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS |
||||||
|
#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN |
||||||
|
#define MBEDTLS_CIPHER_PADDING_ZEROS |
||||||
|
#define MBEDTLS_ERROR_STRERROR_DUMMY |
||||||
|
#define MBEDTLS_FS_IO |
||||||
|
#define MBEDTLS_ENTROPY_NV_SEED |
||||||
|
#define MBEDTLS_SELF_TEST |
||||||
|
#define MBEDTLS_USE_PSA_CRYPTO |
||||||
|
#define MBEDTLS_VERSION_FEATURES |
||||||
|
|
||||||
|
/* Mbed Crypto modules */ |
||||||
|
#define MBEDTLS_AES_C |
||||||
|
#define MBEDTLS_ASN1_PARSE_C |
||||||
|
#define MBEDTLS_ASN1_WRITE_C |
||||||
|
#define MBEDTLS_BASE64_C |
||||||
|
#define MBEDTLS_CAMELLIA_C |
||||||
|
#define MBEDTLS_ARIA_C |
||||||
|
#define MBEDTLS_CCM_C |
||||||
|
#define MBEDTLS_CHACHA20_C |
||||||
|
#define MBEDTLS_CHACHAPOLY_C |
||||||
|
#define MBEDTLS_CIPHER_C |
||||||
|
#define MBEDTLS_CMAC_C |
||||||
|
#define MBEDTLS_CTR_DRBG_C |
||||||
|
#define MBEDTLS_DES_C |
||||||
|
#define MBEDTLS_ENTROPY_C |
||||||
|
#define MBEDTLS_ERROR_C |
||||||
|
#define MBEDTLS_GCM_C |
||||||
|
#define MBEDTLS_HKDF_C |
||||||
|
#define MBEDTLS_HMAC_DRBG_C |
||||||
|
#define MBEDTLS_NIST_KW_C |
||||||
|
#define MBEDTLS_MD_C |
||||||
|
#define MBEDTLS_MD5_C |
||||||
|
#define MBEDTLS_OID_C |
||||||
|
#define MBEDTLS_PEM_PARSE_C |
||||||
|
#define MBEDTLS_PEM_WRITE_C |
||||||
|
#define MBEDTLS_PKCS5_C |
||||||
|
#define MBEDTLS_PKCS12_C |
||||||
|
#define MBEDTLS_PLATFORM_C |
||||||
|
#define MBEDTLS_POLY1305_C |
||||||
|
#define MBEDTLS_PSA_CRYPTO_C |
||||||
|
#define MBEDTLS_PSA_CRYPTO_SE_C |
||||||
|
#define MBEDTLS_PSA_CRYPTO_STORAGE_C |
||||||
|
#define MBEDTLS_PSA_ITS_FILE_C |
||||||
|
#define MBEDTLS_RIPEMD160_C |
||||||
|
#define MBEDTLS_SHA1_C |
||||||
|
/* The library does not currently support enabling SHA-224 without SHA-256.
|
||||||
|
* A future version of the library will have this option disabled |
||||||
|
* by default. */ |
||||||
|
#define MBEDTLS_SHA224_C |
||||||
|
#define MBEDTLS_SHA256_C |
||||||
|
#define MBEDTLS_SHA384_C |
||||||
|
#define MBEDTLS_SHA512_C |
||||||
|
//#define MBEDTLS_THREADING_C
|
||||||
|
#define MBEDTLS_TIMING_C |
||||||
|
#define MBEDTLS_VERSION_C |
@ -0,0 +1,92 @@ |
|||||||
|
/**
|
||||||
|
* \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 |
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* 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 |
||||||
|
|
||||||
|
/* 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 |
||||||
|
/* The library does not currently support enabling SHA-224 without SHA-256.
|
||||||
|
* A future version of the library will have this option disabled |
||||||
|
* by default. */ |
||||||
|
#define MBEDTLS_SHA224_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_MPI_MAX_SIZE 32 // 256-bit EC curve = 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 |
||||||
|
|
||||||
|
/* These defines are present so that the config modifying scripts can enable
|
||||||
|
* them during tests/scripts/test-ref-configs.pl */ |
||||||
|
//#define MBEDTLS_USE_PSA_CRYPTO
|
||||||
|
//#define MBEDTLS_PSA_CRYPTO_C
|
@ -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. |
@ -0,0 +1,2 @@ |
|||||||
|
*.html |
||||||
|
*.pdf |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@ |
|||||||
|
PANDOC = pandoc
|
||||||
|
|
||||||
|
default: all |
||||||
|
|
||||||
|
all_markdown = \
|
||||||
|
mbed-crypto-storage-specification.md \
|
||||||
|
testing/driver-interface-test-strategy.md \
|
||||||
|
testing/invasive-testing.md \
|
||||||
|
testing/test-framework.md \
|
||||||
|
# This line is intentionally left blank
|
||||||
|
|
||||||
|
html: $(all_markdown:.md=.html) |
||||||
|
pdf: $(all_markdown:.md=.pdf) |
||||||
|
all: html pdf |
||||||
|
|
||||||
|
.SUFFIXES: |
||||||
|
.SUFFIXES: .md .html .pdf |
||||||
|
|
||||||
|
.md.html: |
||||||
|
$(PANDOC) -o $@ $<
|
||||||
|
.md.pdf: |
||||||
|
$(PANDOC) -o $@ $<
|
||||||
|
|
||||||
|
clean: |
||||||
|
rm -f *.html *.pdf
|
||||||
|
rm -f testing/*.html testing/*.pdf
|
@ -0,0 +1,91 @@ |
|||||||
|
Alternative implementations of Mbed TLS functionality |
||||||
|
===================================================== |
||||||
|
|
||||||
|
This document describes how parts of the Mbed TLS functionality can be replaced at compile time to integrate the library on a platform. |
||||||
|
|
||||||
|
This document is an overview. It is not exhaustive. Please consult the documentation of individual modules and read the library header files for more details. |
||||||
|
|
||||||
|
## Platform integration |
||||||
|
|
||||||
|
Mbed TLS works out of the box on Unix/Linux/POSIX-like systems and on Windows. On embedded platforms, you may need to customize some aspects of how Mbed TLS interacts with the underlying platform. This section discusses the main areas that can be configured. |
||||||
|
|
||||||
|
The platform module (`include/mbedtls/platform.h`) controls how Mbed TLS accesses standard library features such as memory management (`calloc`, `free`), `printf`, `exit`. You can define custom functions instead of the ones from the C standard library through `MBEDTLS_PLATFORM_XXX` options in the configuration file. Many options have two mechanisms: either define `MBEDTLS_PLATFORM_XXX_MACRO` to the name of a function to call instead of the standard function `xxx`, or define `MBEDTLS_PLATFORM_XXX_ALT` and [register an alternative implementation during the platform setup](#alternative-implementations-of-platform-functions). |
||||||
|
|
||||||
|
The storage of the non-volatile seed for random generation, enabled with `MBEDTLS_ENTROPY_NV_SEED`, is also controlled via the platform module. |
||||||
|
|
||||||
|
For timing functions, you can [declare an alternative implementation of the timing module](#module-alternative-implementations). |
||||||
|
|
||||||
|
On multithreaded platforms, [declare an alternative implementation of the threading module](#module-alternative-implementations). |
||||||
|
|
||||||
|
To configure entropy sources (hardware random generators), see the `MBEDTLS_ENTROPY_XXX` options in the configuration file. |
||||||
|
|
||||||
|
For networking, the `net_sockets` module does not currently support alternative implementations. If this module does not work on your platform, disable `MBEDTLS_NET_C` and use custom functions for TLS. |
||||||
|
|
||||||
|
If your platform has a cryptographic accelerator, you can use it via a [PSA driver](#psa-cryptography-drivers) or declare an [alternative implementation of the corresponding module(s)](#module-alternative-implementations) or [of specific functions](#function-alternative-implementations). PSA drivers will ultimately replace the alternative implementation mechanism, but alternative implementation will remain supported in at least all Mbed TLS versions of the form 3.x. The interface of PSA drivers is currently still experimental and subject to change. |
||||||
|
|
||||||
|
## PSA cryptography drivers |
||||||
|
|
||||||
|
On platforms where a hardware cryptographic engine is present, you can implement a driver for this engine in the PSA interface. Drivers are supported for cryptographic operations with transparent keys (keys available in cleartext), for cryptographic operations with opaque keys (keys that are only available inside the cryptographic engine), and for random generation. Calls to `psa_xxx` functions that perform cryptographic operations are directed to drivers instead of the built-in code as applicable. See the [PSA cryptography driver interface specification](docs/proposed/psa-driver-interface.md), the [Mbed TLS PSA driver developer guide](docs/proposed/psa-driver-developer-guide.md) and the [Mbed TLS PSA driver integration guide](docs/proposed/psa-driver-integration-guide.md) for more information. |
||||||
|
|
||||||
|
As of Mbed TLS 3.0, this interface is still experimental and subject to change, and not all operations support drivers yet. The configuration option `MBEDTLS_USE_PSA_CRYPTO` causes parts of the `mbedtls_xxx` API to use PSA crypto and therefore to support drivers, however it is not yet compatible with all drivers. |
||||||
|
|
||||||
|
## Module alternative implementations |
||||||
|
|
||||||
|
You can replace the code of some modules of Mbed TLS at compile time by a custom implementation. This is possible for low-level cryptography modules (symmetric algorithms, DHM, RSA, ECP, ECJPAKE) and for some platform-related modules (threading, timing). Such custom implementations are called “alternative implementations”, or “ALT implementations” for short. |
||||||
|
|
||||||
|
The general principle of an alternative implementation is: |
||||||
|
* Enable `MBEDTLS_XXX_ALT` in the compile-time configuration where XXX is the module name. For example, `MBEDTLS_AES_ALT` for an implementation of the AES module. This is in addition to enabling `MBEDTLS_XXX_C`. |
||||||
|
* Create a header file `xxx_alt.h` that defines the context type(s) used by the module. For example, `mbedtls_aes_context` for AES. |
||||||
|
* Implement all the functions from the module, i.e. the functions declared in `include/mbedtls/xxx.h`. |
||||||
|
|
||||||
|
See https://mbed-tls.readthedocs.io/en/latest/kb/development/hw_acc_guidelines for a more detailed guide. |
||||||
|
|
||||||
|
### Constraints on context types |
||||||
|
|
||||||
|
Generally, alternative implementations can define their context types to any C type except incomplete and array types (although they would normally be `struct` types). This section lists some known limitations where the context type needs to be a structure with certain fields. |
||||||
|
|
||||||
|
Where a context type needs to have a certain field, the field must have the same type and semantics as in the built-in implementation, but does not need to be at the same position in the structure. Furthermore, unless otherwise indicated, only read access is necessary: the field can be `const`, and modifications to it do not need to be supported. For example, if an alternative implementation of asymmetric cryptography uses a different representation of large integers, it is sufficient to provide a read-only copy of the fields listed here of type `mbedtls_mpi`. |
||||||
|
|
||||||
|
* AES: if `MBEDTLS_AESNI_C` or `MBEDTLS_PADLOCK_C` is enabled, `mbedtls_aes_context` must have the fields `nr` and `rk`. |
||||||
|
* DHM: if `MBEDTLS_DEBUG_C` is enabled, `mbedtls_dhm_context` must have the fields `P`, `Q`, `G`, `GX`, `GY` and `K`. |
||||||
|
* ECP: `mbedtls_ecp_group` must have the fields `id`, `P`, `A`, `B`, `G`, `N`, `pbits` and `nbits`. |
||||||
|
* If `MBEDTLS_PK_PARSE_EC_EXTENDED` is enabled, those fields must be writable, and `mbedtls_ecp_point_read_binary()` must support a group structure where only `P`, `pbits`, `A` and `B` are set. |
||||||
|
|
||||||
|
It must be possible to move a context object in memory (except during the execution of a library function that takes this context as an argument). (This is necessary, for example, to support applications that populate a context on the stack of an inner function and then copy the context upwards through the call chain, or applications written in a language with automatic memory management that can move objects on the heap.) That is, call sequences like the following must work: |
||||||
|
``` |
||||||
|
mbedtls_xxx_context ctx1, ctx2; |
||||||
|
mbedtls_xxx_init(&ctx1); |
||||||
|
mbedtls_xxx_setup(&ctx1, …); |
||||||
|
ctx2 = ctx1; |
||||||
|
memset(&ctx1, 0, sizeof(ctx1)); |
||||||
|
mbedtls_xxx_do_stuff(&ctx2, …); |
||||||
|
mbedtls_xxx_free(&ctx2); |
||||||
|
``` |
||||||
|
In practice, this means that a pointer to a context or to a part of a context does not remain valid across function calls. Alternative implementations do not need to support copying of contexts: contexts can only be cloned through explicit `clone()` functions. |
||||||
|
|
||||||
|
## Function alternative implementations |
||||||
|
|
||||||
|
In some cases, it is possible to replace a single function or a small set of functions instead of [providing an alternative implementation of the whole module](#module-alternative-implementations). |
||||||
|
|
||||||
|
### Alternative implementations of cryptographic functions |
||||||
|
|
||||||
|
Options to replace individual functions of cryptographic modules generally have a name obtained by upper-casing the function name and appending `_ALT`. If the function name contains `_internal`, `_ext` or `_ret`, this is removed in the `_ALT` symbol. When the corresponding option is enabled, the built-in implementation of the function will not be compiled, and you must provide an alternative implementation at link time. |
||||||
|
|
||||||
|
For example, enable `MBEDTLS_AES_ENCRYPT_ALT` at compile time and provide your own implementation of `mbedtls_aes_encrypt()` to provide an accelerated implementation of AES encryption that is compatible with the built-in key schedule. If you wish to implement key schedule differently, you can also enable `MBEDTLS_AES_SETKEY_ENC_ALT` and implement `mbedtls_aes_setkey_enc()`. |
||||||
|
|
||||||
|
Another example: enable `MBEDTLS_SHA256_PROCESS_ALT` and implement `mbedtls_internal_sha256_process()` to provide an accelerated implementation of SHA-256 and SHA-224. |
||||||
|
|
||||||
|
Note that since alternative implementations of individual functions cooperate with the built-in implementation of other functions, you must use the same layout for context objects as the built-in implementation. If you want to use different context types, you need to [provide an alternative implementation of the whole module](#module-alternative-implementations). |
||||||
|
|
||||||
|
### Alternative implementations of platform functions |
||||||
|
|
||||||
|
Several platform functions can be reconfigured dynamically by following the process described here. To reconfigure how Mbed TLS calls the standard library function `xxx()`: |
||||||
|
|
||||||
|
* Define the symbol `MBEDTLS_PLATFORM_XXX_ALT` at compile time. |
||||||
|
* During the initialization of your application, set the global variable `mbedtls_xxx` to an alternative implementation of `xxx()`. |
||||||
|
|
||||||
|
For example, to provide a custom `printf` function at run time, enable `MBEDTLS_PLATFORM_PRINTF_ALT` at compile time and assign to `mbedtls_printf` during the initialization of your application. |
||||||
|
|
||||||
|
Merely enabling `MBEDTLS_PLATFORM_XXX_ALT` does not change the behavior: by default, `mbedtls_xxx` points to the standard function `xxx`. |
||||||
|
|
||||||
|
Note that there are variations on the naming pattern. For example, some configurable functions are activated in pairs, such as `mbedtls_calloc` and `mbedtls_free` via `MBEDTLS_PLATFORM_MEMORY`. Consult the documentation of individual configuration options and of the platform module for details. |
@ -0,0 +1,465 @@ |
|||||||
|
Mbed Crypto storage specification |
||||||
|
================================= |
||||||
|
|
||||||
|
This document specifies how Mbed Crypto uses storage. |
||||||
|
|
||||||
|
Mbed Crypto may be upgraded on an existing device with the storage preserved. Therefore: |
||||||
|
|
||||||
|
1. Any change may break existing installations and may require an upgrade path. |
||||||
|
1. This document retains historical information about all past released versions. Do not remove information from this document unless it has always been incorrect or it is about a version that you are sure was never released. |
||||||
|
|
||||||
|
Mbed Crypto 0.1.0 |
||||||
|
----------------- |
||||||
|
|
||||||
|
Tags: mbedcrypto-0.1.0b, mbedcrypto-0.1.0b2 |
||||||
|
|
||||||
|
Released in November 2018. <br> |
||||||
|
Integrated in Mbed OS 5.11. |
||||||
|
|
||||||
|
Supported backends: |
||||||
|
|
||||||
|
* [PSA ITS](#file-namespace-on-its-for-0.1.0) |
||||||
|
* [C stdio](#file-namespace-on-stdio-for-0.1.0) |
||||||
|
|
||||||
|
Supported features: |
||||||
|
|
||||||
|
* [Persistent transparent keys](#key-file-format-for-0.1.0) designated by a [slot number](#key-names-for-0.1.0). |
||||||
|
* [Nonvolatile random seed](#nonvolatile-random-seed-file-format-for-0.1.0) on ITS only. |
||||||
|
|
||||||
|
This is a beta release, and we do not promise backward compatibility, with one exception: |
||||||
|
|
||||||
|
> On Mbed OS, if a device has a nonvolatile random seed file produced with Mbed OS 5.11.x and is upgraded to a later version of Mbed OS, the nonvolatile random seed file is preserved or upgraded. |
||||||
|
|
||||||
|
We do not make any promises regarding key storage, or regarding the nonvolatile random seed file on other platforms. |
||||||
|
|
||||||
|
### Key names for 0.1.0 |
||||||
|
|
||||||
|
Information about each key is stored in a dedicated file whose name is constructed from the key identifier. The way in which the file name is constructed depends on the storage backend. The content of the file is described [below](#key-file-format-for-0.1.0). |
||||||
|
|
||||||
|
The valid values for a key identifier are the range from 1 to 0xfffeffff. This limitation on the range is not documented in user-facing documentation: according to the user-facing documentation, arbitrary 32-bit values are valid. |
||||||
|
|
||||||
|
The code uses the following constant in an internal header (note that despite the name, this value is actually one plus the maximum permitted value): |
||||||
|
|
||||||
|
#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER 0xffff0000 |
||||||
|
|
||||||
|
There is a shared namespace for all callers. |
||||||
|
|
||||||
|
### Key file format for 0.1.0 |
||||||
|
|
||||||
|
All integers are encoded in little-endian order in 8-bit bytes. |
||||||
|
|
||||||
|
The layout of a key file is: |
||||||
|
|
||||||
|
* magic (8 bytes): `"PSA\0KEY\0"` |
||||||
|
* version (4 bytes): 0 |
||||||
|
* type (4 bytes): `psa_key_type_t` value |
||||||
|
* policy usage flags (4 bytes): `psa_key_usage_t` value |
||||||
|
* policy usage algorithm (4 bytes): `psa_algorithm_t` value |
||||||
|
* key material length (4 bytes) |
||||||
|
* key material: output of `psa_export_key` |
||||||
|
* Any trailing data is rejected on load. |
||||||
|
|
||||||
|
### Nonvolatile random seed file format for 0.1.0 |
||||||
|
|
||||||
|
The nonvolatile random seed file contains a seed for the random generator. If present, it is rewritten at each boot as part of the random generator initialization. |
||||||
|
|
||||||
|
The file format is just the seed as a byte string with no metadata or encoding of any kind. |
||||||
|
|
||||||
|
### File namespace on ITS for 0.1.0 |
||||||
|
|
||||||
|
Assumption: ITS provides a 32-bit file identifier namespace. The Crypto service can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. |
||||||
|
|
||||||
|
* File 0: unused. |
||||||
|
* Files 1 through 0xfffeffff: [content](#key-file-format-for-0.1.0) of the [key whose identifier is the file identifier](#key-names-for-0.1.0). |
||||||
|
* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-0.1.0). |
||||||
|
* Files 0xffff0000 through 0xffffff51, 0xffffff53 through 0xffffffff: unused. |
||||||
|
|
||||||
|
### File namespace on stdio for 0.1.0 |
||||||
|
|
||||||
|
Assumption: C stdio, allowing names containing lowercase letters, digits and underscores, of length up to 23. |
||||||
|
|
||||||
|
An undocumented build-time configuration value `CRYPTO_STORAGE_FILE_LOCATION` allows storing the key files in a directory other than the current directory. This value is simply prepended to the file name (so it must end with a directory separator to put the keys in a different directory). |
||||||
|
|
||||||
|
* `CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0"`: used as a temporary file. Must be writable. May be overwritten or deleted if present. |
||||||
|
* `sprintf(CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu", key_id)` [content](#key-file-format-for-0.1.0) of the [key whose identifier](#key-names-for-0.1.0) is `key_id`. |
||||||
|
* Other files: unused. |
||||||
|
|
||||||
|
Mbed Crypto 1.0.0 |
||||||
|
----------------- |
||||||
|
|
||||||
|
Tags: mbedcrypto-1.0.0d4, mbedcrypto-1.0.0 |
||||||
|
|
||||||
|
Released in February 2019. <br> |
||||||
|
Integrated in Mbed OS 5.12. |
||||||
|
|
||||||
|
Supported integrations: |
||||||
|
|
||||||
|
* [PSA platform](#file-namespace-on-a-psa-platform-for-1.0.0) |
||||||
|
* [library using PSA ITS](#file-namespace-on-its-as-a-library-for-1.0.0) |
||||||
|
* [library using C stdio](#file-namespace-on-stdio-for-1.0.0) |
||||||
|
|
||||||
|
Supported features: |
||||||
|
|
||||||
|
* [Persistent transparent keys](#key-file-format-for-1.0.0) designated by a [key identifier and owner](#key-names-for-1.0.0). |
||||||
|
* [Nonvolatile random seed](#nonvolatile-random-seed-file-format-for-1.0.0) on ITS only. |
||||||
|
|
||||||
|
Backward compatibility commitments: TBD |
||||||
|
|
||||||
|
### Key names for 1.0.0 |
||||||
|
|
||||||
|
Information about each key is stored in a dedicated file designated by the key identifier. In integrations where there is no concept of key owner (in particular, in library integrations), the key identifier is exactly the key identifier as defined in the PSA Cryptography API specification (`psa_key_id_t`). In integrations where there is a concept of key owner (integration into a service for example), the key identifier is made of an owner identifier (its semantics and type are integration specific) and of the key identifier (`psa_key_id_t`) from the key owner point of view. |
||||||
|
|
||||||
|
The way in which the file name is constructed from the key identifier depends on the storage backend. The content of the file is described [below](#key-file-format-for-1.0.0). |
||||||
|
|
||||||
|
* Library integration: the key file name is just the key identifier as defined in the PSA crypto specification. This is a 32-bit value. |
||||||
|
* PSA service integration: the key file name is `(uint64_t)owner_uid << 32 | key_id` where `key_id` is the key identifier from the owner point of view and `owner_uid` (of type `int32_t`) is the calling partition identifier provided to the server by the partition manager. This is a 64-bit value. |
||||||
|
|
||||||
|
### Key file format for 1.0.0 |
||||||
|
|
||||||
|
The layout is identical to [0.1.0](#key-file-format-for-0.1.0) so far. However note that the encoding of key types, algorithms and key material has changed, therefore the storage format is not compatible (despite using the same value in the version field so far). |
||||||
|
|
||||||
|
### Nonvolatile random seed file format for 1.0.0 |
||||||
|
|
||||||
|
The nonvolatile random seed file contains a seed for the random generator. If present, it is rewritten at each boot as part of the random generator initialization. |
||||||
|
|
||||||
|
The file format is just the seed as a byte string with no metadata or encoding of any kind. |
||||||
|
|
||||||
|
This is unchanged since [the feature was introduced in Mbed Crypto 0.1.0](#nonvolatile-random-seed-file-format-for-0.1.0). |
||||||
|
|
||||||
|
### File namespace on a PSA platform for 1.0.0 |
||||||
|
|
||||||
|
Assumption: ITS provides a 64-bit file identifier namespace. The Crypto service can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. |
||||||
|
|
||||||
|
Assumption: the owner identifier is a nonzero value of type `int32_t`. |
||||||
|
|
||||||
|
* Files 0 through 0xffffff51, 0xffffff53 through 0xffffffff: unused, reserved for internal use of the crypto library or crypto service. |
||||||
|
* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-0.1.0). |
||||||
|
* Files 0x100000000 through 0xffffffffffff: [content](#key-file-format-for-1.0.0) of the [key whose identifier is the file identifier](#key-names-for-1.0.0). The upper 32 bits determine the owner. |
||||||
|
|
||||||
|
### File namespace on ITS as a library for 1.0.0 |
||||||
|
|
||||||
|
Assumption: ITS provides a 64-bit file identifier namespace. The entity using the crypto library can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. |
||||||
|
|
||||||
|
This is a library integration, so there is no owner. The key file identifier is identical to the key identifier. |
||||||
|
|
||||||
|
* File 0: unused. |
||||||
|
* Files 1 through 0xfffeffff: [content](#key-file-format-for-1.0.0) of the [key whose identifier is the file identifier](#key-names-for-1.0.0). |
||||||
|
* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-1.0.0). |
||||||
|
* Files 0xffff0000 through 0xffffff51, 0xffffff53 through 0xffffffff, 0x100000000 through 0xffffffffffffffff: unused. |
||||||
|
|
||||||
|
### File namespace on stdio for 1.0.0 |
||||||
|
|
||||||
|
This is a library integration, so there is no owner. The key file identifier is identical to the key identifier. |
||||||
|
|
||||||
|
[Identical to 0.1.0](#file-namespace-on-stdio-for-0.1.0). |
||||||
|
|
||||||
|
### Upgrade from 0.1.0 to 1.0.0. |
||||||
|
|
||||||
|
* Delete files 1 through 0xfffeffff, which contain keys in a format that is no longer supported. |
||||||
|
|
||||||
|
### Suggested changes to make before 1.0.0 |
||||||
|
|
||||||
|
The library integration and the PSA platform integration use different sets of file names. This is annoyingly non-uniform. For example, if we want to store non-key files, we have room in different ranges (0 through 0xffffffff on a PSA platform, 0xffff0000 through 0xffffffffffffffff in a library integration). |
||||||
|
|
||||||
|
It would simplify things to always have a 32-bit owner, with a nonzero value, and thus reserve the range 0–0xffffffff for internal library use. |
||||||
|
|
||||||
|
Mbed Crypto 1.1.0 |
||||||
|
----------------- |
||||||
|
|
||||||
|
Tags: mbedcrypto-1.1.0 |
||||||
|
|
||||||
|
Released in early June 2019. <br> |
||||||
|
Integrated in Mbed OS 5.13. |
||||||
|
|
||||||
|
Changes since [1.0.0](#mbed-crypto-1.0.0): |
||||||
|
|
||||||
|
* The stdio backend for storage has been replaced by an implementation of [PSA ITS over stdio](#file-namespace-on-stdio-for-1.1.0). |
||||||
|
* [Some changes in the key file format](#key-file-format-for-1.1.0). |
||||||
|
|
||||||
|
### File namespace on stdio for 1.1.0 |
||||||
|
|
||||||
|
Assumption: C stdio, allowing names containing lowercase letters, digits and underscores, of length up to 23. |
||||||
|
|
||||||
|
An undocumented build-time configuration value `PSA_ITS_STORAGE_PREFIX` allows storing the key files in a directory other than the current directory. This value is simply prepended to the file name (so it must end with a directory separator to put the keys in a different directory). |
||||||
|
|
||||||
|
* `PSA_ITS_STORAGE_PREFIX "tempfile.psa_its"`: used as a temporary file. Must be writable. May be overwritten or deleted if present. |
||||||
|
* `sprintf(PSA_ITS_STORAGE_PREFIX "%016llx.psa_its", key_id)`: a key or non-key file. The `key_id` in the name is the 64-bit file identifier, which is the [key identifier](#key-names-for-mbed-tls-2.25.0) for a key file or some reserved identifier for a non-key file (currently: only the [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-1.0.0)). The contents of the file are: |
||||||
|
* Magic header (8 bytes): `"PSA\0ITS\0"` |
||||||
|
* File contents. |
||||||
|
|
||||||
|
### Key file format for 1.1.0 |
||||||
|
|
||||||
|
The key file format is identical to [1.0.0](#key-file-format-for-1.0.0), except for the following changes: |
||||||
|
|
||||||
|
* A new policy field, marked as [NEW:1.1.0] below. |
||||||
|
* The encoding of key types, algorithms and key material has changed, therefore the storage format is not compatible (despite using the same value in the version field so far). |
||||||
|
|
||||||
|
A self-contained description of the file layout follows. |
||||||
|
|
||||||
|
All integers are encoded in little-endian order in 8-bit bytes. |
||||||
|
|
||||||
|
The layout of a key file is: |
||||||
|
|
||||||
|
* magic (8 bytes): `"PSA\0KEY\0"` |
||||||
|
* version (4 bytes): 0 |
||||||
|
* type (4 bytes): `psa_key_type_t` value |
||||||
|
* policy usage flags (4 bytes): `psa_key_usage_t` value |
||||||
|
* policy usage algorithm (4 bytes): `psa_algorithm_t` value |
||||||
|
* policy enrollment algorithm (4 bytes): `psa_algorithm_t` value [NEW:1.1.0] |
||||||
|
* key material length (4 bytes) |
||||||
|
* key material: output of `psa_export_key` |
||||||
|
* Any trailing data is rejected on load. |
||||||
|
|
||||||
|
Mbed Crypto TBD |
||||||
|
--------------- |
||||||
|
|
||||||
|
Tags: TBD |
||||||
|
|
||||||
|
Released in TBD 2019. <br> |
||||||
|
Integrated in Mbed OS TBD. |
||||||
|
|
||||||
|
### Changes introduced in TBD |
||||||
|
|
||||||
|
* The layout of a key file now has a lifetime field before the type field. |
||||||
|
* Key files can store references to keys in a secure element. In such key files, the key material contains the slot number. |
||||||
|
|
||||||
|
### File namespace on a PSA platform on TBD |
||||||
|
|
||||||
|
Assumption: ITS provides a 64-bit file identifier namespace. The Crypto service can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. |
||||||
|
|
||||||
|
Assumption: the owner identifier is a nonzero value of type `int32_t`. |
||||||
|
|
||||||
|
* Files 0 through 0xfffeffff: unused. |
||||||
|
* Files 0xffff0000 through 0xffffffff: reserved for internal use of the crypto library or crypto service. See [non-key files](#non-key-files-on-tbd). |
||||||
|
* Files 0x100000000 through 0xffffffffffff: [content](#key-file-format-for-1.0.0) of the [key whose identifier is the file identifier](#key-names-for-1.0.0). The upper 32 bits determine the owner. |
||||||
|
|
||||||
|
### File namespace on ITS as a library on TBD |
||||||
|
|
||||||
|
Assumption: ITS provides a 64-bit file identifier namespace. The entity using the crypto library can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. |
||||||
|
|
||||||
|
This is a library integration, so there is no owner. The key file identifier is identical to the key identifier. |
||||||
|
|
||||||
|
* File 0: unused. |
||||||
|
* Files 1 through 0xfffeffff: [content](#key-file-format-for-1.0.0) of the [key whose identifier is the file identifier](#key-names-for-1.0.0). |
||||||
|
* Files 0xffff0000 through 0xffffffff: reserved for internal use of the crypto library or crypto service. See [non-key files](#non-key-files-on-tbd). |
||||||
|
* Files 0x100000000 through 0xffffffffffffffff: unused. |
||||||
|
|
||||||
|
### Non-key files on TBD |
||||||
|
|
||||||
|
File identifiers in the range 0xffff0000 through 0xffffffff are reserved for internal use in Mbed Crypto. |
||||||
|
|
||||||
|
* Files 0xfffffe02 through 0xfffffeff (`PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime`): secure element driver storage. The content of the file is the secure element driver's persistent data. |
||||||
|
* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-1.0.0). |
||||||
|
* File 0xffffff54 (`PSA_CRYPTO_ITS_TRANSACTION_UID`): [transaction file](#transaction-file-format-for-tbd). |
||||||
|
* Other files are unused and reserved for future use. |
||||||
|
|
||||||
|
### Key file format for TBD |
||||||
|
|
||||||
|
All integers are encoded in little-endian order in 8-bit bytes except where otherwise indicated. |
||||||
|
|
||||||
|
The layout of a key file is: |
||||||
|
|
||||||
|
* magic (8 bytes): `"PSA\0KEY\0"`. |
||||||
|
* version (4 bytes): 0. |
||||||
|
* lifetime (4 bytes): `psa_key_lifetime_t` value. |
||||||
|
* type (4 bytes): `psa_key_type_t` value. |
||||||
|
* policy usage flags (4 bytes): `psa_key_usage_t` value. |
||||||
|
* policy usage algorithm (4 bytes): `psa_algorithm_t` value. |
||||||
|
* policy enrollment algorithm (4 bytes): `psa_algorithm_t` value. |
||||||
|
* key material length (4 bytes). |
||||||
|
* key material: |
||||||
|
* For a transparent key: output of `psa_export_key`. |
||||||
|
* For an opaque key (unified driver interface): driver-specific opaque key blob. |
||||||
|
* For an opaque key (key in a secure element): slot number (8 bytes), in platform endianness. |
||||||
|
* Any trailing data is rejected on load. |
||||||
|
|
||||||
|
### Transaction file format for TBD |
||||||
|
|
||||||
|
The transaction file contains data about an ongoing action that cannot be completed atomically. It exists only if there is an ongoing transaction. |
||||||
|
|
||||||
|
All integers are encoded in platform endianness. |
||||||
|
|
||||||
|
All currently existing transactions concern a key in a secure element. |
||||||
|
|
||||||
|
The layout of a transaction file is: |
||||||
|
|
||||||
|
* type (2 bytes): the [transaction type](#transaction-types-on-tbd). |
||||||
|
* unused (2 bytes) |
||||||
|
* lifetime (4 bytes): `psa_key_lifetime_t` value that corresponds to a key in a secure element. |
||||||
|
* slot number (8 bytes): `psa_key_slot_number_t` value. This is the unique designation of the key for the secure element driver. |
||||||
|
* key identifier (4 bytes in a library integration, 8 bytes on a PSA platform): the internal representation of the key identifier. On a PSA platform, this encodes the key owner in the same way as [in file identifiers for key files](#file-namespace-on-a-psa-platform-on-tbd)). |
||||||
|
|
||||||
|
#### Transaction types on TBD |
||||||
|
|
||||||
|
* 0x0001: key creation. The following locations may or may not contain data about the key that is being created: |
||||||
|
* The slot in the secure element designated by the slot number. |
||||||
|
* The file containing the key metadata designated by the key identifier. |
||||||
|
* The driver persistent data. |
||||||
|
* 0x0002: key destruction. The following locations may or may not still contain data about the key that is being destroyed: |
||||||
|
* The slot in the secure element designated by the slot number. |
||||||
|
* The file containing the key metadata designated by the key identifier. |
||||||
|
* The driver persistent data. |
||||||
|
|
||||||
|
Mbed Crypto TBD |
||||||
|
--------------- |
||||||
|
|
||||||
|
Tags: TBD |
||||||
|
|
||||||
|
Released in TBD 2020. <br> |
||||||
|
Integrated in Mbed OS TBD. |
||||||
|
|
||||||
|
### Changes introduced in TBD |
||||||
|
|
||||||
|
* The type field has been split into a type and a bits field of 2 bytes each. |
||||||
|
|
||||||
|
### Key file format for TBD |
||||||
|
|
||||||
|
All integers are encoded in little-endian order in 8-bit bytes except where otherwise indicated. |
||||||
|
|
||||||
|
The layout of a key file is: |
||||||
|
|
||||||
|
* magic (8 bytes): `"PSA\0KEY\0"`. |
||||||
|
* version (4 bytes): 0. |
||||||
|
* lifetime (4 bytes): `psa_key_lifetime_t` value. |
||||||
|
* type (2 bytes): `psa_key_type_t` value. |
||||||
|
* bits (2 bytes): `psa_key_bits_t` value. |
||||||
|
* policy usage flags (4 bytes): `psa_key_usage_t` value. |
||||||
|
* policy usage algorithm (4 bytes): `psa_algorithm_t` value. |
||||||
|
* policy enrollment algorithm (4 bytes): `psa_algorithm_t` value. |
||||||
|
* key material length (4 bytes). |
||||||
|
* key material: |
||||||
|
* For a transparent key: output of `psa_export_key`. |
||||||
|
* For an opaque key (unified driver interface): driver-specific opaque key blob. |
||||||
|
* For an opaque key (key in a secure element): slot number (8 bytes), in platform endianness. |
||||||
|
* Any trailing data is rejected on load. |
||||||
|
|
||||||
|
Mbed TLS 2.25.0 |
||||||
|
--------------- |
||||||
|
|
||||||
|
Tags: `mbedtls-2.25.0`, `mbedtls-2.26.0`, `mbedtls-2.27.0`, `mbedtls-2.28.0`, `mbedtls-3.0.0`, `mbedtls-3.1.0` |
||||||
|
|
||||||
|
First released in December 2020. |
||||||
|
|
||||||
|
Note: this is the first version that is officially supported. The version number is still 0. |
||||||
|
|
||||||
|
Backward compatibility commitments: we promise backward compatibility for stored keys when Mbed TLS is upgraded from x to y if x >= 2.25 and y < 4. See [`BRANCHES.md`](../../BRANCHES.md) for more details. |
||||||
|
|
||||||
|
Supported integrations: |
||||||
|
|
||||||
|
* [PSA platform](#file-namespace-on-a-psa-platform-on-mbed-tls-2.25.0) |
||||||
|
* [library using PSA ITS](#file-namespace-on-its-as-a-library-on-mbed-tls-2.25.0) |
||||||
|
* [library using C stdio](#file-namespace-on-stdio-for-mbed-tls-2.25.0) |
||||||
|
|
||||||
|
Supported features: |
||||||
|
|
||||||
|
* [Persistent keys](#key-file-format-for-mbed-tls-2.25.0) designated by a [key identifier and owner](#key-names-for-mbed-tls-2.25.0). Keys can be: |
||||||
|
* Transparent, stored in the export format. |
||||||
|
* Opaque, using the unified driver interface with statically registered drivers (`MBEDTLS_PSA_CRYPTO_DRIVERS`). The driver determines the content of the opaque key blob. |
||||||
|
* Opaque, using the deprecated secure element interface with dynamically registered drivers (`MBEDTLS_PSA_CRYPTO_SE_C`). The driver picks a slot number which is stored in the place of the key material. |
||||||
|
* [Nonvolatile random seed](#nonvolatile-random-seed-file-format-for-mbed-tls-2.25.0) on ITS only. |
||||||
|
|
||||||
|
### Changes introduced in Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
* The numerical encodings of `psa_key_type_t`, `psa_key_usage_t` and `psa_algorithm_t` have changed. |
||||||
|
|
||||||
|
### File namespace on a PSA platform on Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
Assumption: ITS provides a 64-bit file identifier namespace. The Crypto service can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. |
||||||
|
|
||||||
|
Assumption: the owner identifier is a nonzero value of type `int32_t`. |
||||||
|
|
||||||
|
* Files 0 through 0xfffeffff: unused. |
||||||
|
* Files 0xffff0000 through 0xffffffff: reserved for internal use of the crypto library or crypto service. See [non-key files](#non-key-files-on-mbed-tls-2.25.0). |
||||||
|
* Files 0x100000000 through 0xffffffffffff: [content](#key-file-format-for-mbed-tls-2.25.0) of the [key whose identifier is the file identifier](#key-names-for-mbed-tls-2.25.0). The upper 32 bits determine the owner. |
||||||
|
|
||||||
|
### File namespace on ITS as a library on Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
Assumption: ITS provides a 64-bit file identifier namespace. The entity using the crypto library can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. |
||||||
|
|
||||||
|
This is a library integration, so there is no owner. The key file identifier is identical to the key identifier. |
||||||
|
|
||||||
|
* File 0: unused. |
||||||
|
* Files 1 through 0xfffeffff: [content](#key-file-format-for-mbed-tls-2.25.0) of the [key whose identifier is the file identifier](#key-names-for-mbed-tls-2.25.0). |
||||||
|
* Files 0xffff0000 through 0xffffffff: reserved for internal use of the crypto library or crypto service. See [non-key files](#non-key-files-on-mbed-tls-2.25.0). |
||||||
|
* Files 0x100000000 through 0xffffffffffffffff: unused. |
||||||
|
|
||||||
|
### File namespace on stdio for Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
Assumption: C stdio, allowing names containing lowercase letters, digits and underscores, of length up to 23. |
||||||
|
|
||||||
|
An undocumented build-time configuration value `PSA_ITS_STORAGE_PREFIX` allows storing the key files in a directory other than the current directory. This value is simply prepended to the file name (so it must end with a directory separator to put the keys in a different directory). |
||||||
|
|
||||||
|
* `PSA_ITS_STORAGE_PREFIX "tempfile.psa_its"`: used as a temporary file. Must be writable. May be overwritten or deleted if present. |
||||||
|
* `sprintf(PSA_ITS_STORAGE_PREFIX "%016llx.psa_its", key_id)`: a key or non-key file. The `key_id` in the name is the 64-bit file identifier, which is the [key identifier](#key-names-for-mbed-tls-2.25.0) for a key file or some reserved identifier for a [non-key file](#non-key-files-on-mbed-tls-2.25.0). The contents of the file are: |
||||||
|
* Magic header (8 bytes): `"PSA\0ITS\0"` |
||||||
|
* File contents. |
||||||
|
|
||||||
|
### Key names for Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
Information about each key is stored in a dedicated file designated by the key identifier. In integrations where there is no concept of key owner (in particular, in library integrations), the key identifier is exactly the key identifier as defined in the PSA Cryptography API specification (`psa_key_id_t`). In integrations where there is a concept of key owner (integration into a service for example), the key identifier is made of an owner identifier (its semantics and type are integration specific) and of the key identifier (`psa_key_id_t`) from the key owner point of view. |
||||||
|
|
||||||
|
The way in which the file name is constructed from the key identifier depends on the storage backend. The content of the file is described [below](#key-file-format-for-mbed-tls-2.25.0). |
||||||
|
|
||||||
|
* Library integration: the key file name is just the key identifier as defined in the PSA crypto specification. This is a 32-bit value which must be in the range 0x00000001..0x3fffffff (`PSA_KEY_ID_USER_MIN`..`PSA_KEY_ID_USER_MAX`). |
||||||
|
* PSA service integration: the key file name is `(uint64_t)owner_uid << 32 | key_id` where `key_id` is the key identifier from the owner point of view and `owner_uid` (of type `int32_t`) is the calling partition identifier provided to the server by the partition manager. This is a 64-bit value. |
||||||
|
|
||||||
|
### Key file format for Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
All integers are encoded in little-endian order in 8-bit bytes except where otherwise indicated. |
||||||
|
|
||||||
|
The layout of a key file is: |
||||||
|
|
||||||
|
* magic (8 bytes): `"PSA\0KEY\0"`. |
||||||
|
* version (4 bytes): 0. |
||||||
|
* lifetime (4 bytes): `psa_key_lifetime_t` value. |
||||||
|
* type (2 bytes): `psa_key_type_t` value. |
||||||
|
* bits (2 bytes): `psa_key_bits_t` value. |
||||||
|
* policy usage flags (4 bytes): `psa_key_usage_t` value. |
||||||
|
* policy usage algorithm (4 bytes): `psa_algorithm_t` value. |
||||||
|
* policy enrollment algorithm (4 bytes): `psa_algorithm_t` value. |
||||||
|
* key material length (4 bytes). |
||||||
|
* key material: |
||||||
|
* For a transparent key: output of `psa_export_key`. |
||||||
|
* For an opaque key (unified driver interface): driver-specific opaque key blob. |
||||||
|
* For an opaque key (key in a dynamic secure element): slot number (8 bytes), in platform endianness. |
||||||
|
* Any trailing data is rejected on load. |
||||||
|
|
||||||
|
### Non-key files on Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
File identifiers that are outside the range of persistent key identifiers are reserved for internal use by the library. The only identifiers currently in use have the owner id (top 32 bits) set to 0. |
||||||
|
|
||||||
|
* Files 0xfffffe02 through 0xfffffeff (`PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime`): dynamic secure element driver storage. The content of the file is the secure element driver's persistent data. |
||||||
|
* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-mbed-tls-2.25.0). |
||||||
|
* File 0xffffff54 (`PSA_CRYPTO_ITS_TRANSACTION_UID`): [transaction file](#transaction-file-format-for-mbed-tls-2.25.0). |
||||||
|
* Other files are unused and reserved for future use. |
||||||
|
|
||||||
|
### Nonvolatile random seed file format for Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
[Identical to Mbed Crypto 0.1.0](#nonvolatile-random-seed-file-format-for-0.1.0). |
||||||
|
|
||||||
|
### Transaction file format for Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
The transaction file contains data about an ongoing action that cannot be completed atomically. It exists only if there is an ongoing transaction. |
||||||
|
|
||||||
|
All integers are encoded in platform endianness. |
||||||
|
|
||||||
|
All currently existing transactions concern a key in a dynamic secure element. |
||||||
|
|
||||||
|
The layout of a transaction file is: |
||||||
|
|
||||||
|
* type (2 bytes): the [transaction type](#transaction-types-on-mbed-tls-2.25.0). |
||||||
|
* unused (2 bytes) |
||||||
|
* lifetime (4 bytes): `psa_key_lifetime_t` value that corresponds to a key in a secure element. |
||||||
|
* slot number (8 bytes): `psa_key_slot_number_t` value. This is the unique designation of the key for the secure element driver. |
||||||
|
* key identifier (4 bytes in a library integration, 8 bytes on a PSA platform): the internal representation of the key identifier. On a PSA platform, this encodes the key owner in the same way as [in file identifiers for key files](#file-namespace-on-a-psa-platform-on-mbed-tls-2.25.0)). |
||||||
|
|
||||||
|
#### Transaction types on Mbed TLS 2.25.0 |
||||||
|
|
||||||
|
* 0x0001: key creation. The following locations may or may not contain data about the key that is being created: |
||||||
|
* The slot in the secure element designated by the slot number. |
||||||
|
* The file containing the key metadata designated by the key identifier. |
||||||
|
* The driver persistent data. |
||||||
|
* 0x0002: key destruction. The following locations may or may not still contain data about the key that is being destroyed: |
||||||
|
* The slot in the secure element designated by the slot number. |
||||||
|
* The file containing the key metadata designated by the key identifier. |
||||||
|
* The driver persistent data. |
@ -0,0 +1,73 @@ |
|||||||
|
PSA Cryptography API implementation and PSA driver interface |
||||||
|
=========================================================== |
||||||
|
|
||||||
|
## Introduction |
||||||
|
|
||||||
|
The [PSA Cryptography API specification](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) defines an interface to cryptographic operations for which the Mbed TLS library provides a reference implementation. The PSA Cryptography API specification is complemented by the PSA driver interface specification which defines an interface for cryptoprocessor drivers. |
||||||
|
|
||||||
|
This document describes the high level organization of the Mbed TLS PSA Cryptography API implementation which is tightly related to the PSA driver interface. |
||||||
|
|
||||||
|
## High level organization of the Mbed TLS PSA Cryptography API implementation |
||||||
|
In one sentence, the Mbed TLS PSA Cryptography API implementation is made of a core and PSA drivers as defined in the PSA driver interface. The key point is that software cryptographic operations are organized as PSA drivers: they interact with the core through the PSA driver interface. |
||||||
|
|
||||||
|
### Rationale |
||||||
|
|
||||||
|
* Addressing software and hardware cryptographic implementations through the same C interface reduces the core code size and its call graph complexity. The core and its dispatching to software and hardware implementations are consequently easier to test and validate. |
||||||
|
* The organization of the software cryptographic implementations in drivers promotes modularization of those implementations. |
||||||
|
* As hardware capabilities, software cryptographic functionalities can be described by a JSON driver description file as defined in the PSA driver interface. |
||||||
|
* Along with JSON driver description files, the PSA driver specification defines the deliverables for a driver to be included into the Mbed TLS PSA Cryptography implementation. This provides a natural framework to integrate third party or alternative software implementations of cryptographic operations. |
||||||
|
|
||||||
|
## The Mbed TLS PSA Cryptography API implementation core |
||||||
|
|
||||||
|
The core implements all the APIs as defined in the PSA Cryptography API specification but does not perform on its own any cryptographic operation. The core relies on PSA drivers to actually |
||||||
|
perform the cryptographic operations. The core is responsible for: |
||||||
|
|
||||||
|
* the key store. |
||||||
|
* checking PSA API arguments and translating them into valid arguments for the necessary calls to the PSA driver interface. |
||||||
|
* dispatching the cryptographic operations to the appropriate PSA drivers. |
||||||
|
|
||||||
|
The sketch of an Mbed TLS PSA cryptographic API implementation is thus: |
||||||
|
```C |
||||||
|
psa_status_t psa_api( ... ) |
||||||
|
{ |
||||||
|
psa_status_t status; |
||||||
|
|
||||||
|
/* Pre driver interface call processing: validation of arguments, building |
||||||
|
* of arguments for the call to the driver interface, ... */ |
||||||
|
|
||||||
|
... |
||||||
|
|
||||||
|
/* Call to the driver interface */ |
||||||
|
status = psa_driver_wrapper_<entry_point>( ... ); |
||||||
|
if( status != PSA_SUCCESS ) |
||||||
|
return( status ); |
||||||
|
|
||||||
|
/* Post driver interface call processing: validation of the values returned |
||||||
|
* by the driver, finalization of the values to return to the caller, |
||||||
|
* clean-up in case of error ... */ |
||||||
|
} |
||||||
|
``` |
||||||
|
The code of most PSA APIs is expected to match precisely the above layout. However, it is likely that the code structure of some APIs will be more complicated with several calls to the driver interface, mainly to encompass a larger variety of hardware designs. For example, to encompass hardware accelerators that are capable of verifying a MAC and those that are only capable of computing a MAC, the psa_mac_verify() API could call first psa_driver_wrapper_mac_verify() and then fallback to psa_driver_wrapper_mac_compute(). |
||||||
|
|
||||||
|
The implementations of `psa_driver_wrapper_<entry_point>` functions are generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. The implementations are generated in a psa_crypto_driver_wrappers.c C file and the function prototypes declared in a psa_crypto_driver_wrappers.h header file. |
||||||
|
|
||||||
|
The psa_driver_wrapper_<entry_point>() functions dispatch cryptographic operations to accelerator drivers, secure element drivers as well as to the software implementations of cryptographic operations. |
||||||
|
|
||||||
|
Note that the implementation allows to build the library with only a C compiler by shipping a generated file corresponding to a pure software implementation. The driver entry points and their code in this generated file are guarded by pre-processor directives based on PSA_WANT_xyz macros (see [Conditional inclusion of cryptographic mechanism through the PSA API in Mbed TLS](psa-conditional-inclusion-c.html). That way, it is possible to compile and include in the library only the desired cryptographic operations. |
||||||
|
|
||||||
|
### Key creation |
||||||
|
|
||||||
|
Key creation implementation in Mbed TLS PSA core is articulated around three internal functions: psa_start_key_creation(), psa_finish_key_creation() and psa_fail_key_creation(). Implementations of key creation PSA APIs, namely psa_import_key(), psa_generate_key(), psa_key_derivation_output_key() and psa_copy_key() go by the following sequence: |
||||||
|
1. Check the input parameters. |
||||||
|
2. Call psa_start_key_creation() that allocates a key slot, prepares it with the specified key attributes, and in case of a volatile key assign it a volatile key identifier. |
||||||
|
3. Generate or copy the key material into the key slot. This entails the allocation of the buffer to store the key material. |
||||||
|
4. Call psa_finish_key_creation() that mostly saves persistent keys into persistent storage. |
||||||
|
|
||||||
|
In case of any error occurring at step 3 or 4, psa_fail_key_creation() is called. It wipes and cleans the slot especially the key material: reset to zero of the RAM memory that contained the key material, free the allocated buffer. |
||||||
|
|
||||||
|
|
||||||
|
## Mbed TLS PSA Cryptography API implementation drivers |
||||||
|
|
||||||
|
A driver of the Mbed TLS PSA Cryptography API implementation (Mbed TLS PSA driver in the following) is a driver in the sense that it is compliant with the PSA driver interface specification. But it is not an actual driver that drives some hardware. It implements cryptographic operations purely in software. |
||||||
|
|
||||||
|
An Mbed TLS PSA driver C file is named psa_crypto_<driver_name>.c and its associated header file psa_crypto_<driver_name>.h. The functions implementing a driver entry point as defined in the PSA driver interface specification are named as mbedtls_psa_<driver name>_<entry point>(). As an example, the psa_crypto_rsa.c and psa_crypto_rsa.h are the files containing the Mbed TLS PSA driver implementing RSA cryptographic operations. This RSA driver implements among other entry points the "import_key" entry point. The function implementing this entry point is named mbedtls_psa_rsa_import_key(). |
@ -0,0 +1,132 @@ |
|||||||
|
#!/bin/sh |
||||||
|
|
||||||
|
# This script runs tests in various revisions and configurations and analyses |
||||||
|
# the results in order to highlight any difference in the set of tests skipped |
||||||
|
# in the test suites of interest. |
||||||
|
# |
||||||
|
# It can be used to ensure the testing criteria mentioned in strategy.md, |
||||||
|
# end of section "Supporting builds with drivers without the software |
||||||
|
# implementation" are met, namely: |
||||||
|
# |
||||||
|
# - the sets of tests skipped in the default config and the full config must be |
||||||
|
# the same before and after the PR that implements step 3; |
||||||
|
# - the set of tests skipped in the driver-only build is the same as in an |
||||||
|
# equivalent software-based configuration, or the difference is small enough, |
||||||
|
# justified, and a github issue is created to track it. |
||||||
|
# This part is verified by tests/scripts/analyze_outcomes.py |
||||||
|
# |
||||||
|
# WARNING: this script checks out a commit other than the head of the current |
||||||
|
# branch; it checks out the current branch again when running successfully, |
||||||
|
# but while the script is running, or if it terminates early in error, you |
||||||
|
# should be aware that you might be at a different commit than expected. |
||||||
|
# |
||||||
|
# NOTE: This is only an example/template script, you should make a copy and |
||||||
|
# edit it to suit your needs. The part that needs editing is at the top. |
||||||
|
# |
||||||
|
# Also, you can comment out parts that don't need to be re-done when |
||||||
|
# re-running this script (for example "get numbers before this PR"). |
||||||
|
|
||||||
|
# ----- BEGIN edit this ----- |
||||||
|
# Space-separated list of test suites to ignore: |
||||||
|
# if SSS is in that list, test_suite_SSS and test_suite_SSS.* are ignored. |
||||||
|
IGNORE="md mdx shax" # accelerated |
||||||
|
IGNORE="$IGNORE entropy hmac_drbg random" # disabled (ext. RNG) |
||||||
|
IGNORE="$IGNORE psa_crypto_init" # needs internal RNG |
||||||
|
IGNORE="$IGNORE hkdf" # disabled in the all.sh component tested |
||||||
|
# ----- END edit this ----- |
||||||
|
|
||||||
|
set -eu |
||||||
|
|
||||||
|
cleanup() { |
||||||
|
make clean |
||||||
|
git checkout -- include/mbedtls/mbedtls_config.h include/psa/crypto_config.h |
||||||
|
} |
||||||
|
|
||||||
|
record() { |
||||||
|
export MBEDTLS_TEST_OUTCOME_FILE="$PWD/outcome-$1.csv" |
||||||
|
rm -f $MBEDTLS_TEST_OUTCOME_FILE |
||||||
|
make check |
||||||
|
} |
||||||
|
|
||||||
|
# save current HEAD |
||||||
|
HEAD=$(git branch --show-current) |
||||||
|
|
||||||
|
# get the numbers before this PR for default and full |
||||||
|
cleanup |
||||||
|
git checkout $(git merge-base HEAD development) |
||||||
|
record "before-default" |
||||||
|
|
||||||
|
cleanup |
||||||
|
scripts/config.py full |
||||||
|
record "before-full" |
||||||
|
|
||||||
|
# get the numbers now for default and full |
||||||
|
cleanup |
||||||
|
git checkout $HEAD |
||||||
|
record "after-default" |
||||||
|
|
||||||
|
cleanup |
||||||
|
scripts/config.py full |
||||||
|
record "after-full" |
||||||
|
|
||||||
|
|
||||||
|
# analysis |
||||||
|
|
||||||
|
populate_suites () { |
||||||
|
SUITES='' |
||||||
|
make generated_files >/dev/null |
||||||
|
data_files=$(cd tests/suites && echo *.data) |
||||||
|
for data in $data_files; do |
||||||
|
suite=${data#test_suite_} |
||||||
|
suite=${suite%.data} |
||||||
|
suite_base=${suite%%.*} |
||||||
|
case " $IGNORE " in |
||||||
|
*" $suite_base "*) :;; |
||||||
|
*) SUITES="$SUITES $suite";; |
||||||
|
esac |
||||||
|
done |
||||||
|
make neat |
||||||
|
} |
||||||
|
|
||||||
|
compare_suite () { |
||||||
|
ref="outcome-$1.csv" |
||||||
|
new="outcome-$2.csv" |
||||||
|
suite="$3" |
||||||
|
|
||||||
|
pattern_suite=";test_suite_$suite;" |
||||||
|
total=$(grep -c "$pattern_suite" "$ref") |
||||||
|
sed_cmd="s/^.*$pattern_suite\(.*\);SKIP.*/\1/p" |
||||||
|
sed -n "$sed_cmd" "$ref" > skipped-ref |
||||||
|
sed -n "$sed_cmd" "$new" > skipped-new |
||||||
|
nb_ref=$(wc -l <skipped-ref) |
||||||
|
nb_new=$(wc -l <skipped-new) |
||||||
|
|
||||||
|
printf "%36s: total %4d; skipped %4d -> %4d\n" \ |
||||||
|
$suite $total $nb_ref $nb_new |
||||||
|
if diff skipped-ref skipped-new | grep '^> '; then |
||||||
|
ret=1 |
||||||
|
else |
||||||
|
ret=0 |
||||||
|
fi |
||||||
|
rm skipped-ref skipped-new |
||||||
|
return $ret |
||||||
|
} |
||||||
|
|
||||||
|
compare_builds () { |
||||||
|
printf "\n*** Comparing $1 -> $2 ***\n" |
||||||
|
failed='' |
||||||
|
for suite in $SUITES; do |
||||||
|
if compare_suite "$1" "$2" "$suite"; then :; else |
||||||
|
failed="$failed $suite" |
||||||
|
fi |
||||||
|
done |
||||||
|
if [ -z "$failed" ]; then |
||||||
|
printf "No coverage gap found.\n" |
||||||
|
else |
||||||
|
printf "Suites with less coverage:%s\n" "$failed" |
||||||
|
fi |
||||||
|
} |
||||||
|
|
||||||
|
populate_suites |
||||||
|
compare_builds before-default after-default |
||||||
|
compare_builds before-full after-full |
@ -0,0 +1,324 @@ |
|||||||
|
This document lists current limitations of the PSA Crypto API (as of version |
||||||
|
1.1) that may impact our ability to (1) use it for all crypto operations in |
||||||
|
TLS and X.509 and (2) support isolation of all long-term secrets in TLS (that |
||||||
|
is, goals G1 and G2 in [strategy.md](strategy.md) in the same directory). |
||||||
|
|
||||||
|
This is supposed to be a complete list, based on a exhaustive review of crypto |
||||||
|
operations done in TLS and X.509 code, but of course it's still possible that |
||||||
|
subtle-but-important issues have been missed. The only way to be really sure |
||||||
|
is, of course, to actually do the migration work. |
||||||
|
|
||||||
|
Limitations relevant for G1 (performing crypto operations) |
||||||
|
========================================================== |
||||||
|
|
||||||
|
Restartable ECC operations |
||||||
|
-------------------------- |
||||||
|
|
||||||
|
There is currently no support for that in PSA at all, but it will be added at |
||||||
|
some point, see <https://github.com/orgs/Mbed-TLS/projects/1#column-18816849>. |
||||||
|
|
||||||
|
Currently, `MBEDTLS_USE_PSA_CRYPTO` is simply incompatible with |
||||||
|
`MBEDTLS_ECP_RESTARTABLE`. |
||||||
|
|
||||||
|
Things that are in the API but not implemented yet |
||||||
|
-------------------------------------------------- |
||||||
|
|
||||||
|
PSA Crypto has an API for FFDH, but it's not implemented in Mbed TLS yet. |
||||||
|
(Regarding FFDH, see the next section as well.) See issue [3261][ffdh] on |
||||||
|
github. |
||||||
|
|
||||||
|
[ffdh]: https://github.com/Mbed-TLS/mbedtls/issues/3261 |
||||||
|
|
||||||
|
Arbitrary parameters for FFDH |
||||||
|
----------------------------- |
||||||
|
|
||||||
|
(See also the first paragraph in the previous section.) |
||||||
|
|
||||||
|
Currently, the PSA Crypto API can only perform FFDH with a limited set of |
||||||
|
well-known parameters (some of them defined in the spec, but implementations |
||||||
|
are free to extend that set). |
||||||
|
|
||||||
|
TLS 1.2 (and earlier) on the other hand have the server send explicit |
||||||
|
parameters (P and G) in its ServerKeyExchange message. This has been found to |
||||||
|
be suboptimal for security, as it is prohibitively hard for the client to |
||||||
|
verify the strength of these parameters. This led to the development of RFC |
||||||
|
7919 which allows use of named groups in TLS 1.2 - however as this is only an |
||||||
|
extension, servers can still send custom parameters if they don't support the |
||||||
|
extension. |
||||||
|
|
||||||
|
In TLS 1.3 the situation will be simpler: named groups are the only |
||||||
|
option, so the current PSA Crypto API is a good match for that. (Not |
||||||
|
coincidentally, all the groups used by RFC 7919 and TLS 1.3 are included |
||||||
|
in the PSA specification.) |
||||||
|
|
||||||
|
There are several options here: |
||||||
|
|
||||||
|
1. Implement support for custom FFDH parameters in PSA Crypto: this would pose |
||||||
|
non-trivial API design problem, but most importantly seems backwards, as |
||||||
|
the crypto community is moving away from custom FFDH parameters. (Could be |
||||||
|
done any time.) |
||||||
|
2. Drop the DHE-RSA and DHE-PSK key exchanges in TLS 1.2 when moving to PSA. |
||||||
|
(For people who want some algorithmic variety in case ECC collapses, FFDH |
||||||
|
would still be available in TLS 1.3, just not in 1.2.) (Can only be done in |
||||||
|
4.0 or another major version.) |
||||||
|
3. Variant of the precedent: only drop client-side support. Server-side is |
||||||
|
easy to support in terms of API/protocol, as the server picks the |
||||||
|
parameters: we just need remove the existing `mbedtls_ssl_conf_dh_param_xxx()` |
||||||
|
APIs and tell people to use `mbedtls_ssl_conf_groups()` instead. (Can only be |
||||||
|
done in 4.0 or another major version.) |
||||||
|
4. Implement RFC 7919, support DHE-RSA and DHE-PSK only in conjunction with it |
||||||
|
when moving to PSA. Server-side would work as above; unfortunately |
||||||
|
client-side the only option is to offer named groups and break the handshake |
||||||
|
if the server didn't take on our offer. This is not fully satisfying, but is |
||||||
|
perhaps the least unsatisfying option in terms of result; it's also probably |
||||||
|
the one that requires the most work, but it would deliver value beyond PSA |
||||||
|
migration by implementing RFC 7919. (Implementing RFC 7919 could be done any |
||||||
|
time; making it mandatory can only be done in 4.0 or another major version.) |
||||||
|
|
||||||
|
RSA-PSS parameters |
||||||
|
------------------ |
||||||
|
|
||||||
|
RSA-PSS signatures are defined by PKCS#1 v2, re-published as RFC 8017 |
||||||
|
(previously RFC 3447). |
||||||
|
|
||||||
|
As standardized, the signature scheme takes several parameters, in addition to |
||||||
|
the hash algorithm potentially used to hash the message being signed: |
||||||
|
- a hash algorithm used for the encoding function |
||||||
|
- a mask generation function |
||||||
|
- most commonly MGF1, which in turn is parametrized by a hash algorithm |
||||||
|
- a salt length |
||||||
|
- a trailer field - the value is fixed to 0xBC by PKCS#1 v2.1, but was left |
||||||
|
configurable in the original scheme; 0xBC is used everywhere in practice. |
||||||
|
|
||||||
|
Both the existing `mbedtls_` API and the PSA API support only MGF1 as the |
||||||
|
generation function (and only 0xBC as the trailer field), but there are |
||||||
|
discrepancies in handling the salt length and which of the various hash |
||||||
|
algorithms can differ from each other. |
||||||
|
|
||||||
|
### API comparison |
||||||
|
|
||||||
|
- RSA: |
||||||
|
- signature: `mbedtls_rsa_rsassa_pss_sign()` |
||||||
|
- message hashed externally |
||||||
|
- encoding hash = MGF1 hash (from context, or argument = message hash) |
||||||
|
- salt length: always using the maximum legal value |
||||||
|
- signature: `mbedtls_rsa_rsassa_pss_sign_ext()` |
||||||
|
- message hashed externally |
||||||
|
- encoding hash = MGF1 hash (from context, or argument = message hash) |
||||||
|
- salt length: specified explicitly |
||||||
|
- verification: `mbedtls_rsassa_pss_verify()` |
||||||
|
- message hashed externally |
||||||
|
- encoding hash = MGF1 hash (from context, or argument = message hash) |
||||||
|
- salt length: any valid length accepted |
||||||
|
- verification: `mbedtls_rsassa_pss_verify_ext()` |
||||||
|
- message hashed externally |
||||||
|
- encoding hash = MGF1 hash from dedicated argument |
||||||
|
- expected salt length: specified explicitly, can specify "ANY" |
||||||
|
- PK: |
||||||
|
- signature: not supported |
||||||
|
- verification: `mbedtls_pk_verify_ext()` |
||||||
|
- message hashed externally |
||||||
|
- encoding hash = MGF1 hash, specified explicitly |
||||||
|
- expected salt length: specified explicitly, can specify "ANY" |
||||||
|
- PSA: |
||||||
|
- algorithm specification: |
||||||
|
- hash alg used for message hashing, encoding and MGF1 |
||||||
|
- salt length can be either "standard" (<= hashlen, see note) or "any" |
||||||
|
- signature generation: |
||||||
|
- salt length: always <= hashlen (see note) and random salt |
||||||
|
- verification: |
||||||
|
- salt length: either <= hashlen (see note), or any depending on algorithm |
||||||
|
|
||||||
|
Note: above, "<= hashlen" means that hashlen is used if possible, but if it |
||||||
|
doesn't fit because the key is too short, then the maximum length that fits is |
||||||
|
used. |
||||||
|
|
||||||
|
The RSA/PK API is in principle more flexible than the PSA Crypto API. The |
||||||
|
following sub-sections study whether and how this matters in practice. |
||||||
|
|
||||||
|
### Use in X.509 |
||||||
|
|
||||||
|
RFC 4055 Section 3.1 defines the encoding of RSA-PSS that's used in X.509. |
||||||
|
It allows independently specifying the message hash (also used for encoding |
||||||
|
hash), the MGF (and its hash if MGF1 is used), and the salt length (plus an |
||||||
|
extra parameter "trailer field" that doesn't vary in practice"). These can be |
||||||
|
encoded as part of the key, and of the signature. If both encoding are |
||||||
|
presents, all values must match except possibly for the salt length, where the |
||||||
|
value from the signature parameters is used. |
||||||
|
|
||||||
|
In Mbed TLS, RSA-PSS parameters can be parsed and displayed for various |
||||||
|
objects (certificates, CRLs, CSRs). During parsing, the following properties |
||||||
|
are enforced: |
||||||
|
- the extra "trailer field" parameter must have its default value |
||||||
|
- the mask generation function is MGF1 |
||||||
|
- encoding hash = message hashing algorithm (may differ from MGF1 hash) |
||||||
|
|
||||||
|
When it comes to cryptographic operations, only two things are supported: |
||||||
|
- verifying the signature on a certificate from its parent; |
||||||
|
- verifying the signature on a CRL from the issuing CA. |
||||||
|
|
||||||
|
The verification is done using `mbedtls_pk_verify_ext()`. |
||||||
|
|
||||||
|
Note: since X.509 parsing ensures that message hash = encoding hash, and |
||||||
|
`mbedtls_pk_verify_ext()` uses encoding hash = mgf1 hash, it looks like all |
||||||
|
three hash algorithms must be equal, which would be good news as it would |
||||||
|
match a limitation of the PSA API. |
||||||
|
|
||||||
|
It is unclear what parameters people use in practice. It looks like by default |
||||||
|
OpenSSL picks saltlen = keylen - hashlen - 2 (tested with openssl 1.1.1f). |
||||||
|
The `certtool` command provided by GnuTLS seems to be picking saltlen = hashlen |
||||||
|
by default (tested with GnuTLS 3.6.13). FIPS 186-4 requires 0 <= saltlen <= |
||||||
|
hashlen. |
||||||
|
|
||||||
|
### Use in TLS |
||||||
|
|
||||||
|
In TLS 1.2 (or lower), RSA-PSS signatures are never used, except via X.509. |
||||||
|
|
||||||
|
In TLS 1.3, RSA-PSS signatures can be used directly in the protocol (in |
||||||
|
addition to indirect use via X.509). It has two sets of three signature |
||||||
|
algorithm identifiers (for SHA-256, SHA-384 and SHA-512), depending of what |
||||||
|
the OID of the public key is (rsaEncryption or RSASSA-PSS). |
||||||
|
|
||||||
|
In both cases, it specifies that: |
||||||
|
- the mask generation function is MGF1 |
||||||
|
- all three hashes are equal |
||||||
|
- the length of the salt MUST be equal to the length of the digest algorithm |
||||||
|
|
||||||
|
When signing, the salt length picked by PSA is the one required by TLS 1.3 |
||||||
|
(unless the key is unreasonably small). |
||||||
|
|
||||||
|
When verifying signatures, PSA will by default enforce the salt len is the one |
||||||
|
required by TLS 1.3. |
||||||
|
|
||||||
|
### Current testing - X509 |
||||||
|
|
||||||
|
All test files use the default trailer field of 0xBC, as enforced by our |
||||||
|
parser. (There's a negative test for that using the |
||||||
|
`x509_parse_rsassa_pss_params` test function and hex data.) |
||||||
|
|
||||||
|
Files with "bad" in the name are expected to be invalid and rejected in tests. |
||||||
|
|
||||||
|
**Test certificates:** |
||||||
|
|
||||||
|
server9-bad-mgfhash.crt (announcing mgf1(sha224), signed with another mgf) |
||||||
|
Hash Algorithm: sha256 |
||||||
|
Mask Algorithm: mgf1 with sha224 |
||||||
|
Salt Length: 0xDE |
||||||
|
server9-bad-saltlen.crt (announcing saltlen = 0xDE, signed with another len) |
||||||
|
Hash Algorithm: sha256 |
||||||
|
Mask Algorithm: mgf1 with sha256 |
||||||
|
Salt Length: 0xDE |
||||||
|
server9-badsign.crt (one bit flipped in the signature) |
||||||
|
Hash Algorithm: sha1 (default) |
||||||
|
Mask Algorithm: mgf1 with sha1 (default) |
||||||
|
Salt Length: 0xEA |
||||||
|
server9-defaults.crt |
||||||
|
Hash Algorithm: sha1 (default) |
||||||
|
Mask Algorithm: mgf1 with sha1 (default) |
||||||
|
Salt Length: 0x14 (default) |
||||||
|
server9-sha224.crt |
||||||
|
Hash Algorithm: sha224 |
||||||
|
Mask Algorithm: mgf1 with sha224 |
||||||
|
Salt Length: 0xE2 |
||||||
|
server9-sha256.crt |
||||||
|
Hash Algorithm: sha256 |
||||||
|
Mask Algorithm: mgf1 with sha256 |
||||||
|
Salt Length: 0xDE |
||||||
|
server9-sha384.crt |
||||||
|
Hash Algorithm: sha384 |
||||||
|
Mask Algorithm: mgf1 with sha384 |
||||||
|
Salt Length: 0xCE |
||||||
|
server9-sha512.crt |
||||||
|
Hash Algorithm: sha512 |
||||||
|
Mask Algorithm: mgf1 with sha512 |
||||||
|
Salt Length: 0xBE |
||||||
|
server9-with-ca.crt |
||||||
|
Hash Algorithm: sha1 (default) |
||||||
|
Mask Algorithm: mgf1 with sha1 (default) |
||||||
|
Salt Length: 0xEA |
||||||
|
server9.crt |
||||||
|
Hash Algorithm: sha1 (default) |
||||||
|
Mask Algorithm: mgf1 with sha1 (default) |
||||||
|
Salt Length: 0xEA |
||||||
|
|
||||||
|
These certificates are signed with a 2048-bit key. It appears that they are |
||||||
|
all using saltlen = keylen - hashlen - 2, except for server9-defaults which is |
||||||
|
using saltlen = hashlen. |
||||||
|
|
||||||
|
**Test CRLs:** |
||||||
|
|
||||||
|
crl-rsa-pss-sha1-badsign.pem |
||||||
|
Hash Algorithm: sha1 (default) |
||||||
|
Mask Algorithm: mgf1 with sha1 (default) |
||||||
|
Salt Length: 0xEA |
||||||
|
crl-rsa-pss-sha1.pem |
||||||
|
Hash Algorithm: sha1 (default) |
||||||
|
Mask Algorithm: mgf1 with sha1 (default) |
||||||
|
Salt Length: 0xEA |
||||||
|
crl-rsa-pss-sha224.pem |
||||||
|
Hash Algorithm: sha224 |
||||||
|
Mask Algorithm: mgf1 with sha224 |
||||||
|
Salt Length: 0xE2 |
||||||
|
crl-rsa-pss-sha256.pem |
||||||
|
Hash Algorithm: sha256 |
||||||
|
Mask Algorithm: mgf1 with sha256 |
||||||
|
Salt Length: 0xDE |
||||||
|
crl-rsa-pss-sha384.pem |
||||||
|
Hash Algorithm: sha384 |
||||||
|
Mask Algorithm: mgf1 with sha384 |
||||||
|
Salt Length: 0xCE |
||||||
|
crl-rsa-pss-sha512.pem |
||||||
|
Hash Algorithm: sha512 |
||||||
|
Mask Algorithm: mgf1 with sha512 |
||||||
|
Salt Length: 0xBE |
||||||
|
|
||||||
|
These CRLs are signed with a 2048-bit key. It appears that they are |
||||||
|
all using saltlen = keylen - hashlen - 2. |
||||||
|
|
||||||
|
**Test CSRs:** |
||||||
|
|
||||||
|
server9.req.sha1 |
||||||
|
Hash Algorithm: sha1 (default) |
||||||
|
Mask Algorithm: mgf1 with sha1 (default) |
||||||
|
Salt Length: 0x6A |
||||||
|
server9.req.sha224 |
||||||
|
Hash Algorithm: sha224 |
||||||
|
Mask Algorithm: mgf1 with sha224 |
||||||
|
Salt Length: 0x62 |
||||||
|
server9.req.sha256 |
||||||
|
Hash Algorithm: sha256 |
||||||
|
Mask Algorithm: mgf1 with sha256 |
||||||
|
Salt Length: 0x5E |
||||||
|
server9.req.sha384 |
||||||
|
Hash Algorithm: sha384 |
||||||
|
Mask Algorithm: mgf1 with sha384 |
||||||
|
Salt Length: 0x4E |
||||||
|
server9.req.sha512 |
||||||
|
Hash Algorithm: sha512 |
||||||
|
Mask Algorithm: mgf1 with sha512 |
||||||
|
Salt Length: 0x3E |
||||||
|
|
||||||
|
These CSRs are signed with a 2048-bit key. It appears that they are |
||||||
|
all using saltlen = keylen - hashlen - 2. |
||||||
|
|
||||||
|
### Possible courses of action |
||||||
|
|
||||||
|
There's no question about what to do with TLS (any version); the only question |
||||||
|
is about X.509 signature verification. Options include: |
||||||
|
|
||||||
|
1. Doing all verifications with `PSA_ALG_RSA_PSS_ANY_SALT` - while this |
||||||
|
wouldn't cause a concrete security issue, this would be non-compliant. |
||||||
|
2. Doing verifications with `PSA_ALG_RSA_PSS` when we're lucky and the encoded |
||||||
|
saltlen happens to match hashlen, and falling back to `ANY_SALT` otherwise. |
||||||
|
Same issue as with the previous point, except more contained. |
||||||
|
3. Reject all certificates with saltlen != hashlen. This includes all |
||||||
|
certificates generated with OpenSSL using the default parameters, so it's |
||||||
|
probably not acceptable. |
||||||
|
4. Request an extension to the PSA Crypto API and use one of the above options |
||||||
|
in the meantime. Such an extension seems inconvenient and not motivated by |
||||||
|
strong security arguments, so it's unclear whether it would be accepted. |
||||||
|
|
||||||
|
Limitations relevant for G2 (isolation of long-term secrets) |
||||||
|
============================================================ |
||||||
|
|
||||||
|
Currently none. |
@ -0,0 +1,516 @@ |
|||||||
|
This document explains the strategy that was used so far in starting the |
||||||
|
migration to PSA Crypto and mentions future perspectives and open questions. |
||||||
|
|
||||||
|
Goals |
||||||
|
===== |
||||||
|
|
||||||
|
Several benefits are expected from migrating to PSA Crypto: |
||||||
|
|
||||||
|
G1. Use PSA Crypto drivers when available. |
||||||
|
G2. Allow isolation of long-term secrets (for example, private keys). |
||||||
|
G3. Allow isolation of short-term secrets (for example, TLS session keys). |
||||||
|
G4. Have a clean, unified API for Crypto (retire the legacy API). |
||||||
|
G5. Code size: compile out our implementation when a driver is available. |
||||||
|
|
||||||
|
As of Mbed TLS 3.2, most of (G1) and all of (G2) is implemented when |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` is enabled. For (G2) to take effect, the application |
||||||
|
needs to be changed to use new APIs. For a more detailed account of what's |
||||||
|
implemented, see `docs/use-psa-crypto.md`, where new APIs are about (G2), and |
||||||
|
internal changes implement (G1). |
||||||
|
|
||||||
|
Generally speaking, the numbering above doesn't mean that each goal requires |
||||||
|
the preceding ones to be completed. |
||||||
|
|
||||||
|
Compile-time options |
||||||
|
==================== |
||||||
|
|
||||||
|
We currently have two compile-time options that are relevant to the migration: |
||||||
|
|
||||||
|
- `MBEDTLS_PSA_CRYPTO_C` - enabled by default, controls the presence of the PSA |
||||||
|
Crypto APIs. |
||||||
|
- `MBEDTLS_USE_PSA_CRYPTO` - disabled by default (enabled in "full" config), |
||||||
|
controls usage of PSA Crypto APIs to perform operations in X.509 and TLS |
||||||
|
(G1 above), as well as the availability of some new APIs (G2 above). |
||||||
|
- `PSA_CRYPTO_CONFIG` - disabled by default, supports builds with drivers and |
||||||
|
without the corresponding software implementation (G5 above). |
||||||
|
|
||||||
|
The reasons why `MBEDTLS_USE_PSA_CRYPTO` is optional and disabled by default |
||||||
|
are: |
||||||
|
- it's incompatible with `MBEDTLS_ECP_RESTARTABLE`; |
||||||
|
- to avoid a hard/default dependency of TLS, X.509 and PK on |
||||||
|
`MBEDTLS_PSA_CRYPTO_C`, for backward compatibility reasons: |
||||||
|
- When `MBEDTLS_PSA_CRYPTO_C` is enabled and used, applications need to call |
||||||
|
`psa_crypto_init()` before TLS/X.509 uses PSA functions. (This prevents us |
||||||
|
from even enabling the option by default.) |
||||||
|
- `MBEDTLS_PSA_CRYPTO_C` has a hard dependency on `MBEDTLS_ENTROPY_C || |
||||||
|
MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` but it's |
||||||
|
currently possible to compile TLS and X.509 without any of the options. |
||||||
|
Also, we can't just auto-enable `MBEDTLS_ENTROPY_C` as it doesn't build |
||||||
|
out of the box on all platforms, and even less |
||||||
|
`MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` as it requires a user-provided RNG |
||||||
|
function. |
||||||
|
|
||||||
|
The downside of this approach is that until we are able to make |
||||||
|
`MBDEDTLS_USE_PSA_CRYPTO` non-optional (always enabled), we have to maintain |
||||||
|
two versions of some parts of the code: one using PSA, the other using the |
||||||
|
legacy APIs. However, see next section for strategies that can lower that |
||||||
|
cost. The rest of this section explains the reasons for the |
||||||
|
incompatibilities mentioned above. |
||||||
|
|
||||||
|
At the time of writing (early 2022) it is unclear what could be done about the |
||||||
|
backward compatibility issues, and in particular if the cost of implementing |
||||||
|
solutions to these problems would be higher or lower than the cost of |
||||||
|
maintaining dual code paths until the next major version. (Note: these |
||||||
|
solutions would probably also solve other problems at the same time.) |
||||||
|
|
||||||
|
### `MBEDTLS_ECP_RESTARTABLE` |
||||||
|
|
||||||
|
Currently this option controls not only the presence of restartable APIs in |
||||||
|
the crypto library, but also their use in the TLS and X.509 layers. Since PSA |
||||||
|
Crypto does not support restartable operations, there's a clear conflict: the |
||||||
|
TLS and X.509 layers can't both use only PSA APIs and get restartable |
||||||
|
behaviour. |
||||||
|
|
||||||
|
Supporting this in PSA is on our roadmap and currently planned for end of |
||||||
|
2022, see <https://github.com/orgs/Mbed-TLS/projects/1#column-18883250>. |
||||||
|
|
||||||
|
It will then require follow-up work to make use of the new PSA API in |
||||||
|
PK/X.509/TLS in all places where we currently allow restartable operations. |
||||||
|
|
||||||
|
### Backward compatibility issues with making `MBEDTLS_USE_PSA_CRYPTO` always on |
||||||
|
|
||||||
|
1. Existing applications may not be calling `psa_crypto_init()` before using |
||||||
|
TLS, X.509 or PK. We can try to work around that by calling (the relevant |
||||||
|
part of) it ourselves under the hood as needed, but that would likely require |
||||||
|
splitting init between the parts that can fail and the parts that can't (see |
||||||
|
<https://github.com/ARM-software/psa-crypto-api/pull/536> for that). |
||||||
|
2. It's currently not possible to enable `MBEDTLS_PSA_CRYPTO_C` in |
||||||
|
configurations that don't have `MBEDTLS_ENTROPY_C`, and we can't just |
||||||
|
auto-enable the latter, as it won't build or work out of the box on all |
||||||
|
platforms. There are two kinds of things we'd need to do if we want to work |
||||||
|
around that: |
||||||
|
1. Make it possible to enable the parts of PSA Crypto that don't require an |
||||||
|
RNG (typically, public key operations, symmetric crypto, some key |
||||||
|
management functions (destroy etc)) in configurations that don't have |
||||||
|
`ENTROPY_C`. This requires going through the PSA code base to adjust |
||||||
|
dependencies. Risk: there may be annoying dependencies, some of which may be |
||||||
|
surprising. |
||||||
|
2. For operations that require an RNG, provide an alternative function |
||||||
|
accepting an explicit `f_rng` parameter (see #5238), that would be |
||||||
|
available in entropy-less builds. (Then code using those functions still needs |
||||||
|
to have one version using it, for entropy-less builds, and one version using |
||||||
|
the standard function, for driver support in build with entropy.) |
||||||
|
|
||||||
|
See <https://github.com/Mbed-TLS/mbedtls/issues/5156>. |
||||||
|
|
||||||
|
Taking advantage of the existing abstractions layers - or not |
||||||
|
============================================================= |
||||||
|
|
||||||
|
The Crypto library in Mbed TLS currently has 3 abstraction layers that offer |
||||||
|
algorithm-agnostic APIs for a class of algorithms: |
||||||
|
|
||||||
|
- MD for messages digests aka hashes (including HMAC) |
||||||
|
- Cipher for symmetric ciphers (included AEAD) |
||||||
|
- PK for asymmetric (aka public-key) cryptography (excluding key exchange) |
||||||
|
|
||||||
|
Note: key exchange (FFDH, ECDH) is not covered by an abstraction layer. |
||||||
|
|
||||||
|
These abstraction layers typically provide, in addition to the API for crypto |
||||||
|
operations, types and numerical identifiers for algorithms (for |
||||||
|
example `mbedtls_cipher_mode_t` and its values). The |
||||||
|
current strategy is to keep using those identifiers in most of the code, in |
||||||
|
particular in existing structures and public APIs, even when |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` is enabled. (This is not an issue for G1, G2, G3 |
||||||
|
above, and is only potentially relevant for G4.) |
||||||
|
|
||||||
|
The are multiple strategies that can be used regarding the place of those |
||||||
|
layers in the migration to PSA. |
||||||
|
|
||||||
|
Silently call to PSA from the abstraction layer |
||||||
|
----------------------------------------------- |
||||||
|
|
||||||
|
- Provide a new definition (conditionally on `USE_PSA_CRYPTO`) of wrapper |
||||||
|
functions in the abstraction layer, that calls PSA instead of the legacy |
||||||
|
crypto API. |
||||||
|
- Upside: changes contained to a single place, no need to change TLS or X.509 |
||||||
|
code anywhere. |
||||||
|
- Downside: tricky to implement if the PSA implementation is currently done on |
||||||
|
top of that layer (dependency loop). |
||||||
|
|
||||||
|
This strategy is currently (early 2022) used for all operations in the PK |
||||||
|
layer. |
||||||
|
|
||||||
|
This strategy is not very well suited to the Cipher layer, as the PSA |
||||||
|
implementation is currently done on top of that layer. |
||||||
|
|
||||||
|
This strategy will probably be used for some time for the PK layer, while we |
||||||
|
figure out what the future of that layer is: parts of it (parse/write, ECDSA |
||||||
|
signatures in the format that X.509 & TLS want) are not covered by PSA, so |
||||||
|
they will need to keep existing in some way. (Also, the PK layer is a good |
||||||
|
place for dispatching to either PSA or `mbedtls_xxx_restartable` while that |
||||||
|
part is not covered by PSA yet, if we decide to do that.) |
||||||
|
|
||||||
|
Replace calls for each operation |
||||||
|
-------------------------------- |
||||||
|
|
||||||
|
- For every operation that's done through this layer in TLS or X.509, just |
||||||
|
replace function call with calls to PSA (conditionally on `USE_PSA_CRYPTO`) |
||||||
|
- Upside: conceptually simple, and if the PSA implementation is currently done |
||||||
|
on top of that layer, avoids concerns about dependency loops. |
||||||
|
- Upside: opens the door to building TLS/X.509 without that layer, saving some |
||||||
|
code size. |
||||||
|
- Downside: TLS/X.509 code has to be done for each operation. |
||||||
|
|
||||||
|
This strategy is currently (early 2022) used for the MD layer and the Cipher |
||||||
|
layer. |
||||||
|
|
||||||
|
Opt-in use of PSA from the abstraction layer |
||||||
|
-------------------------------------------- |
||||||
|
|
||||||
|
- Provide a new way to set up a context that causes operations on that context |
||||||
|
to be done via PSA. |
||||||
|
- Upside: changes mostly contained in one place, TLS/X.509 code only needs to |
||||||
|
be changed when setting up the context, but not when using it. In |
||||||
|
particular, no changes to/duplication of existing public APIs that expect a |
||||||
|
key to be passed as a context of this layer (eg, `mbedtls_pk_context`). |
||||||
|
- Upside: avoids dependency loop when PSA implemented on top of that layer. |
||||||
|
- Downside: when the context is typically set up by the application, requires |
||||||
|
changes in application code. |
||||||
|
|
||||||
|
This strategy is not useful when no context is used, for example with the |
||||||
|
one-shot function `mbedtls_md()`. |
||||||
|
|
||||||
|
There are two variants of this strategy: one where using the new setup |
||||||
|
function also allows for key isolation (the key is only held by PSA, |
||||||
|
supporting both G1 and G2 in that area), and one without isolation (the key is |
||||||
|
still stored outside of PSA most of the time, supporting only G1). |
||||||
|
|
||||||
|
This strategy, with support for key isolation, is currently (early 2022) used for |
||||||
|
private-key operations in the PK layer - see `mbedtls_pk_setup_opaque()`. This |
||||||
|
allows use of PSA-held private ECDSA keys in TLS and X.509 with no change to |
||||||
|
the TLS/X.509 code, but a contained change in the application. |
||||||
|
|
||||||
|
This strategy, without key isolation, was also previously used (until 3.1 |
||||||
|
included) in the Cipher layer - see `mbedtls_cipher_setup_psa()`. This allowed |
||||||
|
use of PSA for cipher operations in TLS with no change to the application |
||||||
|
code, and a contained change in TLS code. (It only supported a subset of |
||||||
|
ciphers.) |
||||||
|
|
||||||
|
Note: for private key operations in the PK layer, both the "silent" and the |
||||||
|
"opt-in" strategy can apply, and can complement each other, as one provides |
||||||
|
support for key isolation, but at the (unavoidable) code of change in |
||||||
|
application code, while the other requires no application change to get |
||||||
|
support for drivers, but fails to provide isolation support. |
||||||
|
|
||||||
|
Summary |
||||||
|
------- |
||||||
|
|
||||||
|
Strategies currently (early 2022) used with each abstraction layer: |
||||||
|
|
||||||
|
- PK (for G1): silently call PSA |
||||||
|
- PK (for G2): opt-in use of PSA (new key type) |
||||||
|
- Cipher (G1): replace calls at each call site |
||||||
|
- MD (G1): replace calls at each call site |
||||||
|
|
||||||
|
|
||||||
|
Supporting builds with drivers without the software implementation |
||||||
|
================================================================== |
||||||
|
|
||||||
|
This section presents a plan towards G5: save code size by compiling out our |
||||||
|
software implementation when a driver is available. |
||||||
|
|
||||||
|
Additionally, we want to save code size by compiling out the |
||||||
|
abstractions layers that we are not using when `MBEDTLS_USE_PSA_CRYPTO` is |
||||||
|
enabled (see previous section): MD and Cipher. |
||||||
|
|
||||||
|
Let's expand a bit on the definition of the goal: in such a configuration |
||||||
|
(driver used, software implementation and abstraction layer compiled out), |
||||||
|
we want: |
||||||
|
|
||||||
|
a. the library to build in a reasonably-complete configuration, |
||||||
|
b. with all tests passing, |
||||||
|
c. and no more tests skipped than the same configuration with software |
||||||
|
implementation. |
||||||
|
|
||||||
|
Criterion (c) ensures not only test coverage, but that driver-based builds are |
||||||
|
at feature parity with software-based builds. |
||||||
|
|
||||||
|
We can roughly divide the work needed to get there in the following steps: |
||||||
|
|
||||||
|
0. Have a working driver interface for the algorithms we want to replace. |
||||||
|
1. Have users of these algorithms call to PSA, not the legacy API, for all |
||||||
|
operations. (This is G1, and for PK, X.509 and TLS this is controlled by |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO`.) This needs to be done in the library and tests. |
||||||
|
2. Have users of these algorithms not depend on the legacy API for information |
||||||
|
management (getting a size for a given algorithm, etc.) |
||||||
|
3. Adapt compile-time guards used to query availability of a given algorithm; |
||||||
|
this needs to be done in the library (for crypto operations and data) and |
||||||
|
tests. |
||||||
|
|
||||||
|
Note: the first two steps enable use of drivers, but not by themselves removal |
||||||
|
of the software implementation. |
||||||
|
|
||||||
|
Note: the fact that step 1 is not achieved for all of libmbedcrypto (see |
||||||
|
below) is the reason why criterion (a) has "a reasonably-complete |
||||||
|
configuration", to allow working around internal crypto dependencies when |
||||||
|
working on other parts such as X.509 and TLS - for example, a configuration |
||||||
|
without RSA PKCS#1 v2.1 still allows reasonable use of X.509 and TLS. |
||||||
|
|
||||||
|
Note: this is a conceptual division that will sometimes translate to how the |
||||||
|
work is divided into PRs, sometimes not. For example, in situations where it's |
||||||
|
not possible to achieve good test coverage at the end of step 1 or step 2, it |
||||||
|
is preferable to group with the next step(s) in the same PR until good test |
||||||
|
coverage can be reached. |
||||||
|
|
||||||
|
**Status as of Mbed TLS 3.2:** |
||||||
|
|
||||||
|
- Step 0 is achieved for most algorithms, with only a few gaps remaining. |
||||||
|
- Step 1 is achieved for most of PK, X.509, and TLS when |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` is enabled with only a few gaps remaining (see |
||||||
|
docs/use-psa-crypto.md). |
||||||
|
- Step 1 is not achieved for a lot of the crypto library including the PSA |
||||||
|
core. For example, `entropy.c` calls the legacy API |
||||||
|
`mbedtls_sha256` (or `mbedtls_sha512` optionally); `hmac_drbg.c` calls the |
||||||
|
legacy API `mbedtls_md` and `ctr_drbg.c` calls the legacy API `mbedtls_aes`; |
||||||
|
the PSA core depends on the entropy module and at least one of the DRBG |
||||||
|
modules (unless `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is used). Further, several |
||||||
|
crypto modules have similar issues, for example RSA PKCS#1 v2.1 calls |
||||||
|
`mbedtls_md` directly. |
||||||
|
- Step 2 is achieved for most of X.509 and TLS (same gaps as step 1) when |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` is enabled - this was tasks like #5795, #5796, |
||||||
|
#5797. It is being done in PK and RSA PKCS#1 v1.5 by PR #6065. |
||||||
|
- Step 3 was mostly not started at all before 3.2; it is being done for PK by |
||||||
|
PR #6065. |
||||||
|
|
||||||
|
**Strategy for step 1:** |
||||||
|
|
||||||
|
Regarding PK, X.509, and TLS, this is mostly achieved with only a few gaps. |
||||||
|
(The strategy was outlined in the previous section.) |
||||||
|
|
||||||
|
Regarding libmbedcrypto, outside of the RNG subsystem, for modules that |
||||||
|
currently depend on other legacy crypto modules, this can be achieved without |
||||||
|
backwards compatibility issues, by using the software implementation if |
||||||
|
available, and "falling back" to PSA only if it's not. The compile-time |
||||||
|
dependency changes from the current one (say, `MD_C` or `AES_C`) to "the |
||||||
|
previous dependency OR PSA Crypto with needed algorithms". When building |
||||||
|
without software implementation, users need to call `psa_crypto_init()` before |
||||||
|
calling any function from these modules. This condition does not constitute a |
||||||
|
break of backwards compatibility, as it was previously impossible to build in |
||||||
|
those configurations, and in configurations were the build was possible, |
||||||
|
application code keeps working unchanged. An work-in-progress example of |
||||||
|
applying this strategy, for RSA PKCS#1 v2.1, is here: |
||||||
|
<https://github.com/Mbed-TLS/mbedtls/pull/6141> |
||||||
|
|
||||||
|
There is a problem with the modules used for the PSA RNG, as currently the RNG |
||||||
|
is initialized before drivers and the key store. This part will need further |
||||||
|
study, but in the meantime we can proceed with everything that's not the |
||||||
|
entropy module of one of the DRBG modules, and that does not depend on one of |
||||||
|
those modules. |
||||||
|
|
||||||
|
**Strategy for step 2:** |
||||||
|
|
||||||
|
The most satisfying situation here is when we can just use the PSA Crypto API |
||||||
|
for information management as well. However sometimes it may not be |
||||||
|
convenient, for example in parts of the code that accept old-style identifiers |
||||||
|
(such as `mbedtls_md_type_t`) in their API and can't assume PSA to be |
||||||
|
compiled in (such as `rsa.c`). |
||||||
|
|
||||||
|
It is suggested that, as a temporary solution until we clean this up |
||||||
|
later when removing the legacy API including its identifiers (G4), we may |
||||||
|
occasionally use ad-hoc internal functions, such as the ones introduced by PR |
||||||
|
6065 in `library/hash_info.[ch]`. |
||||||
|
|
||||||
|
An alternative would be to have two different code paths depending on whether |
||||||
|
`MBEDTLS_PSA_CRYPTO_C` is defined or not. However this is not great for |
||||||
|
readability or testability. |
||||||
|
|
||||||
|
**Strategy for step 3:** |
||||||
|
|
||||||
|
There are currently two (complementary) ways for crypto-using code to check if a |
||||||
|
particular algorithm is supported: using `MBEDTLS_xxx` macros, and using |
||||||
|
`PSA_WANT_xxx` macros. For example, PSA-based code that want to use SHA-256 |
||||||
|
will check for `PSA_WANT_ALG_SHA_256`, while legacy-based code that wants to |
||||||
|
use SHA-256 will check for `MBEDTLS_SHA256_C` if using the `mbedtls_sha256` |
||||||
|
API, or for `MBEDTLS_MD_C && MBEDTLS_SHA256_C` if using the `mbedtls_md` API. |
||||||
|
|
||||||
|
Code that obeys `MBEDTLS_USE_PSA_CRYPTO` will want to use one of the two |
||||||
|
dependencies above depending on whether `MBEDTLS_USE_PSA_CRYPTO` is defined: |
||||||
|
if it is, the code want the algorithm available in PSA, otherwise, it wants it |
||||||
|
available via the legacy API(s) is it using (MD and/or low-level). |
||||||
|
|
||||||
|
The strategy for steps 1 and 2 above will introduce new situations: code that |
||||||
|
currently compute hashes using MD (resp. a low-level hash module) will gain |
||||||
|
the ability to "fall back" to using PSA if the legacy dependency isn't |
||||||
|
available. Data related to a certain hash (OID, sizes, translations) should |
||||||
|
only be included in the build if it is possible to use that hash in some way. |
||||||
|
|
||||||
|
In order to cater to these new needs, new families of macros are introduced in |
||||||
|
`legacy_or_psa.h`, see its documentation for details. |
||||||
|
|
||||||
|
It should be noted that there are currently: |
||||||
|
- too many different ways of computing a hash (low-level, MD, PSA); |
||||||
|
- too many different ways to configure the library that influence which of |
||||||
|
these ways is available and will be used (`MBEDTLS_USE_PSA_CRYPTO`, |
||||||
|
`MBEDTLS_PSA_CRYPTO_CONFIG`, `mbedtls_config.h` + `psa/crypto_config.h`). |
||||||
|
|
||||||
|
As a result, we need more families of dependency macros than we'd like to. |
||||||
|
This is a temporary situation until we move to a place where everything is |
||||||
|
based on PSA Crypto. In the meantime, long and explicit names where chosen for |
||||||
|
the new macros in the hope of avoiding confusion. |
||||||
|
|
||||||
|
Note: the new macros supplement but do not replace the existing macros: |
||||||
|
- code that always uses PSA Crypto (for example, code specific to TLS 1.3) |
||||||
|
should use `PSA_WANT_xxx`; |
||||||
|
- code that always uses the legacy API (for example, crypto modules that have |
||||||
|
not undergone step 1 yet) should use `MBEDTLS_xxx_C`; |
||||||
|
- code that may use one of the two APIs, either based on |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` (X.509, TLS 1.2, shared between TLS 1.2 and 1.3), |
||||||
|
or based on availability (crypto modules after step 1), should use one of |
||||||
|
the new macros from `legacy_or_psa.h`. |
||||||
|
|
||||||
|
Executing step 3 will mostly consist of using the right dependency macros in |
||||||
|
the right places (once the previous steps are done). |
||||||
|
|
||||||
|
**Note on testing** |
||||||
|
|
||||||
|
Since supporting driver-only builds is not about adding features, but about |
||||||
|
supporting existing features in new types of builds, testing will not involve |
||||||
|
adding cases to the test suites, but instead adding new components in `all.sh` |
||||||
|
that build and run tests in newly-supported configurations. For example, if |
||||||
|
we're making some part of the library work with hashes provided only by |
||||||
|
drivers when `MBEDTLS_USE_PSA_CRYPTO` is defined, there should be a place in |
||||||
|
`all.sh` that builds and run tests in such a configuration. |
||||||
|
|
||||||
|
There is however a risk, especially in step 3 where we change how dependencies |
||||||
|
are expressed (sometimes in bulk), to get things wrong in a way that would |
||||||
|
result in more tests being skipped, which is easy to miss. Care must be |
||||||
|
taken to ensure this does not happen. The following criteria can be used: |
||||||
|
|
||||||
|
- the sets of tests skipped in the default config and the full config must be |
||||||
|
the same before and after the PR that implements step 3; |
||||||
|
- the set of tests skipped in the driver-only build is the same as in an |
||||||
|
equivalent software-based configuration, or the difference is small enough, |
||||||
|
justified, and a github issue is created to track it. |
||||||
|
|
||||||
|
Note that the favourable case is when the number of tests skipped is 0 in the |
||||||
|
driver-only build. In other cases, analysis of the outcome files is needed, |
||||||
|
see the example script `outcome-analysis.sh` in the same directory. |
||||||
|
|
||||||
|
|
||||||
|
Migrating away from the legacy API |
||||||
|
================================== |
||||||
|
|
||||||
|
This section briefly introduces questions and possible plans towards G4, |
||||||
|
mainly as they relate to choices in previous stages. |
||||||
|
|
||||||
|
The role of the PK/Cipher/MD APIs in user migration |
||||||
|
--------------------------------------------------- |
||||||
|
|
||||||
|
We're currently taking advantage of the existing PK layer in order |
||||||
|
to reduce the number of places where library code needs to be changed. It's |
||||||
|
only natural to consider using the same strategy (with the PK, MD and Cipher |
||||||
|
layers) for facilitating migration of application code. |
||||||
|
|
||||||
|
Note: a necessary first step for that would be to make sure PSA is no longer |
||||||
|
implemented of top of the concerned layers |
||||||
|
|
||||||
|
### Zero-cost compatibility layer? |
||||||
|
|
||||||
|
The most favourable case is if we can have a zero-cost abstraction (no |
||||||
|
runtime, RAM usage or code size penalty), for example just a bunch of |
||||||
|
`#define`s, essentially mapping `mbedtls_` APIs to their `psa_` equivalent. |
||||||
|
|
||||||
|
Unfortunately that's unlikely to fully work. For example, the MD layer uses the |
||||||
|
same context type for hashes and HMACs, while the PSA API (rightfully) has |
||||||
|
distinct operation types. Similarly, the Cipher layer uses the same context |
||||||
|
type for unauthenticated and AEAD ciphers, which again the PSA API |
||||||
|
distinguishes. |
||||||
|
|
||||||
|
It is unclear how much value, if any, a zero-cost compatibility layer that's |
||||||
|
incomplete (for example, for MD covering only hashes, or for Cipher covering |
||||||
|
only AEAD) or differs significantly from the existing API (for example, |
||||||
|
introducing new context types) would provide to users. |
||||||
|
|
||||||
|
### Low-cost compatibility layers? |
||||||
|
|
||||||
|
Another possibility is to keep most or all of the existing API for the PK, MD |
||||||
|
and Cipher layers, implemented on top of PSA, aiming for the lowest possible |
||||||
|
cost. For example, `mbedtls_md_context_t` would be defined as a (tagged) union |
||||||
|
of `psa_hash_operation_t` and `psa_mac_operation_t`, then `mbedtls_md_setup()` |
||||||
|
would initialize the correct part, and the rest of the functions be simple |
||||||
|
wrappers around PSA functions. This would vastly reduce the complexity of the |
||||||
|
layers compared to the existing (no need to dispatch through function |
||||||
|
pointers, just call the corresponding PSA API). |
||||||
|
|
||||||
|
Since this would still represent a non-zero cost, not only in terms of code |
||||||
|
size, but also in terms of maintenance (testing, etc.) this would probably |
||||||
|
be a temporary solution: for example keep the compatibility layers in 4.0 (and |
||||||
|
make them optional), but remove them in 5.0. |
||||||
|
|
||||||
|
Again, this provides the most value to users if we can manage to keep the |
||||||
|
existing API unchanged. Their might be conflicts between this goal and that of |
||||||
|
reducing the cost, and judgment calls may need to be made. |
||||||
|
|
||||||
|
Note: when it comes to holding public keys in the PK layer, depending on how |
||||||
|
the rest of the code is structured, it may be worth holding the key data in |
||||||
|
memory controlled by the PK layer as opposed to a PSA key slot, moving it to a |
||||||
|
slot only when needed (see current `ecdsa_verify_wrap` when |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` is defined) For example, when parsing a large |
||||||
|
number, N, of X.509 certificates (for example the list of trusted roots), it |
||||||
|
might be undesirable to use N PSA key slots for their public keys as long as |
||||||
|
the certs are loaded. OTOH, this could also be addressed by merging the "X.509 |
||||||
|
parsing on-demand" (#2478), and then the public key data would be held as |
||||||
|
bytes in the X.509 CRT structure, and only moved to a PK context / PSA slot |
||||||
|
when it's actually used. |
||||||
|
|
||||||
|
Note: the PK layer actually consists of two relatively distinct parts: crypto |
||||||
|
operations, which will be covered by PSA, and parsing/writing (exporting) |
||||||
|
from/to various formats, which is currently not fully covered by the PSA |
||||||
|
Crypto API. |
||||||
|
|
||||||
|
### Algorithm identifiers and other identifiers |
||||||
|
|
||||||
|
It should be easy to provide the user with a bunch of `#define`s for algorithm |
||||||
|
identifiers, for example `#define MBEDTLS_MD_SHA256 PSA_ALG_SHA_256`; most of |
||||||
|
those would be in the MD, Cipher and PK compatibility layers mentioned above, |
||||||
|
but there might be some in other modules that may be worth considering, for |
||||||
|
example identifiers for elliptic curves. |
||||||
|
|
||||||
|
### Lower layers |
||||||
|
|
||||||
|
Generally speaking, we would retire all of the low-level, non-generic modules, |
||||||
|
such as AES, SHA-256, RSA, DHM, ECDH, ECP, bignum, etc, without providing |
||||||
|
compatibility APIs for them. People would be encouraged to switch to the PSA |
||||||
|
API. (The compatibility implementation of the existing PK, MD, Cipher APIs |
||||||
|
would mostly benefit people who already used those generic APis rather than |
||||||
|
the low-level, alg-specific ones.) |
||||||
|
|
||||||
|
### APIs in TLS and X.509 |
||||||
|
|
||||||
|
Public APIs in TLS and X.509 may be affected by the migration in at least two |
||||||
|
ways: |
||||||
|
|
||||||
|
1. APIs that rely on a legacy `mbedtls_` crypto type: for example |
||||||
|
`mbedtls_ssl_conf_own_cert()` to configure a (certificate and the |
||||||
|
associated) private key. Currently the private key is passed as a |
||||||
|
`mbedtls_pk_context` object, which would probably change to a `psa_key_id_t`. |
||||||
|
Since some users would probably still be using the compatibility PK layer, it |
||||||
|
would need a way to easily extract the PSA key ID from the PK context. |
||||||
|
|
||||||
|
2. APIs the accept list of identifiers: for example |
||||||
|
`mbedtls_ssl_conf_curves()` taking a list of `mbedtls_ecp_group_id`s. This |
||||||
|
could be changed to accept a list of pairs (`psa_ecc_family_t`, size) but we |
||||||
|
should probably take this opportunity to move to a identifier independent from |
||||||
|
the underlying crypto implementation and use TLS-specific identifiers instead |
||||||
|
(based on IANA values or custom enums), as is currently done in the new |
||||||
|
`mbedtls_ssl_conf_groups()` API, see #4859). |
||||||
|
|
||||||
|
Testing |
||||||
|
------- |
||||||
|
|
||||||
|
An question that needs careful consideration when we come around to removing |
||||||
|
the low-level crypto APIs and making PK, MD and Cipher optional compatibility |
||||||
|
layers is to be sure to preserve testing quality. A lot of the existing test |
||||||
|
cases use the low level crypto APIs; we would need to either keep using that |
||||||
|
API for tests, or manually migrate tests to the PSA Crypto API. Perhaps a |
||||||
|
combination of both, perhaps evolving gradually over time. |
@ -0,0 +1,58 @@ |
|||||||
|
#!/bin/sh |
||||||
|
# |
||||||
|
# Copyright The Mbed TLS Contributors |
||||||
|
# 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. |
||||||
|
# |
||||||
|
# Purpose |
||||||
|
# |
||||||
|
# Show symbols in the X.509 and TLS libraries that are defined in another |
||||||
|
# libmbedtlsXXX.a library. This is usually done to list Crypto dependencies. |
||||||
|
# |
||||||
|
# Usage: |
||||||
|
# - build the library with debug symbols and the config you're interested in |
||||||
|
# (default, full minus MBEDTLS_USE_PSA_CRYPTO, full, etc.) |
||||||
|
# - run this script with the name of your config as the only argument |
||||||
|
|
||||||
|
set -eu |
||||||
|
|
||||||
|
# list mbedtls_ symbols of a given type in a static library |
||||||
|
syms() { |
||||||
|
TYPE="$1" |
||||||
|
FILE="$2" |
||||||
|
|
||||||
|
nm "$FILE" | sed -n "s/[0-9a-f ]*${TYPE} \(mbedtls_.*\)/\1/p" | sort -u |
||||||
|
} |
||||||
|
|
||||||
|
# create listings for the given library |
||||||
|
list() { |
||||||
|
NAME="$1" |
||||||
|
FILE="library/libmbed${NAME}.a" |
||||||
|
PREF="${CONFIG}-$NAME" |
||||||
|
|
||||||
|
syms '[TRrD]' $FILE > ${PREF}-defined |
||||||
|
syms U $FILE > ${PREF}-unresolved |
||||||
|
|
||||||
|
diff ${PREF}-defined ${PREF}-unresolved \ |
||||||
|
| sed -n 's/^> //p' > ${PREF}-external |
||||||
|
sed 's/mbedtls_\([^_]*\).*/\1/' ${PREF}-external \ |
||||||
|
| uniq -c | sort -rn > ${PREF}-modules |
||||||
|
|
||||||
|
rm ${PREF}-defined ${PREF}-unresolved |
||||||
|
} |
||||||
|
|
||||||
|
CONFIG="${1:-unknown}" |
||||||
|
|
||||||
|
list x509 |
||||||
|
list tls |
@ -0,0 +1,99 @@ |
|||||||
|
Testing strategy for `MBEDTLS_USE_PSA_CRYPTO` |
||||||
|
============================================= |
||||||
|
|
||||||
|
This document records the testing strategy used so far in implementing |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO`. |
||||||
|
|
||||||
|
|
||||||
|
General considerations |
||||||
|
---------------------- |
||||||
|
|
||||||
|
There needs to be at least one build in `all.sh` that enables |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` and runs the full battery of tests; currently that's |
||||||
|
ensured by the fact that `scripts/config.py full` enables |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO`. There needs to be at least one build with |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` disabled (as long as it's optional); currently that's |
||||||
|
ensured by the fact that it's disabled in the default config. |
||||||
|
|
||||||
|
Generally, code review is enough to ensure that PSA APIs are indeed used where |
||||||
|
they should be when `MBEDTLS_USE_PSA_CRYPTO` is enabled. |
||||||
|
|
||||||
|
However, when it comes to TLS, we also have the option of using debug messages |
||||||
|
to confirm which code path is taken. This is generally unnecessary, except when |
||||||
|
a decision is made at run-time about whether to use the PSA or legacy code |
||||||
|
path. (For example, for record protection, previously (until 3.1), some ciphers were supported |
||||||
|
via PSA while some others weren't, with a run-time fallback. In this case, it's |
||||||
|
good to have a debug message checked by the test case to confirm that the |
||||||
|
right decision was made at run-time, i. e. that we didn't use the fallback for |
||||||
|
ciphers that are supposed to be supported.) |
||||||
|
|
||||||
|
|
||||||
|
New APIs meant for application use |
||||||
|
---------------------------------- |
||||||
|
|
||||||
|
For example, `mbedtls_pk_setup_opaque()` is meant to be used by applications |
||||||
|
in order to create PK contexts that can then be passed to existing TLS and |
||||||
|
X.509 APIs (which remain unchanged). |
||||||
|
|
||||||
|
In that case, we want: |
||||||
|
|
||||||
|
- unit testing of the new API and directly-related APIs - for example: |
||||||
|
- in `test_suite_pk` we have a new test function `pk_psa_utils` that exercises |
||||||
|
`mbedtls_pk_setup_opaque()` and checks that various utility functions |
||||||
|
(`mbedtls_pk_get_type()` etc.) work and the functions that are expected to |
||||||
|
fail (`mbedtls_pk_verify()` etc) return the expected error. |
||||||
|
- in `test_suite_pk` we modified the existing `pk_psa_sign` test function to |
||||||
|
check that signature generation works as expected |
||||||
|
- in `test_suite_pkwrite` we should have a new test function checking that |
||||||
|
exporting (writing out) the public part of the key works as expected and |
||||||
|
that exporting the private key fails as expected. |
||||||
|
- integration testing of the new API with each existing API which should |
||||||
|
accepts a context created this way - for example: |
||||||
|
- in `programs/ssl/ssl_client2` a new option `key_opaque` that causes the |
||||||
|
new API to be used, and one or more tests in `ssl-opt.sh` using that. |
||||||
|
(We should have the same server-side.) |
||||||
|
- in `test_suite_x509write` we have a new test function |
||||||
|
`x509_csr_check_opaque()` checking integration of the new API with the |
||||||
|
existing `mbedtls_x509write_csr_set_key()`. (And also |
||||||
|
`mbedtls_x509write_crt_set_issuer_key()` since #5710.) |
||||||
|
|
||||||
|
For some APIs, for example with `mbedtls_ssl_conf_psk_opaque()`, testing in |
||||||
|
`test_suite_ssl` was historically not possible, so we only have testing in |
||||||
|
`ssl-opt.sh`. |
||||||
|
|
||||||
|
New APIs meant for internal use |
||||||
|
------------------------------- |
||||||
|
|
||||||
|
For example, `mbedtls_cipher_setup_psa()` (no longer used, soon to be |
||||||
|
deprecated - #5261) was meant to be used by the TLS layer, but probably not |
||||||
|
directly by applications. |
||||||
|
|
||||||
|
In that case, we want: |
||||||
|
|
||||||
|
- unit testing of the new API and directly-related APIs - for example: |
||||||
|
- in `test_suite_cipher`, the existing test functions `auth_crypt_tv` and |
||||||
|
`test_vec_crypt` gained a new parameter `use_psa` and corresponding test |
||||||
|
cases |
||||||
|
- integration testing: |
||||||
|
- usually already covered by existing tests for higher-level modules: |
||||||
|
- for example simple use of `mbedtls_cipher_setup_psa()` in TLS is already |
||||||
|
covered by running the existing TLS tests in a build with |
||||||
|
`MBEDTLS_USA_PSA_CRYPTO` enabled |
||||||
|
- however if use of the new API in higher layers involves more logic that |
||||||
|
use of the old API, specific integrations test may be required |
||||||
|
- for example, the logic to fall back from `mbedtls_cipher_setup_psa()` to |
||||||
|
`mbedtls_cipher_setup()` in TLS is tested by `run_test_psa` in |
||||||
|
`ssl-opt.sh`. |
||||||
|
|
||||||
|
Internal changes |
||||||
|
---------------- |
||||||
|
|
||||||
|
For example, use of PSA to compute the TLS 1.2 PRF. |
||||||
|
|
||||||
|
Changes in this category rarely require specific testing, as everything should |
||||||
|
be already be covered by running the existing tests in a build with |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` enabled; however we need to make sure the existing |
||||||
|
test have sufficient coverage, and improve them if necessary. |
||||||
|
|
||||||
|
However, if additional logic is involved, or there are run-time decisions about |
||||||
|
whether to use the PSA or legacy code paths, specific tests might be in order. |
@ -0,0 +1,133 @@ |
|||||||
|
# Mbed Crypto driver interface test strategy |
||||||
|
|
||||||
|
This document describes the test strategy for the driver interfaces in Mbed Crypto. Mbed Crypto has interfaces for secure element drivers, accelerator drivers and entropy drivers. This document is about testing Mbed Crypto itself; testing drivers is out of scope. |
||||||
|
|
||||||
|
The driver interfaces are standardized through PSA Cryptography functional specifications. |
||||||
|
|
||||||
|
## Secure element driver interface testing |
||||||
|
|
||||||
|
### Secure element driver interfaces |
||||||
|
|
||||||
|
#### Opaque driver interface |
||||||
|
|
||||||
|
The [unified driver interface](../../proposed/psa-driver-interface.md) supports both transparent drivers (for accelerators) and opaque drivers (for secure elements). |
||||||
|
|
||||||
|
Drivers exposing this interface need to be registered at compile time by declaring their JSON description file. |
||||||
|
|
||||||
|
#### Dynamic secure element driver interface |
||||||
|
|
||||||
|
The dynamic secure element driver interface (SE interface for short) is defined by [`psa/crypto_se_driver.h`](../../../include/psa/crypto_se_driver.h). This is an interface between Mbed Crypto and one or more third-party drivers. |
||||||
|
|
||||||
|
The SE interface consists of one function provided by Mbed Crypto (`psa_register_se_driver`) and many functions that drivers must implement. To make a driver usable by Mbed Crypto, the initialization code must call `psa_register_se_driver` with a structure that describes the driver. The structure mostly contains function pointers, pointing to the driver's methods. All calls to a driver function are triggered by a call to a PSA crypto API function. |
||||||
|
|
||||||
|
### SE driver interface unit tests |
||||||
|
|
||||||
|
This section describes unit tests that must be implemented to validate the secure element driver interface. Note that a test case may cover multiple requirements; for example a “good case” test can validate that the proper function is called, that it receives the expected inputs and that it produces the expected outputs. |
||||||
|
|
||||||
|
Many SE driver interface unit tests could be covered by running the existing API tests with a key in a secure element. |
||||||
|
|
||||||
|
#### SE driver registration |
||||||
|
|
||||||
|
This applies to dynamic drivers only. |
||||||
|
|
||||||
|
* Test `psa_register_se_driver` with valid and with invalid arguments. |
||||||
|
* Make at least one failing call to `psa_register_se_driver` followed by a successful call. |
||||||
|
* Make at least one test that successfully registers the maximum number of drivers and fails to register one more. |
||||||
|
|
||||||
|
#### Dispatch to SE driver |
||||||
|
|
||||||
|
For each API function that can lead to a driver call (more precisely, for each driver method call site, but this is practically equivalent): |
||||||
|
|
||||||
|
* Make at least one test with a key in a secure element that checks that the driver method is called. A few API functions involve multiple driver methods; these should validate that all the expected driver methods are called. |
||||||
|
* Make at least one test with a key that is not in a secure element that checks that the driver method is not called. |
||||||
|
* Make at least one test with a key in a secure element with a driver that does not have the requisite method (i.e. the method pointer is `NULL`) but has the substructure containing that method, and check that the return value is `PSA_ERROR_NOT_SUPPORTED`. |
||||||
|
* Make at least one test with a key in a secure element with a driver that does not have the substructure containing that method (i.e. the pointer to the substructure is `NULL`), and check that the return value is `PSA_ERROR_NOT_SUPPORTED`. |
||||||
|
* At least one test should register multiple drivers with a key in each driver and check that the expected driver is called. This does not need to be done for all operations (use a white-box approach to determine if operations may use different code paths to choose the driver). |
||||||
|
* At least one test should register the same driver structure with multiple lifetime values and check that the driver receives the expected lifetime value. |
||||||
|
|
||||||
|
Some methods only make sense as a group (for example a driver that provides the MAC methods must provide all or none). In those cases, test with all of them null and none of them null. |
||||||
|
|
||||||
|
#### SE driver inputs |
||||||
|
|
||||||
|
For each API function that can lead to a driver call (more precisely, for each driver method call site, but this is practically equivalent): |
||||||
|
|
||||||
|
* Wherever the specification guarantees parameters that satisfy certain preconditions, check these preconditions whenever practical. |
||||||
|
* If the API function can take parameters that are invalid and must not reach the driver, call the API function with such parameters and verify that the driver method is not called. |
||||||
|
* Check that the expected inputs reach the driver. This may be implicit in a test that checks the outputs if the only realistic way to obtain the correct outputs is to start from the expected inputs (as is often the case for cryptographic material, but not for metadata). |
||||||
|
|
||||||
|
#### SE driver outputs |
||||||
|
|
||||||
|
For each API function that leads to a driver call, call it with parameters that cause a driver to be invoked and check how Mbed Crypto handles the outputs. |
||||||
|
|
||||||
|
* Correct outputs. |
||||||
|
* Incorrect outputs such as an invalid output length. |
||||||
|
* Expected errors (e.g. `PSA_ERROR_INVALID_SIGNATURE` from a signature verification method). |
||||||
|
* Unexpected errors. At least test that if the driver returns `PSA_ERROR_GENERIC_ERROR`, this is propagated correctly. |
||||||
|
|
||||||
|
Key creation functions invoke multiple methods and need more complex error handling: |
||||||
|
|
||||||
|
* Check the consequence of errors detected at each stage (slot number allocation or validation, key creation method, storage accesses). |
||||||
|
* Check that the storage ends up in the expected state. At least make sure that no intermediate file remains after a failure. |
||||||
|
|
||||||
|
#### Persistence of SE keys |
||||||
|
|
||||||
|
The following tests must be performed at least one for each key creation method (import, generate, ...). |
||||||
|
|
||||||
|
* Test that keys in a secure element survive `psa_close_key(); psa_open_key()`. |
||||||
|
* Test that keys in a secure element survive `mbedtls_psa_crypto_free(); psa_crypto_init()`. |
||||||
|
* Test that the driver's persistent data survives `mbedtls_psa_crypto_free(); psa_crypto_init()`. |
||||||
|
* Test that `psa_destroy_key()` does not leave any trace of the key. |
||||||
|
|
||||||
|
#### Resilience for SE drivers |
||||||
|
|
||||||
|
Creating or removing a key in a secure element involves multiple storage modifications (M<sub>1</sub>, ..., M<sub>n</sub>). If the operation is interrupted by a reset at any point, it must be either rolled back or completed. |
||||||
|
|
||||||
|
* For each potential interruption point (before M<sub>1</sub>, between M<sub>1</sub> and M<sub>2</sub>, ..., after M<sub>n</sub>), call `mbedtls_psa_crypto_free(); psa_crypto_init()` at that point and check that this either rolls back or completes the operation that was started. |
||||||
|
* This must be done for each key creation method and for key destruction. |
||||||
|
* This must be done for each possible flow, including error cases (e.g. a key creation that fails midway due to `OUT_OF_MEMORY`). |
||||||
|
* The recovery during `psa_crypto_init` can itself be interrupted. Test those interruptions too. |
||||||
|
* Two things need to be tested: the key that is being created or destroyed, and the driver's persistent storage. |
||||||
|
* Check both that the storage has the expected content (this can be done by e.g. using a key that is supposed to be present) and does not have any unexpected content (for keys, this can be done by checking that `psa_open_key` fails with `PSA_ERROR_DOES_NOT_EXIST`). |
||||||
|
|
||||||
|
This requires instrumenting the storage implementation, either to force it to fail at each point or to record successive storage states and replay each of them. Each `psa_its_xxx` function call is assumed to be atomic. |
||||||
|
|
||||||
|
### SE driver system tests |
||||||
|
|
||||||
|
#### Real-world use case |
||||||
|
|
||||||
|
We must have at least one driver that is close to real-world conditions: |
||||||
|
|
||||||
|
* With its own source tree. |
||||||
|
* Running on actual hardware. |
||||||
|
* Run the full driver validation test suite (which does not yet exist). |
||||||
|
* Run at least one test application (e.g. the Mbed OS TLS example). |
||||||
|
|
||||||
|
This requirement shall be fulfilled by the [Microchip ATECC508A driver](https://github.com/ARMmbed/mbed-os-atecc608a/). |
||||||
|
|
||||||
|
#### Complete driver |
||||||
|
|
||||||
|
We should have at least one driver that covers the whole interface: |
||||||
|
|
||||||
|
* With its own source tree. |
||||||
|
* Implementing all the methods. |
||||||
|
* Run the full driver validation test suite (which does not yet exist). |
||||||
|
|
||||||
|
A PKCS#11 driver would be a good candidate. It would be useful as part of our product offering. |
||||||
|
|
||||||
|
## Transparent driver interface testing |
||||||
|
|
||||||
|
The [unified driver interface](../../proposed/psa-driver-interface.md) defines interfaces for accelerators. |
||||||
|
|
||||||
|
### Test requirements |
||||||
|
|
||||||
|
#### Requirements for transparent driver testing |
||||||
|
|
||||||
|
Every cryptographic mechanism for which a transparent driver interface exists (key creation, cryptographic operations, …) must be exercised in at least one build. The test must verify that the driver code is called. |
||||||
|
|
||||||
|
#### Requirements for fallback |
||||||
|
|
||||||
|
The driver interface includes a fallback mechanism so that a driver can reject a request at runtime and let another driver handle the request. For each entry point, there must be at least three test runs with two or more drivers available with driver A configured to fall back to driver B, with one run where A returns `PSA_SUCCESS`, one where A returns `PSA_ERROR_NOT_SUPPORTED` and B is invoked, and one where A returns a different error and B is not invoked. |
||||||
|
|
||||||
|
## Entropy and randomness interface testing |
||||||
|
|
||||||
|
TODO |
@ -0,0 +1,367 @@ |
|||||||
|
# Mbed TLS invasive testing strategy |
||||||
|
|
||||||
|
## Introduction |
||||||
|
|
||||||
|
In Mbed TLS, we use black-box testing as much as possible: test the documented behavior of the product, in a realistic environment. However this is not always sufficient. |
||||||
|
|
||||||
|
The goal of this document is to identify areas where black-box testing is insufficient and to propose solutions. |
||||||
|
|
||||||
|
This is a test strategy document, not a test plan. A description of exactly what is tested is out of scope. |
||||||
|
|
||||||
|
This document is structured as follows: |
||||||
|
|
||||||
|
* [“Rules”](#rules) gives general rules and is written for brevity. |
||||||
|
* [“Requirements”](#requirements) explores the reasons why invasive testing is needed and how it should be done. |
||||||
|
* [“Possible approaches”](#possible-approaches) discusses some general methods for non-black-box testing. |
||||||
|
* [“Solutions”](#solutions) explains how we currently solve, or intend to solve, specific problems. |
||||||
|
|
||||||
|
### TLS |
||||||
|
|
||||||
|
This document currently focuses on data structure manipulation and storage, which is what the crypto/keystore and X.509 parts of the library are about. More work is needed to fully take TLS into account. |
||||||
|
|
||||||
|
## Rules |
||||||
|
|
||||||
|
Always follow these rules unless you have a good reason not to. If you deviate, document the rationale somewhere. |
||||||
|
|
||||||
|
See the section [“Possible approaches”](#possible-approaches) for a rationale. |
||||||
|
|
||||||
|
### Interface design for testing |
||||||
|
|
||||||
|
Do not add test-specific interfaces if there's a practical way of doing it another way. All public interfaces should be useful in at least some configurations. Features with a significant impact on the code size or attack surface should have a compile-time guard. |
||||||
|
|
||||||
|
### Reliance on internal details |
||||||
|
|
||||||
|
In unit tests and in test programs, it's ok to include internal header files from `library/`. Do not define non-public interfaces in public headers. In contrast, sample programs must not include header files from `library/`. |
||||||
|
|
||||||
|
Sometimes it makes sense to have unit tests on functions that aren't part of the public API. Declare such functions in `library/*.h` and include the corresponding header in the test code. If the function should be `static` for optimization but can't be `static` for testing, declare it as `MBEDTLS_STATIC_TESTABLE`, and make the tests that use it depend on `MBEDTLS_TEST_HOOKS` (see [“rules for compile-time options”](#rules-for-compile-time-options)). |
||||||
|
|
||||||
|
If test code or test data depends on internal details of the library and not just on its documented behavior, add a comment in the code that explains the dependency. For example: |
||||||
|
|
||||||
|
> ``` |
||||||
|
> /* This test file is specific to the ITS implementation in PSA Crypto |
||||||
|
> * on top of stdio. It expects to know what the stdio name of a file is |
||||||
|
> * based on its keystore name. |
||||||
|
> */ |
||||||
|
> ``` |
||||||
|
|
||||||
|
> ``` |
||||||
|
> # This test assumes that PSA_MAX_KEY_BITS (currently 65536-8 bits = 8191 bytes |
||||||
|
> # and not expected to be raised any time soon) is less than the maximum |
||||||
|
> # output from HKDF-SHA512 (255*64 = 16320 bytes). |
||||||
|
> ``` |
||||||
|
|
||||||
|
### Rules for compile-time options |
||||||
|
|
||||||
|
If the most practical way to test something is to add code to the product that is only useful for testing, do so, but obey the following rules. For more information, see the [rationale](#guidelines-for-compile-time-options). |
||||||
|
|
||||||
|
* **Only use test-specific code when necessary.** Anything that can be tested through the documented API must be tested through the documented API. |
||||||
|
* **Test-specific code must be guarded by `#if defined(MBEDTLS_TEST_HOOKS)`**. Do not create fine-grained guards for test-specific code. |
||||||
|
* **Do not use `MBEDTLS_TEST_HOOKS` for security checks or assertions.** Security checks belong in the product. |
||||||
|
* **Merely defining `MBEDTLS_TEST_HOOKS` must not change the behavior**. It may define extra functions. It may add fields to structures, but if so, make it very clear that these fields have no impact on non-test-specific fields. |
||||||
|
* **Where tests must be able to change the behavior, do it by function substitution.** See [“rules for function substitution”](#rules-for-function-substitution) for more details. |
||||||
|
|
||||||
|
#### Rules for function substitution |
||||||
|
|
||||||
|
This section explains how to replace a library function `mbedtls_foo()` by alternative code for test purposes. That is, library code calls `mbedtls_foo()`, and there is a mechanism to arrange for these calls to invoke different code. |
||||||
|
|
||||||
|
Often `mbedtls_foo` is a macro which is defined to be a system function (like `mbedtls_calloc` or `mbedtls_fopen`), which we replace to mock or wrap the system function. This is useful to simulate I/O failure, for example. Note that if the macro can be replaced at compile time to support alternative platforms, the test code should be compatible with this compile-time configuration so that it works on these alternative platforms as well. |
||||||
|
|
||||||
|
Sometimes the substitutable function is a `static inline` function that does nothing (not a macro, to avoid accidentally skipping side effects in its parameters), to provide a hook for test code; such functions should have a name that starts with the prefix `mbedtls_test_hook_`. In such cases, the function should generally not modify its parameters, so any pointer argument should be const. The function should return void. |
||||||
|
|
||||||
|
With `MBEDTLS_TEST_HOOKS` set, `mbedtls_foo` is a global variable of function pointer type. This global variable is initialized to the system function, or to a function that does nothing. The global variable is defined in a header in the `library` directory such as `psa_crypto_invasive.h`. This is similar to the platform function configuration mechanism with `MBEDTLS_PLATFORM_xxx_ALT`. |
||||||
|
|
||||||
|
In unit test code that needs to modify the internal behavior: |
||||||
|
|
||||||
|
* The test function (or the whole test file) must depend on `MBEDTLS_TEST_HOOKS`. |
||||||
|
* At the beginning of the test function, set the global function pointers to the desired value. |
||||||
|
* In the test function's cleanup code, restore the global function pointers to their default value. |
||||||
|
|
||||||
|
## Requirements |
||||||
|
|
||||||
|
### General goals |
||||||
|
|
||||||
|
We need to balance the following goals, which are sometimes contradictory. |
||||||
|
|
||||||
|
* Coverage: we need to test behaviors which are not easy to trigger by using the API or which cannot be triggered deterministically, for example I/O failures. |
||||||
|
* Correctness: we want to test the actual product, not a modified version, since conclusions drawn from a test of a modified product may not apply to the real product. |
||||||
|
* Effacement: the product should not include features that are solely present for test purposes, since these increase the attack surface and the code size. |
||||||
|
* Portability: tests should work on every platform. Skipping tests on certain platforms may hide errors that are only apparent on such platforms. |
||||||
|
* Maintainability: tests should only enforce the documented behavior of the product, to avoid extra work when the product's internal or implementation-specific behavior changes. We should also not give the impression that whatever the tests check is guaranteed behavior of the product which cannot change in future versions. |
||||||
|
|
||||||
|
Where those goals conflict, we should at least mitigate the goals that cannot be fulfilled, and document the architectural choices and their rationale. |
||||||
|
|
||||||
|
### Problem areas |
||||||
|
|
||||||
|
#### Allocation |
||||||
|
|
||||||
|
Resource allocation can fail, but rarely does so in a typical test environment. How does the product cope if some allocations fail? |
||||||
|
|
||||||
|
Resources include: |
||||||
|
|
||||||
|
* Memory. |
||||||
|
* Files in storage (PSA API only — in the Mbed TLS API, black-box unit tests are sufficient). |
||||||
|
* Key slots (PSA API only). |
||||||
|
* Key slots in a secure element (PSA SE HAL). |
||||||
|
* Communication handles (PSA crypto service only). |
||||||
|
|
||||||
|
#### Storage |
||||||
|
|
||||||
|
Storage can fail, either due to hardware errors or to active attacks on trusted storage. How does the code cope if some storage accesses fail? |
||||||
|
|
||||||
|
We also need to test resilience: if the system is reset during an operation, does it restart in a correct state? |
||||||
|
|
||||||
|
#### Cleanup |
||||||
|
|
||||||
|
When code should clean up resources, how do we know that they have truly been cleaned up? |
||||||
|
|
||||||
|
* Zeroization of confidential data after use. |
||||||
|
* Freeing memory. |
||||||
|
* Freeing key slots. |
||||||
|
* Freeing key slots in a secure element. |
||||||
|
* Deleting files in storage (PSA API only). |
||||||
|
|
||||||
|
#### Internal data |
||||||
|
|
||||||
|
Sometimes it is useful to peek or poke internal data. |
||||||
|
|
||||||
|
* Check consistency of internal data (e.g. output of key generation). |
||||||
|
* Check the format of files (which matters so that the product can still read old files after an upgrade). |
||||||
|
* Inject faults and test corruption checks inside the product. |
||||||
|
|
||||||
|
## Possible approaches |
||||||
|
|
||||||
|
Key to requirement tables: |
||||||
|
|
||||||
|
* ++ requirement is fully met |
||||||
|
* \+ requirement is mostly met |
||||||
|
* ~ requirement is partially met but there are limitations |
||||||
|
* ! requirement is somewhat problematic |
||||||
|
* !! requirement is very problematic |
||||||
|
|
||||||
|
### Fine-grained public interfaces |
||||||
|
|
||||||
|
We can include all the features we want to test in the public interface. Then the tests can be truly black-box. The limitation of this approach is that this requires adding a lot of interfaces that are not useful in production. These interfaces have costs: they increase the code size, the attack surface, and the testing burden (exponentially, because we need to test all these interfaces in combination). |
||||||
|
|
||||||
|
As a rule, we do not add public interfaces solely for testing purposes. We only add public interfaces if they are also useful in production, at least sometimes. For example, the main purpose of `mbedtls_psa_crypto_free` is to clean up all resources in tests, but this is also useful in production in some applications that only want to use PSA Crypto during part of their lifetime. |
||||||
|
|
||||||
|
Mbed TLS traditionally has very fine-grained public interfaces, with many platform functions that can be substituted (`MBEDTLS_PLATFORM_xxx` macros). PSA Crypto has more opacity and less platform substitution macros. |
||||||
|
|
||||||
|
| Requirement | Analysis | |
||||||
|
| ----------- | -------- | |
||||||
|
| Coverage | ~ Many useful tests are not reasonably achievable | |
||||||
|
| Correctness | ++ Ideal | |
||||||
|
| Effacement | !! Requires adding many otherwise-useless interfaces | |
||||||
|
| Portability | ++ Ideal; the additional interfaces may be useful for portability beyond testing | |
||||||
|
| Maintainability | !! Combinatorial explosion on the testing burden | |
||||||
|
| | ! Public interfaces must remain for backward compatibility even if the test architecture changes | |
||||||
|
|
||||||
|
### Fine-grained undocumented interfaces |
||||||
|
|
||||||
|
We can include all the features we want to test in undocumented interfaces. Undocumented interfaces are described in public headers for the sake of the C compiler, but are described as “do not use” in comments (or not described at all) and are not included in Doxygen-rendered documentation. This mitigates some of the downsides of [fine-grained public interfaces](#fine-grained-public-interfaces), but not all. In particular, the extra interfaces do increase the code size, the attack surface and the test surface. |
||||||
|
|
||||||
|
Mbed TLS traditionally has a few internal interfaces, mostly intended for cross-module abstraction leakage rather than for testing. For the PSA API, we favor [internal interfaces](#internal-interfaces). |
||||||
|
|
||||||
|
| Requirement | Analysis | |
||||||
|
| ----------- | -------- | |
||||||
|
| Coverage | ~ Many useful tests are not reasonably achievable | |
||||||
|
| Correctness | ++ Ideal | |
||||||
|
| Effacement | !! Requires adding many otherwise-useless interfaces | |
||||||
|
| Portability | ++ Ideal; the additional interfaces may be useful for portability beyond testing | |
||||||
|
| Maintainability | ! Combinatorial explosion on the testing burden | |
||||||
|
|
||||||
|
### Internal interfaces |
||||||
|
|
||||||
|
We can write tests that call internal functions that are not exposed in the public interfaces. This is nice when it works, because it lets us test the unchanged product without compromising the design of the public interface. |
||||||
|
|
||||||
|
A limitation is that these interfaces must exist in the first place. If they don't, this has mostly the same downside as public interfaces: the extra interfaces increase the code size and the attack surface for no direct benefit to the product. |
||||||
|
|
||||||
|
Another limitation is that internal interfaces need to be used correctly. We may accidentally rely on internal details in the tests that are not necessarily always true (for example that are platform-specific). We may accidentally use these internal interfaces in ways that don't correspond to the actual product. |
||||||
|
|
||||||
|
This approach is mostly portable since it only relies on C interfaces. A limitation is that the test-only interfaces must not be hidden at link time (but link-time hiding is not something we currently do). Another limitation is that this approach does not work for users who patch the library by replacing some modules; this is a secondary concern since we do not officially offer this as a feature. |
||||||
|
|
||||||
|
| Requirement | Analysis | |
||||||
|
| ----------- | -------- | |
||||||
|
| Coverage | ~ Many useful tests require additional internal interfaces | |
||||||
|
| Correctness | + Does not require a product change | |
||||||
|
| | ~ The tests may call internal functions in a way that does not reflect actual usage inside the product | |
||||||
|
| Effacement | ++ Fine as long as the internal interfaces aren't added solely for test purposes | |
||||||
|
| Portability | + Fine as long as we control how the tests are linked | |
||||||
|
| | ~ Doesn't work if the users rewrite an internal module | |
||||||
|
| Maintainability | + Tests interfaces that are documented; dependencies in the tests are easily noticed when changing these interfaces | |
||||||
|
|
||||||
|
### Static analysis |
||||||
|
|
||||||
|
If we guarantee certain properties through static analysis, we don't need to test them. This puts some constraints on the properties: |
||||||
|
|
||||||
|
* We need to have confidence in the specification (but we can gain this confidence by evaluating the specification on test data). |
||||||
|
* This does not work for platform-dependent properties unless we have a formal model of the platform. |
||||||
|
|
||||||
|
| Requirement | Analysis | |
||||||
|
| ----------- | -------- | |
||||||
|
| Coverage | ~ Good for platform-independent properties, if we can guarantee them statically | |
||||||
|
| Correctness | + Good as long as we have confidence in the specification | |
||||||
|
| Effacement | ++ Zero impact on the code | |
||||||
|
| Portability | ++ Zero runtime burden | |
||||||
|
| Maintainability | ~ Static analysis is hard, but it's also helpful | |
||||||
|
|
||||||
|
### Compile-time options |
||||||
|
|
||||||
|
If there's code that we want to have in the product for testing, but not in production, we can add a compile-time option to enable it. This is very powerful and usually easy to use, but comes with a major downside: we aren't testing the same code anymore. |
||||||
|
|
||||||
|
| Requirement | Analysis | |
||||||
|
| ----------- | -------- | |
||||||
|
| Coverage | ++ Most things can be tested that way | |
||||||
|
| Correctness | ! Difficult to ensure that what we test is what we run | |
||||||
|
| Effacement | ++ No impact on the product when built normally or on the documentation, if done right | |
||||||
|
| | ! Risk of getting “no impact” wrong | |
||||||
|
| Portability | ++ It's just C code so it works everywhere | |
||||||
|
| | ~ Doesn't work if the users rewrite an internal module | |
||||||
|
| Maintainability | + Test interfaces impact the product source code, but at least they're clearly marked as such in the code | |
||||||
|
|
||||||
|
#### Guidelines for compile-time options |
||||||
|
|
||||||
|
* **Minimize the number of compile-time options.**<br> |
||||||
|
Either we're testing or we're not. Fine-grained options for testing would require more test builds, especially if combinatorics enters the play. |
||||||
|
* **Merely enabling the compile-time option should not change the behavior.**<br> |
||||||
|
When building in test mode, the code should have exactly the same behavior. Changing the behavior should require some action at runtime (calling a function or changing a variable). |
||||||
|
* **Minimize the impact on code**.<br> |
||||||
|
We should not have test-specific conditional compilation littered through the code, as that makes the code hard to read. |
||||||
|
|
||||||
|
### Runtime instrumentation |
||||||
|
|
||||||
|
Some properties can be tested through runtime instrumentation: have the compiler or a similar tool inject something into the binary. |
||||||
|
|
||||||
|
* Sanitizers check for certain bad usage patterns (ASan, MSan, UBSan, Valgrind). |
||||||
|
* We can inject external libraries at link time. This can be a way to make system functions fail. |
||||||
|
|
||||||
|
| Requirement | Analysis | |
||||||
|
| ----------- | -------- | |
||||||
|
| Coverage | ! Limited scope | |
||||||
|
| Correctness | + Instrumentation generally does not affect the program's functional behavior | |
||||||
|
| Effacement | ++ Zero impact on the code | |
||||||
|
| Portability | ~ Depends on the method | |
||||||
|
| Maintainability | ~ Depending on the instrumentation, this may require additional builds and scripts | |
||||||
|
| | + Many properties come for free, but some require effort (e.g. the test code itself must be leak-free to avoid false positives in a leak detector) | |
||||||
|
|
||||||
|
### Debugger-based testing |
||||||
|
|
||||||
|
If we want to do something in a test that the product isn't capable of doing, we can use a debugger to read or modify the memory, or hook into the code at arbitrary points. |
||||||
|
|
||||||
|
This is a very powerful approach, but it comes with limitations: |
||||||
|
|
||||||
|
* The debugger may introduce behavior changes (e.g. timing). If we modify data structures in memory, we may do so in a way that the code doesn't expect. |
||||||
|
* Due to compiler optimizations, the memory may not have the layout that we expect. |
||||||
|
* Writing reliable debugger scripts is hard. We need to have confidence that we're testing what we mean to test, even in the face of compiler optimizations. Languages such as gdb make it hard to automate even relatively simple things such as finding the place(s) in the binary corresponding to some place in the source code. |
||||||
|
* Debugger scripts are very much non-portable. |
||||||
|
|
||||||
|
| Requirement | Analysis | |
||||||
|
| ----------- | -------- | |
||||||
|
| Coverage | ++ The sky is the limit | |
||||||
|
| Correctness | ++ The code is unmodified, and tested as compiled (so we even detect compiler-induced bugs) | |
||||||
|
| | ! Compiler optimizations may hinder | |
||||||
|
| | ~ Modifying the execution may introduce divergence | |
||||||
|
| Effacement | ++ Zero impact on the code | |
||||||
|
| Portability | !! Not all environments have a debugger, and even if they do, we'd need completely different scripts for every debugger | |
||||||
|
| Maintainability | ! Writing reliable debugger scripts is hard | |
||||||
|
| | !! Very tight coupling with the details of the source code and even with the compiler | |
||||||
|
|
||||||
|
## Solutions |
||||||
|
|
||||||
|
This section lists some strategies that are currently used for invasive testing, or planned to be used. This list is not intended to be exhaustive. |
||||||
|
|
||||||
|
### Memory management |
||||||
|
|
||||||
|
#### Zeroization testing |
||||||
|
|
||||||
|
Goal: test that `mbedtls_platform_zeroize` does wipe the memory buffer. |
||||||
|
|
||||||
|
Solution ([debugger](#debugger-based-testing)): implemented in `tests/scripts/test_zeroize.gdb`. |
||||||
|
|
||||||
|
Rationale: this cannot be tested by adding C code, because the danger is that the compiler optimizes the zeroization away, and any C code that observes the zeroization would cause the compiler not to optimize it away. |
||||||
|
|
||||||
|
#### Memory cleanup |
||||||
|
|
||||||
|
Goal: test the absence of memory leaks. |
||||||
|
|
||||||
|
Solution ([instrumentation](#runtime-instrumentation)): run tests with ASan. (We also use Valgrind, but it's slower than ASan, so we favor ASan.) |
||||||
|
|
||||||
|
Since we run many test jobs with a memory leak detector, each test function or test program must clean up after itself. Use the cleanup code (after the `exit` label in test functions) to free any memory that the function may have allocated. |
||||||
|
|
||||||
|
#### Robustness against memory allocation failure |
||||||
|
|
||||||
|
Solution: TODO. We don't test this at all at this point. |
||||||
|
|
||||||
|
#### PSA key store memory cleanup |
||||||
|
|
||||||
|
Goal: test the absence of resource leaks in the PSA key store code, in particular that `psa_close_key` and `psa_destroy_key` work correctly. |
||||||
|
|
||||||
|
Solution ([internal interface](#internal-interfaces)): in most tests involving PSA functions, the cleanup code explicitly calls `PSA_DONE()` instead of `mbedtls_psa_crypto_free()`. `PSA_DONE` fails the test if the key store in memory is not empty. |
||||||
|
|
||||||
|
Note there must also be tests that call `mbedtls_psa_crypto_free` with keys still open, to verify that it does close all keys. |
||||||
|
|
||||||
|
`PSA_DONE` is a macro defined in `psa_crypto_helpers.h` which uses `mbedtls_psa_get_stats()` to get information about the keystore content before calling `mbedtls_psa_crypto_free()`. This feature is mostly but not exclusively useful for testing, and may be moved under `MBEDTLS_TEST_HOOKS`. |
||||||
|
|
||||||
|
### PSA storage |
||||||
|
|
||||||
|
#### PSA storage cleanup on success |
||||||
|
|
||||||
|
Goal: test that no stray files are left over in the key store after a test that succeeded. |
||||||
|
|
||||||
|
Solution: TODO. Currently the various test suites do it differently. |
||||||
|
|
||||||
|
#### PSA storage cleanup on failure |
||||||
|
|
||||||
|
Goal: ensure that no stray files are left over in the key store even if a test has failed (as that could cause other tests to fail). |
||||||
|
|
||||||
|
Solution: TODO. Currently the various test suites do it differently. |
||||||
|
|
||||||
|
#### PSA storage resilience |
||||||
|
|
||||||
|
Goal: test the resilience of PSA storage against power failures. |
||||||
|
|
||||||
|
Solution: TODO. |
||||||
|
|
||||||
|
See the [secure element driver interface test strategy](driver-interface-test-strategy.html) for more information. |
||||||
|
|
||||||
|
#### Corrupted storage |
||||||
|
|
||||||
|
Goal: test the robustness against corrupted storage. |
||||||
|
|
||||||
|
Solution ([internal interface](#internal-interfaces)): call `psa_its` functions to modify the storage. |
||||||
|
|
||||||
|
#### Storage read failure |
||||||
|
|
||||||
|
Goal: test the robustness against read errors. |
||||||
|
|
||||||
|
Solution: TODO |
||||||
|
|
||||||
|
#### Storage write failure |
||||||
|
|
||||||
|
Goal: test the robustness against write errors (`STORAGE_FAILURE` or `INSUFFICIENT_STORAGE`). |
||||||
|
|
||||||
|
Solution: TODO |
||||||
|
|
||||||
|
#### Storage format stability |
||||||
|
|
||||||
|
Goal: test that the storage format does not change between versions (or if it does, an upgrade path must be provided). |
||||||
|
|
||||||
|
Solution ([internal interface](#internal-interfaces)): call internal functions to inspect the content of the file. |
||||||
|
|
||||||
|
Note that the storage format is defined not only by the general layout, but also by the numerical values of encodings for key types and other metadata. For numerical values, there is a risk that we would accidentally modify a single value or a few values, so the tests should be exhaustive. This probably requires some compile-time analysis (perhaps the automation for `psa_constant_names` can be used here). TODO |
||||||
|
|
||||||
|
### Other fault injection |
||||||
|
|
||||||
|
#### PSA crypto init failure |
||||||
|
|
||||||
|
Goal: test the failure of `psa_crypto_init`. |
||||||
|
|
||||||
|
Solution ([compile-time option](#compile-time-options)): replace entropy initialization functions by functions that can fail. This is the only failure point for `psa_crypto_init` that is present in all builds. |
||||||
|
|
||||||
|
When we implement the PSA entropy driver interface, this should be reworked to use the entropy driver interface. |
||||||
|
|
||||||
|
#### PSA crypto data corruption |
||||||
|
|
||||||
|
The PSA crypto subsystem has a few checks to detect corrupted data in memory. We currently don't have a way to exercise those checks. |
||||||
|
|
||||||
|
Solution: TODO. To corrupt a multipart operation structure, we can do it by looking inside the structure content, but only when running without isolation. To corrupt the key store, we would need to add a function to the library or to use a debugger. |
||||||
|
|
@ -0,0 +1,127 @@ |
|||||||
|
# Mbed TLS PSA keystore format stability testing strategy |
||||||
|
|
||||||
|
## Introduction |
||||||
|
|
||||||
|
The PSA crypto subsystem includes a persistent key store. It is possible to create a persistent key and read it back later. This must work even if Mbed TLS has been upgraded in the meantime (except for deliberate breaks in the backward compatibility of the storage). |
||||||
|
|
||||||
|
The goal of this document is to define a test strategy for the key store that not only validates that it's possible to load a key that was saved with the version of Mbed TLS under test, but also that it's possible to load a key that was saved with previous versions of Mbed TLS. |
||||||
|
|
||||||
|
Interoperability is not a goal: PSA crypto implementations are not intended to have compatible storage formats. Downgrading is not required to work. |
||||||
|
|
||||||
|
## General approach |
||||||
|
|
||||||
|
### Limitations of a direct approach |
||||||
|
|
||||||
|
The goal of storage format stability testing is: as a user of Mbed TLS, I want to store a key under version V and read it back under version W, with W ≥ V. |
||||||
|
|
||||||
|
Doing the testing this way would be difficult because we'd need to have version V of Mbed TLS available when testing version W. |
||||||
|
|
||||||
|
An alternative, semi-direct approach consists of generating test data under version V, and reading it back under version W. Done naively, this would require keeping a large amount of test data (full test coverage multiplied by the number of versions that we want to preserve backward compatibility with). |
||||||
|
|
||||||
|
### Save-and-compare approach |
||||||
|
|
||||||
|
Importing and saving a key is deterministic. Therefore we can ensure the stability of the storage format by creating test cases under a version V of Mbed TLS, where the test case parameters include both the parameters to pass to key creation and the expected state of the storage after the key is created. The test case creates a key as indicated by the parameters, then compares the actual state of the storage with the expected state. |
||||||
|
|
||||||
|
In addition, the test case also loads the key and checks that it has the expected data and metadata. Import-and-save testing and load-and-check testing can be split into separate test functions with the same payloads. |
||||||
|
|
||||||
|
If the test passes with version V, this means that the test data is consistent with what the implementation does. When the test later runs under version W ≥ V, it creates and reads back a storage state which is known to be identical to the state that V would have produced. Thus, this approach validates that W can read storage states created by V. |
||||||
|
|
||||||
|
Note that it is the combination of import-and-save passing on version V and load-and-check passing on version W with the same data that proves that version W can read back what version V wrote. From the perspective of a particular version of the library, the import-and-save tests guarantee forward compatibility while the load-and-check tests guarantee backward compatibility. |
||||||
|
|
||||||
|
Use a similar approach for files other than keys where possible and relevant. |
||||||
|
|
||||||
|
### Keeping up with storage format evolution |
||||||
|
|
||||||
|
Test cases should normally not be removed from the code base: if something has worked before, it should keep working in future versions, so we should keep testing it. |
||||||
|
|
||||||
|
This cannot be enforced solely by looking at a single version of Mbed TLS, since there would be no indication that more test cases used to exist. It can only be enforced through review of library changes. The review is be assisted by a tool that compares the old and the new version, which is implemented in `scripts/abi_check.py`. This tool fails the CI if load-and-check test case disappears (changed test cases are raised as false positives). |
||||||
|
|
||||||
|
If the way certain keys are stored changes, and we don't deliberately decide to stop supporting old keys (which should only be done by retiring a version of the storage format), then we should keep the corresponding test cases in load-only mode: create a file with the expected content, load it and check the data that it contains. |
||||||
|
|
||||||
|
## Storage architecture overview |
||||||
|
|
||||||
|
The PSA subsystem provides storage on top of the PSA trusted storage interface. The state of the storage is a mapping from file identifier (a 64-bit number) to file content (a byte array). These files include: |
||||||
|
|
||||||
|
* [Key files](#key-storage) (files containing one key's metadata and, except for some secure element keys, key material). |
||||||
|
* The [random generator injected seed or state file](#random-generator-state) (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`). |
||||||
|
* [Storage transaction file](#storage-transaction-resumption). |
||||||
|
* [Driver state files](#driver-state-files). |
||||||
|
|
||||||
|
For a more detailed description, refer to the [Mbed Crypto storage specification](../mbed-crypto-storage-specification.md). |
||||||
|
|
||||||
|
In addition, Mbed TLS includes an implementation of the PSA trusted storage interface on top of C stdio. This document addresses the test strategy for [PSA ITS over file](#psa-its-over-file) in a separate section below. |
||||||
|
|
||||||
|
## Key storage testing |
||||||
|
|
||||||
|
This section describes the desired test cases for keys created with the current storage format version. When the storage format changes, if backward compatibility is desired, old test data should be kept as described under [“Keeping up with storage format evolution”](#keeping-up-with-storage-format-evolution). |
||||||
|
|
||||||
|
### Keystore layout |
||||||
|
|
||||||
|
Objective: test that the key file name corresponds to the key identifier. |
||||||
|
|
||||||
|
Method: Create a key with a given identifier (using `psa_import_key`) and verify that a file with the expected name is created, and no other. Repeat for different identifiers. |
||||||
|
|
||||||
|
### General key format |
||||||
|
|
||||||
|
Objective: test the format of the key file: which field goes where and how big it is. |
||||||
|
|
||||||
|
Method: Create a key with certain metadata with `psa_import_key`. Read the file content and validate that it has the expected layout, deduced from the storage specification. Repeat with different metadata. Ensure that there are test cases covering all fields. |
||||||
|
|
||||||
|
### Enumeration of test cases for keys |
||||||
|
|
||||||
|
Objective: ensure that the coverage is sufficient to have assurance that all keys are stored correctly. This requires a sufficient selection of key types, sizes, policies, etc. |
||||||
|
|
||||||
|
In particular, the tests must validate that each `PSA_xxx` constant that is stored in a key is covered by at least one test case: |
||||||
|
|
||||||
|
* Lifetimes: `PSA_KEY_LIFETIME_xxx`, `PSA_KEY_PERSISTENCE_xxx`, `PSA_KEY_LOCATION_xxx`. |
||||||
|
* Usage flags: `PSA_KEY_USAGE_xxx`. |
||||||
|
* Algorithms in policies: `PSA_ALG_xxx`. |
||||||
|
* Key types: `PSA_KEY_TYPE_xxx`, `PSA_ECC_FAMILY_xxx`, `PSA_DH_FAMILY_xxx`. |
||||||
|
|
||||||
|
In addition, the coverage of key material must ensure that any variation in key representation is detected. See [“Considerations on key material representations”](#Considerations-on-key-material-representations) for considerations regarding key types. |
||||||
|
|
||||||
|
Method: Each test case creates a key with `psa_import_key`, purges it from memory, then reads it back and exercises it. |
||||||
|
|
||||||
|
Generate test cases automatically based on an enumeration of available constants and some knowledge of what attributes (sizes, algorithms, …) and content to use for keys of a certain type. |
||||||
|
|
||||||
|
### Testing with alternative lifetime values |
||||||
|
|
||||||
|
Objective: have test coverage for lifetimes other than the default persistent lifetime (`PSA_KEY_LIFETIME_PERSISTENT`). |
||||||
|
|
||||||
|
Method: |
||||||
|
|
||||||
|
* For alternative locations: have tests conditional on the presence of a driver for that location. |
||||||
|
* For alternative persistence levels: have load-and-check tests for supported persistence levels. We may also want to have negative tests ensuring that keys with a not-supported persistence level are not accidentally created. |
||||||
|
|
||||||
|
### Considerations on key material representations |
||||||
|
|
||||||
|
The risks of incompatibilities in key representations depends on the key type and on the presence of drivers. Compatibility of and with drivers is currently out of scope of this document. |
||||||
|
|
||||||
|
Some types only have one plausible representation. Others admit alternative plausible representations (different encodings, or non-canonical representations). |
||||||
|
Here are some areas to watch for, with an identified risk of incompatibilities. |
||||||
|
|
||||||
|
* HMAC keys longer than the block size: pre-hashed or not? |
||||||
|
* DES keys: was parity enforced? |
||||||
|
* RSA keys: can invalid DER encodings (e.g. leading zeros, ignored sign bit) have been stored? |
||||||
|
* RSA private keys: can invalid CRT parameters have been stored? |
||||||
|
* Montgomery private keys: were they stored in masked form? |
||||||
|
|
||||||
|
## Random generator state |
||||||
|
|
||||||
|
TODO |
||||||
|
|
||||||
|
## Driver state files |
||||||
|
|
||||||
|
Not yet implemented. |
||||||
|
|
||||||
|
TODO |
||||||
|
|
||||||
|
## Storage transaction resumption |
||||||
|
|
||||||
|
Only relevant for secure element support. Not yet fully implemented. |
||||||
|
|
||||||
|
TODO |
||||||
|
|
||||||
|
## PSA ITS over file |
||||||
|
|
||||||
|
TODO |
@ -0,0 +1,58 @@ |
|||||||
|
# Mbed TLS test framework |
||||||
|
|
||||||
|
This document is an overview of the Mbed TLS test framework and test tools. |
||||||
|
|
||||||
|
This document is incomplete. You can help by expanding it. |
||||||
|
|
||||||
|
## Unit tests |
||||||
|
|
||||||
|
See <https://mbed-tls.readthedocs.io/en/latest/kb/development/test_suites> |
||||||
|
|
||||||
|
### Unit test descriptions |
||||||
|
|
||||||
|
Each test case has a description which succinctly describes for a human audience what the test does. The first non-comment line of each paragraph in a `.data` file is the test description. The following rules and guidelines apply: |
||||||
|
|
||||||
|
* Test descriptions may not contain semicolons, line breaks and other control characters, or non-ASCII characters. <br> |
||||||
|
Rationale: keep the tools that process test descriptions (`generate_test_code.py`, [outcome file](#outcome-file) tools) simple. |
||||||
|
* Test descriptions must be unique within a `.data` file. If you can't think of a better description, the convention is to append `#1`, `#2`, etc. <br> |
||||||
|
Rationale: make it easy to relate a failure log to the test data. Avoid confusion between cases in the [outcome file](#outcome-file). |
||||||
|
* Test descriptions should be a maximum of **66 characters**. <br> |
||||||
|
Rationale: 66 characters is what our various tools assume (leaving room for 14 more characters on an 80-column line). Longer descriptions may be truncated or may break a visual alignment. <br> |
||||||
|
We have a lot of test cases with longer descriptions, but they should be avoided. At least please make sure that the first 66 characters describe the test uniquely. |
||||||
|
* Make the description descriptive. “foo: x=2, y=4” is more descriptive than “foo #2”. “foo: 0<x<y, both even” is even better if these inequalities and parities are why this particular test data was chosen. |
||||||
|
* Avoid changing the description of an existing test case without a good reason. This breaks the tracking of failures across CI runs, since this tracking is based on the descriptions. |
||||||
|
|
||||||
|
`tests/scripts/check_test_cases.py` enforces some rules and warns if some guidelines are violated. |
||||||
|
|
||||||
|
## TLS tests |
||||||
|
|
||||||
|
### SSL extension tests |
||||||
|
|
||||||
|
#### SSL test case descriptions |
||||||
|
|
||||||
|
Each test case in `ssl-opt.sh` has a description which succinctly describes for a human audience what the test does. The test description is the first parameter to `run_tests`. |
||||||
|
|
||||||
|
The same rules and guidelines apply as for [unit test descriptions](#unit-test-descriptions). In addition, the description must be written on the same line as `run_test`, in double quotes, for the sake of `check_test_cases.py`. |
||||||
|
|
||||||
|
## Running tests |
||||||
|
|
||||||
|
### Outcome file |
||||||
|
|
||||||
|
#### Generating an outcome file |
||||||
|
|
||||||
|
Unit tests and `ssl-opt.sh` record the outcome of each test case in a **test outcome file**. This feature is enabled if the environment variable `MBEDTLS_TEST_OUTCOME_FILE` is set. Set it to the path of the desired file. |
||||||
|
|
||||||
|
If you run `all.sh --outcome-file test-outcome.csv`, this collects the outcome of all the test cases in `test-outcome.csv`. |
||||||
|
|
||||||
|
#### Outcome file format |
||||||
|
|
||||||
|
The outcome file is in a CSV format using `;` (semicolon) as the delimiter and no quoting. This means that fields may not contain newlines or semicolons. There is no title line. |
||||||
|
|
||||||
|
The outcome file has 6 fields: |
||||||
|
|
||||||
|
* **Platform**: a description of the platform, e.g. `Linux-x86_64` or `Linux-x86_64-gcc7-msan`. |
||||||
|
* **Configuration**: a unique description of the configuration (`mbedtls_config.h`). |
||||||
|
* **Test suite**: `test_suite_xxx` or `ssl-opt`. |
||||||
|
* **Test case**: the description of the test case. |
||||||
|
* **Result**: one of `PASS`, `SKIP` or `FAIL`. |
||||||
|
* **Cause**: more information explaining the result. |
@ -0,0 +1,652 @@ |
|||||||
|
TLS 1.3 support |
||||||
|
=============== |
||||||
|
|
||||||
|
Overview |
||||||
|
-------- |
||||||
|
|
||||||
|
Mbed TLS provides a partial implementation of the TLS 1.3 protocol defined in |
||||||
|
the "Support description" section below. The TLS 1.3 support enablement |
||||||
|
is controlled by the MBEDTLS_SSL_PROTO_TLS1_3 configuration option. |
||||||
|
|
||||||
|
The development of the TLS 1.3 protocol is based on the TLS 1.3 prototype |
||||||
|
located at https://github.com/hannestschofenig/mbedtls. The prototype is |
||||||
|
itself based on a version of the development branch that we aim to keep as |
||||||
|
recent as possible (ideally the head) by merging regularly commits of the |
||||||
|
development branch into the prototype. The section "Prototype upstreaming |
||||||
|
status" below describes what remains to be upstreamed. |
||||||
|
|
||||||
|
|
||||||
|
Support description |
||||||
|
------------------- |
||||||
|
|
||||||
|
- Overview |
||||||
|
|
||||||
|
- Mbed TLS implements both the client and the server side of the TLS 1.3 |
||||||
|
protocol. |
||||||
|
|
||||||
|
- Mbed TLS supports ECDHE key establishment. |
||||||
|
|
||||||
|
- Mbed TLS does not support DHE key establishment. |
||||||
|
|
||||||
|
- Mbed TLS supports pre-shared keys for key establishment, pre-shared keys |
||||||
|
provisioned externally as well as provisioned via the ticket mechanism. |
||||||
|
|
||||||
|
- Mbed TLS supports session resumption via the ticket mechanism. |
||||||
|
|
||||||
|
- Mbed TLS does not support sending or receiving early data (0-RTT data). |
||||||
|
|
||||||
|
- Supported cipher suites: depends on the library configuration. Potentially |
||||||
|
all of them: |
||||||
|
TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, |
||||||
|
TLS_AES_128_CCM_SHA256 and TLS_AES_128_CCM_8_SHA256. |
||||||
|
|
||||||
|
- Supported ClientHello extensions: |
||||||
|
|
||||||
|
| Extension | Support | |
||||||
|
| ---------------------------- | ------- | |
||||||
|
| server_name | YES | |
||||||
|
| max_fragment_length | no | |
||||||
|
| status_request | no | |
||||||
|
| supported_groups | YES | |
||||||
|
| signature_algorithms | YES | |
||||||
|
| use_srtp | no | |
||||||
|
| heartbeat | no | |
||||||
|
| apln | YES | |
||||||
|
| signed_certificate_timestamp | no | |
||||||
|
| client_certificate_type | no | |
||||||
|
| server_certificate_type | no | |
||||||
|
| padding | no | |
||||||
|
| key_share | YES | |
||||||
|
| pre_shared_key | YES | |
||||||
|
| psk_key_exchange_modes | YES | |
||||||
|
| early_data | no | |
||||||
|
| cookie | no | |
||||||
|
| supported_versions | YES | |
||||||
|
| certificate_authorities | no | |
||||||
|
| post_handshake_auth | no | |
||||||
|
| signature_algorithms_cert | no | |
||||||
|
|
||||||
|
|
||||||
|
- Supported groups: depends on the library configuration. |
||||||
|
Potentially all ECDHE groups: |
||||||
|
secp256r1, x25519, secp384r1, x448 and secp521r1. |
||||||
|
|
||||||
|
Finite field groups (DHE) are not supported. |
||||||
|
|
||||||
|
- Supported signature algorithms (both for certificates and CertificateVerify): |
||||||
|
depends on the library configuration. |
||||||
|
Potentially: |
||||||
|
ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384, ecdsa_secp521r1_sha512, |
||||||
|
rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512, rsa_pss_rsae_sha256, |
||||||
|
rsa_pss_rsae_sha384 and rsa_pss_rsae_sha512. |
||||||
|
|
||||||
|
Note that in absence of an application profile standard specifying otherwise |
||||||
|
rsa_pkcs1_sha256, rsa_pss_rsae_sha256 and ecdsa_secp256r1_sha256 are |
||||||
|
mandatory (see section 9.1 of the specification). |
||||||
|
|
||||||
|
- Supported versions: |
||||||
|
|
||||||
|
- TLS 1.2 and TLS 1.3 with version negotiation on the client side, not server |
||||||
|
side. |
||||||
|
|
||||||
|
- TLS 1.2 and TLS 1.3 can be enabled in the build independently of each |
||||||
|
other. |
||||||
|
|
||||||
|
- If both TLS 1.3 and TLS 1.2 are enabled at build time, only one of them can |
||||||
|
be configured at runtime via `mbedtls_ssl_conf_{min,max}_tls_version` for a |
||||||
|
server endpoint. Otherwise, `mbedtls_ssl_setup` will raise |
||||||
|
`MBEDTLS_ERR_SSL_BAD_CONFIG` error. |
||||||
|
|
||||||
|
- Compatibility with existing SSL/TLS build options: |
||||||
|
|
||||||
|
The TLS 1.3 implementation is compatible with nearly all TLS 1.2 |
||||||
|
configuration options in the sense that when enabling TLS 1.3 in the library |
||||||
|
there is rarely any need to modify the configuration from that used for |
||||||
|
TLS 1.2. There are two exceptions though: the TLS 1.3 implementation requires |
||||||
|
MBEDTLS_PSA_CRYPTO_C and MBEDTLS_SSL_KEEP_PEER_CERTIFICATE, so these options |
||||||
|
must be enabled. |
||||||
|
|
||||||
|
Most of the Mbed TLS SSL/TLS related options are not supported or not |
||||||
|
applicable to the TLS 1.3 implementation: |
||||||
|
|
||||||
|
| Mbed TLS configuration option | Support | |
||||||
|
| ---------------------------------------- | ------- | |
||||||
|
| MBEDTLS_SSL_ALL_ALERT_MESSAGES | no | |
||||||
|
| MBEDTLS_SSL_ASYNC_PRIVATE | no | |
||||||
|
| MBEDTLS_SSL_CONTEXT_SERIALIZATION | no | |
||||||
|
| MBEDTLS_SSL_DEBUG_ALL | no | |
||||||
|
| MBEDTLS_SSL_ENCRYPT_THEN_MAC | n/a | |
||||||
|
| MBEDTLS_SSL_EXTENDED_MASTER_SECRET | n/a | |
||||||
|
| MBEDTLS_SSL_KEEP_PEER_CERTIFICATE | no (1) | |
||||||
|
| MBEDTLS_SSL_RENEGOTIATION | n/a | |
||||||
|
| MBEDTLS_SSL_MAX_FRAGMENT_LENGTH | no | |
||||||
|
| | | |
||||||
|
| MBEDTLS_SSL_SESSION_TICKETS | yes | |
||||||
|
| MBEDTLS_SSL_SERVER_NAME_INDICATION | yes | |
||||||
|
| MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH | no | |
||||||
|
| | | |
||||||
|
| MBEDTLS_ECP_RESTARTABLE | no | |
||||||
|
| MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED | no | |
||||||
|
| | | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_PSK_ENABLED | n/a (2) | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_RSA_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED | n/a | |
||||||
|
| MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED | n/a | |
||||||
|
| | | |
||||||
|
| MBEDTLS_PSA_CRYPTO_C | no (1) | |
||||||
|
| MBEDTLS_USE_PSA_CRYPTO | yes | |
||||||
|
|
||||||
|
(1) These options must remain in their default state of enabled. |
||||||
|
(2) See the TLS 1.3 specific build options section below. |
||||||
|
|
||||||
|
- TLS 1.3 specific build options: |
||||||
|
|
||||||
|
- MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE enables the support for middlebox |
||||||
|
compatibility mode as defined in section D.4 of RFC 8446. |
||||||
|
|
||||||
|
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED enables the support for |
||||||
|
the PSK key exchange mode as defined by RFC 8446. If it is the only key |
||||||
|
exchange mode enabled, the TLS 1.3 implementation does not contain any code |
||||||
|
related to key exchange protocols, certificates and signatures. |
||||||
|
|
||||||
|
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED enables the |
||||||
|
support for the ephemeral key exchange mode. If it is the only key exchange |
||||||
|
mode enabled, the TLS 1.3 implementation does not contain any code related |
||||||
|
to PSK based key exchange. The ephemeral key exchange mode requires at least |
||||||
|
one of the key exchange protocol allowed by the TLS 1.3 specification, the |
||||||
|
parsing and validation of x509 certificates and at least one signature |
||||||
|
algorithm allowed by the TLS 1.3 specification for signature computing and |
||||||
|
verification. |
||||||
|
|
||||||
|
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED enables the |
||||||
|
support for the PSK ephemeral key exchange mode. If it is the only key |
||||||
|
exchange mode enabled, the TLS 1.3 implementation does not contain any code |
||||||
|
related to certificates and signatures. The PSK ephemeral key exchange |
||||||
|
mode requires at least one of the key exchange protocol allowed by the |
||||||
|
TLS 1.3 specification. |
||||||
|
|
||||||
|
|
||||||
|
Prototype upstreaming status |
||||||
|
---------------------------- |
||||||
|
|
||||||
|
The following parts of the TLS 1.3 prototype remain to be upstreamed: |
||||||
|
|
||||||
|
- Sending (client) and receiving (server) early data (0-RTT data). |
||||||
|
|
||||||
|
- New TLS Message Processing Stack (MPS) |
||||||
|
|
||||||
|
The TLS 1.3 prototype is developed alongside a rewrite of the TLS messaging layer, |
||||||
|
encompassing low-level details such as record parsing, handshake reassembly, and |
||||||
|
DTLS retransmission state machine. |
||||||
|
|
||||||
|
MPS has the following components: |
||||||
|
- Layer 1 (Datagram handling) |
||||||
|
- Layer 2 (Record handling) |
||||||
|
- Layer 3 (Message handling) |
||||||
|
- Layer 4 (Retransmission State Machine) |
||||||
|
- Reader (Abstracted pointer arithmetic and reassembly logic for incoming data) |
||||||
|
- Writer (Abstracted pointer arithmetic and fragmentation logic for outgoing data) |
||||||
|
|
||||||
|
Of those components, the following have been upstreamed |
||||||
|
as part of `MBEDTLS_SSL_PROTO_TLS1_3`: |
||||||
|
|
||||||
|
- Reader ([`library/mps_reader.h`](../../library/mps_reader.h)) |
||||||
|
|
||||||
|
|
||||||
|
Coding rules checklist for TLS 1.3 |
||||||
|
---------------------------------- |
||||||
|
|
||||||
|
The following coding rules are aimed to be a checklist for TLS 1.3 upstreaming |
||||||
|
work to reduce review rounds and the number of comments in each round. They |
||||||
|
come along (do NOT replace) the project coding rules |
||||||
|
(https://mbed-tls.readthedocs.io/en/latest/kb/development/mbedtls-coding-standards). They have been |
||||||
|
established and discussed following the review of #4882 that was the |
||||||
|
PR upstreaming the first part of TLS 1.3 ClientHello writing code. |
||||||
|
|
||||||
|
TLS 1.3 specific coding rules: |
||||||
|
|
||||||
|
- TLS 1.3 specific C modules, headers, static functions names are prefixed |
||||||
|
with `ssl_tls13_`. The same applies to structures and types that are |
||||||
|
internal to C modules. |
||||||
|
|
||||||
|
- TLS 1.3 specific exported functions, structures and types are |
||||||
|
prefixed with `mbedtls_ssl_tls13_`. |
||||||
|
|
||||||
|
- Use TLS1_3 in TLS 1.3 specific macros. |
||||||
|
|
||||||
|
- The names of macros and variables related to a field or structure in the |
||||||
|
TLS 1.3 specification should contain as far as possible the field name as |
||||||
|
it is in the specification. If the field name is "too long" and we prefer |
||||||
|
to introduce some kind of abbreviation of it, use the same abbreviation |
||||||
|
everywhere in the code. |
||||||
|
|
||||||
|
Example 1: #define CLIENT_HELLO_RANDOM_LEN 32, macro for the length of the |
||||||
|
`random` field of the ClientHello message. |
||||||
|
|
||||||
|
Example 2 (consistent abbreviation): `mbedtls_ssl_tls13_write_sig_alg_ext()` |
||||||
|
and `MBEDTLS_TLS_EXT_SIG_ALG`, `sig_alg` standing for |
||||||
|
`signature_algorithms`. |
||||||
|
|
||||||
|
- Regarding vectors that are represented by a length followed by their value |
||||||
|
in the data exchanged between servers and clients: |
||||||
|
|
||||||
|
- Use `<vector name>_len` for the name of a variable used to compute the |
||||||
|
length in bytes of the vector, where <vector name> is the name of the |
||||||
|
vector as defined in the TLS 1.3 specification. |
||||||
|
|
||||||
|
- Use `p_<vector_name>_len` for the name of a variable intended to hold |
||||||
|
the address of the first byte of the vector length. |
||||||
|
|
||||||
|
- Use `<vector_name>` for the name of a variable intended to hold the |
||||||
|
address of the first byte of the vector value. |
||||||
|
|
||||||
|
- Use `<vector_name>_end` for the name of a variable intended to hold |
||||||
|
the address of the first byte past the vector value. |
||||||
|
|
||||||
|
Those idioms should lower the risk of mis-using one of the address in place |
||||||
|
of another one which could potentially lead to some nasty issues. |
||||||
|
|
||||||
|
Example: `cipher_suites` vector of ClientHello in |
||||||
|
`ssl_tls13_write_client_hello_cipher_suites()` |
||||||
|
``` |
||||||
|
size_t cipher_suites_len; |
||||||
|
unsigned char *p_cipher_suites_len; |
||||||
|
unsigned char *cipher_suites; |
||||||
|
``` |
||||||
|
|
||||||
|
- Where applicable, use: |
||||||
|
- the macros to extract a byte from a multi-byte integer MBEDTLS_BYTE_{0-8}. |
||||||
|
- the macros to write in memory in big-endian order a multi-byte integer |
||||||
|
MBEDTLS_PUT_UINT{8|16|32|64}_BE. |
||||||
|
- the macros to read from memory a multi-byte integer in big-endian order |
||||||
|
MBEDTLS_GET_UINT{8|16|32|64}_BE. |
||||||
|
- the macro to check for space when writing into an output buffer |
||||||
|
`MBEDTLS_SSL_CHK_BUF_PTR`. |
||||||
|
- the macro to check for data when reading from an input buffer |
||||||
|
`MBEDTLS_SSL_CHK_BUF_READ_PTR`. |
||||||
|
|
||||||
|
These macros were introduced after the prototype was written thus are |
||||||
|
likely not to be used in prototype where we now would use them in |
||||||
|
development. |
||||||
|
|
||||||
|
The three first types, MBEDTLS_BYTE_{0-8}, MBEDTLS_PUT_UINT{8|16|32|64}_BE |
||||||
|
and MBEDTLS_GET_UINT{8|16|32|64}_BE improve the readability of the code and |
||||||
|
reduce the risk of writing or reading bytes in the wrong order. |
||||||
|
|
||||||
|
The two last types, `MBEDTLS_SSL_CHK_BUF_PTR` and |
||||||
|
`MBEDTLS_SSL_CHK_BUF_READ_PTR`, improve the readability of the code and |
||||||
|
reduce the risk of error in the non-completely-trivial arithmetic to |
||||||
|
check that we do not write or read past the end of a data buffer. The |
||||||
|
usage of those macros combined with the following rule mitigate the risk |
||||||
|
to read/write past the end of a data buffer. |
||||||
|
|
||||||
|
Examples: |
||||||
|
``` |
||||||
|
hs_hdr[1] = MBEDTLS_BYTE_2( total_hs_len ); |
||||||
|
MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0 ); |
||||||
|
MBEDTLS_SSL_CHK_BUF_PTR( p, end, 7 ); |
||||||
|
``` |
||||||
|
|
||||||
|
- To mitigate what happened here |
||||||
|
(https://github.com/Mbed-TLS/mbedtls/pull/4882#discussion_r701704527) from |
||||||
|
happening again, use always a local variable named `p` for the reading |
||||||
|
pointer in functions parsing TLS 1.3 data, and for the writing pointer in |
||||||
|
functions writing data into an output buffer and only that variable. The |
||||||
|
name `p` has been chosen as it was already widely used in TLS code. |
||||||
|
|
||||||
|
- When an TLS 1.3 structure is written or read by a function or as part of |
||||||
|
a function, provide as documentation the definition of the structure as |
||||||
|
it is in the TLS 1.3 specification. |
||||||
|
|
||||||
|
General coding rules: |
||||||
|
|
||||||
|
- We prefer grouping "related statement lines" by not adding blank lines |
||||||
|
between them. |
||||||
|
|
||||||
|
Example 1: |
||||||
|
``` |
||||||
|
ret = ssl_tls13_write_client_hello_cipher_suites( ssl, buf, end, &output_len ); |
||||||
|
if( ret != 0 ) |
||||||
|
return( ret ); |
||||||
|
buf += output_len; |
||||||
|
``` |
||||||
|
|
||||||
|
Example 2: |
||||||
|
``` |
||||||
|
MBEDTLS_SSL_CHK_BUF_PTR( cipher_suites_iter, end, 2 ); |
||||||
|
MBEDTLS_PUT_UINT16_BE( cipher_suite, cipher_suites_iter, 0 ); |
||||||
|
cipher_suites_iter += 2; |
||||||
|
``` |
||||||
|
|
||||||
|
- Use macros for constants that are used in different functions, different |
||||||
|
places in the code. When a constant is used only locally in a function |
||||||
|
(like the length in bytes of the vector lengths in functions reading and |
||||||
|
writing TLS handshake message) there is no need to define a macro for it. |
||||||
|
|
||||||
|
Example: `#define CLIENT_HELLO_RANDOM_LEN 32` |
||||||
|
|
||||||
|
- When declaring a pointer the dereferencing operator should be prepended to |
||||||
|
the pointer name not appended to the pointer type: |
||||||
|
|
||||||
|
Example: `mbedtls_ssl_context *ssl;` |
||||||
|
|
||||||
|
- Maximum line length is 80 characters. |
||||||
|
|
||||||
|
Exceptions: |
||||||
|
|
||||||
|
- string literals can extend beyond 80 characters as we do not want to |
||||||
|
split them to ease their search in the code base. |
||||||
|
|
||||||
|
- A line can be more than 80 characters by a few characters if just looking |
||||||
|
at the 80 first characters is enough to fully understand the line. For |
||||||
|
example it is generally fine if some closure characters like ";" or ")" |
||||||
|
are beyond the 80 characters limit. |
||||||
|
|
||||||
|
If a line becomes too long due to a refactoring (for example renaming a |
||||||
|
function to a longer name, or indenting a block more), avoid rewrapping |
||||||
|
lines in the same commit: it makes the review harder. Make one commit with |
||||||
|
the longer lines and another commit with just the rewrapping. |
||||||
|
|
||||||
|
- When in successive lines, functions and macros parameters should be aligned |
||||||
|
vertically. |
||||||
|
|
||||||
|
Example: |
||||||
|
``` |
||||||
|
int mbedtls_ssl_start_handshake_msg( mbedtls_ssl_context *ssl, |
||||||
|
unsigned hs_type, |
||||||
|
unsigned char **buf, |
||||||
|
size_t *buf_len ); |
||||||
|
``` |
||||||
|
|
||||||
|
- When a function's parameters span several lines, group related parameters |
||||||
|
together if possible. |
||||||
|
|
||||||
|
For example, prefer: |
||||||
|
|
||||||
|
``` |
||||||
|
mbedtls_ssl_start_handshake_msg( ssl, hs_type, |
||||||
|
buf, buf_len ); |
||||||
|
``` |
||||||
|
over |
||||||
|
``` |
||||||
|
mbedtls_ssl_start_handshake_msg( ssl, hs_type, buf, |
||||||
|
buf_len ); |
||||||
|
``` |
||||||
|
even if it fits. |
||||||
|
|
||||||
|
|
||||||
|
Overview of handshake code organization |
||||||
|
--------------------------------------- |
||||||
|
|
||||||
|
The TLS 1.3 handshake protocol is implemented as a state machine. The |
||||||
|
functions `mbedtls_ssl_tls13_handshake_{client,server}_step` are the top level |
||||||
|
functions of that implementation. They are implemented as a switch over all the |
||||||
|
possible states of the state machine. |
||||||
|
|
||||||
|
Most of the states are either dedicated to the processing or writing of an |
||||||
|
handshake message. |
||||||
|
|
||||||
|
The implementation does not go systematically through all states as this would |
||||||
|
result in too many checks of whether something needs to be done or not in a |
||||||
|
given state to be duplicated across several state handlers. For example, on |
||||||
|
client side, the states related to certificate parsing and validation are |
||||||
|
bypassed if the handshake is based on a pre-shared key and thus does not |
||||||
|
involve certificates. |
||||||
|
|
||||||
|
On the contrary, the implementation goes systematically though some states |
||||||
|
even if they could be bypassed if it helps in minimizing when and where inbound |
||||||
|
and outbound keys are updated. The `MBEDTLS_SSL_CLIENT_CERTIFICATE` state on |
||||||
|
client side is a example of that. |
||||||
|
|
||||||
|
The names of the handlers processing/writing an handshake message are |
||||||
|
prefixed with `(mbedtls_)ssl_tls13_{process,write}`. To ease the maintenance and |
||||||
|
reduce the risk of bugs, the code of the message processing and writing |
||||||
|
handlers is split into a sequence of stages. |
||||||
|
|
||||||
|
The sending of data to the peer only occurs in `mbedtls_ssl_handshake_step` |
||||||
|
between the calls to the handlers and as a consequence handlers do not have to |
||||||
|
care about the MBEDTLS_ERR_SSL_WANT_WRITE error code. Furthermore, all pending |
||||||
|
data are flushed before to call the next handler. That way, handlers do not |
||||||
|
have to worry about pending data when changing outbound keys. |
||||||
|
|
||||||
|
### Message processing handlers |
||||||
|
For message processing handlers, the stages are: |
||||||
|
|
||||||
|
* coordination stage: check if the state should be bypassed. This stage is |
||||||
|
optional. The check is either purely based on the reading of the value of some |
||||||
|
fields of the SSL context or based on the reading of the type of the next |
||||||
|
message. The latter occurs when it is not known what the next handshake message |
||||||
|
will be, an example of that on client side being if we are going to receive a |
||||||
|
CertificateRequest message or not. The intent is, apart from the next record |
||||||
|
reading to not modify the SSL context as this stage may be repeated if the |
||||||
|
next handshake message has not been received yet. |
||||||
|
|
||||||
|
* fetching stage: at this stage we are sure of the type of the handshake |
||||||
|
message we must receive next and we try to fetch it. If we did not go through |
||||||
|
a coordination stage involving the next record type reading, the next |
||||||
|
handshake message may not have been received yet, the handler returns with |
||||||
|
`MBEDTLS_ERR_SSL_WANT_READ` without changing the current state and it will be |
||||||
|
called again later. |
||||||
|
|
||||||
|
* pre-processing stage: prepare the SSL context for the message parsing. This |
||||||
|
stage is optional. Any processing that must be done before the parsing of the |
||||||
|
message or that can be done to simplify the parsing code. Some simple and |
||||||
|
partial parsing of the handshake message may append at that stage like in the |
||||||
|
ServerHello message pre-processing. |
||||||
|
|
||||||
|
* parsing stage: parse the message and restrict as much as possible any |
||||||
|
update of the SSL context. The idea of the pre-processing/parsing/post-processing |
||||||
|
organization is to concentrate solely on the parsing in the parsing function to |
||||||
|
reduce the size of its code and to simplify it. |
||||||
|
|
||||||
|
* post-processing stage: following the parsing, further update of the SSL |
||||||
|
context to prepare for the next incoming and outgoing messages. This stage is |
||||||
|
optional. For example, secret and key computations occur at this stage, as well |
||||||
|
as handshake messages checksum update. |
||||||
|
|
||||||
|
* state change: the state change is done in the main state handler to ease the |
||||||
|
navigation of the state machine transitions. |
||||||
|
|
||||||
|
|
||||||
|
### Message writing handlers |
||||||
|
For message writing handlers, the stages are: |
||||||
|
|
||||||
|
* coordination stage: check if the state should be bypassed. This stage is |
||||||
|
optional. The check is based on the value of some fields of the SSL context. |
||||||
|
|
||||||
|
* preparation stage: prepare for the message writing. This stage is optional. |
||||||
|
Any processing that must be done before the writing of the message or that can |
||||||
|
be done to simplify the writing code. |
||||||
|
|
||||||
|
* writing stage: write the message and restrict as much as possible any update |
||||||
|
of the SSL context. The idea of the preparation/writing/finalization |
||||||
|
organization is to concentrate solely on the writing in the writing function to |
||||||
|
reduce the size of its code and simplify it. |
||||||
|
|
||||||
|
* finalization stage: following the writing, further update of the SSL |
||||||
|
context to prepare for the next incoming and outgoing messages. This stage is |
||||||
|
optional. For example, handshake secret and key computation occur at that |
||||||
|
stage (ServerHello writing finalization), switching to handshake keys for |
||||||
|
outbound message on server side as well. |
||||||
|
|
||||||
|
* state change: the state change is done in the main state handler to ease |
||||||
|
the navigation of the state machine transitions. |
||||||
|
|
||||||
|
|
||||||
|
Writing and reading early or 0-RTT data |
||||||
|
--------------------------------------- |
||||||
|
|
||||||
|
An application function to write and send a buffer of data to a server through |
||||||
|
TLS may plausibly look like: |
||||||
|
|
||||||
|
``` |
||||||
|
int write_data( mbedtls_ssl_context *ssl, |
||||||
|
const unsigned char *data_to_write, |
||||||
|
size_t data_to_write_len, |
||||||
|
size_t *data_written ) |
||||||
|
{ |
||||||
|
*data_written = 0; |
||||||
|
|
||||||
|
while( *data_written < data_to_write_len ) |
||||||
|
{ |
||||||
|
ret = mbedtls_ssl_write( ssl, data_to_write + *data_written, |
||||||
|
data_to_write_len - *data_written ); |
||||||
|
|
||||||
|
if( ret < 0 && |
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_READ && |
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE ) |
||||||
|
{ |
||||||
|
return( ret ); |
||||||
|
} |
||||||
|
|
||||||
|
*data_written += ret; |
||||||
|
} |
||||||
|
|
||||||
|
return( 0 ); |
||||||
|
} |
||||||
|
``` |
||||||
|
where ssl is the SSL context to use, data_to_write the address of the data |
||||||
|
buffer and data_to_write_len the number of data bytes. The handshake may |
||||||
|
not be completed, not even started for the SSL context ssl when the function is |
||||||
|
called and in that case the mbedtls_ssl_write() API takes care transparently of |
||||||
|
completing the handshake before to write and send data to the server. The |
||||||
|
mbedtls_ssl_write() may not been able to write and send all data in one go thus |
||||||
|
the need for a loop calling it as long as there are still data to write and |
||||||
|
send. |
||||||
|
|
||||||
|
An application function to write and send early data and only early data, |
||||||
|
data sent during the first flight of client messages while the handshake is in |
||||||
|
its initial phase, would look completely similar but the call to |
||||||
|
mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write(). |
||||||
|
``` |
||||||
|
int write_early_data( mbedtls_ssl_context *ssl, |
||||||
|
const unsigned char *data_to_write, |
||||||
|
size_t data_to_write_len, |
||||||
|
size_t *data_written ) |
||||||
|
{ |
||||||
|
*data_written = 0; |
||||||
|
|
||||||
|
while( *data_written < data_to_write_len ) |
||||||
|
{ |
||||||
|
ret = mbedtls_ssl_write_early_data( ssl, data_to_write + *data_written, |
||||||
|
data_to_write_len - *data_written ); |
||||||
|
|
||||||
|
if( ret < 0 && |
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_READ && |
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE ) |
||||||
|
{ |
||||||
|
return( ret ); |
||||||
|
} |
||||||
|
|
||||||
|
*data_written += ret; |
||||||
|
} |
||||||
|
|
||||||
|
return( 0 ); |
||||||
|
} |
||||||
|
``` |
||||||
|
Note that compared to write_data(), write_early_data() can also return |
||||||
|
MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA and that should be handled |
||||||
|
specifically by the user of write_early_data(). A fresh SSL context (typically |
||||||
|
just after a call to mbedtls_ssl_setup() or mbedtls_ssl_session_reset()) would |
||||||
|
be expected when calling `write_early_data`. |
||||||
|
|
||||||
|
All together, code to write and send a buffer of data as long as possible as |
||||||
|
early data and then as standard post-handshake application data could |
||||||
|
plausibly look like: |
||||||
|
|
||||||
|
``` |
||||||
|
ret = write_early_data( ssl, data_to_write, data_to_write_len, |
||||||
|
&early_data_written ); |
||||||
|
if( ret < 0 && |
||||||
|
ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) |
||||||
|
{ |
||||||
|
goto error; |
||||||
|
} |
||||||
|
|
||||||
|
ret = write_data( ssl, data_to_write + early_data_written, |
||||||
|
data_to_write_len - early_data_written, &data_written ); |
||||||
|
if( ret < 0 ) |
||||||
|
goto error; |
||||||
|
|
||||||
|
data_written += early_data_written; |
||||||
|
``` |
||||||
|
|
||||||
|
Finally, taking into account that the server may reject early data, application |
||||||
|
code to write and send a buffer of data could plausibly look like: |
||||||
|
``` |
||||||
|
ret = write_early_data( ssl, data_to_write, data_to_write_len, |
||||||
|
&early_data_written ); |
||||||
|
if( ret < 0 && |
||||||
|
ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) |
||||||
|
{ |
||||||
|
goto error; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
* Make sure the handshake is completed as it is a requisite to |
||||||
|
* mbedtls_ssl_get_early_data_status(). |
||||||
|
*/ |
||||||
|
while( !mbedtls_ssl_is_handshake_over( ssl ) ) |
||||||
|
{ |
||||||
|
ret = mbedtls_ssl_handshake( ssl ); |
||||||
|
if( ret < 0 && |
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_READ && |
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE ) |
||||||
|
{ |
||||||
|
goto error; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ret = mbedtls_ssl_get_early_data_status( ssl ); |
||||||
|
if( ret < 0 ) |
||||||
|
goto error; |
||||||
|
|
||||||
|
if( ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED ) |
||||||
|
early_data_written = 0; |
||||||
|
|
||||||
|
ret = write_data( ssl, data_to_write + early_data_written, |
||||||
|
data_to_write_len - early_data_written, &data_written ); |
||||||
|
if( ret < 0 ) |
||||||
|
goto error; |
||||||
|
|
||||||
|
data_written += early_data_written; |
||||||
|
``` |
||||||
|
|
||||||
|
Basically, the same holds for reading early data on the server side without the |
||||||
|
complication of possible rejection. An application function to read early data |
||||||
|
into a given buffer could plausibly look like: |
||||||
|
``` |
||||||
|
int read_early_data( mbedtls_ssl_context *ssl, |
||||||
|
unsigned char *buffer, |
||||||
|
size_t buffer_size, |
||||||
|
size_t *data_len ) |
||||||
|
{ |
||||||
|
*data_len = 0; |
||||||
|
|
||||||
|
while( *data_len < buffer_size ) |
||||||
|
{ |
||||||
|
ret = mbedtls_ssl_read_early_data( ssl, buffer + *data_len, |
||||||
|
buffer_size - *data_len ); |
||||||
|
|
||||||
|
if( ret < 0 && |
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_READ && |
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE ) |
||||||
|
{ |
||||||
|
return( ret ); |
||||||
|
} |
||||||
|
|
||||||
|
*data_len += ret; |
||||||
|
} |
||||||
|
|
||||||
|
return( 0 ); |
||||||
|
} |
||||||
|
``` |
||||||
|
with again calls to read_early_data() expected to be done with a fresh SSL |
||||||
|
context. |
@ -0,0 +1,894 @@ |
|||||||
|
## Getting started with Mbed Crypto |
||||||
|
|
||||||
|
### What is Mbed Crypto? |
||||||
|
|
||||||
|
Mbed Crypto is an open source cryptographic library that supports a wide range of cryptographic operations, including: |
||||||
|
* Key management |
||||||
|
* Hashing |
||||||
|
* Symmetric cryptography |
||||||
|
* Asymmetric cryptography |
||||||
|
* Message authentication (MAC) |
||||||
|
* Key generation and derivation |
||||||
|
* Authenticated encryption with associated data (AEAD) |
||||||
|
|
||||||
|
The Mbed Crypto library is a reference implementation of the cryptography interface of the Arm Platform Security Architecture (PSA). It is written in portable C. |
||||||
|
|
||||||
|
The Mbed Crypto library is distributed under the Apache License, version 2.0. |
||||||
|
|
||||||
|
#### Platform Security Architecture (PSA) |
||||||
|
|
||||||
|
Arm's Platform Security Architecture (PSA) is a holistic set of threat models, |
||||||
|
security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that enables you to design security into both hardware and firmware consistently. Part of the API provided by PSA is the cryptography interface, which provides access to a set of primitives. |
||||||
|
|
||||||
|
### Using Mbed Crypto |
||||||
|
|
||||||
|
* [Getting the Mbed Crypto library](#getting-the-mbed-crypto-library) |
||||||
|
* [Building the Mbed Crypto library](#building-the-mbed-crypto-library) |
||||||
|
* [Using the Mbed Crypto library](#using-the-mbed-crypto-library) |
||||||
|
* [Importing a key](#importing-a-key) |
||||||
|
* [Signing a message using RSA](#signing-a-message-using-RSA) |
||||||
|
* [Encrypting or decrypting using symmetric ciphers](#encrypting-or-decrypting-using-symmetric-ciphers) |
||||||
|
* [Hashing a message](#hashing-a-message) |
||||||
|
* [Deriving a new key from an existing key](#deriving-a-new-key-from-an-existing-key) |
||||||
|
* [Generating a random value](#generating-a-random-value) |
||||||
|
* [Authenticating and encrypting or decrypting a message](#authenticating-and-encrypting-or-decrypting-a-message) |
||||||
|
* [Generating and exporting keys](#generating-and-exporting-keys) |
||||||
|
* [More about the Mbed Crypto library](#more-about-the-mbed-crypto-library) |
||||||
|
|
||||||
|
### Getting the Mbed Crypto library |
||||||
|
|
||||||
|
Mbed Crypto releases are available in the [public GitHub repository](https://github.com/ARMmbed/mbed-crypto). |
||||||
|
|
||||||
|
### Building the Mbed Crypto library |
||||||
|
|
||||||
|
**Prerequisites to building the library with the provided makefiles:** |
||||||
|
* GNU Make. |
||||||
|
* A C toolchain (compiler, linker, archiver). |
||||||
|
* Python 2 or Python 3 (either works) to generate the test code. |
||||||
|
* Perl to run the tests. |
||||||
|
|
||||||
|
If you have a C compiler such as GCC or Clang, just run `make` in the top-level directory to build the library, a set of unit tests and some sample programs. |
||||||
|
|
||||||
|
To select a different compiler, set the `CC` variable to the name or path of the compiler and linker (default: `cc`) and set `AR` to a compatible archiver (default: `ar`); for example: |
||||||
|
``` |
||||||
|
make CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar |
||||||
|
``` |
||||||
|
The provided makefiles pass options to the compiler that assume a GCC-like command line syntax. To use a different compiler, you may need to pass different values for `CFLAGS`, `WARNINGS_CFLAGS` and `LDFLAGS`. |
||||||
|
|
||||||
|
To run the unit tests on the host machine, run `make test` from the top-level directory. If you are cross-compiling, copy the test executable from the `tests` directory to the target machine. |
||||||
|
|
||||||
|
### Using the Mbed Crypto library |
||||||
|
|
||||||
|
To use the Mbed Crypto APIs, call `psa_crypto_init()` before calling any other API. This initializes the library. |
||||||
|
|
||||||
|
### Importing a key |
||||||
|
|
||||||
|
To use a key for cryptography operations in Mbed Crypto, you need to first |
||||||
|
import it. The import operation returns the identifier of the key for use |
||||||
|
with other function calls. |
||||||
|
|
||||||
|
**Prerequisites to importing keys:** |
||||||
|
* Initialize the library with a successful call to `psa_crypto_init()`. |
||||||
|
|
||||||
|
This example shows how to import a key: |
||||||
|
```C |
||||||
|
void import_a_key(const uint8_t *key, size_t key_len) |
||||||
|
{ |
||||||
|
psa_status_t status; |
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
||||||
|
psa_key_id_t key_id; |
||||||
|
|
||||||
|
printf("Import an AES key...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Set key attributes */ |
||||||
|
psa_set_key_usage_flags(&attributes, 0); |
||||||
|
psa_set_key_algorithm(&attributes, 0); |
||||||
|
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); |
||||||
|
psa_set_key_bits(&attributes, 128); |
||||||
|
|
||||||
|
/* Import the key */ |
||||||
|
status = psa_import_key(&attributes, key, key_len, &key_id); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to import key\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
printf("Imported a key\n"); |
||||||
|
|
||||||
|
/* Free the attributes */ |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
/* Destroy the key */ |
||||||
|
psa_destroy_key(key_id); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Signing a message using RSA |
||||||
|
|
||||||
|
Mbed Crypto supports encrypting, decrypting, signing and verifying messages using public key signature algorithms, such as RSA or ECDSA. |
||||||
|
|
||||||
|
**Prerequisites to performing asymmetric signature operations:** |
||||||
|
* Initialize the library with a successful call to `psa_crypto_init()`. |
||||||
|
* Have a valid key with appropriate attributes set: |
||||||
|
* Usage flag `PSA_KEY_USAGE_SIGN_HASH` to allow signing. |
||||||
|
* Usage flag `PSA_KEY_USAGE_VERIFY_HASH` to allow signature verification. |
||||||
|
* Algorithm set to the desired signature algorithm. |
||||||
|
|
||||||
|
This example shows how to sign a hash that has already been calculated: |
||||||
|
```C |
||||||
|
void sign_a_message_using_rsa(const uint8_t *key, size_t key_len) |
||||||
|
{ |
||||||
|
psa_status_t status; |
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
||||||
|
uint8_t hash[32] = {0x50, 0xd8, 0x58, 0xe0, 0x98, 0x5e, 0xcc, 0x7f, |
||||||
|
0x60, 0x41, 0x8a, 0xaf, 0x0c, 0xc5, 0xab, 0x58, |
||||||
|
0x7f, 0x42, 0xc2, 0x57, 0x0a, 0x88, 0x40, 0x95, |
||||||
|
0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c}; |
||||||
|
uint8_t signature[PSA_SIGNATURE_MAX_SIZE] = {0}; |
||||||
|
size_t signature_length; |
||||||
|
psa_key_id_t key_id; |
||||||
|
|
||||||
|
printf("Sign a message...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Set key attributes */ |
||||||
|
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); |
||||||
|
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW); |
||||||
|
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); |
||||||
|
psa_set_key_bits(&attributes, 1024); |
||||||
|
|
||||||
|
/* Import the key */ |
||||||
|
status = psa_import_key(&attributes, key, key_len, &key_id); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to import key\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Sign message using the key */ |
||||||
|
status = psa_sign_hash(key_id, PSA_ALG_RSA_PKCS1V15_SIGN_RAW, |
||||||
|
hash, sizeof(hash), |
||||||
|
signature, sizeof(signature), |
||||||
|
&signature_length); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to sign\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
printf("Signed a message\n"); |
||||||
|
|
||||||
|
/* Free the attributes */ |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
/* Destroy the key */ |
||||||
|
psa_destroy_key(key_id); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Using symmetric ciphers |
||||||
|
|
||||||
|
Mbed Crypto supports encrypting and decrypting messages using various symmetric cipher algorithms (both block and stream ciphers). |
||||||
|
|
||||||
|
**Prerequisites to working with the symmetric cipher API:** |
||||||
|
* Initialize the library with a successful call to `psa_crypto_init()`. |
||||||
|
* Have a symmetric key. This key's usage flags must include `PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption. |
||||||
|
|
||||||
|
**To encrypt a message with a symmetric cipher:** |
||||||
|
1. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions. |
||||||
|
1. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`. |
||||||
|
1. Call `psa_cipher_encrypt_setup()` to specify the algorithm and the key to be used. |
||||||
|
1. Call either `psa_cipher_generate_iv()` or `psa_cipher_set_iv()` to generate or set the initialization vector (IV). We recommend calling `psa_cipher_generate_iv()`, unless you require a specific IV value. |
||||||
|
1. Call `psa_cipher_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls. |
||||||
|
1. Call `psa_cipher_finish()` to end the operation and output the encrypted message. |
||||||
|
|
||||||
|
This example shows how to encrypt data using an AES (Advanced Encryption Standard) key in CBC (Cipher Block Chaining) mode with no padding (assuming all prerequisites have been fulfilled): |
||||||
|
```c |
||||||
|
void encrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len) |
||||||
|
{ |
||||||
|
enum { |
||||||
|
block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES), |
||||||
|
}; |
||||||
|
psa_status_t status; |
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
||||||
|
psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING; |
||||||
|
uint8_t plaintext[block_size] = SOME_PLAINTEXT; |
||||||
|
uint8_t iv[block_size]; |
||||||
|
size_t iv_len; |
||||||
|
uint8_t output[block_size]; |
||||||
|
size_t output_len; |
||||||
|
psa_key_id_t key_id; |
||||||
|
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; |
||||||
|
|
||||||
|
printf("Encrypt with cipher...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) |
||||||
|
{ |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Import a key */ |
||||||
|
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); |
||||||
|
psa_set_key_algorithm(&attributes, alg); |
||||||
|
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); |
||||||
|
psa_set_key_bits(&attributes, 128); |
||||||
|
status = psa_import_key(&attributes, key, key_len, &key_id); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to import a key\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
/* Encrypt the plaintext */ |
||||||
|
status = psa_cipher_encrypt_setup(&operation, key_id, alg); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to begin cipher operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_cipher_generate_iv(&operation, iv, sizeof(iv), &iv_len); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to generate IV\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_cipher_update(&operation, plaintext, sizeof(plaintext), |
||||||
|
output, sizeof(output), &output_len); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to update cipher operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_cipher_finish(&operation, output + output_len, |
||||||
|
sizeof(output) - output_len, &output_len); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to finish cipher operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
printf("Encrypted plaintext\n"); |
||||||
|
|
||||||
|
/* Clean up cipher operation context */ |
||||||
|
psa_cipher_abort(&operation); |
||||||
|
|
||||||
|
/* Destroy the key */ |
||||||
|
psa_destroy_key(key_id); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
**To decrypt a message with a symmetric cipher:** |
||||||
|
1. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions. |
||||||
|
1. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`. |
||||||
|
1. Call `psa_cipher_decrypt_setup()` to specify the algorithm and the key to be used. |
||||||
|
1. Call `psa_cipher_set_iv()` with the IV for the decryption. |
||||||
|
1. Call `psa_cipher_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls. |
||||||
|
1. Call `psa_cipher_finish()` to end the operation and output the decrypted message. |
||||||
|
|
||||||
|
This example shows how to decrypt encrypted data using an AES key in CBC mode with no padding |
||||||
|
(assuming all prerequisites have been fulfilled): |
||||||
|
```c |
||||||
|
void decrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len) |
||||||
|
{ |
||||||
|
enum { |
||||||
|
block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES), |
||||||
|
}; |
||||||
|
psa_status_t status; |
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
||||||
|
psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING; |
||||||
|
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; |
||||||
|
uint8_t ciphertext[block_size] = SOME_CIPHERTEXT; |
||||||
|
uint8_t iv[block_size] = ENCRYPTED_WITH_IV; |
||||||
|
uint8_t output[block_size]; |
||||||
|
size_t output_len; |
||||||
|
psa_key_id_t key_id; |
||||||
|
|
||||||
|
printf("Decrypt with cipher...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) |
||||||
|
{ |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Import a key */ |
||||||
|
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); |
||||||
|
psa_set_key_algorithm(&attributes, alg); |
||||||
|
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); |
||||||
|
psa_set_key_bits(&attributes, 128); |
||||||
|
status = psa_import_key(&attributes, key, key_len, &key_id); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to import a key\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
/* Decrypt the ciphertext */ |
||||||
|
status = psa_cipher_decrypt_setup(&operation, key_id, alg); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to begin cipher operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_cipher_set_iv(&operation, iv, sizeof(iv)); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to set IV\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_cipher_update(&operation, ciphertext, sizeof(ciphertext), |
||||||
|
output, sizeof(output), &output_len); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to update cipher operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_cipher_finish(&operation, output + output_len, |
||||||
|
sizeof(output) - output_len, &output_len); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to finish cipher operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
printf("Decrypted ciphertext\n"); |
||||||
|
|
||||||
|
/* Clean up cipher operation context */ |
||||||
|
psa_cipher_abort(&operation); |
||||||
|
|
||||||
|
/* Destroy the key */ |
||||||
|
psa_destroy_key(key_id); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
#### Handling cipher operation contexts |
||||||
|
|
||||||
|
After you've initialized the operation structure with a successful call to `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`, you can terminate the operation at any time by calling `psa_cipher_abort()`. |
||||||
|
|
||||||
|
The call to `psa_cipher_abort()` frees any resources associated with the operation, except for the operation structure itself. |
||||||
|
|
||||||
|
Mbed Crypto implicitly calls `psa_cipher_abort()` when: |
||||||
|
* A call to `psa_cipher_generate_iv()`, `psa_cipher_set_iv()` or `psa_cipher_update()` fails (returning any status other than `PSA_SUCCESS`). |
||||||
|
* A call to `psa_cipher_finish()` succeeds or fails. |
||||||
|
|
||||||
|
After an implicit or explicit call to `psa_cipher_abort()`, the operation structure is invalidated; in other words, you cannot reuse the operation structure for the same operation. You can, however, reuse the operation structure for a different operation by calling either `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` again. |
||||||
|
|
||||||
|
You must call `psa_cipher_abort()` at some point for any operation that is initialized successfully (by a successful call to `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`). |
||||||
|
|
||||||
|
Making multiple sequential calls to `psa_cipher_abort()` on an operation that is terminated (either implicitly or explicitly) is safe and has no effect. |
||||||
|
|
||||||
|
### Hashing a message |
||||||
|
|
||||||
|
Mbed Crypto lets you compute and verify hashes using various hashing |
||||||
|
algorithms. |
||||||
|
|
||||||
|
**Prerequisites to working with the hash APIs:** |
||||||
|
* Initialize the library with a successful call to `psa_crypto_init()`. |
||||||
|
|
||||||
|
**To calculate a hash:** |
||||||
|
1. Allocate an operation structure (`psa_hash_operation_t`) to pass to the hash functions. |
||||||
|
1. Initialize the operation structure to zero or to `PSA_HASH_OPERATION_INIT`. |
||||||
|
1. Call `psa_hash_setup()` to specify the hash algorithm. |
||||||
|
1. Call `psa_hash_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls. |
||||||
|
1. Call `psa_hash_finish()` to calculate the hash, or `psa_hash_verify()` to compare the computed hash with an expected hash value. |
||||||
|
|
||||||
|
This example shows how to calculate the SHA-256 hash of a message: |
||||||
|
```c |
||||||
|
psa_status_t status; |
||||||
|
psa_algorithm_t alg = PSA_ALG_SHA_256; |
||||||
|
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; |
||||||
|
unsigned char input[] = { 'a', 'b', 'c' }; |
||||||
|
unsigned char actual_hash[PSA_HASH_MAX_SIZE]; |
||||||
|
size_t actual_hash_len; |
||||||
|
|
||||||
|
printf("Hash a message...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Compute hash of message */ |
||||||
|
status = psa_hash_setup(&operation, alg); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to begin hash operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_hash_update(&operation, input, sizeof(input)); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to update hash operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_hash_finish(&operation, actual_hash, sizeof(actual_hash), |
||||||
|
&actual_hash_len); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to finish hash operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
printf("Hashed a message\n"); |
||||||
|
|
||||||
|
/* Clean up hash operation context */ |
||||||
|
psa_hash_abort(&operation); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
``` |
||||||
|
|
||||||
|
This example shows how to verify the SHA-256 hash of a message: |
||||||
|
```c |
||||||
|
psa_status_t status; |
||||||
|
psa_algorithm_t alg = PSA_ALG_SHA_256; |
||||||
|
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; |
||||||
|
unsigned char input[] = { 'a', 'b', 'c' }; |
||||||
|
unsigned char expected_hash[] = { |
||||||
|
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 |
||||||
|
}; |
||||||
|
size_t expected_hash_len = PSA_HASH_LENGTH(alg); |
||||||
|
|
||||||
|
printf("Verify a hash...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Verify message hash */ |
||||||
|
status = psa_hash_setup(&operation, alg); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to begin hash operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_hash_update(&operation, input, sizeof(input)); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to update hash operation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_hash_verify(&operation, expected_hash, expected_hash_len); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to verify hash\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
printf("Verified a hash\n"); |
||||||
|
|
||||||
|
/* Clean up hash operation context */ |
||||||
|
psa_hash_abort(&operation); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
``` |
||||||
|
|
||||||
|
The API provides the macro `PSA_HASH_LENGTH`, which returns the expected hash length (in bytes) for the specified algorithm. |
||||||
|
|
||||||
|
#### Handling hash operation contexts |
||||||
|
|
||||||
|
After a successful call to `psa_hash_setup()`, you can terminate the operation at any time by calling `psa_hash_abort()`. The call to `psa_hash_abort()` frees any resources associated with the operation, except for the operation structure itself. |
||||||
|
|
||||||
|
Mbed Crypto implicitly calls `psa_hash_abort()` when: |
||||||
|
1. A call to `psa_hash_update()` fails (returning any status other than `PSA_SUCCESS`). |
||||||
|
1. A call to `psa_hash_finish()` succeeds or fails. |
||||||
|
1. A call to `psa_hash_verify()` succeeds or fails. |
||||||
|
|
||||||
|
After an implicit or explicit call to `psa_hash_abort()`, the operation structure is invalidated; in other words, you cannot reuse the operation structure for the same operation. You can, however, reuse the operation structure for a different operation by calling `psa_hash_setup()` again. |
||||||
|
|
||||||
|
You must call `psa_hash_abort()` at some point for any operation that is initialized successfully (by a successful call to `psa_hash_setup()`) . |
||||||
|
|
||||||
|
Making multiple sequential calls to `psa_hash_abort()` on an operation that has already been terminated (either implicitly or explicitly) is safe and has no effect. |
||||||
|
|
||||||
|
### Generating a random value |
||||||
|
|
||||||
|
Mbed Crypto can generate random data. |
||||||
|
|
||||||
|
**Prerequisites to generating random data:** |
||||||
|
* Initialize the library with a successful call to `psa_crypto_init()`. |
||||||
|
|
||||||
|
<span class="notes">**Note:** To generate a random key, use `psa_generate_key()` instead of `psa_generate_random()`.</span> |
||||||
|
|
||||||
|
This example shows how to generate ten bytes of random data by calling `psa_generate_random()`: |
||||||
|
```C |
||||||
|
psa_status_t status; |
||||||
|
uint8_t random[10] = { 0 }; |
||||||
|
|
||||||
|
printf("Generate random...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
status = psa_generate_random(random, sizeof(random)); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to generate a random value\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
printf("Generated random data\n"); |
||||||
|
|
||||||
|
/* Clean up */ |
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
``` |
||||||
|
|
||||||
|
### Deriving a new key from an existing key |
||||||
|
|
||||||
|
Mbed Crypto provides a key derivation API that lets you derive new keys from |
||||||
|
existing ones. The key derivation API has functions to take inputs, including |
||||||
|
other keys and data, and functions to generate outputs, such as new keys or |
||||||
|
other data. |
||||||
|
|
||||||
|
You must first initialize and set up a key derivation context, |
||||||
|
provided with a key and, optionally, other data. Then, use the key derivation context to either read derived data to a buffer or send derived data directly to a key slot. |
||||||
|
|
||||||
|
See the documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for |
||||||
|
information about which inputs to pass when, and when you can obtain which outputs. |
||||||
|
|
||||||
|
**Prerequisites to working with the key derivation APIs:** |
||||||
|
* Initialize the library with a successful call to `psa_crypto_init()`. |
||||||
|
* Use a key with the appropriate attributes set: |
||||||
|
* Usage flags set for key derivation (`PSA_KEY_USAGE_DERIVE`) |
||||||
|
* Key type set to `PSA_KEY_TYPE_DERIVE`. |
||||||
|
* Algorithm set to a key derivation algorithm |
||||||
|
(for example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)`). |
||||||
|
|
||||||
|
**To derive a new AES-CTR 128-bit encryption key into a given key slot using HKDF |
||||||
|
with a given key, salt and info:** |
||||||
|
|
||||||
|
1. Set up the key derivation context using the `psa_key_derivation_setup()` |
||||||
|
function, specifying the derivation algorithm `PSA_ALG_HKDF(PSA_ALG_SHA_256)`. |
||||||
|
1. Provide an optional salt with `psa_key_derivation_input_bytes()`. |
||||||
|
1. Provide info with `psa_key_derivation_input_bytes()`. |
||||||
|
1. Provide a secret with `psa_key_derivation_input_key()`, referencing a key that |
||||||
|
can be used for key derivation. |
||||||
|
1. Set the key attributes desired for the new derived key. We'll set |
||||||
|
the `PSA_KEY_USAGE_ENCRYPT` usage flag and the `PSA_ALG_CTR` algorithm for this |
||||||
|
example. |
||||||
|
1. Derive the key by calling `psa_key_derivation_output_key()`. |
||||||
|
1. Clean up the key derivation context. |
||||||
|
|
||||||
|
At this point, the derived key slot holds a new 128-bit AES-CTR encryption key |
||||||
|
derived from the key, salt and info provided: |
||||||
|
```C |
||||||
|
psa_status_t status; |
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
||||||
|
static const unsigned char key[] = { |
||||||
|
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, |
||||||
|
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, |
||||||
|
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, |
||||||
|
0x0b }; |
||||||
|
static const unsigned char salt[] = { |
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, |
||||||
|
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c }; |
||||||
|
static const unsigned char info[] = { |
||||||
|
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, |
||||||
|
0xf7, 0xf8, 0xf9 }; |
||||||
|
psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256); |
||||||
|
psa_key_derivation_operation_t operation = |
||||||
|
PSA_KEY_DERIVATION_OPERATION_INIT; |
||||||
|
size_t derived_bits = 128; |
||||||
|
size_t capacity = PSA_BITS_TO_BYTES(derived_bits); |
||||||
|
psa_key_id_t base_key; |
||||||
|
psa_key_id_t derived_key; |
||||||
|
|
||||||
|
printf("Derive a key (HKDF)...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Import a key for use in key derivation. If such a key has already been |
||||||
|
* generated or imported, you can skip this part. */ |
||||||
|
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); |
||||||
|
psa_set_key_algorithm(&attributes, alg); |
||||||
|
psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE); |
||||||
|
status = psa_import_key(&attributes, key, sizeof(key), &base_key); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to import a key\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
/* Derive a key */ |
||||||
|
status = psa_key_derivation_setup(&operation, alg); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to begin key derivation\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_key_derivation_set_capacity(&operation, capacity); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to set capacity\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_key_derivation_input_bytes(&operation, |
||||||
|
PSA_KEY_DERIVATION_INPUT_SALT, |
||||||
|
salt, sizeof(salt)); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to input salt (extract)\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_key_derivation_input_key(&operation, |
||||||
|
PSA_KEY_DERIVATION_INPUT_SECRET, |
||||||
|
base_key); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to input key (extract)\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
status = psa_key_derivation_input_bytes(&operation, |
||||||
|
PSA_KEY_DERIVATION_INPUT_INFO, |
||||||
|
info, sizeof(info)); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to input info (expand)\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); |
||||||
|
psa_set_key_algorithm(&attributes, PSA_ALG_CTR); |
||||||
|
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); |
||||||
|
psa_set_key_bits(&attributes, 128); |
||||||
|
status = psa_key_derivation_output_key(&attributes, &operation, |
||||||
|
&derived_key); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to derive key\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
printf("Derived key\n"); |
||||||
|
|
||||||
|
/* Clean up key derivation operation */ |
||||||
|
psa_key_derivation_abort(&operation); |
||||||
|
|
||||||
|
/* Destroy the keys */ |
||||||
|
psa_destroy_key(derived_key); |
||||||
|
psa_destroy_key(base_key); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
``` |
||||||
|
|
||||||
|
### Authenticating and encrypting or decrypting a message |
||||||
|
|
||||||
|
Mbed Crypto provides a simple way to authenticate and encrypt with associated data (AEAD), supporting the `PSA_ALG_CCM` algorithm. |
||||||
|
|
||||||
|
**Prerequisites to working with the AEAD cipher APIs:** |
||||||
|
* Initialize the library with a successful call to `psa_crypto_init()`. |
||||||
|
* The key attributes for the key used for derivation must have the `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT` usage flags. |
||||||
|
|
||||||
|
This example shows how to authenticate and encrypt a message: |
||||||
|
```C |
||||||
|
psa_status_t status; |
||||||
|
static const uint8_t key[] = { |
||||||
|
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, |
||||||
|
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }; |
||||||
|
static const uint8_t nonce[] = { |
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
||||||
|
0x08, 0x09, 0x0A, 0x0B }; |
||||||
|
static const uint8_t additional_data[] = { |
||||||
|
0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25, |
||||||
|
0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 }; |
||||||
|
static const uint8_t input_data[] = { |
||||||
|
0xB9, 0x6B, 0x49, 0xE2, 0x1D, 0x62, 0x17, 0x41, |
||||||
|
0x63, 0x28, 0x75, 0xDB, 0x7F, 0x6C, 0x92, 0x43, |
||||||
|
0xD2, 0xD7, 0xC2 }; |
||||||
|
uint8_t *output_data = NULL; |
||||||
|
size_t output_size = 0; |
||||||
|
size_t output_length = 0; |
||||||
|
size_t tag_length = 16; |
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
||||||
|
psa_key_id_t key_id; |
||||||
|
|
||||||
|
printf("Authenticate encrypt...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
output_size = sizeof(input_data) + tag_length; |
||||||
|
output_data = (uint8_t *)malloc(output_size); |
||||||
|
if (!output_data) { |
||||||
|
printf("Out of memory\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Import a key */ |
||||||
|
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); |
||||||
|
psa_set_key_algorithm(&attributes, PSA_ALG_CCM); |
||||||
|
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); |
||||||
|
psa_set_key_bits(&attributes, 128); |
||||||
|
status = psa_import_key(&attributes, key, sizeof(key), &key_id); |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
/* Authenticate and encrypt */ |
||||||
|
status = psa_aead_encrypt(key_id, PSA_ALG_CCM, |
||||||
|
nonce, sizeof(nonce), |
||||||
|
additional_data, sizeof(additional_data), |
||||||
|
input_data, sizeof(input_data), |
||||||
|
output_data, output_size, |
||||||
|
&output_length); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to authenticate and encrypt\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
printf("Authenticated and encrypted\n"); |
||||||
|
|
||||||
|
/* Clean up */ |
||||||
|
free(output_data); |
||||||
|
|
||||||
|
/* Destroy the key */ |
||||||
|
psa_destroy_key(key_id); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
``` |
||||||
|
|
||||||
|
This example shows how to authenticate and decrypt a message: |
||||||
|
|
||||||
|
```C |
||||||
|
psa_status_t status; |
||||||
|
static const uint8_t key_data[] = { |
||||||
|
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, |
||||||
|
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }; |
||||||
|
static const uint8_t nonce[] = { |
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
||||||
|
0x08, 0x09, 0x0A, 0x0B }; |
||||||
|
static const uint8_t additional_data[] = { |
||||||
|
0xEC, 0x46, 0xBB, 0x63, 0xB0, 0x25, |
||||||
|
0x20, 0xC3, 0x3C, 0x49, 0xFD, 0x70 }; |
||||||
|
static const uint8_t input_data[] = { |
||||||
|
0x20, 0x30, 0xE0, 0x36, 0xED, 0x09, 0xA0, 0x45, 0xAF, 0x3C, 0xBA, 0xEE, |
||||||
|
0x0F, 0xC8, 0x48, 0xAF, 0xCD, 0x89, 0x54, 0xF4, 0xF6, 0x3F, 0x28, 0x9A, |
||||||
|
0xA1, 0xDD, 0xB2, 0xB8, 0x09, 0xCD, 0x7C, 0xE1, 0x46, 0xE9, 0x98 }; |
||||||
|
uint8_t *output_data = NULL; |
||||||
|
size_t output_size = 0; |
||||||
|
size_t output_length = 0; |
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
||||||
|
psa_key_id_t key_id; |
||||||
|
|
||||||
|
printf("Authenticate decrypt...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
output_size = sizeof(input_data); |
||||||
|
output_data = (uint8_t *)malloc(output_size); |
||||||
|
if (!output_data) { |
||||||
|
printf("Out of memory\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Import a key */ |
||||||
|
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); |
||||||
|
psa_set_key_algorithm(&attributes, PSA_ALG_CCM); |
||||||
|
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); |
||||||
|
psa_set_key_bits(&attributes, 128); |
||||||
|
status = psa_import_key(&attributes, key_data, sizeof(key_data), &key_id); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to import a key\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
/* Authenticate and decrypt */ |
||||||
|
status = psa_aead_decrypt(key_id, PSA_ALG_CCM, |
||||||
|
nonce, sizeof(nonce), |
||||||
|
additional_data, sizeof(additional_data), |
||||||
|
input_data, sizeof(input_data), |
||||||
|
output_data, output_size, |
||||||
|
&output_length); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to authenticate and decrypt %ld\n", status); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
printf("Authenticated and decrypted\n"); |
||||||
|
|
||||||
|
/* Clean up */ |
||||||
|
free(output_data); |
||||||
|
|
||||||
|
/* Destroy the key */ |
||||||
|
psa_destroy_key(key_id); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
``` |
||||||
|
|
||||||
|
### Generating and exporting keys |
||||||
|
|
||||||
|
Mbed Crypto provides a simple way to generate a key or key pair. |
||||||
|
|
||||||
|
**Prerequisites to using key generation and export APIs:** |
||||||
|
* Initialize the library with a successful call to `psa_crypto_init()`. |
||||||
|
|
||||||
|
**To generate an ECDSA key:** |
||||||
|
1. Set the desired key attributes for key generation by calling |
||||||
|
`psa_set_key_algorithm()` with the chosen ECDSA algorithm (such as |
||||||
|
`PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). You only want to export the public key, not the key pair (or private key); therefore, do not set `PSA_KEY_USAGE_EXPORT`. |
||||||
|
1. Generate a key by calling `psa_generate_key()`. |
||||||
|
1. Export the generated public key by calling `psa_export_public_key()`: |
||||||
|
```C |
||||||
|
enum { |
||||||
|
key_bits = 256, |
||||||
|
}; |
||||||
|
psa_status_t status; |
||||||
|
size_t exported_length = 0; |
||||||
|
static uint8_t exported[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)]; |
||||||
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
||||||
|
psa_key_id_t key_id; |
||||||
|
|
||||||
|
printf("Generate a key pair...\t"); |
||||||
|
fflush(stdout); |
||||||
|
|
||||||
|
/* Initialize PSA Crypto */ |
||||||
|
status = psa_crypto_init(); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to initialize PSA Crypto\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
/* Generate a key */ |
||||||
|
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); |
||||||
|
psa_set_key_algorithm(&attributes, |
||||||
|
PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)); |
||||||
|
psa_set_key_type(&attributes, |
||||||
|
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); |
||||||
|
psa_set_key_bits(&attributes, key_bits); |
||||||
|
status = psa_generate_key(&attributes, &key_id); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to generate key\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
psa_reset_key_attributes(&attributes); |
||||||
|
|
||||||
|
status = psa_export_public_key(key_id, exported, sizeof(exported), |
||||||
|
&exported_length); |
||||||
|
if (status != PSA_SUCCESS) { |
||||||
|
printf("Failed to export public key %ld\n", status); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
printf("Exported a public key\n"); |
||||||
|
|
||||||
|
/* Destroy the key */ |
||||||
|
psa_destroy_key(key_id); |
||||||
|
|
||||||
|
mbedtls_psa_crypto_free(); |
||||||
|
``` |
||||||
|
|
||||||
|
### More about the PSA Crypto API |
||||||
|
|
||||||
|
For more information about the PSA Crypto API, please see the [PSA Cryptography API Specification](https://armmbed.github.io/mbed-crypto/html/index.html). |
@ -0,0 +1,25 @@ |
|||||||
|
PANDOC = pandoc
|
||||||
|
|
||||||
|
default: all |
||||||
|
|
||||||
|
all_markdown = \
|
||||||
|
psa-conditional-inclusion-c.md \
|
||||||
|
psa-driver-developer-guide.md \
|
||||||
|
psa-driver-integration-guide.md \
|
||||||
|
psa-driver-interface.md \
|
||||||
|
# This line is intentionally left blank
|
||||||
|
|
||||||
|
html: $(all_markdown:.md=.html) |
||||||
|
pdf: $(all_markdown:.md=.pdf) |
||||||
|
all: html pdf |
||||||
|
|
||||||
|
.SUFFIXES: |
||||||
|
.SUFFIXES: .md .html .pdf |
||||||
|
|
||||||
|
.md.html: |
||||||
|
$(PANDOC) -o $@ $<
|
||||||
|
.md.pdf: |
||||||
|
$(PANDOC) -o $@ $<
|
||||||
|
|
||||||
|
clean: |
||||||
|
rm -f *.html *.pdf
|
@ -0,0 +1,4 @@ |
|||||||
|
The documents in this directory are proposed specifications for Mbed |
||||||
|
TLS features. They are not implemented yet, or only partially |
||||||
|
implemented. Please follow activity on the `development` branch of |
||||||
|
Mbed TLS if you are interested in these features. |
@ -0,0 +1,244 @@ |
|||||||
|
Conditional inclusion of cryptographic mechanism through the PSA API in Mbed TLS |
||||||
|
================================================================================ |
||||||
|
|
||||||
|
This document is a proposed interface for deciding at build time which cryptographic mechanisms to include in the PSA Cryptography interface. |
||||||
|
|
||||||
|
This is currently a proposal for Mbed TLS. It is not currently on track for standardization in PSA. |
||||||
|
|
||||||
|
## Introduction |
||||||
|
|
||||||
|
### Purpose of this specification |
||||||
|
|
||||||
|
The [PSA Cryptography API specification](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) specifies the interface between a PSA Cryptography implementation and an application. The interface defines a number of categories of cryptographic algorithms (hashes, MAC, signatures, etc.). In each category, a typical implementation offers many algorithms (e.g. for signatures: RSA-PKCS#1v1.5, RSA-PSS, ECDSA). When building the implementation for a specific use case, it is often desirable to include only a subset of the available cryptographic mechanisms, primarily in order to reduce the code footprint of the compiled system. |
||||||
|
|
||||||
|
The present document proposes a way for an application using the PSA cryptography interface to declare which mechanisms it requires. |
||||||
|
|
||||||
|
### Conditional inclusion of legacy cryptography modules |
||||||
|
|
||||||
|
Mbed TLS offers a way to select which cryptographic mechanisms are included in a build through its configuration file (`mbedtls_config.h`). This mechanism is based on two main sets of symbols: `MBEDTLS_xxx_C` controls the availability of the mechanism to the application, and `MBEDTLS_xxx_ALT` controls the availability of an alternative implementation, so the software implementation is only included if `MBEDTLS_xxx_C` is defined but not `MBEDTLS_xxx_ALT`. |
||||||
|
|
||||||
|
### PSA evolution |
||||||
|
|
||||||
|
In the PSA cryptography interface, the **core** (built-in implementations of cryptographic mechanisms) can be augmented with drivers. **Transparent drivers** replace the built-in implementation of a cryptographic mechanism (or, with **fallback**, the built-in implementation is tried if the driver only has partial support for the mechanism). **Opaque drivers** implement cryptographic mechanisms on keys which are stored in a separate domain such as a secure element, for which the core only does key management and dispatch using wrapped key blobs or key identifiers. |
||||||
|
|
||||||
|
The current model is difficult to adapt to the PSA interface for several reasons. The `MBEDTLS_xxx_ALT` symbols are somewhat inconsistent, and in particular do not work well for asymmetric cryptography. For example, many parts of the ECC code have no `MBEDTLS_xxx_ALT` symbol, so a platform with ECC acceleration that can perform all ECDSA and ECDH operations in the accelerator would still embark the `bignum` module and large parts of the `ecp_curves`, `ecp` and `ecdsa` modules. Also the availability of a transparent driver for a mechanism does not translate directly to `MBEDTLS_xxx` symbols. |
||||||
|
|
||||||
|
### Requirements |
||||||
|
|
||||||
|
[Req.interface] The application can declare which cryptographic mechanisms it needs. |
||||||
|
|
||||||
|
[Req.inclusion] If the application does not require a mechanism, a suitably configured Mbed TLS build must not include it. The granularity of mechanisms must work for typical use cases and has [acceptable limitations](#acceptable-limitations). |
||||||
|
|
||||||
|
[Req.drivers] If a PSA driver is available in the build, a suitably configured Mbed TLS build must not include the corresponding software code (unless a software fallback is needed). |
||||||
|
|
||||||
|
[Req.c] The configuration mechanism consists of C preprocessor definitions, and the build does not require tools other than a C compiler. This is necessary to allow building an application and Mbed TLS in development environments that do not allow third-party tools. |
||||||
|
|
||||||
|
[Req.adaptability] The implementation of the mechanism must be adaptable with future evolution of the PSA cryptography specifications and Mbed TLS. Therefore the interface must remain sufficiently simple and abstract. |
||||||
|
|
||||||
|
### Acceptable limitations |
||||||
|
|
||||||
|
[Limitation.matrix] If a mechanism is defined by a combination of algorithms and key types, for example a block cipher mode (CBC, CTR, CFB, …) and a block permutation (AES, CAMELLIA, ARIA, …), there is no requirement to include only specific combinations. |
||||||
|
|
||||||
|
[Limitation.direction] For mechanisms that have multiple directions (for example encrypt/decrypt, sign/verify), there is no requirement to include only one direction. |
||||||
|
|
||||||
|
[Limitation.size] There is no requirement to include only support for certain key sizes. |
||||||
|
|
||||||
|
[Limitation.multipart] Where there are multiple ways to perform an operation, for example single-part and multi-part, there is no mechanism to select only one or a subset of the possible ways. |
||||||
|
|
||||||
|
## Interface |
||||||
|
|
||||||
|
### PSA Crypto configuration file |
||||||
|
|
||||||
|
The PSA Crypto configuration file `psa/crypto_config.h` defines a series of symbols of the form `PSA_WANT_xxx` where `xxx` describes the feature that the symbol enables. The symbols are documented in the section [“PSA Crypto configuration symbols”](#psa-crypto-configuration-symbols) below. |
||||||
|
|
||||||
|
The symbol `MBEDTLS_PSA_CRYPTO_CONFIG` in `mbedtls/mbedtls_config.h` determines whether `psa/crypto_config.h` is used. |
||||||
|
|
||||||
|
* If `MBEDTLS_PSA_CRYPTO_CONFIG` is unset, which is the default at least in Mbed TLS 2.x versions, things are as they are today: the PSA subsystem includes generic code unconditionally, and includes support for specific mechanisms conditionally based on the existing `MBEDTLS_xxx_` symbols. |
||||||
|
* If `MBEDTLS_PSA_CRYPTO_CONFIG` is set, the necessary software implementations of cryptographic algorithms are included based on both the content of the PSA Crypto configuration file and the Mbed TLS configuration file. For example, the code in `aes.c` is enabled if either `mbedtls/mbedtls_config.h` contains `MBEDTLS_AES_C` or `psa/crypto_config.h` contains `PSA_WANT_KEY_TYPE_AES`. |
||||||
|
|
||||||
|
### PSA Crypto configuration symbols |
||||||
|
|
||||||
|
#### Configuration symbol syntax |
||||||
|
|
||||||
|
A PSA Crypto configuration symbol is a C preprocessor symbol whose name starts with `PSA_WANT_`. |
||||||
|
|
||||||
|
* If the symbol is not defined, the corresponding feature is not included. |
||||||
|
* If the symbol is defined to a preprocessor expression with the value `1`, the corresponding feature is included. |
||||||
|
* If the symbol is defined with a different value, the behavior is currently undefined and reserved for future use. |
||||||
|
|
||||||
|
#### Configuration symbol usage |
||||||
|
|
||||||
|
The presence of a symbol `PSA_WANT_xxx` in the Mbed TLS configuration determines whether a feature is available through the PSA API. These symbols should be used in any place that requires conditional compilation based on the availability of a cryptographic mechanism through the PSA API, including: |
||||||
|
|
||||||
|
* In Mbed TLS test code. |
||||||
|
* In Mbed TLS library code using `MBEDTLS_USE_PSA_CRYPTO`, for example in TLS to determine which cipher suites to enable. |
||||||
|
* In application code that provides additional features based on cryptographic capabilities, for example additional key parsing and formatting functions, or cipher suite availability for network protocols. |
||||||
|
|
||||||
|
#### Configuration symbol semantics |
||||||
|
|
||||||
|
If a feature is not requested for inclusion in the PSA Crypto configuration file, it may still be included in the build, either because the feature has been requested in some other way, or because the library does not support the exclusion of this feature. Mbed TLS should make a best effort to support the exclusion of all features, but in some cases this may be judged too much effort for too little benefit. |
||||||
|
|
||||||
|
#### Configuration symbols for key types |
||||||
|
|
||||||
|
For each constant or constructor macro of the form `PSA_KEY_TYPE_xxx`, the symbol **`PSA_WANT_KEY_TYPE_xxx`** indicates that support for this key type is desired. |
||||||
|
|
||||||
|
For asymmetric cryptography, `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR` determines whether private-key operations are desired, and `PSA_WANT_KEY_TYPE_xxx_PUBLIC_KEY` determines whether public-key operations are desired. `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR` implicitly enables `PSA_WANT_KEY_TYPE_xxx_PUBLIC_KEY`: there is no way to only include private-key operations (which typically saves little code). |
||||||
|
|
||||||
|
#### Configuration symbols for elliptic curves |
||||||
|
|
||||||
|
For elliptic curve key types, only the specified curves are included. To include a curve, include a symbol of the form **`PSA_WANT_ECC_family_size`**. For example: `PSA_WANT_ECC_SECP_R1_256` for secp256r1, `PSA_WANT_ECC_MONTGOMERY_255` for Curve25519. It is an error to require an ECC key type but no curve, and Mbed TLS will reject this at compile time. |
||||||
|
|
||||||
|
Rationale: this is a deviation of the general principle that `PSA_ECC_FAMILY_xxx` would have a corresponding symbol `PSA_WANT_ECC_FAMILY_xxx`. This deviation is justified by the fact that it is very common to wish to include only certain curves in a family, and that can lead to a significant gain in code size. |
||||||
|
|
||||||
|
#### Configuration symbols for Diffie-Hellman groups |
||||||
|
|
||||||
|
There are no configuration symbols for Diffie-Hellman groups (`PSA_DH_GROUP_xxx`). |
||||||
|
|
||||||
|
Rationale: Finite-field Diffie-Hellman code is usually not specialized for any particular group, so reducing the number of available groups at compile time only saves a little code space. Constrained implementations tend to omit FFDH anyway, so the small code size gain is not important. |
||||||
|
|
||||||
|
#### Configuration symbols for algorithms |
||||||
|
|
||||||
|
For each constant or constructor macro of the form `PSA_ALG_xxx`, the symbol **`PSA_WANT_ALG_xxx`** indicates that support for this algorithm is desired. |
||||||
|
|
||||||
|
For parametrized algorithms, the `PSA_WANT_ALG_xxx` symbol indicates whether the base mechanism is supported. Parameters must themselves be included through their own `PSA_WANT_ALG_xxx` symbols. It is an error to include a base mechanism without at least one possible parameter, and Mbed TLS will reject this at compile time. For example, `PSA_WANT_ALG_ECDSA` requires the inclusion of randomized ECDSA for all hash algorithms whose corresponding symbol `PSA_WANT_ALG_xxx` is enabled. |
||||||
|
|
||||||
|
## Implementation |
||||||
|
|
||||||
|
### Additional non-public symbols |
||||||
|
|
||||||
|
#### Accounting for transparent drivers |
||||||
|
|
||||||
|
In addition to the [configuration symbols](#psa-crypto-configuration-symbols), we need two parallel or mostly parallel sets of symbols: |
||||||
|
|
||||||
|
* **`MBEDTLS_PSA_ACCEL_xxx`** indicates whether a fully-featured, fallback-free transparent driver is available. |
||||||
|
* **`MBEDTLS_PSA_BUILTIN_xxx`** indicates whether the software implementation is needed. |
||||||
|
|
||||||
|
`MBEDTLS_PSA_ACCEL_xxx` is one of the outputs of the transpilation of a driver description, alongside the glue code for calling the drivers. |
||||||
|
|
||||||
|
`MBEDTLS_PSA_BUILTIN_xxx` is enabled when `PSA_WANT_xxx` is enabled and `MBEDTLS_PSA_ACCEL_xxx` is disabled. |
||||||
|
|
||||||
|
These symbols are not part of the public interface of Mbed TLS towards applications or to drivers, regardless of whether the symbols are actually visible. |
||||||
|
|
||||||
|
### Architecture of symbol definitions |
||||||
|
|
||||||
|
#### New-style definition of configuration symbols |
||||||
|
|
||||||
|
When `MBEDTLS_PSA_CRYPTO_CONFIG` is set, the header file `mbedtls/mbedtls_config.h` needs to define all the `MBEDTLS_xxx_C` configuration symbols, including the ones deduced from the PSA Crypto configuration. It does this by including the new header file **`mbedtls/config_psa.h`**, which defines the `MBEDTLS_PSA_BUILTIN_xxx` symbols and deduces the corresponding `MBEDTLS_xxx_C` (and other) symbols. |
||||||
|
|
||||||
|
`mbedtls/config_psa.h` includes `psa/crypto_config.h`, the user-editable file that defines application requirements. |
||||||
|
|
||||||
|
#### Old-style definition of configuration symbols |
||||||
|
|
||||||
|
When `MBEDTLS_PSA_CRYPTO_CONFIG` is not set, the configuration of Mbed TLS works as before, and the inclusion of non-PSA code only depends on `MBEDTLS_xxx` symbols defined (or not) in `mbedtls/mbedtls_config.h`. Furthermore, the new header file **`mbedtls/config_psa.h`** deduces PSA configuration symbols (`PSA_WANT_xxx`, `MBEDTLS_PSA_BUILTIN_xxx`) from classic configuration symbols (`MBEDTLS_xxx`). |
||||||
|
|
||||||
|
The `PSA_WANT_xxx` definitions in `mbedtls/config_psa.h` are needed not only to build the PSA parts of the library, but also to build code that uses these parts. This includes structure definitions in `psa/crypto_struct.h`, size calculations in `psa/crypto_sizes.h`, and application code that's specific to a given cryptographic mechanism. In Mbed TLS itself, code under `MBEDTLS_USE_PSA_CRYPTO` and conditional compilation guards in tests and sample programs need `PSA_WANT_xxx`. |
||||||
|
|
||||||
|
Since some existing applications use a handwritten `mbedtls/mbedtls_config.h` or an edited copy of `mbedtls/mbedtls_config.h` from an earlier version of Mbed TLS, `mbedtls/config_psa.h` must be included via an already existing header that is not `mbedtls/mbedtls_config.h`, so it is included via `psa/crypto.h` (for example from `psa/crypto_platform.h`). |
||||||
|
|
||||||
|
#### Summary of definitions of configuration symbols |
||||||
|
|
||||||
|
Whether `MBEDTLS_PSA_CRYPTO_CONFIG` is set or not, `mbedtls/config_psa.h` includes `mbedtls/crypto_drivers.h`, a header file generated by the transpilation of the driver descriptions. It defines `MBEDTLS_PSA_ACCEL_xxx` symbols according to the availability of transparent drivers without fallback. |
||||||
|
|
||||||
|
The following table summarizes where symbols are defined depending on the configuration mode. |
||||||
|
|
||||||
|
* (U) indicates a symbol that is defined by the user (application). |
||||||
|
* (D) indicates a symbol that is deduced from other symbols by code that ships with Mbed TLS. |
||||||
|
* (G) indicates a symbol that is generated from driver descriptions. |
||||||
|
|
||||||
|
| Symbols | With `MBEDTLS_PSA_CRYPTO_CONFIG` | Without `MBEDTLS_PSA_CRYPTO_CONFIG` | |
||||||
|
| ------------------------- | --------------------------------- | ----------------------------------- | |
||||||
|
| `MBEDTLS_xxx_C` | `mbedtls/mbedtls_config.h` (U) or | `mbedtls/mbedtls_config.h` (U) | |
||||||
|
| | `mbedtls/config_psa.h` (D) | | |
||||||
|
| `PSA_WANT_xxx` | `psa/crypto_config.h` (U) | `mbedtls/config_psa.h` (D) | |
||||||
|
| `MBEDTLS_PSA_BUILTIN_xxx` | `mbedtls/config_psa.h` (D) | `mbedtls/config_psa.h` (D) | |
||||||
|
| `MBEDTLS_PSA_ACCEL_xxx` | `mbedtls/crypto_drivers.h` (G) | N/A | |
||||||
|
|
||||||
|
#### Visibility of internal symbols |
||||||
|
|
||||||
|
Ideally, the `MBEDTLS_PSA_ACCEL_xxx` and `MBEDTLS_PSA_BUILTIN_xxx` symbols should not be visible to application code or driver code, since they are not part of the public interface of the library. However these symbols are needed to deduce whether to include library modules (for example `MBEDTLS_AES_C` has to be enabled if `MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES` is enabled), which makes it difficult to keep them private. |
||||||
|
|
||||||
|
#### Compile-time checks |
||||||
|
|
||||||
|
The header file **`library/psa_check_config.h`** applies sanity checks to the configuration, throwing `#error` if something is wrong. |
||||||
|
|
||||||
|
A mechanism similar to `mbedtls/check_config.h` detects errors such as enabling ECDSA but no curve. |
||||||
|
|
||||||
|
Since configuration symbols must be undefined or 1, any other value should trigger an `#error`. |
||||||
|
|
||||||
|
#### Automatic generation of preprocessor symbol manipulations |
||||||
|
|
||||||
|
A lot of the preprocessor symbol manipulation is systematic calculations that analyze the configuration. `mbedtls/config_psa.h` and `library/psa_check_config.h` should be generated automatically, in the same manner as `version_features.c`. |
||||||
|
|
||||||
|
### Structure of PSA Crypto library code |
||||||
|
|
||||||
|
#### Conditional inclusion of library entry points |
||||||
|
|
||||||
|
An entry point can be eliminated entirely if no algorithm requires it. |
||||||
|
|
||||||
|
#### Conditional inclusion of mechanism-specific code |
||||||
|
|
||||||
|
Code that is specific to certain key types or to certain algorithms must be guarded by the applicable symbols: `PSA_WANT_xxx` for code that is independent of the application, and `MBEDTLS_PSA_BUILTIN_xxx` for code that calls an Mbed TLS software implementation. |
||||||
|
|
||||||
|
## PSA standardization |
||||||
|
|
||||||
|
### JSON configuration mechanism |
||||||
|
|
||||||
|
At the time of writing, the preferred configuration mechanism for a PSA service is in JSON syntax. The translation from JSON to build instructions is not specified by PSA. |
||||||
|
|
||||||
|
For PSA Crypto, the preferred configuration mechanism would be similar to capability specifications of transparent drivers. The same JSON properties that are used to mean “this driver can perform that mechanism” in a driver description would be used to mean “the application wants to perform that mechanism” in the application configuration. |
||||||
|
|
||||||
|
### From JSON to C |
||||||
|
|
||||||
|
The JSON capability language allows a more fine-grained selection than the C mechanism proposed here. For example, it allows requesting only single-part mechanisms, only certain key sizes, or only certain combinations of algorithms and key types. |
||||||
|
|
||||||
|
The JSON capability language can be translated approximately to the boolean symbol mechanism proposed here. The approximation considers a feature to be enabled if any part of it is enabled. For example, if there is a capability for AES-CTR and one for CAMELLIA-GCM, the translation to boolean symbols will also include AES-GCM and CAMELLIA-CTR. If there is a capability for AES-128, the translation will also include AES-192 and AES-256. |
||||||
|
|
||||||
|
The boolean symbol mechanism proposed here can be translated to a list of JSON capabilities: for each included algorithm, include a capability with that algorithm, the key types that apply to that algorithm, no size restriction, and all the entry points that apply to that algorithm. |
||||||
|
|
||||||
|
## Open questions |
||||||
|
|
||||||
|
### Open questions about the interface |
||||||
|
|
||||||
|
#### Naming of symbols |
||||||
|
|
||||||
|
The names of [elliptic curve symbols](#configuration-symbols-for-elliptic-curves) are a bit weird: `SECP_R1_256` instead of `SECP256R1`, `MONTGOMERY_255` instead of `CURVE25519`. Should we make them more classical, but less systematic? |
||||||
|
|
||||||
|
#### Impossible combinations |
||||||
|
|
||||||
|
What does it mean to have `PSA_WANT_ALG_ECDSA` enabled but with only Curve25519? Is it a mandatory error? |
||||||
|
|
||||||
|
#### Diffie-Hellman |
||||||
|
|
||||||
|
Way to request only specific groups? Not a priority: constrained devices don't do FFDH. Specify it as may change in future versions. |
||||||
|
|
||||||
|
#### Coexistence with the current Mbed TLS configuration |
||||||
|
|
||||||
|
The two mechanisms have very different designs. Is there serious potential for confusion? Do we understand how the combinations work? |
||||||
|
|
||||||
|
### Open questions about the design |
||||||
|
|
||||||
|
#### Algorithms without a key type or vice versa |
||||||
|
|
||||||
|
Is it realistic to mandate a compile-time error if a key type is required, but no matching algorithm, or vice versa? Is it always the right thing, for example if there is an opaque driver that manipulates this key type? |
||||||
|
|
||||||
|
#### Opaque-only mechanisms |
||||||
|
|
||||||
|
If a mechanism should only be supported in an opaque driver, what does the core need to know about it? Do we have all the information we need? |
||||||
|
|
||||||
|
This is especially relevant to suppress a mechanism completely if there is no matching algorithm. For example, if there is no transparent implementation of RSA or ECDSA, `psa_sign_hash` and `psa_verify_hash` may still be needed if there is an opaque signature driver. |
||||||
|
|
||||||
|
### Open questions about the implementation |
||||||
|
|
||||||
|
#### Testability |
||||||
|
|
||||||
|
Is this proposal decently testable? There are a lot of combinations. What combinations should we test? |
||||||
|
|
||||||
|
<!-- |
||||||
|
Local Variables: |
||||||
|
time-stamp-line-limit: 40 |
||||||
|
time-stamp-start: "Time-stamp: *\"" |
||||||
|
time-stamp-end: "\"" |
||||||
|
time-stamp-format: "%04Y/%02m/%02d %02H:%02M:%02S %Z" |
||||||
|
time-stamp-time-zone: "GMT" |
||||||
|
End: |
||||||
|
--> |
@ -0,0 +1,51 @@ |
|||||||
|
PSA Cryptoprocessor driver developer's guide |
||||||
|
============================================ |
||||||
|
|
||||||
|
**This is a specification of work in progress. The implementation is not yet merged into Mbed TLS.** |
||||||
|
|
||||||
|
This document describes how to write drivers of cryptoprocessors such as accelerators and secure elements for the PSA cryptography subsystem of Mbed TLS. |
||||||
|
|
||||||
|
This document focuses on behavior that is specific to Mbed TLS. For a reference of the interface between Mbed TLS and drivers, refer to the [PSA Cryptoprocessor Driver Interface specification](psa-driver-interface.html). |
||||||
|
|
||||||
|
The interface is not fully implemented in Mbed TLS yet and is disabled by default. You can enable the experimental work in progress by setting `MBEDTLS_PSA_CRYPTO_DRIVERS` in the compile-time configuration. Please note that the interface may still change: until further notice, we do not guarantee backward compatibility with existing driver code when `MBEDTLS_PSA_CRYPTO_DRIVERS` is enabled. |
||||||
|
|
||||||
|
## Introduction |
||||||
|
|
||||||
|
### Purpose |
||||||
|
|
||||||
|
The PSA cryptography driver interface provides a way to build Mbed TLS with additional code that implements certain cryptographic primitives. This is primarily intended to support platform-specific hardware. |
||||||
|
|
||||||
|
There are two types of drivers: |
||||||
|
|
||||||
|
* **Transparent** drivers implement cryptographic operations on keys that are provided in cleartext at the beginning of each operation. They are typically used for hardware **accelerators**. When a transparent driver is available for a particular combination of parameters (cryptographic algorithm, key type and size, etc.), it is used instead of the default software implementation. Transparent drivers can also be pure software implementations that are distributed as plug-ins to a PSA Crypto implementation. |
||||||
|
* **Opaque** drivers implement cryptographic operations on keys that can only be used inside a protected environment such as a **secure element**, a hardware security module, a smartcard, a secure enclave, etc. An opaque driver is invoked for the specific key location that the driver is registered for: the dispatch is based on the key's lifetime. |
||||||
|
|
||||||
|
### Deliverables for a driver |
||||||
|
|
||||||
|
To write a driver, you need to implement some functions with C linkage, and to declare these functions in a **driver description file**. The driver description file declares which functions the driver implements and what cryptographic mechanisms they support. Depending on the driver type, you may also need to define some C types and macros in a header file. |
||||||
|
|
||||||
|
The concrete syntax for a driver description file is JSON. The structure of this JSON file is specified in the section [“Driver description syntax”](psa-driver-interface.html#driver-description-syntax) of the PSA cryptography driver interface specification. |
||||||
|
|
||||||
|
A driver therefore consists of: |
||||||
|
|
||||||
|
* A driver description file (in JSON format). |
||||||
|
* C header files defining the types required by the driver description. The names of these header files is declared in the driver description file. |
||||||
|
* An object file compiled for the target platform defining the functions required by the driver description. Implementations may allow drivers to be provided as source files and compiled with the core instead of being pre-compiled. |
||||||
|
|
||||||
|
## Driver C interfaces |
||||||
|
|
||||||
|
Mbed TLS calls driver entry points [as specified in the PSA Cryptography Driver Interface specification](psa-driver-interface.html#driver-entry-points) except as otherwise indicated in this section. |
||||||
|
|
||||||
|
## Mbed TLS extensions |
||||||
|
|
||||||
|
The driver description can include Mbed TLS extensions (marked by the namespace "mbedtls"). Mbed TLS extensions are meant to extend/help integrating the driver into the library's infrastructure. |
||||||
|
* `"mbedtls/h_condition"` (optional, string) can include complex preprocessor definitions to conditionally include header files for a given driver. |
||||||
|
* `"mbedtls/c_condition"` (optional, string) can include complex preprocessor definitions to conditionally enable dispatch capabilities for a driver. |
||||||
|
|
||||||
|
## Building and testing your driver |
||||||
|
|
||||||
|
<!-- TODO --> |
||||||
|
|
||||||
|
## Dependencies on the Mbed TLS configuration |
||||||
|
|
||||||
|
<!-- TODO --> |
@ -0,0 +1,45 @@ |
|||||||
|
Building Mbed TLS with PSA cryptoprocessor drivers |
||||||
|
================================================== |
||||||
|
|
||||||
|
**This is a specification of work in progress. The implementation is not yet merged into Mbed TLS.** |
||||||
|
|
||||||
|
This document describes how to build Mbed TLS with additional cryptoprocessor drivers that follow the PSA cryptoprocessor driver interface. |
||||||
|
|
||||||
|
The interface is not fully implemented in Mbed TLS yet and is disabled by default. You can enable the experimental work in progress by setting `MBEDTLS_PSA_CRYPTO_DRIVERS` in the compile-time configuration. Please note that the interface may still change: until further notice, we do not guarantee backward compatibility with existing driver code when `MBEDTLS_PSA_CRYPTO_DRIVERS` is enabled. |
||||||
|
|
||||||
|
## Introduction |
||||||
|
|
||||||
|
The PSA cryptography driver interface provides a way to build Mbed TLS with additional code that implements certain cryptographic primitives. This is primarily intended to support platform-specific hardware. |
||||||
|
|
||||||
|
Note that such drivers are only available through the PSA cryptography API (crypto functions beginning with `psa_`, and X.509 and TLS interfaces that reference PSA types). |
||||||
|
|
||||||
|
Concretely speaking, a driver consists of one or more **driver description files** in JSON format and some code to include in the build. The driver code can either be provided in binary form as additional object file to link, or in source form. |
||||||
|
|
||||||
|
## How to build Mbed TLS with drivers |
||||||
|
|
||||||
|
To build Mbed TLS with drivers: |
||||||
|
|
||||||
|
1. Activate `MBEDTLS_PSA_CRYPTO_DRIVERS` in the library configuration. |
||||||
|
|
||||||
|
``` |
||||||
|
cd /path/to/mbedtls |
||||||
|
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS |
||||||
|
``` |
||||||
|
|
||||||
|
2. Pass the driver description files through the Make variable `PSA_DRIVERS` when building the library. |
||||||
|
|
||||||
|
``` |
||||||
|
cd /path/to/mbedtls |
||||||
|
make PSA_DRIVERS="/path/to/acme/driver.json /path/to/nadir/driver.json" lib |
||||||
|
``` |
||||||
|
|
||||||
|
3. Link your application with the implementation of the driver functions. |
||||||
|
|
||||||
|
``` |
||||||
|
cd /path/to/application |
||||||
|
ld myapp.o -L/path/to/acme -lacmedriver -L/path/to/nadir -lnadirdriver -L/path/to/mbedtls -lmbedcrypto |
||||||
|
``` |
||||||
|
|
||||||
|
<!-- TODO: what if the driver is provided as C source code? --> |
||||||
|
|
||||||
|
<!-- TODO: what about additional include files? --> |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,40 @@ |
|||||||
|
Migrating to an auto generated psa_crypto_driver_wrappers.c file |
||||||
|
================================================================ |
||||||
|
|
||||||
|
**This is a specification of work in progress. The implementation is not yet merged into Mbed TLS.** |
||||||
|
|
||||||
|
This document describes how to migrate to the auto generated psa_crypto_driver_wrappers.c file. |
||||||
|
It is meant to give the library user migration guidelines while the Mbed TLS project tides over multiple minor revs of version 1.0, after which this will be merged into psa-driver-interface.md. |
||||||
|
|
||||||
|
## Introduction |
||||||
|
|
||||||
|
The design of the Driver Wrappers code generation is based on the design proposal https://github.com/Mbed-TLS/mbedtls/pull/5067 |
||||||
|
During the process of implementation there might be minor variations wrt versioning and broader implementation specific ideas, but the design remains the same. |
||||||
|
|
||||||
|
## Prerequisites |
||||||
|
|
||||||
|
Python3, Jinja2 rev 2.10.1 and jsonschema rev 3.2.0 |
||||||
|
|
||||||
|
## Feature Version |
||||||
|
|
||||||
|
1.1 |
||||||
|
|
||||||
|
### What's critical for a migrating user |
||||||
|
|
||||||
|
The Driver Wrapper auto generation project is designed to use a python templating library ( Jinja2 ) to render templates based on drivers that are defined using a Driver description JSON file(s). |
||||||
|
|
||||||
|
While that is the larger goal, for version 1.1 here's what's changed |
||||||
|
|
||||||
|
#### What's changed |
||||||
|
|
||||||
|
(1) psa_crypto_driver_wrappers.c will from this point on be auto generated. |
||||||
|
(2) The auto generation is based on the template file at **scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja**. |
||||||
|
(3) The driver JSONS to be used for generating the psa_crypto_driver_wrappers.c file can be found at **scripts/data_files/driver_jsons/** as their default location, this path includes the schemas against which the driver schemas will be validated (driver_opaque_schema.json, driver_transparent_schema.json) and a driverlist.json which specifies the drivers to be considered and the order in which they want to be called into. The default location for driverlist.json and driver JSONS can be overloaded by passing an argument --json-dir while running the script generate_driver_wrappers.py. |
||||||
|
(4) While the complete driver wrapper templating support is yet to come in, if the library user sees a need to patch psa_crypto_driver_wrappers.c file, the user will need to patch into the template file as needed (psa_crypto_driver_wrappers.c.jinja). |
||||||
|
|
||||||
|
#### How to set your driver up |
||||||
|
|
||||||
|
Please refer to psa-driver-interface.md for information on how a driver schema can be written. |
||||||
|
One can also refer to the example test drivers/ JSON schemas under **scripts/data_files/driver_jsons/**. |
||||||
|
|
||||||
|
The JSON file 'driverlist.json' is meant to be edited by the user to reflect the drivers one wants to use on a device. The order in which the drivers are passed is also essential if/when there are multiple transparent drivers on a given system to retain the same order in the templating. |
@ -0,0 +1,114 @@ |
|||||||
|
This document describes the compile-time configuration option |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` from a user's perspective. |
||||||
|
|
||||||
|
This option makes the X.509 and TLS library use PSA for cryptographic |
||||||
|
operations, and enables new APIs for using keys handled by PSA Crypto. |
||||||
|
|
||||||
|
General considerations |
||||||
|
---------------------- |
||||||
|
|
||||||
|
**Compile-time:** enabling `MBEDTLS_USE_PSA_CRYPTO` requires |
||||||
|
`MBEDTLS_ECP_RESTARTABLE` to be disabled. |
||||||
|
|
||||||
|
**Application code:** when this option is enabled, you need to call |
||||||
|
`psa_crypto_init()` before calling any function from the SSL/TLS, X.509 or PK |
||||||
|
module. |
||||||
|
|
||||||
|
**Scope:** `MBEDTLS_USE_PSA_CRYPTO` has no effect on the parts of the code that |
||||||
|
are specific to TLS 1.3; those parts always use PSA Crypto. The parts of the |
||||||
|
TLS 1.3 code that are common with TLS 1.2, however, follow this option; |
||||||
|
currently this is the record protection code, computation of the running |
||||||
|
handshake hash, and X.509. You need to enable `MBEDTLS_USE_PSA_CRYPTO` if you |
||||||
|
want TLS 1.3 to use PSA everywhere. |
||||||
|
|
||||||
|
New APIs / API extensions |
||||||
|
------------------------- |
||||||
|
|
||||||
|
### PSA-held (opaque) keys in the PK layer |
||||||
|
|
||||||
|
**New API function:** `mbedtls_pk_setup_opaque()` - can be used to |
||||||
|
wrap a PSA key pair into a PK context. The key can be used for private-key |
||||||
|
operations and its public part can be exported. |
||||||
|
|
||||||
|
**Benefits:** isolation of long-term secrets, use of PSA Crypto drivers. |
||||||
|
|
||||||
|
**Limitations:** can only wrap a key pair, can only use it for private key |
||||||
|
operations. (That is, signature generation, and for RSA decryption too.) |
||||||
|
Note: for ECDSA, currently this uses randomized ECDSA while Mbed TLS uses |
||||||
|
deterministic ECDSA by default. The following operations are not supported |
||||||
|
with a context set this way, while they would be available with a normal |
||||||
|
context: `mbedtls_pk_check_pair()`, `mbedtls_pk_debug()`, all public key |
||||||
|
operations. |
||||||
|
|
||||||
|
**Use in X.509 and TLS:** opt-in. The application needs to construct the PK context |
||||||
|
using the new API in order to get the benefits; it can then pass the |
||||||
|
resulting context to the following existing APIs: |
||||||
|
|
||||||
|
- `mbedtls_ssl_conf_own_cert()` or `mbedtls_ssl_set_hs_own_cert()` to use the |
||||||
|
key together with a certificate for certificate-based key exchanges; |
||||||
|
- `mbedtls_x509write_csr_set_key()` to generate a CSR (certificate signature |
||||||
|
request); |
||||||
|
- `mbedtls_x509write_crt_set_issuer_key()` to generate a certificate. |
||||||
|
|
||||||
|
### PSA-held (opaque) keys for TLS pre-shared keys (PSK) |
||||||
|
|
||||||
|
**New API functions:** `mbedtls_ssl_conf_psk_opaque()` and |
||||||
|
`mbedtls_ssl_set_hs_psk_opaque()`. Call one of these from an application to |
||||||
|
register a PSA key for use with a PSK key exchange. |
||||||
|
|
||||||
|
**Benefits:** isolation of long-term secrets. |
||||||
|
|
||||||
|
**Limitations:** none. |
||||||
|
|
||||||
|
**Use in TLS:** opt-in. The application needs to register the key using one of |
||||||
|
the new APIs to get the benefits. |
||||||
|
|
||||||
|
### PSA-based operations in the Cipher layer |
||||||
|
|
||||||
|
There is a new API function `mbedtls_cipher_setup_psa()` to set up a context |
||||||
|
that will call PSA to store the key and perform the operations. |
||||||
|
|
||||||
|
This function only worked for a small number of ciphers. It is now deprecated |
||||||
|
and it is recommended to use `psa_cipher_xxx()` or `psa_aead_xxx()` functions |
||||||
|
directly instead. |
||||||
|
|
||||||
|
**Warning:** This function will be removed in a future version of Mbed TLS. If |
||||||
|
you are using it and would like us to keep it, please let us know about your |
||||||
|
use case. |
||||||
|
|
||||||
|
Internal changes |
||||||
|
---------------- |
||||||
|
|
||||||
|
All of these internal changes are active as soon as `MBEDTLS_USE_PSA_CRYPTO` |
||||||
|
is enabled, no change required on the application side. |
||||||
|
|
||||||
|
### TLS: most crypto operations based on PSA |
||||||
|
|
||||||
|
Current exceptions: |
||||||
|
|
||||||
|
- finite-field (non-EC) Diffie-Hellman (used in key exchanges: DHE-RSA, |
||||||
|
DHE-PSK) |
||||||
|
|
||||||
|
Other than the above exceptions, all crypto operations are based on PSA when |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` is enabled. |
||||||
|
|
||||||
|
### X.509: most crypto operations based on PSA |
||||||
|
|
||||||
|
Current exception: |
||||||
|
|
||||||
|
- verification of RSA-PSS signatures with a salt length that is different from |
||||||
|
the hash length. |
||||||
|
|
||||||
|
Other than the above exception, all crypto operations are based on PSA when |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` is enabled. |
||||||
|
|
||||||
|
### PK layer: most crypto operations based on PSA |
||||||
|
|
||||||
|
Current exception: |
||||||
|
|
||||||
|
- verification of RSA-PSS signatures with a salt length that is different from |
||||||
|
the hash length, or with an MGF hash that's different from the message hash. |
||||||
|
|
||||||
|
Other than the above exception, all crypto operations are based on PSA when |
||||||
|
`MBEDTLS_USE_PSA_CRYPTO` is enabled. |
||||||
|
|
@ -0,0 +1,66 @@ |
|||||||
|
/**
|
||||||
|
* \file doc_encdec.h |
||||||
|
* |
||||||
|
* \brief Encryption/decryption module documentation file. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 encryption 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()). |
||||||
|
* - 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()) |
||||||
|
* - 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. |
||||||
|
*/ |
@ -0,0 +1,42 @@ |
|||||||
|
/**
|
||||||
|
* \file doc_hashing.h |
||||||
|
* |
||||||
|
* \brief Hashing module documentation file. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @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: |
||||||
|
* - MD5 128-bit one-way hash function 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. |
||||||
|
*/ |
@ -0,0 +1,94 @@ |
|||||||
|
/**
|
||||||
|
* \file doc_mainpage.h |
||||||
|
* |
||||||
|
* \brief Main page documentation file. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @mainpage mbed TLS v3.3.0 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 TLSv1.0 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) |
||||||
|
*/ |
@ -0,0 +1,39 @@ |
|||||||
|
/**
|
||||||
|
* \file doc_rng.h |
||||||
|
* |
||||||
|
* \brief Random number generator (RNG) module documentation file. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @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. |
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
@ -0,0 +1,49 @@ |
|||||||
|
/**
|
||||||
|
* \file doc_ssltls.h |
||||||
|
* |
||||||
|
* \brief SSL/TLS communication module documentation file. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @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. |
||||||
|
*/ |
@ -0,0 +1,44 @@ |
|||||||
|
/**
|
||||||
|
* \file doc_tcpip.h |
||||||
|
* |
||||||
|
* \brief TCP/IP communication module documentation file. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @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. |
||||||
|
*/ |
@ -0,0 +1,43 @@ |
|||||||
|
/**
|
||||||
|
* \file doc_x509.h |
||||||
|
* |
||||||
|
* \brief X.509 module documentation file. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @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. |
||||||
|
*/ |
@ -0,0 +1,29 @@ |
|||||||
|
PROJECT_NAME = "mbed TLS v3.3.0" |
||||||
|
OUTPUT_DIRECTORY = ../apidoc/ |
||||||
|
FULL_PATH_NAMES = NO |
||||||
|
OPTIMIZE_OUTPUT_FOR_C = YES |
||||||
|
EXTRACT_ALL = YES |
||||||
|
EXTRACT_PRIVATE = YES |
||||||
|
EXTRACT_STATIC = YES |
||||||
|
CASE_SENSE_NAMES = NO |
||||||
|
INPUT = ../include input |
||||||
|
FILE_PATTERNS = *.h |
||||||
|
RECURSIVE = YES |
||||||
|
EXCLUDE_SYMLINKS = YES |
||||||
|
SOURCE_BROWSER = YES |
||||||
|
REFERENCED_BY_RELATION = YES |
||||||
|
REFERENCES_RELATION = YES |
||||||
|
ALPHABETICAL_INDEX = NO |
||||||
|
HTML_OUTPUT = . |
||||||
|
HTML_TIMESTAMP = YES |
||||||
|
SEARCHENGINE = YES |
||||||
|
GENERATE_LATEX = NO |
||||||
|
MACRO_EXPANSION = YES |
||||||
|
EXPAND_ONLY_PREDEF = YES |
||||||
|
INCLUDE_PATH = ../include |
||||||
|
EXPAND_AS_DEFINED = MBEDTLS_PRIVATE |
||||||
|
CLASS_DIAGRAMS = NO |
||||||
|
HAVE_DOT = YES |
||||||
|
DOT_GRAPH_MAX_NODES = 200 |
||||||
|
MAX_DOT_GRAPH_DEPTH = 1000 |
||||||
|
DOT_TRANSPARENT = YES |
@ -0,0 +1,4 @@ |
|||||||
|
Makefile |
||||||
|
*.sln |
||||||
|
*.vcxproj |
||||||
|
mbedtls/check_config |
@ -0,0 +1,22 @@ |
|||||||
|
option(INSTALL_MBEDTLS_HEADERS "Install mbed TLS headers." ON) |
||||||
|
|
||||||
|
if(INSTALL_MBEDTLS_HEADERS) |
||||||
|
|
||||||
|
file(GLOB headers "mbedtls/*.h") |
||||||
|
file(GLOB psa_headers "psa/*.h") |
||||||
|
|
||||||
|
install(FILES ${headers} |
||||||
|
DESTINATION include/mbedtls |
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) |
||||||
|
|
||||||
|
install(FILES ${psa_headers} |
||||||
|
DESTINATION include/psa |
||||||
|
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) |
||||||
|
|
||||||
|
endif(INSTALL_MBEDTLS_HEADERS) |
||||||
|
|
||||||
|
# Make mbedtls_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) |
||||||
|
link_to_source(psa) |
||||||
|
endif() |
@ -0,0 +1,636 @@ |
|||||||
|
/**
|
||||||
|
* \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 |
||||||
|
* <em>FIPS Publication 197: Advanced Encryption Standard</em> and |
||||||
|
* <em>ISO/IEC 18033-2:2006: Information technology -- Security |
||||||
|
* techniques -- Encryption algorithms -- Part 2: Asymmetric |
||||||
|
* ciphers</em>. |
||||||
|
* |
||||||
|
* The AES-XTS block mode is standardized by NIST SP 800-38E |
||||||
|
* <https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38e.pdf>
|
||||||
|
* and described in detail by IEEE P1619 |
||||||
|
* <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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_AES_H |
||||||
|
#define MBEDTLS_AES_H |
||||||
|
#include "mbedtls/private_access.h" |
||||||
|
|
||||||
|
#include "mbedtls/build_info.h" |
||||||
|
#include "mbedtls/platform_util.h" |
||||||
|
|
||||||
|
#include <stddef.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
/* 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 */ |
||||||
|
/** Invalid key length. */ |
||||||
|
#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 |
||||||
|
/** Invalid data input length. */ |
||||||
|
#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 |
||||||
|
|
||||||
|
/* Error codes in range 0x0021-0x0025 */ |
||||||
|
/** Invalid input data. */ |
||||||
|
#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
#if !defined(MBEDTLS_AES_ALT) |
||||||
|
// Regular implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The AES context-type definition. |
||||||
|
*/ |
||||||
|
typedef struct mbedtls_aes_context |
||||||
|
{ |
||||||
|
int MBEDTLS_PRIVATE(nr); /*!< The number of rounds. */ |
||||||
|
size_t MBEDTLS_PRIVATE(rk_offset); /*!< The offset in array elements to AES
|
||||||
|
round keys in the buffer. */ |
||||||
|
uint32_t MBEDTLS_PRIVATE(buf)[68]; /*!< Unaligned data buffer. This buffer can
|
||||||
|
hold 32 extra Bytes, which can be used for |
||||||
|
one of the following purposes: |
||||||
|
<ul><li>Alignment if VIA padlock is |
||||||
|
used.</li> |
||||||
|
<li>Simplifying key expansion in the 256-bit |
||||||
|
case by generating an extra round key. |
||||||
|
</li></ul> */ |
||||||
|
} |
||||||
|
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 MBEDTLS_PRIVATE(crypt); /*!< The AES context to use for AES block
|
||||||
|
encryption or decryption. */ |
||||||
|
mbedtls_aes_context MBEDTLS_PRIVATE(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: |
||||||
|
* <ul><li>128 bits</li> |
||||||
|
* <li>192 bits</li> |
||||||
|
* <li>256 bits</li></ul> |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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: |
||||||
|
* <ul><li>128 bits</li> |
||||||
|
* <li>192 bits</li> |
||||||
|
* <li>256 bits</li></ul> |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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: |
||||||
|
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> |
||||||
|
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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: |
||||||
|
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> |
||||||
|
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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). |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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. |
||||||
|
* |
||||||
|
* 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 strategies, 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. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
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. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_TYPICAL |
||||||
|
int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, |
||||||
|
const unsigned char input[16], |
||||||
|
unsigned char output[16] ); |
||||||
|
|
||||||
|
#if defined(MBEDTLS_SELF_TEST) |
||||||
|
/**
|
||||||
|
* \brief Checkup routine. |
||||||
|
* |
||||||
|
* \return \c 0 on success. |
||||||
|
* \return \c 1 on failure. |
||||||
|
*/ |
||||||
|
MBEDTLS_CHECK_RETURN_CRITICAL |
||||||
|
int mbedtls_aes_self_test( int verbose ); |
||||||
|
|
||||||
|
#endif /* MBEDTLS_SELF_TEST */ |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif /* aes.h */ |
@ -0,0 +1,358 @@ |
|||||||
|
/**
|
||||||
|
* \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 <em>KS X 1213:2004</em> (in |
||||||
|
* Korean, but see http://210.104.33.10/ARIA/index-e.html in English)
|
||||||
|
* and also described by the IETF in <em>RFC 5794</em>. |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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_ARIA_H |
||||||
|
#define MBEDTLS_ARIA_H |
||||||
|
#include "mbedtls/private_access.h" |
||||||
|
|
||||||
|
#include "mbedtls/build_info.h" |
||||||
|
|
||||||
|
#include <stddef.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#include "mbedtls/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 /**< Maximum number of rounds in ARIA. */ |
||||||
|
#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ |
||||||
|
|
||||||
|
/** Bad input data. */ |
||||||
|
#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C |
||||||
|
|
||||||
|
/** Invalid data input length. */ |
||||||
|
#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
#if !defined(MBEDTLS_ARIA_ALT) |
||||||
|
// Regular implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The ARIA context-type definition. |
||||||
|
*/ |
||||||
|
typedef struct mbedtls_aria_context |
||||||
|
{ |
||||||
|
unsigned char MBEDTLS_PRIVATE(nr); /*!< The number of rounds (12, 14 or 16) */ |
||||||
|
/*! The ARIA round keys. */ |
||||||
|
uint32_t MBEDTLS_PRIVATE(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: |
||||||
|
* <ul><li>128 bits</li> |
||||||
|
* <li>192 bits</li> |
||||||
|
* <li>256 bits</li></ul> |
||||||
|
* |
||||||
|
* \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: |
||||||
|
* <ul><li>128 bits</li> |
||||||
|
* <li>192 bits</li> |
||||||
|
* <li>256 bits</li></ul> |
||||||
|
* |
||||||
|
* \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 strategies, 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 */ |
@ -0,0 +1,653 @@ |
|||||||
|
/**
|
||||||
|
* \file asn1.h |
||||||
|
* |
||||||
|
* \brief Generic ASN.1 parsing |
||||||
|
*/ |
||||||
|
/*
|
||||||
|
* Copyright The Mbed TLS Contributors |
||||||
|
* 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_ASN1_H |
||||||
|
#define MBEDTLS_ASN1_H |
||||||
|
#include "mbedtls/private_access.h" |
||||||
|
|
||||||
|
#include "mbedtls/build_info.h" |
||||||
|
#include "mbedtls/platform_util.h" |
||||||
|
|
||||||
|
#include <stddef.h> |
||||||
|
|
||||||
|
#if defined(MBEDTLS_BIGNUM_C) |
||||||
|
#include "mbedtls/bignum.h" |
||||||
|
#endif |
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup asn1_module |
||||||
|
* \{ |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* \name ASN1 Error codes |
||||||
|
* These error codes are combined with other error codes for |
||||||
|
* higher error granularity. |
||||||
|
* e.g. X.509 and PKCS #7 error codes |
||||||
|
* ASN1 is a standard to specify data structures. |
||||||
|
* \{ |
||||||
|
*/ |
||||||
|
/** Out of data when parsing an ASN1 data structure. */ |
||||||
|
#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 |
||||||
|
/** ASN1 tag was of an unexpected value. */ |
||||||
|
#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 |
||||||
|
/** Error when trying to determine the length or invalid length. */ |
||||||
|
#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 |
||||||
|
/** Actual length differs from expected length. */ |
||||||
|
#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 |
||||||
|
/** Data is invalid. */ |
||||||
|
#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 |
||||||
|
/** Memory allocation failed */ |
||||||
|
#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A |
||||||
|
/** Buffer too small when writing ASN.1 data structure. */ |
||||||
|
#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C |
||||||
|
|
||||||
|
/** \} name ASN1 Error codes */ |
||||||
|
|
||||||
|
/**
|
||||||
|
* \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_ENUMERATED 0x0A |
||||||
|
#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 |
||||||
|
|
||||||
|
/* Slightly smaller way to check if tag is a string tag
|
||||||
|
* compared to canonical implementation. */ |
||||||
|
#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \ |
||||||
|
( ( tag ) < 32u && ( \
|
||||||
|
( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \
|
||||||
|
( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \
|
||||||
|
( 1u << MBEDTLS_ASN1_T61_STRING ) | \
|
||||||
|
( 1u << MBEDTLS_ASN1_IA5_STRING ) | \
|
||||||
|
( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \
|
||||||
|
( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \
|
||||||
|
( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) ) |
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 DER constants */ |
||||||
|
|
||||||
|
/** 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 ) |
||||||
|
|
||||||
|
#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ |
||||||
|
( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \
|
||||||
|
memcmp( (oid_str), (oid_buf), (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. */ |
||||||
|
|
||||||
|
/** The next entry in the sequence.
|
||||||
|
* |
||||||
|
* The details of memory management for sequences are not documented and |
||||||
|
* may change in future versions. Set this field to \p NULL when |
||||||
|
* initializing a structure, and do not modify it except via Mbed TLS |
||||||
|
* library functions. |
||||||
|
*/ |
||||||
|
struct mbedtls_asn1_sequence *next; |
||||||
|
} |
||||||
|
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. */ |
||||||
|
|
||||||
|
/** The next entry in the sequence.
|
||||||
|
* |
||||||
|
* The details of memory management for named data sequences are not |
||||||
|
* documented and may change in future versions. Set this field to \p NULL |
||||||
|
* when initializing a structure, and do not modify it except via Mbed TLS |
||||||
|
* library functions. |
||||||
|
*/ |
||||||
|
struct mbedtls_asn1_named_data *next; |
||||||
|
|
||||||
|
/** Merge next item into the current one?
|
||||||
|
* |
||||||
|
* This field exists for the sake of Mbed TLS's X.509 certificate parsing |
||||||
|
* code and may change in future versions of the library. |
||||||
|
*/ |
||||||
|
unsigned char MBEDTLS_PRIVATE(next_merged); |
||||||
|
} |
||||||
|
mbedtls_asn1_named_data; |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the length of an ASN.1 element. |
||||||
|
* Updates the pointer to immediately behind the length. |
||||||
|
* |
||||||
|
* \param p On entry, \c *p points to the first byte of the length, |
||||||
|
* i.e. immediately after the tag. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* after the length, i.e. the first byte of the content. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param len On successful completion, \c *len contains the length |
||||||
|
* read from the ASN.1 input. |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element |
||||||
|
* would end beyond \p end. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. |
||||||
|
*/ |
||||||
|
int mbedtls_asn1_get_len( unsigned char **p, |
||||||
|
const unsigned char *end, |
||||||
|
size_t *len ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the tag and length of the element. |
||||||
|
* Check for the requested tag. |
||||||
|
* Updates the pointer to immediately behind the tag and length. |
||||||
|
* |
||||||
|
* \param p On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* after the length, i.e. the first byte of the content. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param len On successful completion, \c *len contains the length |
||||||
|
* read from the ASN.1 input. |
||||||
|
* \param tag The expected tag. |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start |
||||||
|
* with the requested tag. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element |
||||||
|
* would end beyond \p end. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. |
||||||
|
*/ |
||||||
|
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 On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* beyond the ASN.1 element. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param val On success, the parsed value (\c 0 or \c 1). |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return An ASN.1 error code if the input does not start with |
||||||
|
* a valid ASN.1 BOOLEAN. |
||||||
|
*/ |
||||||
|
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 On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* beyond the ASN.1 element. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param val On success, the parsed value. |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return An ASN.1 error code if the input does not start with |
||||||
|
* a valid ASN.1 INTEGER. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does |
||||||
|
* not fit in an \c int. |
||||||
|
*/ |
||||||
|
int mbedtls_asn1_get_int( unsigned char **p, |
||||||
|
const unsigned char *end, |
||||||
|
int *val ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieve an enumerated ASN.1 tag and its value. |
||||||
|
* Updates the pointer to immediately behind the full tag. |
||||||
|
* |
||||||
|
* \param p On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* beyond the ASN.1 element. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param val On success, the parsed value. |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return An ASN.1 error code if the input does not start with |
||||||
|
* a valid ASN.1 ENUMERATED. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does |
||||||
|
* not fit in an \c int. |
||||||
|
*/ |
||||||
|
int mbedtls_asn1_get_enum( 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 On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p is equal to \p end. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param bs On success, ::mbedtls_asn1_bitstring information about |
||||||
|
* the parsed value. |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains |
||||||
|
* extra data after a valid BIT STRING. |
||||||
|
* \return An ASN.1 error code if the input does not start with |
||||||
|
* a valid ASN.1 BIT STRING. |
||||||
|
*/ |
||||||
|
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 On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* of the content of the BIT STRING. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param len On success, \c *len is the length of the content in bytes. |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with |
||||||
|
* a valid BIT STRING with a nonzero number of unused bits. |
||||||
|
* \return An ASN.1 error code if the input does not start with |
||||||
|
* a valid ASN.1 BIT STRING. |
||||||
|
*/ |
||||||
|
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 <tag>". |
||||||
|
* Updates the pointer to immediately behind the full sequence tag. |
||||||
|
* |
||||||
|
* This function allocates memory for the sequence elements. You can free |
||||||
|
* the allocated memory with mbedtls_asn1_sequence_free(). |
||||||
|
* |
||||||
|
* \note On error, this function may return a partial list in \p cur. |
||||||
|
* You must set `cur->next = NULL` before calling this function! |
||||||
|
* Otherwise it is impossible to distinguish a previously non-null |
||||||
|
* pointer from a pointer to an object allocated by this function. |
||||||
|
* |
||||||
|
* \note If the sequence is empty, this function does not modify |
||||||
|
* \c *cur. If the sequence is valid and non-empty, this |
||||||
|
* function sets `cur->buf.tag` to \p tag. This allows |
||||||
|
* callers to distinguish between an empty sequence and |
||||||
|
* a one-element sequence. |
||||||
|
* |
||||||
|
* \param p On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p is equal to \p end. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param cur A ::mbedtls_asn1_sequence which this function fills. |
||||||
|
* When this function returns, \c *cur is the head of a linked |
||||||
|
* list. Each node in this list is allocated with |
||||||
|
* mbedtls_calloc() apart from \p cur itself, and should |
||||||
|
* therefore be freed with mbedtls_free(). |
||||||
|
* The list describes the content of the sequence. |
||||||
|
* The head of the list (i.e. \c *cur itself) describes the |
||||||
|
* first element, `*cur->next` describes the second element, etc. |
||||||
|
* For each element, `buf.tag == tag`, `buf.len` is the length |
||||||
|
* of the content of the content of the element, and `buf.p` |
||||||
|
* points to the first byte of the content (i.e. immediately |
||||||
|
* past the length of the element). |
||||||
|
* Note that list elements may be allocated even on error. |
||||||
|
* \param tag Each element of the sequence must have this tag. |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains |
||||||
|
* extra data after a valid SEQUENCE OF \p tag. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with |
||||||
|
* an ASN.1 SEQUENCE in which an element has a tag that |
||||||
|
* is different from \p tag. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. |
||||||
|
* \return An ASN.1 error code if the input does not start with |
||||||
|
* a valid ASN.1 SEQUENCE. |
||||||
|
*/ |
||||||
|
int mbedtls_asn1_get_sequence_of( unsigned char **p, |
||||||
|
const unsigned char *end, |
||||||
|
mbedtls_asn1_sequence *cur, |
||||||
|
int tag ); |
||||||
|
/**
|
||||||
|
* \brief Free a heap-allocated linked list presentation of |
||||||
|
* an ASN.1 sequence, including the first element. |
||||||
|
* |
||||||
|
* There are two common ways to manage the memory used for the representation |
||||||
|
* of a parsed ASN.1 sequence: |
||||||
|
* - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). |
||||||
|
* Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). |
||||||
|
* When you have finished processing the sequence, |
||||||
|
* call mbedtls_asn1_sequence_free() on `head`. |
||||||
|
* - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, |
||||||
|
* for example on the stack. Make sure that `head->next == NULL`. |
||||||
|
* Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). |
||||||
|
* When you have finished processing the sequence, |
||||||
|
* call mbedtls_asn1_sequence_free() on `head->cur`, |
||||||
|
* then free `head` itself in the appropriate manner. |
||||||
|
* |
||||||
|
* \param seq The address of the first sequence component. This may |
||||||
|
* be \c NULL, in which case this functions returns |
||||||
|
* immediately. |
||||||
|
*/ |
||||||
|
void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Traverse an ASN.1 SEQUENCE container and |
||||||
|
* call a callback for each entry. |
||||||
|
* |
||||||
|
* This function checks that the input is a SEQUENCE of elements that |
||||||
|
* each have a "must" tag, and calls a callback function on the elements |
||||||
|
* that have a "may" tag. |
||||||
|
* |
||||||
|
* For example, to validate that the input is a SEQUENCE of `tag1` and call |
||||||
|
* `cb` on each element, use |
||||||
|
* ``` |
||||||
|
* mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); |
||||||
|
* ``` |
||||||
|
* |
||||||
|
* To validate that the input is a SEQUENCE of ANY and call `cb` on |
||||||
|
* each element, use |
||||||
|
* ``` |
||||||
|
* mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); |
||||||
|
* ``` |
||||||
|
* |
||||||
|
* To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} |
||||||
|
* and call `cb` on each element that is an OCTET STRING, use |
||||||
|
* ``` |
||||||
|
* mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); |
||||||
|
* ``` |
||||||
|
* |
||||||
|
* The callback is called on the elements with a "may" tag from left to |
||||||
|
* right. If the input is not a valid SEQUENCE of elements with a "must" tag, |
||||||
|
* the callback is called on the elements up to the leftmost point where |
||||||
|
* the input is invalid. |
||||||
|
* |
||||||
|
* \warning This function is still experimental and may change |
||||||
|
* at any time. |
||||||
|
* |
||||||
|
* \param p The address of the pointer to the beginning of |
||||||
|
* the ASN.1 SEQUENCE header. This is updated to |
||||||
|
* point to the end of the ASN.1 SEQUENCE container |
||||||
|
* on a successful invocation. |
||||||
|
* \param end The end of the ASN.1 SEQUENCE container. |
||||||
|
* \param tag_must_mask A mask to be applied to the ASN.1 tags found within |
||||||
|
* the SEQUENCE before comparing to \p tag_must_value. |
||||||
|
* \param tag_must_val The required value of each ASN.1 tag found in the |
||||||
|
* SEQUENCE, after masking with \p tag_must_mask. |
||||||
|
* Mismatching tags lead to an error. |
||||||
|
* For example, a value of \c 0 for both \p tag_must_mask |
||||||
|
* and \p tag_must_val means that every tag is allowed, |
||||||
|
* while a value of \c 0xFF for \p tag_must_mask means |
||||||
|
* that \p tag_must_val is the only allowed tag. |
||||||
|
* \param tag_may_mask A mask to be applied to the ASN.1 tags found within |
||||||
|
* the SEQUENCE before comparing to \p tag_may_value. |
||||||
|
* \param tag_may_val The desired value of each ASN.1 tag found in the |
||||||
|
* SEQUENCE, after masking with \p tag_may_mask. |
||||||
|
* Mismatching tags will be silently ignored. |
||||||
|
* For example, a value of \c 0 for \p tag_may_mask and |
||||||
|
* \p tag_may_val means that any tag will be considered, |
||||||
|
* while a value of \c 0xFF for \p tag_may_mask means |
||||||
|
* that all tags with value different from \p tag_may_val |
||||||
|
* will be ignored. |
||||||
|
* \param cb The callback to trigger for each component |
||||||
|
* in the ASN.1 SEQUENCE that matches \p tag_may_val. |
||||||
|
* The callback function is called with the following |
||||||
|
* parameters: |
||||||
|
* - \p ctx. |
||||||
|
* - The tag of the current element. |
||||||
|
* - A pointer to the start of the current element's |
||||||
|
* content inside the input. |
||||||
|
* - The length of the content of the current element. |
||||||
|
* If the callback returns a non-zero value, |
||||||
|
* the function stops immediately, |
||||||
|
* forwarding the callback's return value. |
||||||
|
* \param ctx The context to be passed to the callback \p cb. |
||||||
|
* |
||||||
|
* \return \c 0 if successful the entire ASN.1 SEQUENCE |
||||||
|
* was traversed without parsing or callback errors. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input |
||||||
|
* contains extra data after a valid SEQUENCE |
||||||
|
* of elements with an accepted tag. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts |
||||||
|
* with an ASN.1 SEQUENCE in which an element has a tag |
||||||
|
* that is not accepted. |
||||||
|
* \return An ASN.1 error code if the input does not start with |
||||||
|
* a valid ASN.1 SEQUENCE. |
||||||
|
* \return A non-zero error code forwarded from the callback |
||||||
|
* \p cb in case the latter returns a non-zero value. |
||||||
|
*/ |
||||||
|
int mbedtls_asn1_traverse_sequence_of( |
||||||
|
unsigned char **p, |
||||||
|
const unsigned char *end, |
||||||
|
unsigned char tag_must_mask, unsigned char tag_must_val, |
||||||
|
unsigned char tag_may_mask, unsigned char tag_may_val, |
||||||
|
int (*cb)( void *ctx, int tag, |
||||||
|
unsigned char* start, size_t len ), |
||||||
|
void *ctx ); |
||||||
|
|
||||||
|
#if defined(MBEDTLS_BIGNUM_C) |
||||||
|
/**
|
||||||
|
* \brief Retrieve an integer ASN.1 tag and its value. |
||||||
|
* Updates the pointer to immediately behind the full tag. |
||||||
|
* |
||||||
|
* \param p On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* beyond the ASN.1 element. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param X On success, the parsed value. |
||||||
|
* |
||||||
|
* \return 0 if successful. |
||||||
|
* \return An ASN.1 error code if the input does not start with |
||||||
|
* a valid ASN.1 INTEGER. |
||||||
|
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does |
||||||
|
* not fit in an \c int. |
||||||
|
* \return An MPI error code if the parsed value is too large. |
||||||
|
*/ |
||||||
|
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 On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* beyond the AlgorithmIdentifier element. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \param end End of data. |
||||||
|
* \param alg The buffer to receive the OID. |
||||||
|
* \param params The buffer to receive the parameters. |
||||||
|
* This is zeroized if there are no parameters. |
||||||
|
* |
||||||
|
* \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 On entry, \c *p points to the start of the ASN.1 element. |
||||||
|
* On successful completion, \c *p points to the first byte |
||||||
|
* beyond the AlgorithmIdentifier element. |
||||||
|
* On error, the value of \c *p is undefined. |
||||||
|
* \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. |
||||||
|
*/ |
||||||
|
const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( const mbedtls_asn1_named_data *list, |
||||||
|
const char *oid, size_t len ); |
||||||
|
|
||||||
|
#if !defined(MBEDTLS_DEPRECATED_REMOVED) |
||||||
|
/**
|
||||||
|
* \brief Free a mbedtls_asn1_named_data entry |
||||||
|
* |
||||||
|
* \deprecated This function is deprecated and will be removed in a |
||||||
|
* future version of the library. |
||||||
|
* Please use mbedtls_asn1_free_named_data_list() |
||||||
|
* or mbedtls_asn1_free_named_data_list_shallow(). |
||||||
|
* |
||||||
|
* \param entry The named data entry to free. |
||||||
|
* This function calls mbedtls_free() on |
||||||
|
* `entry->oid.p` and `entry->val.p`. |
||||||
|
*/ |
||||||
|
void MBEDTLS_DEPRECATED mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); |
||||||
|
#endif /* MBEDTLS_DEPRECATED_REMOVED */ |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Free all entries in a mbedtls_asn1_named_data list. |
||||||
|
* |
||||||
|
* \param head Pointer to the head of the list of named data entries to free. |
||||||
|
* This function calls mbedtls_free() on |
||||||
|
* `entry->oid.p` and `entry->val.p` and then on `entry` |
||||||
|
* for each list entry, and sets \c *head to \c NULL. |
||||||
|
*/ |
||||||
|
void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); |
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Free all shallow entries in a mbedtls_asn1_named_data list, |
||||||
|
* but do not free internal pointer targets. |
||||||
|
* |
||||||
|
* \param name Head of the list of named data entries to free. |
||||||
|
* This function calls mbedtls_free() on each list element. |
||||||
|
*/ |
||||||
|
void mbedtls_asn1_free_named_data_list_shallow( mbedtls_asn1_named_data *name ); |
||||||
|
|
||||||
|
/** \} name Functions to parse ASN.1 data structures */ |
||||||
|
/** \} addtogroup asn1_module */ |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif /* asn1.h */ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue