Compare commits

...

1 Commits

  1. 21
      Makefile
  2. 2
      spritehttpd/lib/mbedtls-3.3.0/.gitattributes
  3. 35
      spritehttpd/lib/mbedtls-3.3.0/.github/ISSUE_TEMPLATE/bug_report.md
  4. 8
      spritehttpd/lib/mbedtls-3.3.0/.github/ISSUE_TEMPLATE/config.yml
  5. 17
      spritehttpd/lib/mbedtls-3.3.0/.github/ISSUE_TEMPLATE/feature_request.md
  6. 19
      spritehttpd/lib/mbedtls-3.3.0/.github/pull_request_template.md
  7. 59
      spritehttpd/lib/mbedtls-3.3.0/.gitignore
  8. 3
      spritehttpd/lib/mbedtls-3.3.0/.globalrc
  9. 4
      spritehttpd/lib/mbedtls-3.3.0/.mypy.ini
  10. 79
      spritehttpd/lib/mbedtls-3.3.0/.pylintrc
  11. 104
      spritehttpd/lib/mbedtls-3.3.0/.travis.yml
  12. 1
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/.gitignore
  13. 5
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/CMakeLists.txt
  14. 2
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/Makefile.inc
  15. 2
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/.gitignore
  16. 27
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/CMakeLists.txt
  17. 6
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/Makefile.inc
  18. 5
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/README.md
  19. 21
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/Hacl_Curve25519.h
  20. 234
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/everest.h
  21. 29
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlib.h
  22. 124
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlib/FStar_UInt128.h
  23. 280
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlib/FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.h
  24. 204
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlin/c_endianness.h
  25. 16
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlin/internal/builtin.h
  26. 46
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlin/internal/callconv.h
  27. 34
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlin/internal/compat.h
  28. 57
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlin/internal/debug.h
  29. 102
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlin/internal/target.h
  30. 61
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlin/internal/types.h
  31. 5
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/kremlin/internal/wasmsupport.h
  32. 21
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/vs2010/Hacl_Curve25519.h
  33. 36
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/vs2010/inttypes.h
  34. 31
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/vs2010/stdbool.h
  35. 190
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/include/everest/x25519.h
  36. 760
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/library/Hacl_Curve25519.c
  37. 50
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/library/Hacl_Curve25519_joined.c
  38. 102
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/library/everest.c
  39. 413
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/library/kremlib/FStar_UInt128_extracted.c
  40. 100
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/library/kremlib/FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.c
  41. 805
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/library/legacy/Hacl_Curve25519.c
  42. 186
      spritehttpd/lib/mbedtls-3.3.0/3rdparty/everest/library/x25519.c
  43. 106
      spritehttpd/lib/mbedtls-3.3.0/BRANCHES.md
  44. 20
      spritehttpd/lib/mbedtls-3.3.0/BUGS.md
  45. 378
      spritehttpd/lib/mbedtls-3.3.0/CMakeLists.txt
  46. 95
      spritehttpd/lib/mbedtls-3.3.0/CONTRIBUTING.md
  47. 5315
      spritehttpd/lib/mbedtls-3.3.0/ChangeLog
  48. 4
      spritehttpd/lib/mbedtls-3.3.0/DartConfiguration.tcl
  49. 202
      spritehttpd/lib/mbedtls-3.3.0/LICENSE
  50. 188
      spritehttpd/lib/mbedtls-3.3.0/Makefile
  51. 315
      spritehttpd/lib/mbedtls-3.3.0/README.md
  52. 20
      spritehttpd/lib/mbedtls-3.3.0/SECURITY.md
  53. 16
      spritehttpd/lib/mbedtls-3.3.0/SUPPORT.md
  54. 3
      spritehttpd/lib/mbedtls-3.3.0/cmake/MbedTLSConfig.cmake.in
  55. 24
      spritehttpd/lib/mbedtls-3.3.0/configs/README.txt
  56. 108
      spritehttpd/lib/mbedtls-3.3.0/configs/config-ccm-psk-dtls1_2.h
  57. 99
      spritehttpd/lib/mbedtls-3.3.0/configs/config-ccm-psk-tls1_2.h
  58. 85
      spritehttpd/lib/mbedtls-3.3.0/configs/config-no-entropy.h
  59. 122
      spritehttpd/lib/mbedtls-3.3.0/configs/config-suite-b.h
  60. 89
      spritehttpd/lib/mbedtls-3.3.0/configs/config-symmetric-only.h
  61. 92
      spritehttpd/lib/mbedtls-3.3.0/configs/config-thread.h
  62. 37
      spritehttpd/lib/mbedtls-3.3.0/dco.txt
  63. 2
      spritehttpd/lib/mbedtls-3.3.0/docs/.gitignore
  64. 1039
      spritehttpd/lib/mbedtls-3.3.0/docs/3.0-migration-guide.md
  65. 26
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/Makefile
  66. 91
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/alternative-implementations.md
  67. 465
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/mbed-crypto-storage-specification.md
  68. 73
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/psa-crypto-implementation-structure.md
  69. 132
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/psa-migration/outcome-analysis.sh
  70. 324
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/psa-migration/psa-limitations.md
  71. 516
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/psa-migration/strategy.md
  72. 58
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/psa-migration/syms.sh
  73. 99
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/psa-migration/testing.md
  74. 133
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/testing/driver-interface-test-strategy.md
  75. 367
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/testing/invasive-testing.md
  76. 127
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/testing/psa-storage-format-testing.md
  77. 58
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/testing/test-framework.md
  78. 652
      spritehttpd/lib/mbedtls-3.3.0/docs/architecture/tls13-support.md
  79. 894
      spritehttpd/lib/mbedtls-3.3.0/docs/getting_started.md
  80. 25
      spritehttpd/lib/mbedtls-3.3.0/docs/proposed/Makefile
  81. 4
      spritehttpd/lib/mbedtls-3.3.0/docs/proposed/README
  82. 244
      spritehttpd/lib/mbedtls-3.3.0/docs/proposed/psa-conditional-inclusion-c.md
  83. 51
      spritehttpd/lib/mbedtls-3.3.0/docs/proposed/psa-driver-developer-guide.md
  84. 45
      spritehttpd/lib/mbedtls-3.3.0/docs/proposed/psa-driver-integration-guide.md
  85. 1009
      spritehttpd/lib/mbedtls-3.3.0/docs/proposed/psa-driver-interface.md
  86. 40
      spritehttpd/lib/mbedtls-3.3.0/docs/proposed/psa-driver-wrappers-codegen-migration-guide.md
  87. 114
      spritehttpd/lib/mbedtls-3.3.0/docs/use-psa-crypto.md
  88. 66
      spritehttpd/lib/mbedtls-3.3.0/doxygen/input/doc_encdec.h
  89. 42
      spritehttpd/lib/mbedtls-3.3.0/doxygen/input/doc_hashing.h
  90. 94
      spritehttpd/lib/mbedtls-3.3.0/doxygen/input/doc_mainpage.h
  91. 39
      spritehttpd/lib/mbedtls-3.3.0/doxygen/input/doc_rng.h
  92. 49
      spritehttpd/lib/mbedtls-3.3.0/doxygen/input/doc_ssltls.h
  93. 44
      spritehttpd/lib/mbedtls-3.3.0/doxygen/input/doc_tcpip.h
  94. 43
      spritehttpd/lib/mbedtls-3.3.0/doxygen/input/doc_x509.h
  95. 29
      spritehttpd/lib/mbedtls-3.3.0/doxygen/mbedtls.doxyfile
  96. 4
      spritehttpd/lib/mbedtls-3.3.0/include/.gitignore
  97. 22
      spritehttpd/lib/mbedtls-3.3.0/include/CMakeLists.txt
  98. 636
      spritehttpd/lib/mbedtls-3.3.0/include/mbedtls/aes.h
  99. 358
      spritehttpd/lib/mbedtls-3.3.0/include/mbedtls/aria.h
  100. 653
      spritehttpd/lib/mbedtls-3.3.0/include/mbedtls/asn1.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,4 +1,4 @@
.PHONY: clean all lib demo fstool
.PHONY: clean all lib demo fstool mbedtls
# -*- Settings -*-
@ -65,6 +65,21 @@ else
endif
# -*- MbedTLS -*-
MBEDTLS_BASE_DIR=spritehttpd/lib/mbedtls-3.3.0/
MBEDTLS_INCLUDE_DIR=$(MBEDTLS_BASE_DIR)/include
MBEDTLS_LIB_DIR=$(MBEDTLS_BASE_DIR)/library
# spritehttpd/lib/mbedtls-3.3.0/library/libmbedcrypto.a
# spritehttpd/lib/mbedtls-3.3.0/library/libmbedtls.a
# spritehttpd/lib/mbedtls-3.3.0/library/libmbedx509.a
mbedtls:
# TODO specify GCC version etc ...
$(MAKE) -C $(MBEDTLS_BASE_DIR) lib -j `nproc` CC=$(CC) AR=$(AR)
# -*- Library -*-
LIB_SOURCES = \
@ -133,9 +148,9 @@ $(DEMO_FS_C_FILE): $(FSTOOL_TARGET) $(DEMO_STATIC_FILES)
$(FSTOOL_TARGET) -P --gzip=jpg -o - --strip=$(DEMO_DIR)/staticfiles $(DEMO_STATIC_FILES) \
| $(FSTOOL_TARGET) -M -o $@ -i -
$(DEMO_TARGET): $(DEMO_SOURCES) $(LIB_TARGET)
$(DEMO_TARGET): $(DEMO_SOURCES) $(LIB_TARGET) mbedtls
$(CC) $(DEMO_CFLAGS) $(DEMO_SOURCES) \
-o $@ -l$(LIBBASENAME) -L.
-o $@ -l$(LIBBASENAME) -L. -L$(MBEDTLS_LIB_DIR) -lmbedtls -lmbedx509 -lmbedcrypto
# -*- FS builder -*-

@ -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,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,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.

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? -->

@ -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…
Cancel
Save