diff --git a/.github/issue_template.md b/.github/issue_template.md
index 5e9d83d4fc..7c31353512 100644
--- a/.github/issue_template.md
+++ b/.github/issue_template.md
@@ -38,4 +38,4 @@ Version:
## Question
-**Please first check for answers in the [Mbed TLS knowledge Base](https://tls.mbed.org/kb), and preferably file an issue in the [Mbed TLS support forum](https://tls.mbed.org/discussions)**
+**Please first check for answers in the [Mbed TLS knowledge Base](https://tls.mbed.org/kb), and preferably file an issue in the [Mbed TLS support forum](https://forums.mbed.com/c/mbed-tls)**
diff --git a/.gitignore b/.gitignore
index fee2a31cd1..f40064d5bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,5 +21,8 @@ massif-*
*.ilk
*.lib
+# Python build artifacts:
+*.pyc
+
# CMake generates *.dir/ folders for in-tree builds (used by MSVC projects), ignore all of those:
*.dir/
diff --git a/.pylint b/.pylint
new file mode 100644
index 0000000000..934f30be5c
--- /dev/null
+++ b/.pylint
@@ -0,0 +1,425 @@
+[MASTER]
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code
+extension-pkg-whitelist=
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Add files or directories matching the regex patterns to the blacklist. The
+# regex matches against base names, not paths.
+ignore-patterns=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Use multiple processes to speed up Pylint.
+jobs=1
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Specify a configuration file.
+#rcfile=
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
+confidence=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+enable=
+
+
+[REPORTS]
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, json
+# and msvs (visual studio).You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+
+[SIMILARITIES]
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[FORMAT]
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )??$
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Maximum number of characters on a single line.
+max-line-length=79
+
+# Maximum number of lines in a module
+max-module-lines=2000
+
+# List of optional constructs for which whitespace checking is disabled. `dict-
+# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
+# `trailing-comma` allows a space between comma and closing bracket: (a, ).
+# `empty-line` allows space-only lines.
+no-space-check=trailing-comma,dict-separator
+
+# Allow the body of a class to be on the same line as the declaration if body
+# contains single statement.
+single-line-class-stmt=no
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+
+[BASIC]
+
+# Naming hint for argument names
+argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct argument names
+argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Naming hint for attribute names
+attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct attribute names
+attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Naming hint for class attribute names
+class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression matching correct class attribute names
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Naming hint for class names
+class-name-hint=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression matching correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Naming hint for constant names
+const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression matching correct constant names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+# Naming hint for function names
+function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct function names
+function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Include a hint for the correct naming format with invalid-name
+include-naming-hint=no
+
+# Naming hint for inline iteration names
+inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
+
+# Regular expression matching correct inline iteration names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Naming hint for method names
+method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct method names
+method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Naming hint for module names
+module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression matching correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
+
+# List of decorators that produce properties, such as abc.abstractproperty. Add
+# to this list to register other decorators that produce valid properties.
+property-classes=abc.abstractproperty
+
+# Naming hint for variable names
+variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct variable names
+variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+
+[TYPECHECK]
+
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
+
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis. It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
+
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
+
+# The minimum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
+
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
+
+
+[VARIABLES]
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,_cb
+
+# A regular expression matching the name of dummy variables (i.e. expectedly
+# not used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,future.builtins
+
+
+[SPELLING]
+
+# Spelling dictionary name. Available dictionaries: none. To make it working
+# install python-enchant package.
+spelling-dict=
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to indicated private dictionary in
+# --spelling-private-dict-file option instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[LOGGING]
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format
+logging-modules=logging
+
+
+[CLASSES]
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,_fields,_replace,_source,_make
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Maximum number of boolean expressions in a if statement
+max-bool-expr=5
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+
+[IMPORTS]
+
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
+
+# Analyse import fallback blocks. This can be used to support both Python 2 and
+# 3 compatible code, which means that the block might have code that exists
+# only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=no
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+# Force import order to recognize a module as part of the standard
+# compatibility libraries.
+known-standard-library=
+
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/.travis.yml b/.travis.yml
index fa01e5a24c..4d23652c67 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,6 +9,7 @@ script:
- tests/scripts/check-generated-files.sh
- tests/scripts/check-doxy-blocks.pl
- tests/scripts/check-names.sh
+- tests/scripts/check-files.py
- tests/scripts/doxygen.sh
- cmake -D CMAKE_BUILD_TYPE:String="Check" .
- make
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2018d35c2b..99bf31f1f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 2.6)
-project("mbed TLS" C)
+if(TEST_CPP)
+ project("mbed TLS" C CXX)
+else()
+ project("mbed TLS" C)
+endif()
option(USE_PKCS11_HELPER_LIBRARY "Build mbed TLS with the pkcs11-helper library." OFF)
option(ENABLE_ZLIB_SUPPORT "Build mbed TLS with zlib library." OFF)
@@ -8,8 +12,13 @@ option(ENABLE_PROGRAMS "Build mbed TLS programs." ON)
option(UNSAFE_BUILD "Allow unsafe builds. These builds ARE NOT SECURE." OFF)
+string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
+string(REGEX MATCH "GNU" CMAKE_COMPILER_IS_GNU "${CMAKE_C_COMPILER_ID}")
+string(REGEX MATCH "IAR" CMAKE_COMPILER_IS_IAR "${CMAKE_C_COMPILER_ID}")
+string(REGEX MATCH "MSVC" CMAKE_COMPILER_IS_MSVC "${CMAKE_C_COMPILER_ID}")
+
# the test suites currently have compile errors with MSVC
-if(MSVC)
+if(CMAKE_COMPILER_IS_MSVC)
option(ENABLE_TESTING "Build mbed TLS tests." OFF)
else()
option(ENABLE_TESTING "Build mbed TLS tests." ON)
@@ -27,9 +36,27 @@ set(NULL_ENTROPY_WARNING "${WARNING_BORDER}"
"${NULL_ENTROPY_WARN_L3}"
"${WARNING_BORDER}")
+set(CTR_DRBG_128_BIT_KEY_WARN_L1 "**** WARNING! MBEDTLS_CTR_DRBG_USE_128_BIT_KEY defined!\n")
+set(CTR_DRBG_128_BIT_KEY_WARN_L2 "**** Using 128-bit keys for CTR_DRBG limits the security of generated\n")
+set(CTR_DRBG_128_BIT_KEY_WARN_L3 "**** keys and operations that use random values generated to 128-bit security\n")
+
+set(CTR_DRBG_128_BIT_KEY_WARNING "${WARNING_BORDER}"
+ "${CTR_DRBG_128_BIT_KEY_WARN_L1}"
+ "${CTR_DRBG_128_BIT_KEY_WARN_L2}"
+ "${CTR_DRBG_128_BIT_KEY_WARN_L3}"
+ "${WARNING_BORDER}")
+
+find_package(PythonInterp)
find_package(Perl)
if(PERL_FOUND)
+ # If 128-bit keys are configured for CTR_DRBG, display an appropriate warning
+ execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
+ RESULT_VARIABLE result)
+ if(${result} EQUAL 0)
+ message(WARNING ${CTR_DRBG_128_BIT_KEY_WARNING})
+ endif()
+
# If NULL Entropy is configured, display an appropriate warning
execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY
RESULT_VARIABLE result)
@@ -56,9 +83,37 @@ set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
CACHE STRING "Choose the type of build: None Debug Release Coverage ASan ASanDbg MemSan MemSanDbg Check CheckFull"
FORCE)
+# Create a symbolic link from ${base_name} in the binary directory
+# to the corresponding path in the source directory.
+function(link_to_source base_name)
+ # Get OS dependent path to use in `execute_process`
+ file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${base_name}" link)
+ file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}" target)
+
+ if (NOT EXISTS ${link})
+ if (CMAKE_HOST_UNIX)
+ set(command ln -s ${target} ${link})
+ else()
+ if (IS_DIRECTORY ${target})
+ set(command cmd.exe /c mklink /j ${link} ${target})
+ else()
+ set(command cmd.exe /c mklink /h ${link} ${target})
+ endif()
+ endif()
+
+ execute_process(COMMAND ${command}
+ RESULT_VARIABLE result
+ ERROR_VARIABLE output)
+
+ if (NOT ${result} EQUAL 0)
+ message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
+ endif()
+ endif()
+endfunction(link_to_source)
+
string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
-if(CMAKE_COMPILER_IS_GNUCC)
+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
@@ -77,30 +132,34 @@ if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
set(CMAKE_C_FLAGS_CHECK "-Werror -Os")
set(CMAKE_C_FLAGS_CHECKFULL "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
-endif(CMAKE_COMPILER_IS_GNUCC)
+endif(CMAKE_COMPILER_IS_GNU)
if(CMAKE_COMPILER_IS_CLANG)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow")
set(CMAKE_C_FLAGS_RELEASE "-O2")
set(CMAKE_C_FLAGS_DEBUG "-O0 -g3")
set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage")
- set(CMAKE_C_FLAGS_ASAN "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover -O3")
- set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
+ set(CMAKE_C_FLAGS_ASAN "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
+ set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
set(CMAKE_C_FLAGS_MEMSAN "-Werror -fsanitize=memory -O3")
set(CMAKE_C_FLAGS_MEMSANDBG "-Werror -fsanitize=memory -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2")
set(CMAKE_C_FLAGS_CHECK "-Werror -Os")
endif(CMAKE_COMPILER_IS_CLANG)
-if(MSVC)
+if(CMAKE_COMPILER_IS_IAR)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts --warnings_are_errors -Ohz")
+endif(CMAKE_COMPILER_IS_IAR)
+
+if(CMAKE_COMPILER_IS_MSVC)
# Strictest warnings, and treat as errors
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
-endif(MSVC)
+endif(CMAKE_COMPILER_IS_MSVC)
if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
- if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+ if(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
set(CMAKE_SHARED_LINKER_FLAGS "--coverage")
- endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+ endif(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
endif(CMAKE_BUILD_TYPE STREQUAL "Coverage")
if(LIB_INSTALL_DIR)
@@ -164,3 +223,12 @@ if(ENABLE_TESTING)
)
endif(UNIX)
endif()
+
+# 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()
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3c6dc74c81..3433ed0017 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,38 +26,70 @@ Making a Contribution
1. For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it.
1. Mbed TLS is released under the Apache license, and as such, all the added files should include the Apache license header.
-Backports
----------
-Mbed TLS maintains some legacy branches, which are released as LTS versions. Mbed TLS should follow backwards compatibility rules, to fit with existing users. As such, backporting to these branches should be handled according to the following rules:
-
-1. If the contribution is a new feature or enhancement, no backporting is needed.
-1. Bug fixes should be backported to the legacy branches containing these bugs.
-1. Changes in the API do not require backporting. If a bug fix introduced a new API, such as new error codes, the bug fix should be implemented differently in the legacy branch.
+API/ABI Compatibility
+---------------------
+The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches.
+
+To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change.
+
+Where changes to an existing interface are necessary, functions in the public interface which need to be changed, are marked as 'deprecated'. This is done with the preprocessor symbols `MBEDTLS_DEPRECATED_WARNING` and `MBEDTLS_DEPRECATED_REMOVED`. Then, a new function with a new name but similar if not identical behaviour to the original function containing the necessary changes should be created alongside the existing deprecated function.
+
+When a build is made with the deprecation preprocessor symbols defined, a compiler warning will be generated to warn a user that the function will be removed at some point in the future, notifying users that they should change from the older deprecated function to the newer function at their own convenience.
+
+Therefore, no changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. As described above, if a function needs to be changed, a new function needs to be created alongside it, with a new name, and whatever change is necessary, such as a new parameter or the addition of a return value.
+
+Periodically, the library will remove deprecated functions from the library which will be a breaking change in the API, but such changes will be made only in a planned, structured way that gives sufficient notice to users of the library.
+
+Long Term Support Branches
+--------------------------
+Mbed TLS maintains several LTS (Long Term Support) branches, which are maintained continuously for a given period. The LTS branches are provided to allow users of the library to have a maintained, stable version of the library which contains only security fixes and fixes for other defects, without encountering additional features or API extensions which may introduce issues or change the code size or RAM usage, which can be significant considerations on some platforms. To allow users to take advantage of the LTS branches, these branches maintain backwards compatibility for both the public API and ABI.
+
+When backporting to these branches please observe the following rules:
+
+ 1. Any change to the library which changes the API or ABI cannot be backported.
+
+ 2. 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.
+
+ 3. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be addtional test cases or quality improvements such as changes to build or test scripts.
+
+It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development) by contributors.
+
+Currently maintained LTS branches are:
-It would be highly appreciated if a contribution would be backported to a legacy branch in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development).
-At the moment, the legacy branches are:
-
-1. [mbedtls-1.3](https://github.com/ARMmbed/mbedtls/tree/mbedtls-1.3)
1. [mbedtls-2.1](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.1)
+2. [mbedtls-2.7](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.7)
+
+
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 an elaborate test suite in `tests/` that initially requires Perl 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.
+As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist.
+
+Mbed TLS includes a comprehensive set of test suites in the `tests/` directory that are dynamically generated to produce the actual test source files (e.g. `test_suite_mpi.c`). These files are generated from a `function file` (e.g. `suites/test_suite_mpi.function`) and a `data file` (e.g. `suites/test_suite_mpi.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function.
+
+[A Knowledge Base article describing how to add additional tests is available on the Mbed TLS website](https://tls.mbed.org/kb/development/test_suites).
+
+A test script `tests/scripts/basic-build-test.sh` is available to show test coverage of the library. New code contributions should provide a similar level of code coverage to that which already exists for the library.
Sample applications, if needed, should be modified as well.
Continuous Integration Tests
----------------------------
-Once a PR has been made, the Continuous Integration (CI) tests are triggered and run. You should follow the result of the CI tests, and fix failures.
+Once a PR has been made, the Continuous Integration (CI) tests are triggered and run. You should follow the result of the CI tests, and fix failures.
+
It is advised to enable the [githooks scripts](https://github.com/ARMmbed/mbedtls/tree/development/tests/git-scripts) prior to pushing your changes, for catching some of the issues as early as possible.
Documentation
-------------
-Mbed TLS should be well documented. If documentation is needed, speak out!
+Mbed TLS is well documented, but if you think documentation is needed, speak out!
1. All interfaces should be documented through Doxygen. New APIs should introduce Doxygen documentation.
-1. Complex parts in the code should include comments.
-1. If needed, a Readme file is advised.
-1. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description.
-1. A [ChangeLog](https://github.com/ARMmbed/mbedtls/blob/development/ChangeLog) entry should be added for this contribution.
+
+2. Complex parts in the code should include comments.
+
+3. If needed, a Readme file is advised.
+
+4. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description.
+
+5. A [ChangeLog](https://github.com/ARMmbed/mbedtls/blob/development/ChangeLog) entry should be added for this contribution.
+
diff --git a/ChangeLog b/ChangeLog
index 348864c0e9..b885998954 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,274 @@ mbed TLS ChangeLog (Sorted per branch, date)
= mbed TLS x.x.x branch released xxxx-xx-xx
+Security
+ * Fix overly strict DN comparison when looking for CRLs
+ belonging to a particular CA. This previously lead to
+ ignoring CRLs when the CRL's issuer name and the CA's
+ subject name differed in their string encoding (e.g.,
+ one using PrintableString and the other UTF8String) or
+ in the choice of upper and lower case. Reported by
+ HenrikRosenquistAndersson in #1784.
+
+Features
+ * Add support for temporarily suspending expensive ECC computations after
+ some configurable amount of operations, to be used in single-threaded
+ constrained systems where ECC is time consuming and blocking until
+ completion cannot be tolerated. This is enabled by
+ MBEDTLS_ECP_RESTARTABLE at compile time (disabled by default) and
+ configured by mbedtls_ecp_set_max_ops() at runtime. It applies to new
+ xxx_restartable functions in ECP, ECDSA, PK and X.509 (CRL not supported
+ yet), and to existing functions in ECDH and SSL (currently only
+ implemented client-side, for ECDHE-ECDSA ciphersuites in TLS 1.2,
+ including client authentication).
+ * Add support for Arm CPU DSP extensions to accelerate asymmetric key
+ operations. On CPUs where the extensions are available, they can accelerate
+ MPI multiplications used in ECC and RSA cryptography. Contributed by
+ Aurelien Jarno.
+
+Bugfix
+ * Fix wrong order of freeing in programs/ssl/ssl_server2 example
+ application leading to a memory leak in case both
+ MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE are set.
+ Fixes #2069.
+ * Fix a bug in the update function for SSL ticket keys which previously
+ invalidated keys of a lifetime of less than a 1s. Fixes #1968.
+ * Fix failure in hmac_drbg in the benchmark sample application, when
+ MBEDTLS_THREADING_C is defined. Found by TrinityTonic, #1095
+ * Fix a bug in the record decryption routine ssl_decrypt_buf()
+ which lead to accepting properly authenticated but improperly
+ padded records in case of CBC ciphersuites using Encrypt-then-MAC.
+ * Fix memory leak and freeing without initialization in the example
+ program programs/x509/cert_write. Fixes #1422.
+ * Ignore IV in mbedtls_cipher_set_iv() when the cipher mode is MBEDTLS_MODE_ECB
+ Fix for #1091 raised by ezdevelop
+
+Changes
+ * Removed support for Yotta as a build tool.
+ * Add tests for session resumption in DTLS.
+ * Close a test gap in (D)TLS between the client side and the server side:
+ test the handling of large packets and small packets on the client side
+ in the same way as on the server side.
+ * Change the dtls_client and dtls_server samples to work by default over
+ IPv6 and optionally by a build option over IPv4.
+
+= mbed TLS 2.13.1 branch released 2018-09-06
+
+API Changes
+ * Extend the platform module with an abstraction mbedtls_platform_gmtime_r()
+ whose implementation should behave as a thread-safe version of gmtime().
+ This allows users to configure such an implementation at compile time when
+ the target system cannot be deduced automatically, by setting the option
+ MBEDTLS_PLATFORM_GMTIME_R_ALT. At this stage Mbed TLS is only able to
+ automatically select implementations for Windows and POSIX C libraries.
+
+Bugfix
+ * Fix build failures on platforms where only gmtime() is available but
+ neither gmtime_r() nor gmtime_s() are present. Fixes #1907.
+
+= mbed TLS 2.13.0 branch released 2018-08-31
+
+Security
+ * Fix an issue in the X.509 module which could lead to a buffer overread
+ during certificate extensions parsing. In case of receiving malformed
+ input (extensions length field equal to 0), an illegal read of one byte
+ beyond the input buffer is made. Found and analyzed by Nathan Crandall.
+
+Features
+ * Add support for fragmentation of outgoing DTLS handshake messages. This
+ is controlled by the maximum fragment length as set locally or negotiated
+ with the peer, as well as by a new per-connection MTU option, set using
+ mbedtls_ssl_set_mtu().
+ * Add support for auto-adjustment of MTU to a safe value during the
+ handshake when flights do not get through (RFC 6347, section 4.1.1.1,
+ last paragraph).
+ * Add support for packing multiple records within a single datagram,
+ enabled by default.
+ * Add support for buffering out-of-order handshake messages in DTLS.
+ The maximum amount of RAM used for this can be controlled by the
+ compile-time constant MBEDTLS_SSL_DTLS_MAX_BUFFERING defined
+ in mbedtls/config.h.
+
+API Changes
+ * Add function mbedtls_ssl_set_datagram_packing() to configure
+ the use of datagram packing (enabled by default).
+
+Bugfix
+ * Fix a potential memory leak in mbedtls_ssl_setup() function. An allocation
+ failure in the function could lead to other buffers being leaked.
+ * Fixes an issue with MBEDTLS_CHACHAPOLY_C which would not compile if
+ MBEDTLS_ARC4_C and MBEDTLS_CIPHER_NULL_CIPHER weren't also defined. #1890
+ * Fix a memory leak in ecp_mul_comb() if ecp_precompute_comb() fails.
+ Fix contributed by Espressif Systems.
+ * Add ecc extensions only if an ecc based ciphersuite is used.
+ This improves compliance to RFC 4492, and as a result, solves
+ interoperability issues with BouncyCastle. Raised by milenamil in #1157.
+ * Replace printf with mbedtls_printf in the ARIA module. Found by
+ TrinityTonic in #1908.
+ * Fix potential use-after-free in mbedtls_ssl_get_max_frag_len()
+ and mbedtls_ssl_get_record_expansion() after a session reset. Fixes #1941.
+ * Fix a bug that caused SSL/TLS clients to incorrectly abort the handshake
+ with TLS versions 1.1 and earlier when the server requested authentication
+ without providing a list of CAs. This was due to an overly strict bounds
+ check in parsing the CertificateRequest message,
+ introduced in Mbed TLS 2.12.0. Fixes #1954.
+ * Fix a miscalculation of the maximum record expansion in
+ mbedtls_ssl_get_record_expansion() in case of ChachaPoly ciphersuites,
+ or CBC ciphersuites in (D)TLS versions 1.1 or higher. Fixes #1913, #1914.
+ * Fix undefined shifts with negative values in certificates parsing
+ (found by Catena cyber using oss-fuzz)
+ * Fix memory leak and free without initialization in pk_encrypt
+ and pk_decrypt example programs. Reported by Brace Stout. Fixes #1128.
+ * Remove redundant else statement. Raised by irwir. Fixes #1776.
+
+Changes
+ * Copy headers preserving timestamps when doing a "make install".
+ Contributed by xueruini.
+ * Allow the forward declaration of public structs. Contributed by Dawid
+ Drozd. Fixes #1215 raised by randombit.
+ * Improve compatibility with some alternative CCM implementations by using
+ CCM test vectors from RAM.
+ * Add support for buffering of out-of-order handshake messages.
+ * Add warnings to the documentation of the HKDF module to reduce the risk
+ of misusing the mbedtls_hkdf_extract() and mbedtls_hkdf_expand()
+ functions. Fixes #1775. Reported by Brian J. Murray.
+
+= mbed TLS 2.12.0 branch released 2018-07-25
+
+Security
+ * Fix a vulnerability in TLS ciphersuites based on CBC and using SHA-384,
+ in (D)TLS 1.0 to 1.2, that allowed an active network attacker to
+ partially recover the plaintext of messages under some conditions by
+ exploiting timing measurements. With DTLS, the attacker could perform
+ this recovery by sending many messages in the same connection. With TLS
+ or if mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only
+ worked if the same secret (for example a HTTP Cookie) has been repeatedly
+ sent over connections manipulated by the attacker. Connections using GCM
+ or CCM instead of CBC, using hash sizes other than SHA-384, or using
+ Encrypt-then-Mac (RFC 7366) were not affected. The vulnerability was
+ caused by a miscalculation (for SHA-384) in a countermeasure to the
+ original Lucky 13 attack. Found by Kenny Paterson, Eyal Ronen and Adi
+ Shamir.
+ * Fix a vulnerability in TLS ciphersuites based on CBC, in (D)TLS 1.0 to
+ 1.2, that allowed a local attacker, able to execute code on the local
+ machine as well as manipulate network packets, to partially recover the
+ plaintext of messages under some conditions by using a cache attack
+ targetting an internal MD/SHA buffer. With TLS or if
+ mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only worked if
+ the same secret (for example a HTTP Cookie) has been repeatedly sent over
+ connections manipulated by the attacker. Connections using GCM or CCM
+ instead of CBC or using Encrypt-then-Mac (RFC 7366) were not affected.
+ Found by Kenny Paterson, Eyal Ronen and Adi Shamir.
+ * Add a counter-measure against a vulnerability in TLS ciphersuites based
+ on CBC, in (D)TLS 1.0 to 1.2, that allowed a local attacker, able to
+ execute code on the local machine as well as manipulate network packets,
+ to partially recover the plaintext of messages under some conditions (see
+ previous entry) by using a cache attack targeting the SSL input record
+ buffer. Connections using GCM or CCM instead of CBC or using
+ Encrypt-then-Mac (RFC 7366) were not affected. Found by Kenny Paterson,
+ Eyal Ronen and Adi Shamir.
+
+Features
+ * Add new crypto primitives from RFC 7539: stream cipher Chacha20, one-time
+ authenticator Poly1305 and AEAD construct Chacha20-Poly1305. Contributed
+ by Daniel King.
+ * Add support for CHACHA20-POLY1305 ciphersuites from RFC 7905.
+ * Add platform support for the Haiku OS. (https://www.haiku-os.org).
+ Contributed by Augustin Cavalier.
+ * Make the receive and transmit buffers independent sizes, for situations
+ where the outgoing buffer can be fixed at a smaller size than the incoming
+ buffer, which can save some RAM. If buffer lengths are kept equal, there
+ is no functional difference. Contributed by Angus Gratton, and also
+ independently contributed again by Paul Sokolovsky.
+ * Add support for key wrapping modes based on AES as defined by
+ NIST SP 800-38F algorithms KW and KWP and by RFC 3394 and RFC 5649.
+ * Add support for 128-bit keys in CTR_DRBG. Note that using keys shorter
+ than 256 bits limits the security of generated material to 128 bits.
+
+Bugfix
+ * Fix the key_app_writer example which was writing a leading zero byte which
+ was creating an invalid ASN.1 tag. Found by Aryeh R. Fixes #1257.
+ * Fix compilation error on C++, because of a variable named new.
+ Found and fixed by Hirotaka Niisato in #1783.
+ * Fix "no symbols" warning issued by ranlib when building on Mac OS X. Fix
+ contributed by tabascoeye.
+ * Clarify documentation for mbedtls_ssl_write() to include 0 as a valid
+ return value. Found by @davidwu2000. #839
+ * Fix a memory leak in mbedtls_x509_csr_parse(), found by catenacyber,
+ Philippe Antoine. Fixes #1623.
+ * Remove unused headers included in x509.c. Found by Chris Hanson and fixed
+ by Brendan Shanks. Part of a fix for #992.
+ * Fix compilation error when MBEDTLS_ARC4_C is disabled and
+ MBEDTLS_CIPHER_NULL_CIPHER is enabled. Found by TrinityTonic in #1719.
+ * Added length checks to some TLS parsing functions. Found and fixed by
+ Philippe Antoine from Catena cyber. #1663.
+ * Fix the inline assembly for the MPI multiply helper function for i386 and
+ i386 with SSE2. Found by László Langó. Fixes #1550
+ * Fix namespacing in header files. Remove the `mbedtls` namespacing in
+ the `#include` in the header files. Resolves #857
+ * Fix compiler warning of 'use before initialisation' in
+ mbedtls_pk_parse_key(). Found by Martin Boye Petersen and fixed by Dawid
+ Drozd. #1098
+ * Fix decryption for zero length messages (which contain all padding) when a
+ CBC based ciphersuite is used together with Encrypt-then-MAC. Previously,
+ such a message was wrongly reported as an invalid record and therefore lead
+ to the connection being terminated. Seen most often with OpenSSL using
+ TLS 1.0. Reported by @kFYatek and by Conor Murphy on the forum. Fix
+ contributed by Espressif Systems. Fixes #1632
+ * Fix ssl_client2 example to send application data with 0-length content
+ when the request_size argument is set to 0 as stated in the documentation.
+ Fixes #1833.
+ * Correct the documentation for `mbedtls_ssl_get_session()`. This API has
+ deep copy of the session, and the peer certificate is not lost. Fixes #926.
+ * Fix build using -std=c99. Fixed by Nick Wilson.
+
+Changes
+ * Fail when receiving a TLS alert message with an invalid length, or invalid
+ zero-length messages when using TLS 1.2. Contributed by Espressif Systems.
+ * Change the default behaviour of mbedtls_hkdf_extract() to return an error
+ when calling with a NULL salt and non-zero salt_len. Contributed by
+ Brian J Murray
+ * Change the shebang line in Perl scripts to look up perl in the PATH.
+ Contributed by fbrosson.
+ * Allow overriding the time on Windows via the platform-time abstraction.
+ Fixed by Nick Wilson.
+ * Use gmtime_r/gmtime_s for thread-safety. Fixed by Nick Wilson.
+
+= mbed TLS 2.11.0 branch released 2018-06-18
+
+Features
+ * Add additional block mode, OFB (Output Feedback), to the AES module and
+ cipher abstraction module.
+ * Implement the HMAC-based extract-and-expand key derivation function
+ (HKDF) per RFC 5869. Contributed by Thomas Fossati.
+ * Add support for the CCM* block cipher mode as defined in IEEE Std. 802.15.4.
+ * Add support for the XTS block cipher mode with AES (AES-XTS).
+ Contributed by Aorimn in pull request #414.
+ * In TLS servers, support offloading private key operations to an external
+ cryptoprocessor. Private key operations can be asynchronous to allow
+ non-blocking operation of the TLS server stack.
+
+Bugfix
+ * Fix the cert_write example to handle certificates signed with elliptic
+ curves as well as RSA. Fixes #777 found by dbedev.
+ * Fix for redefinition of _WIN32_WINNT to avoid overriding a definition
+ used by user applications. Found and fixed by Fabio Alessandrelli.
+ * Fix compilation warnings with IAR toolchain, on 32 bit platform.
+ Reported by rahmanih in #683
+ * Fix braces in mbedtls_memory_buffer_alloc_status(). Found by sbranden, #552.
+
+Changes
+ * Changed CMake defaults for IAR to treat all compiler warnings as errors.
+ * Changed the Clang parameters used in the CMake build files to work for
+ versions later than 3.6. Versions of Clang earlier than this may no longer
+ work. Fixes #1072
+
+= mbed TLS 2.10.0 branch released 2018-06-06
+
+Features
+ * Add support for ARIA cipher (RFC 5794) and associated TLS ciphersuites
+ (RFC 6209). Disabled by default, see MBEDTLS_ARIA_C in config.h
+
API Changes
* Extend the platform module with a util component that contains
functionality shared by multiple Mbed TLS modules. At this stage
@@ -13,6 +281,15 @@ API Changes
Therefore, mbedtls_platform_zeroize() is moved to the platform module to
facilitate testing and maintenance.
+Bugfix
+ * Fix an issue with MicroBlaze support in bn_mul.h which was causing the
+ build to fail. Found by zv-io. Fixes #1651.
+
+Changes
+ * Support TLS testing in out-of-source builds using cmake. Fixes #1193.
+ * Fix redundant declaration of mbedtls_ssl_list_ciphersuites. Raised by
+ TrinityTonic. #1359.
+
= mbed TLS 2.9.0 branch released 2018-04-30
Security
diff --git a/Makefile b/Makefile
index a0fcb2bc56..f4c0a00215 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,7 @@ tests: lib
ifndef WINDOWS
install: no_test
mkdir -p $(DESTDIR)/include/mbedtls
- cp -r include/mbedtls $(DESTDIR)/include
+ cp -rp include/mbedtls $(DESTDIR)/include
mkdir -p $(DESTDIR)/lib
cp -RP library/libmbedtls.* $(DESTDIR)/lib
@@ -61,9 +61,21 @@ NULL_ENTROPY_WARN_L3=**** AND IS *NOT* SUITABLE FOR PRODUCTION USE ****\n
NULL_ENTROPY_WARNING=\n$(WARNING_BORDER)$(NULL_ENTROPY_WARN_L1)$(NULL_ENTROPY_WARN_L2)$(NULL_ENTROPY_WARN_L3)$(WARNING_BORDER)
+WARNING_BORDER_LONG =**********************************************************************************\n
+CTR_DRBG_128_BIT_KEY_WARN_L1=**** WARNING! MBEDTLS_CTR_DRBG_USE_128_BIT_KEY defined! ****\n
+CTR_DRBG_128_BIT_KEY_WARN_L2=**** Using 128-bit keys for CTR_DRBG limits the security of generated ****\n
+CTR_DRBG_128_BIT_KEY_WARN_L3=**** keys and operations that use random values generated to 128-bit security ****\n
+
+CTR_DRBG_128_BIT_KEY_WARNING=\n$(WARNING_BORDER_LONG)$(CTR_DRBG_128_BIT_KEY_WARN_L1)$(CTR_DRBG_128_BIT_KEY_WARN_L2)$(CTR_DRBG_128_BIT_KEY_WARN_L3)$(WARNING_BORDER_LONG)
+
# Post build steps
post_build:
ifndef WINDOWS
+
+ # If 128-bit keys are configured for CTR_DRBG, display an appropriate warning
+ -scripts/config.pl get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY && ([ $$? -eq 0 ]) && \
+ echo '$(CTR_DRBG_128_BIT_KEY_WARNING)'
+
# If NULL Entropy is configured, display an appropriate warning
-scripts/config.pl get MBEDTLS_TEST_NULL_ENTROPY && ([ $$? -eq 0 ]) && \
echo '$(NULL_ENTROPY_WARNING)'
diff --git a/README.md b/README.md
index a2c3c6f21e..d7a0e9d6bb 100644
--- a/README.md
+++ b/README.md
@@ -11,47 +11,16 @@ Compiler options can be set using conventional environment variables such as `CC
Compiling
---------
-There are currently four active build systems used within Mbed TLS releases:
+There are currently three active build systems used within Mbed TLS releases:
-- yotta
- GNU Make
- CMake
- Microsoft Visual Studio (Microsoft Visual Studio 2010 or later)
The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically.
-Yotta, as a build system, is slightly different from the other build systems:
-
-- it provides a minimalistic configuration file by default
-- depending on the yotta target, features of Mbed OS may be used in examples and tests
-
The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`. Also, when loading shared libraries using dlopen(), you'll need to load libmbedcrypto first, then libmbedx509, before you can load libmbedtls.
-### Yotta
-
-[yotta](http://yottabuild.org) is a package manager and build system developed by Mbed, and is the build system of Mbed OS 16.03. To install it on your platform, please follow the yotta [installation instructions](http://docs.yottabuild.org/#installing).
-
-Once yotta is installed, you can use it to download the latest version of Mbed TLS from the yotta registry with:
-
- yotta install mbedtls
-
-and build it with:
-
- yotta build
-
-If, on the other hand, you already have a copy of Mbed TLS from a source other than the yotta registry, for example from cloning our GitHub repository, or from downloading a tarball of the standalone edition, then you'll first need to generate the yotta module by running:
-
- yotta/create-module.sh
-
-This should be executed from the root Mbed TLS project directory. This will create the yotta module in the `yotta/module` directory within it. You can then change to that directory and build as usual:
-
- cd yotta/module
- yotta build
-
-In any case, you'll probably want to set the yotta target before building unless it has already been set globally. For more information on using yotta, please consult the [yotta documentation](http://docs.yottabuild.org/).
-
-For more details on the yotta/Mbed OS edition of Mbed TLS, including example programs, please consult the [Readme at the root of the yotta module](https://github.com/ARMmbed/mbedtls/blob/development/yotta/data/README.md).
-
### 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.
@@ -78,11 +47,11 @@ In order to build for a Windows platform, you should use `WINDOWS_BUILD=1` if th
Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved.
-Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so it 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 overriden from the command line.
+Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overriden from the command line.
Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://tls.mbed.org/kb) for articles on your platform or issue.
-In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS knowledge base](https://tls.mbed.org/kb).
+In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://tls.mbed.org/kb).
### CMake
@@ -169,7 +138,7 @@ The solution file `mbedTLS.sln` contains all the basic projects needed to build
Example programs
----------------
-We've included example programs for a lot of different features and uses in `programs/`. Most programs only focus on a single feature or usage scenario, so keep that in mind when copying parts of the code.
+We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md). Most programs only focus on a single feature or usage scenario, so keep that in mind when copying parts of the code.
Tests
-----
@@ -192,7 +161,7 @@ We provide some non-standard configurations focused on specific use cases in the
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:
+Mbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following Knowledge Base articles useful:
- [Porting Mbed TLS to a new environment or OS](https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS)
- [What external dependencies does Mbed TLS rely on?](https://tls.mbed.org/kb/development/what-external-dependencies-does-mbedtls-rely-on)
@@ -211,7 +180,7 @@ To accept the Contributor’s Licence Agreement (CLA), individual contributors c
### Making a Contribution
-1. [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://tls.mbed.org/discussions) around a feature idea or a bug.
+1. [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://forums.mbed.com/c/mbed-tls) around a feature idea or a bug.
2. Fork the [Mbed TLS repository on GitHub](https://github.com/ARMmbed/mbedtls) to start making your changes. As a general rule, you should use the "development" branch as a basis.
3. Write a test which shows that the bug was fixed or that the feature works as expected.
4. Send a pull request and bug us until it gets merged and published. Contributions may need some modifications, so work with us to get your change accepted. We will include your name in the ChangeLog :)
diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h
index a783e6b73b..c9b58dd538 100644
--- a/configs/config-ccm-psk-tls1_2.h
+++ b/configs/config-ccm-psk-tls1_2.h
@@ -81,7 +81,7 @@
* both ends of the connection! (See comments in "mbedtls/ssl.h".)
* The optimal size here depends on the typical size of records.
*/
-#define MBEDTLS_SSL_MAX_CONTENT_LEN 512
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024
#include "mbedtls/check_config.h"
diff --git a/configs/config-no-entropy.h b/configs/config-no-entropy.h
index b4a0930b9c..7d34ad52ec 100644
--- a/configs/config-no-entropy.h
+++ b/configs/config-no-entropy.h
@@ -82,6 +82,7 @@
#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
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index e27c221bbc..b9f9ec1c46 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -24,7 +24,7 @@
*/
/**
- * @mainpage mbed TLS v2.9.0 source code documentation
+ * @mainpage mbed TLS v2.13.1 source code documentation
*
* This documentation describes the internal structure of mbed TLS. It was
* automatically generated from specially formatted comment blocks in
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index 510fa85b0b..8df061e31c 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -28,7 +28,7 @@ DOXYFILE_ENCODING = UTF-8
# identify the project. Note that if you do not use Doxywizard you need
# to put quotes around the project name if it contains spaces.
-PROJECT_NAME = "mbed TLS v2.9.0"
+PROJECT_NAME = "mbed TLS v2.13.1"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
@@ -664,7 +664,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = ..
+INPUT = ../include input
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -696,7 +696,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE = ../configs ../yotta/module
+EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 985a3530b9..1b581a54dd 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -9,3 +9,8 @@ if(INSTALL_MBEDTLS_HEADERS)
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
endif(INSTALL_MBEDTLS_HEADERS)
+
+# Make config.h available in an out-of-source build. ssl-opt.sh requires it.
+if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
+ link_to_source(mbedtls)
+endif()
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index e0fc238d79..4c8dab3151 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -13,6 +13,11 @@
* ISO/IEC 18033-2:2006: Information technology -- Security
* techniques -- Encryption algorithms -- Part 2: Asymmetric
* ciphers.
+ *
+ * The AES-XTS block mode is standardized by NIST SP 800-38E
+ *
+ * and described in detail by IEEE P1619
+ * .
*/
/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
@@ -53,7 +58,8 @@
#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
-/* Error codes in range 0x0023-0x0025 */
+/* Error codes in range 0x0021-0x0025 */
+#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */
#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */
#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */
@@ -73,7 +79,7 @@ extern "C" {
/**
* \brief The AES context-type definition.
*/
-typedef struct
+typedef struct mbedtls_aes_context
{
int nr; /*!< The number of rounds. */
uint32_t *rk; /*!< AES round keys. */
@@ -88,6 +94,19 @@ typedef struct
}
mbedtls_aes_context;
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief The AES XTS context-type definition.
+ */
+typedef struct mbedtls_aes_xts_context
+{
+ mbedtls_aes_context crypt; /*!< The AES context to use for AES block
+ encryption or decryption. */
+ mbedtls_aes_context tweak; /*!< The AES context used for tweak
+ computation. */
+} mbedtls_aes_xts_context;
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
#else /* MBEDTLS_AES_ALT */
#include "aes_alt.h"
#endif /* MBEDTLS_AES_ALT */
@@ -109,6 +128,25 @@ void mbedtls_aes_init( mbedtls_aes_context *ctx );
*/
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.
+ */
+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.
+ */
+void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
/**
* \brief This function sets the encryption key.
*
@@ -141,6 +179,44 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
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.
+ * \param key The encryption key. This is comprised of the XTS key1
+ * concatenated with the XTS key2.
+ * \param keybits The size of \p key passed in bits. Valid options are:
+ *
256 bits (each of key1 and key2 is a 128-bit key)
+ *
512 bits (each of key1 and key2 is a 256-bit key)
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits );
+
+/**
+ * \brief This function prepares an XTS context for decryption and
+ * sets the decryption key.
+ *
+ * \param ctx The AES XTS context to which the key should be bound.
+ * \param key The decryption key. This is comprised of the XTS key1
+ * concatenated with the XTS key2.
+ * \param keybits The size of \p key passed in bits. Valid options are:
+ *
256 bits (each of key1 and key2 is a 128-bit key)
+ *
512 bits (each of key1 and key2 is a 256-bit key)
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
/**
* \brief This function performs an AES single-block encryption or
* decryption operation.
@@ -212,6 +288,49 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
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.
+ * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
+ * #MBEDTLS_AES_DECRYPT.
+ * \param length The length of a data unit in bytes. This can be any
+ * length between 16 bytes and 2^24 bytes inclusive
+ * (between 1 and 2^20 block cipher blocks).
+ * \param data_unit The address of the data unit encoded as an array of 16
+ * bytes in little-endian format. For disk encryption, this
+ * is typically the index of the block device sector that
+ * contains the data.
+ * \param input The buffer holding the input data (which is an entire
+ * data unit). This function reads \p length bytes from \p
+ * input.
+ * \param output The buffer holding the output data (which is an entire
+ * data unit). This function writes \p length bytes to \p
+ * output.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is
+ * smaller than an AES block in size (16 bytes) or if \p
+ * length is larger than 2^20 blocks (16 MiB).
+ */
+int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char data_unit[16],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
* \brief This function performs an AES-CFB128 encryption or decryption
@@ -295,6 +414,56 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
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.
+ * \param length The length of the input data.
+ * \param iv_off The offset in IV (updated after use).
+ * \param iv The initialization vector (updated after use).
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
* \brief This function performs an AES-CTR encryption or decryption
@@ -309,7 +478,49 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
* must use the context initialized with mbedtls_aes_setkey_enc()
* for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT.
*
- * \warning You must keep the maximum use of your counter in mind.
+ * \warning You must never reuse a nonce value with the same key. Doing so
+ * would void the encryption for the two messages encrypted with
+ * the same nonce and key.
+ *
+ * There are two common strategies for managing nonces with CTR:
+ *
+ * 1. You can handle everything as a single message processed over
+ * successive calls to this function. In that case, you want to
+ * set \p nonce_counter and \p nc_off to 0 for the first call, and
+ * then preserve the values of \p nonce_counter, \p nc_off and \p
+ * stream_block across calls to this function as they will be
+ * updated by this function.
+ *
+ * With this strategy, you must not encrypt more than 2**128
+ * blocks of data with the same key.
+ *
+ * 2. You can encrypt separate messages by dividing the \p
+ * nonce_counter buffer in two areas: the first one used for a
+ * per-message nonce, handled by yourself, and the second one
+ * updated by this function internally.
+ *
+ * For example, you might reserve the first 12 bytes for the
+ * per-message nonce, and the last 4 bytes for internal use. In that
+ * case, before calling this function on a new message you need to
+ * set the first 12 bytes of \p nonce_counter to your chosen nonce
+ * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p
+ * stream_block to be ignored). That way, you can encrypt at most
+ * 2**96 messages of up to 2**32 blocks each with the same key.
+ *
+ * The per-message nonce (or information sufficient to reconstruct
+ * it) needs to be communicated with the ciphertext and must be unique.
+ * The recommended way to ensure uniqueness is to use a message
+ * counter. An alternative is to generate random nonces, but this
+ * limits the number of messages that can be securely encrypted:
+ * for example, with 96-bit random nonces, you should not encrypt
+ * more than 2**32 messages with the same key.
+ *
+ * Note that for both stategies, sizes are measured in blocks and
+ * that an AES block is 16 bytes.
+ *
+ * \warning Upon return, \p stream_block contains sensitive data. Its
+ * content must not be written to insecure storage and should be
+ * securely discarded as soon as it's no longer needed.
*
* \param ctx The AES context to use for encryption or decryption.
* \param length The length of the input data.
diff --git a/include/mbedtls/arc4.h b/include/mbedtls/arc4.h
index f11fc5be0a..83a7461f3f 100644
--- a/include/mbedtls/arc4.h
+++ b/include/mbedtls/arc4.h
@@ -53,7 +53,7 @@ extern "C" {
* security risk. We recommend considering stronger ciphers instead.
*
*/
-typedef struct
+typedef struct mbedtls_arc4_context
{
int x; /*!< permutation index */
int y; /*!< permutation index */
diff --git a/include/mbedtls/aria.h b/include/mbedtls/aria.h
new file mode 100644
index 0000000000..4a79c13872
--- /dev/null
+++ b/include/mbedtls/aria.h
@@ -0,0 +1,331 @@
+/**
+ * \file aria.h
+ *
+ * \brief ARIA block cipher
+ *
+ * The ARIA algorithm is a symmetric block cipher that can encrypt and
+ * decrypt information. It is defined by the Korean Agency for
+ * Technology and Standards (KATS) in KS X 1213:2004 (in
+ * Korean, but see http://210.104.33.10/ARIA/index-e.html in English)
+ * and also described by the IETF in RFC 5794.
+ */
+/* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_ARIA_H
+#define MBEDTLS_ARIA_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include
+#include
+
+#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */
+#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */
+
+#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */
+#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */
+#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */
+
+#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH -0x005C /**< Invalid key length. */
+#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */
+#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */
+#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */
+
+#if !defined(MBEDTLS_ARIA_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The ARIA context-type definition.
+ */
+typedef struct mbedtls_aria_context
+{
+ unsigned char nr; /*!< The number of rounds (12, 14 or 16) */
+ /*! The ARIA round keys. */
+ uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4];
+}
+mbedtls_aria_context;
+
+#else /* MBEDTLS_ARIA_ALT */
+#include "aria_alt.h"
+#endif /* MBEDTLS_ARIA_ALT */
+
+/**
+ * \brief This function initializes the specified ARIA context.
+ *
+ * It must be the first API called before using
+ * the context.
+ *
+ * \param ctx The ARIA context to initialize.
+ */
+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.
+ */
+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.
+ * \param key The encryption key.
+ * \param keybits The size of data passed in bits. Valid options are:
+ *
128 bits
+ *
192 bits
+ *
256 bits
+ *
+ * \return \c 0 on success or #MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH
+ * 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.
+ * \param key The decryption key.
+ * \param keybits The size of data passed. Valid options are:
+ *
128 bits
+ *
192 bits
+ *
256 bits
+ *
+ * \return \c 0 on success, or #MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH 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.
+ * \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.
+ */
+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.
+ * \param mode The ARIA operation: #MBEDTLS_ARIA_ENCRYPT or
+ * #MBEDTLS_ARIA_DECRYPT.
+ * \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).
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ *
+ * \return \c 0 on success, or #MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH
+ * 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.
+ * \param mode The ARIA operation: #MBEDTLS_ARIA_ENCRYPT or
+ * #MBEDTLS_ARIA_DECRYPT.
+ * \param length The length of the input data.
+ * \param iv_off The offset in IV (updated after use).
+ * \param iv The initialization vector (updated after use).
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/**
+ * \brief This function performs an ARIA-CTR encryption or decryption
+ * operation.
+ *
+ * This function performs the operation defined in the \p mode
+ * parameter (encrypt/decrypt), on the input data buffer
+ * defined in the \p input parameter.
+ *
+ * Due to the nature of CTR, you must use the same key schedule
+ * for both encryption and decryption operations. Therefore, you
+ * must use the context initialized with mbedtls_aria_setkey_enc()
+ * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT.
+ *
+ * \warning You must never reuse a nonce value with the same key. Doing so
+ * would void the encryption for the two messages encrypted with
+ * the same nonce and key.
+ *
+ * There are two common strategies for managing nonces with CTR:
+ *
+ * 1. You can handle everything as a single message processed over
+ * successive calls to this function. In that case, you want to
+ * set \p nonce_counter and \p nc_off to 0 for the first call, and
+ * then preserve the values of \p nonce_counter, \p nc_off and \p
+ * stream_block across calls to this function as they will be
+ * updated by this function.
+ *
+ * With this strategy, you must not encrypt more than 2**128
+ * blocks of data with the same key.
+ *
+ * 2. You can encrypt separate messages by dividing the \p
+ * nonce_counter buffer in two areas: the first one used for a
+ * per-message nonce, handled by yourself, and the second one
+ * updated by this function internally.
+ *
+ * For example, you might reserve the first 12 bytes for the
+ * per-message nonce, and the last 4 bytes for internal use. In that
+ * case, before calling this function on a new message you need to
+ * set the first 12 bytes of \p nonce_counter to your chosen nonce
+ * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p
+ * stream_block to be ignored). That way, you can encrypt at most
+ * 2**96 messages of up to 2**32 blocks each with the same key.
+ *
+ * The per-message nonce (or information sufficient to reconstruct
+ * it) needs to be communicated with the ciphertext and must be unique.
+ * The recommended way to ensure uniqueness is to use a message
+ * counter. An alternative is to generate random nonces, but this
+ * limits the number of messages that can be securely encrypted:
+ * for example, with 96-bit random nonces, you should not encrypt
+ * more than 2**32 messages with the same key.
+ *
+ * Note that for both stategies, sizes are measured in blocks and
+ * that an ARIA block is 16 bytes.
+ *
+ * \warning Upon return, \p stream_block contains sensitive data. Its
+ * content must not be written to insecure storage and should be
+ * securely discarded as soon as it's no longer needed.
+ *
+ * \param ctx The ARIA context to use for encryption or decryption.
+ * \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.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream block for resuming. This is
+ * overwritten by the function.
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE],
+ unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output );
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief Checkup routine.
+ *
+ * \return \c 0 on success, or \c 1 on failure.
+ */
+int mbedtls_aria_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aria.h */
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index 31383b1eb5..732ecbef1c 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -177,7 +177,7 @@ extern "C" {
/**
* \brief MPI structure
*/
-typedef struct
+typedef struct mbedtls_mpi
{
int s; /*!< integer sign */
size_t n; /*!< total # of limbs */
diff --git a/include/mbedtls/blowfish.h b/include/mbedtls/blowfish.h
index 22479be5ae..eea6882f75 100644
--- a/include/mbedtls/blowfish.h
+++ b/include/mbedtls/blowfish.h
@@ -55,7 +55,7 @@ extern "C" {
/**
* \brief Blowfish context structure
*/
-typedef struct
+typedef struct mbedtls_blowfish_context
{
uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */
uint32_t S[4][256]; /*!< key dependent S-boxes */
@@ -174,7 +174,46 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
/**
* \brief Blowfish-CTR buffer encryption/decryption
*
- * Warning: You have to keep the maximum use of your counter in mind!
+ * \warning You must never reuse a nonce value with the same key. Doing so
+ * would void the encryption for the two messages encrypted with
+ * the same nonce and key.
+ *
+ * There are two common strategies for managing nonces with CTR:
+ *
+ * 1. You can handle everything as a single message processed over
+ * successive calls to this function. In that case, you want to
+ * set \p nonce_counter and \p nc_off to 0 for the first call, and
+ * then preserve the values of \p nonce_counter, \p nc_off and \p
+ * stream_block across calls to this function as they will be
+ * updated by this function.
+ *
+ * With this strategy, you must not encrypt more than 2**64
+ * blocks of data with the same key.
+ *
+ * 2. You can encrypt separate messages by dividing the \p
+ * nonce_counter buffer in two areas: the first one used for a
+ * per-message nonce, handled by yourself, and the second one
+ * updated by this function internally.
+ *
+ * For example, you might reserve the first 4 bytes for the
+ * per-message nonce, and the last 4 bytes for internal use. In that
+ * case, before calling this function on a new message you need to
+ * set the first 4 bytes of \p nonce_counter to your chosen nonce
+ * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p
+ * stream_block to be ignored). That way, you can encrypt at most
+ * 2**32 messages of up to 2**32 blocks each with the same key.
+ *
+ * The per-message nonce (or information sufficient to reconstruct
+ * it) needs to be communicated with the ciphertext and must be unique.
+ * The recommended way to ensure uniqueness is to use a message
+ * counter.
+ *
+ * Note that for both stategies, sizes are measured in blocks and
+ * that a Blowfish block is 8 bytes.
+ *
+ * \warning Upon return, \p stream_block contains sensitive data. Its
+ * content must not be written to insecure storage and should be
+ * securely discarded as soon as it's no longer needed.
*
* \param ctx Blowfish context
* \param length The length of the data
diff --git a/include/mbedtls/bn_mul.h b/include/mbedtls/bn_mul.h
index 354c1cc1ab..0af694c7c5 100644
--- a/include/mbedtls/bn_mul.h
+++ b/include/mbedtls/bn_mul.h
@@ -49,7 +49,14 @@
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
#if defined(__GNUC__) && \
( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
-#if defined(__i386__)
+
+/*
+ * Disable use of the i386 assembly code below if option -O0, to disable all
+ * compiler optimisations, is passed, detected with __OPTIMIZE__
+ * This is done as the number of registers used in the assembly code doesn't
+ * work with the -O0 option.
+ */
+#if defined(__i386__) && defined(__OPTIMIZE__)
#define MULADDC_INIT \
asm( \
@@ -142,7 +149,7 @@
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
- : "eax", "ecx", "edx", "esi", "edi" \
+ : "eax", "ebx", "ecx", "edx", "esi", "edi" \
);
#else
@@ -154,7 +161,7 @@
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
- : "eax", "ecx", "edx", "esi", "edi" \
+ : "eax", "ebx", "ecx", "edx", "esi", "edi" \
);
#endif /* SSE2 */
#endif /* i386 */
@@ -521,7 +528,7 @@
"swi r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
- : "r3", "r4" "r5", "r6", "r7", "r8", \
+ : "r3", "r4", "r5", "r6", "r7", "r8", \
"r9", "r10", "r11", "r12", "r13" \
);
@@ -558,9 +565,8 @@
#endif /* TriCore */
/*
- * gcc -O0 by default uses r7 for the frame pointer, so it complains about our
- * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately,
- * passing that option is not easy when building with yotta.
+ * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about
+ * our use of r7 below, unless -fomit-frame-pointer is passed.
*
* On the other hand, -fomit-frame-pointer is implied by any -Ox options with
* x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
@@ -630,6 +636,23 @@
"r6", "r7", "r8", "r9", "cc" \
);
+#elif defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)
+
+#define MULADDC_INIT \
+ asm(
+
+#define MULADDC_CORE \
+ "ldr r0, [%0], #4 \n\t" \
+ "ldr r1, [%1] \n\t" \
+ "umaal r1, %2, %3, r0 \n\t" \
+ "str r1, [%1], #4 \n\t"
+
+#define MULADDC_STOP \
+ : "=r" (s), "=r" (d), "=r" (c) \
+ : "r" (b), "0" (s), "1" (d), "2" (c) \
+ : "r0", "r1", "memory" \
+ );
+
#else
#define MULADDC_INIT \
diff --git a/include/mbedtls/camellia.h b/include/mbedtls/camellia.h
index f0466bfd7e..fa1e05ee7f 100644
--- a/include/mbedtls/camellia.h
+++ b/include/mbedtls/camellia.h
@@ -51,7 +51,7 @@ extern "C" {
/**
* \brief CAMELLIA context structure
*/
-typedef struct
+typedef struct mbedtls_camellia_context
{
int nr; /*!< number of rounds */
uint32_t rk[68]; /*!< CAMELLIA round keys */
@@ -187,12 +187,54 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
/**
* \brief CAMELLIA-CTR buffer encryption/decryption
*
- * Warning: You have to keep the maximum use of your counter in mind!
- *
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT.
*
+ * \warning You must never reuse a nonce value with the same key. Doing so
+ * would void the encryption for the two messages encrypted with
+ * the same nonce and key.
+ *
+ * There are two common strategies for managing nonces with CTR:
+ *
+ * 1. You can handle everything as a single message processed over
+ * successive calls to this function. In that case, you want to
+ * set \p nonce_counter and \p nc_off to 0 for the first call, and
+ * then preserve the values of \p nonce_counter, \p nc_off and \p
+ * stream_block across calls to this function as they will be
+ * updated by this function.
+ *
+ * With this strategy, you must not encrypt more than 2**128
+ * blocks of data with the same key.
+ *
+ * 2. You can encrypt separate messages by dividing the \p
+ * nonce_counter buffer in two areas: the first one used for a
+ * per-message nonce, handled by yourself, and the second one
+ * updated by this function internally.
+ *
+ * For example, you might reserve the first 12 bytes for the
+ * per-message nonce, and the last 4 bytes for internal use. In that
+ * case, before calling this function on a new message you need to
+ * set the first 12 bytes of \p nonce_counter to your chosen nonce
+ * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p
+ * stream_block to be ignored). That way, you can encrypt at most
+ * 2**96 messages of up to 2**32 blocks each with the same key.
+ *
+ * The per-message nonce (or information sufficient to reconstruct
+ * it) needs to be communicated with the ciphertext and must be unique.
+ * The recommended way to ensure uniqueness is to use a message
+ * counter. An alternative is to generate random nonces, but this
+ * limits the number of messages that can be securely encrypted:
+ * for example, with 96-bit random nonces, you should not encrypt
+ * more than 2**32 messages with the same key.
+ *
+ * Note that for both stategies, sizes are measured in blocks and
+ * that a CAMELLIA 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 CAMELLIA context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h
index 8585ce5e7c..e1dc124b89 100644
--- a/include/mbedtls/ccm.h
+++ b/include/mbedtls/ccm.h
@@ -14,6 +14,18 @@
*
Nonce - A unique value that is assigned to the payload and the
* associated data.
*
+ * Definition of CCM:
+ * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+ * RFC 3610 "Counter with CBC-MAC (CCM)"
+ *
+ * Related:
+ * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
+ *
+ * Definition of CCM*:
+ * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks
+ * Integer representation is fixed most-significant-octet-first order and
+ * the representation of octets is most-significant-bit-first order. This is
+ * consistent with RFC 3610.
*/
/*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
@@ -56,7 +68,8 @@ extern "C" {
* \brief The CCM context-type definition. The CCM context is passed
* to the APIs called.
*/
-typedef struct {
+typedef struct mbedtls_ccm_context
+{
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
}
mbedtls_ccm_context;
@@ -102,7 +115,6 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
/**
* \brief This function encrypts a buffer using CCM.
*
- *
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in RFC-3610:
* Counter with CBC-MAC (CCM), use
@@ -112,15 +124,17 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
* \param ctx The CCM context to use for encryption.
* \param length The length of the input data in Bytes.
* \param iv Initialization vector (nonce).
- * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ * or 13. The length L of the message length field is
+ * 15 - \p iv_len.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
- * \param tag The buffer holding the tag.
- * \param tag_len The length of the tag to generate in Bytes:
+ * \param tag The buffer holding the authentication field.
+ * \param tag_len The length of the authentication field to generate in Bytes:
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success.
@@ -133,21 +147,64 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
unsigned char *tag, size_t tag_len );
/**
- * \brief This function performs a CCM authenticated decryption of a
- * buffer.
+ * \brief This function encrypts a buffer using CCM*.
*
- * \param ctx The CCM context to use for decryption.
+ * \note The tag is written to a separate buffer. To concatenate
+ * the \p tag with the \p output, as done in RFC-3610:
+ * Counter with CBC-MAC (CCM), use
+ * \p tag = \p output + \p length, and make sure that the
+ * output buffer is at least \p length + \p tag_len wide.
+ *
+ * \note When using this function in a variable tag length context,
+ * the tag length has to be encoded into the \p iv passed to
+ * this function.
+ *
+ * \param ctx The CCM context to use for encryption.
* \param length The length of the input data in Bytes.
- * \param iv Initialization vector.
- * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param iv Initialization vector (nonce).
+ * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ * or 13. The length L of the message length field is
+ * 15 - \p iv_len.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
- * \param tag The buffer holding the tag.
- * \param tag_len The length of the tag in Bytes.
+ * \param tag The buffer holding the authentication field.
+ * \param tag_len The length of the authentication field to generate in Bytes:
+ * 0, 4, 6, 8, 10, 12, 14 or 16.
+ *
+ * \warning Passing 0 as \p tag_len means that the message is no
+ * longer authenticated.
+ *
+ * \return \c 0 on success.
+ * \return A CCM or cipher-specific error code on failure.
+ */
+int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief This function performs a CCM authenticated decryption of a
+ * buffer.
+ *
+ * \param ctx The CCM context to use for decryption.
+ * \param length The length of the input data in Bytes.
+ * \param iv Initialization vector (nonce).
+ * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ * or 13. The length L of the message length field is
+ * 15 - \p iv_len.
+ * \param add The additional data field.
+ * \param add_len The length of additional data in Bytes.
+ * Must be less than 2^16 - 2^8.
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ * Must be at least \p length Bytes wide.
+ * \param tag The buffer holding the authentication field.
+ * \param tag_len The length of the authentication field in Bytes.
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success. This indicates that the message is authentic.
@@ -160,6 +217,43 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
+/**
+ * \brief This function performs a CCM* authenticated decryption of a
+ * buffer.
+ *
+ * \note When using this function in a variable tag length context,
+ * the tag length has to be decoded from \p iv and passed to
+ * this function as \p tag_len. (\p tag needs to be adjusted
+ * accordingly.)
+ *
+ * \param ctx The CCM context to use for decryption.
+ * \param length The length of the input data in Bytes.
+ * \param iv Initialization vector (nonce).
+ * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ * or 13. The length L of the message length field is
+ * 15 - \p iv_len.
+ * \param add The additional data field.
+ * \param add_len The length of additional data in Bytes.
+ * Must be less than 2^16 - 2^8.
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ * Must be at least \p length Bytes wide.
+ * \param tag The buffer holding the authentication field.
+ * \param tag_len The length of the authentication field in Bytes.
+ * 0, 4, 6, 8, 10, 12, 14 or 16.
+ *
+ * \warning Passing 0 as \p tag_len means that the message is no
+ * longer authenticated.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
+ * \return A cipher-specific error code on calculation failure.
+ */
+int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ const unsigned char *tag, size_t tag_len );
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**
diff --git a/include/mbedtls/chacha20.h b/include/mbedtls/chacha20.h
new file mode 100644
index 0000000000..cfea40a574
--- /dev/null
+++ b/include/mbedtls/chacha20.h
@@ -0,0 +1,212 @@
+/**
+ * \file chacha20.h
+ *
+ * \brief This file contains ChaCha20 definitions and functions.
+ *
+ * ChaCha20 is a stream cipher that can encrypt and decrypt
+ * information. ChaCha was created by Daniel Bernstein as a variant of
+ * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf
+ * ChaCha20 is the variant with 20 rounds, that was also standardized
+ * in RFC 7539.
+ *
+ * \author Daniel King
+ */
+
+/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_CHACHA20_H
+#define MBEDTLS_CHACHA20_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include
+#include
+
+#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */
+#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */
+#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDTLS_CHACHA20_ALT)
+
+typedef struct mbedtls_chacha20_context
+{
+ uint32_t state[16]; /*! The state (before round operations). */
+ uint8_t keystream8[64]; /*! Leftover keystream bytes. */
+ size_t keystream_bytes_used; /*! Number of keystream bytes already used. */
+}
+mbedtls_chacha20_context;
+
+#else /* MBEDTLS_CHACHA20_ALT */
+#include "chacha20_alt.h"
+#endif /* MBEDTLS_CHACHA20_ALT */
+
+/**
+ * \brief This function initializes the specified ChaCha20 context.
+ *
+ * It must be the first API called before using
+ * the context.
+ *
+ * It is usually followed by calls to
+ * \c mbedtls_chacha20_setkey() and
+ * \c mbedtls_chacha20_starts(), then one or more calls to
+ * to \c mbedtls_chacha20_update(), and finally to
+ * \c mbedtls_chacha20_free().
+ *
+ * \param ctx The ChaCha20 context to initialize.
+ */
+void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx );
+
+/**
+ * \brief This function releases and clears the specified ChaCha20 context.
+ *
+ * \param ctx The ChaCha20 context to clear.
+ */
+void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx );
+
+/**
+ * \brief This function sets the encryption/decryption key.
+ *
+ * \note After using this function, you must also call
+ * \c mbedtls_chacha20_starts() to set a nonce before you
+ * start encrypting/decrypting data with
+ * \c mbedtls_chacha_update().
+ *
+ * \param ctx The ChaCha20 context to which the key should be bound.
+ * \param key The encryption/decryption key. Must be 32 bytes in length.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL.
+ */
+int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
+ const unsigned char key[32] );
+
+/**
+ * \brief This function sets the nonce and initial counter value.
+ *
+ * \note A ChaCha20 context can be re-used with the same key by
+ * calling this function to change the nonce.
+ *
+ * \warning You must never use the same nonce twice with the same key.
+ * This would void any confidentiality guarantees for the
+ * messages encrypted with the same nonce and key.
+ *
+ * \param ctx The ChaCha20 context to which the nonce should be bound.
+ * \param nonce The nonce. Must be 12 bytes in size.
+ * \param counter The initial counter value. This is usually 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is
+ * NULL.
+ */
+int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
+ const unsigned char nonce[12],
+ uint32_t counter );
+
+/**
+ * \brief This function encrypts or decrypts data.
+ *
+ * Since ChaCha20 is a stream cipher, the same operation is
+ * used for encrypting and decrypting data.
+ *
+ * \note The \p input and \p output pointers must either be equal or
+ * point to non-overlapping buffers.
+ *
+ * \note \c mbedtls_chacha20_setkey() and
+ * \c mbedtls_chacha20_starts() must be called at least once
+ * to setup the context before this function can be called.
+ *
+ * \note This function can be called multiple times in a row in
+ * order to encrypt of decrypt data piecewise with the same
+ * key and nonce.
+ *
+ * \param ctx The ChaCha20 context to use for encryption or decryption.
+ * \param size The length of the input data in bytes.
+ * \param input The buffer holding the input data.
+ * This pointer can be NULL if size == 0.
+ * \param output The buffer holding the output data.
+ * Must be able to hold \p size bytes.
+ * This pointer can be NULL if size == 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if the ctx, input, or
+ * output pointers are NULL.
+ */
+int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
+ size_t size,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function encrypts or decrypts data with ChaCha20 and
+ * the given key and nonce.
+ *
+ * Since ChaCha20 is a stream cipher, the same operation is
+ * used for encrypting and decrypting data.
+ *
+ * \warning You must never use the same (key, nonce) pair more than
+ * once. This would void any confidentiality guarantees for
+ * the messages encrypted with the same nonce and key.
+ *
+ * \note The \p input and \p output pointers must either be equal or
+ * point to non-overlapping buffers.
+ *
+ * \param key The encryption/decryption key. Must be 32 bytes in length.
+ * \param nonce The nonce. Must be 12 bytes in size.
+ * \param counter The initial counter value. This is usually 0.
+ * \param size The length of the input data in bytes.
+ * \param input The buffer holding the input data.
+ * This pointer can be NULL if size == 0.
+ * \param output The buffer holding the output data.
+ * Must be able to hold \p size bytes.
+ * This pointer can be NULL if size == 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if key, nonce, input,
+ * or output is NULL.
+ */
+int mbedtls_chacha20_crypt( const unsigned char key[32],
+ const unsigned char nonce[12],
+ uint32_t counter,
+ size_t size,
+ const unsigned char* input,
+ unsigned char* output );
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief The ChaCha20 checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedtls_chacha20_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CHACHA20_H */
diff --git a/include/mbedtls/chachapoly.h b/include/mbedtls/chachapoly.h
new file mode 100644
index 0000000000..7de6f4e8c6
--- /dev/null
+++ b/include/mbedtls/chachapoly.h
@@ -0,0 +1,355 @@
+/**
+ * \file chachapoly.h
+ *
+ * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and
+ * functions.
+ *
+ * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption
+ * with Associated Data (AEAD) that can be used to encrypt and
+ * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel
+ * Bernstein and was standardized in RFC 7539.
+ *
+ * \author Daniel King
+ */
+
+/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_CHACHAPOLY_H
+#define MBEDTLS_CHACHAPOLY_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+/* for shared error codes */
+#include "poly1305.h"
+
+#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */
+#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */
+ MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */
+}
+mbedtls_chachapoly_mode_t;
+
+#if !defined(MBEDTLS_CHACHAPOLY_ALT)
+
+#include "chacha20.h"
+
+typedef struct mbedtls_chachapoly_context
+{
+ mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */
+ mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */
+ uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */
+ uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */
+ int state; /**< The current state of the context. */
+ mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */
+}
+mbedtls_chachapoly_context;
+
+#else /* !MBEDTLS_CHACHAPOLY_ALT */
+#include "chachapoly_alt.h"
+#endif /* !MBEDTLS_CHACHAPOLY_ALT */
+
+/**
+ * \brief This function initializes the specified ChaCha20-Poly1305 context.
+ *
+ * It must be the first API called before using
+ * the context. It must be followed by a call to
+ * \c mbedtls_chachapoly_setkey() before any operation can be
+ * done, and to \c mbedtls_chachapoly_free() once all
+ * operations with that context have been finished.
+ *
+ * In order to encrypt or decrypt full messages at once, for
+ * each message you should make a single call to
+ * \c mbedtls_chachapoly_crypt_and_tag() or
+ * \c mbedtls_chachapoly_auth_decrypt().
+ *
+ * In order to encrypt messages piecewise, for each
+ * message you should make a call to
+ * \c mbedtls_chachapoly_starts(), then 0 or more calls to
+ * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to
+ * \c mbedtls_chachapoly_update(), then one call to
+ * \c mbedtls_chachapoly_finish().
+ *
+ * \warning Decryption with the piecewise API is discouraged! Always
+ * use \c mbedtls_chachapoly_auth_decrypt() when possible!
+ *
+ * If however this is not possible because the data is too
+ * large to fit in memory, you need to:
+ *
+ * - call \c mbedtls_chachapoly_starts() and (if needed)
+ * \c mbedtls_chachapoly_update_aad() as above,
+ * - call \c mbedtls_chachapoly_update() multiple times and
+ * ensure its output (the plaintext) is NOT used in any other
+ * way than placing it in temporary storage at this point,
+ * - call \c mbedtls_chachapoly_finish() to compute the
+ * authentication tag and compared it in constant time to the
+ * tag received with the ciphertext.
+ *
+ * If the tags are not equal, you must immediately discard
+ * all previous outputs of \c mbedtls_chachapoly_update(),
+ * otherwise you can now safely use the plaintext.
+ *
+ * \param ctx The ChachaPoly context to initialize.
+ */
+void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx );
+
+/**
+ * \brief This function releases and clears the specified ChaCha20-Poly1305 context.
+ *
+ * \param ctx The ChachaPoly context to clear.
+ */
+void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx );
+
+/**
+ * \brief This function sets the ChaCha20-Poly1305 symmetric encryption key.
+ *
+ * \param ctx The ChaCha20-Poly1305 context to which the key should be
+ * bound.
+ * \param key The 256-bit (32 bytes) key.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if \p ctx or \p key are NULL.
+ */
+int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
+ const unsigned char key[32] );
+
+/**
+ * \brief This function starts a ChaCha20-Poly1305 encryption or
+ * decryption operation.
+ *
+ * \warning You must never use the same nonce twice with the same key.
+ * This would void any confidentiality and authenticity
+ * guarantees for the messages encrypted with the same nonce
+ * and key.
+ *
+ * \note If the context is being used for AAD only (no data to
+ * encrypt or decrypt) then \p mode can be set to any value.
+ *
+ * \warning Decryption with the piecewise API is discouraged, see the
+ * warning on \c mbedtls_chachapoly_init().
+ *
+ * \param ctx The ChaCha20-Poly1305 context.
+ * \param nonce The nonce/IV to use for the message. Must be 12 bytes.
+ * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
+ * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning).
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if \p ctx or \p mac are NULL.
+ */
+int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
+ const unsigned char nonce[12],
+ mbedtls_chachapoly_mode_t mode );
+
+/**
+ * \brief This function feeds additional data to be authenticated
+ * into an ongoing ChaCha20-Poly1305 operation.
+ *
+ * The Additional Authenticated Data (AAD), also called
+ * Associated Data (AD) is only authenticated but not
+ * encrypted nor included in the encrypted output. It is
+ * usually transmitted separately from the ciphertext or
+ * computed locally by each party.
+ *
+ * \note This function is called before data is encrypted/decrypted.
+ * I.e. call this function to process the AAD before calling
+ * \c mbedtls_chachapoly_update().
+ *
+ * You may call this function multiple times to process
+ * an arbitrary amount of AAD. It is permitted to call
+ * this function 0 times, if no AAD is used.
+ *
+ * This function cannot be called any more if data has
+ * been processed by \c mbedtls_chachapoly_update(),
+ * or if the context has been finished.
+ *
+ * \warning Decryption with the piecewise API is discouraged, see the
+ * warning on \c mbedtls_chachapoly_init().
+ *
+ * \param ctx The ChaCha20-Poly1305 context to use.
+ * \param aad_len The length (in bytes) of the AAD. The length has no
+ * restrictions.
+ * \param aad Buffer containing the AAD.
+ * This pointer can be NULL if aad_len == 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if \p ctx or \p aad are NULL.
+ * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
+ * if the operations has not been started or has been
+ * finished, or if the AAD has been finished.
+ */
+int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
+ const unsigned char *aad,
+ size_t aad_len );
+
+/**
+ * \brief Thus function feeds data to be encrypted or decrypted
+ * into an on-going ChaCha20-Poly1305
+ * operation.
+ *
+ * The direction (encryption or decryption) depends on the
+ * mode that was given when calling
+ * \c mbedtls_chachapoly_starts().
+ *
+ * You may call this function multiple times to process
+ * an arbitrary amount of data. It is permitted to call
+ * this function 0 times, if no data is to be encrypted
+ * or decrypted.
+ *
+ * \warning Decryption with the piecewise API is discouraged, see the
+ * warning on \c mbedtls_chachapoly_init().
+ *
+ * \param ctx The ChaCha20-Poly1305 context to use.
+ * \param len The length (in bytes) of the data to encrypt or decrypt.
+ * \param input The buffer containing the data to encrypt or decrypt.
+ * This pointer can be NULL if len == 0.
+ * \param output The buffer to where the encrypted or decrypted data is written.
+ * Must be able to hold \p len bytes.
+ * This pointer can be NULL if len == 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if \p ctx, \p input, or \p output are NULL.
+ * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
+ * if the operation has not been started or has been
+ * finished.
+ */
+int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
+ size_t len,
+ const unsigned char *input,
+ unsigned char *output );
+
+/**
+ * \brief This function finished the ChaCha20-Poly1305 operation and
+ * generates the MAC (authentication tag).
+ *
+ * \param ctx The ChaCha20-Poly1305 context to use.
+ * \param mac The buffer to where the 128-bit (16 bytes) MAC is written.
+ *
+ * \warning Decryption with the piecewise API is discouraged, see the
+ * warning on \c mbedtls_chachapoly_init().
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if \p ctx or \p mac are NULL.
+ * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
+ * if the operation has not been started or has been
+ * finished.
+ */
+int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
+ unsigned char mac[16] );
+
+/**
+ * \brief This function performs a complete ChaCha20-Poly1305
+ * authenticated encryption with the previously-set key.
+ *
+ * \note Before using this function, you must set the key with
+ * \c mbedtls_chachapoly_setkey().
+ *
+ * \warning You must never use the same nonce twice with the same key.
+ * This would void any confidentiality and authenticity
+ * guarantees for the messages encrypted with the same nonce
+ * and key.
+ *
+ * \param ctx The ChaCha20-Poly1305 context to use (holds the key).
+ * \param length The length (in bytes) of the data to encrypt or decrypt.
+ * \param nonce The 96-bit (12 bytes) nonce/IV to use.
+ * \param aad The buffer containing the additional authenticated data (AAD).
+ * This pointer can be NULL if aad_len == 0.
+ * \param aad_len The length (in bytes) of the AAD data to process.
+ * \param input The buffer containing the data to encrypt or decrypt.
+ * This pointer can be NULL if ilen == 0.
+ * \param output The buffer to where the encrypted or decrypted data is written.
+ * This pointer can be NULL if ilen == 0.
+ * \param tag The buffer to where the computed 128-bit (16 bytes) MAC is written.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if one or more of the required parameters are NULL.
+ */
+int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
+ size_t length,
+ const unsigned char nonce[12],
+ const unsigned char *aad,
+ size_t aad_len,
+ const unsigned char *input,
+ unsigned char *output,
+ unsigned char tag[16] );
+
+/**
+ * \brief This function performs a complete ChaCha20-Poly1305
+ * authenticated decryption with the previously-set key.
+ *
+ * \note Before using this function, you must set the key with
+ * \c mbedtls_chachapoly_setkey().
+ *
+ * \param ctx The ChaCha20-Poly1305 context to use (holds the key).
+ * \param length The length (in bytes) of the data to decrypt.
+ * \param nonce The 96-bit (12 bytes) nonce/IV to use.
+ * \param aad The buffer containing the additional authenticated data (AAD).
+ * This pointer can be NULL if aad_len == 0.
+ * \param aad_len The length (in bytes) of the AAD data to process.
+ * \param tag The buffer holding the authentication tag.
+ * \param input The buffer containing the data to decrypt.
+ * This pointer can be NULL if ilen == 0.
+ * \param output The buffer to where the decrypted data is written.
+ * This pointer can be NULL if ilen == 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if one or more of the required parameters are NULL.
+ * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED
+ * if the data was not authentic.
+ */
+int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
+ size_t length,
+ const unsigned char nonce[12],
+ const unsigned char *aad,
+ size_t aad_len,
+ const unsigned char tag[16],
+ const unsigned char *input,
+ unsigned char *output );
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief The ChaCha20-Poly1305 checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedtls_chachapoly_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CHACHAPOLY_H */
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index be80332963..9e6bb8a46a 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -4,7 +4,7 @@
* \brief Consistency checks for configuration options
*/
/*
- * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -87,6 +87,11 @@
#error "MBEDTLS_CMAC_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_NIST_KW_C) && \
+ ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) )
+#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C)
#error "MBEDTLS_ECDH_C defined, but not all prerequisites"
#endif
@@ -191,6 +196,10 @@
#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C)
+#error "MBEDTLS_HKDF_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C)
#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites"
#endif
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 3ee2ab7db9..dfb1541103 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -37,7 +37,7 @@
#include
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
#define MBEDTLS_CIPHER_MODE_AEAD
#endif
@@ -45,7 +45,8 @@
#define MBEDTLS_CIPHER_MODE_WITH_PADDING
#endif
-#if defined(MBEDTLS_ARC4_C)
+#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \
+ defined(MBEDTLS_CHACHA20_C)
#define MBEDTLS_CIPHER_MODE_STREAM
#endif
@@ -86,6 +87,8 @@ typedef enum {
MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */
MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */
MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */
+ MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */
+ MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */
} mbedtls_cipher_id_t;
/**
@@ -145,6 +148,31 @@ typedef enum {
MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */
MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */
MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */
+ MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */
+ MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */
+ MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */
+ MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */
+ MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */
+ MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */
+ MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */
+ MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */
+ MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */
+ MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */
+ MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */
+ MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */
+ MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */
+ MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */
+ MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */
+ MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */
+ MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */
+ MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */
+ MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */
+ MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */
+ MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */
+ MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */
+ MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */
+ MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */
} mbedtls_cipher_type_t;
/** Supported cipher modes. */
@@ -153,11 +181,13 @@ typedef enum {
MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */
MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */
MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */
- MBEDTLS_MODE_OFB, /**< The OFB cipher mode - unsupported. */
+ MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */
MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */
MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */
MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */
MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */
+ MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */
+ MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */
} mbedtls_cipher_mode_t;
/** Supported cipher padding types. */
@@ -206,7 +236,8 @@ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
* Cipher information. Allows calling cipher functions
* in a generic way.
*/
-typedef struct {
+typedef struct mbedtls_cipher_info_t
+{
/** Full cipher identifier. For example,
* MBEDTLS_CIPHER_AES_256_CBC.
*/
@@ -247,7 +278,8 @@ typedef struct {
/**
* Generic cipher context.
*/
-typedef struct {
+typedef struct mbedtls_cipher_context_t
+{
/** Information about the associated cipher. */
const mbedtls_cipher_info_t *cipher_info;
@@ -273,7 +305,8 @@ typedef struct {
/** Number of Bytes that have not been processed yet. */
size_t unprocessed_len;
- /** Current IV or NONCE_COUNTER for CTR-mode. */
+ /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number
+ * for XTS-mode. */
unsigned char iv[MBEDTLS_MAX_IV_LENGTH];
/** IV size in Bytes, for ciphers with variable-length IVs. */
@@ -560,11 +593,11 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
*/
int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
/**
* \brief This function adds additional data for AEAD ciphers.
- * Only supported with GCM. Must be called
- * exactly once, after mbedtls_cipher_reset().
+ * Currently supported with GCM and ChaCha20+Poly1305.
+ * Must be called exactly once, after mbedtls_cipher_reset().
*
* \param ctx The generic cipher context.
* \param ad The additional data to use.
@@ -575,7 +608,7 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
*/
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len );
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
/**
* \brief The generic cipher update function. It encrypts or
@@ -633,10 +666,10 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen );
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
/**
* \brief This function writes a tag for AEAD ciphers.
- * Only supported with GCM.
+ * Currently supported with GCM and ChaCha20+Poly1305.
* Must be called after mbedtls_cipher_finish().
*
* \param ctx The generic cipher context.
@@ -651,7 +684,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
/**
* \brief This function checks the tag for AEAD ciphers.
- * Only supported with GCM.
+ * Currently supported with GCM and ChaCha20+Poly1305.
* Must be called after mbedtls_cipher_finish().
*
* \param ctx The generic cipher context.
@@ -663,7 +696,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
*/
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len );
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
/**
* \brief The generic all-in-one encryption/decryption function,
diff --git a/include/mbedtls/cipher_internal.h b/include/mbedtls/cipher_internal.h
index 969ff9ccb8..c6def0bef7 100644
--- a/include/mbedtls/cipher_internal.h
+++ b/include/mbedtls/cipher_internal.h
@@ -64,6 +64,14 @@ struct mbedtls_cipher_base_t
unsigned char *output );
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ /** Encrypt using OFB (Full length) */
+ int (*ofb_func)( void *ctx, size_t length, size_t *iv_off,
+ unsigned char *iv,
+ const unsigned char *input,
+ unsigned char *output );
+#endif
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/** Encrypt using CTR */
int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
@@ -71,6 +79,13 @@ struct mbedtls_cipher_base_t
const unsigned char *input, unsigned char *output );
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ /** Encrypt or decrypt using XTS. */
+ int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length,
+ const unsigned char data_unit[16],
+ const unsigned char *input, unsigned char *output );
+#endif
+
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
/** Encrypt using STREAM */
int (*stream_func)( void *ctx, size_t length,
diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h
index 913c05f8a7..a4fd552565 100644
--- a/include/mbedtls/cmac.h
+++ b/include/mbedtls/cmac.h
@@ -28,7 +28,7 @@
#ifndef MBEDTLS_CMAC_H
#define MBEDTLS_CMAC_H
-#include "mbedtls/cipher.h"
+#include "cipher.h"
#ifdef __cplusplus
extern "C" {
diff --git a/include/mbedtls/compat-1.3.h b/include/mbedtls/compat-1.3.h
index 600a0f154c..213b691403 100644
--- a/include/mbedtls/compat-1.3.h
+++ b/include/mbedtls/compat-1.3.h
@@ -1378,7 +1378,8 @@
#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED
#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED
#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED
-#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN
+#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \
+ ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) )
#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES
#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT
#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 7c9acb2309..28e860b189 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -8,7 +8,7 @@
* memory footprint.
*/
/*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -48,10 +48,14 @@
* Requires support for asm() in compiler.
*
* Used in:
+ * library/aria.c
* library/timing.c
- * library/padlock.c
* include/mbedtls/bn_mul.h
*
+ * Required by:
+ * MBEDTLS_AESNI_C
+ * MBEDTLS_PADLOCK_C
+ *
* Comment to disable the use of assembly code.
*/
#define MBEDTLS_HAVE_ASM
@@ -84,6 +88,28 @@
*/
//#define MBEDTLS_NO_UDBL_DIVISION
+/**
+ * \def MBEDTLS_NO_64BIT_MULTIPLICATION
+ *
+ * The platform lacks support for 32x32 -> 64-bit multiplication.
+ *
+ * Used in:
+ * library/poly1305.c
+ *
+ * Some parts of the library may use multiplication of two unsigned 32-bit
+ * operands with a 64-bit result in order to speed up computations. On some
+ * platforms, this is not available in hardware and has to be implemented in
+ * software, usually in a library provided by the toolchain.
+ *
+ * Sometimes it is not desirable to have to link to that library. This option
+ * removes the dependency of that library on platforms that lack a hardware
+ * 64-bit multiplier by embedding a software implementation in Mbed TLS.
+ *
+ * Note that depending on the compiler, this may decrease performance compared
+ * to using the library function provided by the toolchain.
+ */
+//#define MBEDTLS_NO_64BIT_MULTIPLICATION
+
/**
* \def MBEDTLS_HAVE_SSE2
*
@@ -111,12 +137,21 @@
/**
* \def MBEDTLS_HAVE_TIME_DATE
*
- * System has time.h and time(), gmtime() and the clock is correct.
+ * System has time.h, time(), and an implementation for
+ * mbedtls_platform_gmtime_r() (see below).
* The time needs to be correct (not necesarily very accurate, but at least
* the date should be correct). This is used to verify the validity period of
* X.509 certificates.
*
* Comment if your system does not have a correct clock.
+ *
+ * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that
+ * behaves similarly to the gmtime_r() function from the C standard. Refer to
+ * the documentation for mbedtls_platform_gmtime_r() for more information.
+ *
+ * \note It is possible to configure an implementation for
+ * mbedtls_platform_gmtime_r() at compile-time by using the macro
+ * MBEDTLS_PLATFORM_GMTIME_R_ALT.
*/
#define MBEDTLS_HAVE_TIME_DATE
@@ -271,23 +306,29 @@
*/
//#define MBEDTLS_AES_ALT
//#define MBEDTLS_ARC4_ALT
+//#define MBEDTLS_ARIA_ALT
//#define MBEDTLS_BLOWFISH_ALT
//#define MBEDTLS_CAMELLIA_ALT
//#define MBEDTLS_CCM_ALT
+//#define MBEDTLS_CHACHA20_ALT
+//#define MBEDTLS_CHACHAPOLY_ALT
//#define MBEDTLS_CMAC_ALT
//#define MBEDTLS_DES_ALT
//#define MBEDTLS_DHM_ALT
//#define MBEDTLS_ECJPAKE_ALT
//#define MBEDTLS_GCM_ALT
+//#define MBEDTLS_NIST_KW_ALT
//#define MBEDTLS_MD2_ALT
//#define MBEDTLS_MD4_ALT
//#define MBEDTLS_MD5_ALT
+//#define MBEDTLS_POLY1305_ALT
//#define MBEDTLS_RIPEMD160_ALT
//#define MBEDTLS_RSA_ALT
//#define MBEDTLS_SHA1_ALT
//#define MBEDTLS_SHA256_ALT
//#define MBEDTLS_SHA512_ALT
//#define MBEDTLS_XTEA_ALT
+
/*
* When replacing the elliptic curve module, pleace consider, that it is
* implemented with two .c files:
@@ -509,6 +550,20 @@
*/
#define MBEDTLS_CIPHER_MODE_CTR
+/**
+ * \def MBEDTLS_CIPHER_MODE_OFB
+ *
+ * Enable Output Feedback mode (OFB) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_OFB
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_XTS
+ *
+ * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES.
+ */
+#define MBEDTLS_CIPHER_MODE_XTS
+
/**
* \def MBEDTLS_CIPHER_NULL_CIPHER
*
@@ -622,6 +677,26 @@
*/
#define MBEDTLS_ECP_NIST_OPTIM
+/**
+ * \def MBEDTLS_ECP_RESTARTABLE
+ *
+ * Enable "non-blocking" ECC operations that can return early and be resumed.
+ *
+ * This allows various functions to pause by returning
+ * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module,
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in
+ * order to further progress and eventually complete their operation. This is
+ * controlled through mbedtls_ecp_set_max_ops() which limits the maximum
+ * number of ECC operations a function may perform before pausing; see
+ * mbedtls_ecp_set_max_ops() for more information.
+ *
+ * This is useful in non-threaded environments if you want to avoid blocking
+ * for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
+ *
+ * Uncomment this macro to enable restartable ECC computations.
+ */
+//#define MBEDTLS_ECP_RESTARTABLE
+
/**
* \def MBEDTLS_ECDSA_DETERMINISTIC
*
@@ -1128,6 +1203,17 @@
*/
#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+/**
+ * \def MBEDTLS_SSL_ASYNC_PRIVATE
+ *
+ * Enable asynchronous external private key operations in SSL. This allows
+ * you to configure an SSL connection to call an external cryptographic
+ * module to perform private key operations instead of performing the
+ * operation inside the library.
+ *
+ */
+//#define MBEDTLS_SSL_ASYNC_PRIVATE
+
/**
* \def MBEDTLS_SSL_DEBUG_ALL
*
@@ -1617,7 +1703,7 @@
* Enable the AES block cipher.
*
* Module: library/aes.c
- * Caller: library/ssl_tls.c
+ * Caller: library/cipher.c
* library/pem.c
* library/ctr_drbg.c
*
@@ -1692,7 +1778,7 @@
* Enable the ARCFOUR stream cipher.
*
* Module: library/arc4.c
- * Caller: library/ssl_tls.c
+ * Caller: library/cipher.c
*
* This module enables the following ciphersuites (if other requisites are
* enabled as well):
@@ -1786,7 +1872,7 @@
* Enable the Camellia block cipher.
*
* Module: library/camellia.c
- * Caller: library/ssl_tls.c
+ * Caller: library/cipher.c
*
* This module enables the following ciphersuites (if other requisites are
* enabled as well):
@@ -1835,6 +1921,58 @@
*/
#define MBEDTLS_CAMELLIA_C
+/**
+ * \def MBEDTLS_ARIA_C
+ *
+ * Enable the ARIA block cipher.
+ *
+ * Module: library/aria.c
+ * Caller: library/cipher.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *
+ * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384
+ * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256
+ * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384
+ * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256
+ * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384
+ */
+//#define MBEDTLS_ARIA_C
+
/**
* \def MBEDTLS_CCM_C
*
@@ -1861,6 +1999,26 @@
*/
#define MBEDTLS_CERTS_C
+/**
+ * \def MBEDTLS_CHACHA20_C
+ *
+ * Enable the ChaCha20 stream cipher.
+ *
+ * Module: library/chacha20.c
+ */
+#define MBEDTLS_CHACHA20_C
+
+/**
+ * \def MBEDTLS_CHACHAPOLY_C
+ *
+ * Enable the ChaCha20-Poly1305 AEAD algorithm.
+ *
+ * Module: library/chachapoly.c
+ *
+ * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
+ */
+#define MBEDTLS_CHACHAPOLY_C
+
/**
* \def MBEDTLS_CIPHER_C
*
@@ -1889,14 +2047,16 @@
/**
* \def MBEDTLS_CTR_DRBG_C
*
- * Enable the CTR_DRBG AES-256-based random generator.
+ * Enable the CTR_DRBG AES-based random generator.
+ * The CTR_DRBG generator uses AES-256 by default.
+ * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
*
* Module: library/ctr_drbg.c
* Caller:
*
* Requires: MBEDTLS_AES_C
*
- * This module provides the CTR_DRBG AES-256 random number generator.
+ * This module provides the CTR_DRBG AES random number generator.
*/
#define MBEDTLS_CTR_DRBG_C
@@ -1921,7 +2081,7 @@
*
* Module: library/des.c
* Caller: library/pem.c
- * library/ssl_tls.c
+ * library/cipher.c
*
* This module enables the following ciphersuites (if other requisites are
* enabled as well):
@@ -2091,6 +2251,21 @@
*/
//#define MBEDTLS_HAVEGE_C
+/**
+ * \def MBEDTLS_HKDF_C
+ *
+ * Enable the HKDF algorithm (RFC 5869).
+ *
+ * Module: library/hkdf.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the Hashed Message Authentication Code
+ * (HMAC)-based key derivation function (HKDF).
+ */
+#define MBEDTLS_HKDF_C
+
/**
* \def MBEDTLS_HMAC_DRBG_C
*
@@ -2105,6 +2280,19 @@
*/
#define MBEDTLS_HMAC_DRBG_C
+/**
+ * \def MBEDTLS_NIST_KW_C
+ *
+ * Enable the Key Wrapping mode for 128-bit block ciphers,
+ * as defined in NIST SP 800-38F. Only KW and KWP modes
+ * are supported. At the moment, only AES is approved by NIST.
+ *
+ * Module: library/nist_kw.c
+ *
+ * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C
+ */
+//#define MBEDTLS_NIST_KW_C
+
/**
* \def MBEDTLS_MD_C
*
@@ -2388,6 +2576,16 @@
*/
#define MBEDTLS_PLATFORM_C
+/**
+ * \def MBEDTLS_POLY1305_C
+ *
+ * Enable the Poly1305 MAC algorithm.
+ *
+ * Module: library/poly1305.c
+ * Caller: library/chachapoly.c
+ */
+#define MBEDTLS_POLY1305_C
+
/**
* \def MBEDTLS_RIPEMD160_C
*
@@ -2743,6 +2941,7 @@
//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
/* HMAC_DRBG options */
//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
@@ -2798,7 +2997,68 @@
//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */
/* SSL options */
-//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */
+
+/** \def MBEDTLS_SSL_MAX_CONTENT_LEN
+ *
+ * Maximum fragment length in bytes.
+ *
+ * Determines the size of both the incoming and outgoing TLS I/O buffers.
+ *
+ * Uncommenting MBEDTLS_SSL_IN_CONTENT_LEN and/or MBEDTLS_SSL_OUT_CONTENT_LEN
+ * will override this length by setting maximum incoming and/or outgoing
+ * fragment length, respectively.
+ */
+//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384
+
+/** \def MBEDTLS_SSL_IN_CONTENT_LEN
+ *
+ * Maximum incoming fragment length in bytes.
+ *
+ * Uncomment to set the size of the inward TLS buffer independently of the
+ * outward buffer.
+ */
+//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384
+
+/** \def MBEDTLS_SSL_OUT_CONTENT_LEN
+ *
+ * Maximum outgoing fragment length in bytes.
+ *
+ * Uncomment to set the size of the outward TLS buffer independently of the
+ * inward buffer.
+ *
+ * It is possible to save RAM by setting a smaller outward buffer, while keeping
+ * the default inward 16384 byte buffer to conform to the TLS specification.
+ *
+ * The minimum required outward buffer size is determined by the handshake
+ * protocol's usage. Handshaking will fail if the outward buffer is too small.
+ * The specific size requirement depends on the configured ciphers and any
+ * certificate data which is sent during the handshake.
+ *
+ * For absolute minimum RAM usage, it's best to enable
+ * MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This
+ * reduces both incoming and outgoing buffer sizes. However this is only
+ * guaranteed if the other end of the connection also supports the TLS
+ * max_fragment_len extension. Otherwise the connection may fail.
+ */
+//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384
+
+/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING
+ *
+ * Maximum number of heap-allocated bytes for the purpose of
+ * DTLS handshake message reassembly and future message buffering.
+ *
+ * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN
+ * to account for a reassembled handshake message of maximum size,
+ * together with its reassembly bitmap.
+ *
+ * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default)
+ * should be sufficient for all practical situations as it allows
+ * to reassembly a large handshake message (such as a certificate)
+ * while buffering multiple smaller handshake messages.
+ *
+ */
+//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768
+
//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */
//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
@@ -2872,25 +3132,33 @@
*/
//#define MBEDTLS_PLATFORM_ZEROIZE_ALT
+/**
+ * Uncomment the macro to let Mbed TLS use your alternate implementation of
+ * mbedtls_platform_gmtime_r(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * gmtime() is not a thread-safe function as defined in the C standard. The
+ * library will try to use safer implementations of this function, such as
+ * gmtime_r() when available. However, if Mbed TLS cannot identify the target
+ * system, the implementation of mbedtls_platform_gmtime_r() will default to
+ * using the standard gmtime(). In this case, calls from the library to
+ * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex
+ * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the
+ * library are also guarded with this mutex to avoid race conditions. However,
+ * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will
+ * unconditionally use the implementation for mbedtls_platform_gmtime_r()
+ * supplied at compile time.
+ */
+//#define MBEDTLS_PLATFORM_GMTIME_R_ALT
+
/* \} name SECTION: Customisation configuration options */
-/* Target and application specific configurations */
-//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h"
-
-#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE)
-#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE
-#endif
-
-/*
+/* Target and application specific configurations
+ *
* Allow user to override any previous default.
*
- * Use two macro names for that, as:
- * - with yotta the prefix YOTTA_CFG_ is forced
- * - without yotta is looks weird to have a YOTTA prefix.
*/
-#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE)
-#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE
-#elif defined(MBEDTLS_USER_CONFIG_FILE)
+#if defined(MBEDTLS_USER_CONFIG_FILE)
#include MBEDTLS_USER_CONFIG_FILE
#endif
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index dcbc047924..c91ca58b35 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -8,8 +8,11 @@
* Recommendation for Random Number Generation Using Deterministic Random
* Bit Generators.
*
- * The Mbed TLS implementation of CTR_DRBG uses AES-256 as the underlying
- * block cipher.
+ * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
+ * as the underlying block cipher.
+ *
+ * \warning Using 128-bit keys for CTR_DRBG limits the security of generated
+ * keys and operations that use random values generated to 128-bit security.
*/
/*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
@@ -36,7 +39,7 @@
#include "aes.h"
#if defined(MBEDTLS_THREADING_C)
-#include "mbedtls/threading.h"
+#include "threading.h"
#endif
#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */
@@ -45,7 +48,13 @@
#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */
#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */
-#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */
+
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+#define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size used by the cipher (compile-time choice: 128 bits). */
+#else
+#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher (compile-time choice: 256 bits). */
+#endif
+
#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */
@@ -108,7 +117,7 @@ extern "C" {
/**
* \brief The CTR_DRBG context structure.
*/
-typedef struct
+typedef struct mbedtls_ctr_drbg_context
{
unsigned char counter[16]; /*!< The counter (V). */
int reseed_counter; /*!< The reseed counter. */
diff --git a/include/mbedtls/des.h b/include/mbedtls/des.h
index 6eb7d03bae..91d16b6fb4 100644
--- a/include/mbedtls/des.h
+++ b/include/mbedtls/des.h
@@ -61,7 +61,7 @@ extern "C" {
* security risk. We recommend considering stronger ciphers
* instead.
*/
-typedef struct
+typedef struct mbedtls_des_context
{
uint32_t sk[32]; /*!< DES subkeys */
}
@@ -70,7 +70,7 @@ mbedtls_des_context;
/**
* \brief Triple-DES context structure
*/
-typedef struct
+typedef struct mbedtls_des3_context
{
uint32_t sk[96]; /*!< 3DES subkeys */
}
diff --git a/include/mbedtls/dhm.h b/include/mbedtls/dhm.h
index 75317a8e6d..3e1178940a 100644
--- a/include/mbedtls/dhm.h
+++ b/include/mbedtls/dhm.h
@@ -96,7 +96,7 @@ extern "C" {
/**
* \brief The DHM context structure.
*/
-typedef struct
+typedef struct mbedtls_dhm_context
{
size_t len; /*!< The size of \p P in Bytes. */
mbedtls_mpi P; /*!< The prime modulus. */
diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h
index 5fdf55a88a..27f2ffc6aa 100644
--- a/include/mbedtls/ecdh.h
+++ b/include/mbedtls/ecdh.h
@@ -50,9 +50,13 @@ typedef enum
} mbedtls_ecdh_side;
/**
+ *
+ * \warning Performing multiple operations concurrently on the same
+ * ECDSA context is not supported; objects of this type
+ * should not be shared between multiple threads.
* \brief The ECDH context structure.
*/
-typedef struct
+typedef struct mbedtls_ecdh_context
{
mbedtls_ecp_group grp; /*!< The elliptic curve used. */
mbedtls_mpi d; /*!< The private key. */
@@ -63,6 +67,10 @@ typedef struct
mbedtls_ecp_point Vi; /*!< The blinding value. */
mbedtls_ecp_point Vf; /*!< The unblinding value. */
mbedtls_mpi _d; /*!< The previous \p d. */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ int restart_enabled; /*!< The flag for restartable mode. */
+ mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
+#endif
}
mbedtls_ecdh_context;
@@ -83,9 +91,8 @@ mbedtls_ecdh_context;
* \param p_rng The RNG context.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX or
+ * \return Another \c MBEDTLS_ERR_ECP_XXX or
* \c MBEDTLS_MPI_XXX error code on failure.
- *
*/
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
@@ -112,7 +119,7 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp
* \param p_rng The RNG context.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX or
+ * \return Another \c MBEDTLS_ERR_ECP_XXX or
* \c MBEDTLS_MPI_XXX error code on failure.
*/
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
@@ -155,7 +162,9 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx );
* \param p_rng The RNG context.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
@@ -197,7 +206,7 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
* 0: The key of the peer.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*
*/
int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
@@ -220,7 +229,9 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai
* \param p_rng The RNG context.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
@@ -266,13 +277,31 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
* \param p_rng The RNG context.
*
* \return \c 0 on success.
- * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief This function enables restartable EC computations for this
+ * context. (Default: disabled.)
+ *
+ * \see \c mbedtls_ecp_set_max_ops()
+ *
+ * \note It is not possible to safely disable restartable
+ * computations once enabled, except by free-ing the context,
+ * which cancels possible in-progress operations.
+ *
+ * \param ctx The ECDH context.
+ */
+void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
#ifdef __cplusplus
}
#endif
diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h
index ce1a03d791..4057828d47 100644
--- a/include/mbedtls/ecdsa.h
+++ b/include/mbedtls/ecdsa.h
@@ -55,15 +55,65 @@
/** The maximal size of an ECDSA signature in Bytes. */
#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) )
-/**
- * \brief The ECDSA context structure.
- */
-typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
-
#ifdef __cplusplus
extern "C" {
#endif
+/**
+ * \brief The ECDSA context structure.
+ *
+ * \warning Performing multiple operations concurrently on the same
+ * ECDSA context is not supported; objects of this type
+ * should not be shared between multiple threads.
+ */
+typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief Internal restart context for ecdsa_verify()
+ *
+ * \note Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx;
+
+/**
+ * \brief Internal restart context for ecdsa_sign()
+ *
+ * \note Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx;
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+/**
+ * \brief Internal restart context for ecdsa_sign_det()
+ *
+ * \note Opaque struct, defined in ecdsa.c
+ */
+typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx;
+#endif
+
+/**
+ * \brief General context for resuming ECDSA operations
+ */
+typedef struct
+{
+ mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and
+ shared administrative info */
+ mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */
+ mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */
+#endif
+} mbedtls_ecdsa_restart_ctx;
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_ecdsa_restart_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/**
* \brief This function computes the ECDSA signature of a
* previously-hashed message.
@@ -205,6 +255,40 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+/**
+ * \brief This function computes the ECDSA signature and writes it
+ * to a buffer, in a restartable way.
+ *
+ * \see \c mbedtls_ecdsa_write_signature()
+ *
+ * \note This function is like \c mbedtls_ecdsa_write_signature()
+ * but it can return early and restart according to the limit
+ * set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param ctx The ECDSA context.
+ * \param md_alg The message digest that was used to hash the message.
+ * \param hash The message hash.
+ * \param hlen The length of the hash.
+ * \param sig The buffer that holds the signature.
+ * \param slen The length of the signature written.
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ * \param rs_ctx The restart context (NULL disables restart).
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
+ * \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hlen,
+ unsigned char *sig, size_t *slen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ mbedtls_ecdsa_restart_ctx *rs_ctx );
+
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
@@ -288,6 +372,37 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen );
+/**
+ * \brief This function reads and verifies an ECDSA signature,
+ * in a restartable way.
+ *
+ * \see \c mbedtls_ecdsa_read_signature()
+ *
+ * \note This function is like \c mbedtls_ecdsa_read_signature()
+ * but it can return early and restart according to the limit
+ * set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param ctx The ECDSA context.
+ * \param hash The message hash.
+ * \param hlen The size of the hash.
+ * \param sig The signature to read and verify.
+ * \param slen The size of \p sig.
+ * \param rs_ctx The restart context (NULL disables restart).
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
+ * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
+ * signature in \p sig, but its length is less than \p siglen.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX
+ * error code on failure for any other reason.
+ */
+int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
+ const unsigned char *hash, size_t hlen,
+ const unsigned char *sig, size_t slen,
+ mbedtls_ecdsa_restart_ctx *rs_ctx );
+
/**
* \brief This function generates an ECDSA keypair on the given curve.
*
@@ -332,6 +447,18 @@ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx );
*/
void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Initialize a restart context
+ */
+void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx );
+
+/**
+ * \brief Free the components of a restart context
+ */
+void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
#ifdef __cplusplus
}
#endif
diff --git a/include/mbedtls/ecjpake.h b/include/mbedtls/ecjpake.h
index cc2b316f5e..59d12f080f 100644
--- a/include/mbedtls/ecjpake.h
+++ b/include/mbedtls/ecjpake.h
@@ -68,7 +68,7 @@ typedef enum {
* convetion from the Thread v1.0 spec. Correspondance is indicated in the
* description as a pair C: client name, S: server name
*/
-typedef struct
+typedef struct mbedtls_ecjpake_context
{
const mbedtls_md_info_t *md_info; /**< Hash to use */
mbedtls_ecp_group grp; /**< Elliptic curve */
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index 3a407986dd..5db87524e1 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -50,6 +50,7 @@
#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */
#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */
#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */
+#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */
#ifdef __cplusplus
extern "C" {
@@ -92,7 +93,7 @@ typedef enum
/**
* Curve information, for use by other modules.
*/
-typedef struct
+typedef struct mbedtls_ecp_curve_info
{
mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */
uint16_t tls_id; /*!< The TLS NamedCurve identifier. */
@@ -111,7 +112,7 @@ typedef struct
* Otherwise, \p X and \p Y are its standard (affine)
* coordinates.
*/
-typedef struct
+typedef struct mbedtls_ecp_point
{
mbedtls_mpi X; /*!< The X coordinate of the ECP point. */
mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */
@@ -156,7 +157,7 @@ mbedtls_ecp_point;
* reduction. It must return 0 on success and non-zero on failure.
*
*/
-typedef struct
+typedef struct mbedtls_ecp_group
{
mbedtls_ecp_group_id id; /*!< An internal group identifier. */
mbedtls_mpi P; /*!< The prime modulus of the base field. */
@@ -181,6 +182,70 @@ typedef struct
}
mbedtls_ecp_group;
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief Internal restart context for multiplication
+ *
+ * \note Opaque struct
+ */
+typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx;
+
+/**
+ * \brief Internal restart context for ecp_muladd()
+ *
+ * \note Opaque struct
+ */
+typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx;
+
+/**
+ * \brief General context for resuming ECC operations
+ */
+typedef struct
+{
+ unsigned ops_done; /*!< current ops count */
+ unsigned depth; /*!< call depth (0 = top-level) */
+ mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */
+ mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */
+} mbedtls_ecp_restart_ctx;
+
+/*
+ * Operation counts for restartable functions
+ */
+#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */
+#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */
+#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */
+#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */
+
+/**
+ * \brief Internal; for restartable functions in other modules.
+ * Check and update basic ops budget.
+ *
+ * \param grp Group structure
+ * \param rs_ctx Restart context
+ * \param ops Number of basic ops to do
+ *
+ * \return \c 0 if doing \p ops basic ops is still allowed,
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise.
+ */
+int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_restart_ctx *rs_ctx,
+ unsigned ops );
+
+/* Utility macro for checking and updating ops budget */
+#define MBEDTLS_ECP_BUDGET( ops ) \
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \
+ (unsigned) (ops) ) );
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */
+
+/* We want to declare restartable versions of existing functions anyway */
+typedef void mbedtls_ecp_restart_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/**
* \name SECTION: Module settings
*
@@ -251,7 +316,7 @@ mbedtls_ecp_group;
* \note Members are deliberately in the same order as in the
* ::mbedtls_ecdsa_context structure.
*/
-typedef struct
+typedef struct mbedtls_ecp_keypair
{
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
mbedtls_mpi d; /*!< our secret value */
@@ -270,6 +335,75 @@ mbedtls_ecp_keypair;
*/
#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Set the maximum number of basic operations done in a row.
+ *
+ * If more operations are needed to complete a computation,
+ * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the
+ * function performing the computation. It is then the
+ * caller's responsibility to either call again with the same
+ * parameters until it returns 0 or an error code; or to free
+ * the restart context if the operation is to be aborted.
+ *
+ * It is strictly required that all input parameters and the
+ * restart context be the same on successive calls for the
+ * same operation, but output parameters need not be the
+ * same; they must not be used until the function finally
+ * returns 0.
+ *
+ * This only applies to functions whose documentation
+ * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the
+ * SSL module). For functions that accept a "restart context"
+ * argument, passing NULL disables restart and makes the
+ * function equivalent to the function with the same name
+ * with \c _restartable removed. For functions in the ECDH
+ * module, restart is disabled unless the function accepts
+ * an "ECDH context" argument and
+ * mbedtls_ecdh_enable_restart() was previously called on
+ * that context. For function in the SSL module, restart is
+ * only enabled for specific sides and key exchanges
+ * (currently only for clients and ECDHE-ECDSA).
+ *
+ * \param max_ops Maximum number of basic operations done in a row.
+ * Default: 0 (unlimited).
+ * Lower (non-zero) values mean ECC functions will block for
+ * a lesser maximum amount of time.
+ *
+ * \note A "basic operation" is defined as a rough equivalent of a
+ * multiplication in GF(p) for the NIST P-256 curve.
+ * As an indication, with default settings, a scalar
+ * multiplication (full run of \c mbedtls_ecp_mul()) is:
+ * - about 3300 basic operations for P-256
+ * - about 9400 basic operations for P-384
+ *
+ * \note Very low values are not always respected: sometimes
+ * functions need to block for a minimum number of
+ * operations, and will do so even if max_ops is set to a
+ * lower value. That minimum depends on the curve size, and
+ * can be made lower by decreasing the value of
+ * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the
+ * lowest effective value for various curves and values of
+ * that parameter (w for short):
+ * w=6 w=5 w=4 w=3 w=2
+ * P-256 208 208 160 136 124
+ * P-384 682 416 320 272 248
+ * P-521 1364 832 640 544 496
+ *
+ * \note This setting is currently ignored by Curve25519.
+ */
+void mbedtls_ecp_set_max_ops( unsigned max_ops );
+
+/**
+ * \brief Check if restart is enabled (max_ops != 0)
+ *
+ * \return \c 0 if \c max_ops == 0 (restart disabled)
+ * \return \c 1 otherwise (restart enabled)
+ */
+int mbedtls_ecp_restart_is_enabled( void );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/**
* \brief This function retrieves the information defined in
* mbedtls_ecp_curve_info() for all supported curves in order
@@ -366,6 +500,18 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp );
*/
void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Initialize a restart context
+ */
+void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx );
+
+/**
+ * \brief Free the components of a restart context
+ */
+void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx );
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/**
* \brief This function copies the contents of point \p Q into
* point \p P.
@@ -597,6 +743,36 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+/**
+ * \brief This function performs multiplication of a point by
+ * an integer: \p R = \p m * \p P in a restartable way.
+ *
+ * \see mbedtls_ecp_mul()
+ *
+ * \note This function does the same as \c mbedtls_ecp_mul(), but
+ * it can return early and restart according to the limit set
+ * with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param grp The ECP group.
+ * \param R The destination point.
+ * \param m The integer by which to multiply.
+ * \param P The point to multiply.
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG context.
+ * \param rs_ctx The restart context (NULL disables restart).
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private
+ * key, or \p P is not a valid public key.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx );
+
/**
* \brief This function performs multiplication and addition of two
* points by integers: \p R = \p m * \p P + \p n * \p Q
@@ -623,6 +799,39 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
const mbedtls_mpi *n, const mbedtls_ecp_point *Q );
+/**
+ * \brief This function performs multiplication and addition of two
+ * points by integers: \p R = \p m * \p P + \p n * \p Q in a
+ * restartable way.
+ *
+ * \see \c mbedtls_ecp_muladd()
+ *
+ * \note This function works the same as \c mbedtls_ecp_muladd(),
+ * but it can return early and restart according to the limit
+ * set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param grp The ECP group.
+ * \param R The destination point.
+ * \param m The integer by which to multiply \p P.
+ * \param P The point to multiply by \p m.
+ * \param n The integer by which to multiply \p Q.
+ * \param Q The point to be multiplied by \p n.
+ * \param rs_ctx The restart context (NULL disables restart).
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not
+ * valid private keys, or \p P or \p Q are not valid public
+ * keys.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_ecp_muladd_restartable(
+ mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
+ mbedtls_ecp_restart_ctx *rs_ctx );
+
/**
* \brief This function checks that a point is a valid public key
* on this curve.
@@ -665,6 +874,23 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po
*/
int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d );
+/**
+ * \brief This function generates a private key.
+ *
+ * \param grp The ECP group.
+ * \param d The destination MPI (secret part).
+ * \param f_rng The RNG function.
+ * \param p_rng The RNG parameter.
+ *
+ * \return \c 0 on success.
+ * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code
+ * on failure.
+ */
+int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *d,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng );
+
/**
* \brief This function generates a keypair with a configurable base
* point.
diff --git a/include/mbedtls/entropy.h b/include/mbedtls/entropy.h
index a5cb05a584..ca06dc3c58 100644
--- a/include/mbedtls/entropy.h
+++ b/include/mbedtls/entropy.h
@@ -107,7 +107,7 @@ typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, s
/**
* \brief Entropy source state
*/
-typedef struct
+typedef struct mbedtls_entropy_source_state
{
mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */
void * p_source; /**< The callback data pointer */
@@ -120,7 +120,7 @@ mbedtls_entropy_source_state;
/**
* \brief Entropy context structure
*/
-typedef struct
+typedef struct mbedtls_entropy_context
{
int accumulator_started;
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index 8b4d3a8755..39cd67fdbb 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -4,7 +4,7 @@
* \brief Error to string translation
*/
/*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -53,7 +53,7 @@
* GCM 3 0x0012-0x0014 0x0013-0x0013
* BLOWFISH 3 0x0016-0x0018 0x0017-0x0017
* THREADING 3 0x001A-0x001E
- * AES 4 0x0020-0x0022 0x0023-0x0025
+ * AES 5 0x0020-0x0022 0x0021-0x0025
* CAMELLIA 3 0x0024-0x0026 0x0027-0x0027
* XTEA 2 0x0028-0x0028 0x0029-0x0029
* BASE64 2 0x002A-0x002C
@@ -62,7 +62,8 @@
* DES 2 0x0032-0x0032 0x0033-0x0033
* CTR_DBRG 4 0x0034-0x003A
* ENTROPY 3 0x003C-0x0040 0x003D-0x003F
- * NET 11 0x0042-0x0052 0x0043-0x0045
+ * NET 13 0x0042-0x0052 0x0043-0x0049
+ * ARIA 4 0x0058-0x005E
* ASN1 7 0x0060-0x006C
* CMAC 1 0x007A-0x007A
* PBKDF2 1 0x007C-0x007C
@@ -76,6 +77,10 @@
* SHA1 1 0x0035-0x0035
* SHA256 1 0x0037-0x0037
* SHA512 1 0x0039-0x0039
+ * CHACHA20 3 0x0051-0x0055
+ * POLY1305 3 0x0057-0x005B
+ * CHACHAPOLY 2 0x0054-0x0056
+ * PLATFORM 1 0x0070-0x0070
*
* High-level module nr (3 bits - 0x0...-0x7...)
* Name ID Nr of Errors
@@ -86,11 +91,12 @@
* DHM 3 11
* PK 3 15 (Started from top)
* RSA 4 11
- * ECP 4 9 (Started from top)
+ * ECP 4 10 (Started from top)
* MD 5 5
+ * HKDF 5 1 (Started from top)
* CIPHER 6 8
- * SSL 6 17 (Started from top)
- * SSL 7 31
+ * SSL 6 23 (Started from top)
+ * SSL 7 32
*
* Module dependent error code (5 bits 0x.00.-0x.F8.)
*/
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index bec5577142..d2098eb9f9 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -53,7 +53,8 @@ extern "C" {
/**
* \brief The GCM context structure.
*/
-typedef struct {
+typedef struct mbedtls_gcm_context
+{
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
uint64_t HL[16]; /*!< Precalculated HTable low. */
uint64_t HH[16]; /*!< Precalculated HTable high. */
@@ -113,21 +114,41 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
* the same as input buffer. If the buffers overlap, the output
* buffer must trail at least 8 Bytes behind the input buffer.
*
+ * \warning When this function performs a decryption, it outputs the
+ * authentication tag and does not verify that the data is
+ * authentic. You should use this function to perform encryption
+ * only. For decryption, use mbedtls_gcm_auth_decrypt() instead.
+ *
* \param ctx The GCM context to use for encryption or decryption.
- * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
- * #MBEDTLS_GCM_DECRYPT.
- * \param length The length of the input data. This must be a multiple of
- * 16 except in the last call before mbedtls_gcm_finish().
+ * \param mode The operation to perform:
+ * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption.
+ * The ciphertext is written to \p output and the
+ * authentication tag is written to \p tag.
+ * - #MBEDTLS_GCM_DECRYPT to perform decryption.
+ * The plaintext is written to \p output and the
+ * authentication tag is written to \p tag.
+ * Note that this mode is not recommended, because it does
+ * not verify the authenticity of the data. For this reason,
+ * you should use mbedtls_gcm_auth_decrypt() instead of
+ * calling this function in decryption mode.
+ * \param length The length of the input data, which is equal to the length
+ * of the output data.
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data.
* \param add_len The length of the additional data.
- * \param input The buffer holding the input data.
- * \param output The buffer for holding the output data.
+ * \param input The buffer holding the input data. Its size is \b length.
+ * \param output The buffer for holding the output data. It must have room
+ * for \b length bytes.
* \param tag_len The length of the tag to generate.
* \param tag The buffer for holding the tag.
*
- * \return \c 0 on success.
+ * \return \c 0 if the encryption or decryption was performed
+ * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode,
+ * this does not indicate that the data is authentic.
+ * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid.
+ * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific
+ * error code if the encryption or decryption failed.
*/
int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
int mode,
@@ -150,19 +171,23 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
* must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context.
- * \param length The length of the input data. This must be a multiple
- * of 16 except in the last call before mbedtls_gcm_finish().
+ * \param length The length of the ciphertext to decrypt, which is also
+ * the length of the decrypted plaintext.
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data.
* \param add_len The length of the additional data.
- * \param tag The buffer holding the tag.
- * \param tag_len The length of the tag.
- * \param input The buffer holding the input data.
- * \param output The buffer for holding the output data.
+ * \param tag The buffer holding the tag to verify.
+ * \param tag_len The length of the tag to verify.
+ * \param input The buffer holding the ciphertext. Its size is \b length.
+ * \param output The buffer for holding the decrypted plaintext. It must
+ * have room for \b length bytes.
*
- * \return 0 if successful and authenticated.
- * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
+ * \return \c 0 if successful and authenticated.
+ * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
+ * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid.
+ * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific
+ * error code if the decryption failed.
*/
int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
size_t length,
diff --git a/include/mbedtls/havege.h b/include/mbedtls/havege.h
index d4cb3ed38d..57e8c40943 100644
--- a/include/mbedtls/havege.h
+++ b/include/mbedtls/havege.h
@@ -35,7 +35,7 @@ extern "C" {
/**
* \brief HAVEGE state structure
*/
-typedef struct
+typedef struct mbedtls_havege_state
{
int PT1, PT2, offset[2];
int pool[MBEDTLS_HAVEGE_COLLECT_SIZE];
diff --git a/include/mbedtls/hkdf.h b/include/mbedtls/hkdf.h
new file mode 100644
index 0000000000..e6ed7cde97
--- /dev/null
+++ b/include/mbedtls/hkdf.h
@@ -0,0 +1,135 @@
+/**
+ * \file hkdf.h
+ *
+ * \brief This file contains the HKDF interface.
+ *
+ * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is
+ * specified by RFC 5869.
+ */
+/*
+ * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_HKDF_H
+#define MBEDTLS_HKDF_H
+
+#include "md.h"
+
+/**
+ * \name HKDF Error codes
+ * \{
+ */
+#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */
+/* \} name */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function
+ * (HKDF).
+ *
+ * \param md A hash function; md.size denotes the length of the hash
+ * function output in bytes.
+ * \param salt An optional salt value (a non-secret random value);
+ * if the salt is not provided, a string of all zeros of
+ * md.size length is used as the salt.
+ * \param salt_len The length in bytes of the optional \p salt.
+ * \param ikm The input keying material.
+ * \param ikm_len The length in bytes of \p ikm.
+ * \param info An optional context and application specific information
+ * string. This can be a zero-length string.
+ * \param info_len The length of \p info in bytes.
+ * \param okm The output keying material of \p okm_len bytes.
+ * \param okm_len The length of the output keying material in bytes. This
+ * must be less than or equal to 255 * md.size bytes.
+ *
+ * \return 0 on success.
+ * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
+ * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
+ * MD layer.
+ */
+int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
+ size_t salt_len, const unsigned char *ikm, size_t ikm_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len );
+
+/**
+ * \brief Take the input keying material \p ikm and extract from it a
+ * fixed-length pseudorandom key \p prk.
+ *
+ * \warning This function should only be used if the security of it has been
+ * studied and established in that particular context (eg. TLS 1.3
+ * key schedule). For standard HKDF security guarantees use
+ * \c mbedtls_hkdf instead.
+ *
+ * \param md A hash function; md.size denotes the length of the
+ * hash function output in bytes.
+ * \param salt An optional salt value (a non-secret random value);
+ * if the salt is not provided, a string of all zeros
+ * of md.size length is used as the salt.
+ * \param salt_len The length in bytes of the optional \p salt.
+ * \param ikm The input keying material.
+ * \param ikm_len The length in bytes of \p ikm.
+ * \param[out] prk A pseudorandom key of at least md.size bytes.
+ *
+ * \return 0 on success.
+ * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
+ * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
+ * MD layer.
+ */
+int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *ikm, size_t ikm_len,
+ unsigned char *prk );
+
+/**
+ * \brief Expand the supplied \p prk into several additional pseudorandom
+ * keys, which is the output of the HKDF.
+ *
+ * \warning This function should only be used if the security of it has been
+ * studied and established in that particular context (eg. TLS 1.3
+ * key schedule). For standard HKDF security guarantees use
+ * \c mbedtls_hkdf instead.
+ *
+ * \param md A hash function; md.size denotes the length of the hash
+ * function output in bytes.
+ * \param prk A pseudorandom key of at least md.size bytes. \p prk is
+ * usually the output from the HKDF extract step.
+ * \param prk_len The length in bytes of \p prk.
+ * \param info An optional context and application specific information
+ * string. This can be a zero-length string.
+ * \param info_len The length of \p info in bytes.
+ * \param okm The output keying material of \p okm_len bytes.
+ * \param okm_len The length of the output keying material in bytes. This
+ * must be less than or equal to 255 * md.size bytes.
+ *
+ * \return 0 on success.
+ * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
+ * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
+ * MD layer.
+ */
+int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
+ size_t prk_len, const unsigned char *info,
+ size_t info_len, unsigned char *okm, size_t okm_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* hkdf.h */
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index e0821cf788..3bc675ec7c 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -27,7 +27,7 @@
#include "md.h"
#if defined(MBEDTLS_THREADING_C)
-#include "mbedtls/threading.h"
+#include "threading.h"
#endif
/*
@@ -74,7 +74,7 @@ extern "C" {
/**
* HMAC_DRBG context.
*/
-typedef struct
+typedef struct mbedtls_hmac_drbg_context
{
/* Working state: the key K is not stored explicitely,
* but is implied by the HMAC context */
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index 6b6f5c53dd..bf29524983 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -80,7 +80,8 @@ typedef struct mbedtls_md_info_t mbedtls_md_info_t;
/**
* The generic message-digest context.
*/
-typedef struct {
+typedef struct mbedtls_md_context_t
+{
/** Information about the associated message digest. */
const mbedtls_md_info_t *md_info;
diff --git a/include/mbedtls/md2.h b/include/mbedtls/md2.h
index 08e75b247b..a46bddb74b 100644
--- a/include/mbedtls/md2.h
+++ b/include/mbedtls/md2.h
@@ -55,7 +55,7 @@ extern "C" {
* stronger message digests instead.
*
*/
-typedef struct
+typedef struct mbedtls_md2_context
{
unsigned char cksum[16]; /*!< checksum of the data block */
unsigned char state[48]; /*!< intermediate digest state */
diff --git a/include/mbedtls/md4.h b/include/mbedtls/md4.h
index 8ee4e5cabf..1672e9074e 100644
--- a/include/mbedtls/md4.h
+++ b/include/mbedtls/md4.h
@@ -56,7 +56,7 @@ extern "C" {
* stronger message digests instead.
*
*/
-typedef struct
+typedef struct mbedtls_md4_context
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
diff --git a/include/mbedtls/md5.h b/include/mbedtls/md5.h
index 43ead4b747..4c9509010b 100644
--- a/include/mbedtls/md5.h
+++ b/include/mbedtls/md5.h
@@ -55,7 +55,7 @@ extern "C" {
* stronger message digests instead.
*
*/
-typedef struct
+typedef struct mbedtls_md5_context
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
diff --git a/include/mbedtls/net.h b/include/mbedtls/net.h
index 28ae8217c0..6c13b53fb9 100644
--- a/include/mbedtls/net.h
+++ b/include/mbedtls/net.h
@@ -1,7 +1,7 @@
/**
* \file net.h
*
- * \brief Deprecated header file that includes mbedtls/net_sockets.h
+ * \brief Deprecated header file that includes net_sockets.h
*
* \deprecated Superseded by mbedtls/net_sockets.h
*/
@@ -25,7 +25,7 @@
*/
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-#include "mbedtls/net_sockets.h"
+#include "net_sockets.h"
#if defined(MBEDTLS_DEPRECATED_WARNING)
#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h"
#endif /* MBEDTLS_DEPRECATED_WARNING */
diff --git a/include/mbedtls/net_sockets.h b/include/mbedtls/net_sockets.h
index 0f9b31ebcb..4c7ef00fe6 100644
--- a/include/mbedtls/net_sockets.h
+++ b/include/mbedtls/net_sockets.h
@@ -1,7 +1,23 @@
/**
* \file net_sockets.h
*
- * \brief Network communication functions
+ * \brief Network sockets abstraction layer to integrate Mbed TLS into a
+ * BSD-style sockets API.
+ *
+ * The network sockets module provides an example integration of the
+ * Mbed TLS library into a BSD sockets implementation. The module is
+ * intended to be an example of how Mbed TLS can be integrated into a
+ * networking stack, as well as to be Mbed TLS's network integration
+ * for its supported platforms.
+ *
+ * The module is intended only to be used with the Mbed TLS library and
+ * is not intended to be used by third party application software
+ * directly.
+ *
+ * The supported platforms are as follows:
+ * * Microsoft Windows and Windows CE
+ * * POSIX/Unix platforms including Linux, OS X
+ *
*/
/*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@@ -68,7 +84,7 @@ extern "C" {
* (eg two file descriptors for combined IPv4 + IPv6 support, or additional
* structures for hand-made UDP demultiplexing).
*/
-typedef struct
+typedef struct mbedtls_net_context
{
int fd; /**< The underlying file descriptor */
}
diff --git a/include/mbedtls/nist_kw.h b/include/mbedtls/nist_kw.h
new file mode 100644
index 0000000000..5a0f656a8f
--- /dev/null
+++ b/include/mbedtls/nist_kw.h
@@ -0,0 +1,178 @@
+/**
+ * \file nist_kw.h
+ *
+ * \brief This file provides an API for key wrapping (KW) and key wrapping with
+ * padding (KWP) as defined in NIST SP 800-38F.
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
+ *
+ * Key wrapping specifies a deterministic authenticated-encryption mode
+ * of operation, according to NIST SP 800-38F: Recommendation for
+ * Block Cipher Modes of Operation: Methods for Key Wrapping. Its
+ * purpose is to protect cryptographic keys.
+ *
+ * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP.
+ * https://tools.ietf.org/html/rfc3394
+ * https://tools.ietf.org/html/rfc5649
+ *
+ */
+/*
+ * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_NIST_KW_H
+#define MBEDTLS_NIST_KW_H
+
+#include "cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+ MBEDTLS_KW_MODE_KW = 0,
+ MBEDTLS_KW_MODE_KWP = 1
+} mbedtls_nist_kw_mode_t;
+
+#if !defined(MBEDTLS_NIST_KW_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief The key wrapping context-type definition. The key wrapping context is passed
+ * to the APIs called.
+ *
+ * \note The definition of this type may change in future library versions.
+ * Don't make any assumptions on this context!
+ */
+typedef struct {
+ mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
+} mbedtls_nist_kw_context;
+
+#else /* MBEDTLS_NIST_key wrapping_ALT */
+#include "nist_kw_alt.h"
+#endif /* MBEDTLS_NIST_KW_ALT */
+
+/**
+ * \brief This function initializes the specified key wrapping context
+ * to make references valid and prepare the context
+ * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free().
+ *
+ * \param ctx The key wrapping context to initialize.
+ *
+ */
+void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx );
+
+/**
+ * \brief This function initializes the key wrapping context set in the
+ * \p ctx parameter and sets the encryption key.
+ *
+ * \param ctx The key wrapping context.
+ * \param cipher The 128-bit block cipher to use. Only AES is supported.
+ * \param key The Key Encryption Key (KEK).
+ * \param keybits The KEK size in bits. This must be acceptable by the cipher.
+ * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping
+ *
+ * \return \c 0 on success.
+ * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input.
+ * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers
+ * which are not supported.
+ * \return cipher-specific error code on failure of the underlying cipher.
+ */
+int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
+ mbedtls_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits,
+ const int is_wrap );
+
+/**
+ * \brief This function releases and clears the specified key wrapping context
+ * and underlying cipher sub-context.
+ *
+ * \param ctx The key wrapping context to clear.
+ */
+void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx );
+
+/**
+ * \brief This function encrypts a buffer using key wrapping.
+ *
+ * \param ctx The key wrapping context to use for encryption.
+ * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)
+ * \param input The buffer holding the input data.
+ * \param in_len The length of the input data in Bytes.
+ * The input uses units of 8 Bytes called semiblocks.
+ *
For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
+ *
For KWP mode: any length between 1 and 2^32-1 inclusive.
+ * \param[out] output The buffer holding the output data.
+ *
For KW mode: Must be at least 8 bytes larger than \p in_len.
+ *
For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of
+ * 8 bytes for KWP (15 bytes at most).
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure.
+ * \param[in] out_size The capacity of the output buffer.
+ *
+ * \return \c 0 on success.
+ * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
+ * \return cipher-specific error code on failure of the underlying cipher.
+ */
+int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,
+ const unsigned char *input, size_t in_len,
+ unsigned char *output, size_t* out_len, size_t out_size );
+
+/**
+ * \brief This function decrypts a buffer using key wrapping.
+ *
+ * \param ctx The key wrapping context to use for decryption.
+ * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)
+ * \param input The buffer holding the input data.
+ * \param in_len The length of the input data in Bytes.
+ * The input uses units of 8 Bytes called semiblocks.
+ * The input must be a multiple of semiblocks.
+ *
For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
+ *
For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
+ * \param[out] output The buffer holding the output data.
+ * The output buffer's minimal length is 8 bytes shorter than \p in_len.
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure.
+ * For KWP mode, the length could be up to 15 bytes shorter than \p in_len,
+ * depending on how much padding was added to the data.
+ * \param[in] out_size The capacity of the output buffer.
+ *
+ * \return \c 0 on success.
+ * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
+ * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext.
+ * \return cipher-specific error code on failure of the underlying cipher.
+ */
+int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,
+ const unsigned char *input, size_t in_len,
+ unsigned char *output, size_t* out_len, size_t out_size);
+
+
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+/**
+ * \brief The key wrapping checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedtls_nist_kw_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_NIST_KW_H */
diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index 408645ece7..6fbd018aaa 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -97,6 +97,8 @@
/* ISO arc for standard certificate and CRL extensions */
#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */
+#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */
+
/**
* Private Internet Extensions
* { iso(1) identified-organization(3) dod(6) internet(1)
@@ -219,12 +221,12 @@
#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */
#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */
-#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */
-#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
+#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */
+#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
-#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */
+#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */
-#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
+#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
@@ -241,7 +243,20 @@
*/
#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */
#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */
+#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */
+/*
+ * Key Wrapping algorithms
+ */
+/*
+ * RFC 5649
+ */
+#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */
+#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */
+#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */
+#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */
+#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */
+#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */
/*
* PKCS#5 OIDs
*/
@@ -388,7 +403,8 @@ extern "C" {
/**
* \brief Base OID descriptor structure
*/
-typedef struct {
+typedef struct mbedtls_oid_descriptor_t
+{
const char *asn1; /*!< OID ASN.1 representation */
size_t asn1_len; /*!< length of asn1 */
const char *name; /*!< official name (e.g. from RFC) */
diff --git a/include/mbedtls/pem.h b/include/mbedtls/pem.h
index 2cf4c0a709..fa82f7bdbd 100644
--- a/include/mbedtls/pem.h
+++ b/include/mbedtls/pem.h
@@ -51,7 +51,7 @@ extern "C" {
/**
* \brief PEM context structure
*/
-typedef struct
+typedef struct mbedtls_pem_context
{
unsigned char *buf; /*!< buffer for decoded data */
size_t buflen; /*!< length of the buffer */
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index ee06b2fd20..9ec33da057 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -87,7 +87,7 @@ typedef enum {
* \brief Options for RSASSA-PSS signature verification.
* See \c mbedtls_rsa_rsassa_pss_verify_ext()
*/
-typedef struct
+typedef struct mbedtls_pk_rsassa_pss_options
{
mbedtls_md_type_t mgf1_hash_id;
int expected_salt_len;
@@ -107,7 +107,7 @@ typedef enum
/**
* \brief Item to send to the debug module
*/
-typedef struct
+typedef struct mbedtls_pk_debug_item
{
mbedtls_pk_debug_type type;
const char *name;
@@ -125,12 +125,26 @@ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t;
/**
* \brief Public key container
*/
-typedef struct
+typedef struct mbedtls_pk_context
{
- const mbedtls_pk_info_t * pk_info; /**< Public key informations */
+ const mbedtls_pk_info_t * pk_info; /**< Public key information */
void * pk_ctx; /**< Underlying public key context */
} mbedtls_pk_context;
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Context for resuming operations
+ */
+typedef struct
+{
+ const mbedtls_pk_info_t * pk_info; /**< Public key information */
+ void * rs_ctx; /**< Underlying restart context */
+} mbedtls_pk_restart_ctx;
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_pk_restart_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
#if defined(MBEDTLS_RSA_C)
/**
* Quick access to an RSA context inside a PK context.
@@ -190,6 +204,18 @@ void mbedtls_pk_init( mbedtls_pk_context *ctx );
*/
void mbedtls_pk_free( mbedtls_pk_context *ctx );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Initialize a restart context
+ */
+void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx );
+
+/**
+ * \brief Free the components of a restart context
+ */
+void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
/**
* \brief Initialize a PK context with the information given
* and allocates the type-specific PK subcontext.
@@ -286,6 +312,32 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len );
+/**
+ * \brief Restartable version of \c mbedtls_pk_verify()
+ *
+ * \note Performs the same job as \c mbedtls_pk_verify(), but can
+ * return early and restart according to the limit set with
+ * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
+ * operations. For RSA, same as \c mbedtls_pk_verify().
+ *
+ * \param ctx PK context to use
+ * \param md_alg Hash algorithm used (see notes)
+ * \param hash Hash of the message to sign
+ * \param hash_len Hash length or 0 (see notes)
+ * \param sig Signature to verify
+ * \param sig_len Signature length
+ * \param rs_ctx Restart context (NULL to disable restart)
+ *
+ * \return See \c mbedtls_pk_verify(), or
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ mbedtls_pk_restart_ctx *rs_ctx );
+
/**
* \brief Verify signature, with options.
* (Includes verification of the padding depending on type.)
@@ -349,6 +401,35 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+/**
+ * \brief Restartable version of \c mbedtls_pk_sign()
+ *
+ * \note Performs the same job as \c mbedtls_pk_sign(), but can
+ * return early and restart according to the limit set with
+ * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
+ * operations. For RSA, same as \c mbedtls_pk_sign().
+ *
+ * \param ctx PK context to use - must hold a private key
+ * \param md_alg Hash algorithm used (see notes)
+ * \param hash Hash of the message to sign
+ * \param hash_len Hash length or 0 (see notes)
+ * \param sig Place to write the signature
+ * \param sig_len Number of bytes written
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ * \param rs_ctx Restart context (NULL to disable restart)
+ *
+ * \return See \c mbedtls_pk_sign(), or
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_pk_restart_ctx *rs_ctx );
+
/**
* \brief Decrypt message (including padding if relevant).
*
diff --git a/include/mbedtls/pk_internal.h b/include/mbedtls/pk_internal.h
index 3dae0fc5b2..48b7a5f7bf 100644
--- a/include/mbedtls/pk_internal.h
+++ b/include/mbedtls/pk_internal.h
@@ -59,6 +59,21 @@ struct mbedtls_pk_info_t
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /** Verify signature (restartable) */
+ int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ void *rs_ctx );
+
+ /** Make signature (restartable) */
+ int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng, void *rs_ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
/** Decrypt message */
int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize,
@@ -80,6 +95,14 @@ struct mbedtls_pk_info_t
/** Free the given context */
void (*ctx_free_func)( void *ctx );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /** Allocate the restart context */
+ void * (*rs_alloc_func)( void );
+
+ /** Free the restart context */
+ void (*rs_free_func)( void *rs_ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
/** Interface with the debug module */
void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items );
diff --git a/include/mbedtls/pkcs11.h b/include/mbedtls/pkcs11.h
index bf65c55a79..02427ddc1e 100644
--- a/include/mbedtls/pkcs11.h
+++ b/include/mbedtls/pkcs11.h
@@ -50,7 +50,8 @@ extern "C" {
/**
* Context for PKCS #11 private keys.
*/
-typedef struct {
+typedef struct mbedtls_pkcs11_context
+{
pkcs11h_certificate_t pkcs11h_cert;
int len;
} mbedtls_pkcs11_context;
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index bba770911e..5cd143ce53 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -40,9 +40,11 @@
#endif
#if defined(MBEDTLS_HAVE_TIME)
-#include "mbedtls/platform_time.h"
+#include "platform_time.h"
#endif
+#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -121,8 +123,8 @@ extern "C" {
#else
/* For size_t */
#include
-extern void * (*mbedtls_calloc)( size_t n, size_t size );
-extern void (*mbedtls_free)( void *ptr );
+extern void *mbedtls_calloc( size_t n, size_t size );
+extern void mbedtls_free( void *ptr );
/**
* \brief This function dynamically sets the memory-management
@@ -315,7 +317,8 @@ int mbedtls_platform_set_nv_seed(
* \note This structure may be used to assist platform-specific
* setup or teardown operations.
*/
-typedef struct {
+typedef struct mbedtls_platform_context
+{
char dummy; /**< A placeholder member, as empty structs are not portable. */
}
mbedtls_platform_context;
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index 84f0732eeb..164a1a05f9 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -25,7 +25,17 @@
#ifndef MBEDTLS_PLATFORM_UTIL_H
#define MBEDTLS_PLATFORM_UTIL_H
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
#include
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+#include "mbedtls/platform_time.h"
+#include
+#endif /* MBEDTLS_HAVE_TIME_DATE */
#ifdef __cplusplus
extern "C" {
@@ -55,6 +65,37 @@ extern "C" {
*/
void mbedtls_platform_zeroize( void *buf, size_t len );
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+/**
+ * \brief Platform-specific implementation of gmtime_r()
+ *
+ * The function is a thread-safe abstraction that behaves
+ * similarly to the gmtime_r() function from Unix/POSIX.
+ *
+ * Mbed TLS will try to identify the underlying platform and
+ * make use of an appropriate underlying implementation (e.g.
+ * gmtime_r() for POSIX and gmtime_s() for Windows). If this is
+ * not possible, then gmtime() will be used. In this case, calls
+ * from the library to gmtime() will be guarded by the mutex
+ * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is
+ * enabled. It is recommended that calls from outside the library
+ * are also guarded by this mutex.
+ *
+ * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will
+ * unconditionally use the alternative implementation for
+ * mbedtls_platform_gmtime_r() supplied by the user at compile time.
+ *
+ * \param tt Pointer to an object containing time (in seconds) since the
+ * epoch to be converted
+ * \param tm_buf Pointer to an object where the results will be stored
+ *
+ * \return Pointer to an object of type struct tm on success, otherwise
+ * NULL
+ */
+struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
+ struct tm *tm_buf );
+#endif /* MBEDTLS_HAVE_TIME_DATE */
+
#ifdef __cplusplus
}
#endif
diff --git a/include/mbedtls/poly1305.h b/include/mbedtls/poly1305.h
new file mode 100644
index 0000000000..c490cdf2bd
--- /dev/null
+++ b/include/mbedtls/poly1305.h
@@ -0,0 +1,181 @@
+/**
+ * \file poly1305.h
+ *
+ * \brief This file contains Poly1305 definitions and functions.
+ *
+ * Poly1305 is a one-time message authenticator that can be used to
+ * authenticate messages. Poly1305-AES was created by Daniel
+ * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic
+ * Poly1305 algorithm (not tied to AES) was also standardized in RFC
+ * 7539.
+ *
+ * \author Daniel King
+ */
+
+/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_POLY1305_H
+#define MBEDTLS_POLY1305_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include
+#include
+
+#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */
+#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */
+#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDTLS_POLY1305_ALT)
+
+typedef struct mbedtls_poly1305_context
+{
+ uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */
+ uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */
+ uint32_t acc[5]; /** The accumulator number. */
+ uint8_t queue[16]; /** The current partial block of data. */
+ size_t queue_len; /** The number of bytes stored in 'queue'. */
+}
+mbedtls_poly1305_context;
+
+#else /* MBEDTLS_POLY1305_ALT */
+#include "poly1305_alt.h"
+#endif /* MBEDTLS_POLY1305_ALT */
+
+/**
+ * \brief This function initializes the specified Poly1305 context.
+ *
+ * It must be the first API called before using
+ * the context.
+ *
+ * It is usually followed by a call to
+ * \c mbedtls_poly1305_starts(), then one or more calls to
+ * \c mbedtls_poly1305_update(), then one call to
+ * \c mbedtls_poly1305_finish(), then finally
+ * \c mbedtls_poly1305_free().
+ *
+ * \param ctx The Poly1305 context to initialize.
+ */
+void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx );
+
+/**
+ * \brief This function releases and clears the specified Poly1305 context.
+ *
+ * \param ctx The Poly1305 context to clear.
+ */
+void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx );
+
+/**
+ * \brief This function sets the one-time authentication key.
+ *
+ * \warning The key must be unique and unpredictable for each
+ * invocation of Poly1305.
+ *
+ * \param ctx The Poly1305 context to which the key should be bound.
+ * \param key The buffer containing the 256-bit key.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if ctx or key are NULL.
+ */
+int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
+ const unsigned char key[32] );
+
+/**
+ * \brief This functions feeds an input buffer into an ongoing
+ * Poly1305 computation.
+ *
+ * It is called between \c mbedtls_cipher_poly1305_starts() and
+ * \c mbedtls_cipher_poly1305_finish().
+ * It can be called repeatedly to process a stream of data.
+ *
+ * \param ctx The Poly1305 context to use for the Poly1305 operation.
+ * \param ilen The length of the input data (in bytes). Any value is accepted.
+ * \param input The buffer holding the input data.
+ * This pointer can be NULL if ilen == 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if ctx or input are NULL.
+ */
+int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
+ const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief This function generates the Poly1305 Message
+ * Authentication Code (MAC).
+ *
+ * \param ctx The Poly1305 context to use for the Poly1305 operation.
+ * \param mac The buffer to where the MAC is written. Must be big enough
+ * to hold the 16-byte MAC.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if ctx or mac are NULL.
+ */
+int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
+ unsigned char mac[16] );
+
+/**
+ * \brief This function calculates the Poly1305 MAC of the input
+ * buffer with the provided key.
+ *
+ * \warning The key must be unique and unpredictable for each
+ * invocation of Poly1305.
+ *
+ * \param key The buffer containing the 256-bit key.
+ * \param ilen The length of the input data (in bytes). Any value is accepted.
+ * \param input The buffer holding the input data.
+ * This pointer can be NULL if ilen == 0.
+ * \param mac The buffer to where the MAC is written. Must be big enough
+ * to hold the 16-byte MAC.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ * if key, input, or mac are NULL.
+ */
+int mbedtls_poly1305_mac( const unsigned char key[32],
+ const unsigned char *input,
+ size_t ilen,
+ unsigned char mac[16] );
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief The Poly1305 checkup routine.
+ *
+ * \return \c 0 on success.
+ * \return \c 1 on failure.
+ */
+int mbedtls_poly1305_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_POLY1305_H */
diff --git a/include/mbedtls/ripemd160.h b/include/mbedtls/ripemd160.h
index a0dac0c360..0c8e568b9e 100644
--- a/include/mbedtls/ripemd160.h
+++ b/include/mbedtls/ripemd160.h
@@ -46,7 +46,7 @@ extern "C" {
/**
* \brief RIPEMD-160 context structure
*/
-typedef struct
+typedef struct mbedtls_ripemd160_context
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index 19eb2ee74c..6eea5af2f0 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -92,7 +92,7 @@ extern "C" {
* is deprecated. All manipulation should instead be done through
* the public interface functions.
*/
-typedef struct
+typedef struct mbedtls_rsa_context
{
int ver; /*!< Always 0.*/
size_t len; /*!< The size of \p N in Bytes. */
diff --git a/include/mbedtls/sha1.h b/include/mbedtls/sha1.h
index 65a124c94b..7a19da0a48 100644
--- a/include/mbedtls/sha1.h
+++ b/include/mbedtls/sha1.h
@@ -58,7 +58,7 @@ extern "C" {
* stronger message digests instead.
*
*/
-typedef struct
+typedef struct mbedtls_sha1_context
{
uint32_t total[2]; /*!< The number of Bytes processed. */
uint32_t state[5]; /*!< The intermediate digest state. */
diff --git a/include/mbedtls/sha256.h b/include/mbedtls/sha256.h
index adf31a82ed..33aff28314 100644
--- a/include/mbedtls/sha256.h
+++ b/include/mbedtls/sha256.h
@@ -53,7 +53,7 @@ extern "C" {
* checksum calculations. The choice between these two is
* made in the call to mbedtls_sha256_starts_ret().
*/
-typedef struct
+typedef struct mbedtls_sha256_context
{
uint32_t total[2]; /*!< The number of Bytes processed. */
uint32_t state[8]; /*!< The intermediate digest state. */
diff --git a/include/mbedtls/sha512.h b/include/mbedtls/sha512.h
index 5bb83f43bd..0145890424 100644
--- a/include/mbedtls/sha512.h
+++ b/include/mbedtls/sha512.h
@@ -52,7 +52,7 @@ extern "C" {
* checksum calculations. The choice between these two is
* made in the call to mbedtls_sha512_starts_ret().
*/
-typedef struct
+typedef struct mbedtls_sha512_context
{
uint64_t total[2]; /*!< The number of Bytes processed. */
uint64_t state[8]; /*!< The intermediate digest state. */
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index f91066d570..e8f664a787 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -62,7 +62,7 @@
#endif
#if defined(MBEDTLS_HAVE_TIME)
-#include "mbedtls/platform_time.h"
+#include "platform_time.h"
#endif
/*
@@ -120,6 +120,9 @@
#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */
#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */
#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */
+#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */
+#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */
+#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */
/*
* Various constants
@@ -219,7 +222,7 @@
#endif
/*
- * Maxium fragment length in bytes,
+ * Maximum fragment length in bytes,
* determines the size of each of the two internal I/O buffers.
*
* Note: the RFC defines the default size of SSL / TLS messages. If you
@@ -233,6 +236,22 @@
#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */
#endif
+#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN)
+#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
+#endif
+
+#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN)
+#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
+#endif
+
+/*
+ * Maximum number of heap-allocated bytes for the purpose of
+ * DTLS handshake message reassembly and future message buffering.
+ */
+#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING)
+#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768
+#endif
+
/* \} name SECTION: Module settings */
/*
@@ -536,7 +555,6 @@ typedef void mbedtls_ssl_set_timer_t( void * ctx,
*/
typedef int mbedtls_ssl_get_timer_t( void * ctx );
-
/* Defined below */
typedef struct mbedtls_ssl_session mbedtls_ssl_session;
typedef struct mbedtls_ssl_context mbedtls_ssl_context;
@@ -553,6 +571,218 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert;
typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item;
#endif
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+/**
+ * \brief Callback type: start external signature operation.
+ *
+ * This callback is called during an SSL handshake to start
+ * a signature decryption operation using an
+ * external processor. The parameter \p cert contains
+ * the public key; it is up to the callback function to
+ * determine how to access the associated private key.
+ *
+ * This function typically sends or enqueues a request, and
+ * does not wait for the operation to complete. This allows
+ * the handshake step to be non-blocking.
+ *
+ * The parameters \p ssl and \p cert are guaranteed to remain
+ * valid throughout the handshake. On the other hand, this
+ * function must save the contents of \p hash if the value
+ * is needed for later processing, because the \p hash buffer
+ * is no longer valid after this function returns.
+ *
+ * This function may call mbedtls_ssl_set_async_operation_data()
+ * to store an operation context for later retrieval
+ * by the resume or cancel callback.
+ *
+ * \note For RSA signatures, this function must produce output
+ * that is consistent with PKCS#1 v1.5 in the same way as
+ * mbedtls_rsa_pkcs1_sign(). Before the private key operation,
+ * apply the padding steps described in RFC 8017, section 9.2
+ * "EMSA-PKCS1-v1_5" as follows.
+ * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5
+ * encoding, treating \p hash as the DigestInfo to be
+ * padded. In other words, apply EMSA-PKCS1-v1_5 starting
+ * from step 3, with `T = hash` and `tLen = hash_len`.
+ * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5
+ * encoding, treating \p hash as the hash to be encoded and
+ * padded. In other words, apply EMSA-PKCS1-v1_5 starting
+ * from step 2, with `digestAlgorithm` obtained by calling
+ * mbedtls_oid_get_oid_by_md() on \p md_alg.
+ *
+ * \note For ECDSA signatures, the output format is the DER encoding
+ * `Ecdsa-Sig-Value` defined in
+ * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4).
+ *
+ * \param ssl The SSL connection instance. It should not be
+ * modified other than via
+ * mbedtls_ssl_set_async_operation_data().
+ * \param cert Certificate containing the public key.
+ * In simple cases, this is one of the pointers passed to
+ * mbedtls_ssl_conf_own_cert() when configuring the SSL
+ * connection. However, if other callbacks are used, this
+ * property may not hold. For example, if an SNI callback
+ * is registered with mbedtls_ssl_conf_sni(), then
+ * this callback determines what certificate is used.
+ * \param md_alg Hash algorithm.
+ * \param hash Buffer containing the hash. This buffer is
+ * no longer valid when the function returns.
+ * \param hash_len Size of the \c hash buffer in bytes.
+ *
+ * \return 0 if the operation was started successfully and the SSL
+ * stack should call the resume callback immediately.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
+ * was started successfully and the SSL stack should return
+ * immediately without calling the resume callback yet.
+ * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external
+ * processor does not support this key. The SSL stack will
+ * use the private key object instead.
+ * \return Any other error indicates a fatal failure and is
+ * propagated up the call chain. The callback should
+ * use \c MBEDTLS_ERR_PK_xxx error codes, and must not
+ * use \c MBEDTLS_ERR_SSL_xxx error codes except as
+ * directed in the documentation of this callback.
+ */
+typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl,
+ mbedtls_x509_crt *cert,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash,
+ size_t hash_len );
+
+/**
+ * \brief Callback type: start external decryption operation.
+ *
+ * This callback is called during an SSL handshake to start
+ * an RSA decryption operation using an
+ * external processor. The parameter \p cert contains
+ * the public key; it is up to the callback function to
+ * determine how to access the associated private key.
+ *
+ * This function typically sends or enqueues a request, and
+ * does not wait for the operation to complete. This allows
+ * the handshake step to be non-blocking.
+ *
+ * The parameters \p ssl and \p cert are guaranteed to remain
+ * valid throughout the handshake. On the other hand, this
+ * function must save the contents of \p input if the value
+ * is needed for later processing, because the \p input buffer
+ * is no longer valid after this function returns.
+ *
+ * This function may call mbedtls_ssl_set_async_operation_data()
+ * to store an operation context for later retrieval
+ * by the resume or cancel callback.
+ *
+ * \warning RSA decryption as used in TLS is subject to a potential
+ * timing side channel attack first discovered by Bleichenbacher
+ * in 1998. This attack can be remotely exploitable
+ * in practice. To avoid this attack, you must ensure that
+ * if the callback performs an RSA decryption, the time it
+ * takes to execute and return the result does not depend
+ * on whether the RSA decryption succeeded or reported
+ * invalid padding.
+ *
+ * \param ssl The SSL connection instance. It should not be
+ * modified other than via
+ * mbedtls_ssl_set_async_operation_data().
+ * \param cert Certificate containing the public key.
+ * In simple cases, this is one of the pointers passed to
+ * mbedtls_ssl_conf_own_cert() when configuring the SSL
+ * connection. However, if other callbacks are used, this
+ * property may not hold. For example, if an SNI callback
+ * is registered with mbedtls_ssl_conf_sni(), then
+ * this callback determines what certificate is used.
+ * \param input Buffer containing the input ciphertext. This buffer
+ * is no longer valid when the function returns.
+ * \param input_len Size of the \p input buffer in bytes.
+ *
+ * \return 0 if the operation was started successfully and the SSL
+ * stack should call the resume callback immediately.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
+ * was started successfully and the SSL stack should return
+ * immediately without calling the resume callback yet.
+ * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external
+ * processor does not support this key. The SSL stack will
+ * use the private key object instead.
+ * \return Any other error indicates a fatal failure and is
+ * propagated up the call chain. The callback should
+ * use \c MBEDTLS_ERR_PK_xxx error codes, and must not
+ * use \c MBEDTLS_ERR_SSL_xxx error codes except as
+ * directed in the documentation of this callback.
+ */
+typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl,
+ mbedtls_x509_crt *cert,
+ const unsigned char *input,
+ size_t input_len );
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+/**
+ * \brief Callback type: resume external operation.
+ *
+ * This callback is called during an SSL handshake to resume
+ * an external operation started by the
+ * ::mbedtls_ssl_async_sign_t or
+ * ::mbedtls_ssl_async_decrypt_t callback.
+ *
+ * This function typically checks the status of a pending
+ * request or causes the request queue to make progress, and
+ * does not wait for the operation to complete. This allows
+ * the handshake step to be non-blocking.
+ *
+ * This function may call mbedtls_ssl_get_async_operation_data()
+ * to retrieve an operation context set by the start callback.
+ * It may call mbedtls_ssl_set_async_operation_data() to modify
+ * this context.
+ *
+ * Note that when this function returns a status other than
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any
+ * resources associated with the operation.
+ *
+ * \param ssl The SSL connection instance. It should not be
+ * modified other than via
+ * mbedtls_ssl_set_async_operation_data().
+ * \param output Buffer containing the output (signature or decrypted
+ * data) on success.
+ * \param output_len On success, number of bytes written to \p output.
+ * \param output_size Size of the \p output buffer in bytes.
+ *
+ * \return 0 if output of the operation is available in the
+ * \p output buffer.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
+ * is still in progress. Subsequent requests for progress
+ * on the SSL connection will call the resume callback
+ * again.
+ * \return Any other error means that the operation is aborted.
+ * The SSL handshake is aborted. The callback should
+ * use \c MBEDTLS_ERR_PK_xxx error codes, and must not
+ * use \c MBEDTLS_ERR_SSL_xxx error codes except as
+ * directed in the documentation of this callback.
+ */
+typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl,
+ unsigned char *output,
+ size_t *output_len,
+ size_t output_size );
+
+/**
+ * \brief Callback type: cancel external operation.
+ *
+ * This callback is called if an SSL connection is closed
+ * while an asynchronous operation is in progress. Note that
+ * this callback is not called if the
+ * ::mbedtls_ssl_async_resume_t callback has run and has
+ * returned a value other than
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case
+ * the asynchronous operation has already completed.
+ *
+ * This function may call mbedtls_ssl_get_async_operation_data()
+ * to retrieve an operation context set by the start callback.
+ *
+ * \param ssl The SSL connection instance. It should not be
+ * modified.
+ */
+typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl );
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
/*
* This structure is used for storing current session data.
*/
@@ -669,6 +899,16 @@ struct mbedtls_ssl_config
mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */
+ mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+ mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */
+ mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */
+ void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
const int *sig_hashes; /*!< allowed signature hashes */
#endif
@@ -792,14 +1032,14 @@ struct mbedtls_ssl_context
int renego_records_seen; /*!< Records since renego request, or with DTLS,
number of retransmissions of request if
renego_max_records is < 0 */
-#endif
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */
int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
unsigned badmac_seen; /*!< records with a bad MAC received */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
mbedtls_ssl_send_t *f_send; /*!< Callback for network send */
mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */
@@ -855,11 +1095,11 @@ struct mbedtls_ssl_context
uint16_t in_epoch; /*!< DTLS epoch for incoming records */
size_t next_record_offset; /*!< offset of the next record in datagram
(equal to in_left if none) */
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
uint64_t in_window_top; /*!< last validated record seq_num */
uint64_t in_window; /*!< bitmask for replay detection */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
size_t in_hslen; /*!< current handshake message length,
including the handshake header */
@@ -868,6 +1108,11 @@ struct mbedtls_ssl_context
int keep_current_message; /*!< drop or reuse current message
on next call to record layer? */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ uint8_t disable_datagram_packing; /*!< Disable packing multiple records
+ * within a single datagram. */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
/*
* Record layer (outgoing data)
*/
@@ -882,12 +1127,18 @@ struct mbedtls_ssl_context
size_t out_msglen; /*!< record header: message length */
size_t out_left; /*!< amount of data not yet written */
+ unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
#if defined(MBEDTLS_ZLIB_SUPPORT)
unsigned char *compress_buf; /*!< zlib data buffer */
-#endif
+#endif /* MBEDTLS_ZLIB_SUPPORT */
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
signed char split_done; /*!< current record already splitted? */
-#endif
+#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
/*
* PKI layer
@@ -900,11 +1151,11 @@ struct mbedtls_ssl_context
#if defined(MBEDTLS_X509_CRT_PARSE_C)
char *hostname; /*!< expected peer CN for verification
(and SNI if available) */
-#endif
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_ALPN)
const char *alpn_chosen; /*!< negotiated protocol */
-#endif
+#endif /* MBEDTLS_SSL_ALPN */
/*
* Information for DTLS hello verify
@@ -912,7 +1163,7 @@ struct mbedtls_ssl_context
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
unsigned char *cli_id; /*!< transport-level ID of the client */
size_t cli_id_len; /*!< length of cli_id */
-#endif
+#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
/*
* Secure renegotiation
@@ -924,7 +1175,7 @@ struct mbedtls_ssl_context
size_t verify_data_len; /*!< length of verify data stored */
char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
-#endif
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
};
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
@@ -946,14 +1197,6 @@ extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl);
extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl);
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
-/**
- * \brief Returns the list of ciphersuites supported by the SSL/TLS module.
- *
- * \return a statically allocated array of ciphersuites, the last
- * entry is 0.
- */
-const int *mbedtls_ssl_list_ciphersuites( void );
-
/**
* \brief Return the name of the ciphersuite associated with the
* given ID
@@ -1152,6 +1395,52 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
mbedtls_ssl_recv_t *f_recv,
mbedtls_ssl_recv_timeout_t *f_recv_timeout );
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+/**
+ * \brief Set the Maximum Tranport Unit (MTU).
+ * Special value: 0 means unset (no limit).
+ * This represents the maximum size of a datagram payload
+ * handled by the transport layer (usually UDP) as determined
+ * by the network link and stack. In practice, this controls
+ * the maximum size datagram the DTLS layer will pass to the
+ * \c f_send() callback set using \c mbedtls_ssl_set_bio().
+ *
+ * \note The limit on datagram size is converted to a limit on
+ * record payload by subtracting the current overhead of
+ * encapsulation and encryption/authentication if any.
+ *
+ * \note This can be called at any point during the connection, for
+ * example when a Path Maximum Transfer Unit (PMTU)
+ * estimate becomes available from other sources,
+ * such as lower (or higher) protocol layers.
+ *
+ * \note This setting only controls the size of the packets we send,
+ * and does not restrict the size of the datagrams we're
+ * willing to receive. Client-side, you can request the
+ * server to use smaller records with \c
+ * mbedtls_ssl_conf_max_frag_len().
+ *
+ * \note If both a MTU and a maximum fragment length have been
+ * configured (or negotiated with the peer), the resulting
+ * lower limit on record payload (see first note) is used.
+ *
+ * \note This can only be used to decrease the maximum size
+ * of datagrams (hence records, see first note) sent. It
+ * cannot be used to increase the maximum size of records over
+ * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN.
+ *
+ * \note Values lower than the current record layer expansion will
+ * result in an error when trying to send data.
+ *
+ * \note Using record compression together with a non-zero MTU value
+ * will result in an error when trying to send data.
+ *
+ * \param ssl SSL context
+ * \param mtu Value of the path MTU in bytes
+ */
+void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
/**
* \brief Set the timeout period for mbedtls_ssl_read()
* (Default: no timeout.)
@@ -1315,6 +1604,85 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
void *p_export_keys );
#endif /* MBEDTLS_SSL_EXPORT_KEYS */
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+/**
+ * \brief Configure asynchronous private key operation callbacks.
+ *
+ * \param conf SSL configuration context
+ * \param f_async_sign Callback to start a signature operation. See
+ * the description of ::mbedtls_ssl_async_sign_t
+ * for more information. This may be \c NULL if the
+ * external processor does not support any signature
+ * operation; in this case the private key object
+ * associated with the certificate will be used.
+ * \param f_async_decrypt Callback to start a decryption operation. See
+ * the description of ::mbedtls_ssl_async_decrypt_t
+ * for more information. This may be \c NULL if the
+ * external processor does not support any decryption
+ * operation; in this case the private key object
+ * associated with the certificate will be used.
+ * \param f_async_resume Callback to resume an asynchronous operation. See
+ * the description of ::mbedtls_ssl_async_resume_t
+ * for more information. This may not be \c NULL unless
+ * \p f_async_sign and \p f_async_decrypt are both
+ * \c NULL.
+ * \param f_async_cancel Callback to cancel an asynchronous operation. See
+ * the description of ::mbedtls_ssl_async_cancel_t
+ * for more information. This may be \c NULL if
+ * no cleanup is needed.
+ * \param config_data A pointer to configuration data which can be
+ * retrieved with
+ * mbedtls_ssl_conf_get_async_config_data(). The
+ * library stores this value without dereferencing it.
+ */
+void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf,
+ mbedtls_ssl_async_sign_t *f_async_sign,
+ mbedtls_ssl_async_decrypt_t *f_async_decrypt,
+ mbedtls_ssl_async_resume_t *f_async_resume,
+ mbedtls_ssl_async_cancel_t *f_async_cancel,
+ void *config_data );
+
+/**
+ * \brief Retrieve the configuration data set by
+ * mbedtls_ssl_conf_async_private_cb().
+ *
+ * \param conf SSL configuration context
+ * \return The configuration data set by
+ * mbedtls_ssl_conf_async_private_cb().
+ */
+void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf );
+
+/**
+ * \brief Retrieve the asynchronous operation user context.
+ *
+ * \note This function may only be called while a handshake
+ * is in progress.
+ *
+ * \param ssl The SSL context to access.
+ *
+ * \return The asynchronous operation user context that was last
+ * set during the current handshake. If
+ * mbedtls_ssl_set_async_operation_data() has not yet been
+ * called during the current handshake, this function returns
+ * \c NULL.
+ */
+void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl );
+
+/**
+ * \brief Retrieve the asynchronous operation user context.
+ *
+ * \note This function may only be called while a handshake
+ * is in progress.
+ *
+ * \param ssl The SSL context to access.
+ * \param ctx The new value of the asynchronous operation user context.
+ * Call mbedtls_ssl_get_async_operation_data() later during the
+ * same handshake to retrieve this value.
+ */
+void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl,
+ void *ctx );
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
/**
* \brief Callback type: generate a cookie
*
@@ -1456,6 +1824,38 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi
#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+/**
+ * \brief Allow or disallow packing of multiple handshake records
+ * within a single datagram.
+ *
+ * \param ssl The SSL context to configure.
+ * \param allow_packing This determines whether datagram packing may
+ * be used or not. A value of \c 0 means that every
+ * record will be sent in a separate datagram; a
+ * value of \c 1 means that, if space permits,
+ * multiple handshake messages (including CCS) belonging to
+ * a single flight may be packed within a single datagram.
+ *
+ * \note This is enabled by default and should only be disabled
+ * for test purposes, or if datagram packing causes
+ * interoperability issues with peers that don't support it.
+ *
+ * \note Allowing datagram packing reduces the network load since
+ * there's less overhead if multiple messages share the same
+ * datagram. Also, it increases the handshake efficiency
+ * since messages belonging to a single datagram will not
+ * be reordered in transit, and so future message buffering
+ * or flight retransmission (if no buffering is used) as
+ * means to deal with reordering are needed less frequently.
+ *
+ * \note Application records are not affected by this option and
+ * are currently always sent in separate datagrams.
+ *
+ */
+void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl,
+ unsigned allow_packing );
+
/**
* \brief Set retransmit timeout values for the DTLS handshake.
* (DTLS only, no effect on TLS.)
@@ -2125,12 +2525,25 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
/**
* \brief Set the maximum fragment length to emit and/or negotiate
- * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes)
+ * (Default: the smaller of MBEDTLS_SSL_IN_CONTENT_LEN and
+ * MBEDTLS_SSL_OUT_CONTENT_LEN, usually 2^14 bytes)
* (Server: set maximum fragment length to emit,
* usually negotiated by the client during handshake
* (Client: set maximum fragment length to emit *and*
* negotiate with the server during handshake)
*
+ * \note With TLS, this currently only affects ApplicationData (sent
+ * with \c mbedtls_ssl_read()), not handshake messages.
+ * With DTLS, this affects both ApplicationData and handshake.
+ *
+ * \note This sets the maximum length for a record's payload,
+ * excluding record overhead that will be added to it, see
+ * \c mbedtls_ssl_get_record_expansion().
+ *
+ * \note For DTLS, it is also possible to set a limit for the total
+ * size of daragrams passed to the transport layer, including
+ * record overhead, see \c mbedtls_ssl_set_mtu().
+ *
* \param conf SSL configuration
* \param mfl_code Code for maximum fragment length (allowed values:
* MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024,
@@ -2393,6 +2806,9 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl );
* \brief Return the (maximum) number of bytes added by the record
* layer: header + encryption/MAC overhead (inc. padding)
*
+ * \note This function is not available (always returns an error)
+ * when record compression is enabled.
+ *
* \param ssl SSL context
*
* \return Current maximum record expansion in bytes, or
@@ -2407,12 +2823,8 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl );
* This is the value negotiated with peer if any,
* or the locally configured value.
*
- * \note With DTLS, \c mbedtls_ssl_write() will return an error if
- * called with a larger length value.
- * With TLS, \c mbedtls_ssl_write() will fragment the input if
- * necessary and return the number of bytes written; it is up
- * to the caller to call \c mbedtls_ssl_write() again in
- * order to send the remaining bytes if any.
+ * \sa mbedtls_ssl_conf_max_frag_len()
+ * \sa mbedtls_ssl_get_max_record_payload()
*
* \param ssl SSL context
*
@@ -2421,6 +2833,34 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl );
size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+/**
+ * \brief Return the current maximum outgoing record payload in bytes.
+ * This takes into account the config.h setting \c
+ * MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated
+ * max fragment length extension if used, and for DTLS the
+ * path MTU as configured and current record expansion.
+ *
+ * \note With DTLS, \c mbedtls_ssl_write() will return an error if
+ * called with a larger length value.
+ * With TLS, \c mbedtls_ssl_write() will fragment the input if
+ * necessary and return the number of bytes written; it is up
+ * to the caller to call \c mbedtls_ssl_write() again in
+ * order to send the remaining bytes if any.
+ *
+ * \note This function is not available (always returns an error)
+ * when record compression is enabled.
+ *
+ * \sa mbedtls_ssl_set_mtu()
+ * \sa mbedtls_ssl_get_max_frag_len()
+ * \sa mbedtls_ssl_get_record_expansion()
+ *
+ * \param ssl SSL context
+ *
+ * \return Current maximum payload for an outgoing record,
+ * or a negative error code.
+ */
+int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl );
+
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
* \brief Return the peer certificate from the current connection
@@ -2444,7 +2884,6 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss
* \brief Save session in order to resume it later (client-side only)
* Session data is copied to presented session structure.
*
- * \warning Currently, peer certificate is lost in the operation.
*
* \param ssl SSL context
* \param session session context
@@ -2452,7 +2891,18 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss
* \return 0 if successful,
* MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or
- * arguments are otherwise invalid
+ * arguments are otherwise invalid.
+ *
+ * \note Only the server certificate is copied, and not the full chain,
+ * so you should not attempt to validate the certificate again
+ * by calling \c mbedtls_x509_crt_verify() on it.
+ * Instead, you should use the results from the verification
+ * in the original handshake by calling \c mbedtls_ssl_get_verify_result()
+ * after loading the session again into a new SSL context
+ * using \c mbedtls_ssl_set_session().
+ *
+ * \note Once the session object is not needed anymore, you should
+ * free it by calling \c mbedtls_ssl_session_free().
*
* \sa mbedtls_ssl_set_session()
*/
@@ -2464,35 +2914,50 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session
*
* \param ssl SSL context
*
- * \return 0 if successful, or
- * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
- * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or
- * a specific SSL error code.
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ * if the handshake is incomplete and waiting for data to
+ * be available for reading from or writing to the underlying
+ * transport - in this case you must call this function again
+ * when the underlying transport is ready for the operation.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ * operation is in progress (see
+ * mbedtls_ssl_conf_async_private_cb()) - in this case you
+ * must call this function again when the operation is ready.
+ * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ * operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ * in this case you must call this function again to complete
+ * the handshake when you're done attending other tasks.
+ * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use
+ * and the client did not demonstrate reachability yet - in
+ * this case you must stop using the context (see below).
+ * \return Another SSL error code - in this case you must stop using
+ * the context (see below).
*
- * If this function returns MBEDTLS_ERR_SSL_WANT_READ, the
- * handshake is unfinished and no further data is available
- * from the underlying transport. In this case, you must call
- * the function again at some later stage.
+ * \warning If this function returns something other than
+ * \c 0,
+ * #MBEDTLS_ERR_SSL_WANT_READ,
+ * #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ * you must stop using the SSL context for reading or writing,
+ * and either free it or call \c mbedtls_ssl_session_reset()
+ * on it before re-using it for a new connection; the current
+ * connection must be closed.
+ *
+ * \note If DTLS is in use, then you may choose to handle
+ * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
+ * purposes, as it is an expected return value rather than an
+ * actual error, but you still need to reset/free the context.
*
* \note Remarks regarding event-driven DTLS:
- * If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
+ * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram
* from the underlying transport layer is currently being processed,
* and it is safe to idle until the timer or the underlying transport
* signal a new event. This is not true for a successful handshake,
* in which case the datagram of the underlying transport that is
* currently being processed might or might not contain further
* DTLS records.
- *
- * \note If this function returns something other than 0 or
- * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- * the SSL context for reading or writing, and either free it or
- * call \c mbedtls_ssl_session_reset() on it before re-using it
- * for a new connection; the current connection must be closed.
- *
- * \note If DTLS is in use, then you may choose to handle
- * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
- * purposes, as it is an expected return value rather than an
- * actual error, but you still need to reset/free the context.
*/
int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
@@ -2500,20 +2965,21 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
* \brief Perform a single step of the SSL handshake
*
* \note The state of the context (ssl->state) will be at
- * the next state after execution of this function. Do not
+ * the next state after this function returns \c 0. Do not
* call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
*
- * \note If this function returns something other than 0 or
- * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- * the SSL context for reading or writing, and either free it or
- * call \c mbedtls_ssl_session_reset() on it before re-using it
- * for a new connection; the current connection must be closed.
- *
* \param ssl SSL context
*
- * \return 0 if successful, or
- * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
- * a specific SSL error code.
+ * \return See mbedtls_ssl_handshake().
+ *
+ * \warning If this function returns something other than \c 0,
+ * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
+ * the SSL context for reading or writing, and either free it
+ * or call \c mbedtls_ssl_session_reset() on it before
+ * re-using it for a new connection; the current connection
+ * must be closed.
*/
int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
@@ -2528,13 +2994,18 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
* \param ssl SSL context
*
* \return 0 if successful, or any mbedtls_ssl_handshake() return
- * value.
+ * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't
+ * happen during a renegotiation.
+ *
+ * \warning If this function returns something other than \c 0,
+ * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
+ * the SSL context for reading or writing, and either free it
+ * or call \c mbedtls_ssl_session_reset() on it before
+ * re-using it for a new connection; the current connection
+ * must be closed.
*
- * \note If this function returns something other than 0 or
- * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- * the SSL context for reading or writing, and either free it or
- * call \c mbedtls_ssl_session_reset() on it before re-using it
- * for a new connection; the current connection must be closed.
*/
int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_RENEGOTIATION */
@@ -2546,42 +3017,56 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
* \param buf buffer that will hold the data
* \param len maximum number of bytes to read
*
- * \return One of the following:
- * - 0 if the read end of the underlying transport was closed,
- * - the (positive) number of bytes read, or
- * - a negative error code on failure.
+ * \return The (positive) number of bytes read if successful.
+ * \return \c 0 if the read end of the underlying transport was closed
+ * - in this case you must stop using the context (see below).
+ * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ * if the handshake is incomplete and waiting for data to
+ * be available for reading from or writing to the underlying
+ * transport - in this case you must call this function again
+ * when the underlying transport is ready for the operation.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ * operation is in progress (see
+ * mbedtls_ssl_conf_async_private_cb()) - in this case you
+ * must call this function again when the operation is ready.
+ * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ * operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ * in this case you must call this function again to complete
+ * the handshake when you're done attending other tasks.
+ * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server
+ * side of a DTLS connection and the client is initiating a
+ * new connection using the same source port. See below.
+ * \return Another SSL error code - in this case you must stop using
+ * the context (see below).
*
- * If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data
- * is available from the underlying transport. In this case,
- * the function needs to be called again at some later stage.
+ * \warning If this function returns something other than
+ * a positive value,
+ * #MBEDTLS_ERR_SSL_WANT_READ,
+ * #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
+ * you must stop using the SSL context for reading or writing,
+ * and either free it or call \c mbedtls_ssl_session_reset()
+ * on it before re-using it for a new connection; the current
+ * connection must be closed.
*
- * If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending
- * but the underlying transport isn't available for writing. In this
- * case, the function needs to be called again at some later stage.
- *
- * When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
+ * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT
* (which can only happen server-side), it means that a client
* is initiating a new connection using the same source port.
* You can either treat that as a connection close and wait
* for the client to resend a ClientHello, or directly
* continue with \c mbedtls_ssl_handshake() with the same
- * context (as it has beeen reset internally). Either way, you
- * should make sure this is seen by the application as a new
+ * context (as it has been reset internally). Either way, you
+ * must make sure this is seen by the application as a new
* connection: application state, if any, should be reset, and
* most importantly the identity of the client must be checked
* again. WARNING: not validating the identity of the client
* again, or not transmitting the new identity to the
* application layer, would allow authentication bypass!
*
- * \note If this function returns something other than a positive value
- * or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
- * you must stop using the SSL context for reading or writing,
- * and either free it or call \c mbedtls_ssl_session_reset() on it
- * before re-using it for a new connection; the current connection
- * must be closed.
- *
* \note Remarks regarding event-driven DTLS:
- * - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
+ * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram
* from the underlying transport layer is currently being processed,
* and it is safe to idle until the timer or the underlying transport
* signal a new event.
@@ -2610,21 +3095,41 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
* \param buf buffer holding the data
* \param len how many bytes must be written
*
- * \return the number of bytes actually written (may be less than len),
- * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ,
- * or another negative error code.
+ * \return The (non-negative) number of bytes actually written if
+ * successful (may be less than \p len).
+ * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
+ * if the handshake is incomplete and waiting for data to
+ * be available for reading from or writing to the underlying
+ * transport - in this case you must call this function again
+ * when the underlying transport is ready for the operation.
+ * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
+ * operation is in progress (see
+ * mbedtls_ssl_conf_async_private_cb()) - in this case you
+ * must call this function again when the operation is ready.
+ * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
+ * operation is in progress (see mbedtls_ecp_set_max_ops()) -
+ * in this case you must call this function again to complete
+ * the handshake when you're done attending other tasks.
+ * \return Another SSL error code - in this case you must stop using
+ * the context (see below).
*
- * \note If this function returns something other than a positive value
- * or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- * the SSL context for reading or writing, and either free it or
- * call \c mbedtls_ssl_session_reset() on it before re-using it
- * for a new connection; the current connection must be closed.
+ * \warning If this function returns something other than
+ * a non-negative value,
+ * #MBEDTLS_ERR_SSL_WANT_READ,
+ * #MBEDTLS_ERR_SSL_WANT_WRITE,
+ * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
+ * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ * you must stop using the SSL context for reading or writing,
+ * and either free it or call \c mbedtls_ssl_session_reset()
+ * on it before re-using it for a new connection; the current
+ * connection must be closed.
*
- * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ,
+ * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ,
* it must be called later with the *same* arguments,
- * until it returns a positive value. When the function returns
- * MBEDTLS_ERR_SSL_WANT_WRITE there may be some partial
- * data in the output buffer, however this is not yet sent.
+ * until it returns a value greater that or equal to 0. When
+ * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be
+ * some partial data in the output buffer, however this is not
+ * yet sent.
*
* \note If the requested length is greater than the maximum
* fragment length (either the built-in limit or the one set
@@ -2633,6 +3138,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
* - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned.
* \c mbedtls_ssl_get_max_frag_len() may be used to query the
* active maximum fragment length.
+ *
+ * \note Attempting to write 0 bytes will result in an empty TLS
+ * application record being sent.
*/
int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len );
@@ -2725,6 +3233,9 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session );
* \brief Free referenced items in an SSL session including the
* peer certificate and clear memory
*
+ * \note A session object can be freed even if the SSL context
+ * that was used to retrieve the session is still in use.
+ *
* \param session SSL session
*/
void mbedtls_ssl_session_free( mbedtls_ssl_session *session );
diff --git a/include/mbedtls/ssl_ciphersuites.h b/include/mbedtls/ssl_ciphersuites.h
index 1d2aabc372..cda8b4835b 100644
--- a/include/mbedtls/ssl_ciphersuites.h
+++ b/include/mbedtls/ssl_ciphersuites.h
@@ -169,6 +169,45 @@ extern "C" {
#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */
#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */
+#define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */
+#define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */
+#define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */
+#define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */
+#define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */
+
#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */
#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */
#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */
@@ -232,6 +271,15 @@ extern "C" {
#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */
+/* RFC 7905 */
+#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */
+#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */
+
/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange.
* Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below
*/
diff --git a/include/mbedtls/ssl_cookie.h b/include/mbedtls/ssl_cookie.h
index 80b65bbbb9..6a0ad4fa96 100644
--- a/include/mbedtls/ssl_cookie.h
+++ b/include/mbedtls/ssl_cookie.h
@@ -50,7 +50,7 @@ extern "C" {
/**
* \brief Context for the default cookie functions.
*/
-typedef struct
+typedef struct mbedtls_ssl_cookie_ctx
{
mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */
#if !defined(MBEDTLS_HAVE_TIME)
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 60b431a0f4..97abb9f90b 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -93,6 +93,14 @@
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+/* Shorthand for restartable ECC */
+#if defined(MBEDTLS_ECP_RESTARTABLE) && \
+ defined(MBEDTLS_SSL_CLI_C) && \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#define MBEDTLS_SSL__ECP_RESTARTABLE
+#endif
+
#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0
#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */
#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */
@@ -143,32 +151,76 @@
#define MBEDTLS_SSL_PADDING_ADD 0
#endif
-#define MBEDTLS_SSL_PAYLOAD_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \
- + MBEDTLS_SSL_COMPRESSION_ADD \
- + MBEDTLS_MAX_IV_LENGTH \
- + MBEDTLS_SSL_MAC_ADD \
- + MBEDTLS_SSL_PADDING_ADD \
- )
+#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \
+ MBEDTLS_MAX_IV_LENGTH + \
+ MBEDTLS_SSL_MAC_ADD + \
+ MBEDTLS_SSL_PADDING_ADD \
+ )
+
+#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
+ ( MBEDTLS_SSL_IN_CONTENT_LEN ) )
+
+#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
+ ( MBEDTLS_SSL_OUT_CONTENT_LEN ) )
+
+/* The maximum number of buffered handshake messages. */
+#define MBEDTLS_SSL_MAX_BUFFERED_HS 4
+
+/* Maximum length we can advertise as our max content length for
+ RFC 6066 max_fragment_length extension negotiation purposes
+ (the lesser of both sizes, if they are unequal.)
+ */
+#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \
+ (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \
+ ? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \
+ : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \
+ )
/*
* Check that we obey the standard's message size bounds
*/
#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384
-#error Bad configuration - record content too large.
+#error "Bad configuration - record content too large."
#endif
-#if MBEDTLS_SSL_PAYLOAD_LEN > 16384 + 2048
-#error Bad configuration - protected record payload too large.
+#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN
+#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN."
#endif
+#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN
+#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN."
+#endif
+
+#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048
+#error "Bad configuration - incoming protected record payload too large."
+#endif
+
+#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048
+#error "Bad configuration - outgoing protected record payload too large."
+#endif
+
+/* Calculate buffer sizes */
+
/* Note: Even though the TLS record header is only 5 bytes
long, we're internally using 8 bytes to store the
implicit sequence number. */
#define MBEDTLS_SSL_HEADER_LEN 13
-#define MBEDTLS_SSL_BUFFER_LEN \
- ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_PAYLOAD_LEN ) )
+#define MBEDTLS_SSL_IN_BUFFER_LEN \
+ ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) )
+
+#define MBEDTLS_SSL_OUT_BUFFER_LEN \
+ ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) )
+
+#ifdef MBEDTLS_ZLIB_SUPPORT
+/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */
+#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \
+ ( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN ) \
+ ? MBEDTLS_SSL_IN_BUFFER_LEN \
+ : MBEDTLS_SSL_OUT_BUFFER_LEN \
+ )
+#endif
/*
* TLS extension flags (for extensions with outgoing ServerHello content
@@ -243,6 +295,18 @@ struct mbedtls_ssl_handshake_params
mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ int ecrs_enabled; /*!< Handshake supports EC restart? */
+ mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */
+ enum { /* this complements ssl->state with info on intra-state operations */
+ ssl_ecrs_none = 0, /*!< nothing going on (yet) */
+ ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */
+ ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */
+ ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */
+ ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */
+ } ecrs_state; /*!< current (or last) operation */
+ size_t ecrs_n; /*!< place for saving a length */
+#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS)
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
unsigned int in_msg_seq; /*!< Incoming handshake sequence number */
@@ -252,18 +316,45 @@ struct mbedtls_ssl_handshake_params
unsigned char verify_cookie_len; /*!< Cli: cookie length
Srv: flag for sending a cookie */
- unsigned char *hs_msg; /*!< Reassembled handshake message */
-
uint32_t retransmit_timeout; /*!< Current value of timeout */
unsigned char retransmit_state; /*!< Retransmission state */
- mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */
- mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */
+ mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */
+ mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */
+ unsigned char *cur_msg_p; /*!< Position in current message */
unsigned int in_flight_start_seq; /*!< Minimum message sequence in the
flight being received */
mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for
resending messages */
unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter
for resending messages */
+
+ struct
+ {
+ size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
+ * buffers used for message buffering. */
+
+ uint8_t seen_ccs; /*!< Indicates if a CCS message has
+ * been seen in the current flight. */
+
+ struct mbedtls_ssl_hs_buffer
+ {
+ unsigned is_valid : 1;
+ unsigned is_fragmented : 1;
+ unsigned is_complete : 1;
+ unsigned char *data;
+ size_t data_len;
+ } hs[MBEDTLS_SSL_MAX_BUFFERED_HS];
+
+ struct
+ {
+ unsigned char *data;
+ size_t len;
+ unsigned epoch;
+ } future_record;
+
+ } buffering;
+
+ uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */
#endif /* MBEDTLS_SSL_PROTO_DTLS */
/*
@@ -307,8 +398,23 @@ struct mbedtls_ssl_handshake_params
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
int extended_ms; /*!< use Extended Master Secret? */
#endif
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ /** Asynchronous operation context. This field is meant for use by the
+ * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start,
+ * mbedtls_ssl_config::f_async_decrypt_start,
+ * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel).
+ * The library does not use it internally. */
+ void *user_async_ctx;
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
};
+typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer;
+
/*
* This structure contains a full set of runtime transform parameters
* either in negotiation or active.
@@ -410,9 +516,9 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform );
* \brief Free referenced items in an SSL handshake context and clear
* memory
*
- * \param handshake SSL handshake context
+ * \param ssl SSL context
*/
-void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake );
+void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl );
int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl );
int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl );
@@ -423,7 +529,6 @@ int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl );
void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl );
int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl );
-int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl );
int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl );
int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl );
void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
@@ -435,7 +540,10 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
* of the logic of (D)TLS from the implementation
* of the secure transport.
*
- * \param ssl SSL context to use
+ * \param ssl The SSL context to use.
+ * \param update_hs_digest This indicates if the handshake digest
+ * should be automatically updated in case
+ * a handshake message is found.
*
* \return 0 or non-zero error code.
*
@@ -501,10 +609,12 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
* following the above definition.
*
*/
-int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
+ unsigned update_hs_digest );
int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want );
-int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush );
int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl );
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl );
@@ -613,6 +723,7 @@ static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl )
void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl );
void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl );
int mbedtls_ssl_resend( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl );
#endif
/* Visible for testing purposes only */
@@ -630,7 +741,13 @@ static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t
volatile unsigned char diff = 0;
for( i = 0; i < n; i++ )
- diff |= A[i] ^ B[i];
+ {
+ /* Read volatile data in order before computing diff.
+ * This avoids IAR compiler warning:
+ * 'the order of volatile accesses is undefined ..' */
+ unsigned char x = A[i], y = B[i];
+ diff |= x ^ y;
+ }
return( diff );
}
@@ -646,9 +763,9 @@ int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
- unsigned char *output,
- unsigned char *data, size_t data_len,
- mbedtls_md_type_t md_alg );
+ unsigned char *hash, size_t *hashlen,
+ unsigned char *data, size_t data_len,
+ mbedtls_md_type_t md_alg );
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
MBEDTLS_SSL_PROTO_TLS1_2 */
diff --git a/include/mbedtls/ssl_ticket.h b/include/mbedtls/ssl_ticket.h
index 93ad46ac9c..b2686df09f 100644
--- a/include/mbedtls/ssl_ticket.h
+++ b/include/mbedtls/ssl_ticket.h
@@ -44,7 +44,7 @@ extern "C" {
/**
* \brief Information for session ticket protection
*/
-typedef struct
+typedef struct mbedtls_ssl_ticket_key
{
unsigned char name[4]; /*!< random key identifier */
uint32_t generation_time; /*!< key generation timestamp (seconds) */
@@ -55,7 +55,7 @@ mbedtls_ssl_ticket_key;
/**
* \brief Context for session ticket handling functions
*/
-typedef struct
+typedef struct mbedtls_ssl_ticket_context
{
mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */
unsigned char active; /*!< index of the currently active key */
diff --git a/include/mbedtls/threading.h b/include/mbedtls/threading.h
index aeea5d0e1a..75298bf8a3 100644
--- a/include/mbedtls/threading.h
+++ b/include/mbedtls/threading.h
@@ -42,7 +42,7 @@ extern "C" {
#if defined(MBEDTLS_THREADING_PTHREAD)
#include
-typedef struct
+typedef struct mbedtls_threading_mutex_t
{
pthread_mutex_t mutex;
char is_valid;
@@ -99,9 +99,17 @@ extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex );
#if defined(MBEDTLS_FS_IO)
extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex;
#endif
-#if defined(MBEDTLS_HAVE_TIME_DATE)
+
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+/* This mutex may or may not be used in the default definition of
+ * mbedtls_platform_gmtime_r(), but in order to determine that,
+ * we need to check POSIX features, hence modify _POSIX_C_SOURCE.
+ * With the current approach, this declaration is orphaned, lacking
+ * an accompanying definition, in case mbedtls_platform_gmtime_r()
+ * doesn't need it, but that's not a problem. */
extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex;
-#endif
+#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
+
#endif /* MBEDTLS_THREADING_C */
#ifdef __cplusplus
diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h
index bbcb90688a..a965fe0d35 100644
--- a/include/mbedtls/timing.h
+++ b/include/mbedtls/timing.h
@@ -51,7 +51,7 @@ struct mbedtls_timing_hr_time
/**
* \brief Context for mbedtls_timing_set/get_delay()
*/
-typedef struct
+typedef struct mbedtls_timing_delay_context
{
struct mbedtls_timing_hr_time timer;
uint32_t int_ms;
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index aa52ce21ec..326b8bd451 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -39,17 +39,17 @@
* Major, Minor, Patchlevel
*/
#define MBEDTLS_VERSION_MAJOR 2
-#define MBEDTLS_VERSION_MINOR 9
-#define MBEDTLS_VERSION_PATCH 0
+#define MBEDTLS_VERSION_MINOR 13
+#define MBEDTLS_VERSION_PATCH 1
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x02090000
-#define MBEDTLS_VERSION_STRING "2.9.0"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.9.0"
+#define MBEDTLS_VERSION_NUMBER 0x020D0100
+#define MBEDTLS_VERSION_STRING "2.13.1"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.13.1"
#if defined(MBEDTLS_VERSION_C)
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index ac23cffe84..afeefca60e 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -105,7 +105,7 @@ mbedtls_x509_crt;
*
* All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG().
*/
-typedef struct
+typedef struct mbedtls_x509_crt_profile
{
uint32_t allowed_mds; /**< MDs for signatures */
uint32_t allowed_pks; /**< PK algs for signatures */
@@ -143,6 +143,63 @@ typedef struct mbedtls_x509write_cert
}
mbedtls_x509write_cert;
+/**
+ * Item in a verification chain: cert and flags for it
+ */
+typedef struct {
+ mbedtls_x509_crt *crt;
+ uint32_t flags;
+} mbedtls_x509_crt_verify_chain_item;
+
+/**
+ * Max size of verification chain: end-entity + intermediates + trusted root
+ */
+#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
+
+/**
+ * Verification chain as built by \c mbedtls_crt_verify_chain()
+ */
+typedef struct
+{
+ mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE];
+ unsigned len;
+} mbedtls_x509_crt_verify_chain;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+
+/**
+ * \brief Context for resuming X.509 verify operations
+ */
+typedef struct
+{
+ /* for check_signature() */
+ mbedtls_pk_restart_ctx pk;
+
+ /* for find_parent_in() */
+ mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */
+ mbedtls_x509_crt *fallback_parent;
+ int fallback_signature_is_good;
+
+ /* for find_parent() */
+ int parent_is_trusted; /* -1 if find_parent is not in progress */
+
+ /* for verify_chain() */
+ enum {
+ x509_crt_rs_none,
+ x509_crt_rs_find_parent,
+ } in_progress; /* none if no operation is in progress */
+ int self_cnt;
+ mbedtls_x509_crt_verify_chain ver_chain;
+
+} mbedtls_x509_crt_restart_ctx;
+
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+/* Now we can declare functions that take a pointer to that */
+typedef void mbedtls_x509_crt_restart_ctx;
+
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
* Default security profile. Should provide a good balance between security
@@ -353,6 +410,37 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy );
+/**
+ * \brief Restartable version of \c mbedtls_crt_verify_with_profile()
+ *
+ * \note Performs the same job as \c mbedtls_crt_verify_with_profile()
+ * but can return early and restart according to the limit
+ * set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
+ *
+ * \param crt a certificate (chain) to be verified
+ * \param trust_ca the list of trusted CAs
+ * \param ca_crl the list of CRLs for trusted CAs
+ * \param profile security profile for verification
+ * \param cn expected Common Name (can be set to
+ * NULL if the CN must not be verified)
+ * \param flags result of the verification
+ * \param f_vrfy verification function
+ * \param p_vrfy verification parameter
+ * \param rs_ctx restart context (NULL to disable restart)
+ *
+ * \return See \c mbedtls_crt_verify_with_profile(), or
+ * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
+ * operations was reached: see \c mbedtls_ecp_set_max_ops().
+ */
+int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crl *ca_crl,
+ const mbedtls_x509_crt_profile *profile,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy,
+ mbedtls_x509_crt_restart_ctx *rs_ctx );
+
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
/**
* \brief Check usage of certificate against keyUsage extension.
@@ -424,6 +512,18 @@ void mbedtls_x509_crt_init( mbedtls_x509_crt *crt );
* \param crt Certificate chain to free
*/
void mbedtls_x509_crt_free( mbedtls_x509_crt *crt );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/**
+ * \brief Initialize a restart context
+ */
+void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx );
+
+/**
+ * \brief Free the components of a restart context
+ */
+void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
/* \} name */
diff --git a/include/mbedtls/xtea.h b/include/mbedtls/xtea.h
index 8df708a3a5..c70c3fe265 100644
--- a/include/mbedtls/xtea.h
+++ b/include/mbedtls/xtea.h
@@ -50,7 +50,7 @@ extern "C" {
/**
* \brief XTEA context structure
*/
-typedef struct
+typedef struct mbedtls_xtea_context
{
uint32_t k[4]; /*!< key */
}
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 6177ca2b4c..275eda3bbd 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -6,6 +6,7 @@ set(src_crypto
aes.c
aesni.c
arc4.c
+ aria.c
asn1parse.c
asn1write.c
base64.c
@@ -13,6 +14,8 @@ set(src_crypto
blowfish.c
camellia.c
ccm.c
+ chacha20.c
+ chachapoly.c
cipher.c
cipher_wrap.c
cmac.c
@@ -29,6 +32,7 @@ set(src_crypto
error.c
gcm.c
havege.c
+ hkdf.c
hmac_drbg.c
md.c
md2.c
@@ -36,6 +40,7 @@ set(src_crypto
md5.c
md_wrap.c
memory_buffer_alloc.c
+ nist_kw.c
oid.c
padlock.c
pem.c
@@ -47,6 +52,7 @@ set(src_crypto
pkwrite.c
platform.c
platform_util.c
+ poly1305.c
ripemd160.c
rsa.c
rsa_internal.c
@@ -96,6 +102,17 @@ if(WIN32)
set(libs ${libs} ws2_32)
endif(WIN32)
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ SET(CMAKE_C_ARCHIVE_CREATE " Scr ")
+ SET(CMAKE_CXX_ARCHIVE_CREATE " Scr ")
+ SET(CMAKE_C_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ")
+ SET(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ")
+endif()
+
+if(HAIKU)
+ set(libs ${libs} network)
+endif(HAIKU)
+
if(USE_PKCS11_HELPER_LIBRARY)
set(libs ${libs} pkcs11-helper)
endif(USE_PKCS11_HELPER_LIBRARY)
@@ -142,15 +159,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY)
if(USE_SHARED_MBEDTLS_LIBRARY)
add_library(mbedcrypto SHARED ${src_crypto})
- set_target_properties(mbedcrypto PROPERTIES VERSION 2.9.0 SOVERSION 2)
+ set_target_properties(mbedcrypto PROPERTIES VERSION 2.13.1 SOVERSION 3)
target_link_libraries(mbedcrypto ${libs})
add_library(mbedx509 SHARED ${src_x509})
- set_target_properties(mbedx509 PROPERTIES VERSION 2.9.0 SOVERSION 0)
+ set_target_properties(mbedx509 PROPERTIES VERSION 2.13.1 SOVERSION 0)
target_link_libraries(mbedx509 ${libs} mbedcrypto)
add_library(mbedtls SHARED ${src_tls})
- set_target_properties(mbedtls PROPERTIES VERSION 2.9.0 SOVERSION 10)
+ set_target_properties(mbedtls PROPERTIES VERSION 2.13.1 SOVERSION 12)
target_link_libraries(mbedtls ${libs} mbedx509)
install(TARGETS mbedtls mbedx509 mbedcrypto
diff --git a/library/Makefile b/library/Makefile
index b155c720ea..430c598812 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -21,6 +21,10 @@ endif
# if were running on Windows build for Windows
ifdef WINDOWS
WINDOWS_BUILD=1
+else ifeq ($(shell uname -s),Darwin)
+ifeq ($(AR),ar)
+APPLE_BUILD ?= 1
+endif
endif
# To compile as a shared library:
@@ -31,42 +35,56 @@ LOCAL_CFLAGS += -fPIC -fpic
endif
endif
-SOEXT_TLS=so.10
+SOEXT_TLS=so.12
SOEXT_X509=so.0
-SOEXT_CRYPTO=so.2
-
-# Set DLEXT=dylib to compile as a shared library for Mac OS X
-DLEXT ?= so
+SOEXT_CRYPTO=so.3
# Set AR_DASH= (empty string) to use an ar implentation that does not accept
# the - prefix for command line options (e.g. llvm-ar)
AR_DASH ?= -
-# Windows shared library extension:
+ARFLAGS = $(AR_DASH)src
+ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
+ARFLAGS = $(AR_DASH)Src
+RLFLAGS = -no_warning_for_no_symbols -c
+RL ?= ranlib
+endif
+endif
+
+DLEXT ?= so
ifdef WINDOWS_BUILD
-DLEXT=dll
+# Windows shared library extension:
+DLEXT = dll
+else ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
+# Mac OS X shared library extension:
+DLEXT = dylib
+endif
endif
OBJS_CRYPTO= aes.o aesni.o arc4.o \
- asn1parse.o asn1write.o base64.o \
- bignum.o blowfish.o camellia.o \
- ccm.o cipher.o cipher_wrap.o \
+ aria.o asn1parse.o asn1write.o \
+ base64.o bignum.o blowfish.o \
+ camellia.o ccm.o chacha20.o \
+ chachapoly.o cipher.o cipher_wrap.o \
cmac.o ctr_drbg.o des.o \
dhm.o ecdh.o ecdsa.o \
ecjpake.o ecp.o \
ecp_curves.o entropy.o entropy_poll.o \
error.o gcm.o havege.o \
+ hkdf.o \
hmac_drbg.o md.o md2.o \
md4.o md5.o md_wrap.o \
- memory_buffer_alloc.o oid.o \
- padlock.o pem.o pk.o \
- pk_wrap.o pkcs12.o pkcs5.o \
- pkparse.o pkwrite.o platform.o \
- platform_util.o ripemd160.o rsa_internal.o \
- rsa.o sha1.o sha256.o \
- sha512.o threading.o timing.o \
- version.o version_features.o \
- xtea.o
+ memory_buffer_alloc.o nist_kw.o \
+ oid.o padlock.o pem.o \
+ pk.o pk_wrap.o pkcs12.o \
+ pkcs5.o pkparse.o pkwrite.o \
+ platform.o platform_util.o poly1305.o \
+ ripemd160.o rsa_internal.o rsa.o \
+ sha1.o sha256.o sha512.o \
+ threading.o timing.o version.o \
+ version_features.o xtea.o
OBJS_X509= certs.o pkcs11.o x509.o \
x509_create.o x509_crl.o x509_crt.o \
@@ -95,9 +113,13 @@ shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT)
# tls
libmbedtls.a: $(OBJS_TLS)
echo " AR $@"
- $(AR) $(AR_DASH)rc $@ $(OBJS_TLS)
+ $(AR) $(ARFLAGS) $@ $(OBJS_TLS)
+ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
echo " RL $@"
- $(AR) $(AR_DASH)s $@
+ $(RL) $(RLFLAGS) $@
+endif
+endif
libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so
echo " LD $@"
@@ -118,9 +140,13 @@ libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll
# x509
libmbedx509.a: $(OBJS_X509)
echo " AR $@"
- $(AR) $(AR_DASH)rc $@ $(OBJS_X509)
+ $(AR) $(ARFLAGS) $@ $(OBJS_X509)
+ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
echo " RL $@"
- $(AR) $(AR_DASH)s $@
+ $(RL) $(RLFLAGS) $@
+endif
+endif
libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so
echo " LD $@"
@@ -141,9 +167,13 @@ libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll
# crypto
libmbedcrypto.a: $(OBJS_CRYPTO)
echo " AR $@"
- $(AR) $(AR_DASH)rc $@ $(OBJS_CRYPTO)
+ $(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO)
+ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
echo " RL $@"
- $(AR) $(AR_DASH)s $@
+ $(RL) $(RLFLAGS) $@
+endif
+endif
libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO)
echo " LD $@"
diff --git a/library/aes.c b/library/aes.c
index b0aea0091b..5c939bba47 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -521,6 +521,20 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx )
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
}
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
+{
+ mbedtls_aes_init( &ctx->crypt );
+ mbedtls_aes_init( &ctx->tweak );
+}
+
+void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx )
+{
+ mbedtls_aes_free( &ctx->crypt );
+ mbedtls_aes_free( &ctx->tweak );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
/*
* AES key schedule (encryption)
*/
@@ -702,6 +716,78 @@ exit:
return( ret );
}
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int mbedtls_aes_xts_decode_keys( const unsigned char *key,
+ unsigned int keybits,
+ const unsigned char **key1,
+ unsigned int *key1bits,
+ const unsigned char **key2,
+ unsigned int *key2bits )
+{
+ const unsigned int half_keybits = keybits / 2;
+ const unsigned int half_keybytes = half_keybits / 8;
+
+ switch( keybits )
+ {
+ case 256: break;
+ case 512: break;
+ default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+ *key1bits = half_keybits;
+ *key2bits = half_keybits;
+ *key1 = &key[0];
+ *key2 = &key[half_keybytes];
+
+ return 0;
+}
+
+int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits)
+{
+ int ret;
+ const unsigned char *key1, *key2;
+ unsigned int key1bits, key2bits;
+
+ ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
+ &key2, &key2bits );
+ if( ret != 0 )
+ return( ret );
+
+ /* Set the tweak key. Always set tweak key for the encryption mode. */
+ ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
+ if( ret != 0 )
+ return( ret );
+
+ /* Set crypt key for encryption. */
+ return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits );
+}
+
+int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits)
+{
+ int ret;
+ const unsigned char *key1, *key2;
+ unsigned int key1bits, key2bits;
+
+ ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
+ &key2, &key2bits );
+ if( ret != 0 )
+ return( ret );
+
+ /* Set the tweak key. Always set tweak key for encryption. */
+ ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
+ if( ret != 0 )
+ return( ret );
+
+ /* Set crypt key for decryption. */
+ return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
@@ -983,6 +1069,165 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+
+/* Endianess with 64 bits values */
+#ifndef GET_UINT64_LE
+#define GET_UINT64_LE(n,b,i) \
+{ \
+ (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \
+ | ( (uint64_t) (b)[(i) + 6] << 48 ) \
+ | ( (uint64_t) (b)[(i) + 5] << 40 ) \
+ | ( (uint64_t) (b)[(i) + 4] << 32 ) \
+ | ( (uint64_t) (b)[(i) + 3] << 24 ) \
+ | ( (uint64_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint64_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint64_t) (b)[(i) ] ); \
+}
+#endif
+
+#ifndef PUT_UINT64_LE
+#define PUT_UINT64_LE(n,b,i) \
+{ \
+ (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \
+ (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \
+ (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \
+ (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+}
+#endif
+
+typedef unsigned char mbedtls_be128[16];
+
+/*
+ * GF(2^128) multiplication function
+ *
+ * This function multiplies a field element by x in the polynomial field
+ * representation. It uses 64-bit word operations to gain speed but compensates
+ * for machine endianess and hence works correctly on both big and little
+ * endian machines.
+ */
+static void mbedtls_gf128mul_x_ble( unsigned char r[16],
+ const unsigned char x[16] )
+{
+ uint64_t a, b, ra, rb;
+
+ GET_UINT64_LE( a, x, 0 );
+ GET_UINT64_LE( b, x, 8 );
+
+ ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
+ rb = ( a >> 63 ) | ( b << 1 );
+
+ PUT_UINT64_LE( ra, r, 0 );
+ PUT_UINT64_LE( rb, r, 8 );
+}
+
+/*
+ * AES-XTS buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char data_unit[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t blocks = length / 16;
+ size_t leftover = length % 16;
+ unsigned char tweak[16];
+ unsigned char prev_tweak[16];
+ unsigned char tmp[16];
+
+ /* Sectors must be at least 16 bytes. */
+ if( length < 16 )
+ return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+
+ /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
+ if( length > ( 1 << 20 ) * 16 )
+ return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+
+ /* Compute the tweak. */
+ ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
+ data_unit, tweak );
+ if( ret != 0 )
+ return( ret );
+
+ while( blocks-- )
+ {
+ size_t i;
+
+ if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
+ {
+ /* We are on the last block in a decrypt operation that has
+ * leftover bytes, so we need to use the next tweak for this block,
+ * and this tweak for the lefover bytes. Save the current tweak for
+ * the leftovers and then update the current tweak for use on this,
+ * the last full block. */
+ memcpy( prev_tweak, tweak, sizeof( tweak ) );
+ mbedtls_gf128mul_x_ble( tweak, tweak );
+ }
+
+ for( i = 0; i < 16; i++ )
+ tmp[i] = input[i] ^ tweak[i];
+
+ ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
+ if( ret != 0 )
+ return( ret );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = tmp[i] ^ tweak[i];
+
+ /* Update the tweak for the next block. */
+ mbedtls_gf128mul_x_ble( tweak, tweak );
+
+ output += 16;
+ input += 16;
+ }
+
+ if( leftover )
+ {
+ /* If we are on the leftover bytes in a decrypt operation, we need to
+ * use the previous tweak for these bytes (as saved in prev_tweak). */
+ unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
+
+ /* We are now on the final part of the data unit, which doesn't divide
+ * evenly by 16. It's time for ciphertext stealing. */
+ size_t i;
+ unsigned char *prev_output = output - 16;
+
+ /* Copy ciphertext bytes from the previous block to our output for each
+ * byte of cyphertext we won't steal. At the same time, copy the
+ * remainder of the input for this final round (since the loop bounds
+ * are the same). */
+ for( i = 0; i < leftover; i++ )
+ {
+ output[i] = prev_output[i];
+ tmp[i] = input[i] ^ t[i];
+ }
+
+ /* Copy ciphertext bytes from the previous block for input in this
+ * round. */
+ for( ; i < 16; i++ )
+ tmp[i] = prev_output[i] ^ t[i];
+
+ ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
+ if( ret != 0 )
+ return ret;
+
+ /* Write the result back to the previous block, overriding the previous
+ * output we copied. */
+ for( i = 0; i < 16; i++ )
+ prev_output[i] = tmp[i] ^ t[i];
+ }
+
+ return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/*
* AES-CFB128 buffer encryption/decryption
@@ -1061,7 +1306,41 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
return( 0 );
}
-#endif /*MBEDTLS_CIPHER_MODE_CFB */
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB (Output Feedback Mode) buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret = 0;
+ size_t n = *iv_off;
+
+ while( length-- )
+ {
+ if( n == 0 )
+ {
+ ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+ if( ret != 0 )
+ goto exit;
+ }
+ *output++ = *input++ ^ iv[n];
+
+ n = ( n + 1 ) & 0x0F;
+ }
+
+ *iv_off = n;
+
+exit:
+ return( ret );
+}
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
@@ -1078,6 +1357,9 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
int c, i;
size_t n = *nc_off;
+ if ( n > 0x0F )
+ return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
+
while( length-- )
{
if( n == 0 ) {
@@ -1215,6 +1497,72 @@ static const unsigned char aes_test_cfb128_ct[3][64] =
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB test vectors from:
+ *
+ * https://csrc.nist.gov/publications/detail/sp/800-38a/final
+ */
+static const unsigned char aes_test_ofb_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_ofb_iv[16] =
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_ofb_pt[64] =
+{
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_ofb_ct[3][64] =
+{
+ { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+ 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+ 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
+ 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+ 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
+ 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+ 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
+ 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },
+ { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+ 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+ 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
+ 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+ 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f,
+ 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+ 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e,
+ 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a },
+ { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+ 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+ 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,
+ 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+ 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed,
+ 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+ 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,
+ 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* AES-CTR test vectors from:
@@ -1278,6 +1626,74 @@ static const int aes_test_ctr_len[3] =
{ 16, 32, 36 };
#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/*
+ * AES-XTS test vectors from:
+ *
+ * IEEE P1619/D16 Annex B
+ * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
+ * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf)
+ */
+static const unsigned char aes_test_xts_key[][32] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+ { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+ 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+};
+
+static const unsigned char aes_test_xts_pt32[][32] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+ { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+};
+
+static const unsigned char aes_test_xts_ct32[][32] =
+{
+ { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+ 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+ 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+ 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+ { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+ 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+ 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+ 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+ { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+ 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+ 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+ 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
+};
+
+static const unsigned char aes_test_xts_data_unit[][16] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+};
+
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
/*
* Checkup routine
*/
@@ -1294,11 +1710,14 @@ int mbedtls_aes_self_test( int verbose )
#if defined(MBEDTLS_CIPHER_MODE_CBC)
unsigned char prv[16];
#endif
-#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB)
+#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
+ defined(MBEDTLS_CIPHER_MODE_OFB)
size_t offset;
#endif
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
+#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS)
int len;
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
unsigned char nonce_counter[16];
unsigned char stream_block[16];
#endif
@@ -1506,6 +1925,69 @@ int mbedtls_aes_self_test( int verbose )
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CFB */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ /*
+ * OFB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
+
+ if( verbose != 0 )
+ mbedtls_printf( " AES-OFB-%3d (%s): ", keybits,
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, aes_test_ofb_iv, 16 );
+ memcpy( key, aes_test_ofb_key[u], keybits / 8 );
+
+ offset = 0;
+ ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDTLS_AES_ALT is defined.
+ */
+ if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+ {
+ mbedtls_printf( "skipped\n" );
+ continue;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ if( mode == MBEDTLS_AES_DECRYPT )
+ {
+ memcpy( buf, aes_test_ofb_ct[u], 64 );
+ aes_tests = aes_test_ofb_pt;
+ }
+ else
+ {
+ memcpy( buf, aes_test_ofb_pt, 64 );
+ aes_tests = aes_test_ofb_ct[u];
+ }
+
+ ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf );
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, aes_tests, 64 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* CTR mode
@@ -1558,6 +2040,73 @@ int mbedtls_aes_self_test( int verbose )
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ {
+ static const int num_tests =
+ sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
+ mbedtls_aes_xts_context ctx_xts;
+
+ /*
+ * XTS mode
+ */
+ mbedtls_aes_xts_init( &ctx_xts );
+
+ for( i = 0; i < num_tests << 1; i++ )
+ {
+ const unsigned char *data_unit;
+ u = i >> 1;
+ mode = i & 1;
+
+ if( verbose != 0 )
+ mbedtls_printf( " AES-XTS-128 (%s): ",
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( key, 0, sizeof( key ) );
+ memcpy( key, aes_test_xts_key[u], 32 );
+ data_unit = aes_test_xts_data_unit[u];
+
+ len = sizeof( *aes_test_xts_ct32 );
+
+ if( mode == MBEDTLS_AES_DECRYPT )
+ {
+ ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 );
+ if( ret != 0)
+ goto exit;
+ memcpy( buf, aes_test_xts_ct32[u], len );
+ aes_tests = aes_test_xts_pt32[u];
+ }
+ else
+ {
+ ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 );
+ if( ret != 0)
+ goto exit;
+ memcpy( buf, aes_test_xts_pt32[u], len );
+ aes_tests = aes_test_xts_ct32[u];
+ }
+
+
+ ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit,
+ buf, buf );
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, aes_tests, len ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ mbedtls_aes_xts_free( &ctx_xts );
+ }
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
ret = 0;
exit:
diff --git a/library/aria.c b/library/aria.c
new file mode 100644
index 0000000000..ca9e147f0d
--- /dev/null
+++ b/library/aria.c
@@ -0,0 +1,1028 @@
+/*
+ * ARIA implementation
+ *
+ * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+/*
+ * This implementation is based on the following standards:
+ * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf
+ * [2] https://tools.ietf.org/html/rfc5794
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_ARIA_C)
+
+#include "mbedtls/aria.h"
+
+#include
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#if !defined(MBEDTLS_ARIA_ALT)
+
+#include "mbedtls/platform_util.h"
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE( n, b, i ) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE( n, b, i ) \
+{ \
+ (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
+ (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
+ (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
+ (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
+}
+#endif
+
+/*
+ * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes
+ *
+ * This is submatrix P1 in [1] Appendix B.1
+ *
+ * Common compilers fail to translate this to minimal number of instructions,
+ * so let's provide asm versions for common platforms with C fallback.
+ */
+#if defined(MBEDTLS_HAVE_ASM)
+#if defined(__arm__) /* rev16 available from v6 up */
+/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
+#if defined(__GNUC__) && \
+ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \
+ __ARM_ARCH >= 6
+static inline uint32_t aria_p1( uint32_t x )
+{
+ uint32_t r;
+ __asm( "rev16 %0, %1" : "=l" (r) : "l" (x) );
+ return( r );
+}
+#define ARIA_P1 aria_p1
+#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \
+ ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 )
+static inline uint32_t aria_p1( uint32_t x )
+{
+ uint32_t r;
+ __asm( "rev16 r, x" );
+ return( r );
+}
+#define ARIA_P1 aria_p1
+#endif
+#endif /* arm */
+#if defined(__GNUC__) && \
+ defined(__i386__) || defined(__amd64__) || defined( __x86_64__)
+/* I couldn't find an Intel equivalent of rev16, so two instructions */
+#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) )
+#endif /* x86 gnuc */
+#endif /* MBEDTLS_HAVE_ASM && GNUC */
+#if !defined(ARIA_P1)
+#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8))
+#endif
+
+/*
+ * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits
+ *
+ * This is submatrix P2 in [1] Appendix B.1
+ *
+ * Common compilers will translate this to a single instruction.
+ */
+#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16))
+
+/*
+ * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness
+ *
+ * This is submatrix P3 in [1] Appendix B.1
+ *
+ * Some compilers fail to translate this to a single instruction,
+ * so let's provide asm versions for common platforms with C fallback.
+ */
+#if defined(MBEDTLS_HAVE_ASM)
+#if defined(__arm__) /* rev available from v6 up */
+/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
+#if defined(__GNUC__) && \
+ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \
+ __ARM_ARCH >= 6
+static inline uint32_t aria_p3( uint32_t x )
+{
+ uint32_t r;
+ __asm( "rev %0, %1" : "=l" (r) : "l" (x) );
+ return( r );
+}
+#define ARIA_P3 aria_p3
+#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \
+ ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 )
+static inline uint32_t aria_p3( uint32_t x )
+{
+ uint32_t r;
+ __asm( "rev r, x" );
+ return( r );
+}
+#define ARIA_P3 aria_p3
+#endif
+#endif /* arm */
+#if defined(__GNUC__) && \
+ defined(__i386__) || defined(__amd64__) || defined( __x86_64__)
+static inline uint32_t aria_p3( uint32_t x )
+{
+ __asm( "bswap %0" : "=r" (x) : "0" (x) );
+ return( x );
+}
+#define ARIA_P3 aria_p3
+#endif /* x86 gnuc */
+#endif /* MBEDTLS_HAVE_ASM && GNUC */
+#if !defined(ARIA_P3)
+#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) )
+#endif
+
+/*
+ * ARIA Affine Transform
+ * (a, b, c, d) = state in/out
+ *
+ * If we denote the first byte of input by 0, ..., the last byte by f,
+ * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef.
+ *
+ * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple
+ * rearrangements on adjacent pairs, output is:
+ *
+ * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe
+ * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd
+ * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd
+ * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc
+ * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe
+ * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc
+ * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef
+ * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef
+ *
+ * Note: another presentation of the A transform can be found as the first
+ * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4.
+ * The implementation below uses only P1 and P2 as they are sufficient.
+ */
+static inline void aria_a( uint32_t *a, uint32_t *b,
+ uint32_t *c, uint32_t *d )
+{
+ uint32_t ta, tb, tc;
+ ta = *b; // 4567
+ *b = *a; // 0123
+ *a = ARIA_P2( ta ); // 6745
+ tb = ARIA_P2( *d ); // efcd
+ *d = ARIA_P1( *c ); // 98ba
+ *c = ARIA_P1( tb ); // fedc
+ ta ^= *d; // 4567+98ba
+ tc = ARIA_P2( *b ); // 2301
+ ta = ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc
+ tb ^= ARIA_P2( *d ); // ba98+efcd
+ tc ^= ARIA_P1( *a ); // 2301+7654
+ *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT
+ tb = ARIA_P2( tb ) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc
+ *a ^= ARIA_P1( tb ); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT
+ ta = ARIA_P2( ta ); // 0123+7654+ab89+dcfe
+ *d ^= ARIA_P1( ta ) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT
+ tc = ARIA_P2( tc ); // 0123+5476
+ *c ^= ARIA_P1( tc ) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT
+}
+
+/*
+ * ARIA Substitution Layer SL1 / SL2
+ * (a, b, c, d) = state in/out
+ * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below)
+ *
+ * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1
+ * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2
+ */
+static inline void aria_sl( uint32_t *a, uint32_t *b,
+ uint32_t *c, uint32_t *d,
+ const uint8_t sa[256], const uint8_t sb[256],
+ const uint8_t sc[256], const uint8_t sd[256] )
+{
+ *a = ( (uint32_t) sa[ *a & 0xFF] ) ^
+ (((uint32_t) sb[(*a >> 8) & 0xFF]) << 8) ^
+ (((uint32_t) sc[(*a >> 16) & 0xFF]) << 16) ^
+ (((uint32_t) sd[ *a >> 24 ]) << 24);
+ *b = ( (uint32_t) sa[ *b & 0xFF] ) ^
+ (((uint32_t) sb[(*b >> 8) & 0xFF]) << 8) ^
+ (((uint32_t) sc[(*b >> 16) & 0xFF]) << 16) ^
+ (((uint32_t) sd[ *b >> 24 ]) << 24);
+ *c = ( (uint32_t) sa[ *c & 0xFF] ) ^
+ (((uint32_t) sb[(*c >> 8) & 0xFF]) << 8) ^
+ (((uint32_t) sc[(*c >> 16) & 0xFF]) << 16) ^
+ (((uint32_t) sd[ *c >> 24 ]) << 24);
+ *d = ( (uint32_t) sa[ *d & 0xFF] ) ^
+ (((uint32_t) sb[(*d >> 8) & 0xFF]) << 8) ^
+ (((uint32_t) sc[(*d >> 16) & 0xFF]) << 16) ^
+ (((uint32_t) sd[ *d >> 24 ]) << 24);
+}
+
+/*
+ * S-Boxes
+ */
+static const uint8_t aria_sb1[256] =
+{
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
+ 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
+ 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
+ 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
+ 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
+ 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
+ 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
+ 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
+ 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
+ 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
+ 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
+ 0xB0, 0x54, 0xBB, 0x16
+};
+
+static const uint8_t aria_sb2[256] =
+{
+ 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46,
+ 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B,
+ 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B,
+ 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB,
+ 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA,
+ 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91,
+ 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38,
+ 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53,
+ 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74,
+ 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26,
+ 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD,
+ 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC,
+ 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E,
+ 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A,
+ 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5,
+ 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8,
+ 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24,
+ 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F,
+ 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33,
+ 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D,
+ 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A,
+ 0xAF, 0xBA, 0xB5, 0x81
+};
+
+static const uint8_t aria_is1[256] =
+{
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
+ 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
+ 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
+ 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
+ 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
+ 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
+ 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
+ 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
+ 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
+ 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
+ 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
+ 0x55, 0x21, 0x0C, 0x7D
+};
+
+static const uint8_t aria_is2[256] =
+{
+ 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1,
+ 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3,
+ 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89,
+ 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D,
+ 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98,
+ 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58,
+ 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F,
+ 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE,
+ 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23,
+ 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19,
+ 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55,
+ 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A,
+ 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE,
+ 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0,
+ 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6,
+ 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5,
+ 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13,
+ 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73,
+ 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94,
+ 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3,
+ 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33,
+ 0x03, 0xA2, 0xAC, 0x60
+};
+
+/*
+ * Helper for key schedule: r = FO( p, k ) ^ x
+ */
+static void aria_fo_xor( uint32_t r[4], const uint32_t p[4],
+ const uint32_t k[4], const uint32_t x[4] )
+{
+ uint32_t a, b, c, d;
+
+ a = p[0] ^ k[0];
+ b = p[1] ^ k[1];
+ c = p[2] ^ k[2];
+ d = p[3] ^ k[3];
+
+ aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 );
+ aria_a( &a, &b, &c, &d );
+
+ r[0] = a ^ x[0];
+ r[1] = b ^ x[1];
+ r[2] = c ^ x[2];
+ r[3] = d ^ x[3];
+}
+
+/*
+ * Helper for key schedule: r = FE( p, k ) ^ x
+ */
+static void aria_fe_xor( uint32_t r[4], const uint32_t p[4],
+ const uint32_t k[4], const uint32_t x[4] )
+{
+ uint32_t a, b, c, d;
+
+ a = p[0] ^ k[0];
+ b = p[1] ^ k[1];
+ c = p[2] ^ k[2];
+ d = p[3] ^ k[3];
+
+ aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 );
+ aria_a( &a, &b, &c, &d );
+
+ r[0] = a ^ x[0];
+ r[1] = b ^ x[1];
+ r[2] = c ^ x[2];
+ r[3] = d ^ x[3];
+}
+
+/*
+ * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup.
+ *
+ * We chose to store bytes into 32-bit words in little-endian format (see
+ * GET/PUT_UINT32_LE) so we need to reverse bytes here.
+ */
+static void aria_rot128( uint32_t r[4], const uint32_t a[4],
+ const uint32_t b[4], uint8_t n )
+{
+ uint8_t i, j;
+ uint32_t t, u;
+
+ const uint8_t n1 = n % 32; // bit offset
+ const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset
+
+ j = ( n / 32 ) % 4; // initial word offset
+ t = ARIA_P3( b[j] ); // big endian
+ for( i = 0; i < 4; i++ )
+ {
+ j = ( j + 1 ) % 4; // get next word, big endian
+ u = ARIA_P3( b[j] );
+ t <<= n1; // rotate
+ t |= u >> n2;
+ t = ARIA_P3( t ); // back to little endian
+ r[i] = a[i] ^ t; // store
+ t = u; // move to next word
+ }
+}
+
+/*
+ * Set encryption key
+ */
+int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx,
+ const unsigned char *key, unsigned int keybits )
+{
+ /* round constant masks */
+ const uint32_t rc[3][4] =
+ {
+ { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA },
+ { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF },
+ { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 }
+ };
+
+ int i;
+ uint32_t w[4][4], *w2;
+
+ if( keybits != 128 && keybits != 192 && keybits != 256 )
+ return( MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH );
+
+ /* Copy key to W0 (and potential remainder to W1) */
+ GET_UINT32_LE( w[0][0], key, 0 );
+ GET_UINT32_LE( w[0][1], key, 4 );
+ GET_UINT32_LE( w[0][2], key, 8 );
+ GET_UINT32_LE( w[0][3], key, 12 );
+
+ memset( w[1], 0, 16 );
+ if( keybits >= 192 )
+ {
+ GET_UINT32_LE( w[1][0], key, 16 ); // 192 bit key
+ GET_UINT32_LE( w[1][1], key, 20 );
+ }
+ if( keybits == 256 )
+ {
+ GET_UINT32_LE( w[1][2], key, 24 ); // 256 bit key
+ GET_UINT32_LE( w[1][3], key, 28 );
+ }
+
+ i = ( keybits - 128 ) >> 6; // index: 0, 1, 2
+ ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16
+
+ aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR
+ i = i < 2 ? i + 1 : 0;
+ aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0
+ i = i < 2 ? i + 1 : 0;
+ aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1
+
+ for( i = 0; i < 4; i++ ) // create round keys
+ {
+ w2 = w[(i + 1) & 3];
+ aria_rot128( ctx->rk[i ], w[i], w2, 128 - 19 );
+ aria_rot128( ctx->rk[i + 4], w[i], w2, 128 - 31 );
+ aria_rot128( ctx->rk[i + 8], w[i], w2, 61 );
+ aria_rot128( ctx->rk[i + 12], w[i], w2, 31 );
+ }
+ aria_rot128( ctx->rk[16], w[0], w[1], 19 );
+
+ /* w holds enough info to reconstruct the round keys */
+ mbedtls_platform_zeroize( w, sizeof( w ) );
+
+ return( 0 );
+}
+
+/*
+ * Set decryption key
+ */
+int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx,
+ const unsigned char *key, unsigned int keybits )
+{
+ int i, j, k, ret;
+
+ ret = mbedtls_aria_setkey_enc( ctx, key, keybits );
+ if( ret != 0 )
+ return( ret );
+
+ /* flip the order of round keys */
+ for( i = 0, j = ctx->nr; i < j; i++, j-- )
+ {
+ for( k = 0; k < 4; k++ )
+ {
+ uint32_t t = ctx->rk[i][k];
+ ctx->rk[i][k] = ctx->rk[j][k];
+ ctx->rk[j][k] = t;
+ }
+ }
+
+ /* apply affine transform to middle keys */
+ for( i = 1; i < ctx->nr; i++ )
+ {
+ aria_a( &ctx->rk[i][0], &ctx->rk[i][1],
+ &ctx->rk[i][2], &ctx->rk[i][3] );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Encrypt a block
+ */
+int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx,
+ const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE],
+ unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] )
+{
+ int i;
+
+ uint32_t a, b, c, d;
+
+ GET_UINT32_LE( a, input, 0 );
+ GET_UINT32_LE( b, input, 4 );
+ GET_UINT32_LE( c, input, 8 );
+ GET_UINT32_LE( d, input, 12 );
+
+ i = 0;
+ while( 1 )
+ {
+ a ^= ctx->rk[i][0];
+ b ^= ctx->rk[i][1];
+ c ^= ctx->rk[i][2];
+ d ^= ctx->rk[i][3];
+ i++;
+
+ aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 );
+ aria_a( &a, &b, &c, &d );
+
+ a ^= ctx->rk[i][0];
+ b ^= ctx->rk[i][1];
+ c ^= ctx->rk[i][2];
+ d ^= ctx->rk[i][3];
+ i++;
+
+ aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 );
+ if( i >= ctx->nr )
+ break;
+ aria_a( &a, &b, &c, &d );
+ }
+
+ /* final key mixing */
+ a ^= ctx->rk[i][0];
+ b ^= ctx->rk[i][1];
+ c ^= ctx->rk[i][2];
+ d ^= ctx->rk[i][3];
+
+ PUT_UINT32_LE( a, output, 0 );
+ PUT_UINT32_LE( b, output, 4 );
+ PUT_UINT32_LE( c, output, 8 );
+ PUT_UINT32_LE( d, output, 12 );
+
+ return( 0 );
+}
+
+/* Initialize context */
+void mbedtls_aria_init( mbedtls_aria_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedtls_aria_context ) );
+}
+
+/* Clear context */
+void mbedtls_aria_free( mbedtls_aria_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) );
+}
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+/*
+ * ARIA-CBC buffer encryption/decryption
+ */
+int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int i;
+ unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE];
+
+ if( length % MBEDTLS_ARIA_BLOCKSIZE )
+ return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH );
+
+ if( mode == MBEDTLS_ARIA_DECRYPT )
+ {
+ while( length > 0 )
+ {
+ memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE );
+ mbedtls_aria_crypt_ecb( ctx, input, output );
+
+ for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ )
+ output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+ memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE );
+
+ input += MBEDTLS_ARIA_BLOCKSIZE;
+ output += MBEDTLS_ARIA_BLOCKSIZE;
+ length -= MBEDTLS_ARIA_BLOCKSIZE;
+ }
+ }
+ else
+ {
+ while( length > 0 )
+ {
+ for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ )
+ output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+ mbedtls_aria_crypt_ecb( ctx, output, output );
+ memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE );
+
+ input += MBEDTLS_ARIA_BLOCKSIZE;
+ output += MBEDTLS_ARIA_BLOCKSIZE;
+ length -= MBEDTLS_ARIA_BLOCKSIZE;
+ }
+ }
+
+ return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+/*
+ * ARIA-CFB128 buffer encryption/decryption
+ */
+int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx,
+ int mode,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ unsigned char c;
+ size_t n = *iv_off;
+
+ if( mode == MBEDTLS_ARIA_DECRYPT )
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ mbedtls_aria_crypt_ecb( ctx, iv, iv );
+
+ c = *input++;
+ *output++ = c ^ iv[n];
+ iv[n] = c;
+
+ n = ( n + 1 ) & 0x0F;
+ }
+ }
+ else
+ {
+ while( length-- )
+ {
+ if( n == 0 )
+ mbedtls_aria_crypt_ecb( ctx, iv, iv );
+
+ iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+ n = ( n + 1 ) & 0x0F;
+ }
+ }
+
+ *iv_off = n;
+
+ return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/*
+ * ARIA-CTR buffer encryption/decryption
+ */
+int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx,
+ size_t length,
+ size_t *nc_off,
+ unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE],
+ unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int c, i;
+ size_t n = *nc_off;
+
+ while( length-- )
+ {
+ if( n == 0 ) {
+ mbedtls_aria_crypt_ecb( ctx, nonce_counter,
+ stream_block );
+
+ for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- )
+ if( ++nonce_counter[i - 1] != 0 )
+ break;
+ }
+ c = *input++;
+ *output++ = (unsigned char)( c ^ stream_block[n] );
+
+ n = ( n + 1 ) & 0x0F;
+ }
+
+ *nc_off = n;
+
+ return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#endif /* !MBEDTLS_ARIA_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+/*
+ * Basic ARIA ECB test vectors from RFC 5794
+ */
+static const uint8_t aria_test1_ecb_key[32] = // test key
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit
+};
+
+static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext
+{
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all
+ 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes
+};
+
+static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext
+{
+ { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit
+ 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 },
+ { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit
+ 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 },
+ { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit
+ 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC }
+};
+
+/*
+ * Mode tests from "Test Vectors for ARIA" Version 1.0
+ * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf
+ */
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
+ defined(MBEDTLS_CIPHER_MODE_CTR))
+static const uint8_t aria_test2_key[32] =
+{
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit
+};
+
+static const uint8_t aria_test2_pt[48] =
+{
+ 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all
+ 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc,
+ 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb,
+};
+#endif
+
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB))
+static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] =
+{
+ 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB
+ 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV
+};
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext
+{
+ { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key
+ 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34,
+ 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64,
+ 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38,
+ 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c,
+ 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 },
+ { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key
+ 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f,
+ 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1,
+ 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5,
+ 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92,
+ 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e },
+ { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key
+ 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab,
+ 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef,
+ 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52,
+ 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5,
+ 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b }
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext
+{
+ { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key
+ 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00,
+ 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a,
+ 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01,
+ 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96,
+ 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b },
+ { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key
+ 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c,
+ 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94,
+ 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59,
+ 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86,
+ 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b },
+ { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key
+ 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35,
+ 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70,
+ 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa,
+ 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c,
+ 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext
+{
+ { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key
+ 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1,
+ 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1,
+ 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f,
+ 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71,
+ 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 },
+ { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key
+ 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce,
+ 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde,
+ 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79,
+ 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce,
+ 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf },
+ { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key
+ 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2,
+ 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89,
+ 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f,
+ 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7,
+ 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#define ARIA_SELF_TEST_IF_FAIL \
+ { \
+ if( verbose ) \
+ mbedtls_printf( "failed\n" ); \
+ return( 1 ); \
+ } else { \
+ if( verbose ) \
+ mbedtls_printf( "passed\n" ); \
+ }
+
+/*
+ * Checkup routine
+ */
+int mbedtls_aria_self_test( int verbose )
+{
+ int i;
+ uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE];
+ mbedtls_aria_context ctx;
+
+#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR))
+ size_t j;
+#endif
+
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \
+ defined(MBEDTLS_CIPHER_MODE_CFB) || \
+ defined(MBEDTLS_CIPHER_MODE_CTR))
+ uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE];
+#endif
+
+ /*
+ * Test set 1
+ */
+ for( i = 0; i < 3; i++ )
+ {
+ /* test ECB encryption */
+ if( verbose )
+ mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i );
+ mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i );
+ mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk );
+ if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
+ ARIA_SELF_TEST_IF_FAIL;
+
+ /* test ECB decryption */
+ if( verbose )
+ mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i );
+ mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i );
+ mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk );
+ if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
+ ARIA_SELF_TEST_IF_FAIL;
+ }
+ if( verbose )
+ mbedtls_printf( "\n" );
+
+ /*
+ * Test set 2
+ */
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ for( i = 0; i < 3; i++ )
+ {
+ /* Test CBC encryption */
+ if( verbose )
+ mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i );
+ mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
+ memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
+ memset( buf, 0x55, sizeof( buf ) );
+ mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv,
+ aria_test2_pt, buf );
+ if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 )
+ ARIA_SELF_TEST_IF_FAIL;
+
+ /* Test CBC decryption */
+ if( verbose )
+ mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i );
+ mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i );
+ memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
+ memset( buf, 0xAA, sizeof( buf ) );
+ mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv,
+ aria_test2_cbc_ct[i], buf );
+ if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
+ ARIA_SELF_TEST_IF_FAIL;
+ }
+ if( verbose )
+ mbedtls_printf( "\n" );
+
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ for( i = 0; i < 3; i++ )
+ {
+ /* Test CFB encryption */
+ if( verbose )
+ mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i );
+ mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
+ memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
+ memset( buf, 0x55, sizeof( buf ) );
+ j = 0;
+ mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv,
+ aria_test2_pt, buf );
+ if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 )
+ ARIA_SELF_TEST_IF_FAIL;
+
+ /* Test CFB decryption */
+ if( verbose )
+ mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i );
+ mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
+ memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
+ memset( buf, 0xAA, sizeof( buf ) );
+ j = 0;
+ mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j,
+ iv, aria_test2_cfb_ct[i], buf );
+ if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
+ ARIA_SELF_TEST_IF_FAIL;
+ }
+ if( verbose )
+ mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ for( i = 0; i < 3; i++ )
+ {
+ /* Test CTR encryption */
+ if( verbose )
+ mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i );
+ mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
+ memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0
+ memset( buf, 0x55, sizeof( buf ) );
+ j = 0;
+ mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
+ aria_test2_pt, buf );
+ if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 )
+ ARIA_SELF_TEST_IF_FAIL;
+
+ /* Test CTR decryption */
+ if( verbose )
+ mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i );
+ mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
+ memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0
+ memset( buf, 0xAA, sizeof( buf ) );
+ j = 0;
+ mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
+ aria_test2_ctr_ct[i], buf );
+ if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
+ ARIA_SELF_TEST_IF_FAIL;
+ }
+ if( verbose )
+ mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+ return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_ARIA_C */
diff --git a/library/asn1write.c b/library/asn1write.c
index 957d69f545..d617de5b07 100644
--- a/library/asn1write.c
+++ b/library/asn1write.c
@@ -83,7 +83,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len
return( 4 );
}
+#if SIZE_MAX > 0xFFFFFFFF
if( len <= 0xFFFFFFFF )
+#endif
{
if( *p - start < 5 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
@@ -96,7 +98,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len
return( 5 );
}
+#if SIZE_MAX > 0xFFFFFFFF
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+#endif
}
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
diff --git a/library/ccm.c b/library/ccm.c
index cf6520935e..90cab8e147 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -152,8 +152,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
* Check length requirements: SP800-38C A.1
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
* 'length' checked later (when writing it to the first block)
+ *
+ * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
*/
- if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
+ if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
/* Also implies q is within bounds */
@@ -302,7 +304,7 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
/*
* Authenticated encryption
*/
-int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
@@ -312,10 +314,23 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
add, add_len, input, output, tag, tag_len ) );
}
+int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ unsigned char *tag, size_t tag_len )
+{
+ if( tag_len == 0 )
+ return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+ return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
+ add_len, input, output, tag, tag_len ) );
+}
+
/*
* Authenticated decryption
*/
-int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
@@ -346,6 +361,18 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
return( 0 );
}
+int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *add, size_t add_len,
+ const unsigned char *input, unsigned char *output,
+ const unsigned char *tag, size_t tag_len )
+{
+ if( tag_len == 0 )
+ return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+ return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
+ add_len, input, output, tag, tag_len ) );
+}
#endif /* !MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
@@ -354,7 +381,8 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
*/
#define NB_TESTS 3
-
+#define CCM_SELFTEST_PT_MAX_LEN 24
+#define CCM_SELFTEST_CT_MAX_LEN 32
/*
* The data is the same for all tests, only the used length changes
*/
@@ -374,7 +402,7 @@ static const unsigned char ad[] = {
0x10, 0x11, 0x12, 0x13
};
-static const unsigned char msg[] = {
+static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = {
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
@@ -385,7 +413,7 @@ static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
-static const unsigned char res[NB_TESTS][32] = {
+static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
{ 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
{ 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
@@ -399,7 +427,13 @@ static const unsigned char res[NB_TESTS][32] = {
int mbedtls_ccm_self_test( int verbose )
{
mbedtls_ccm_context ctx;
- unsigned char out[32];
+ /*
+ * Some hardware accelerators require the input and output buffers
+ * would be in RAM, because the flash is not accessible.
+ * Use buffers on the stack to hold the test vectors data.
+ */
+ unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
+ unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
size_t i;
int ret;
@@ -418,27 +452,32 @@ int mbedtls_ccm_self_test( int verbose )
if( verbose != 0 )
mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
+ memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
+ memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN );
+ memcpy( plaintext, msg, msg_len[i] );
+
ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
- iv, iv_len[i], ad, add_len[i],
- msg, out,
- out + msg_len[i], tag_len[i] );
+ iv, iv_len[i], ad, add_len[i],
+ plaintext, ciphertext,
+ ciphertext + msg_len[i], tag_len[i] );
if( ret != 0 ||
- memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
+ memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
+ memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
- iv, iv_len[i], ad, add_len[i],
- res[i], out,
- res[i] + msg_len[i], tag_len[i] );
+ iv, iv_len[i], ad, add_len[i],
+ ciphertext, plaintext,
+ ciphertext + msg_len[i], tag_len[i] );
if( ret != 0 ||
- memcmp( out, msg, msg_len[i] ) != 0 )
+ memcmp( plaintext, msg, msg_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
diff --git a/library/chacha20.c b/library/chacha20.c
new file mode 100644
index 0000000000..d14a51e044
--- /dev/null
+++ b/library/chacha20.c
@@ -0,0 +1,570 @@
+/**
+ * \file chacha20.c
+ *
+ * \brief ChaCha20 cipher.
+ *
+ * \author Daniel King
+ *
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CHACHA20_C)
+
+#include "mbedtls/chacha20.h"
+#include "mbedtls/platform_util.h"
+
+#include
+#include
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#if !defined(MBEDTLS_CHACHA20_ALT)
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#define BYTES_TO_U32_LE( data, offset ) \
+ ( (uint32_t) data[offset] \
+ | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
+ | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \
+ | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \
+ )
+
+#define ROTL32( value, amount ) \
+ ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
+
+#define CHACHA20_CTR_INDEX ( 12U )
+
+#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
+
+/**
+ * \brief ChaCha20 quarter round operation.
+ *
+ * The quarter round is defined as follows (from RFC 7539):
+ * 1. a += b; d ^= a; d <<<= 16;
+ * 2. c += d; b ^= c; b <<<= 12;
+ * 3. a += b; d ^= a; d <<<= 8;
+ * 4. c += d; b ^= c; b <<<= 7;
+ *
+ * \param state ChaCha20 state to modify.
+ * \param a The index of 'a' in the state.
+ * \param b The index of 'b' in the state.
+ * \param c The index of 'c' in the state.
+ * \param d The index of 'd' in the state.
+ */
+static inline void chacha20_quarter_round( uint32_t state[16],
+ size_t a,
+ size_t b,
+ size_t c,
+ size_t d )
+{
+ /* a += b; d ^= a; d <<<= 16; */
+ state[a] += state[b];
+ state[d] ^= state[a];
+ state[d] = ROTL32( state[d], 16 );
+
+ /* c += d; b ^= c; b <<<= 12 */
+ state[c] += state[d];
+ state[b] ^= state[c];
+ state[b] = ROTL32( state[b], 12 );
+
+ /* a += b; d ^= a; d <<<= 8; */
+ state[a] += state[b];
+ state[d] ^= state[a];
+ state[d] = ROTL32( state[d], 8 );
+
+ /* c += d; b ^= c; b <<<= 7; */
+ state[c] += state[d];
+ state[b] ^= state[c];
+ state[b] = ROTL32( state[b], 7 );
+}
+
+/**
+ * \brief Perform the ChaCha20 inner block operation.
+ *
+ * This function performs two rounds: the column round and the
+ * diagonal round.
+ *
+ * \param state The ChaCha20 state to update.
+ */
+static void chacha20_inner_block( uint32_t state[16] )
+{
+ chacha20_quarter_round( state, 0, 4, 8, 12 );
+ chacha20_quarter_round( state, 1, 5, 9, 13 );
+ chacha20_quarter_round( state, 2, 6, 10, 14 );
+ chacha20_quarter_round( state, 3, 7, 11, 15 );
+
+ chacha20_quarter_round( state, 0, 5, 10, 15 );
+ chacha20_quarter_round( state, 1, 6, 11, 12 );
+ chacha20_quarter_round( state, 2, 7, 8, 13 );
+ chacha20_quarter_round( state, 3, 4, 9, 14 );
+}
+
+/**
+ * \brief Generates a keystream block.
+ *
+ * \param initial_state The initial ChaCha20 state (key, nonce, counter).
+ * \param keystream Generated keystream bytes are written to this buffer.
+ */
+static void chacha20_block( const uint32_t initial_state[16],
+ unsigned char keystream[64] )
+{
+ uint32_t working_state[16];
+ size_t i;
+
+ memcpy( working_state,
+ initial_state,
+ CHACHA20_BLOCK_SIZE_BYTES );
+
+ for( i = 0U; i < 10U; i++ )
+ chacha20_inner_block( working_state );
+
+ working_state[ 0] += initial_state[ 0];
+ working_state[ 1] += initial_state[ 1];
+ working_state[ 2] += initial_state[ 2];
+ working_state[ 3] += initial_state[ 3];
+ working_state[ 4] += initial_state[ 4];
+ working_state[ 5] += initial_state[ 5];
+ working_state[ 6] += initial_state[ 6];
+ working_state[ 7] += initial_state[ 7];
+ working_state[ 8] += initial_state[ 8];
+ working_state[ 9] += initial_state[ 9];
+ working_state[10] += initial_state[10];
+ working_state[11] += initial_state[11];
+ working_state[12] += initial_state[12];
+ working_state[13] += initial_state[13];
+ working_state[14] += initial_state[14];
+ working_state[15] += initial_state[15];
+
+ for( i = 0U; i < 16; i++ )
+ {
+ size_t offset = i * 4U;
+
+ keystream[offset ] = (unsigned char)( working_state[i] );
+ keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 );
+ keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
+ keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
+ }
+
+ mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
+}
+
+void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
+{
+ if( ctx != NULL )
+ {
+ mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
+ mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
+
+ /* Initially, there's no keystream bytes available */
+ ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
+ }
+}
+
+void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
+{
+ if( ctx != NULL )
+ {
+ mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
+ }
+}
+
+int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
+ const unsigned char key[32] )
+{
+ if( ( ctx == NULL ) || ( key == NULL ) )
+ {
+ return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+ }
+
+ /* ChaCha20 constants - the string "expand 32-byte k" */
+ ctx->state[0] = 0x61707865;
+ ctx->state[1] = 0x3320646e;
+ ctx->state[2] = 0x79622d32;
+ ctx->state[3] = 0x6b206574;
+
+ /* Set key */
+ ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
+ ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
+ ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
+ ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
+ ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
+ ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
+ ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
+ ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
+
+ return( 0 );
+}
+
+int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
+ const unsigned char nonce[12],
+ uint32_t counter )
+{
+ if( ( ctx == NULL ) || ( nonce == NULL ) )
+ {
+ return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+ }
+
+ /* Counter */
+ ctx->state[12] = counter;
+
+ /* Nonce */
+ ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
+ ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
+ ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
+
+ mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
+
+ /* Initially, there's no keystream bytes available */
+ ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
+
+ return( 0 );
+}
+
+int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
+ size_t size,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ size_t offset = 0U;
+ size_t i;
+
+ if( ctx == NULL )
+ {
+ return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+ }
+ else if( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
+ {
+ /* input and output pointers are allowed to be NULL only if size == 0 */
+ return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+ }
+
+ /* Use leftover keystream bytes, if available */
+ while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
+ {
+ output[offset] = input[offset]
+ ^ ctx->keystream8[ctx->keystream_bytes_used];
+
+ ctx->keystream_bytes_used++;
+ offset++;
+ size--;
+ }
+
+ /* Process full blocks */
+ while( size >= CHACHA20_BLOCK_SIZE_BYTES )
+ {
+ /* Generate new keystream block and increment counter */
+ chacha20_block( ctx->state, ctx->keystream8 );
+ ctx->state[CHACHA20_CTR_INDEX]++;
+
+ for( i = 0U; i < 64U; i += 8U )
+ {
+ output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
+ output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
+ output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
+ output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
+ output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
+ output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
+ output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
+ output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
+ }
+
+ offset += CHACHA20_BLOCK_SIZE_BYTES;
+ size -= CHACHA20_BLOCK_SIZE_BYTES;
+ }
+
+ /* Last (partial) block */
+ if( size > 0U )
+ {
+ /* Generate new keystream block and increment counter */
+ chacha20_block( ctx->state, ctx->keystream8 );
+ ctx->state[CHACHA20_CTR_INDEX]++;
+
+ for( i = 0U; i < size; i++)
+ {
+ output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
+ }
+
+ ctx->keystream_bytes_used = size;
+
+ }
+
+ return( 0 );
+}
+
+int mbedtls_chacha20_crypt( const unsigned char key[32],
+ const unsigned char nonce[12],
+ uint32_t counter,
+ size_t data_len,
+ const unsigned char* input,
+ unsigned char* output )
+{
+ mbedtls_chacha20_context ctx;
+ int ret;
+
+ mbedtls_chacha20_init( &ctx );
+
+ ret = mbedtls_chacha20_setkey( &ctx, key );
+ if( ret != 0 )
+ goto cleanup;
+
+ ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
+ if( ret != 0 )
+ goto cleanup;
+
+ ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
+
+cleanup:
+ mbedtls_chacha20_free( &ctx );
+ return( ret );
+}
+
+#endif /* !MBEDTLS_CHACHA20_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char test_keys[2][32] =
+{
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+ }
+};
+
+static const unsigned char test_nonces[2][12] =
+{
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02
+ }
+};
+
+static const uint32_t test_counters[2] =
+{
+ 0U,
+ 1U
+};
+
+static const unsigned char test_input[2][375] =
+{
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ {
+ 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
+ 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
+ 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
+ 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
+ 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
+ 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
+ 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
+ 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
+ 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
+ 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
+ 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
+ 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+ 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
+ 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
+ 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
+ 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
+ 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+ 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
+ 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
+ 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
+ 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
+ }
+};
+
+static const unsigned char test_output[2][375] =
+{
+ {
+ 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+ 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+ 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+ 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
+ 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
+ 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
+ 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
+ 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
+ },
+ {
+ 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
+ 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
+ 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
+ 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
+ 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
+ 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
+ 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
+ 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
+ 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
+ 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
+ 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
+ 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
+ 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
+ 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
+ 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
+ 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
+ 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
+ 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
+ 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
+ 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
+ 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
+ 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
+ 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
+ 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
+ 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
+ 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
+ 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
+ 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
+ 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
+ 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
+ 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
+ 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
+ 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
+ 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
+ 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
+ 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
+ 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
+ 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
+ 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
+ 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
+ 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
+ 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
+ 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
+ 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
+ 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
+ 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
+ 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
+ }
+};
+
+static const size_t test_lengths[2] =
+{
+ 64U,
+ 375U
+};
+
+#define ASSERT( cond, args ) \
+ do \
+ { \
+ if( ! ( cond ) ) \
+ { \
+ if( verbose != 0 ) \
+ mbedtls_printf args; \
+ \
+ return( -1 ); \
+ } \
+ } \
+ while( 0 )
+
+int mbedtls_chacha20_self_test( int verbose )
+{
+ unsigned char output[381];
+ unsigned i;
+ int ret;
+
+ for( i = 0U; i < 2U; i++ )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " ChaCha20 test %u ", i );
+
+ ret = mbedtls_chacha20_crypt( test_keys[i],
+ test_nonces[i],
+ test_counters[i],
+ test_lengths[i],
+ test_input[i],
+ output );
+
+ ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
+
+ ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
+ ( "failed (output)\n" ) );
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* !MBEDTLS_CHACHA20_C */
diff --git a/library/chachapoly.c b/library/chachapoly.c
new file mode 100644
index 0000000000..860f877653
--- /dev/null
+++ b/library/chachapoly.c
@@ -0,0 +1,547 @@
+/**
+ * \file chachapoly.c
+ *
+ * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
+ *
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+
+#include "mbedtls/chachapoly.h"
+#include "mbedtls/platform_util.h"
+
+#include
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#if !defined(MBEDTLS_CHACHAPOLY_ALT)
+
+#define CHACHAPOLY_STATE_INIT ( 0 )
+#define CHACHAPOLY_STATE_AAD ( 1 )
+#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
+#define CHACHAPOLY_STATE_FINISHED ( 3 )
+
+/**
+ * \brief Adds nul bytes to pad the AAD for Poly1305.
+ *
+ * \param ctx The ChaCha20-Poly1305 context.
+ */
+static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
+{
+ uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
+ unsigned char zeroes[15];
+
+ if( partial_block_len == 0U )
+ return( 0 );
+
+ memset( zeroes, 0, sizeof( zeroes ) );
+
+ return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
+ zeroes,
+ 16U - partial_block_len ) );
+}
+
+/**
+ * \brief Adds nul bytes to pad the ciphertext for Poly1305.
+ *
+ * \param ctx The ChaCha20-Poly1305 context.
+ */
+static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
+{
+ uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
+ unsigned char zeroes[15];
+
+ if( partial_block_len == 0U )
+ return( 0 );
+
+ memset( zeroes, 0, sizeof( zeroes ) );
+ return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
+ zeroes,
+ 16U - partial_block_len ) );
+}
+
+void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
+{
+ if( ctx != NULL )
+ {
+ mbedtls_chacha20_init( &ctx->chacha20_ctx );
+ mbedtls_poly1305_init( &ctx->poly1305_ctx );
+ ctx->aad_len = 0U;
+ ctx->ciphertext_len = 0U;
+ ctx->state = CHACHAPOLY_STATE_INIT;
+ ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
+ }
+}
+
+void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
+{
+ if( ctx != NULL )
+ {
+ mbedtls_chacha20_free( &ctx->chacha20_ctx );
+ mbedtls_poly1305_free( &ctx->poly1305_ctx );
+ ctx->aad_len = 0U;
+ ctx->ciphertext_len = 0U;
+ ctx->state = CHACHAPOLY_STATE_INIT;
+ ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
+ }
+}
+
+int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
+ const unsigned char key[32] )
+{
+ int ret;
+
+ if( ( ctx == NULL ) || ( key == NULL ) )
+ {
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+
+ ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
+
+ return( ret );
+}
+
+int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
+ const unsigned char nonce[12],
+ mbedtls_chachapoly_mode_t mode )
+{
+ int ret;
+ unsigned char poly1305_key[64];
+
+ if( ( ctx == NULL ) || ( nonce == NULL ) )
+ {
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+
+ /* Set counter = 0, will be update to 1 when generating Poly1305 key */
+ ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
+ if( ret != 0 )
+ goto cleanup;
+
+ /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
+ * counter = 0. This is the same as encrypting a buffer of zeroes.
+ * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
+ * The other 256 bits are discarded.
+ */
+ memset( poly1305_key, 0, sizeof( poly1305_key ) );
+ ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
+ poly1305_key, poly1305_key );
+ if( ret != 0 )
+ goto cleanup;
+
+ ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
+
+ if( ret == 0 )
+ {
+ ctx->aad_len = 0U;
+ ctx->ciphertext_len = 0U;
+ ctx->state = CHACHAPOLY_STATE_AAD;
+ ctx->mode = mode;
+ }
+
+cleanup:
+ mbedtls_platform_zeroize( poly1305_key, 64U );
+ return( ret );
+}
+
+int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
+ const unsigned char *aad,
+ size_t aad_len )
+{
+ if( ctx == NULL )
+ {
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+ else if( ( aad_len > 0U ) && ( aad == NULL ) )
+ {
+ /* aad pointer is allowed to be NULL if aad_len == 0 */
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+ else if( ctx->state != CHACHAPOLY_STATE_AAD )
+ {
+ return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+ }
+
+ ctx->aad_len += aad_len;
+
+ return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
+}
+
+int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
+ size_t len,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+
+ if( ctx == NULL )
+ {
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+ else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
+ {
+ /* input and output pointers are allowed to be NULL if len == 0 */
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+ else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
+ ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
+ {
+ return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+ }
+
+ if( ctx->state == CHACHAPOLY_STATE_AAD )
+ {
+ ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
+
+ ret = chachapoly_pad_aad( ctx );
+ if( ret != 0 )
+ return( ret );
+ }
+
+ ctx->ciphertext_len += len;
+
+ if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
+ {
+ ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
+ if( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
+ if( ret != 0 )
+ return( ret );
+ }
+ else /* DECRYPT */
+ {
+ ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
+ if( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
+ if( ret != 0 )
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
+ unsigned char mac[16] )
+{
+ int ret;
+ unsigned char len_block[16];
+
+ if( ( ctx == NULL ) || ( mac == NULL ) )
+ {
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+ else if( ctx->state == CHACHAPOLY_STATE_INIT )
+ {
+ return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+ }
+
+ if( ctx->state == CHACHAPOLY_STATE_AAD )
+ {
+ ret = chachapoly_pad_aad( ctx );
+ if( ret != 0 )
+ return( ret );
+ }
+ else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
+ {
+ ret = chachapoly_pad_ciphertext( ctx );
+ if( ret != 0 )
+ return( ret );
+ }
+
+ ctx->state = CHACHAPOLY_STATE_FINISHED;
+
+ /* The lengths of the AAD and ciphertext are processed by
+ * Poly1305 as the final 128-bit block, encoded as little-endian integers.
+ */
+ len_block[ 0] = (unsigned char)( ctx->aad_len );
+ len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
+ len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
+ len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
+ len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
+ len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
+ len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
+ len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
+ len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
+ len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
+ len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
+ len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
+ len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
+ len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
+ len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
+ len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
+
+ ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
+ if( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
+
+ return( ret );
+}
+
+static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
+ mbedtls_chachapoly_mode_t mode,
+ size_t length,
+ const unsigned char nonce[12],
+ const unsigned char *aad,
+ size_t aad_len,
+ const unsigned char *input,
+ unsigned char *output,
+ unsigned char tag[16] )
+{
+ int ret;
+
+ ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
+ if( ret != 0 )
+ goto cleanup;
+
+ ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
+ if( ret != 0 )
+ goto cleanup;
+
+ ret = mbedtls_chachapoly_update( ctx, length, input, output );
+ if( ret != 0 )
+ goto cleanup;
+
+ ret = mbedtls_chachapoly_finish( ctx, tag );
+
+cleanup:
+ return( ret );
+}
+
+int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
+ size_t length,
+ const unsigned char nonce[12],
+ const unsigned char *aad,
+ size_t aad_len,
+ const unsigned char *input,
+ unsigned char *output,
+ unsigned char tag[16] )
+{
+ return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
+ length, nonce, aad, aad_len,
+ input, output, tag ) );
+}
+
+int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
+ size_t length,
+ const unsigned char nonce[12],
+ const unsigned char *aad,
+ size_t aad_len,
+ const unsigned char tag[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ unsigned char check_tag[16];
+ size_t i;
+ int diff;
+
+ if( tag == NULL )
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+ if( ( ret = chachapoly_crypt_and_tag( ctx,
+ MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
+ aad, aad_len, input, output, check_tag ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* Check tag in "constant-time" */
+ for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
+ diff |= tag[i] ^ check_tag[i];
+
+ if( diff != 0 )
+ {
+ mbedtls_platform_zeroize( output, length );
+ return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
+ }
+
+ return( 0 );
+}
+
+#endif /* MBEDTLS_CHACHAPOLY_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char test_key[1][32] =
+{
+ {
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
+ }
+};
+
+static const unsigned char test_nonce[1][12] =
+{
+ {
+ 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
+ }
+};
+
+static const unsigned char test_aad[1][12] =
+{
+ {
+ 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7
+ }
+};
+
+static const size_t test_aad_len[1] =
+{
+ 12U
+};
+
+static const unsigned char test_input[1][114] =
+{
+ {
+ 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
+ 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
+ 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
+ 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
+ 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
+ 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
+ 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
+ 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
+ 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
+ 0x74, 0x2e
+ }
+};
+
+static const unsigned char test_output[1][114] =
+{
+ {
+ 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
+ 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
+ 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
+ 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
+ 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
+ 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
+ 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
+ 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
+ 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
+ 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
+ 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
+ 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
+ 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
+ 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
+ 0x61, 0x16
+ }
+};
+
+static const size_t test_input_len[1] =
+{
+ 114U
+};
+
+static const unsigned char test_mac[1][16] =
+{
+ {
+ 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
+ 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
+ }
+};
+
+#define ASSERT( cond, args ) \
+ do \
+ { \
+ if( ! ( cond ) ) \
+ { \
+ if( verbose != 0 ) \
+ mbedtls_printf args; \
+ \
+ return( -1 ); \
+ } \
+ } \
+ while( 0 )
+
+int mbedtls_chachapoly_self_test( int verbose )
+{
+ mbedtls_chachapoly_context ctx;
+ unsigned i;
+ int ret;
+ unsigned char output[200];
+ unsigned char mac[16];
+
+ for( i = 0U; i < 1U; i++ )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
+
+ mbedtls_chachapoly_init( &ctx );
+
+ ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
+ ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
+
+ ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
+ test_input_len[i],
+ test_nonce[i],
+ test_aad[i],
+ test_aad_len[i],
+ test_input[i],
+ output,
+ mac );
+
+ ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
+
+ ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
+ ( "failure (wrong output)\n" ) );
+
+ ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
+ ( "failure (wrong MAC)\n" ) );
+
+ mbedtls_chachapoly_free( &ctx );
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_CHACHAPOLY_C */
diff --git a/library/cipher.c b/library/cipher.c
index a5cd61cdf3..d7acf34ee5 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -38,6 +38,10 @@
#include
#include
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#include "mbedtls/chachapoly.h"
+#endif
+
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
@@ -46,6 +50,10 @@
#include "mbedtls/ccm.h"
#endif
+#if defined(MBEDTLS_CHACHA20_C)
+#include "mbedtls/chacha20.h"
+#endif
+
#if defined(MBEDTLS_CMAC_C)
#include "mbedtls/cmac.h"
#endif
@@ -57,9 +65,25 @@
#define mbedtls_free free
#endif
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#define MBEDTLS_CIPHER_MODE_STREAM
-#endif
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
+/* Compare the contents of two buffers in constant time.
+ * Returns 0 if the contents are bitwise identical, otherwise returns
+ * a non-zero value.
+ * This is currently only used by GCM and ChaCha20+Poly1305.
+ */
+static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len )
+{
+ const unsigned char *p1 = (const unsigned char*) v1;
+ const unsigned char *p2 = (const unsigned char*) v2;
+ size_t i;
+ unsigned char diff;
+
+ for( diff = 0, i = 0; i < len; i++ )
+ diff |= p1[i] ^ p2[i];
+
+ return (int)diff;
+}
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
static int supported_init = 0;
@@ -191,10 +215,11 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k
ctx->operation = operation;
/*
- * For CFB and CTR mode always use the encryption key schedule
+ * For OFB, CFB and CTR mode always use the encryption key schedule
*/
if( MBEDTLS_ENCRYPT == operation ||
MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
{
return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
@@ -212,9 +237,13 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len )
{
size_t actual_iv_size;
-
- if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+ if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ else if( NULL == iv && iv_len != 0 )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( NULL == iv && iv_len == 0 )
+ ctx->iv_size = 0;
/* avoid buffer overflow in ctx->iv */
if( iv_len > MBEDTLS_MAX_IV_LENGTH )
@@ -231,8 +260,23 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
- memcpy( ctx->iv, iv, actual_iv_size );
- ctx->iv_size = actual_iv_size;
+#if defined(MBEDTLS_CHACHA20_C)
+ if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
+ {
+ if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
+ iv,
+ 0U ) ) /* Initial counter value */
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+ }
+#endif
+
+ if ( actual_iv_size != 0 )
+ {
+ memcpy( ctx->iv, iv, actual_iv_size );
+ ctx->iv_size = actual_iv_size;
+ }
return( 0 );
}
@@ -247,22 +291,45 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
return( 0 );
}
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
ctx->iv, ctx->iv_size, ad, ad_len );
}
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ int result;
+ mbedtls_chachapoly_mode_t mode;
+
+ mode = ( ctx->operation == MBEDTLS_ENCRYPT )
+ ? MBEDTLS_CHACHAPOLY_ENCRYPT
+ : MBEDTLS_CHACHAPOLY_DECRYPT;
+
+ result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+ ctx->iv,
+ mode );
+ if ( result != 0 )
+ return( result );
+
+ return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+ ad, ad_len );
+ }
+#endif
return( 0 );
}
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
size_t ilen, unsigned char *output, size_t *olen )
@@ -303,6 +370,15 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
}
#endif
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
+ {
+ *olen = ilen;
+ return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+ ilen, input, output );
+ }
+#endif
+
if ( 0 == block_size )
{
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
@@ -424,6 +500,21 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
}
#endif /* MBEDTLS_CIPHER_MODE_CFB */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
+ {
+ if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
+ ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen = ilen;
+
+ return( 0 );
+ }
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
{
@@ -440,6 +531,27 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
+ {
+ if( ctx->unprocessed_len > 0 ) {
+ /* We can only process an entire data unit at a time. */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+
+ ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
+ ctx->operation, ilen, ctx->iv, input, output );
+ if( ret != 0 )
+ {
+ return( ret );
+ }
+
+ *olen = ilen;
+
+ return( 0 );
+ }
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
{
@@ -639,13 +751,21 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
*olen = 0;
if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
{
return( 0 );
}
+ if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) ||
+ ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
+ {
+ return( 0 );
+ }
+
if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
{
if( ctx->unprocessed_len != 0 )
@@ -757,7 +877,7 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph
}
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
unsigned char *tag, size_t tag_len )
{
@@ -767,8 +887,22 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
if( MBEDTLS_ENCRYPT != ctx->operation )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ /* Don't allow truncated MAC for Poly1305 */
+ if ( tag_len != 16U )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+ tag );
+ }
+#endif
return( 0 );
}
@@ -776,6 +910,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len )
{
+ unsigned char check_tag[16];
int ret;
if( NULL == ctx || NULL == ctx->cipher_info ||
@@ -784,12 +919,9 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
+#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
- unsigned char check_tag[16];
- size_t i;
- int diff;
-
if( tag_len > sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@@ -800,18 +932,38 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
}
/* Check the tag in "constant-time" */
- for( diff = 0, i = 0; i < tag_len; i++ )
- diff |= tag[i] ^ check_tag[i];
-
- if( diff != 0 )
+ if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
return( 0 );
}
+#endif /* MBEDTLS_GCM_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ /* Don't allow truncated MAC for Poly1305 */
+ if ( tag_len != sizeof( check_tag ) )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+ check_tag );
+ if ( ret != 0 )
+ {
+ return( ret );
+ }
+
+ /* Check the tag in "constant-time" */
+ if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
+ return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
+
+ return( 0 );
+ }
+#endif /* MBEDTLS_CHACHAPOLY_C */
return( 0 );
}
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
/*
* Packet-oriented wrapper for non-AEAD modes
@@ -870,6 +1022,21 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
tag, tag_len ) );
}
#endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ /* ChachaPoly has fixed length nonce and MAC (tag) */
+ if ( ( iv_len != ctx->cipher_info->iv_size ) ||
+ ( tag_len != 16U ) )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ *olen = ilen;
+ return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx,
+ ilen, iv, ad, ad_len, input, output, tag ) );
+ }
+#endif /* MBEDTLS_CHACHAPOLY_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
@@ -916,6 +1083,28 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
return( ret );
}
#endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ int ret;
+
+ /* ChachaPoly has fixed length nonce and MAC (tag) */
+ if ( ( iv_len != ctx->cipher_info->iv_size ) ||
+ ( tag_len != 16U ) )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ *olen = ilen;
+ ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen,
+ iv, ad, ad_len, tag, input, output );
+
+ if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED )
+ ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+
+ return( ret );
+ }
+#endif /* MBEDTLS_CHACHAPOLY_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index dc76af8ff4..6dd8c5d3a9 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -33,6 +33,10 @@
#include "mbedtls/cipher_internal.h"
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#include "mbedtls/chachapoly.h"
+#endif
+
#if defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#endif
@@ -45,6 +49,10 @@
#include "mbedtls/camellia.h"
#endif
+#if defined(MBEDTLS_ARIA_C)
+#include "mbedtls/aria.h"
+#endif
+
#if defined(MBEDTLS_DES_C)
#include "mbedtls/des.h"
#endif
@@ -53,6 +61,10 @@
#include "mbedtls/blowfish.h"
#endif
+#if defined(MBEDTLS_CHACHA20_C)
+#include "mbedtls/chacha20.h"
+#endif
+
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
@@ -138,6 +150,15 @@ static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation,
}
#endif /* MBEDTLS_CIPHER_MODE_CFB */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off,
+ unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+ return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off,
+ iv, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
unsigned char *nonce_counter, unsigned char *stream_block,
@@ -148,6 +169,33 @@ static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation,
+ size_t length,
+ const unsigned char data_unit[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ mbedtls_aes_xts_context *xts_ctx = ctx;
+ int mode;
+
+ switch( operation )
+ {
+ case MBEDTLS_ENCRYPT:
+ mode = MBEDTLS_AES_ENCRYPT;
+ break;
+ case MBEDTLS_DECRYPT:
+ mode = MBEDTLS_AES_DECRYPT;
+ break;
+ default:
+ return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+ }
+
+ return mbedtls_aes_crypt_xts( xts_ctx, mode, length,
+ data_unit, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
unsigned int key_bitlen )
{
@@ -187,9 +235,15 @@ static const mbedtls_cipher_base_t aes_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
aes_crypt_cfb128_wrap,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ aes_crypt_ofb_wrap,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
aes_crypt_ctr_wrap,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -204,7 +258,7 @@ static const mbedtls_cipher_info_t aes_128_ecb_info = {
MBEDTLS_MODE_ECB,
128,
"AES-128-ECB",
- 16,
+ 0,
0,
16,
&aes_info
@@ -215,7 +269,7 @@ static const mbedtls_cipher_info_t aes_192_ecb_info = {
MBEDTLS_MODE_ECB,
192,
"AES-192-ECB",
- 16,
+ 0,
0,
16,
&aes_info
@@ -226,7 +280,7 @@ static const mbedtls_cipher_info_t aes_256_ecb_info = {
MBEDTLS_MODE_ECB,
256,
"AES-256-ECB",
- 16,
+ 0,
0,
16,
&aes_info
@@ -302,6 +356,41 @@ static const mbedtls_cipher_info_t aes_256_cfb128_info = {
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+static const mbedtls_cipher_info_t aes_128_ofb_info = {
+ MBEDTLS_CIPHER_AES_128_OFB,
+ MBEDTLS_MODE_OFB,
+ 128,
+ "AES-128-OFB",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_ofb_info = {
+ MBEDTLS_CIPHER_AES_192_OFB,
+ MBEDTLS_MODE_OFB,
+ 192,
+ "AES-192-OFB",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_ofb_info = {
+ MBEDTLS_CIPHER_AES_256_OFB,
+ MBEDTLS_MODE_OFB,
+ 256,
+ "AES-256-OFB",
+ 16,
+ 0,
+ 16,
+ &aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
static const mbedtls_cipher_info_t aes_128_ctr_info = {
MBEDTLS_CIPHER_AES_128_CTR,
@@ -337,6 +426,92 @@ static const mbedtls_cipher_info_t aes_256_ctr_info = {
};
#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ mbedtls_aes_xts_context *xts_ctx = ctx;
+ return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) );
+}
+
+static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ mbedtls_aes_xts_context *xts_ctx = ctx;
+ return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) );
+}
+
+static void *xts_aes_ctx_alloc( void )
+{
+ mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) );
+
+ if( xts_ctx != NULL )
+ mbedtls_aes_xts_init( xts_ctx );
+
+ return( xts_ctx );
+}
+
+static void xts_aes_ctx_free( void *ctx )
+{
+ mbedtls_aes_xts_context *xts_ctx = ctx;
+
+ if( xts_ctx == NULL )
+ return;
+
+ mbedtls_aes_xts_free( xts_ctx );
+ mbedtls_free( xts_ctx );
+}
+
+static const mbedtls_cipher_base_t xts_aes_info = {
+ MBEDTLS_CIPHER_ID_AES,
+ NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ aes_crypt_xts_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ xts_aes_setkey_enc_wrap,
+ xts_aes_setkey_dec_wrap,
+ xts_aes_ctx_alloc,
+ xts_aes_ctx_free
+};
+
+static const mbedtls_cipher_info_t aes_128_xts_info = {
+ MBEDTLS_CIPHER_AES_128_XTS,
+ MBEDTLS_MODE_XTS,
+ 256,
+ "AES-128-XTS",
+ 16,
+ 0,
+ 16,
+ &xts_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_xts_info = {
+ MBEDTLS_CIPHER_AES_256_XTS,
+ MBEDTLS_MODE_XTS,
+ 512,
+ "AES-256-XTS",
+ 16,
+ 0,
+ 16,
+ &xts_aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
#if defined(MBEDTLS_GCM_C)
static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
unsigned int key_bitlen )
@@ -354,9 +529,15 @@ static const mbedtls_cipher_base_t gcm_aes_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -417,9 +598,15 @@ static const mbedtls_cipher_base_t ccm_aes_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -544,9 +731,15 @@ static const mbedtls_cipher_base_t camellia_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
camellia_crypt_cfb128_wrap,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
camellia_crypt_ctr_wrap,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -711,9 +904,15 @@ static const mbedtls_cipher_base_t gcm_camellia_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -774,9 +973,15 @@ static const mbedtls_cipher_base_t ccm_camellia_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -822,6 +1027,382 @@ static const mbedtls_cipher_info_t camellia_256_ccm_info = {
#endif /* MBEDTLS_CAMELLIA_C */
+#if defined(MBEDTLS_ARIA_C)
+
+static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
+ const unsigned char *input, unsigned char *output )
+{
+ (void) operation;
+ return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input,
+ output );
+}
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation,
+ size_t length, unsigned char *iv,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv,
+ input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation,
+ size_t length, size_t *iv_off, unsigned char *iv,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length,
+ iv_off, iv, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
+ unsigned char *nonce_counter, unsigned char *stream_block,
+ const unsigned char *input, unsigned char *output )
+{
+ return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off,
+ nonce_counter, stream_block, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen );
+}
+
+static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen );
+}
+
+static void * aria_ctx_alloc( void )
+{
+ mbedtls_aria_context *ctx;
+ ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) );
+
+ if( ctx == NULL )
+ return( NULL );
+
+ mbedtls_aria_init( ctx );
+
+ return( ctx );
+}
+
+static void aria_ctx_free( void *ctx )
+{
+ mbedtls_aria_free( (mbedtls_aria_context *) ctx );
+ mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t aria_info = {
+ MBEDTLS_CIPHER_ID_ARIA,
+ aria_crypt_ecb_wrap,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ aria_crypt_cbc_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ aria_crypt_cfb128_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ aria_crypt_ctr_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ aria_setkey_enc_wrap,
+ aria_setkey_dec_wrap,
+ aria_ctx_alloc,
+ aria_ctx_free
+};
+
+static const mbedtls_cipher_info_t aria_128_ecb_info = {
+ MBEDTLS_CIPHER_ARIA_128_ECB,
+ MBEDTLS_MODE_ECB,
+ 128,
+ "ARIA-128-ECB",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+static const mbedtls_cipher_info_t aria_192_ecb_info = {
+ MBEDTLS_CIPHER_ARIA_192_ECB,
+ MBEDTLS_MODE_ECB,
+ 192,
+ "ARIA-192-ECB",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+static const mbedtls_cipher_info_t aria_256_ecb_info = {
+ MBEDTLS_CIPHER_ARIA_256_ECB,
+ MBEDTLS_MODE_ECB,
+ 256,
+ "ARIA-256-ECB",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const mbedtls_cipher_info_t aria_128_cbc_info = {
+ MBEDTLS_CIPHER_ARIA_128_CBC,
+ MBEDTLS_MODE_CBC,
+ 128,
+ "ARIA-128-CBC",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+static const mbedtls_cipher_info_t aria_192_cbc_info = {
+ MBEDTLS_CIPHER_ARIA_192_CBC,
+ MBEDTLS_MODE_CBC,
+ 192,
+ "ARIA-192-CBC",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+static const mbedtls_cipher_info_t aria_256_cbc_info = {
+ MBEDTLS_CIPHER_ARIA_256_CBC,
+ MBEDTLS_MODE_CBC,
+ 256,
+ "ARIA-256-CBC",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+static const mbedtls_cipher_info_t aria_128_cfb128_info = {
+ MBEDTLS_CIPHER_ARIA_128_CFB128,
+ MBEDTLS_MODE_CFB,
+ 128,
+ "ARIA-128-CFB128",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+static const mbedtls_cipher_info_t aria_192_cfb128_info = {
+ MBEDTLS_CIPHER_ARIA_192_CFB128,
+ MBEDTLS_MODE_CFB,
+ 192,
+ "ARIA-192-CFB128",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+static const mbedtls_cipher_info_t aria_256_cfb128_info = {
+ MBEDTLS_CIPHER_ARIA_256_CFB128,
+ MBEDTLS_MODE_CFB,
+ 256,
+ "ARIA-256-CFB128",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+static const mbedtls_cipher_info_t aria_128_ctr_info = {
+ MBEDTLS_CIPHER_ARIA_128_CTR,
+ MBEDTLS_MODE_CTR,
+ 128,
+ "ARIA-128-CTR",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+static const mbedtls_cipher_info_t aria_192_ctr_info = {
+ MBEDTLS_CIPHER_ARIA_192_CTR,
+ MBEDTLS_MODE_CTR,
+ 192,
+ "ARIA-192-CTR",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+
+static const mbedtls_cipher_info_t aria_256_ctr_info = {
+ MBEDTLS_CIPHER_ARIA_256_CTR,
+ MBEDTLS_MODE_CTR,
+ 256,
+ "ARIA-256-CTR",
+ 16,
+ 0,
+ 16,
+ &aria_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#if defined(MBEDTLS_GCM_C)
+static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA,
+ key, key_bitlen );
+}
+
+static const mbedtls_cipher_base_t gcm_aria_info = {
+ MBEDTLS_CIPHER_ID_ARIA,
+ NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ gcm_aria_setkey_wrap,
+ gcm_aria_setkey_wrap,
+ gcm_ctx_alloc,
+ gcm_ctx_free,
+};
+
+static const mbedtls_cipher_info_t aria_128_gcm_info = {
+ MBEDTLS_CIPHER_ARIA_128_GCM,
+ MBEDTLS_MODE_GCM,
+ 128,
+ "ARIA-128-GCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aria_info
+};
+
+static const mbedtls_cipher_info_t aria_192_gcm_info = {
+ MBEDTLS_CIPHER_ARIA_192_GCM,
+ MBEDTLS_MODE_GCM,
+ 192,
+ "ARIA-192-GCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aria_info
+};
+
+static const mbedtls_cipher_info_t aria_256_gcm_info = {
+ MBEDTLS_CIPHER_ARIA_256_GCM,
+ MBEDTLS_MODE_GCM,
+ 256,
+ "ARIA-256-GCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &gcm_aria_info
+};
+#endif /* MBEDTLS_GCM_C */
+
+#if defined(MBEDTLS_CCM_C)
+static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA,
+ key, key_bitlen );
+}
+
+static const mbedtls_cipher_base_t ccm_aria_info = {
+ MBEDTLS_CIPHER_ID_ARIA,
+ NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ ccm_aria_setkey_wrap,
+ ccm_aria_setkey_wrap,
+ ccm_ctx_alloc,
+ ccm_ctx_free,
+};
+
+static const mbedtls_cipher_info_t aria_128_ccm_info = {
+ MBEDTLS_CIPHER_ARIA_128_CCM,
+ MBEDTLS_MODE_CCM,
+ 128,
+ "ARIA-128-CCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_aria_info
+};
+
+static const mbedtls_cipher_info_t aria_192_ccm_info = {
+ MBEDTLS_CIPHER_ARIA_192_CCM,
+ MBEDTLS_MODE_CCM,
+ 192,
+ "ARIA-192-CCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_aria_info
+};
+
+static const mbedtls_cipher_info_t aria_256_ccm_info = {
+ MBEDTLS_CIPHER_ARIA_256_CCM,
+ MBEDTLS_MODE_CCM,
+ 256,
+ "ARIA-256-CCM",
+ 12,
+ MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+ 16,
+ &ccm_aria_info
+};
+#endif /* MBEDTLS_CCM_C */
+
+#endif /* MBEDTLS_ARIA_C */
+
#if defined(MBEDTLS_DES_C)
static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
@@ -950,9 +1531,15 @@ static const mbedtls_cipher_base_t des_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -995,9 +1582,15 @@ static const mbedtls_cipher_base_t des_ede_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -1040,9 +1633,15 @@ static const mbedtls_cipher_base_t des_ede3_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -1149,9 +1748,15 @@ static const mbedtls_cipher_base_t blowfish_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
blowfish_crypt_cfb64_wrap,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
blowfish_crypt_ctr_wrap,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@@ -1259,9 +1864,15 @@ static const mbedtls_cipher_base_t arc4_base_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
arc4_crypt_stream_wrap,
#endif
@@ -1283,6 +1894,162 @@ static const mbedtls_cipher_info_t arc4_128_info = {
};
#endif /* MBEDTLS_ARC4_C */
+#if defined(MBEDTLS_CHACHA20_C)
+
+static int chacha20_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ if( key_bitlen != 256U )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ return( 0 );
+}
+
+static int chacha20_stream_wrap( void *ctx, size_t length,
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+
+ ret = mbedtls_chacha20_update( ctx, length, input, output );
+ if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ return( ret );
+}
+
+static void * chacha20_ctx_alloc( void )
+{
+ mbedtls_chacha20_context *ctx;
+ ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) );
+
+ if( ctx == NULL )
+ return( NULL );
+
+ mbedtls_chacha20_init( ctx );
+
+ return( ctx );
+}
+
+static void chacha20_ctx_free( void *ctx )
+{
+ mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx );
+ mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t chacha20_base_info = {
+ MBEDTLS_CIPHER_ID_CHACHA20,
+ NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+ chacha20_stream_wrap,
+#endif
+ chacha20_setkey_wrap,
+ chacha20_setkey_wrap,
+ chacha20_ctx_alloc,
+ chacha20_ctx_free
+};
+static const mbedtls_cipher_info_t chacha20_info = {
+ MBEDTLS_CIPHER_CHACHA20,
+ MBEDTLS_MODE_STREAM,
+ 256,
+ "CHACHA20",
+ 12,
+ 0,
+ 1,
+ &chacha20_base_info
+};
+#endif /* MBEDTLS_CHACHA20_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+
+static int chachapoly_setkey_wrap( void *ctx,
+ const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ if( key_bitlen != 256U )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ return( 0 );
+}
+
+static void * chachapoly_ctx_alloc( void )
+{
+ mbedtls_chachapoly_context *ctx;
+ ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) );
+
+ if( ctx == NULL )
+ return( NULL );
+
+ mbedtls_chachapoly_init( ctx );
+
+ return( ctx );
+}
+
+static void chachapoly_ctx_free( void *ctx )
+{
+ mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx );
+ mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t chachapoly_base_info = {
+ MBEDTLS_CIPHER_ID_CHACHA20,
+ NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ chachapoly_setkey_wrap,
+ chachapoly_setkey_wrap,
+ chachapoly_ctx_alloc,
+ chachapoly_ctx_free
+};
+static const mbedtls_cipher_info_t chachapoly_info = {
+ MBEDTLS_CIPHER_CHACHA20_POLY1305,
+ MBEDTLS_MODE_CHACHAPOLY,
+ 256,
+ "CHACHA20-POLY1305",
+ 12,
+ 0,
+ 1,
+ &chachapoly_base_info
+};
+#endif /* MBEDTLS_CHACHAPOLY_C */
+
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
static int null_crypt_stream( void *ctx, size_t length,
const unsigned char *input,
@@ -1322,9 +2089,15 @@ static const mbedtls_cipher_base_t null_base_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
null_crypt_stream,
#endif
@@ -1362,11 +2135,20 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
{ MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info },
{ MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info },
#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info },
+ { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info },
+ { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info },
+#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
{ MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info },
{ MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info },
{ MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info },
#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info },
+ { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info },
+#endif
#if defined(MBEDTLS_GCM_C)
{ MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info },
{ MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info },
@@ -1427,6 +2209,37 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
#endif
#endif /* MBEDTLS_CAMELLIA_C */
+#if defined(MBEDTLS_ARIA_C)
+ { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info },
+ { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info },
+ { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info },
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info },
+ { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info },
+ { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info },
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info },
+ { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info },
+ { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info },
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info },
+ { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info },
+ { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info },
+#endif
+#if defined(MBEDTLS_GCM_C)
+ { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info },
+ { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info },
+ { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info },
+#endif
+#if defined(MBEDTLS_CCM_C)
+ { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info },
+ { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info },
+ { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info },
+#endif
+#endif /* MBEDTLS_ARIA_C */
+
#if defined(MBEDTLS_DES_C)
{ MBEDTLS_CIPHER_DES_ECB, &des_ecb_info },
{ MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info },
@@ -1438,6 +2251,14 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
#endif
#endif /* MBEDTLS_DES_C */
+#if defined(MBEDTLS_CHACHA20_C)
+ { MBEDTLS_CIPHER_CHACHA20, &chacha20_info },
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info },
+#endif
+
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
{ MBEDTLS_CIPHER_NULL, &null_cipher_info },
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */
diff --git a/library/cmac.c b/library/cmac.c
index 4d7a1f1693..5d101e1c7d 100644
--- a/library/cmac.c
+++ b/library/cmac.c
@@ -828,6 +828,7 @@ static int cmac_test_subkeys( int verbose,
mbedtls_cipher_free( &ctx );
}
+ ret = 0;
goto exit;
cleanup:
@@ -883,6 +884,7 @@ static int cmac_test_wth_cipher( int verbose,
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
+ ret = 0;
exit:
return( ret );
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index d0e5ba862d..fead18f723 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -66,6 +66,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
* Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
* NIST tests to succeed (which require known length fixed entropy)
*/
+/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
+ * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
+ * custom, len, entropy_len)
+ * implements
+ * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
+ * security_strength) -> initial_working_state
+ * with inputs
+ * custom[:len] = nonce || personalization_string
+ * where entropy_input comes from f_entropy for entropy_len bytes
+ * and with outputs
+ * ctx = initial_working_state
+ */
int mbedtls_ctr_drbg_seed_entropy_len(
mbedtls_ctr_drbg_context *ctx,
int (*f_entropy)(void *, unsigned char *, size_t),
@@ -256,6 +268,14 @@ exit:
return( ret );
}
+/* CTR_DRBG_Update (SP 800-90A §10.2.1.2)
+ * ctr_drbg_update_internal(ctx, provided_data)
+ * implements
+ * CTR_DRBG_Update(provided_data, Key, V)
+ * with inputs and outputs
+ * ctx->aes_ctx = Key
+ * ctx->counter = V
+ */
static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
{
@@ -301,6 +321,18 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
return( 0 );
}
+/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
+ * mbedtls_ctr_drbg_update(ctx, additional, add_len)
+ * implements
+ * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
+ * security_strength) -> initial_working_state
+ * with inputs
+ * ctx->counter = all-bits-0
+ * ctx->aes_ctx = context from all-bits-0 key
+ * additional[:add_len] = entropy_input || nonce || personalization_string
+ * and with outputs
+ * ctx = initial_working_state
+ */
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len )
{
@@ -318,6 +350,18 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
}
}
+/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
+ * mbedtls_ctr_drbg_reseed(ctx, additional, len)
+ * implements
+ * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
+ * -> new_working_state
+ * with inputs
+ * ctx contains working_state
+ * additional[:len] = additional_input
+ * and entropy_input comes from calling ctx->f_entropy
+ * and with output
+ * ctx contains new_working_state
+ */
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t len )
{
@@ -371,6 +415,25 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
return( 0 );
}
+/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
+ * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
+ * implements
+ * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
+ * -> working_state_after_reseed
+ * if required, then
+ * CTR_DRBG_Generate(working_state_after_reseed,
+ * requested_number_of_bits, additional_input)
+ * -> status, returned_bits, new_working_state
+ * with inputs
+ * ctx contains working_state
+ * requested_number_of_bits = 8 * output_len
+ * additional[:add_len] = additional_input
+ * and entropy_input comes from calling ctx->f_entropy
+ * and with outputs
+ * status = SUCCESS (this function does the reseed internally)
+ * returned_bits = output[:output_len]
+ * ctx contains new_working_state
+ */
int mbedtls_ctr_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t output_len,
const unsigned char *additional, size_t add_len )
diff --git a/library/ecdh.c b/library/ecdh.c
index 61380b6936..80e9676419 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -40,13 +40,41 @@
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
/*
- * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
+ * Generate public key (restartable version)
+ *
+ * Note: this internal function relies on its caller preserving the value of
+ * the output parameter 'd' across continuation calls. This would not be
+ * acceptable for a public function but is OK here as we control call sites.
+ */
+static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
+ mbedtls_mpi *d, mbedtls_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
+{
+ int ret;
+
+ /* If multiplication is in progress, we already generated a privkey */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+#endif
+ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
+
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
+ f_rng, p_rng, rs_ctx ) );
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Generate public key
*/
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
+ return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
}
#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
@@ -54,22 +82,20 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp
/*
* Compute shared secret (SEC1 3.3.1)
*/
-int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
+static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
+ mbedtls_mpi *z,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
mbedtls_ecp_point P;
mbedtls_ecp_point_init( &P );
- /*
- * Make sure Q is a valid pubkey before using it
- */
- MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
-
- MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
+ f_rng, p_rng, rs_ctx ) );
if( mbedtls_ecp_is_zero( &P ) )
{
@@ -86,12 +112,37 @@ cleanup:
}
#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
+/*
+ * Compute shared secret (SEC1 3.3.1)
+ */
+int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
+ const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ return( ecdh_compute_shared_restartable( grp, z, Q, d,
+ f_rng, p_rng, NULL ) );
+}
+
/*
* Initialize context
*/
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
{
- memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
+ mbedtls_ecp_group_init( &ctx->grp );
+ mbedtls_mpi_init( &ctx->d );
+ mbedtls_ecp_point_init( &ctx->Q );
+ mbedtls_ecp_point_init( &ctx->Qp );
+ mbedtls_mpi_init( &ctx->z );
+ ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
+ mbedtls_ecp_point_init( &ctx->Vi );
+ mbedtls_ecp_point_init( &ctx->Vf );
+ mbedtls_mpi_init( &ctx->_d );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ ctx->restart_enabled = 0;
+ mbedtls_ecp_restart_init( &ctx->rs );
+#endif
}
/*
@@ -103,15 +154,29 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
return;
mbedtls_ecp_group_free( &ctx->grp );
+ mbedtls_mpi_free( &ctx->d );
mbedtls_ecp_point_free( &ctx->Q );
mbedtls_ecp_point_free( &ctx->Qp );
+ mbedtls_mpi_free( &ctx->z );
mbedtls_ecp_point_free( &ctx->Vi );
mbedtls_ecp_point_free( &ctx->Vf );
- mbedtls_mpi_free( &ctx->d );
- mbedtls_mpi_free( &ctx->z );
mbedtls_mpi_free( &ctx->_d );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ mbedtls_ecp_restart_free( &ctx->rs );
+#endif
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Enable restartable operations for context
+ */
+void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
+{
+ ctx->restart_enabled = 1;
+}
+#endif
+
/*
* Setup and write the ServerKeyExhange parameters (RFC 4492)
* struct {
@@ -126,12 +191,18 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
{
int ret;
size_t grp_len, pt_len;
+ mbedtls_ecp_restart_ctx *rs_ctx = NULL;
if( ctx == NULL || ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
- != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( ctx->restart_enabled )
+ rs_ctx = &ctx->rs;
+#endif
+
+ if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
+ f_rng, p_rng, rs_ctx ) ) != 0 )
return( ret );
if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
@@ -142,7 +213,7 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
blen -= grp_len;
if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
- &pt_len, buf, blen ) ) != 0 )
+ &pt_len, buf, blen ) ) != 0 )
return( ret );
*olen = grp_len + pt_len;
@@ -206,12 +277,18 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
void *p_rng )
{
int ret;
+ mbedtls_ecp_restart_ctx *rs_ctx = NULL;
if( ctx == NULL || ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
- != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( ctx->restart_enabled )
+ rs_ctx = &ctx->rs;
+#endif
+
+ if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
+ f_rng, p_rng, rs_ctx ) ) != 0 )
return( ret );
return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
@@ -248,12 +325,18 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
void *p_rng )
{
int ret;
+ mbedtls_ecp_restart_ctx *rs_ctx = NULL;
- if( ctx == NULL )
+ if( ctx == NULL || ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
- f_rng, p_rng ) ) != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( ctx->restart_enabled )
+ rs_ctx = &ctx->rs;
+#endif
+
+ if( ( ret = ecdh_compute_shared_restartable( &ctx->grp,
+ &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng, rs_ctx ) ) != 0 )
{
return( ret );
}
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 17a88bdd29..abac015ceb 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -42,6 +42,178 @@
#include "mbedtls/hmac_drbg.h"
#endif
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include
+#define mbedtls_calloc calloc
+#define mbedtls_free free
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+
+/*
+ * Sub-context for ecdsa_verify()
+ */
+struct mbedtls_ecdsa_restart_ver
+{
+ mbedtls_mpi u1, u2; /* intermediate values */
+ enum { /* what to do next? */
+ ecdsa_ver_init = 0, /* getting started */
+ ecdsa_ver_muladd, /* muladd step */
+ } state;
+};
+
+/*
+ * Init verify restart sub-context
+ */
+static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx )
+{
+ mbedtls_mpi_init( &ctx->u1 );
+ mbedtls_mpi_init( &ctx->u2 );
+ ctx->state = ecdsa_ver_init;
+}
+
+/*
+ * Free the components of a verify restart sub-context
+ */
+static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_mpi_free( &ctx->u1 );
+ mbedtls_mpi_free( &ctx->u2 );
+
+ ecdsa_restart_ver_init( ctx );
+}
+
+/*
+ * Sub-context for ecdsa_sign()
+ */
+struct mbedtls_ecdsa_restart_sig
+{
+ int sign_tries;
+ int key_tries;
+ mbedtls_mpi k; /* per-signature random */
+ mbedtls_mpi r; /* r value */
+ enum { /* what to do next? */
+ ecdsa_sig_init = 0, /* getting started */
+ ecdsa_sig_mul, /* doing ecp_mul() */
+ ecdsa_sig_modn, /* mod N computations */
+ } state;
+};
+
+/*
+ * Init verify sign sub-context
+ */
+static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx )
+{
+ ctx->sign_tries = 0;
+ ctx->key_tries = 0;
+ mbedtls_mpi_init( &ctx->k );
+ mbedtls_mpi_init( &ctx->r );
+ ctx->state = ecdsa_sig_init;
+}
+
+/*
+ * Free the components of a sign restart sub-context
+ */
+static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_mpi_free( &ctx->k );
+ mbedtls_mpi_free( &ctx->r );
+}
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+/*
+ * Sub-context for ecdsa_sign_det()
+ */
+struct mbedtls_ecdsa_restart_det
+{
+ mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */
+ enum { /* what to do next? */
+ ecdsa_det_init = 0, /* getting started */
+ ecdsa_det_sign, /* make signature */
+ } state;
+};
+
+/*
+ * Init verify sign_det sub-context
+ */
+static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx )
+{
+ mbedtls_hmac_drbg_init( &ctx->rng_ctx );
+ ctx->state = ecdsa_det_init;
+}
+
+/*
+ * Free the components of a sign_det restart sub-context
+ */
+static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_hmac_drbg_free( &ctx->rng_ctx );
+
+ ecdsa_restart_det_init( ctx );
+}
+#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
+
+#define ECDSA_RS_ECP &rs_ctx->ecp
+
+/* Utility macro for checking and updating ops budget */
+#define ECDSA_BUDGET( ops ) \
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) );
+
+/* Call this when entering a function that needs its own sub-context */
+#define ECDSA_RS_ENTER( SUB ) do { \
+ /* reset ops count for this call if top-level */ \
+ if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \
+ rs_ctx->ecp.ops_done = 0; \
+ \
+ /* set up our own sub-context if needed */ \
+ if( mbedtls_ecp_restart_is_enabled() && \
+ rs_ctx != NULL && rs_ctx->SUB == NULL ) \
+ { \
+ rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
+ if( rs_ctx->SUB == NULL ) \
+ return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
+ \
+ ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \
+ } \
+} while( 0 )
+
+/* Call this when leaving a function that needs its own sub-context */
+#define ECDSA_RS_LEAVE( SUB ) do { \
+ /* clear our sub-context when not in progress (done or error) */ \
+ if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
+ ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
+ { \
+ ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \
+ mbedtls_free( rs_ctx->SUB ); \
+ rs_ctx->SUB = NULL; \
+ } \
+ \
+ if( rs_ctx != NULL ) \
+ rs_ctx->ecp.depth--; \
+} while( 0 )
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define ECDSA_RS_ECP NULL
+
+#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */
+
+#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx
+#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/*
* Derive a suitable integer for group grp from a buffer of length len
* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
@@ -70,13 +242,17 @@ cleanup:
* Compute ECDSA signature of a hashed message (SEC1 4.1.3)
* Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
*/
-int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
+ mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret, key_tries, sign_tries, blind_tries;
+ int ret, key_tries, sign_tries;
+ int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
mbedtls_ecp_point R;
mbedtls_mpi k, e, t;
+ mbedtls_mpi *pk = &k, *pr = r;
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
if( grp->N.p == NULL )
@@ -89,26 +265,72 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
mbedtls_ecp_point_init( &R );
mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
- sign_tries = 0;
+ ECDSA_RS_ENTER( sig );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->sig != NULL )
+ {
+ /* redirect to our context */
+ p_sign_tries = &rs_ctx->sig->sign_tries;
+ p_key_tries = &rs_ctx->sig->key_tries;
+ pk = &rs_ctx->sig->k;
+ pr = &rs_ctx->sig->r;
+
+ /* jump to current step */
+ if( rs_ctx->sig->state == ecdsa_sig_mul )
+ goto mul;
+ if( rs_ctx->sig->state == ecdsa_sig_modn )
+ goto modn;
+ }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
+ *p_sign_tries = 0;
do
{
+ if( *p_sign_tries++ > 10 )
+ {
+ ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
+ goto cleanup;
+ }
+
/*
* Steps 1-3: generate a suitable ephemeral keypair
* and set r = xR mod n
*/
- key_tries = 0;
+ *p_key_tries = 0;
do
{
- MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
-
- if( key_tries++ > 10 )
+ if( *p_key_tries++ > 10 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
+
+ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->sig != NULL )
+ rs_ctx->sig->state = ecdsa_sig_mul;
+
+mul:
+#endif
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
+ f_rng, p_rng, ECDSA_RS_ECP ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
}
- while( mbedtls_mpi_cmp_int( r, 0 ) == 0 );
+ while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->sig != NULL )
+ rs_ctx->sig->state = ecdsa_sig_modn;
+
+modn:
+#endif
+ /*
+ * Accounting for everything up to the end of the loop
+ * (step 6, but checking now avoids saving e and t)
+ */
+ ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 );
/*
* Step 5: derive MPI from hashed message
@@ -119,57 +341,60 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
* Generate a random value to blind inv_mod in next step,
* avoiding a potential timing leak.
*/
- blind_tries = 0;
- do
- {
- size_t n_size = ( grp->nbits + 7 ) / 8;
- MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
-
- /* See mbedtls_ecp_gen_keypair() */
- if( ++blind_tries > 30 )
- return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
- }
- while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 ||
- mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) );
/*
* Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
-
- if( sign_tries++ > 10 )
- {
- ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
- goto cleanup;
- }
}
while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->sig != NULL )
+ mbedtls_mpi_copy( r, pr );
+#endif
+
cleanup:
mbedtls_ecp_point_free( &R );
mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
+ ECDSA_RS_LEAVE( sig );
+
return( ret );
}
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
+/*
+ * Compute ECDSA signature of a hashed message
+ */
+int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+ const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
+ f_rng, p_rng, NULL ) );
+}
+
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/*
* Deterministic signature wrapper
*/
-int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
+ mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
- mbedtls_md_type_t md_alg )
+ mbedtls_md_type_t md_alg,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
int ret;
mbedtls_hmac_drbg_context rng_ctx;
+ mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
size_t grp_len = ( grp->nbits + 7 ) / 8;
const mbedtls_md_info_t *md_info;
@@ -181,21 +406,53 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi
mbedtls_mpi_init( &h );
mbedtls_hmac_drbg_init( &rng_ctx );
+ ECDSA_RS_ENTER( det );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->det != NULL )
+ {
+ /* redirect to our context */
+ p_rng = &rs_ctx->det->rng_ctx;
+
+ /* jump to current step */
+ if( rs_ctx->det->state == ecdsa_det_sign )
+ goto sign;
+ }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/* Use private key and message hash (reduced) to initialize HMAC_DRBG */
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
- mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
+ mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len );
- ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
- mbedtls_hmac_drbg_random, &rng_ctx );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->det != NULL )
+ rs_ctx->det->state = ecdsa_det_sign;
+
+sign:
+#endif
+ ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
+ mbedtls_hmac_drbg_random, p_rng, rs_ctx );
cleanup:
mbedtls_hmac_drbg_free( &rng_ctx );
mbedtls_mpi_free( &h );
+ ECDSA_RS_LEAVE( det );
+
return( ret );
}
+
+/*
+ * Deterministic signature wrapper
+ */
+int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+ const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+ mbedtls_md_type_t md_alg )
+{
+ return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) );
+}
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
@@ -203,21 +460,40 @@ cleanup:
* Verify ECDSA signature of hashed message (SEC1 4.1.4)
* Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
*/
-int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
- const unsigned char *buf, size_t blen,
- const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
+static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
+ const unsigned char *buf, size_t blen,
+ const mbedtls_ecp_point *Q,
+ const mbedtls_mpi *r, const mbedtls_mpi *s,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
int ret;
mbedtls_mpi e, s_inv, u1, u2;
mbedtls_ecp_point R;
+ mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
mbedtls_ecp_point_init( &R );
- mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
+ mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv );
+ mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
if( grp->N.p == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ ECDSA_RS_ENTER( ver );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ver != NULL )
+ {
+ /* redirect to our context */
+ pu1 = &rs_ctx->ver->u1;
+ pu2 = &rs_ctx->ver->u2;
+
+ /* jump to current step */
+ if( rs_ctx->ver->state == ecdsa_ver_muladd )
+ goto muladd;
+ }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
/*
* Step 1: make sure r and s are in range 1..n-1
*/
@@ -228,11 +504,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
goto cleanup;
}
- /*
- * Additional precaution: make sure Q is valid
- */
- MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
-
/*
* Step 3: derive MPI from hashed message
*/
@@ -241,21 +512,27 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
/*
* Step 4: u1 = e / s mod n, u2 = r / s mod n
*/
+ ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 );
+
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ver != NULL )
+ rs_ctx->ver->state = ecdsa_ver_muladd;
+
+muladd:
+#endif
/*
* Step 5: R = u1 G + u2 Q
- *
- * Since we're not using any secret data, no need to pass a RNG to
- * mbedtls_ecp_mul() for countermesures.
*/
- MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp,
+ &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) );
if( mbedtls_ecp_is_zero( &R ) )
{
@@ -280,12 +557,25 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
cleanup:
mbedtls_ecp_point_free( &R );
- mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
+ mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv );
+ mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
+
+ ECDSA_RS_LEAVE( ver );
return( ret );
}
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
+/*
+ * Verify ECDSA signature of hashed message
+ */
+int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
+ const unsigned char *buf, size_t blen,
+ const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
+{
+ return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) );
+}
+
/*
* Convert a signature (given by context) to ASN.1
*/
@@ -313,11 +603,13 @@ static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
/*
* Compute and write signature
*/
-int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
+int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
+ mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+ void *p_rng,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
int ret;
mbedtls_mpi r, s;
@@ -329,13 +621,13 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
(void) f_rng;
(void) p_rng;
- MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
- hash, hlen, md_alg ) );
+ MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
+ hash, hlen, md_alg, rs_ctx ) );
#else
(void) md_alg;
- MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
- hash, hlen, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
+ hash, hlen, f_rng, p_rng, rs_ctx ) );
#endif
MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
@@ -347,6 +639,19 @@ cleanup:
return( ret );
}
+/*
+ * Compute and write signature
+ */
+int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hlen,
+ unsigned char *sig, size_t *slen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ return( mbedtls_ecdsa_write_signature_restartable(
+ ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) );
+}
+
#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \
defined(MBEDTLS_ECDSA_DETERMINISTIC)
int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
@@ -365,6 +670,18 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen )
+{
+ return( mbedtls_ecdsa_read_signature_restartable(
+ ctx, hash, hlen, sig, slen, NULL ) );
+}
+
+/*
+ * Restartable read and check signature
+ */
+int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
+ const unsigned char *hash, size_t hlen,
+ const unsigned char *sig, size_t slen,
+ mbedtls_ecdsa_restart_ctx *rs_ctx )
{
int ret;
unsigned char *p = (unsigned char *) sig;
@@ -396,8 +713,8 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
goto cleanup;
}
- if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
- &ctx->Q, &r, &s ) ) != 0 )
+ if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen,
+ &ctx->Q, &r, &s, rs_ctx ) ) != 0 )
goto cleanup;
/* At this point we know that the buffer starts with a valid signature.
@@ -458,4 +775,42 @@ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
mbedtls_ecp_keypair_free( ctx );
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx )
+{
+ mbedtls_ecp_restart_init( &ctx->ecp );
+
+ ctx->ver = NULL;
+ ctx->sig = NULL;
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ ctx->det = NULL;
+#endif
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx )
+{
+ mbedtls_ecp_restart_free( &ctx->ecp );
+
+ ecdsa_restart_ver_free( ctx->ver );
+ mbedtls_free( ctx->ver );
+ ctx->ver = NULL;
+
+ ecdsa_restart_sig_free( ctx->sig );
+ mbedtls_free( ctx->sig );
+ ctx->sig = NULL;
+
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ ecdsa_restart_det_free( ctx->det );
+ mbedtls_free( ctx->det );
+ ctx->det = NULL;
+#endif
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
#endif /* MBEDTLS_ECDSA_C */
diff --git a/library/ecp.c b/library/ecp.c
index 41db3fbe5b..de5725c700 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -82,6 +82,230 @@
static unsigned long add_count, dbl_count, mul_count;
#endif
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Maximum number of "basic operations" to be done in a row.
+ *
+ * Default value 0 means that ECC operations will not yield.
+ * Note that regardless of the value of ecp_max_ops, always at
+ * least one step is performed before yielding.
+ *
+ * Setting ecp_max_ops=1 can be suitable for testing purposes
+ * as it will interrupt computation at all possible points.
+ */
+static unsigned ecp_max_ops = 0;
+
+/*
+ * Set ecp_max_ops
+ */
+void mbedtls_ecp_set_max_ops( unsigned max_ops )
+{
+ ecp_max_ops = max_ops;
+}
+
+/*
+ * Check if restart is enabled
+ */
+int mbedtls_ecp_restart_is_enabled( void )
+{
+ return( ecp_max_ops != 0 );
+}
+
+/*
+ * Restart sub-context for ecp_mul_comb()
+ */
+struct mbedtls_ecp_restart_mul
+{
+ mbedtls_ecp_point R; /* current intermediate result */
+ size_t i; /* current index in various loops, 0 outside */
+ mbedtls_ecp_point *T; /* table for precomputed points */
+ unsigned char T_size; /* number of points in table T */
+ enum { /* what were we doing last time we returned? */
+ ecp_rsm_init = 0, /* nothing so far, dummy initial state */
+ ecp_rsm_pre_dbl, /* precompute 2^n multiples */
+ ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
+ ecp_rsm_pre_add, /* precompute remaining points by adding */
+ ecp_rsm_pre_norm_add, /* normalize all precomputed points */
+ ecp_rsm_comb_core, /* ecp_mul_comb_core() */
+ ecp_rsm_final_norm, /* do the final normalization */
+ } state;
+};
+
+/*
+ * Init restart_mul sub-context
+ */
+static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
+{
+ mbedtls_ecp_point_init( &ctx->R );
+ ctx->i = 0;
+ ctx->T = NULL;
+ ctx->T_size = 0;
+ ctx->state = ecp_rsm_init;
+}
+
+/*
+ * Free the components of a restart_mul sub-context
+ */
+static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
+{
+ unsigned char i;
+
+ if( ctx == NULL )
+ return;
+
+ mbedtls_ecp_point_free( &ctx->R );
+
+ if( ctx->T != NULL )
+ {
+ for( i = 0; i < ctx->T_size; i++ )
+ mbedtls_ecp_point_free( ctx->T + i );
+ mbedtls_free( ctx->T );
+ }
+
+ ecp_restart_rsm_init( ctx );
+}
+
+/*
+ * Restart context for ecp_muladd()
+ */
+struct mbedtls_ecp_restart_muladd
+{
+ mbedtls_ecp_point mP; /* mP value */
+ mbedtls_ecp_point R; /* R intermediate result */
+ enum { /* what should we do next? */
+ ecp_rsma_mul1 = 0, /* first multiplication */
+ ecp_rsma_mul2, /* second multiplication */
+ ecp_rsma_add, /* addition */
+ ecp_rsma_norm, /* normalization */
+ } state;
+};
+
+/*
+ * Init restart_muladd sub-context
+ */
+static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
+{
+ mbedtls_ecp_point_init( &ctx->mP );
+ mbedtls_ecp_point_init( &ctx->R );
+ ctx->state = ecp_rsma_mul1;
+}
+
+/*
+ * Free the components of a restart_muladd sub-context
+ */
+static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_ecp_point_free( &ctx->mP );
+ mbedtls_ecp_point_free( &ctx->R );
+
+ ecp_restart_ma_init( ctx );
+}
+
+/*
+ * Initialize a restart context
+ */
+void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
+{
+ ctx->ops_done = 0;
+ ctx->depth = 0;
+ ctx->rsm = NULL;
+ ctx->ma = NULL;
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ ecp_restart_rsm_free( ctx->rsm );
+ mbedtls_free( ctx->rsm );
+
+ ecp_restart_ma_free( ctx->ma );
+ mbedtls_free( ctx->ma );
+
+ mbedtls_ecp_restart_init( ctx );
+}
+
+/*
+ * Check if we can do the next step
+ */
+int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_restart_ctx *rs_ctx,
+ unsigned ops )
+{
+ if( rs_ctx != NULL && ecp_max_ops != 0 )
+ {
+ /* scale depending on curve size: the chosen reference is 256-bit,
+ * and multiplication is quadratic. Round to the closest integer. */
+ if( grp->pbits >= 512 )
+ ops *= 4;
+ else if( grp->pbits >= 384 )
+ ops *= 2;
+
+ /* Avoid infinite loops: always allow first step.
+ * Because of that, however, it's not generally true
+ * that ops_done <= ecp_max_ops, so the check
+ * ops_done > ecp_max_ops below is mandatory. */
+ if( ( rs_ctx->ops_done != 0 ) &&
+ ( rs_ctx->ops_done > ecp_max_ops ||
+ ops > ecp_max_ops - rs_ctx->ops_done ) )
+ {
+ return( MBEDTLS_ERR_ECP_IN_PROGRESS );
+ }
+
+ /* update running count */
+ rs_ctx->ops_done += ops;
+ }
+
+ return( 0 );
+}
+
+/* Call this when entering a function that needs its own sub-context */
+#define ECP_RS_ENTER( SUB ) do { \
+ /* reset ops count for this call if top-level */ \
+ if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
+ rs_ctx->ops_done = 0; \
+ \
+ /* set up our own sub-context if needed */ \
+ if( mbedtls_ecp_restart_is_enabled() && \
+ rs_ctx != NULL && rs_ctx->SUB == NULL ) \
+ { \
+ rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
+ if( rs_ctx->SUB == NULL ) \
+ return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
+ \
+ ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
+ } \
+} while( 0 )
+
+/* Call this when leaving a function that needs its own sub-context */
+#define ECP_RS_LEAVE( SUB ) do { \
+ /* clear our sub-context when not in progress (done or error) */ \
+ if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
+ ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
+ { \
+ ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
+ mbedtls_free( rs_ctx->SUB ); \
+ rs_ctx->SUB = NULL; \
+ } \
+ \
+ if( rs_ctx != NULL ) \
+ rs_ctx->depth--; \
+} while( 0 )
+
+#else /* MBEDTLS_ECP_RESTARTABLE */
+
+#define ECP_RS_ENTER( sub ) (void) rs_ctx;
+#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
+
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
@@ -289,7 +513,21 @@ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
if( grp == NULL )
return;
- memset( grp, 0, sizeof( mbedtls_ecp_group ) );
+ grp->id = MBEDTLS_ECP_DP_NONE;
+ mbedtls_mpi_init( &grp->P );
+ mbedtls_mpi_init( &grp->A );
+ mbedtls_mpi_init( &grp->B );
+ mbedtls_ecp_point_init( &grp->G );
+ mbedtls_mpi_init( &grp->N );
+ grp->pbits = 0;
+ grp->nbits = 0;
+ grp->h = 0;
+ grp->modp = NULL;
+ grp->t_pre = NULL;
+ grp->t_post = NULL;
+ grp->t_data = NULL;
+ grp->T = NULL;
+ grp->T_size = 0;
}
/*
@@ -752,11 +990,10 @@ static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p
return( 0 );
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_normalize_jac( grp, pt );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
+
mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
/*
@@ -796,32 +1033,33 @@ cleanup:
* Cost: 1N(t) := 1I + (6t - 3)M + 1S
*/
static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
- mbedtls_ecp_point *T[], size_t t_len )
+ mbedtls_ecp_point *T[], size_t T_size )
{
int ret;
size_t i;
mbedtls_mpi *c, u, Zi, ZZi;
- if( t_len < 2 )
+ if( T_size < 2 )
return( ecp_normalize_jac( grp, *T ) );
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
#endif
- if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
+ if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
+ for( i = 0; i < T_size; i++ )
+ mbedtls_mpi_init( &c[i] );
+
mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
/*
* c[i] = Z_0 * ... * Z_i
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
- for( i = 1; i < t_len; i++ )
+ for( i = 1; i < T_size; i++ )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
MOD_MUL( c[i] );
@@ -830,9 +1068,9 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
/*
* u = 1 / (Z_0 * ... * Z_n) mod P
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
- for( i = t_len - 1; ; i-- )
+ for( i = T_size - 1; ; i-- )
{
/*
* Zi = 1 / Z_i mod p
@@ -872,7 +1110,7 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
cleanup:
mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
- for( i = 0; i < t_len; i++ )
+ for( i = 0; i < T_size; i++ )
mbedtls_mpi_free( &c[i] );
mbedtls_free( c );
@@ -929,10 +1167,8 @@ static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
#endif
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_double_jac( grp, R, P );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U );
@@ -1027,10 +1263,8 @@ static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
#endif
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
/*
@@ -1114,10 +1348,8 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p
int count = 0;
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
p_size = ( grp->pbits + 7 ) / 8;
@@ -1173,11 +1405,38 @@ cleanup:
* modified version that provides resistance to SPA by avoiding zero
* digits in the representation as in [3]. We modify the method further by
* requiring that all K_i be odd, which has the small cost that our
- * representation uses one more K_i, due to carries.
+ * representation uses one more K_i, due to carries, but saves on the size of
+ * the precomputed table.
*
- * Also, for the sake of compactness, only the seven low-order bits of x[i]
- * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
- * the paper): it is set if and only if if s_i == -1;
+ * Summary of the comb method and its modifications:
+ *
+ * - The goal is to compute m*P for some w*d-bit integer m.
+ *
+ * - The basic comb method splits m into the w-bit integers
+ * x[0] .. x[d-1] where x[i] consists of the bits in m whose
+ * index has residue i modulo d, and computes m * P as
+ * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
+ * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
+ *
+ * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
+ * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] ..,
+ * thereby successively converting it into a form where all summands
+ * are nonzero, at the cost of negative summands. This is the basic idea of [3].
+ *
+ * - More generally, even if x[i+1] != 0, we can first transform the sum as
+ * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
+ * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
+ * Performing and iterating this procedure for those x[i] that are even
+ * (keeping track of carry), we can transform the original sum into one of the form
+ * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
+ * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
+ * which is why we are only computing half of it in the first place in
+ * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
+ *
+ * - For the sake of compactness, only the seven low-order bits of x[i]
+ * are used to represent its absolute value (K_i in the paper), and the msb
+ * of x[i] encodes the sign (s_i in the paper): it is set if and only if
+ * if s_i == -1;
*
* Calling conventions:
* - x is an array of size d + 1
@@ -1186,8 +1445,8 @@ cleanup:
* - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
* (the result will be incorrect if these assumptions are not satisfied)
*/
-static void ecp_comb_fixed( unsigned char x[], size_t d,
- unsigned char w, const mbedtls_mpi *m )
+static void ecp_comb_recode_core( unsigned char x[], size_t d,
+ unsigned char w, const mbedtls_mpi *m )
{
size_t i, j;
unsigned char c, cc, adjust;
@@ -1217,70 +1476,178 @@ static void ecp_comb_fixed( unsigned char x[], size_t d,
}
/*
- * Precompute points for the comb method
+ * Precompute points for the adapted comb method
*
- * If i = i_{w-1} ... i_1 is the binary representation of i, then
- * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P
+ * Assumption: T must be able to hold 2^{w - 1} elements.
*
- * T must be able to hold 2^{w - 1} elements
+ * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
+ * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P.
*
* Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)
+ *
+ * Note: Even comb values (those where P would be omitted from the
+ * sum defining T[i] above) are not needed in our adaption
+ * the comb method. See ecp_comb_recode_core().
+ *
+ * This function currently works in four steps:
+ * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
+ * (2) [norm_dbl] Normalization of coordinates of these T[i]
+ * (3) [add] Computation of all T[i]
+ * (4) [norm_add] Normalization of all T[i]
+ *
+ * Step 1 can be interrupted but not the others; together with the final
+ * coordinate normalization they are the largest steps done at once, depending
+ * on the window size. Here are operation counts for P-256:
+ *
+ * step (2) (3) (4)
+ * w = 5 142 165 208
+ * w = 4 136 77 160
+ * w = 3 130 33 136
+ * w = 2 124 11 124
+ *
+ * So if ECC operations are blocking for too long even with a low max_ops
+ * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
+ * to minimize maximum blocking time.
*/
static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
- unsigned char w, size_t d )
+ unsigned char w, size_t d,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
- unsigned char i, k;
- size_t j;
+ unsigned char i;
+ size_t j = 0;
+ const unsigned char T_size = 1U << ( w - 1 );
mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ {
+ if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
+ goto dbl;
+ if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
+ goto norm_dbl;
+ if( rs_ctx->rsm->state == ecp_rsm_pre_add )
+ goto add;
+ if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
+ goto norm_add;
+ }
+#else
+ (void) rs_ctx;
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ {
+ rs_ctx->rsm->state = ecp_rsm_pre_dbl;
+
+ /* initial state for the loop */
+ rs_ctx->rsm->i = 0;
+ }
+
+dbl:
+#endif
/*
* Set T[0] = P and
* T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
*/
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
- k = 0;
- for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
- {
- cur = T + i;
- MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
- for( j = 0; j < d; j++ )
- MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
+ j = rs_ctx->rsm->i;
+ else
+#endif
+ j = 0;
- TT[k++] = cur;
+ for( ; j < d * ( w - 1 ); j++ )
+ {
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
+
+ i = 1U << ( j / d );
+ cur = T + i;
+
+ if( j % d == 0 )
+ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
+
+ MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
}
- MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
+norm_dbl:
+#endif
+ /*
+ * Normalize current elements in T. As T has holes,
+ * use an auxiliary array of pointers to elements in T.
+ */
+ j = 0;
+ for( i = 1; i < T_size; i <<= 1 )
+ TT[j++] = T + i;
+
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
+
+ MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ rs_ctx->rsm->state = ecp_rsm_pre_add;
+
+add:
+#endif
/*
* Compute the remaining ones using the minimal number of additions
* Be careful to update T[2^l] only after using it!
*/
- k = 0;
- for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
+ MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
+
+ for( i = 1; i < T_size; i <<= 1 )
{
j = i;
while( j-- )
- {
MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
- TT[k++] = &T[i + j];
- }
}
- MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
+
+norm_add:
+#endif
+ /*
+ * Normalize final elements in T. Even though there are no holes now, we
+ * still need the auxiliary array for homogeneity with the previous
+ * call. Also, skip T[0] which is already normalised, being a copy of P.
+ */
+ for( j = 0; j + 1 < T_size; j++ )
+ TT[j] = T + j + 1;
+
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
+
+ MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
cleanup:
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+ ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ {
+ if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
+ rs_ctx->rsm->i = j;
+ }
+#endif
return( ret );
}
/*
* Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
+ *
+ * See ecp_comb_recode_core() for background
*/
static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
- const mbedtls_ecp_point T[], unsigned char t_len,
+ const mbedtls_ecp_point T[], unsigned char T_size,
unsigned char i )
{
int ret;
@@ -1290,7 +1657,7 @@ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
ii = ( i & 0x7Fu ) >> 1;
/* Read the whole table to thwart cache-based timing attacks */
- for( j = 0; j < t_len; j++ )
+ for( j = 0; j < T_size; j++ )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
@@ -1310,10 +1677,11 @@ cleanup:
* Cost: d A + d D + 1 R
*/
static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
- const mbedtls_ecp_point T[], unsigned char t_len,
+ const mbedtls_ecp_point T[], unsigned char T_size,
const unsigned char x[], size_t d,
int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
mbedtls_ecp_point Txi;
@@ -1321,17 +1689,42 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R
mbedtls_ecp_point_init( &Txi );
- /* Start with a non-zero point and randomize its coordinates */
- i = d;
- MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
- if( f_rng != 0 )
- MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+#if !defined(MBEDTLS_ECP_RESTARTABLE)
+ (void) rs_ctx;
+#endif
- while( i-- != 0 )
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+ rs_ctx->rsm->state != ecp_rsm_comb_core )
{
+ rs_ctx->rsm->i = 0;
+ rs_ctx->rsm->state = ecp_rsm_comb_core;
+ }
+
+ /* new 'if' instead of nested for the sake of the 'else' branch */
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
+ {
+ /* restore current index (R already pointing to rs_ctx->rsm->R) */
+ i = rs_ctx->rsm->i;
+ }
+ else
+#endif
+ {
+ /* Start with a non-zero point and randomize its coordinates */
+ i = d;
+ MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
+ if( f_rng != 0 )
+ MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+ }
+
+ while( i != 0 )
+ {
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
+ --i;
+
MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
- MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
+ MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
}
@@ -1339,32 +1732,130 @@ cleanup:
mbedtls_ecp_point_free( &Txi );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
+ ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ {
+ rs_ctx->rsm->i = i;
+ /* no need to save R, already pointing to rs_ctx->rsm->R */
+ }
+#endif
+
return( ret );
}
/*
- * Multiplication using the comb method,
- * for curves in short Weierstrass form
+ * Recode the scalar to get constant-time comb multiplication
+ *
+ * As the actual scalar recoding needs an odd scalar as a starting point,
+ * this wrapper ensures that by replacing m by N - m if necessary, and
+ * informs the caller that the result of multiplication will be negated.
+ *
+ * This works because we only support large prime order for Short Weierstrass
+ * curves, so N is always odd hence either m or N - m is.
+ *
+ * See ecp_comb_recode_core() for background.
*/
-static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
- const mbedtls_mpi *m, const mbedtls_ecp_point *P,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
+ const mbedtls_mpi *m,
+ unsigned char k[COMB_MAX_D + 1],
+ size_t d,
+ unsigned char w,
+ unsigned char *parity_trick )
{
int ret;
- unsigned char w, m_is_odd, p_eq_g, pre_len, i;
- size_t d;
- unsigned char k[COMB_MAX_D + 1];
- mbedtls_ecp_point *T;
mbedtls_mpi M, mm;
mbedtls_mpi_init( &M );
mbedtls_mpi_init( &mm );
- /* we need N to be odd to trnaform m in an odd number, check now */
+ /* N is always odd (see above), just make extra sure */
if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ /* do we need the parity trick? */
+ *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
+
+ /* execute parity fix in constant time */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
+
+ /* actual scalar recoding */
+ ecp_comb_recode_core( k, d, w, &M );
+
+cleanup:
+ mbedtls_mpi_free( &mm );
+ mbedtls_mpi_free( &M );
+
+ return( ret );
+}
+
+/*
+ * Perform comb multiplication (for short Weierstrass curves)
+ * once the auxiliary table has been pre-computed.
+ *
+ * Scalar recoding may use a parity trick that makes us compute -m * P,
+ * if that is the case we'll need to recover m * P at the end.
+ */
+static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
+ mbedtls_ecp_point *R,
+ const mbedtls_mpi *m,
+ const mbedtls_ecp_point *T,
+ unsigned char T_size,
+ unsigned char w,
+ size_t d,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
+{
+ int ret;
+ unsigned char parity_trick;
+ unsigned char k[COMB_MAX_D + 1];
+ mbedtls_ecp_point *RR = R;
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ {
+ RR = &rs_ctx->rsm->R;
+
+ if( rs_ctx->rsm->state == ecp_rsm_final_norm )
+ goto final_norm;
+ }
+#endif
+
+ MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
+ &parity_trick ) );
+ MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
+ f_rng, p_rng, rs_ctx ) );
+ MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ rs_ctx->rsm->state = ecp_rsm_final_norm;
+
+final_norm:
+#endif
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
+ MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
+#endif
+
+cleanup:
+ return( ret );
+}
+
+/*
+ * Pick window size based on curve size and whether we optimize for base point
+ */
+static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
+ unsigned char p_eq_g )
+{
+ unsigned char w;
+
/*
* Minimize the number of multiplications, that is minimize
* 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
@@ -1377,14 +1868,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
* Just adding one avoids upping the cost of the first mul too much,
* and the memory cost too.
*/
-#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
- p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
- mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
if( p_eq_g )
w++;
-#else
- p_eq_g = 0;
-#endif
/*
* Make sure w is within bounds.
@@ -1395,70 +1880,140 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
if( w >= grp->nbits )
w = 2;
- /* Other sizes that depend on w */
- pre_len = 1U << ( w - 1 );
+ return( w );
+}
+
+/*
+ * Multiplication using the comb method - for curves in short Weierstrass form
+ *
+ * This function is mainly responsible for administrative work:
+ * - managing the restart context if enabled
+ * - managing the table of precomputed points (passed between the below two
+ * functions): allocation, computation, ownership tranfer, freeing.
+ *
+ * It delegates the actual arithmetic work to:
+ * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
+ *
+ * See comments on ecp_comb_recode_core() regarding the computation strategy.
+ */
+static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
+{
+ int ret;
+ unsigned char w, p_eq_g, i;
+ size_t d;
+ unsigned char T_size, T_ok;
+ mbedtls_ecp_point *T;
+
+ ECP_RS_ENTER( rsm );
+
+ /* Is P the base point ? */
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+ p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
+ mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
+#else
+ p_eq_g = 0;
+#endif
+
+ /* Pick window size and deduce related sizes */
+ w = ecp_pick_window_size( grp, p_eq_g );
+ T_size = 1U << ( w - 1 );
d = ( grp->nbits + w - 1 ) / w;
- /*
- * Prepare precomputed points: if P == G we want to
- * use grp->T if already initialized, or initialize it.
- */
- T = p_eq_g ? grp->T : NULL;
-
- if( T == NULL )
+ /* Pre-computed table: do we have it already for the base point? */
+ if( p_eq_g && grp->T != NULL )
{
- T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
+ /* second pointer to the same table, will be deleted on exit */
+ T = grp->T;
+ T_ok = 1;
+ }
+ else
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ /* Pre-computed table: do we have one in progress? complete? */
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
+ {
+ /* transfer ownership of T from rsm to local function */
+ T = rs_ctx->rsm->T;
+ rs_ctx->rsm->T = NULL;
+ rs_ctx->rsm->T_size = 0;
+
+ /* This effectively jumps to the call to mul_comb_after_precomp() */
+ T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
+ }
+ else
+#endif
+ /* Allocate table if we didn't have any */
+ {
+ T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
if( T == NULL )
{
ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
goto cleanup;
}
- MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
+ for( i = 0; i < T_size; i++ )
+ mbedtls_ecp_point_init( &T[i] );
+
+ T_ok = 0;
+ }
+
+ /* Compute table (or finish computing it) if not done already */
+ if( !T_ok )
+ {
+ MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
if( p_eq_g )
{
+ /* almost transfer ownership of T to the group, but keep a copy of
+ * the pointer to use for calling the next function more easily */
grp->T = T;
- grp->T_size = pre_len;
+ grp->T_size = T_size;
}
}
- /*
- * Make sure M is odd (M = m or M = N - m, since N is odd)
- * using the fact that m * P = - (N - m) * P
- */
- m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
-
- /*
- * Go for comb multiplication, R = M * P
- */
- ecp_comb_fixed( k, d, w, &M );
- MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) );
-
- /*
- * Now get m * P from M * P and normalize it
- */
- MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
- MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
+ /* Actual comb multiplication using precomputed points */
+ MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
+ T, T_size, w, d,
+ f_rng, p_rng, rs_ctx ) );
cleanup:
- if( T != NULL && ! p_eq_g )
+ /* does T belong to the group? */
+ if( T == grp->T )
+ T = NULL;
+
+ /* does T belong to the restart context? */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL )
{
- for( i = 0; i < pre_len; i++ )
+ /* transfer ownership of T from local function to rsm */
+ rs_ctx->rsm->T_size = T_size;
+ rs_ctx->rsm->T = T;
+ T = NULL;
+ }
+#endif
+
+ /* did T belong to us? then let's destroy it! */
+ if( T != NULL )
+ {
+ for( i = 0; i < T_size; i++ )
mbedtls_ecp_point_free( &T[i] );
mbedtls_free( T );
}
- mbedtls_mpi_free( &M );
- mbedtls_mpi_free( &mm );
-
+ /* don't free R while in progress in case R == P */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+#endif
+ /* prevent caller from using invalid value */
if( ret != 0 )
mbedtls_ecp_point_free( R );
+ ECP_RS_LEAVE( rsm );
+
return( ret );
}
@@ -1482,10 +2037,8 @@ static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P
int ret;
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_normalize_mxz( grp, P );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
@@ -1513,10 +2066,8 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P
int count = 0;
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
p_size = ( grp->pbits + 7 ) / 8;
@@ -1568,10 +2119,8 @@ static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
- if ( mbedtls_internal_ecp_grp_capable( grp ) )
- {
- return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
- }
+ if( mbedtls_internal_ecp_grp_capable( grp ) )
+ return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
@@ -1668,54 +2217,77 @@ cleanup:
#endif /* ECP_MONTGOMERY */
/*
- * Multiplication R = m * P
+ * Restartable multiplication R = m * P
*/
-int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
char is_grp_capable = 0;
#endif
- /* Common sanity checks */
- if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
- return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
-
- if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
- ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
- return( ret );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ /* reset ops count for this call if top-level */
+ if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
+ rs_ctx->ops_done = 0;
+#endif
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
- if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
- {
+ if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
+#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ /* skip argument check when restarting */
+ if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+#endif
+ {
+ /* check_privkey is free */
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
+
+ /* Common sanity checks */
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
}
-#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+ ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
#if defined(ECP_MONTGOMERY)
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
- ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
-
+ MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
#endif
#if defined(ECP_SHORTWEIERSTRASS)
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
- ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
-
+ MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
#endif
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+
cleanup:
- if ( is_grp_capable )
- {
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+ if( is_grp_capable )
mbedtls_internal_ecp_free( grp );
- }
-
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL )
+ rs_ctx->depth--;
+#endif
+
return( ret );
}
+/*
+ * Multiplication R = m * P
+ */
+int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
+}
+
#if defined(ECP_SHORTWEIERSTRASS)
/*
* Check that an affine point is valid as a public key,
@@ -1773,7 +2345,8 @@ cleanup:
static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
mbedtls_ecp_point *R,
const mbedtls_mpi *m,
- const mbedtls_ecp_point *P )
+ const mbedtls_ecp_point *P,
+ mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
@@ -1789,13 +2362,104 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
}
else
{
- MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
+ NULL, NULL, rs_ctx ) );
}
cleanup:
return( ret );
}
+/*
+ * Restartable linear combination
+ * NOT constant-time
+ */
+int mbedtls_ecp_muladd_restartable(
+ mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+ const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+ const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
+ mbedtls_ecp_restart_ctx *rs_ctx )
+{
+ int ret;
+ mbedtls_ecp_point mP;
+ mbedtls_ecp_point *pmP = &mP;
+ mbedtls_ecp_point *pR = R;
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+ char is_grp_capable = 0;
+#endif
+
+ if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+
+ mbedtls_ecp_point_init( &mP );
+
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+ if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
+ MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
+#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+ ECP_RS_ENTER( ma );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ {
+ /* redirect intermediate results to restart context */
+ pmP = &rs_ctx->ma->mP;
+ pR = &rs_ctx->ma->R;
+
+ /* jump to next operation */
+ if( rs_ctx->ma->state == ecp_rsma_mul2 )
+ goto mul2;
+ if( rs_ctx->ma->state == ecp_rsma_add )
+ goto add;
+ if( rs_ctx->ma->state == ecp_rsma_norm )
+ goto norm;
+ }
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ rs_ctx->ma->state = ecp_rsma_mul2;
+
+mul2:
+#endif
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ rs_ctx->ma->state = ecp_rsma_add;
+
+add:
+#endif
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
+ MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ rs_ctx->ma->state = ecp_rsma_norm;
+
+norm:
+#endif
+ MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
+ MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && rs_ctx->ma != NULL )
+ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
+#endif
+
+cleanup:
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+ if( is_grp_capable )
+ mbedtls_internal_ecp_free( grp );
+#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+ mbedtls_ecp_point_free( &mP );
+
+ ECP_RS_LEAVE( ma );
+
+ return( ret );
+}
+
/*
* Linear combination
* NOT constant-time
@@ -1804,45 +2468,9 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
{
- int ret;
- mbedtls_ecp_point mP;
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
- char is_grp_capable = 0;
-#endif
-
- if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
- return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
-
- mbedtls_ecp_point_init( &mP );
-
- MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
- MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
-
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
- if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
- {
- MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
- }
-
-#endif /* MBEDTLS_ECP_INTERNAL_ALT */
- MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
- MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
-
-cleanup:
-
-#if defined(MBEDTLS_ECP_INTERNAL_ALT)
- if ( is_grp_capable )
- {
- mbedtls_internal_ecp_free( grp );
- }
-
-#endif /* MBEDTLS_ECP_INTERNAL_ALT */
- mbedtls_ecp_point_free( &mP );
-
- return( ret );
+ return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
}
-
#if defined(ECP_MONTGOMERY)
/*
* Check validity of a public key for Montgomery curves with x-only schemes
@@ -1892,7 +2520,6 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *
mbedtls_mpi_get_bit( d, 1 ) != 0 ||
mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
return( MBEDTLS_ERR_ECP_INVALID_KEY );
- else
/* see [Curve25519] page 5 */
if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
@@ -1917,15 +2544,14 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *
}
/*
- * Generate a keypair with configurable base point
+ * Generate a private key
*/
-int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
- const mbedtls_ecp_point *G,
- mbedtls_mpi *d, mbedtls_ecp_point *Q,
+int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
size_t n_size = ( grp->nbits + 7 ) / 8;
#if defined(ECP_MONTGOMERY)
@@ -1954,8 +2580,8 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
}
}
- else
#endif /* ECP_MONTGOMERY */
+
#if defined(ECP_SHORTWEIERSTRASS)
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
{
@@ -1989,15 +2615,28 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
}
- else
#endif /* ECP_SHORTWEIERSTRASS */
- return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
cleanup:
- if( ret != 0 )
- return( ret );
+ return( ret );
+}
- return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+/*
+ * Generate a keypair with configurable base point
+ */
+int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *G,
+ mbedtls_mpi *d, mbedtls_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ int ret;
+
+ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
+ MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+
+cleanup:
+ return( ret );
}
/*
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 67900c46c8..040aa117dc 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -19,19 +19,25 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
+#if defined(__linux__)
+/* Ensure that syscall() is available even when compiling with -std=c99 */
+#define _GNU_SOURCE
+#endif
+
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
+#include
+
#if defined(MBEDTLS_ENTROPY_C)
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#if defined(MBEDTLS_TIMING_C)
-#include
#include "mbedtls/timing.h"
#endif
#if defined(MBEDTLS_HAVEGE_C)
@@ -44,7 +50,8 @@
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
- !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
+ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
+ !defined(__HAIKU__)
#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
#endif
diff --git a/library/error.c b/library/error.c
index 222d85b62e..27692dbf7b 100644
--- a/library/error.c
+++ b/library/error.c
@@ -49,6 +49,10 @@
#include "mbedtls/arc4.h"
#endif
+#if defined(MBEDTLS_ARIA_C)
+#include "mbedtls/aria.h"
+#endif
+
#if defined(MBEDTLS_BASE64_C)
#include "mbedtls/base64.h"
#endif
@@ -69,6 +73,14 @@
#include "mbedtls/ccm.h"
#endif
+#if defined(MBEDTLS_CHACHA20_C)
+#include "mbedtls/chacha20.h"
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#include "mbedtls/chachapoly.h"
+#endif
+
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher.h"
#endif
@@ -101,6 +113,10 @@
#include "mbedtls/gcm.h"
#endif
+#if defined(MBEDTLS_HKDF_C)
+#include "mbedtls/hkdf.h"
+#endif
+
#if defined(MBEDTLS_HMAC_DRBG_C)
#include "mbedtls/hmac_drbg.h"
#endif
@@ -149,6 +165,14 @@
#include "mbedtls/pkcs5.h"
#endif
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#endif
+
+#if defined(MBEDTLS_POLY1305_C)
+#include "mbedtls/poly1305.h"
+#endif
+
#if defined(MBEDTLS_RIPEMD160_C)
#include "mbedtls/ripemd160.h"
#endif
@@ -269,6 +293,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" );
if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" );
+ if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) )
+ mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" );
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_MD_C)
@@ -493,6 +519,12 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" );
if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) )
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" );
+ if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) )
+ mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" );
+ if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) )
+ mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" );
+ if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) )
+ mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" );
#endif /* MBEDTLS_SSL_TLS_C */
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
@@ -572,6 +604,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "AES - Invalid key length" );
if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" );
+ if( use_ret == -(MBEDTLS_ERR_AES_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "AES - Invalid input data" );
if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) )
mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" );
if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) )
@@ -583,6 +617,17 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" );
#endif /* MBEDTLS_ARC4_C */
+#if defined(MBEDTLS_ARIA_C)
+ if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH) )
+ mbedtls_snprintf( buf, buflen, "ARIA - Invalid key length" );
+ if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) )
+ mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" );
+ if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) )
+ mbedtls_snprintf( buf, buflen, "ARIA - Feature not available. For example, an unsupported ARIA key size" );
+ if( use_ret == -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED) )
+ mbedtls_snprintf( buf, buflen, "ARIA - ARIA hardware accelerator failed" );
+#endif /* MBEDTLS_ARIA_C */
+
#if defined(MBEDTLS_ASN1_PARSE_C)
if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) )
mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
@@ -653,6 +698,22 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" );
#endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHA20_C)
+ if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" );
+ if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) )
+ mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" );
+ if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) )
+ mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" );
+#endif /* MBEDTLS_CHACHA20_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) )
+ mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" );
+ if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) )
+ mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" );
+#endif /* MBEDTLS_CHACHAPOLY_C */
+
#if defined(MBEDTLS_CMAC_C)
if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" );
@@ -698,6 +759,11 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" );
#endif /* MBEDTLS_GCM_C */
+#if defined(MBEDTLS_HKDF_C)
+ if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" );
+#endif /* MBEDTLS_HKDF_C */
+
#if defined(MBEDTLS_HMAC_DRBG_C)
if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) )
mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
@@ -765,6 +831,20 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
#endif /* MBEDTLS_PADLOCK_C */
+#if defined(MBEDTLS_PLATFORM_C)
+ if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) )
+ mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" );
+#endif /* MBEDTLS_PLATFORM_C */
+
+#if defined(MBEDTLS_POLY1305_C)
+ if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) )
+ mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" );
+ if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) )
+ mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" );
+ if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) )
+ mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" );
+#endif /* MBEDTLS_POLY1305_C */
+
#if defined(MBEDTLS_RIPEMD160_C)
if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" );
diff --git a/library/hkdf.c b/library/hkdf.c
new file mode 100644
index 0000000000..82d8a429f4
--- /dev/null
+++ b/library/hkdf.c
@@ -0,0 +1,192 @@
+/*
+ * HKDF implementation -- RFC 5869
+ *
+ * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_HKDF_C)
+
+#include
+#include "mbedtls/hkdf.h"
+#include "mbedtls/platform_util.h"
+
+int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
+ size_t salt_len, const unsigned char *ikm, size_t ikm_len,
+ const unsigned char *info, size_t info_len,
+ unsigned char *okm, size_t okm_len )
+{
+ int ret;
+ unsigned char prk[MBEDTLS_MD_MAX_SIZE];
+
+ ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk );
+
+ if( ret == 0 )
+ {
+ ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ),
+ info, info_len, okm, okm_len );
+ }
+
+ mbedtls_platform_zeroize( prk, sizeof( prk ) );
+
+ return( ret );
+}
+
+int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
+ const unsigned char *salt, size_t salt_len,
+ const unsigned char *ikm, size_t ikm_len,
+ unsigned char *prk )
+{
+ unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' };
+
+ if( salt == NULL )
+ {
+ size_t hash_len;
+
+ if( salt_len != 0 )
+ {
+ return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
+ }
+
+ hash_len = mbedtls_md_get_size( md );
+
+ if( hash_len == 0 )
+ {
+ return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
+ }
+
+ salt = null_salt;
+ salt_len = hash_len;
+ }
+
+ return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) );
+}
+
+int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
+ size_t prk_len, const unsigned char *info,
+ size_t info_len, unsigned char *okm, size_t okm_len )
+{
+ size_t hash_len;
+ size_t where = 0;
+ size_t n;
+ size_t t_len = 0;
+ size_t i;
+ int ret = 0;
+ mbedtls_md_context_t ctx;
+ unsigned char t[MBEDTLS_MD_MAX_SIZE];
+
+ if( okm == NULL )
+ {
+ return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+ }
+
+ hash_len = mbedtls_md_get_size( md );
+
+ if( prk_len < hash_len || hash_len == 0 )
+ {
+ return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+ }
+
+ if( info == NULL )
+ {
+ info = (const unsigned char *) "";
+ info_len = 0;
+ }
+
+ n = okm_len / hash_len;
+
+ if( (okm_len % hash_len) != 0 )
+ {
+ n++;
+ }
+
+ /*
+ * Per RFC 5869 Section 2.3, okm_len must not exceed
+ * 255 times the hash length
+ */
+ if( n > 255 )
+ {
+ return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+ }
+
+ mbedtls_md_init( &ctx );
+
+ if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 )
+ {
+ goto exit;
+ }
+
+ /*
+ * Compute T = T(1) | T(2) | T(3) | ... | T(N)
+ * Where T(N) is defined in RFC 5869 Section 2.3
+ */
+ for( i = 1; i <= n; i++ )
+ {
+ size_t num_to_copy;
+ unsigned char c = i & 0xff;
+
+ ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len );
+ if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ ret = mbedtls_md_hmac_update( &ctx, t, t_len );
+ if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ ret = mbedtls_md_hmac_update( &ctx, info, info_len );
+ if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ /* The constant concatenated to the end of each T(n) is a single octet.
+ * */
+ ret = mbedtls_md_hmac_update( &ctx, &c, 1 );
+ if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ ret = mbedtls_md_hmac_finish( &ctx, t );
+ if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ num_to_copy = i != n ? hash_len : okm_len - where;
+ memcpy( okm + where, t, num_to_copy );
+ where += hash_len;
+ t_len = hash_len;
+ }
+
+exit:
+ mbedtls_md_free( &ctx );
+ mbedtls_platform_zeroize( t, sizeof( t ) );
+
+ return( ret );
+}
+
+#endif /* MBEDTLS_HKDF_C */
diff --git a/library/md5.c b/library/md5.c
index 8238c2b81a..2a740cda81 100644
--- a/library/md5.c
+++ b/library/md5.c
@@ -309,14 +309,6 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx,
}
#endif
-static const unsigned char md5_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
/*
* MD5 final digest
*/
@@ -324,26 +316,48 @@ int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
unsigned char output[16] )
{
int ret;
- uint32_t last, padn;
+ uint32_t used;
uint32_t high, low;
- unsigned char msglen[8];
+ /*
+ * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
+ */
+ used = ctx->total[0] & 0x3F;
+
+ ctx->buffer[used++] = 0x80;
+
+ if( used <= 56 )
+ {
+ /* Enough room for padding + length in current block */
+ memset( ctx->buffer + used, 0, 56 - used );
+ }
+ else
+ {
+ /* We'll need an extra block */
+ memset( ctx->buffer + used, 0, 64 - used );
+
+ if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ memset( ctx->buffer, 0, 56 );
+ }
+
+ /*
+ * Add message length
+ */
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
- PUT_UINT32_LE( low, msglen, 0 );
- PUT_UINT32_LE( high, msglen, 4 );
+ PUT_UINT32_LE( low, ctx->buffer, 56 );
+ PUT_UINT32_LE( high, ctx->buffer, 60 );
- last = ctx->total[0] & 0x3F;
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
- if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 )
- return( ret );
-
- if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 )
- return( ret );
+ if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+ /*
+ * Output final state
+ */
PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 );
diff --git a/library/memory_buffer_alloc.c b/library/memory_buffer_alloc.c
index ceaeda1e73..51ea7c41d7 100644
--- a/library/memory_buffer_alloc.c
+++ b/library/memory_buffer_alloc.c
@@ -518,7 +518,9 @@ void mbedtls_memory_buffer_alloc_status( void )
heap.alloc_count, heap.free_count );
if( heap.first->next == NULL )
+ {
mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
+ }
else
{
mbedtls_fprintf( stderr, "Memory currently allocated:\n" );
diff --git a/library/net_sockets.c b/library/net_sockets.c
index 7b4a423ccd..816b1303df 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -19,6 +19,11 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
+/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
+ * be set before config.h, which pulls in glibc's features.h indirectly.
+ * Harmless on other platforms. */
+#define _POSIX_C_SOURCE 200112L
+
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@@ -28,7 +33,8 @@
#if defined(MBEDTLS_NET_C)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
- !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
+ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
+ !defined(__HAIKU__)
#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
#endif
@@ -47,11 +53,12 @@
#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
-#ifdef _WIN32_WINNT
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501)
#undef _WIN32_WINNT
-#endif
/* Enables getaddrinfo() & Co */
#define _WIN32_WINNT 0x0501
+#endif
+
#include
#include
diff --git a/library/nist_kw.c b/library/nist_kw.c
new file mode 100644
index 0000000000..176af9fe08
--- /dev/null
+++ b/library/nist_kw.c
@@ -0,0 +1,755 @@
+/*
+ * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
+ * only
+ *
+ * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+/*
+ * Definition of Key Wrapping:
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
+ * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
+ * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
+ *
+ * Note: RFC 3394 defines different methodology for intermediate operations for
+ * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_NIST_KW_C)
+
+#include "mbedtls/nist_kw.h"
+#include "mbedtls/platform_util.h"
+
+#include
+#include
+
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+
+#if !defined(MBEDTLS_NIST_KW_ALT)
+
+#define KW_SEMIBLOCK_LENGTH 8
+#define MIN_SEMIBLOCKS_COUNT 3
+
+/* constant-time buffer comparison */
+static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n )
+{
+ size_t i;
+ volatile const unsigned char *A = (volatile const unsigned char *) a;
+ volatile const unsigned char *B = (volatile const unsigned char *) b;
+ volatile unsigned char diff = 0;
+
+ for( i = 0; i < n; i++ )
+ {
+ /* Read volatile data in order before computing diff.
+ * This avoids IAR compiler warning:
+ * 'the order of volatile accesses is undefined ..' */
+ unsigned char x = A[i], y = B[i];
+ diff |= x ^ y;
+ }
+
+ return( diff );
+}
+
+/*! The 64-bit default integrity check value (ICV) for KW mode. */
+static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
+/*! The 32-bit default integrity check value (ICV) for KWP mode. */
+static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6};
+
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+do { \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+} while( 0 )
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+do { \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+} while( 0 )
+#endif
+
+/*
+ * Initialize context
+ */
+void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) );
+}
+
+int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
+ mbedtls_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits,
+ const int is_wrap )
+{
+ int ret;
+ const mbedtls_cipher_info_t *cipher_info;
+
+ cipher_info = mbedtls_cipher_info_from_values( cipher,
+ keybits,
+ MBEDTLS_MODE_ECB );
+ if( cipher_info == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( cipher_info->block_size != 16 )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ /*
+ * SP 800-38F currently defines AES cipher as the only block cipher allowed:
+ * "For KW and KWP, the underlying block cipher shall be approved, and the
+ * block size shall be 128 bits. Currently, the AES block cipher, with key
+ * lengths of 128, 192, or 256 bits, is the only block cipher that fits
+ * this profile."
+ * Currently we don't support other 128 bit block ciphers for key wrapping,
+ * such as Camellia and Aria.
+ */
+ if( cipher != MBEDTLS_CIPHER_ID_AES )
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+ mbedtls_cipher_free( &ctx->cipher_ctx );
+
+ if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
+ return( ret );
+
+ if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
+ is_wrap ? MBEDTLS_ENCRYPT :
+ MBEDTLS_DECRYPT )
+ ) != 0 )
+ {
+ return( ret );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Free context
+ */
+void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx )
+{
+ mbedtls_cipher_free( &ctx->cipher_ctx );
+ mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) );
+}
+
+/*
+ * Helper function for Xoring the uint64_t "t" with the encrypted A.
+ * Defined in NIST SP 800-38F section 6.1
+ */
+static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t )
+{
+ size_t i = 0;
+ for( i = 0; i < sizeof( t ); i++ )
+ {
+ A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff;
+ }
+}
+
+/*
+ * KW-AE as defined in SP 800-38F section 6.2
+ * KWP-AE as defined in SP 800-38F section 6.3
+ */
+int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
+ mbedtls_nist_kw_mode_t mode,
+ const unsigned char *input, size_t in_len,
+ unsigned char *output, size_t *out_len, size_t out_size )
+{
+ int ret = 0;
+ size_t semiblocks = 0;
+ size_t s;
+ size_t olen, padlen = 0;
+ uint64_t t = 0;
+ unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
+ unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
+ unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
+ unsigned char *A = output;
+
+ *out_len = 0;
+ /*
+ * Generate the String to work on
+ */
+ if( mode == MBEDTLS_KW_MODE_KW )
+ {
+ if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ /*
+ * According to SP 800-38F Table 1, the plaintext length for KW
+ * must be between 2 to 2^54-1 semiblocks inclusive.
+ */
+ if( in_len < 16 ||
+#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
+ in_len > 0x1FFFFFFFFFFFFF8 ||
+#endif
+ in_len % KW_SEMIBLOCK_LENGTH != 0 )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
+ memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
+ }
+ else
+ {
+ if( in_len % 8 != 0 )
+ {
+ padlen = ( 8 - ( in_len % 8 ) );
+ }
+
+ if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ /*
+ * According to SP 800-38F Table 1, the plaintext length for KWP
+ * must be between 1 and 2^32-1 octets inclusive.
+ */
+ if( in_len < 1
+#if SIZE_MAX > 0xFFFFFFFF
+ || in_len > 0xFFFFFFFF
+#endif
+ )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
+ PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
+ KW_SEMIBLOCK_LENGTH / 2 );
+
+ memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
+ memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
+ }
+ semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
+
+ s = 6 * ( semiblocks - 1 );
+
+ if( mode == MBEDTLS_KW_MODE_KWP
+ && in_len <= KW_SEMIBLOCK_LENGTH )
+ {
+ memcpy( inbuff, output, 16 );
+ ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+ inbuff, 16, output, &olen );
+ if( ret != 0 )
+ goto cleanup;
+ }
+ else
+ {
+ /*
+ * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
+ */
+ if( semiblocks < MIN_SEMIBLOCKS_COUNT )
+ {
+ ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ /* Calculate intermediate values */
+ for( t = 1; t <= s; t++ )
+ {
+ memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
+ memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
+
+ ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+ inbuff, 16, outbuff, &olen );
+ if( ret != 0 )
+ goto cleanup;
+
+ memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
+ calc_a_xor_t( A, t );
+
+ memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
+ R2 += KW_SEMIBLOCK_LENGTH;
+ if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
+ R2 = output + KW_SEMIBLOCK_LENGTH;
+ }
+ }
+
+ *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
+
+cleanup:
+
+ if( ret != 0)
+ {
+ memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
+ }
+ mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
+ mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
+ mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
+ return( ret );
+}
+
+/*
+ * W-1 function as defined in RFC 3394 section 2.2.2
+ * This function assumes the following:
+ * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
+ * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
+ * 3. Minimal number of semiblocks is 3.
+ * 4. A is a buffer to hold the first semiblock of the input buffer.
+ */
+static int unwrap( mbedtls_nist_kw_context *ctx,
+ const unsigned char *input, size_t semiblocks,
+ unsigned char A[KW_SEMIBLOCK_LENGTH],
+ unsigned char *output, size_t* out_len )
+{
+ int ret = 0;
+ const size_t s = 6 * ( semiblocks - 1 );
+ size_t olen;
+ uint64_t t = 0;
+ unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
+ unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
+ unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
+ *out_len = 0;
+
+ if( semiblocks < MIN_SEMIBLOCKS_COUNT )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ memcpy( A, input, KW_SEMIBLOCK_LENGTH );
+ memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+
+ /* Calculate intermediate values */
+ for( t = s; t >= 1; t-- )
+ {
+ calc_a_xor_t( A, t );
+
+ memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
+ memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
+
+ ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+ inbuff, 16, outbuff, &olen );
+ if( ret != 0 )
+ goto cleanup;
+
+ memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
+
+ /* Set R as LSB64 of outbuff */
+ memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
+
+ if( R == output )
+ R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
+ else
+ R -= KW_SEMIBLOCK_LENGTH;
+ }
+
+ *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
+
+cleanup:
+ if( ret != 0)
+ memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+ mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) );
+ mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
+
+ return( ret );
+}
+
+/*
+ * KW-AD as defined in SP 800-38F section 6.2
+ * KWP-AD as defined in SP 800-38F section 6.3
+ */
+int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
+ mbedtls_nist_kw_mode_t mode,
+ const unsigned char *input, size_t in_len,
+ unsigned char *output, size_t *out_len, size_t out_size )
+{
+ int ret = 0;
+ size_t i, olen;
+ unsigned char A[KW_SEMIBLOCK_LENGTH];
+ unsigned char diff, bad_padding = 0;
+
+ *out_len = 0;
+ if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ if( mode == MBEDTLS_KW_MODE_KW )
+ {
+ /*
+ * According to SP 800-38F Table 1, the ciphertext length for KW
+ * must be between 3 to 2^54 semiblocks inclusive.
+ */
+ if( in_len < 24 ||
+#if SIZE_MAX > 0x200000000000000
+ in_len > 0x200000000000000 ||
+#endif
+ in_len % KW_SEMIBLOCK_LENGTH != 0 )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
+ A, output, out_len );
+ if( ret != 0 )
+ goto cleanup;
+
+ /* Check ICV in "constant-time" */
+ diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
+
+ if( diff != 0 )
+ {
+ ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+ goto cleanup;
+ }
+
+ }
+ else if( mode == MBEDTLS_KW_MODE_KWP )
+ {
+ size_t padlen = 0;
+ uint32_t Plen;
+ /*
+ * According to SP 800-38F Table 1, the ciphertext length for KWP
+ * must be between 2 to 2^29 semiblocks inclusive.
+ */
+ if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
+#if SIZE_MAX > 0x100000000
+ in_len > 0x100000000 ||
+#endif
+ in_len % KW_SEMIBLOCK_LENGTH != 0 )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
+ {
+ unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
+ ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+ input, 16, outbuff, &olen );
+ if( ret != 0 )
+ goto cleanup;
+
+ memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
+ memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
+ mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
+ *out_len = KW_SEMIBLOCK_LENGTH;
+ }
+ else
+ {
+ /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
+ ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
+ A, output, out_len );
+ if( ret != 0 )
+ goto cleanup;
+ }
+
+ /* Check ICV in "constant-time" */
+ diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
+
+ if( diff != 0 )
+ {
+ ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+ }
+
+ GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
+
+ /*
+ * Plen is the length of the plaintext, when the input is valid.
+ * If Plen is larger than the plaintext and padding, padlen will be
+ * larger than 8, because of the type wrap around.
+ */
+ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
+ if ( padlen > 7 )
+ {
+ padlen &= 7;
+ ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+ }
+
+ /* Check padding in "constant-time" */
+ for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
+ {
+ if( i >= KW_SEMIBLOCK_LENGTH - padlen )
+ diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
+ else
+ bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
+ }
+
+ if( diff != 0 )
+ {
+ ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+ }
+
+ if( ret != 0 )
+ {
+ goto cleanup;
+ }
+ memset( output + Plen, 0, padlen );
+ *out_len = Plen;
+ }
+ else
+ {
+ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ goto cleanup;
+ }
+
+cleanup:
+ if( ret != 0 )
+ {
+ memset( output, 0, *out_len );
+ *out_len = 0;
+ }
+
+ mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
+ mbedtls_platform_zeroize( &diff, sizeof( diff ) );
+ mbedtls_platform_zeroize( A, sizeof( A ) );
+ mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
+ return( ret );
+}
+
+#endif /* !MBEDTLS_NIST_KW_ALT */
+
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+
+#define KW_TESTS 3
+
+/*
+ * Test vectors taken from NIST
+ * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
+ */
+static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
+
+static const unsigned char kw_key[KW_TESTS][32] = {
+ { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
+ 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
+ { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
+ 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
+ 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
+ { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
+ 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
+ 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
+ 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
+};
+
+static const unsigned char kw_msg[KW_TESTS][40] = {
+ { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
+ 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
+ { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
+ 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
+ 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
+ 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
+ 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
+ { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
+ 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
+ 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
+};
+
+static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
+static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
+static const unsigned char kw_res[KW_TESTS][48] = {
+ { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
+ 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
+ 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
+ { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
+ 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
+ 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
+ 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
+ 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
+ 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
+ { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
+ 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
+ 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
+ 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
+};
+
+static const unsigned char kwp_key[KW_TESTS][32] = {
+ { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
+ 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
+ { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
+ 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
+ 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
+ { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
+ 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
+ 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
+ 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
+};
+
+static const unsigned char kwp_msg[KW_TESTS][31] = {
+ { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
+ 0x96 },
+ { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
+ 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
+ 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
+ 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
+ { 0xd1 }
+};
+static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
+
+static const unsigned char kwp_res[KW_TESTS][48] = {
+ { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
+ 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
+ 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
+ { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
+ 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
+ 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
+ 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
+ 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
+ { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
+ 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
+};
+static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
+
+int mbedtls_nist_kw_self_test( int verbose )
+{
+ mbedtls_nist_kw_context ctx;
+ unsigned char out[48];
+ size_t olen;
+ int i;
+ int ret = 0;
+ mbedtls_nist_kw_init( &ctx );
+
+ for( i = 0; i < KW_TESTS; i++ )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 );
+
+ ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+ kw_key[i], key_len[i] * 8, 1 );
+ if( ret != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " KW: setup failed " );
+
+ goto end;
+ }
+
+ ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
+ kw_msg_len[i], out, &olen, sizeof( out ) );
+ if( ret != 0 || kw_out_len[i] != olen ||
+ memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed. ");
+
+ ret = 1;
+ goto end;
+ }
+
+ if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+ kw_key[i], key_len[i] * 8, 0 ) )
+ != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " KW: setup failed ");
+
+ goto end;
+ }
+
+ ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
+ out, olen, out, &olen, sizeof( out ) );
+
+ if( ret != 0 || olen != kw_msg_len[i] ||
+ memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed\n" );
+
+ ret = 1;
+ goto end;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( " passed\n" );
+ }
+
+ for( i = 0; i < KW_TESTS; i++ )
+ {
+ olen = sizeof( out );
+ if( verbose != 0 )
+ mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
+
+ ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
+ key_len[i] * 8, 1 );
+ if( ret != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " KWP: setup failed " );
+
+ goto end;
+ }
+ ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
+ kwp_msg_len[i], out, &olen, sizeof( out ) );
+
+ if( ret != 0 || kwp_out_len[i] != olen ||
+ memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed. ");
+
+ ret = 1;
+ goto end;
+ }
+
+ if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+ kwp_key[i], key_len[i] * 8, 0 ) )
+ != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " KWP: setup failed ");
+
+ goto end;
+ }
+
+ ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out,
+ olen, out, &olen, sizeof( out ) );
+
+ if( ret != 0 || olen != kwp_msg_len[i] ||
+ memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed. ");
+
+ ret = 1;
+ goto end;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( " passed\n" );
+ }
+end:
+ mbedtls_nist_kw_free( &ctx );
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ return( ret );
+}
+
+#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+
+#endif /* MBEDTLS_NIST_KW_C */
diff --git a/library/pk.c b/library/pk.c
index f05b139e3f..e0e8dbad2f 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -69,6 +69,34 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx )
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
}
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
+{
+ ctx->pk_info = NULL;
+ ctx->rs_ctx = NULL;
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
+{
+ if( ctx == NULL || ctx->pk_info == NULL ||
+ ctx->pk_info->rs_free_func == NULL )
+ {
+ return;
+ }
+
+ ctx->pk_info->rs_free_func( ctx->rs_ctx );
+
+ ctx->pk_info = NULL;
+ ctx->rs_ctx = NULL;
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
/*
* Get pk_info structure from type
*/
@@ -171,6 +199,73 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len
return( 0 );
}
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Helper to set up a restart context if needed
+ */
+static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
+ const mbedtls_pk_info_t *info )
+{
+ /* Don't do anything if already set up or invalid */
+ if( ctx == NULL || ctx->pk_info != NULL )
+ return( 0 );
+
+ /* Should never happen when we're called */
+ if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
+ return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+
+ ctx->pk_info = info;
+
+ return( 0 );
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+/*
+ * Verify a signature (restartable)
+ */
+int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ mbedtls_pk_restart_ctx *rs_ctx )
+{
+ if( ctx == NULL || ctx->pk_info == NULL ||
+ pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* optimization: use non-restartable version if restart disabled */
+ if( rs_ctx != NULL &&
+ mbedtls_ecp_restart_is_enabled() &&
+ ctx->pk_info->verify_rs_func != NULL )
+ {
+ int ret;
+
+ if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
+ return( ret );
+
+ ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
+ md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
+
+ if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+ mbedtls_pk_restart_free( rs_ctx );
+
+ return( ret );
+ }
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+ (void) rs_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+ if( ctx->pk_info->verify_func == NULL )
+ return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+
+ return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
+ sig, sig_len ) );
+}
+
/*
* Verify a signature
*/
@@ -178,15 +273,8 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- if( ctx == NULL || ctx->pk_info == NULL ||
- pk_hashlen_helper( md_alg, &hash_len ) != 0 )
- return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
- if( ctx->pk_info->verify_func == NULL )
- return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
-
- return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
- sig, sig_len ) );
+ return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
+ sig, sig_len, NULL ) );
}
/*
@@ -247,6 +335,50 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
}
+/*
+ * Make a signature (restartable)
+ */
+int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
+ mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ mbedtls_pk_restart_ctx *rs_ctx )
+{
+ if( ctx == NULL || ctx->pk_info == NULL ||
+ pk_hashlen_helper( md_alg, &hash_len ) != 0 )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* optimization: use non-restartable version if restart disabled */
+ if( rs_ctx != NULL &&
+ mbedtls_ecp_restart_is_enabled() &&
+ ctx->pk_info->sign_rs_func != NULL )
+ {
+ int ret;
+
+ if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
+ return( ret );
+
+ ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
+ hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
+
+ if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+ mbedtls_pk_restart_free( rs_ctx );
+
+ return( ret );
+ }
+#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+ (void) rs_ctx;
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+ if( ctx->pk_info->sign_func == NULL )
+ return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+
+ return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
+ sig, sig_len, f_rng, p_rng ) );
+}
+
/*
* Make a signature
*/
@@ -255,15 +387,8 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- if( ctx == NULL || ctx->pk_info == NULL ||
- pk_hashlen_helper( md_alg, &hash_len ) != 0 )
- return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
- if( ctx->pk_info->sign_func == NULL )
- return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
-
- return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
- sig, sig_len, f_rng, p_rng ) );
+ return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
+ sig, sig_len, f_rng, p_rng, NULL ) );
}
/*
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 2c7d2d79b8..87806be337 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -190,11 +190,19 @@ const mbedtls_pk_info_t mbedtls_rsa_info = {
rsa_can_do,
rsa_verify_wrap,
rsa_sign_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
rsa_decrypt_wrap,
rsa_encrypt_wrap,
rsa_check_pair_wrap,
rsa_alloc_wrap,
rsa_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
rsa_debug,
};
#endif /* MBEDTLS_RSA_C */
@@ -262,6 +270,110 @@ static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
return( ret );
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+/* Forward declarations */
+static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ void *rs_ctx );
+
+static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ void *rs_ctx );
+
+/*
+ * Restart context for ECDSA operations with ECKEY context
+ *
+ * We need to store an actual ECDSA context, as we need to pass the same to
+ * the underlying ecdsa function, so we can't create it on the fly every time.
+ */
+typedef struct
+{
+ mbedtls_ecdsa_restart_ctx ecdsa_rs;
+ mbedtls_ecdsa_context ecdsa_ctx;
+} eckey_restart_ctx;
+
+static void *eckey_rs_alloc( void )
+{
+ eckey_restart_ctx *rs_ctx;
+
+ void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) );
+
+ if( ctx != NULL )
+ {
+ rs_ctx = ctx;
+ mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs );
+ mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx );
+ }
+
+ return( ctx );
+}
+
+static void eckey_rs_free( void *ctx )
+{
+ eckey_restart_ctx *rs_ctx;
+
+ if( ctx == NULL)
+ return;
+
+ rs_ctx = ctx;
+ mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs );
+ mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx );
+
+ mbedtls_free( ctx );
+}
+
+static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ void *rs_ctx )
+{
+ int ret;
+ eckey_restart_ctx *rs = rs_ctx;
+
+ /* Should never happen */
+ if( rs == NULL )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ /* set up our own sub-context if needed (that is, on first run) */
+ if( rs->ecdsa_ctx.grp.pbits == 0 )
+ MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
+
+ MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx,
+ md_alg, hash, hash_len,
+ sig, sig_len, &rs->ecdsa_rs ) );
+
+cleanup:
+ return( ret );
+}
+
+static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ void *rs_ctx )
+{
+ int ret;
+ eckey_restart_ctx *rs = rs_ctx;
+
+ /* Should never happen */
+ if( rs == NULL )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ /* set up our own sub-context if needed (that is, on first run) */
+ if( rs->ecdsa_ctx.grp.pbits == 0 )
+ MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
+
+ MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg,
+ hash, hash_len, sig, sig_len,
+ f_rng, p_rng, &rs->ecdsa_rs ) );
+
+cleanup:
+ return( ret );
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_ECDSA_C */
static int eckey_check_pair( const void *pub, const void *prv )
@@ -301,15 +413,23 @@ const mbedtls_pk_info_t mbedtls_eckey_info = {
#if defined(MBEDTLS_ECDSA_C)
eckey_verify_wrap,
eckey_sign_wrap,
-#else
- NULL,
- NULL,
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ eckey_verify_rs_wrap,
+ eckey_sign_rs_wrap,
#endif
+#else /* MBEDTLS_ECDSA_C */
+ NULL,
+ NULL,
+#endif /* MBEDTLS_ECDSA_C */
NULL,
NULL,
eckey_check_pair,
eckey_alloc_wrap,
eckey_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ eckey_rs_alloc,
+ eckey_rs_free,
+#endif
eckey_debug,
};
@@ -329,11 +449,19 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = {
eckeydh_can_do,
NULL,
NULL,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
NULL,
NULL,
eckey_check_pair,
eckey_alloc_wrap, /* Same underlying key structure */
eckey_free_wrap, /* Same underlying key structure */
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
eckey_debug, /* Same underlying key structure */
};
#endif /* MBEDTLS_ECP_C */
@@ -369,6 +497,40 @@ static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ const unsigned char *sig, size_t sig_len,
+ void *rs_ctx )
+{
+ int ret;
+ ((void) md_alg);
+
+ ret = mbedtls_ecdsa_read_signature_restartable(
+ (mbedtls_ecdsa_context *) ctx,
+ hash, hash_len, sig, sig_len,
+ (mbedtls_ecdsa_restart_ctx *) rs_ctx );
+
+ if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
+ return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
+
+ return( ret );
+}
+
+static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ void *rs_ctx )
+{
+ return( mbedtls_ecdsa_write_signature_restartable(
+ (mbedtls_ecdsa_context *) ctx,
+ md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng,
+ (mbedtls_ecdsa_restart_ctx *) rs_ctx ) );
+
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
static void *ecdsa_alloc_wrap( void )
{
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) );
@@ -385,6 +547,24 @@ static void ecdsa_free_wrap( void *ctx )
mbedtls_free( ctx );
}
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+static void *ecdsa_rs_alloc( void )
+{
+ void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) );
+
+ if( ctx != NULL )
+ mbedtls_ecdsa_restart_init( ctx );
+
+ return( ctx );
+}
+
+static void ecdsa_rs_free( void *ctx )
+{
+ mbedtls_ecdsa_restart_free( ctx );
+ mbedtls_free( ctx );
+}
+#endif /* MBEDTLS_ECP_RESTARTABLE */
+
const mbedtls_pk_info_t mbedtls_ecdsa_info = {
MBEDTLS_PK_ECDSA,
"ECDSA",
@@ -392,11 +572,19 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = {
ecdsa_can_do,
ecdsa_verify_wrap,
ecdsa_sign_wrap,
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ ecdsa_verify_rs_wrap,
+ ecdsa_sign_rs_wrap,
+#endif
NULL,
NULL,
eckey_check_pair, /* Compatible key structures */
ecdsa_alloc_wrap,
ecdsa_free_wrap,
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ ecdsa_rs_alloc,
+ ecdsa_rs_free,
+#endif
eckey_debug, /* Compatible key structures */
};
#endif /* MBEDTLS_ECDSA_C */
@@ -506,6 +694,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
rsa_alt_can_do,
NULL,
rsa_alt_sign_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
rsa_alt_decrypt_wrap,
NULL,
#if defined(MBEDTLS_RSA_C)
@@ -515,6 +707,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
#endif
rsa_alt_alloc_wrap,
rsa_alt_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL,
+ NULL,
+#endif
NULL,
};
diff --git a/library/pkcs5.c b/library/pkcs5.c
index 440a174b5b..f04f0ab25e 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -249,8 +249,10 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p
memset( counter, 0, 4 );
counter[3] = 1;
+#if UINT_MAX > 0xFFFFFFFF
if( iteration_count > 0xFFFFFFFF )
return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
+#endif
while( key_length )
{
diff --git a/library/pkparse.c b/library/pkparse.c
index ccb7f5409d..d6ac987e23 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -1261,7 +1261,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( ret );
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
#else
- ((void) ret);
((void) pwd);
((void) pwdlen);
#endif /* MBEDTLS_PEM_PARSE_C */
diff --git a/library/platform.c b/library/platform.c
index 9e992875d9..b24b2fa652 100644
--- a/library/platform.c
+++ b/library/platform.c
@@ -51,14 +51,24 @@ static void platform_free_uninit( void *ptr )
#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit
#endif /* !MBEDTLS_PLATFORM_STD_FREE */
-void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC;
-void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE;
+static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC;
+static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE;
+
+void * mbedtls_calloc( size_t nmemb, size_t size )
+{
+ return (*mbedtls_calloc_func)( nmemb, size );
+}
+
+void mbedtls_free( void * ptr )
+{
+ (*mbedtls_free_func)( ptr );
+}
int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
void (*free_func)( void * ) )
{
- mbedtls_calloc = calloc_func;
- mbedtls_free = free_func;
+ mbedtls_calloc_func = calloc_func;
+ mbedtls_free_func = free_func;
return( 0 );
}
#endif /* MBEDTLS_PLATFORM_MEMORY */
diff --git a/library/platform_util.c b/library/platform_util.c
index 1a57de9393..ca5fe4fb87 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -20,6 +20,14 @@
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
+/*
+ * Ensure gmtime_r is available even with -std=c99; must be defined before
+ * config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ */
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200112L
+#endif
+
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@@ -27,6 +35,7 @@
#endif
#include "mbedtls/platform_util.h"
+#include "mbedtls/threading.h"
#include
#include
@@ -65,3 +74,62 @@ void mbedtls_platform_zeroize( void *buf, size_t len )
memset_func( buf, 0, len );
}
#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
+
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+#include
+#if !defined(_WIN32) && (defined(unix) || \
+ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
+ defined(__MACH__)))
+#include
+#endif /* !_WIN32 && (unix || __unix || __unix__ ||
+ * (__APPLE__ && __MACH__)) */
+
+#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
+ _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
+/*
+ * This is a convenience shorthand macro to avoid checking the long
+ * preprocessor conditions above. Ideally, we could expose this macro in
+ * platform_util.h and simply use it in platform_util.c, threading.c and
+ * threading.h. However, this macro is not part of the Mbed TLS public API, so
+ * we keep it private by only defining it in this file
+ */
+#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
+#define PLATFORM_UTIL_USE_GMTIME
+#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
+
+#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
+ _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
+
+struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
+ struct tm *tm_buf )
+{
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+ return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL );
+#elif !defined(PLATFORM_UTIL_USE_GMTIME)
+ return( gmtime_r( tt, tm_buf ) );
+#else
+ struct tm *lt;
+
+#if defined(MBEDTLS_THREADING_C)
+ if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
+ return( NULL );
+#endif /* MBEDTLS_THREADING_C */
+
+ lt = gmtime( tt );
+
+ if( lt != NULL )
+ {
+ memcpy( tm_buf, lt, sizeof( struct tm ) );
+ }
+
+#if defined(MBEDTLS_THREADING_C)
+ if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
+ return( NULL );
+#endif /* MBEDTLS_THREADING_C */
+
+ return( ( lt == NULL ) ? NULL : tm_buf );
+#endif /* _WIN32 && !EFIX64 && !EFI32 */
+}
+#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */
diff --git a/library/poly1305.c b/library/poly1305.c
new file mode 100644
index 0000000000..e22d3afb68
--- /dev/null
+++ b/library/poly1305.c
@@ -0,0 +1,563 @@
+/**
+ * \file poly1305.c
+ *
+ * \brief Poly1305 authentication algorithm.
+ *
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_POLY1305_C)
+
+#include "mbedtls/poly1305.h"
+#include "mbedtls/platform_util.h"
+
+#include
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#if !defined(MBEDTLS_POLY1305_ALT)
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+ !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#define POLY1305_BLOCK_SIZE_BYTES ( 16U )
+
+#define BYTES_TO_U32_LE( data, offset ) \
+ ( (uint32_t) data[offset] \
+ | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
+ | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \
+ | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \
+ )
+
+/*
+ * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.
+ * However we provided an alternative for platforms without such a multiplier.
+ */
+#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
+static uint64_t mul64( uint32_t a, uint32_t b )
+{
+ /* a = al + 2**16 ah, b = bl + 2**16 bh */
+ const uint16_t al = (uint16_t) a;
+ const uint16_t bl = (uint16_t) b;
+ const uint16_t ah = a >> 16;
+ const uint16_t bh = b >> 16;
+
+ /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */
+ const uint32_t lo = (uint32_t) al * bl;
+ const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh;
+ const uint32_t hi = (uint32_t) ah * bh;
+
+ return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) );
+}
+#else
+static inline uint64_t mul64( uint32_t a, uint32_t b )
+{
+ return( (uint64_t) a * b );
+}
+#endif
+
+
+/**
+ * \brief Process blocks with Poly1305.
+ *
+ * \param ctx The Poly1305 context.
+ * \param nblocks Number of blocks to process. Note that this
+ * function only processes full blocks.
+ * \param input Buffer containing the input block(s).
+ * \param needs_padding Set to 0 if the padding bit has already been
+ * applied to the input data before calling this
+ * function. Otherwise, set this parameter to 1.
+ */
+static void poly1305_process( mbedtls_poly1305_context *ctx,
+ size_t nblocks,
+ const unsigned char *input,
+ uint32_t needs_padding )
+{
+ uint64_t d0, d1, d2, d3;
+ uint32_t acc0, acc1, acc2, acc3, acc4;
+ uint32_t r0, r1, r2, r3;
+ uint32_t rs1, rs2, rs3;
+ size_t offset = 0U;
+ size_t i;
+
+ r0 = ctx->r[0];
+ r1 = ctx->r[1];
+ r2 = ctx->r[2];
+ r3 = ctx->r[3];
+
+ rs1 = r1 + ( r1 >> 2U );
+ rs2 = r2 + ( r2 >> 2U );
+ rs3 = r3 + ( r3 >> 2U );
+
+ acc0 = ctx->acc[0];
+ acc1 = ctx->acc[1];
+ acc2 = ctx->acc[2];
+ acc3 = ctx->acc[3];
+ acc4 = ctx->acc[4];
+
+ /* Process full blocks */
+ for( i = 0U; i < nblocks; i++ )
+ {
+ /* The input block is treated as a 128-bit little-endian integer */
+ d0 = BYTES_TO_U32_LE( input, offset + 0 );
+ d1 = BYTES_TO_U32_LE( input, offset + 4 );
+ d2 = BYTES_TO_U32_LE( input, offset + 8 );
+ d3 = BYTES_TO_U32_LE( input, offset + 12 );
+
+ /* Compute: acc += (padded) block as a 130-bit integer */
+ d0 += (uint64_t) acc0;
+ d1 += (uint64_t) acc1 + ( d0 >> 32U );
+ d2 += (uint64_t) acc2 + ( d1 >> 32U );
+ d3 += (uint64_t) acc3 + ( d2 >> 32U );
+ acc0 = (uint32_t) d0;
+ acc1 = (uint32_t) d1;
+ acc2 = (uint32_t) d2;
+ acc3 = (uint32_t) d3;
+ acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding;
+
+ /* Compute: acc *= r */
+ d0 = mul64( acc0, r0 ) +
+ mul64( acc1, rs3 ) +
+ mul64( acc2, rs2 ) +
+ mul64( acc3, rs1 );
+ d1 = mul64( acc0, r1 ) +
+ mul64( acc1, r0 ) +
+ mul64( acc2, rs3 ) +
+ mul64( acc3, rs2 ) +
+ mul64( acc4, rs1 );
+ d2 = mul64( acc0, r2 ) +
+ mul64( acc1, r1 ) +
+ mul64( acc2, r0 ) +
+ mul64( acc3, rs3 ) +
+ mul64( acc4, rs2 );
+ d3 = mul64( acc0, r3 ) +
+ mul64( acc1, r2 ) +
+ mul64( acc2, r1 ) +
+ mul64( acc3, r0 ) +
+ mul64( acc4, rs3 );
+ acc4 *= r0;
+
+ /* Compute: acc %= (2^130 - 5) (partial remainder) */
+ d1 += ( d0 >> 32 );
+ d2 += ( d1 >> 32 );
+ d3 += ( d2 >> 32 );
+ acc0 = (uint32_t) d0;
+ acc1 = (uint32_t) d1;
+ acc2 = (uint32_t) d2;
+ acc3 = (uint32_t) d3;
+ acc4 = (uint32_t) ( d3 >> 32 ) + acc4;
+
+ d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU );
+ acc4 &= 3U;
+ acc0 = (uint32_t) d0;
+ d0 = (uint64_t) acc1 + ( d0 >> 32U );
+ acc1 = (uint32_t) d0;
+ d0 = (uint64_t) acc2 + ( d0 >> 32U );
+ acc2 = (uint32_t) d0;
+ d0 = (uint64_t) acc3 + ( d0 >> 32U );
+ acc3 = (uint32_t) d0;
+ d0 = (uint64_t) acc4 + ( d0 >> 32U );
+ acc4 = (uint32_t) d0;
+
+ offset += POLY1305_BLOCK_SIZE_BYTES;
+ }
+
+ ctx->acc[0] = acc0;
+ ctx->acc[1] = acc1;
+ ctx->acc[2] = acc2;
+ ctx->acc[3] = acc3;
+ ctx->acc[4] = acc4;
+}
+
+/**
+ * \brief Compute the Poly1305 MAC
+ *
+ * \param ctx The Poly1305 context.
+ * \param mac The buffer to where the MAC is written. Must be
+ * big enough to contain the 16-byte MAC.
+ */
+static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx,
+ unsigned char mac[16] )
+{
+ uint64_t d;
+ uint32_t g0, g1, g2, g3, g4;
+ uint32_t acc0, acc1, acc2, acc3, acc4;
+ uint32_t mask;
+ uint32_t mask_inv;
+
+ acc0 = ctx->acc[0];
+ acc1 = ctx->acc[1];
+ acc2 = ctx->acc[2];
+ acc3 = ctx->acc[3];
+ acc4 = ctx->acc[4];
+
+ /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5.
+ * We do this by calculating acc - (2^130 - 5), then checking if
+ * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5)
+ */
+
+ /* Calculate acc + -(2^130 - 5) */
+ d = ( (uint64_t) acc0 + 5U );
+ g0 = (uint32_t) d;
+ d = ( (uint64_t) acc1 + ( d >> 32 ) );
+ g1 = (uint32_t) d;
+ d = ( (uint64_t) acc2 + ( d >> 32 ) );
+ g2 = (uint32_t) d;
+ d = ( (uint64_t) acc3 + ( d >> 32 ) );
+ g3 = (uint32_t) d;
+ g4 = acc4 + (uint32_t) ( d >> 32U );
+
+ /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */
+ mask = (uint32_t) 0U - ( g4 >> 2U );
+ mask_inv = ~mask;
+
+ /* If 131st bit is set then acc=g, otherwise, acc is unmodified */
+ acc0 = ( acc0 & mask_inv ) | ( g0 & mask );
+ acc1 = ( acc1 & mask_inv ) | ( g1 & mask );
+ acc2 = ( acc2 & mask_inv ) | ( g2 & mask );
+ acc3 = ( acc3 & mask_inv ) | ( g3 & mask );
+
+ /* Add 's' */
+ d = (uint64_t) acc0 + ctx->s[0];
+ acc0 = (uint32_t) d;
+ d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U );
+ acc1 = (uint32_t) d;
+ d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U );
+ acc2 = (uint32_t) d;
+ acc3 += ctx->s[3] + (uint32_t) ( d >> 32U );
+
+ /* Compute MAC (128 least significant bits of the accumulator) */
+ mac[ 0] = (unsigned char)( acc0 );
+ mac[ 1] = (unsigned char)( acc0 >> 8 );
+ mac[ 2] = (unsigned char)( acc0 >> 16 );
+ mac[ 3] = (unsigned char)( acc0 >> 24 );
+ mac[ 4] = (unsigned char)( acc1 );
+ mac[ 5] = (unsigned char)( acc1 >> 8 );
+ mac[ 6] = (unsigned char)( acc1 >> 16 );
+ mac[ 7] = (unsigned char)( acc1 >> 24 );
+ mac[ 8] = (unsigned char)( acc2 );
+ mac[ 9] = (unsigned char)( acc2 >> 8 );
+ mac[10] = (unsigned char)( acc2 >> 16 );
+ mac[11] = (unsigned char)( acc2 >> 24 );
+ mac[12] = (unsigned char)( acc3 );
+ mac[13] = (unsigned char)( acc3 >> 8 );
+ mac[14] = (unsigned char)( acc3 >> 16 );
+ mac[15] = (unsigned char)( acc3 >> 24 );
+}
+
+void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx )
+{
+ if( ctx != NULL )
+ {
+ mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
+ }
+}
+
+void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx )
+{
+ if( ctx != NULL )
+ {
+ mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
+ }
+}
+
+int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
+ const unsigned char key[32] )
+{
+ if( ctx == NULL || key == NULL )
+ {
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+
+ /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
+ ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU;
+ ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU;
+ ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU;
+ ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU;
+
+ ctx->s[0] = BYTES_TO_U32_LE( key, 16 );
+ ctx->s[1] = BYTES_TO_U32_LE( key, 20 );
+ ctx->s[2] = BYTES_TO_U32_LE( key, 24 );
+ ctx->s[3] = BYTES_TO_U32_LE( key, 28 );
+
+ /* Initial accumulator state */
+ ctx->acc[0] = 0U;
+ ctx->acc[1] = 0U;
+ ctx->acc[2] = 0U;
+ ctx->acc[3] = 0U;
+ ctx->acc[4] = 0U;
+
+ /* Queue initially empty */
+ mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) );
+ ctx->queue_len = 0U;
+
+ return( 0 );
+}
+
+int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
+ const unsigned char *input,
+ size_t ilen )
+{
+ size_t offset = 0U;
+ size_t remaining = ilen;
+ size_t queue_free_len;
+ size_t nblocks;
+
+ if( ctx == NULL )
+ {
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+ else if( ( ilen > 0U ) && ( input == NULL ) )
+ {
+ /* input pointer is allowed to be NULL only if ilen == 0 */
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+
+ if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) )
+ {
+ queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
+
+ if( ilen < queue_free_len )
+ {
+ /* Not enough data to complete the block.
+ * Store this data with the other leftovers.
+ */
+ memcpy( &ctx->queue[ctx->queue_len],
+ input,
+ ilen );
+
+ ctx->queue_len += ilen;
+
+ remaining = 0U;
+ }
+ else
+ {
+ /* Enough data to produce a complete block */
+ memcpy( &ctx->queue[ctx->queue_len],
+ input,
+ queue_free_len );
+
+ ctx->queue_len = 0U;
+
+ poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */
+
+ offset += queue_free_len;
+ remaining -= queue_free_len;
+ }
+ }
+
+ if( remaining >= POLY1305_BLOCK_SIZE_BYTES )
+ {
+ nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES;
+
+ poly1305_process( ctx, nblocks, &input[offset], 1U );
+
+ offset += nblocks * POLY1305_BLOCK_SIZE_BYTES;
+ remaining %= POLY1305_BLOCK_SIZE_BYTES;
+ }
+
+ if( remaining > 0U )
+ {
+ /* Store partial block */
+ ctx->queue_len = remaining;
+ memcpy( ctx->queue, &input[offset], remaining );
+ }
+
+ return( 0 );
+}
+
+int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
+ unsigned char mac[16] )
+{
+ if( ( ctx == NULL ) || ( mac == NULL ) )
+ {
+ return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+ }
+
+ /* Process any leftover data */
+ if( ctx->queue_len > 0U )
+ {
+ /* Add padding bit */
+ ctx->queue[ctx->queue_len] = 1U;
+ ctx->queue_len++;
+
+ /* Pad with zeroes */
+ memset( &ctx->queue[ctx->queue_len],
+ 0,
+ POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
+
+ poly1305_process( ctx, 1U, /* Process 1 block */
+ ctx->queue, 0U ); /* Already padded above */
+ }
+
+ poly1305_compute_mac( ctx, mac );
+
+ return( 0 );
+}
+
+int mbedtls_poly1305_mac( const unsigned char key[32],
+ const unsigned char *input,
+ size_t ilen,
+ unsigned char mac[16] )
+{
+ mbedtls_poly1305_context ctx;
+ int ret;
+
+ mbedtls_poly1305_init( &ctx );
+
+ ret = mbedtls_poly1305_starts( &ctx, key );
+ if( ret != 0 )
+ goto cleanup;
+
+ ret = mbedtls_poly1305_update( &ctx, input, ilen );
+ if( ret != 0 )
+ goto cleanup;
+
+ ret = mbedtls_poly1305_finish( &ctx, mac );
+
+cleanup:
+ mbedtls_poly1305_free( &ctx );
+ return( ret );
+}
+
+#endif /* MBEDTLS_POLY1305_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char test_keys[2][32] =
+{
+ {
+ 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
+ 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8,
+ 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
+ 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b
+ },
+ {
+ 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
+ 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
+ 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
+ 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0
+ }
+};
+
+static const unsigned char test_data[2][127] =
+{
+ {
+ 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
+ 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,
+ 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,
+ 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,
+ 0x75, 0x70
+ },
+ {
+ 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,
+ 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,
+ 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,
+ 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,
+ 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,
+ 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,
+ 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,
+ 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e
+ }
+};
+
+static const size_t test_data_len[2] =
+{
+ 34U,
+ 127U
+};
+
+static const unsigned char test_mac[2][16] =
+{
+ {
+ 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
+ 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9
+ },
+ {
+ 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,
+ 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62
+ }
+};
+
+#define ASSERT( cond, args ) \
+ do \
+ { \
+ if( ! ( cond ) ) \
+ { \
+ if( verbose != 0 ) \
+ mbedtls_printf args; \
+ \
+ return( -1 ); \
+ } \
+ } \
+ while( 0 )
+
+int mbedtls_poly1305_self_test( int verbose )
+{
+ unsigned char mac[16];
+ unsigned i;
+ int ret;
+
+ for( i = 0U; i < 2U; i++ )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " Poly1305 test %u ", i );
+
+ ret = mbedtls_poly1305_mac( test_keys[i],
+ test_data[i],
+ test_data_len[i],
+ mac );
+ ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
+
+ ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) );
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_POLY1305_C */
diff --git a/library/sha1.c b/library/sha1.c
index 1587de4805..bab6087c4e 100644
--- a/library/sha1.c
+++ b/library/sha1.c
@@ -342,14 +342,6 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
}
#endif
-static const unsigned char sha1_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
/*
* SHA-1 final digest
*/
@@ -357,25 +349,48 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
unsigned char output[20] )
{
int ret;
- uint32_t last, padn;
+ uint32_t used;
uint32_t high, low;
- unsigned char msglen[8];
+ /*
+ * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
+ */
+ used = ctx->total[0] & 0x3F;
+
+ ctx->buffer[used++] = 0x80;
+
+ if( used <= 56 )
+ {
+ /* Enough room for padding + length in current block */
+ memset( ctx->buffer + used, 0, 56 - used );
+ }
+ else
+ {
+ /* We'll need an extra block */
+ memset( ctx->buffer + used, 0, 64 - used );
+
+ if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ memset( ctx->buffer, 0, 56 );
+ }
+
+ /*
+ * Add message length
+ */
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
- PUT_UINT32_BE( high, msglen, 0 );
- PUT_UINT32_BE( low, msglen, 4 );
+ PUT_UINT32_BE( high, ctx->buffer, 56 );
+ PUT_UINT32_BE( low, ctx->buffer, 60 );
- last = ctx->total[0] & 0x3F;
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
- if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 )
- return( ret );
- if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 )
+ if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
+ /*
+ * Output final state
+ */
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
diff --git a/library/sha256.c b/library/sha256.c
index 695485d847..dbb4a89861 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -311,14 +311,6 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
}
#endif
-static const unsigned char sha256_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
/*
* SHA-256 final digest
*/
@@ -326,26 +318,48 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
unsigned char output[32] )
{
int ret;
- uint32_t last, padn;
+ uint32_t used;
uint32_t high, low;
- unsigned char msglen[8];
+ /*
+ * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
+ */
+ used = ctx->total[0] & 0x3F;
+
+ ctx->buffer[used++] = 0x80;
+
+ if( used <= 56 )
+ {
+ /* Enough room for padding + length in current block */
+ memset( ctx->buffer + used, 0, 56 - used );
+ }
+ else
+ {
+ /* We'll need an extra block */
+ memset( ctx->buffer + used, 0, 64 - used );
+
+ if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ memset( ctx->buffer, 0, 56 );
+ }
+
+ /*
+ * Add message length
+ */
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
- PUT_UINT32_BE( high, msglen, 0 );
- PUT_UINT32_BE( low, msglen, 4 );
+ PUT_UINT32_BE( high, ctx->buffer, 56 );
+ PUT_UINT32_BE( low, ctx->buffer, 60 );
- last = ctx->total[0] & 0x3F;
- padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
- if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 )
- return( ret );
-
- if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 )
+ if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
+ /*
+ * Output final state
+ */
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
diff --git a/library/sha512.c b/library/sha512.c
index 6de94e99b4..a9440e8af5 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -341,18 +341,6 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
}
#endif
-static const unsigned char sha512_padding[128] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
/*
* SHA-512 final digest
*/
@@ -360,26 +348,48 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
unsigned char output[64] )
{
int ret;
- size_t last, padn;
+ unsigned used;
uint64_t high, low;
- unsigned char msglen[16];
+ /*
+ * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
+ */
+ used = ctx->total[0] & 0x7F;
+
+ ctx->buffer[used++] = 0x80;
+
+ if( used <= 112 )
+ {
+ /* Enough room for padding + length in current block */
+ memset( ctx->buffer + used, 0, 112 - used );
+ }
+ else
+ {
+ /* We'll need an extra block */
+ memset( ctx->buffer + used, 0, 128 - used );
+
+ if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+
+ memset( ctx->buffer, 0, 112 );
+ }
+
+ /*
+ * Add message length
+ */
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
- PUT_UINT64_BE( high, msglen, 0 );
- PUT_UINT64_BE( low, msglen, 8 );
+ PUT_UINT64_BE( high, ctx->buffer, 112 );
+ PUT_UINT64_BE( low, ctx->buffer, 120 );
- last = (size_t)( ctx->total[0] & 0x7F );
- padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
-
- if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 )
- return( ret );
-
- if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 )
- return( ret );
+ if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
+ return( ret );
+ /*
+ * Output final state
+ */
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );
diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
index 95e6163ccc..745474effe 100644
--- a/library/ssl_ciphersuites.c
+++ b/library/ssl_ciphersuites.c
@@ -47,7 +47,7 @@
* 1. By key exchange:
* Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK
* 2. By key length and cipher:
- * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES
+ * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES
* 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8
* 4. By hash function used when relevant
* 5. By key exchange/auth again: EC > non-EC
@@ -57,6 +57,11 @@ static const int ciphersuite_preference[] =
#if defined(MBEDTLS_SSL_CIPHERSUITES)
MBEDTLS_SSL_CIPHERSUITES,
#else
+ /* Chacha-Poly ephemeral suites */
+ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+
/* All AES-256 ephemeral suites */
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
@@ -81,6 +86,14 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ /* All ARIA-256 ephemeral suites */
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
+
/* All AES-128 ephemeral suites */
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
@@ -105,12 +118,22 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ /* All ARIA-128 ephemeral suites */
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
+
/* All remaining >= 128-bit ephemeral suites */
MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
/* The PSK ephemeral suites */
+ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+ MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
@@ -121,6 +144,9 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
+ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
@@ -132,6 +158,9 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
+ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
@@ -161,6 +190,14 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ /* All ARIA-256 suites */
+ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
+ MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
+
/* All AES-128 suites */
MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
@@ -183,27 +220,41 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ /* All ARIA-128 suites */
+ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
+ MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
+
/* All remaining >= 128-bit suites */
MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
/* The RSA PSK suites */
+ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
/* The PSK suites */
+ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
@@ -211,6 +262,8 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
+ MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
+ MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
@@ -219,6 +272,8 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
+ MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
+ MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
@@ -266,6 +321,75 @@ static const int ciphersuite_preference[] =
static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
{
+#if defined(MBEDTLS_CHACHAPOLY_C) && \
+ defined(MBEDTLS_SHA256_C) && \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+ { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+ MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+ { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+ MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
+ { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+ MBEDTLS_KEY_EXCHANGE_DHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+ { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256",
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+ MBEDTLS_KEY_EXCHANGE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+ { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+ MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+ { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+ MBEDTLS_KEY_EXCHANGE_DHE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+ { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256",
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+ MBEDTLS_KEY_EXCHANGE_RSA_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#endif /* MBEDTLS_CHACHAPOLY_C &&
+ MBEDTLS_SHA256_C &&
+ MBEDTLS_SSL_PROTO_TLS1_2 */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
#if defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_SHA1_C)
@@ -1688,6 +1812,365 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
#endif /* MBEDTLS_DES_C */
#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */
+#if defined(MBEDTLS_ARIA_C)
+
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
+ "TLS-RSA-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
+ "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
+ "TLS-RSA-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
+ "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
+ "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
+ "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
+ "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
+ "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
+ "TLS-PSK-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
+ "TLS-PSK-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
+ "TLS-PSK-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
+ "TLS-PSK-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
+ "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
+ "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
+ "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
+ "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
+ "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
+ "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
+ "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
+ "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
+ "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+ { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384",
+ MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
+ "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+ { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256",
+ MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 },
+#endif
+
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+
+#endif /* MBEDTLS_ARIA_C */
+
+
{ 0, "",
MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE,
0, 0, 0, 0, 0 }
@@ -1837,7 +2320,8 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphers
#endif /* MBEDTLS_PK_C */
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
{
switch( info->key_exchange )
@@ -1847,13 +2331,14 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+ case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
return( 1 );
default:
return( 0 );
}
}
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info )
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 7455e99d2e..5720a4b885 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -57,7 +57,7 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t hostname_len;
*olen = 0;
@@ -127,7 +127,7 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@@ -171,7 +171,7 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t sig_alg_len = 0;
const int *md;
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
@@ -256,7 +256,7 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
unsigned char *elliptic_curve_list = p + 6;
size_t elliptic_curve_len = 0;
const mbedtls_ecp_curve_info *info;
@@ -329,7 +329,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@@ -362,7 +362,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
{
int ret;
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t kkpp_len;
*olen = 0;
@@ -439,7 +439,7 @@ static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@@ -472,7 +472,7 @@ static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@@ -504,7 +504,7 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@@ -538,7 +538,7 @@ static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@@ -572,7 +572,7 @@ static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t tlen = ssl->session_negotiate->ticket_len;
*olen = 0;
@@ -616,7 +616,7 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t alpnlen = 0;
const char **cur;
@@ -766,6 +766,10 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
unsigned char offer_compress;
const int *ciphersuites;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+ int uses_ec = 0;
+#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
@@ -917,6 +921,11 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x",
ciphersuites[i] ) );
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+ uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info );
+#endif
+
n++;
*p++ = (unsigned char)( ciphersuites[i] >> 8 );
*p++ = (unsigned char)( ciphersuites[i] );
@@ -1010,11 +1019,14 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
- ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
- ext_len += olen;
+ if( uses_ec )
+ {
+ ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
+ ext_len += olen;
- ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
- ext_len += olen;
+ ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+ ext_len += olen;
+ }
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -1076,12 +1088,21 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
mbedtls_ssl_send_flight_completed( ssl );
#endif
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+ return( ret );
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
return( 0 );
@@ -1247,14 +1268,14 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
size_t list_size;
const unsigned char *p;
- list_size = buf[0];
- if( list_size + 1 != len )
+ if( len == 0 || (size_t)( buf[0] + 1 ) != len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
+ list_size = buf[0];
p = buf + 1;
while( list_size > 0 )
@@ -1479,7 +1500,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
buf = ssl->in_msg;
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
/* No alert on a read error. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
@@ -1742,6 +1763,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&
+ ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ {
+ ssl->handshake->ecrs_enabled = 1;
+ }
+#endif
+
if( comp != MBEDTLS_SSL_COMPRESS_NULL
#if defined(MBEDTLS_ZLIB_SUPPORT)
&& comp != MBEDTLS_SSL_COMPRESS_DEFLATE
@@ -2047,6 +2076,10 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
(const unsigned char **) p, end ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
@@ -2117,7 +2150,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
unsigned char *p = ssl->handshake->premaster + pms_offset;
- if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) );
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
@@ -2160,7 +2193,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
p, ssl->handshake->pmslen,
ssl->out_msg + offset + len_bytes, olen,
- MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes,
+ MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret );
@@ -2328,7 +2361,15 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled &&
+ ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing )
+ {
+ goto start_processing;
+ }
+#endif
+
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -2365,6 +2406,12 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
}
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing;
+
+start_processing:
+#endif
p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
end = ssl->in_msg + ssl->in_hslen;
MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p );
@@ -2457,6 +2504,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
size_t params_len = p - params;
+ void *rs_ctx = NULL;
/*
* Handle the digitally-signed structure
@@ -2544,10 +2592,9 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( md_alg != MBEDTLS_MD_NONE )
{
- /* Info from md_alg will be used instead */
- hashlen = 0;
- ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params,
- params_len, md_alg );
+ ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
+ params, params_len,
+ md_alg );
if( ret != 0 )
return( ret );
}
@@ -2559,8 +2606,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
- (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
if( ssl->session_negotiate->peer_cert == NULL )
{
@@ -2581,12 +2627,25 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
}
- if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
- md_alg, hash, hashlen, p, sig_len ) ) != 0 )
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ rs_ctx = &ssl->handshake->ecrs_ctx.pk;
+#endif
+
+ if( ( ret = mbedtls_pk_verify_restartable(
+ &ssl->session_negotiate->peer_cert->pk,
+ md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 )
{
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+#endif
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
}
@@ -2637,7 +2696,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
return( 0 );
}
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -2789,7 +2848,7 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -2884,6 +2943,16 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
*/
i = 4;
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ {
+ if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret )
+ goto ecdh_calc_secret;
+
+ mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx );
+ }
+#endif
+
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
&n,
&ssl->out_msg[i], 1000,
@@ -2891,11 +2960,26 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ {
+ ssl->handshake->ecrs_n = n;
+ ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;
+ }
+
+ecdh_calc_secret:
+ if( ssl->handshake->ecrs_enabled )
+ n = ssl->handshake->ecrs_n;
+#endif
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
&ssl->handshake->pmslen,
ssl->handshake->premaster,
@@ -2903,6 +2987,10 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
@@ -2928,7 +3016,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
i = 4;
n = ssl->conf->psk_identity_len;
- if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or "
"SSL buffer too short" ) );
@@ -2964,7 +3052,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
*/
n = ssl->handshake->dhm_ctx.len;
- if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long"
" or SSL buffer too short" ) );
@@ -2993,7 +3081,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
* ClientECDiffieHellmanPublic public;
*/
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n,
- &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i,
+ &ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
@@ -3034,7 +3122,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
i = 4;
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
- ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n,
+ ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
@@ -3065,9 +3153,9 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -3121,9 +3209,18 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
unsigned char *hash_start = hash;
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
unsigned int hashlen;
+ void *rs_ctx = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled &&
+ ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign )
+ {
+ goto sign;
+ }
+#endif
+
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
@@ -3155,8 +3252,15 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
}
/*
- * Make an RSA signature of the handshake digests
+ * Make a signature of the handshake digests
*/
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign;
+
+sign:
+#endif
+
ssl->handshake->calc_verify( ssl, hash );
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
@@ -3233,11 +3337,21 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen,
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled )
+ rs_ctx = &ssl->handshake->ecrs_ctx.pk;
+#endif
+
+ if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ),
+ md_alg, hash_start, hashlen,
ssl->out_msg + 6 + offset, &n,
- ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+ ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+#endif
return( ret );
}
@@ -3250,9 +3364,9 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -3278,7 +3392,7 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -3313,8 +3427,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
- lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) |
- ( msg[2] << 8 ) | ( msg[3] );
+ lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) |
+ ( msg[2] << 8 ) | ( msg[3] );
ticket_len = ( msg[4] << 8 ) | ( msg[5] );
@@ -3392,10 +3506,10 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
{
- if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
return( ret );
}
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
/* Change state now, so that it is right in mbedtls_ssl_read_record(), used
* by DTLS for dropping out-of-sequence ChangeCipherSpec records */
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 09b7a3fed3..36ca0d69f9 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -91,6 +91,13 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
+ if( len < 2 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( servername_list_size + 2 != len )
{
@@ -101,7 +108,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
}
p = buf + 2;
- while( servername_list_size > 0 )
+ while( servername_list_size > 2 )
{
hostname_len = ( ( p[1] << 8 ) | p[2] );
if( hostname_len + 3 > servername_list_size )
@@ -205,6 +212,12 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
mbedtls_md_type_t md_cur;
mbedtls_pk_type_t sig_cur;
+ if ( len < 2 ) {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( sig_alg_list_size + 2 != len ||
sig_alg_list_size % 2 != 0 )
@@ -273,6 +286,12 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
const unsigned char *p;
const mbedtls_ecp_curve_info *curve_info, **curves;
+ if ( len < 2 ) {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( list_size + 2 != len ||
list_size % 2 != 0 )
@@ -332,14 +351,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
size_t list_size;
const unsigned char *p;
- list_size = buf[0];
- if( list_size + 1 != len )
+ if( len == 0 || (size_t)( buf[0] + 1 ) != len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
+ list_size = buf[0];
p = buf + 1;
while( list_size > 0 )
@@ -709,7 +728,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
cur->cert );
- if( ! mbedtls_pk_can_do( cur->key, pk_alg ) )
+ if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
continue;
@@ -733,7 +752,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDSA_C)
if( pk_alg == MBEDTLS_PK_ECDSA &&
- ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 )
+ ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
continue;
@@ -1275,7 +1294,7 @@ read_record_header:
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
- memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 );
+ memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 );
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
@@ -1303,7 +1322,7 @@ read_record_header:
else
#endif
{
- if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
@@ -1656,10 +1675,16 @@ read_record_header:
while( ext_len != 0 )
{
- unsigned int ext_id = ( ( ext[0] << 8 )
- | ( ext[1] ) );
- unsigned int ext_size = ( ( ext[2] << 8 )
- | ( ext[3] ) );
+ unsigned int ext_id;
+ unsigned int ext_size;
+ if ( ext_len < 4 ) {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) );
+ ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) );
if( ext_size + 4 > ext_len )
{
@@ -2235,7 +2260,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
{
int ret;
unsigned char *p = buf;
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t kkpp_len;
*olen = 0;
@@ -2342,7 +2367,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
cookie_len_byte = p++;
if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie,
- &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN,
+ &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,
ssl->cli_id, ssl->cli_id_len ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret );
@@ -2359,12 +2384,21 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+ return( ret );
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) );
return( 0 );
@@ -2564,8 +2598,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
- ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
- ext_len += olen;
+ if ( mbedtls_ssl_ciphersuite_uses_ec(
+ mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) )
+ {
+ ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
+ ext_len += olen;
+ }
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -2595,7 +2633,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO;
- ret = mbedtls_ssl_write_record( ssl );
+ ret = mbedtls_ssl_write_handshake_msg( ssl );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
@@ -2638,7 +2676,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
size_t dn_size, total_dn_size; /* excluding length bytes */
size_t ct_len, sa_len; /* including length bytes */
unsigned char *buf, *p;
- const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
const mbedtls_x509_crt *crt;
int authmode;
@@ -2790,7 +2828,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 );
ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size );
- ret = mbedtls_ssl_write_record( ssl );
+ ret = mbedtls_ssl_write_handshake_msg( ssl );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
@@ -2828,54 +2866,56 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
-static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
+#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \
+ defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
+ size_t *signature_len )
+{
+ /* Append the signature to ssl->out_msg, leaving 2 bytes for the
+ * signature length which will be added in ssl_write_server_key_exchange
+ * after the call to ssl_prepare_server_key_exchange.
+ * ssl_write_server_key_exchange also takes care of incrementing
+ * ssl->out_msglen. */
+ unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
+ size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN
+ - sig_start );
+ int ret = ssl->conf->f_async_resume( ssl,
+ sig_start, signature_len, sig_max_len );
+ if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
+ {
+ ssl->handshake->async_in_progress = 0;
+ mbedtls_ssl_set_async_operation_data( ssl, NULL );
+ }
+ MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret );
+ return( ret );
+}
+#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) &&
+ defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
+
+/* Prepare the ServerKeyExchange message, up to and including
+ * calculating the signature if any, but excluding formatting the
+ * signature and sending the message. */
+static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
+ size_t *signature_len )
{
- int ret;
- size_t n = 0;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
-
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
- unsigned char *p = ssl->out_msg + 4;
- size_t len;
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
- unsigned char *dig_signed = p;
- size_t dig_signed_len = 0;
+ unsigned char *dig_signed = NULL;
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
+ (void) ciphersuite_info; /* unused in some configurations */
+#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
+ (void) signature_len;
+#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
+
+ ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */
/*
*
- * Part 1: Extract static ECDH parameters and abort
- * if ServerKeyExchange not needed.
- *
- */
-
- /* For suites involving ECDH, extract DH parameters
- * from certificate at this point. */
-#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
- if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
- {
- ssl_get_ecdh_params_from_cert( ssl );
- }
-#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
-
- /* Key exchanges not involving ephemeral keys don't use
- * ServerKeyExchange, so end here. */
-#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
- if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
- ssl->state++;
- return( 0 );
- }
-#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */
-
- /*
- *
- * Part 2: Provide key exchange parameters for chosen ciphersuite.
+ * Part 1: Provide key exchange parameters for chosen ciphersuite.
*
*/
@@ -2885,18 +2925,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+ int ret;
+ size_t len = 0;
- ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
- p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng );
+ ret = mbedtls_ecjpake_write_round_two(
+ &ssl->handshake->ecjpake_ctx,
+ ssl->out_msg + ssl->out_msglen,
+ MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len,
+ ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
return( ret );
}
- p += len;
- n += len;
+ ssl->out_msglen += len;
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
@@ -2910,10 +2953,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{
- *(p++) = 0x00;
- *(p++) = 0x00;
-
- n += 2;
+ ssl->out_msg[ssl->out_msglen++] = 0x00;
+ ssl->out_msg[ssl->out_msglen++] = 0x00;
}
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
@@ -2924,6 +2965,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
{
+ int ret;
+ size_t len = 0;
+
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) );
@@ -2947,21 +2991,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
return( ret );
}
- if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx,
- (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
- p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+ if( ( ret = mbedtls_dhm_make_params(
+ &ssl->handshake->dhm_ctx,
+ (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
+ ssl->out_msg + ssl->out_msglen, &len,
+ ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret );
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
- dig_signed = p;
- dig_signed_len = len;
+ dig_signed = ssl->out_msg + ssl->out_msglen;
#endif
- p += len;
- n += len;
+ ssl->out_msglen += len;
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X );
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
@@ -2986,6 +3030,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
*/
const mbedtls_ecp_curve_info **curve = NULL;
const mbedtls_ecp_group_id *gid;
+ int ret;
+ size_t len = 0;
/* Match our preference list against the offered curves */
for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
@@ -3009,21 +3055,21 @@ curve_matching_done:
return( ret );
}
- if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len,
- p, MBEDTLS_SSL_MAX_CONTENT_LEN - n,
- ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+ if( ( ret = mbedtls_ecdh_make_params(
+ &ssl->handshake->ecdh_ctx, &len,
+ ssl->out_msg + ssl->out_msglen,
+ MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen,
+ ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
- dig_signed = p;
- dig_signed_len = len;
+ dig_signed = ssl->out_msg + ssl->out_msglen;
#endif
- p += len;
- n += len;
+ ssl->out_msglen += len;
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
}
@@ -3031,19 +3077,20 @@ curve_matching_done:
/*
*
- * Part 3: For key exchanges involving the server signing the
+ * Part 2: For key exchanges involving the server signing the
* exchange parameters, compute and add the signature here.
*
*/
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
{
- size_t signature_len = 0;
- unsigned int hashlen = 0;
- unsigned char hash[64];
+ size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
+ size_t hashlen = 0;
+ unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+ int ret;
/*
- * 3.1: Choose hash algorithm:
+ * 2.1: Choose hash algorithm:
* A: For TLS 1.2, obey signature-hash-algorithm extension
* to choose appropriate hash.
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
@@ -3090,7 +3137,7 @@ curve_matching_done:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) );
/*
- * 3.2: Compute the hash to be signed
+ * 2.2: Compute the hash to be signed
*/
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
@@ -3110,9 +3157,7 @@ curve_matching_done:
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( md_alg != MBEDTLS_MD_NONE )
{
- /* Info from md_alg will be used instead */
- hashlen = 0;
- ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash,
+ ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
dig_signed,
dig_signed_len,
md_alg );
@@ -3127,18 +3172,11 @@ curve_matching_done:
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
- (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
/*
- * 3.3: Compute and add the signature
+ * 2.3: Compute and add the signature
*/
- if( mbedtls_ssl_own_key( ssl ) == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
- return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
- }
-
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
@@ -3158,46 +3196,162 @@ curve_matching_done:
*
*/
- *(p++) = mbedtls_ssl_hash_from_md_alg( md_alg );
- *(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg );
-
- n += 2;
+ ssl->out_msg[ssl->out_msglen++] =
+ mbedtls_ssl_hash_from_md_alg( md_alg );
+ ssl->out_msg[ssl->out_msglen++] =
+ mbedtls_ssl_sig_from_pk_alg( sig_alg );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
- if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen,
- p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ if( ssl->conf->f_async_sign_start != NULL )
+ {
+ ret = ssl->conf->f_async_sign_start( ssl,
+ mbedtls_ssl_own_cert( ssl ),
+ md_alg, hash, hashlen );
+ switch( ret )
+ {
+ case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
+ /* act as if f_async_sign was null */
+ break;
+ case 0:
+ ssl->handshake->async_in_progress = 1;
+ return( ssl_resume_server_key_exchange( ssl, signature_len ) );
+ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
+ ssl->handshake->async_in_progress = 1;
+ return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
+ default:
+ MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret );
+ return( ret );
+ }
+ }
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+ if( mbedtls_ssl_own_key( ssl ) == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
+ return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
+ }
+
+ /* Append the signature to ssl->out_msg, leaving 2 bytes for the
+ * signature length which will be added in ssl_write_server_key_exchange
+ * after the call to ssl_prepare_server_key_exchange.
+ * ssl_write_server_key_exchange also takes care of incrementing
+ * ssl->out_msglen. */
+ if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ),
+ md_alg, hash, hashlen,
+ ssl->out_msg + ssl->out_msglen + 2,
+ signature_len,
+ ssl->conf->f_rng,
+ ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
return( ret );
}
-
- *(p++) = (unsigned char)( signature_len >> 8 );
- *(p++) = (unsigned char)( signature_len );
- n += 2;
-
- MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len );
-
- n += signature_len;
}
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
- /* Done with actual work; add header and send. */
+ return( 0 );
+}
- ssl->out_msglen = 4 + n;
+/* Prepare the ServerKeyExchange message and send it. For ciphersuites
+ * that do not include a ServerKeyExchange message, do nothing. Either
+ * way, if successful, move on to the next step in the SSL state
+ * machine. */
+static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
+{
+ int ret;
+ size_t signature_len = 0;
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+ ssl->transform_negotiate->ciphersuite_info;
+#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
+ /* Extract static ECDH parameters and abort if ServerKeyExchange
+ * is not needed. */
+ if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
+ {
+ /* For suites involving ECDH, extract DH parameters
+ * from certificate at this point. */
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
+ if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
+ {
+ ssl_get_ecdh_params_from_cert( ssl );
+ }
+#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
+
+ /* Key exchanges not involving ephemeral keys don't use
+ * ServerKeyExchange, so end here. */
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
+ ssl->state++;
+ return( 0 );
+ }
+#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \
+ defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ /* If we have already prepared the message and there is an ongoing
+ * signature operation, resume signing. */
+ if( ssl->handshake->async_in_progress != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) );
+ ret = ssl_resume_server_key_exchange( ssl, &signature_len );
+ }
+ else
+#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) &&
+ defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
+ {
+ /* ServerKeyExchange is needed. Prepare the message. */
+ ret = ssl_prepare_server_key_exchange( ssl, &signature_len );
+ }
+
+ if( ret != 0 )
+ {
+ /* If we're starting to write a new message, set ssl->out_msglen
+ * to 0. But if we're resuming after an asynchronous message,
+ * out_msglen is the amount of data written so far and mst be
+ * preserved. */
+ if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) );
+ else
+ ssl->out_msglen = 0;
+ return( ret );
+ }
+
+ /* If there is a signature, write its length.
+ * ssl_prepare_server_key_exchange already wrote the signature
+ * itself at its proper place in the output buffer. */
+#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
+ if( signature_len != 0 )
+ {
+ ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 );
+ ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len );
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "my signature",
+ ssl->out_msg + ssl->out_msglen,
+ signature_len );
+
+ /* Skip over the already-written signature */
+ ssl->out_msglen += signature_len;
+ }
+#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
+
+ /* Add header and send. */
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
-
return( 0 );
}
@@ -3218,12 +3372,21 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
mbedtls_ssl_send_flight_completed( ssl );
#endif
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+ return( ret );
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
return( 0 );
@@ -3272,33 +3435,59 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char *
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
- const unsigned char *p,
- const unsigned char *end,
- size_t pms_offset )
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
+ unsigned char *peer_pms,
+ size_t *peer_pmslen,
+ size_t peer_pmssize )
+{
+ int ret = ssl->conf->f_async_resume( ssl,
+ peer_pms, peer_pmslen, peer_pmssize );
+ if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
+ {
+ ssl->handshake->async_in_progress = 0;
+ mbedtls_ssl_set_async_operation_data( ssl, NULL );
+ }
+ MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret );
+ return( ret );
+}
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
+ const unsigned char *p,
+ const unsigned char *end,
+ unsigned char *peer_pms,
+ size_t *peer_pmslen,
+ size_t peer_pmssize )
{
int ret;
- size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) );
- unsigned char *pms = ssl->handshake->premaster + pms_offset;
- unsigned char ver[2];
- unsigned char fake_pms[48], peer_pms[48];
- unsigned char mask;
- size_t i, peer_pmslen;
- unsigned int diff;
+ mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
+ mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
+ size_t len = mbedtls_pk_get_len( public_key );
- if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) )
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ /* If we have already started decoding the message and there is an ongoing
+ * decryption operation, resume signing. */
+ if( ssl->handshake->async_in_progress != 0 )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
- return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) );
+ return( ssl_resume_decrypt_pms( ssl,
+ peer_pms, peer_pmslen, peer_pmssize ) );
}
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/*
- * Decrypt the premaster using own private RSA key
+ * Prepare to decrypt the premaster using own private RSA key
*/
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
{
+ if ( p + 2 > end ) {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+ }
if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
*p++ != ( ( len ) & 0xFF ) )
{
@@ -3314,30 +3503,120 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
+ /*
+ * Decrypt the premaster secret
+ */
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ if( ssl->conf->f_async_decrypt_start != NULL )
+ {
+ ret = ssl->conf->f_async_decrypt_start( ssl,
+ mbedtls_ssl_own_cert( ssl ),
+ p, len );
+ switch( ret )
+ {
+ case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
+ /* act as if f_async_decrypt_start was null */
+ break;
+ case 0:
+ ssl->handshake->async_in_progress = 1;
+ return( ssl_resume_decrypt_pms( ssl,
+ peer_pms,
+ peer_pmslen,
+ peer_pmssize ) );
+ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
+ ssl->handshake->async_in_progress = 1;
+ return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
+ default:
+ MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret );
+ return( ret );
+ }
+ }
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+ if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
+ return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
+ }
+
+ ret = mbedtls_pk_decrypt( private_key, p, len,
+ peer_pms, peer_pmslen, peer_pmssize,
+ ssl->conf->f_rng, ssl->conf->p_rng );
+ return( ret );
+}
+
+static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
+ const unsigned char *p,
+ const unsigned char *end,
+ size_t pms_offset )
+{
+ int ret;
+ unsigned char *pms = ssl->handshake->premaster + pms_offset;
+ unsigned char ver[2];
+ unsigned char fake_pms[48], peer_pms[48];
+ unsigned char mask;
+ size_t i, peer_pmslen;
+ unsigned int diff;
+
+ /* In case of a failure in decryption, the decryption may write less than
+ * 2 bytes of output, but we always read the first two bytes. It doesn't
+ * matter in the end because diff will be nonzero in that case due to
+ * peer_pmslen being less than 48, and we only care whether diff is 0.
+ * But do initialize peer_pms for robustness anyway. This also makes
+ * memory analyzers happy (don't access uninitialized memory, even
+ * if it's an unsigned char). */
+ peer_pms[0] = peer_pms[1] = ~0;
+
+ ret = ssl_decrypt_encrypted_pms( ssl, p, end,
+ peer_pms,
+ &peer_pmslen,
+ sizeof( peer_pms ) );
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
+ return( ret );
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
mbedtls_ssl_write_version( ssl->handshake->max_major_ver,
- ssl->handshake->max_minor_ver,
- ssl->conf->transport, ver );
+ ssl->handshake->max_minor_ver,
+ ssl->conf->transport, ver );
+
+ /* Avoid data-dependent branches while checking for invalid
+ * padding, to protect against timing-based Bleichenbacher-type
+ * attacks. */
+ diff = (unsigned int) ret;
+ diff |= peer_pmslen ^ 48;
+ diff |= peer_pms[0] ^ ver[0];
+ diff |= peer_pms[1] ^ ver[1];
+
+ /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
+ /* MSVC has a warning about unary minus on unsigned, but this is
+ * well-defined and precisely what we want to do here */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+ mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
/*
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
* must not cause the connection to end immediately; instead, send a
* bad_record_mac later in the handshake.
- * Also, avoid data-dependant branches here to protect against
- * timing-based variants.
+ * To protect against timing-based variants of the attack, we must
+ * not have any branch that depends on whether the decryption was
+ * successful. In particular, always generate the fake premaster secret,
+ * regardless of whether it will ultimately influence the output or not.
*/
ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
if( ret != 0 )
+ {
+ /* It's ok to abort on an RNG failure, since this does not reveal
+ * anything about the RSA decryption. */
return( ret );
-
- ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len,
- peer_pms, &peer_pmslen,
- sizeof( peer_pms ),
- ssl->conf->f_rng, ssl->conf->p_rng );
-
- diff = (unsigned int) ret;
- diff |= peer_pmslen ^ 48;
- diff |= peer_pms[0] ^ ver[0];
- diff |= peer_pms[1] ^ ver[1];
+ }
#if defined(MBEDTLS_SSL_DEBUG_ALL)
if( diff != 0 )
@@ -3352,18 +3631,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
}
ssl->handshake->pmslen = 48;
- /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
- /* MSVC has a warning about unary minus on unsigned, but this is
- * well-defined and precisely what we want to do here */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
- mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
+ /* Set pms to either the true or the fake PMS, without
+ * data-dependent branches. */
for( i = 0; i < ssl->handshake->pmslen; i++ )
pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
@@ -3445,7 +3714,21 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \
+ ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) )
+ if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) &&
+ ( ssl->handshake->async_in_progress != 0 ) )
+ {
+ /* We've already read a record and there is an asynchronous
+ * operation in progress to decrypt it. So skip reading the
+ * record. */
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) );
+ }
+ else
+#endif
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -3557,6 +3840,19 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ if ( ssl->handshake->async_in_progress != 0 )
+ {
+ /* There is an asynchronous operation in progress to
+ * decrypt the encrypted premaster secret, so skip
+ * directly to resuming this operation. */
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) );
+ /* Update p to skip the PSK identity. ssl_parse_encrypted_pms
+ * won't actually use it, but maintain p anyway for robustness. */
+ p += ssl->conf->psk_identity_len + 2;
+ }
+ else
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
@@ -3742,25 +4038,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
}
/* Read the message without adding it to the checksum */
- do {
-
- do ret = mbedtls_ssl_read_record_layer( ssl );
- while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
-
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
- return( ret );
- }
-
- ret = mbedtls_ssl_handle_message_type( ssl );
-
- } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
- MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
-
+ ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ );
if( 0 != ret )
{
- MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret );
return( ret );
}
@@ -3926,7 +4207,7 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket,
ssl->session_negotiate,
ssl->out_msg + 10,
- ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN,
+ ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
&tlen, &lifetime ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret );
@@ -3949,9 +4230,9 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
*/
ssl->handshake->new_session_ticket = 0;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -3980,10 +4261,10 @@ int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
{
- if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
return( ret );
}
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
switch( ssl->state )
{
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index a2b304869e..985b7cd507 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -97,7 +97,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
uint32_t current_time = (uint32_t) mbedtls_time( NULL );
uint32_t key_time = ctx->keys[ctx->active].generation_time;
- if( current_time > key_time &&
+ if( current_time >= key_time &&
current_time - key_time < ctx->ticket_lifetime )
{
return( 0 );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index bc9dc77e16..bf43e8894b 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -54,6 +54,9 @@
#include "mbedtls/oid.h"
#endif
+static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
+static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
+
/* Length of the "epoch" field in the record header */
static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl )
{
@@ -96,7 +99,101 @@ static int ssl_check_timer( mbedtls_ssl_context *ssl )
return( 0 );
}
+static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform );
+static void ssl_update_in_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform );
+
+#define SSL_DONT_FORCE_FLUSH 0
+#define SSL_FORCE_FLUSH 1
+
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+/* Forward declarations for functions related to message buffering. */
+static void ssl_buffering_free( mbedtls_ssl_context *ssl );
+static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
+ uint8_t slot );
+static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_buffer_message( mbedtls_ssl_context *ssl );
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl );
+static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
+
+static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl );
+static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
+{
+ size_t mtu = ssl_get_current_mtu( ssl );
+
+ if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN )
+ return( mtu );
+
+ return( MBEDTLS_SSL_OUT_BUFFER_LEN );
+}
+
+static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
+{
+ size_t const bytes_written = ssl->out_left;
+ size_t const mtu = ssl_get_maximum_datagram_size( ssl );
+
+ /* Double-check that the write-index hasn't gone
+ * past what we can transmit in a single datagram. */
+ if( bytes_written > mtu )
+ {
+ /* Should never happen... */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ return( (int) ( mtu - bytes_written ) );
+}
+
+static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
+{
+ int ret;
+ size_t remaining, expansion;
+ size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
+
+ if( max_len > mfl )
+ max_len = mfl;
+
+ /* By the standard (RFC 6066 Sect. 4), the MFL extension
+ * only limits the maximum record payload size, so in theory
+ * we would be allowed to pack multiple records of payload size
+ * MFL into a single datagram. However, this would mean that there's
+ * no way to explicitly communicate MTU restrictions to the peer.
+ *
+ * The following reduction of max_len makes sure that we never
+ * write datagrams larger than MFL + Record Expansion Overhead.
+ */
+ if( max_len <= ssl->out_left )
+ return( 0 );
+
+ max_len -= ssl->out_left;
+#endif
+
+ ret = ssl_get_remaining_space_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+ remaining = (size_t) ret;
+
+ ret = mbedtls_ssl_get_record_expansion( ssl );
+ if( ret < 0 )
+ return( ret );
+ expansion = (size_t) ret;
+
+ if( remaining <= expansion )
+ return( 0 );
+
+ remaining -= expansion;
+ if( remaining >= max_len )
+ remaining = max_len;
+
+ return( (int) remaining );
+}
+
/*
* Double the retransmit timeout value, within the allowed range,
* returning -1 if the maximum value has already been reached.
@@ -108,6 +205,18 @@ static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
return( -1 );
+ /* Implement the final paragraph of RFC 6347 section 4.1.1.1
+ * in the following way: after the initial transmission and a first
+ * retransmission, back off to a temporary estimated MTU of 508 bytes.
+ * This value is guaranteed to be deliverable (if not guaranteed to be
+ * delivered) of any compliant IPv4 (and IPv6) network, and should work
+ * on most non-IP stacks too. */
+ if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
+ {
+ ssl->handshake->mtu = 508;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
+ }
+
new_timeout = 2 * ssl->handshake->retransmit_timeout;
/* Avoid arithmetic overflow and range overflow */
@@ -141,14 +250,24 @@ static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
* } MaxFragmentLength;
* and we add 0 -> extension unused
*/
-static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] =
+static unsigned int ssl_mfl_code_to_length( int mfl )
{
- MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */
- 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */
- 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */
- 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */
- 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */
-};
+ switch( mfl )
+ {
+ case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
+ return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN );
+ case MBEDTLS_SSL_MAX_FRAG_LEN_512:
+ return 512;
+ case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
+ return 1024;
+ case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
+ return 2048;
+ case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
+ return 4096;
+ default:
+ return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN );
+ }
+}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_CLI_C)
@@ -688,18 +807,32 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
transform->keylen = cipher_info->key_bitlen / 8;
if( cipher_info->mode == MBEDTLS_MODE_GCM ||
- cipher_info->mode == MBEDTLS_MODE_CCM )
+ cipher_info->mode == MBEDTLS_MODE_CCM ||
+ cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
{
+ size_t taglen, explicit_ivlen;
+
transform->maclen = 0;
mac_key_len = 0;
+ /* All modes haves 96-bit IVs;
+ * GCM and CCM has 4 implicit and 8 explicit bytes
+ * ChachaPoly has all 12 bytes implicit
+ */
transform->ivlen = 12;
- transform->fixed_ivlen = 4;
+ if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
+ transform->fixed_ivlen = 12;
+ else
+ transform->fixed_ivlen = 4;
- /* Minimum length is expicit IV + tag */
- transform->minlen = transform->ivlen - transform->fixed_ivlen
- + ( transform->ciphersuite_info->flags &
- MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 );
+ /* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */
+ taglen = transform->ciphersuite_info->flags &
+ MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
+
+
+ /* Minimum length of encrypted record */
+ explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
+ transform->minlen = explicit_ivlen + taglen;
}
else
{
@@ -956,11 +1089,11 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
if( ssl->compress_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) );
- ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN );
+ ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
if( ssl->compress_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
- MBEDTLS_SSL_BUFFER_LEN ) );
+ MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) );
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
}
}
@@ -1151,6 +1284,9 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
* other_secret already set by the ClientKeyExchange message,
* and is 48 bytes long
*/
+ if( end - p < 2 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
*p++ = 0;
*p++ = 48;
p += 48;
@@ -1272,10 +1408,31 @@ static void ssl_mac( mbedtls_md_context_t *md_ctx,
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \
( defined(MBEDTLS_CIPHER_MODE_CBC) && \
- ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) )
+ ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C)) )
#define SSL_SOME_MODES_USE_MAC
#endif
+/* The function below is only used in the Lucky 13 counter-measure in
+ * ssl_decrypt_buf(). These are the defines that guard the call site. */
+#if defined(SSL_SOME_MODES_USE_MAC) && \
+ ( defined(MBEDTLS_SSL_PROTO_TLS1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2) )
+/* This function makes sure every byte in the memory region is accessed
+ * (in ascending addresses order) */
+static void ssl_read_memory( unsigned char *p, size_t len )
+{
+ unsigned char acc = 0;
+ volatile unsigned char force;
+
+ for( ; len != 0; p++, len-- )
+ acc ^= *p;
+
+ force = acc;
+ (void) force;
+}
+#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */
+
/*
* Encryption/decryption functions
*/
@@ -1297,14 +1454,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
ssl->out_msg, ssl->out_msglen );
- if( ssl->out_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
- (unsigned) ssl->out_msglen,
- MBEDTLS_SSL_MAX_CONTENT_LEN ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
-
/*
* Add MAC before if needed
*/
@@ -1394,17 +1543,26 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_GCM_C) || \
+ defined(MBEDTLS_CCM_C) || \
+ defined(MBEDTLS_CHACHAPOLY_C)
if( mode == MBEDTLS_MODE_GCM ||
- mode == MBEDTLS_MODE_CCM )
+ mode == MBEDTLS_MODE_CCM ||
+ mode == MBEDTLS_MODE_CHACHAPOLY )
{
int ret;
size_t enc_msglen, olen;
unsigned char *enc_msg;
unsigned char add_data[13];
- unsigned char taglen = ssl->transform_out->ciphersuite_info->flags &
+ unsigned char iv[12];
+ mbedtls_ssl_transform *transform = ssl->transform_out;
+ unsigned char taglen = transform->ciphersuite_info->flags &
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
+ size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
+ /*
+ * Prepare additional authenticated data
+ */
memcpy( add_data, ssl->out_ctr, 8 );
add_data[8] = ssl->out_msgtype;
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
@@ -1412,44 +1570,57 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF;
add_data[12] = ssl->out_msglen & 0xFF;
- MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
- add_data, 13 );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 );
/*
* Generate IV
*/
- if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 )
+ if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
+ {
+ /* GCM and CCM: fixed || explicit (=seqnum) */
+ memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
+ memcpy( iv + transform->fixed_ivlen, ssl->out_ctr, 8 );
+ memcpy( ssl->out_iv, ssl->out_ctr, 8 );
+
+ }
+ else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
+ {
+ /* ChachaPoly: fixed XOR sequence number */
+ unsigned char i;
+
+ memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
+
+ for( i = 0; i < 8; i++ )
+ iv[i+4] ^= ssl->out_ctr[i];
+ }
+ else
{
/* Reminder if we ever add an AEAD mode with a different size */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
- ssl->out_ctr, 8 );
- memcpy( ssl->out_iv, ssl->out_ctr, 8 );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv,
- ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
+ iv, transform->ivlen );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
+ ssl->out_iv, explicit_ivlen );
/*
- * Fix pointer positions and message length with added IV
+ * Fix message length with added IV
*/
enc_msg = ssl->out_msg;
enc_msglen = ssl->out_msglen;
- ssl->out_msglen += ssl->transform_out->ivlen -
- ssl->transform_out->fixed_ivlen;
+ ssl->out_msglen += explicit_ivlen;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including %d bytes of padding",
- ssl->out_msglen, 0 ) );
+ "including 0 bytes of padding",
+ ssl->out_msglen ) );
/*
* Encrypt and authenticate
*/
- if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc,
- ssl->transform_out->iv_enc,
- ssl->transform_out->ivlen,
+ if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc,
+ iv, transform->ivlen,
add_data, 13,
enc_msg, enc_msglen,
enc_msg, &olen,
@@ -1473,7 +1644,7 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
else
#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
#if defined(MBEDTLS_CIPHER_MODE_CBC) && \
- ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) )
+ ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) )
if( mode == MBEDTLS_MODE_CBC )
{
int ret;
@@ -1556,6 +1727,8 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
if( auth_done == 0 )
{
+ unsigned char mac[MBEDTLS_SSL_MAC_ADD];
+
/*
* MAC(MAC_write_key, seq_num +
* TLSCipherText.type +
@@ -1578,10 +1751,12 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 );
mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc,
ssl->out_iv, ssl->out_msglen );
- mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc,
- ssl->out_iv + ssl->out_msglen );
+ mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac );
mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc );
+ memcpy( ssl->out_iv + ssl->out_msglen, mac,
+ ssl->transform_out->maclen );
+
ssl->out_msglen += ssl->transform_out->maclen;
auth_done++;
}
@@ -1589,7 +1764,7 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_CIPHER_MODE_CBC &&
- ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */
+ ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
@@ -1609,7 +1784,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
{
- size_t i;
mbedtls_cipher_mode_t mode;
int auth_done = 0;
#if defined(SSL_SOME_MODES_USE_MAC)
@@ -1659,20 +1833,27 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_GCM_C) || \
+ defined(MBEDTLS_CCM_C) || \
+ defined(MBEDTLS_CHACHAPOLY_C)
if( mode == MBEDTLS_MODE_GCM ||
- mode == MBEDTLS_MODE_CCM )
+ mode == MBEDTLS_MODE_CCM ||
+ mode == MBEDTLS_MODE_CHACHAPOLY )
{
int ret;
size_t dec_msglen, olen;
unsigned char *dec_msg;
unsigned char *dec_msg_result;
unsigned char add_data[13];
- unsigned char taglen = ssl->transform_in->ciphersuite_info->flags &
+ unsigned char iv[12];
+ mbedtls_ssl_transform *transform = ssl->transform_in;
+ unsigned char taglen = transform->ciphersuite_info->flags &
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
- size_t explicit_iv_len = ssl->transform_in->ivlen -
- ssl->transform_in->fixed_ivlen;
+ size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
+ /*
+ * Compute and update sizes
+ */
if( ssl->in_msglen < explicit_iv_len + taglen )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
@@ -1686,6 +1867,9 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
dec_msg_result = ssl->in_msg;
ssl->in_msglen = dec_msglen;
+ /*
+ * Prepare additional authenticated data
+ */
memcpy( add_data, ssl->in_ctr, 8 );
add_data[8] = ssl->in_msgtype;
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
@@ -1693,23 +1877,43 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
add_data[12] = ssl->in_msglen & 0xFF;
- MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
- add_data, 13 );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 );
- memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen,
- ssl->in_iv,
- ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen );
+ /*
+ * Prepare IV
+ */
+ if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
+ {
+ /* GCM and CCM: fixed || explicit (transmitted) */
+ memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
+ memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 );
- MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec,
- ssl->transform_in->ivlen );
+ }
+ else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
+ {
+ /* ChachaPoly: fixed XOR sequence number */
+ unsigned char i;
+
+ memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
+
+ for( i = 0; i < 8; i++ )
+ iv[i+4] ^= ssl->in_ctr[i];
+ }
+ else
+ {
+ /* Reminder if we ever add an AEAD mode with a different size */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen );
/*
* Decrypt and authenticate
*/
if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec,
- ssl->transform_in->iv_dec,
- ssl->transform_in->ivlen,
+ iv, transform->ivlen,
add_data, 13,
dec_msg, dec_msglen,
dec_msg_result, &olen,
@@ -1733,7 +1937,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
else
#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
#if defined(MBEDTLS_CIPHER_MODE_CBC) && \
- ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) )
+ ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) )
if( mode == MBEDTLS_MODE_CBC )
{
/*
@@ -1827,6 +2031,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
*/
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
{
+ unsigned char i;
dec_msglen -= ssl->transform_in->ivlen;
ssl->in_msglen -= ssl->transform_in->ivlen;
@@ -1900,27 +2105,28 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
* and fake check up to 256 bytes of padding
*/
size_t pad_count = 0, real_count = 1;
- size_t padding_idx = ssl->in_msglen - padlen - 1;
+ size_t padding_idx = ssl->in_msglen - padlen;
+ size_t i;
/*
* Padding is guaranteed to be incorrect if:
- * 1. padlen >= ssl->in_msglen
+ * 1. padlen > ssl->in_msglen
*
- * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN +
+ * 2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN +
* ssl->transform_in->maclen
*
* In both cases we reset padding_idx to a safe value (0) to
* prevent out-of-buffer reads.
*/
- correct &= ( ssl->in_msglen >= padlen + 1 );
- correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN +
+ correct &= ( padlen <= ssl->in_msglen );
+ correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN +
ssl->transform_in->maclen );
padding_idx *= correct;
- for( i = 1; i <= 256; i++ )
+ for( i = 0; i < 256; i++ )
{
- real_count &= ( i <= padlen );
+ real_count &= ( i < padlen );
pad_count += real_count *
( ssl->in_msg[padding_idx + i] == padlen - 1 );
}
@@ -1945,14 +2151,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_CIPHER_MODE_CBC &&
- ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */
+ ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption",
ssl->in_msg, ssl->in_msglen );
+#endif
/*
* Authenticate if not done yet.
@@ -1985,20 +2193,69 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
{
/*
* Process MAC and always update for padlen afterwards to make
- * total time independent of padlen
- *
- * extra_run compensates MAC check for padlen
+ * total time independent of padlen.
*
* Known timing attacks:
* - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
*
- * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values
- * correctly. (We round down instead of up, so -56 is the correct
- * value for our calculations instead of -55)
+ * To compensate for different timings for the MAC calculation
+ * depending on how much padding was removed (which is determined
+ * by padlen), process extra_run more blocks through the hash
+ * function.
+ *
+ * The formula in the paper is
+ * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 )
+ * where L1 is the size of the header plus the decrypted message
+ * plus CBC padding and L2 is the size of the header plus the
+ * decrypted message. This is for an underlying hash function
+ * with 64-byte blocks.
+ * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values
+ * correctly. We round down instead of up, so -56 is the correct
+ * value for our calculations instead of -55.
+ *
+ * Repeat the formula rather than defining a block_size variable.
+ * This avoids requiring division by a variable at runtime
+ * (which would be marginally less efficient and would require
+ * linking an extra division function in some builds).
*/
size_t j, extra_run = 0;
- extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
- ( 13 + ssl->in_msglen + 8 ) / 64;
+
+ /*
+ * The next two sizes are the minimum and maximum values of
+ * in_msglen over all padlen values.
+ *
+ * They're independent of padlen, since we previously did
+ * in_msglen -= padlen.
+ *
+ * Note that max_len + maclen is never more than the buffer
+ * length, as we previously did in_msglen -= maclen too.
+ */
+ const size_t max_len = ssl->in_msglen + padlen;
+ const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
+
+ switch( ssl->transform_in->ciphersuite_info->mac )
+ {
+#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \
+ defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_MD5:
+ case MBEDTLS_MD_SHA1:
+ case MBEDTLS_MD_SHA256:
+ /* 8 bytes of message size, 64-byte compression blocks */
+ extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
+ ( 13 + ssl->in_msglen + 8 ) / 64;
+ break;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+ case MBEDTLS_MD_SHA384:
+ /* 16 bytes of message size, 128-byte compression blocks */
+ extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 -
+ ( 13 + ssl->in_msglen + 16 ) / 128;
+ break;
+#endif
+ default:
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
extra_run &= correct * 0xFF;
@@ -2007,12 +2264,25 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 );
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg,
ssl->in_msglen );
+ /* Make sure we access everything even when padlen > 0. This
+ * makes the synchronisation requirements for just-in-time
+ * Prime+Probe attacks much tighter and hopefully impractical. */
+ ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen );
mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect );
- /* Call mbedtls_md_process at least once due to cache attacks */
+
+ /* Call mbedtls_md_process at least once due to cache attacks
+ * that observe whether md_process() was called of not */
for( j = 0; j < extra_run + 1; j++ )
mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec );
+
+ /* Make sure we access all the memory that could contain the MAC,
+ * before we check it in the next code block. This makes the
+ * synchronisation requirements for just-in-time Prime+Probe
+ * attacks much tighter and hopefully impractical. */
+ ssl_read_memory( ssl->in_msg + min_len,
+ max_len - min_len + ssl->transform_in->maclen );
}
else
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@@ -2022,9 +2292,11 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen );
MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen,
ssl->transform_in->maclen );
+#endif
if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect,
ssl->transform_in->maclen ) != 0 )
@@ -2035,13 +2307,13 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
correct = 0;
}
auth_done++;
-
- /*
- * Finally check the correct flag
- */
- if( correct == 0 )
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
}
+
+ /*
+ * Finally check the correct flag
+ */
+ if( correct == 0 )
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
#endif /* SSL_SOME_MODES_USE_MAC */
/* Make extra sure authentication was performed, exactly once */
@@ -2053,6 +2325,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
if( ssl->in_msglen == 0 )
{
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
+ && ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
+ {
+ /* TLS v1.2 explicitly disallows zero-length messages which are not application data */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
ssl->nb_zero++;
/*
@@ -2077,6 +2359,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
else
#endif
{
+ unsigned char i;
for( i = 8; i > ssl_ep_len( ssl ); i-- )
if( ++ssl->in_ctr[i - 1] != 0 )
break;
@@ -2126,7 +2409,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl )
ssl->transform_out->ctx_deflate.next_in = msg_pre;
ssl->transform_out->ctx_deflate.avail_in = len_pre;
ssl->transform_out->ctx_deflate.next_out = msg_post;
- ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN - bytes_written;
+ ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written;
ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
if( ret != Z_OK )
@@ -2135,7 +2418,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
}
- ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN -
+ ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN -
ssl->transform_out->ctx_deflate.avail_out - bytes_written;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
@@ -2173,7 +2456,7 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
ssl->transform_in->ctx_inflate.next_in = msg_pre;
ssl->transform_in->ctx_inflate.avail_in = len_pre;
ssl->transform_in->ctx_inflate.next_out = msg_post;
- ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_BUFFER_LEN -
+ ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN -
header_bytes;
ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
@@ -2183,7 +2466,7 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
}
- ssl->in_msglen = MBEDTLS_SSL_BUFFER_LEN -
+ ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN -
ssl->transform_in->ctx_inflate.avail_out - header_bytes;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
@@ -2258,7 +2541,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
+ if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -2344,7 +2627,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
}
else
{
- len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
+ len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
timeout = ssl->handshake->retransmit_timeout;
@@ -2466,7 +2749,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
{
int ret;
- unsigned char *buf, i;
+ unsigned char *buf;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
@@ -2489,8 +2772,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
- buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) +
- ssl->out_msglen - ssl->out_left;
+ buf = ssl->out_hdr - ssl->out_left;
ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left );
MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret );
@@ -2509,16 +2791,17 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
ssl->out_left -= ret;
}
- for( i = 8; i > ssl_ep_len( ssl ); i-- )
- if( ++ssl->out_ctr[i - 1] != 0 )
- break;
-
- /* The loop goes to its end iff the counter is wrapping */
- if( i == ssl_ep_len( ssl ) )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
- return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+ ssl->out_hdr = ssl->out_buf;
}
+ else
+#endif
+ {
+ ssl->out_hdr = ssl->out_buf + 8;
+ }
+ ssl_update_out_pointers( ssl, ssl->transform_out );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
@@ -2535,6 +2818,9 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
static int ssl_flight_append( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_flight_item *msg;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight",
+ ssl->out_msg, ssl->out_msglen );
/* Allocate space for current message */
if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL )
@@ -2568,6 +2854,7 @@ static int ssl_flight_append( mbedtls_ssl_context *ssl )
cur->next = msg;
}
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) );
return( 0 );
}
@@ -2616,19 +2903,12 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl )
ssl->handshake->alt_transform_out = tmp_transform;
/* Swap epoch + sequence_number */
- memcpy( tmp_out_ctr, ssl->out_ctr, 8 );
- memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 );
+ memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 );
+ memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 );
memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 );
/* Adjust to the newly activated transform */
- if( ssl->transform_out != NULL &&
- ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen -
- ssl->transform_out->fixed_ivlen;
- }
- else
- ssl->out_msg = ssl->out_iv;
+ ssl_update_out_pointers( ssl, ssl->transform_out );
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_activate != NULL )
@@ -2644,20 +2924,38 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl )
/*
* Retransmit the current flight of messages.
+ */
+int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
+{
+ int ret = 0;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
+
+ ret = mbedtls_ssl_flight_transmit( ssl );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
+
+ return( ret );
+}
+
+/*
+ * Transmit or retransmit the current flight of messages.
*
* Need to remember the current message in case flush_output returns
* WANT_WRITE, causing us to exit this function and come back later.
* This function must be called until state is no longer SENDING.
*/
-int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
+ int ret;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) );
ssl->handshake->cur_msg = ssl->handshake->flight;
+ ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
ssl_swap_epochs( ssl );
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
@@ -2665,33 +2963,129 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
while( ssl->handshake->cur_msg != NULL )
{
- int ret;
- mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg;
+ size_t max_frag_len;
+ const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
+
+ int const is_finished =
+ ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ cur->p[0] == MBEDTLS_SSL_HS_FINISHED );
+
+ uint8_t const force_flush = ssl->disable_datagram_packing == 1 ?
+ SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
/* Swap epochs before sending Finished: we can't do it after
* sending ChangeCipherSpec, in case write returns WANT_READ.
* Must be done before copying, may change out_msg pointer */
- if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
- cur->p[0] == MBEDTLS_SSL_HS_FINISHED )
+ if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
{
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
ssl_swap_epochs( ssl );
}
- memcpy( ssl->out_msg, cur->p, cur->len );
- ssl->out_msglen = cur->len;
- ssl->out_msgtype = cur->type;
+ ret = ssl_get_remaining_payload_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+ max_frag_len = (size_t) ret;
- ssl->handshake->cur_msg = cur->next;
+ /* CCS is copied as is, while HS messages may need fragmentation */
+ if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ if( max_frag_len == 0 )
+ {
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
- MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 );
+ continue;
+ }
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ memcpy( ssl->out_msg, cur->p, cur->len );
+ ssl->out_msglen = cur->len;
+ ssl->out_msgtype = cur->type;
+
+ /* Update position inside current message */
+ ssl->handshake->cur_msg_p += cur->len;
+ }
+ else
+ {
+ const unsigned char * const p = ssl->handshake->cur_msg_p;
+ const size_t hs_len = cur->len - 12;
+ const size_t frag_off = p - ( cur->p + 12 );
+ const size_t rem_len = hs_len - frag_off;
+ size_t cur_hs_frag_len, max_hs_frag_len;
+
+ if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
+ {
+ if( is_finished )
+ ssl_swap_epochs( ssl );
+
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ continue;
+ }
+ max_hs_frag_len = max_frag_len - 12;
+
+ cur_hs_frag_len = rem_len > max_hs_frag_len ?
+ max_hs_frag_len : rem_len;
+
+ if( frag_off == 0 && cur_hs_frag_len != hs_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)",
+ (unsigned) cur_hs_frag_len,
+ (unsigned) max_hs_frag_len ) );
+ }
+
+ /* Messages are stored with handshake headers as if not fragmented,
+ * copy beginning of headers then fill fragmentation fields.
+ * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
+ memcpy( ssl->out_msg, cur->p, 6 );
+
+ ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff );
+ ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff );
+ ssl->out_msg[8] = ( ( frag_off ) & 0xff );
+
+ ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff );
+ ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff );
+ ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff );
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
+
+ /* Copy the handshake message content and set records fields */
+ memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
+ ssl->out_msglen = cur_hs_frag_len + 12;
+ ssl->out_msgtype = cur->type;
+
+ /* Update position inside current message */
+ ssl->handshake->cur_msg_p += cur_hs_frag_len;
+ }
+
+ /* If done with the current message move to the next one if any */
+ if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
+ {
+ if( cur->next != NULL )
+ {
+ ssl->handshake->cur_msg = cur->next;
+ ssl->handshake->cur_msg_p = cur->next->p + 12;
+ }
+ else
+ {
+ ssl->handshake->cur_msg = NULL;
+ ssl->handshake->cur_msg_p = NULL;
+ }
+ }
+
+ /* Actually send the message out */
+ if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
return( ret );
}
}
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ /* Update state and set timer */
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
else
@@ -2700,7 +3094,7 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
}
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) );
return( 0 );
}
@@ -2718,6 +3112,12 @@ void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl )
/* The next incoming flight will start with this msg_seq */
ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;
+ /* We don't want to remember CCS's across flight boundaries. */
+ ssl->handshake->buffering.seen_ccs = 0;
+
+ /* Clear future message buffering structure. */
+ ssl_buffering_free( ssl );
+
/* Cancel timer */
ssl_set_timer( ssl, 0 );
@@ -2749,43 +3149,100 @@ void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_SSL_PROTO_DTLS */
/*
- * Record layer functions
+ * Handshake layer functions
*/
/*
- * Write current record.
- * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg.
+ * Write (DTLS: or queue) current handshake (including CCS) message.
+ *
+ * - fill in handshake headers
+ * - update handshake checksum
+ * - DTLS: save message for resending
+ * - then pass to the record layer
+ *
+ * DTLS: except for HelloRequest, messages are only queued, and will only be
+ * actually sent when calling flight_transmit() or resend().
+ *
+ * Inputs:
+ * - ssl->out_msglen: 4 + actual handshake message len
+ * (4 is the size of handshake headers for TLS)
+ * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)
+ * - ssl->out_msg + 4: the handshake message body
+ *
+ * Outputs, ie state before passing to flight_append() or write_record():
+ * - ssl->out_msglen: the length of the record contents
+ * (including handshake headers but excluding record headers)
+ * - ssl->out_msg: the record contents (handshake headers + content)
*/
-int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
{
- int ret, done = 0, out_msg_type;
- size_t len = ssl->out_msglen;
+ int ret;
+ const size_t hs_len = ssl->out_msglen - 4;
+ const unsigned char hs_type = ssl->out_msg[0];
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) );
+
+ /*
+ * Sanity checks
+ */
+ if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE &&
+ ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ /* In SSLv3, the client might send a NoCertificate alert. */
+#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
+ if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
+ ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT &&
+ ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
+#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+
+ if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST &&
+ ssl->handshake == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake != NULL &&
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
{
- ; /* Skip special handshake treatment when resending */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- else
#endif
+
+ /* Double-check that we did not exceed the bounds
+ * of the outgoing record buffer.
+ * This should never fail as the various message
+ * writing functions must obey the bounds of the
+ * outgoing record buffer, but better be safe.
+ *
+ * Note: We deliberately do not check for the MTU or MFL here.
+ */
+ if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
+ "size %u, maximum %u",
+ (unsigned) ssl->out_msglen,
+ (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ /*
+ * Fill handshake headers
+ */
if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
{
- out_msg_type = ssl->out_msg[0];
-
- if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST &&
- ssl->handshake == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 );
- ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 );
- ssl->out_msg[3] = (unsigned char)( ( len - 4 ) );
+ ssl->out_msg[1] = (unsigned char)( hs_len >> 16 );
+ ssl->out_msg[2] = (unsigned char)( hs_len >> 8 );
+ ssl->out_msg[3] = (unsigned char)( hs_len );
/*
* DTLS has additional fields in the Handshake layer,
@@ -2798,21 +3255,20 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
/* Make room for the additional DTLS fields */
- if( MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen < 8 )
+ if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
"size %u, maximum %u",
- (unsigned) ( ssl->in_hslen - 4 ),
- (unsigned) ( MBEDTLS_SSL_MAX_CONTENT_LEN - 12 ) ) );
+ (unsigned) ( hs_len ),
+ (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 );
+ memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len );
ssl->out_msglen += 8;
- len += 8;
/* Write message_seq and update it, except for HelloRequest */
- if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
+ if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
{
ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF;
ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF;
@@ -2824,23 +3280,23 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
ssl->out_msg[5] = 0;
}
- /* We don't fragment, so frag_offset = 0 and frag_len = len */
+ /* Handshake hashes are computed without fragmentation,
+ * so set frag_offset = 0 and frag_len = hs_len for now */
memset( ssl->out_msg + 6, 0x00, 3 );
memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 );
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
- if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
- ssl->handshake->update_checksum( ssl, ssl->out_msg, len );
+ /* Update running hashes of handshake messages seen */
+ if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
+ ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
}
- /* Save handshake and CCS messages for resending */
+ /* Either send now, or just save to be sent (and resent) later */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->handshake != NULL &&
- ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING &&
- ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ||
- ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) )
+ ( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||
+ hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) )
{
if( ( ret = ssl_flight_append( ssl ) ) != 0 )
{
@@ -2848,7 +3304,40 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
return( ret );
}
}
+ else
#endif
+ {
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) );
+
+ return( 0 );
+}
+
+/*
+ * Record layer functions
+ */
+
+/*
+ * Write current record.
+ *
+ * Uses:
+ * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)
+ * - ssl->out_msglen: length of the record content (excl headers)
+ * - ssl->out_msg: record content
+ */
+int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
+{
+ int ret, done = 0;
+ size_t len = ssl->out_msglen;
+ uint8_t flush = force_flush;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
#if defined(MBEDTLS_ZLIB_SUPPORT)
if( ssl->transform_out != NULL &&
@@ -2882,10 +3371,14 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
if( !done )
{
+ unsigned i;
+ size_t protected_record_size;
+
ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
ssl->conf->transport, ssl->out_hdr + 1 );
+ memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
ssl->out_len[0] = (unsigned char)( len >> 8 );
ssl->out_len[1] = (unsigned char)( len );
@@ -2902,18 +3395,76 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
ssl->out_len[1] = (unsigned char)( len );
}
- ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen;
+ protected_record_size = len + mbedtls_ssl_hdr_len( ssl );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ /* In case of DTLS, double-check that we don't exceed
+ * the remaining space in the datagram. */
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ret = ssl_get_remaining_space_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+
+ if( protected_record_size > (size_t) ret )
+ {
+ /* Should never happen */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
- "version = [%d:%d], msglen = %d",
- ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2],
- ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) );
+ "version = [%d:%d], msglen = %d",
+ ssl->out_hdr[0], ssl->out_hdr[1],
+ ssl->out_hdr[2], len ) );
MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
- ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen );
+ ssl->out_hdr, protected_record_size );
+
+ ssl->out_left += protected_record_size;
+ ssl->out_hdr += protected_record_size;
+ ssl_update_out_pointers( ssl, ssl->transform_out );
+
+ for( i = 8; i > ssl_ep_len( ssl ); i-- )
+ if( ++ssl->cur_out_ctr[i - 1] != 0 )
+ break;
+
+ /* The loop goes to its end iff the counter is wrapping */
+ if( i == ssl_ep_len( ssl ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
+ return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+ }
}
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ flush == SSL_DONT_FORCE_FLUSH )
+ {
+ size_t remaining;
+ ret = ssl_get_remaining_payload_in_datagram( ssl );
+ if( ret < 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram",
+ ret );
+ return( ret );
+ }
+
+ remaining = (size_t) ret;
+ if( remaining == 0 )
+ {
+ flush = SSL_FORCE_FLUSH;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ if( ( flush == SSL_FORCE_FLUSH ) &&
+ ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
return( ret );
@@ -2925,6 +3476,52 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
+{
+ if( ssl->in_msglen < ssl->in_hslen ||
+ memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 ||
+ memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 )
+ {
+ return( 1 );
+ }
+ return( 0 );
+}
+
+static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[9] << 16 ) |
+ ( ssl->in_msg[10] << 8 ) |
+ ssl->in_msg[11] );
+}
+
+static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[6] << 16 ) |
+ ( ssl->in_msg[7] << 8 ) |
+ ssl->in_msg[8] );
+}
+
+static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
+{
+ uint32_t msg_len, frag_off, frag_len;
+
+ msg_len = ssl_get_hs_total_len( ssl );
+ frag_off = ssl_get_hs_frag_off( ssl );
+ frag_len = ssl_get_hs_frag_len( ssl );
+
+ if( frag_off > msg_len )
+ return( -1 );
+
+ if( frag_len > msg_len - frag_off )
+ return( -1 );
+
+ if( frag_len + 12 > ssl->in_msglen )
+ return( -1 );
+
+ return( 0 );
+}
+
/*
* Mark bits in bitmask (used for DTLS HS reassembly)
*/
@@ -2986,162 +3583,30 @@ static int ssl_bitmask_check( unsigned char *mask, size_t len )
return( 0 );
}
-/*
- * Reassemble fragmented DTLS handshake messages.
- *
- * Use a temporary buffer for reassembly, divided in two parts:
- * - the first holds the reassembled message (including handshake header),
- * - the second holds a bitmask indicating which parts of the message
- * (excluding headers) have been received so far.
- */
-static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
+/* msg_len does not include the handshake header */
+static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
+ unsigned add_bitmap )
{
- unsigned char *msg, *bitmask;
- size_t frag_len, frag_off;
- size_t msg_len = ssl->in_hslen - 12; /* Without headers */
+ size_t alloc_len;
- if( ssl->handshake == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) );
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
- }
+ alloc_len = 12; /* Handshake header */
+ alloc_len += msg_len; /* Content buffer */
- /*
- * For first fragment, check size and allocate buffer
- */
- if( ssl->handshake->hs_msg == NULL )
- {
- size_t alloc_len;
+ if( add_bitmap )
+ alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
- msg_len ) );
-
- if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) );
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- /* The bitmask needs one bit per byte of message excluding header */
- alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 );
-
- ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len );
- if( ssl->handshake->hs_msg == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) );
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- }
-
- /* Prepare final header: copy msg_type, length and message_seq,
- * then add standardised fragment_offset and fragment_length */
- memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 );
- memset( ssl->handshake->hs_msg + 6, 0, 3 );
- memcpy( ssl->handshake->hs_msg + 9,
- ssl->handshake->hs_msg + 1, 3 );
- }
- else
- {
- /* Make sure msg_type and length are consistent */
- if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
- }
-
- msg = ssl->handshake->hs_msg + 12;
- bitmask = msg + msg_len;
-
- /*
- * Check and copy current fragment
- */
- frag_off = ( ssl->in_msg[6] << 16 ) |
- ( ssl->in_msg[7] << 8 ) |
- ssl->in_msg[8];
- frag_len = ( ssl->in_msg[9] << 16 ) |
- ( ssl->in_msg[10] << 8 ) |
- ssl->in_msg[11];
-
- if( frag_off + frag_len > msg_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d",
- frag_off, frag_len, msg_len ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- if( frag_len + 12 > ssl->in_msglen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d",
- frag_len, ssl->in_msglen ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
- frag_off, frag_len ) );
-
- memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
- ssl_bitmask_set( bitmask, frag_off, frag_len );
-
- /*
- * Do we have the complete message by now?
- * If yes, finalize it, else ask to read the next record.
- */
- if( ssl_bitmask_check( bitmask, msg_len ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) );
- return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) );
-
- if( frag_len + 12 < ssl->in_msglen )
- {
- /*
- * We'got more handshake messages in the same record.
- * This case is not handled now because no know implementation does
- * that and it's hard to test, so we prefer to fail cleanly for now.
- */
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) );
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- if( ssl->in_left > ssl->next_record_offset )
- {
- /*
- * We've got more data in the buffer after the current record,
- * that we don't want to overwrite. Move it before writing the
- * reassembled message, and adjust in_left and next_record_offset.
- */
- unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset;
- unsigned char *new_remain = ssl->in_msg + ssl->in_hslen;
- size_t remain_len = ssl->in_left - ssl->next_record_offset;
-
- /* First compute and check new lengths */
- ssl->next_record_offset = new_remain - ssl->in_hdr;
- ssl->in_left = ssl->next_record_offset + remain_len;
-
- if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN -
- (size_t)( ssl->in_hdr - ssl->in_buf ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) );
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- }
-
- memmove( new_remain, cur_remain, remain_len );
- }
-
- memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen );
-
- mbedtls_free( ssl->handshake->hs_msg );
- ssl->handshake->hs_msg = NULL;
-
- MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message",
- ssl->in_msg, ssl->in_hslen );
-
- return( 0 );
+ return( alloc_len );
}
+
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[1] << 16 ) |
+ ( ssl->in_msg[2] << 8 ) |
+ ssl->in_msg[3] );
+}
+
int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
{
if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
@@ -3151,10 +3616,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
- ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + (
- ( ssl->in_msg[1] << 16 ) |
- ( ssl->in_msg[2] << 8 ) |
- ssl->in_msg[3] );
+ ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
" %d, type = %d, hslen = %d",
@@ -3166,12 +3628,26 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
int ret;
unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+ if( ssl_check_hs_header( ssl ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
if( ssl->handshake != NULL &&
( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
recv_msg_seq != ssl->handshake->in_msg_seq ) ||
( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
{
+ if( recv_msg_seq > ssl->handshake->in_msg_seq )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)",
+ recv_msg_seq,
+ ssl->handshake->in_msg_seq ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+
/* Retransmit only on last message from previous flight, to avoid
* too many retransmissions.
* Besides, No sane server ever retransmits HelloVerifyRequest */
@@ -3201,20 +3677,14 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
}
/* Wait until message completion to increment in_msg_seq */
- /* Reassemble if current message is fragmented or reassembly is
- * already in progress */
- if( ssl->in_msglen < ssl->in_hslen ||
- memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 ||
- memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ||
- ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) )
+ /* Message reassembly is handled alongside buffering of future
+ * messages; the commonality is that both handshake fragments and
+ * future messages cannot be forwarded immediately to the
+ * handshake logic layer. */
+ if( ssl_hs_is_proper_fragment( ssl ) == 1 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) );
-
- if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret );
- return( ret );
- }
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
}
}
else
@@ -3231,9 +3701,9 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
- ssl->handshake != NULL )
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
{
ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
}
@@ -3243,7 +3713,29 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ssl->handshake != NULL )
{
- ssl->handshake->in_msg_seq++;
+ unsigned offset;
+ mbedtls_ssl_hs_buffer *hs_buf;
+
+ /* Increment handshake sequence number */
+ hs->in_msg_seq++;
+
+ /*
+ * Clear up handshake buffering and reassembly structure.
+ */
+
+ /* Free first entry */
+ ssl_buffering_free_slot( ssl, 0 );
+
+ /* Shift all other entries */
+ for( offset = 0, hs_buf = &hs->buffering.hs[0];
+ offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
+ offset++, hs_buf++ )
+ {
+ *hs_buf = *(hs_buf + 1);
+ }
+
+ /* Create a fresh last entry */
+ memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
}
#endif
}
@@ -3496,7 +3988,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
ssl->conf->p_cookie,
ssl->cli_id, ssl->cli_id_len,
ssl->in_buf, ssl->in_left,
- ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len );
+ ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
@@ -3593,7 +4085,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
}
/* Check length against the size of our buffer */
- if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN
+ if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN
- (size_t)( ssl->in_msg - ssl->in_buf ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
@@ -3644,7 +4136,16 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+ {
+ /* Consider buffering the record. */
+ if( rec_epoch == (unsigned int) ssl->in_epoch + 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+ }
}
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
@@ -3657,15 +4158,6 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
}
#endif
- /* Drop unexpected ChangeCipherSpec messages */
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
- ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
- ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
- }
-
/* Drop unexpected ApplicationData records,
* except at the beginning of renegotiations */
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
@@ -3687,7 +4179,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
if( ssl->transform_in == NULL )
{
if( ssl->in_msglen < 1 ||
- ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3703,7 +4195,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_PROTO_SSL3)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
- ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
+ ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3716,7 +4208,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
*/
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
ssl->in_msglen > ssl->transform_in->minlen +
- MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
+ MBEDTLS_SSL_IN_CONTENT_LEN + 256 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3764,7 +4256,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
ssl->in_msg, ssl->in_msglen );
- if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3802,7 +4294,14 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl );
* RFC 6347 4.1.2.7) and continue reading until a valid record is found.
*
*/
-int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
+
+/* Helper functions for mbedtls_ssl_read_record(). */
+static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
+static int ssl_get_next_record( mbedtls_ssl_context *ssl );
+static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
+
+int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
+ unsigned update_hs_digest )
{
int ret;
@@ -3812,17 +4311,53 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
{
do {
- do ret = mbedtls_ssl_read_record_layer( ssl );
- while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
-
+ ret = ssl_consume_current_message( ssl );
if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
return( ret );
+
+ if( ssl_record_is_in_progress( ssl ) == 0 )
+ {
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ int have_buffered = 0;
+
+ /* We only check for buffered messages if the
+ * current datagram is fully consumed. */
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl_next_record_is_in_datagram( ssl ) == 0 )
+ {
+ if( ssl_load_buffered_message( ssl ) == 0 )
+ have_buffered = 1;
+ }
+
+ if( have_buffered == 0 )
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ ret = ssl_get_next_record( ssl );
+ if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
+ continue;
+
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
+ return( ret );
+ }
+ }
}
ret = mbedtls_ssl_handle_message_type( ssl );
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+ {
+ /* Buffer future message */
+ ret = ssl_buffer_message( ssl );
+ if( ret != 0 )
+ return( ret );
+
+ ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
@@ -3832,14 +4367,15 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
return( ret );
}
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ update_hs_digest == 1 )
{
mbedtls_ssl_update_handshake_status( ssl );
}
}
else
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= reuse previously read message" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
ssl->keep_current_message = 0;
}
@@ -3848,13 +4384,350 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
return( 0 );
}
-int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
{
- int ret;
+ if( ssl->in_left > ssl->next_record_offset )
+ return( 1 );
+ return( 0 );
+}
+
+static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ mbedtls_ssl_hs_buffer * hs_buf;
+ int ret = 0;
+
+ if( hs == NULL )
+ return( -1 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
+
+ if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
+ ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
+ {
+ /* Check if we have seen a ChangeCipherSpec before.
+ * If yes, synthesize a CCS record. */
+ if( !hs->buffering.seen_ccs )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) );
+ ret = -1;
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
+ ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
+ ssl->in_msglen = 1;
+ ssl->in_msg[0] = 1;
+
+ /* As long as they are equal, the exact value doesn't matter. */
+ ssl->in_left = 0;
+ ssl->next_record_offset = 0;
+
+ hs->buffering.seen_ccs = 0;
+ goto exit;
+ }
+
+#if defined(MBEDTLS_DEBUG_C)
+ /* Debug only */
+ {
+ unsigned offset;
+ for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+ {
+ hs_buf = &hs->buffering.hs[offset];
+ if( hs_buf->is_valid == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
+ hs->in_msg_seq + offset,
+ hs_buf->is_complete ? "fully" : "partially" ) );
+ }
+ }
+ }
+#endif /* MBEDTLS_DEBUG_C */
+
+ /* Check if we have buffered and/or fully reassembled the
+ * next handshake message. */
+ hs_buf = &hs->buffering.hs[0];
+ if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) )
+ {
+ /* Synthesize a record containing the buffered HS message. */
+ size_t msg_len = ( hs_buf->data[1] << 16 ) |
+ ( hs_buf->data[2] << 8 ) |
+ hs_buf->data[3];
+
+ /* Double-check that we haven't accidentally buffered
+ * a message that doesn't fit into the input buffer. */
+ if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)",
+ hs_buf->data, msg_len + 12 );
+
+ ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+ ssl->in_hslen = msg_len + 12;
+ ssl->in_msglen = msg_len + 12;
+ memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen );
+
+ ret = 0;
+ goto exit;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered",
+ hs->in_msg_seq ) );
+ }
+
+ ret = -1;
+
+exit:
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) );
+ return( ret );
+}
+
+static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
+ size_t desired )
+{
+ int offset;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available",
+ (unsigned) desired ) );
+
+ /* Get rid of future records epoch first, if such exist. */
+ ssl_free_buffered_record( ssl );
+
+ /* Check if we have enough space available now. */
+ if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) );
+ return( 0 );
+ }
+
+ /* We don't have enough space to buffer the next expected handshake
+ * message. Remove buffers used for future messages to gain space,
+ * starting with the most distant one. */
+ for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
+ offset >= 0; offset-- )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message",
+ offset ) );
+
+ ssl_buffering_free_slot( ssl, (uint8_t) offset );
+
+ /* Check if we have enough space available now. */
+ if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) );
+ return( 0 );
+ }
+ }
+
+ return( -1 );
+}
+
+static int ssl_buffer_message( mbedtls_ssl_context *ssl )
+{
+ int ret = 0;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+ if( hs == NULL )
+ return( 0 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) );
+
+ switch( ssl->in_msgtype )
+ {
+ case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) );
+
+ hs->buffering.seen_ccs = 1;
+ break;
+
+ case MBEDTLS_SSL_MSG_HANDSHAKE:
+ {
+ unsigned recv_msg_seq_offset;
+ unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+ mbedtls_ssl_hs_buffer *hs_buf;
+ size_t msg_len = ssl->in_hslen - 12;
+
+ /* We should never receive an old handshake
+ * message - double-check nonetheless. */
+ if( recv_msg_seq < ssl->handshake->in_msg_seq )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;
+ if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+ {
+ /* Silently ignore -- message too far in the future */
+ MBEDTLS_SSL_DEBUG_MSG( 2,
+ ( "Ignore future HS message with sequence number %u, "
+ "buffering window %u - %u",
+ recv_msg_seq, ssl->handshake->in_msg_seq,
+ ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) );
+
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ",
+ recv_msg_seq, recv_msg_seq_offset ) );
+
+ hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ];
+
+ /* Check if the buffering for this seq nr has already commenced. */
+ if( !hs_buf->is_valid )
+ {
+ size_t reassembly_buf_sz;
+
+ hs_buf->is_fragmented =
+ ( ssl_hs_is_proper_fragment( ssl ) == 1 );
+
+ /* We copy the message back into the input buffer
+ * after reassembly, so check that it's not too large.
+ * This is an implementation-specific limitation
+ * and not one from the standard, hence it is not
+ * checked in ssl_check_hs_header(). */
+ if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ /* Ignore message */
+ goto exit;
+ }
+
+ /* Check if we have enough space to buffer the message. */
+ if( hs->buffering.total_bytes_buffered >
+ MBEDTLS_SSL_DTLS_MAX_BUFFERING )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len,
+ hs_buf->is_fragmented );
+
+ if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ if( recv_msg_seq_offset > 0 )
+ {
+ /* If we can't buffer a future message because
+ * of space limitations -- ignore. */
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
+ (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ goto exit;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n",
+ (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ }
+
+ if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n",
+ (unsigned) msg_len,
+ (unsigned) reassembly_buf_sz,
+ MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+ goto exit;
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
+ msg_len ) );
+
+ hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
+ if( hs_buf->data == NULL )
+ {
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto exit;
+ }
+ hs_buf->data_len = reassembly_buf_sz;
+
+ /* Prepare final header: copy msg_type, length and message_seq,
+ * then add standardised fragment_offset and fragment_length */
+ memcpy( hs_buf->data, ssl->in_msg, 6 );
+ memset( hs_buf->data + 6, 0, 3 );
+ memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 );
+
+ hs_buf->is_valid = 1;
+
+ hs->buffering.total_bytes_buffered += reassembly_buf_sz;
+ }
+ else
+ {
+ /* Make sure msg_type and length are consistent */
+ if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) );
+ /* Ignore */
+ goto exit;
+ }
+ }
+
+ if( !hs_buf->is_complete )
+ {
+ size_t frag_len, frag_off;
+ unsigned char * const msg = hs_buf->data + 12;
+
+ /*
+ * Check and copy current fragment
+ */
+
+ /* Validation of header fields already done in
+ * mbedtls_ssl_prepare_handshake_record(). */
+ frag_off = ssl_get_hs_frag_off( ssl );
+ frag_len = ssl_get_hs_frag_len( ssl );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
+ frag_off, frag_len ) );
+ memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
+
+ if( hs_buf->is_fragmented )
+ {
+ unsigned char * const bitmask = msg + msg_len;
+ ssl_bitmask_set( bitmask, frag_off, frag_len );
+ hs_buf->is_complete = ( ssl_bitmask_check( bitmask,
+ msg_len ) == 0 );
+ }
+ else
+ {
+ hs_buf->is_complete = 1;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete",
+ hs_buf->is_complete ? "" : "not yet " ) );
+ }
+
+ break;
+ }
+
+ default:
+ /* We don't buffer other types of messages. */
+ break;
+ }
+
+exit:
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) );
+ return( ret );
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
+{
/*
- * Step A
- *
* Consume last content-layer message and potentially
* update in_msglen which keeps track of the contents'
* consumption state.
@@ -3936,20 +4809,161 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
ssl->in_msglen = 0;
}
- /*
- * Step B
- *
- * Fetch and decode new record if current one is fully consumed.
- *
- */
+ return( 0 );
+}
+static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
+{
if( ssl->in_msglen > 0 )
+ return( 1 );
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ if( hs == NULL )
+ return;
+
+ if( hs->buffering.future_record.data != NULL )
{
- /* There's something left to be processed in the current record. */
+ hs->buffering.total_bytes_buffered -=
+ hs->buffering.future_record.len;
+
+ mbedtls_free( hs->buffering.future_record.data );
+ hs->buffering.future_record.data = NULL;
+ }
+}
+
+static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ unsigned char * rec;
+ size_t rec_len;
+ unsigned rec_epoch;
+
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ return( 0 );
+
+ if( hs == NULL )
+ return( 0 );
+
+ rec = hs->buffering.future_record.data;
+ rec_len = hs->buffering.future_record.len;
+ rec_epoch = hs->buffering.future_record.epoch;
+
+ if( rec == NULL )
+ return( 0 );
+
+ /* Only consider loading future records if the
+ * input buffer is empty. */
+ if( ssl_next_record_is_in_datagram( ssl ) == 1 )
+ return( 0 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
+
+ if( rec_epoch != ssl->in_epoch )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) );
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) );
+
+ /* Double-check that the record is not too large */
+ if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN -
+ (size_t)( ssl->in_hdr - ssl->in_buf ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ memcpy( ssl->in_hdr, rec, rec_len );
+ ssl->in_left = rec_len;
+ ssl->next_record_offset = 0;
+
+ ssl_free_buffered_record( ssl );
+
+exit:
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) );
+ return( 0 );
+}
+
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ size_t const rec_hdr_len = 13;
+ size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen;
+
+ /* Don't buffer future records outside handshakes. */
+ if( hs == NULL )
+ return( 0 );
+
+ /* Only buffer handshake records (we are only interested
+ * in Finished messages). */
+ if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
+ return( 0 );
+
+ /* Don't buffer more than one future epoch record. */
+ if( hs->buffering.future_record.data != NULL )
+ return( 0 );
+
+ /* Don't buffer record if there's not enough buffering space remaining. */
+ if( total_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
+ (unsigned) total_buf_sz, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
return( 0 );
}
- /* Current record either fully processed or to be discarded. */
+ /* Buffer record */
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
+ ssl->in_epoch + 1 ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", ssl->in_hdr,
+ rec_hdr_len + ssl->in_msglen );
+
+ /* ssl_parse_record_header() only considers records
+ * of the next epoch as candidates for buffering. */
+ hs->buffering.future_record.epoch = ssl->in_epoch + 1;
+ hs->buffering.future_record.len = total_buf_sz;
+
+ hs->buffering.future_record.data =
+ mbedtls_calloc( 1, hs->buffering.future_record.len );
+ if( hs->buffering.future_record.data == NULL )
+ {
+ /* If we run out of RAM trying to buffer a
+ * record from the next epoch, just ignore. */
+ return( 0 );
+ }
+
+ memcpy( hs->buffering.future_record.data, ssl->in_hdr, total_buf_sz );
+
+ hs->buffering.total_bytes_buffered += total_buf_sz;
+ return( 0 );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static int ssl_get_next_record( mbedtls_ssl_context *ssl )
+{
+ int ret;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ /* We might have buffered a future record; if so,
+ * and if the epoch matches now, load it.
+ * On success, this call will set ssl->in_left to
+ * the length of the buffered record, so that
+ * the calls to ssl_fetch_input() below will
+ * essentially be no-ops. */
+ ret = ssl_load_buffered_record( ssl );
+ if( ret != 0 )
+ return( ret );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 )
{
@@ -3963,6 +4977,16 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
{
+ if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+ {
+ ret = ssl_buffer_future_record( ssl );
+ if( ret != 0 )
+ return( ret );
+
+ /* Fall through to handling of unexpected records */
+ ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
+ }
+
if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
{
/* Skip unexpected record (but not whole datagram) */
@@ -4094,8 +5118,51 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
}
}
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ if( ssl->in_msglen != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d",
+ ssl->in_msglen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msg[0] != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x",
+ ssl->in_msg[0] ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
+ ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
+ {
+ if( ssl->handshake == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+#endif
+ }
+
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
{
+ if( ssl->in_msglen != 2 )
+ {
+ /* Note: Standard allows for more than one 2 byte alert
+ to be packed in a single message, but Mbed TLS doesn't
+ currently support this. */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d",
+ ssl->in_msglen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
ssl->in_msg[0], ssl->in_msg[1] ) );
@@ -4185,7 +5252,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
ssl->out_msg[0] = level;
ssl->out_msg[1] = message;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
return( ret );
@@ -4325,10 +5392,10 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
while( crt != NULL )
{
n = crt->raw.len;
- if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i )
+ if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
- i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) );
+ i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) );
return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE );
}
@@ -4354,9 +5421,9 @@ write_msg:
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -4365,60 +5432,16 @@ write_msg:
return( ret );
}
-int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+/*
+ * Once the certificate message is read, parse it into a cert chain and
+ * perform basic checks, but leave actual verification to the caller
+ */
+static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
{
- int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ int ret;
size_t i, n;
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
- int authmode = ssl->conf->authmode;
uint8_t alert;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
-
- if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-
-#if defined(MBEDTLS_SSL_SRV_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
- if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET )
- authmode = ssl->handshake->sni_authmode;
-#endif
-
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- authmode == MBEDTLS_SSL_VERIFY_NONE )
- {
- ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-#endif
-
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
- {
- /* mbedtls_ssl_read_record may have sent an alert already. We
- let it decide whether to alert. */
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
- }
-
- ssl->state++;
-
#if defined(MBEDTLS_SSL_SRV_C)
#if defined(MBEDTLS_SSL_PROTO_SSL3)
/*
@@ -4438,10 +5461,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
one. The client should know what's going on, so we
don't send an alert. */
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
- if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
- return( 0 );
- else
- return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
}
}
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
@@ -4462,10 +5482,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
one. The client should know what's going on, so we
don't send an alert. */
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
- if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
- return( 0 );
- else
- return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
+ return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
}
}
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@@ -4528,6 +5545,12 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
while( i < ssl->in_hslen )
{
+ if ( i + 3 > ssl->in_hslen ) {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
if( ssl->in_msg[i] != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
@@ -4609,6 +5632,94 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
}
#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
+ return( 0 );
+}
+
+int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+{
+ int ret;
+ const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+ ssl->transform_negotiate->ciphersuite_info;
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
+ ? ssl->handshake->sni_authmode
+ : ssl->conf->authmode;
+#else
+ const int authmode = ssl->conf->authmode;
+#endif
+ void *rs_ctx = NULL;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+ if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+#if defined(MBEDTLS_SSL_SRV_C)
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ authmode == MBEDTLS_SSL_VERIFY_NONE )
+ {
+ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+
+ ssl->state++;
+ return( 0 );
+ }
+#endif
+
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled &&
+ ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
+ {
+ goto crt_verify;
+ }
+#endif
+
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
+ {
+ /* mbedtls_ssl_read_record may have sent an alert already. We
+ let it decide whether to alert. */
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 )
+ {
+#if defined(MBEDTLS_SSL_SRV_C)
+ if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE &&
+ authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
+ {
+ ret = 0;
+ }
+#endif
+
+ ssl->state++;
+ return( ret );
+ }
+
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ssl->handshake->ecrs_enabled)
+ ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
+
+crt_verify:
+ if( ssl->handshake->ecrs_enabled)
+ rs_ctx = &ssl->handshake->ecrs_ctx;
+#endif
+
if( authmode != MBEDTLS_SSL_VERIFY_NONE )
{
mbedtls_x509_crt *ca_chain;
@@ -4630,19 +5741,24 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
/*
* Main check: verify certificate
*/
- ret = mbedtls_x509_crt_verify_with_profile(
+ ret = mbedtls_x509_crt_verify_restartable(
ssl->session_negotiate->peer_cert,
ca_chain, ca_crl,
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
- ssl->conf->f_vrfy, ssl->conf->p_vrfy );
+ ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
}
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
+#endif
+
/*
* Secondary checks: always done, but change 'ret' only if it was 0
*/
@@ -4695,6 +5811,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( ret != 0 )
{
+ uint8_t alert;
+
/* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */
@@ -4737,6 +5855,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_DEBUG_C */
}
+ ssl->state++;
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
return( ret );
@@ -4761,9 +5881,9 @@ int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
ssl->state++;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -4778,7 +5898,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -4792,13 +5912,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
}
- if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
- return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC );
- }
+ /* CCS records are only accepted if they have length 1 and content '1',
+ * so we don't need to check this here. */
/*
* Switch to our negotiated transform and session parameters for inbound
@@ -4828,16 +5943,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_SSL_PROTO_DTLS */
memset( ssl->in_ctr, 0, 8 );
- /*
- * Set the in_msg pointer to the correct location based on IV length
- */
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen -
- ssl->transform_negotiate->fixed_ivlen;
- }
- else
- ssl->in_msg = ssl->in_iv;
+ ssl_update_in_pointers( ssl, ssl->transform_negotiate );
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_activate != NULL )
@@ -5202,7 +6308,7 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
/*
* Free our handshake params
*/
- mbedtls_ssl_handshake_free( ssl->handshake );
+ mbedtls_ssl_handshake_free( ssl );
mbedtls_free( ssl->handshake );
ssl->handshake = NULL;
@@ -5288,16 +6394,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
- /*
- * Set the out_msg pointer to the correct location based on IV length
- */
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen -
- ssl->transform_negotiate->fixed_ivlen;
- }
- else
- ssl->out_msg = ssl->out_iv;
+ ssl_update_out_pointers( ssl, ssl->transform_negotiate );
ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint );
@@ -5349,14 +6446,14 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
/* Remember current epoch settings for resending */
ssl->handshake->alt_transform_out = ssl->transform_out;
- memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 );
+ memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 );
/* Set sequence_number to zero */
- memset( ssl->out_ctr + 2, 0, 6 );
+ memset( ssl->cur_out_ctr + 2, 0, 6 );
/* Increment epoch */
for( i = 2; i > 0; i-- )
- if( ++ssl->out_ctr[i - 1] != 0 )
+ if( ++ssl->cur_out_ctr[i - 1] != 0 )
break;
/* The loop goes to its end iff the counter is wrapping */
@@ -5368,7 +6465,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_SSL_PROTO_DTLS */
- memset( ssl->out_ctr, 0, 8 );
+ memset( ssl->cur_out_ctr, 0, 8 );
ssl->transform_out = ssl->transform_negotiate;
ssl->session_out = ssl->session_negotiate;
@@ -5389,12 +6486,21 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
mbedtls_ssl_send_flight_completed( ssl );
#endif
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
+ return( ret );
+ }
+#endif
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
return( 0 );
@@ -5416,7 +6522,7 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 );
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
@@ -5528,6 +6634,10 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake )
#endif
#endif
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx );
+#endif
+
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET;
#endif
@@ -5557,7 +6667,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl )
if( ssl->session_negotiate )
mbedtls_ssl_session_free( ssl->session_negotiate );
if( ssl->handshake )
- mbedtls_ssl_handshake_free( ssl->handshake );
+ mbedtls_ssl_handshake_free( ssl );
/*
* Either the pointers are now NULL or cleared properly and can be freed.
@@ -5647,6 +6757,78 @@ static int ssl_cookie_check_dummy( void *ctx,
}
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
+/* Once ssl->out_hdr as the address of the beginning of the
+ * next outgoing record is set, deduce the other pointers.
+ *
+ * Note: For TLS, we save the implicit record sequence number
+ * (entering MAC computation) in the 8 bytes before ssl->out_hdr,
+ * and the caller has to make sure there's space for this.
+ */
+
+static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->out_ctr = ssl->out_hdr + 3;
+ ssl->out_len = ssl->out_hdr + 11;
+ ssl->out_iv = ssl->out_hdr + 13;
+ }
+ else
+#endif
+ {
+ ssl->out_ctr = ssl->out_hdr - 8;
+ ssl->out_len = ssl->out_hdr + 3;
+ ssl->out_iv = ssl->out_hdr + 5;
+ }
+
+ /* Adjust out_msg to make space for explicit IV, if used. */
+ if( transform != NULL &&
+ ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen;
+ }
+ else
+ ssl->out_msg = ssl->out_iv;
+}
+
+/* Once ssl->in_hdr as the address of the beginning of the
+ * next incoming record is set, deduce the other pointers.
+ *
+ * Note: For TLS, we save the implicit record sequence number
+ * (entering MAC computation) in the 8 bytes before ssl->in_hdr,
+ * and the caller has to make sure there's space for this.
+ */
+
+static void ssl_update_in_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->in_ctr = ssl->in_hdr + 3;
+ ssl->in_len = ssl->in_hdr + 11;
+ ssl->in_iv = ssl->in_hdr + 13;
+ }
+ else
+#endif
+ {
+ ssl->in_ctr = ssl->in_hdr - 8;
+ ssl->in_len = ssl->in_hdr + 3;
+ ssl->in_iv = ssl->in_hdr + 5;
+ }
+
+ /* Offset in_msg from in_iv to allow space for explicit IV, if used. */
+ if( transform != NULL &&
+ ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen;
+ }
+ else
+ ssl->in_msg = ssl->in_iv;
+}
+
/*
* Initialize an SSL context
*/
@@ -5658,61 +6840,87 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl )
/*
* Setup an SSL context
*/
+
+static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl )
+{
+ /* Set the incoming and outgoing record pointers. */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->out_hdr = ssl->out_buf;
+ ssl->in_hdr = ssl->in_buf;
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ ssl->out_hdr = ssl->out_buf + 8;
+ ssl->in_hdr = ssl->in_buf + 8;
+ }
+
+ /* Derive other internal pointers. */
+ ssl_update_out_pointers( ssl, NULL /* no transform enabled */ );
+ ssl_update_in_pointers ( ssl, NULL /* no transform enabled */ );
+}
+
int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
const mbedtls_ssl_config *conf )
{
int ret;
- const size_t len = MBEDTLS_SSL_BUFFER_LEN;
ssl->conf = conf;
/*
* Prepare base structures
*/
- if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL ||
- ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL )
+
+ /* Set to NULL in case of an error condition */
+ ssl->out_buf = NULL;
+
+ ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN );
+ if( ssl->in_buf == NULL )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) );
- mbedtls_free( ssl->in_buf );
- ssl->in_buf = NULL;
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) );
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto error;
}
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN );
+ if( ssl->out_buf == NULL )
{
- ssl->out_hdr = ssl->out_buf;
- ssl->out_ctr = ssl->out_buf + 3;
- ssl->out_len = ssl->out_buf + 11;
- ssl->out_iv = ssl->out_buf + 13;
- ssl->out_msg = ssl->out_buf + 13;
-
- ssl->in_hdr = ssl->in_buf;
- ssl->in_ctr = ssl->in_buf + 3;
- ssl->in_len = ssl->in_buf + 11;
- ssl->in_iv = ssl->in_buf + 13;
- ssl->in_msg = ssl->in_buf + 13;
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) );
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto error;
}
- else
-#endif
- {
- ssl->out_ctr = ssl->out_buf;
- ssl->out_hdr = ssl->out_buf + 8;
- ssl->out_len = ssl->out_buf + 11;
- ssl->out_iv = ssl->out_buf + 13;
- ssl->out_msg = ssl->out_buf + 13;
- ssl->in_ctr = ssl->in_buf;
- ssl->in_hdr = ssl->in_buf + 8;
- ssl->in_len = ssl->in_buf + 11;
- ssl->in_iv = ssl->in_buf + 13;
- ssl->in_msg = ssl->in_buf + 13;
- }
+ ssl_reset_in_out_pointers( ssl );
if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
- return( ret );
+ goto error;
return( 0 );
+
+error:
+ mbedtls_free( ssl->in_buf );
+ mbedtls_free( ssl->out_buf );
+
+ ssl->conf = NULL;
+
+ ssl->in_buf = NULL;
+ ssl->out_buf = NULL;
+
+ ssl->in_hdr = NULL;
+ ssl->in_ctr = NULL;
+ ssl->in_len = NULL;
+ ssl->in_iv = NULL;
+ ssl->in_msg = NULL;
+
+ ssl->out_hdr = NULL;
+ ssl->out_ctr = NULL;
+ ssl->out_len = NULL;
+ ssl->out_iv = NULL;
+ ssl->out_msg = NULL;
+
+ return( ret );
}
/*
@@ -5726,6 +6934,11 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
{
int ret;
+#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \
+ !defined(MBEDTLS_SSL_SRV_C)
+ ((void) partial);
+#endif
+
ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
/* Cancel any possibly running timer */
@@ -5742,12 +6955,10 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION;
ssl->in_offt = NULL;
+ ssl_reset_in_out_pointers( ssl );
- ssl->in_msg = ssl->in_buf + 13;
ssl->in_msgtype = 0;
ssl->in_msglen = 0;
- if( partial == 0 )
- ssl->in_left = 0;
#if defined(MBEDTLS_SSL_PROTO_DTLS)
ssl->next_record_offset = 0;
ssl->in_epoch = 0;
@@ -5761,7 +6972,6 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->keep_current_message = 0;
- ssl->out_msg = ssl->out_buf + 13;
ssl->out_msgtype = 0;
ssl->out_msglen = 0;
ssl->out_left = 0;
@@ -5770,12 +6980,23 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->split_done = 0;
#endif
+ memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) );
+
ssl->transform_in = NULL;
ssl->transform_out = NULL;
- memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
+ ssl->session_in = NULL;
+ ssl->session_out = NULL;
+
+ memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN );
+
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
if( partial == 0 )
- memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+ {
+ ssl->in_left = 0;
+ memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN );
+ }
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_reset != NULL )
@@ -5808,7 +7029,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
if( partial == 0 )
+#endif
{
mbedtls_free( ssl->cli_id );
ssl->cli_id = NULL;
@@ -5859,7 +7082,15 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS)
-void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max )
+
+void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl,
+ unsigned allow_packing )
+{
+ ssl->disable_datagram_packing = !allow_packing;
+}
+
+void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf,
+ uint32_t min, uint32_t max )
{
conf->hs_timeout_min = min;
conf->hs_timeout_max = max;
@@ -5909,6 +7140,13 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
ssl->f_recv_timeout = f_recv_timeout;
}
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu )
+{
+ ssl->mtu = mtu;
+}
+#endif
+
void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout )
{
conf->read_timeout = timeout;
@@ -5995,27 +7233,27 @@ static int ssl_append_key_cert( mbedtls_ssl_key_cert **head,
mbedtls_x509_crt *cert,
mbedtls_pk_context *key )
{
- mbedtls_ssl_key_cert *new;
+ mbedtls_ssl_key_cert *new_cert;
- new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) );
- if( new == NULL )
+ new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) );
+ if( new_cert == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- new->cert = cert;
- new->key = key;
- new->next = NULL;
+ new_cert->cert = cert;
+ new_cert->key = key;
+ new_cert->next = NULL;
/* Update head is the list was null, else add to the end */
if( *head == NULL )
{
- *head = new;
+ *head = new_cert;
}
else
{
mbedtls_ssl_key_cert *cur = *head;
while( cur->next != NULL )
cur = cur->next;
- cur->next = new;
+ cur->next = new_cert;
}
return( 0 );
@@ -6100,7 +7338,7 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
/* Identity len will be encoded on two bytes */
if( ( psk_identity_len >> 16 ) != 0 ||
- psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@@ -6401,7 +7639,7 @@ void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 )
int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code )
{
if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ||
- mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN )
{
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@@ -6480,6 +7718,43 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
}
#endif
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+void mbedtls_ssl_conf_async_private_cb(
+ mbedtls_ssl_config *conf,
+ mbedtls_ssl_async_sign_t *f_async_sign,
+ mbedtls_ssl_async_decrypt_t *f_async_decrypt,
+ mbedtls_ssl_async_resume_t *f_async_resume,
+ mbedtls_ssl_async_cancel_t *f_async_cancel,
+ void *async_config_data )
+{
+ conf->f_async_sign_start = f_async_sign;
+ conf->f_async_decrypt_start = f_async_decrypt;
+ conf->f_async_resume = f_async_resume;
+ conf->f_async_cancel = f_async_cancel;
+ conf->p_async_config_data = async_config_data;
+}
+
+void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf )
+{
+ return( conf->p_async_config_data );
+}
+
+void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl )
+{
+ if( ssl->handshake == NULL )
+ return( NULL );
+ else
+ return( ssl->handshake->user_async_ctx );
+}
+
+void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl,
+ void *ctx )
+{
+ if( ssl->handshake != NULL )
+ ssl->handshake->user_async_ctx = ctx;
+}
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
/*
* SSL get accessors
*/
@@ -6535,7 +7810,7 @@ int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
/*
* In all other cases, the rest of the message can be dropped.
- * As in ssl_read_record_layer, this needs to be adapted if
+ * As in ssl_get_next_record, this needs to be adapted if
* we implement support for multiple alerts in single records.
*/
@@ -6602,28 +7877,47 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl )
int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
{
- size_t transform_expansion;
+ size_t transform_expansion = 0;
const mbedtls_ssl_transform *transform = ssl->transform_out;
+ unsigned block_size;
+
+ if( transform == NULL )
+ return( (int) mbedtls_ssl_hdr_len( ssl ) );
#if defined(MBEDTLS_ZLIB_SUPPORT)
if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif
- if( transform == NULL )
- return( (int) mbedtls_ssl_hdr_len( ssl ) );
-
switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
{
case MBEDTLS_MODE_GCM:
case MBEDTLS_MODE_CCM:
+ case MBEDTLS_MODE_CHACHAPOLY:
case MBEDTLS_MODE_STREAM:
transform_expansion = transform->minlen;
break;
case MBEDTLS_MODE_CBC:
- transform_expansion = transform->maclen
- + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc );
+
+ block_size = mbedtls_cipher_get_block_size(
+ &transform->cipher_ctx_enc );
+
+ /* Expansion due to the addition of the MAC. */
+ transform_expansion += transform->maclen;
+
+ /* Expansion due to the addition of CBC padding;
+ * Theoretically up to 256 bytes, but we never use
+ * more than the block size of the underlying cipher. */
+ transform_expansion += block_size;
+
+ /* For TLS 1.1 or higher, an explicit IV is added
+ * after the record header. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ transform_expansion += block_size;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+
break;
default:
@@ -6642,21 +7936,91 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl )
/*
* Assume mfl_code is correct since it was checked when set
*/
- max_len = mfl_code_to_length[ssl->conf->mfl_code];
+ max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code );
- /*
- * Check if a smaller max length was negotiated
- */
+ /* Check if a smaller max length was negotiated */
if( ssl->session_out != NULL &&
- mfl_code_to_length[ssl->session_out->mfl_code] < max_len )
+ ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len )
{
- max_len = mfl_code_to_length[ssl->session_out->mfl_code];
+ max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code );
}
- return max_len;
+ /* During a handshake, use the value being negotiated */
+ if( ssl->session_negotiate != NULL &&
+ ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len )
+ {
+ max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code );
+ }
+
+ return( max_len );
}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl )
+{
+ /* Return unlimited mtu for client hello messages to avoid fragmentation. */
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+ ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO ||
+ ssl->state == MBEDTLS_SSL_SERVER_HELLO ) )
+ return ( 0 );
+
+ if( ssl->handshake == NULL || ssl->handshake->mtu == 0 )
+ return( ssl->mtu );
+
+ if( ssl->mtu == 0 )
+ return( ssl->handshake->mtu );
+
+ return( ssl->mtu < ssl->handshake->mtu ?
+ ssl->mtu : ssl->handshake->mtu );
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl )
+{
+ size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \
+ !defined(MBEDTLS_SSL_PROTO_DTLS)
+ (void) ssl;
+#endif
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
+
+ if( max_len > mfl )
+ max_len = mfl;
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl_get_current_mtu( ssl ) != 0 )
+ {
+ const size_t mtu = ssl_get_current_mtu( ssl );
+ const int ret = mbedtls_ssl_get_record_expansion( ssl );
+ const size_t overhead = (size_t) ret;
+
+ if( ret < 0 )
+ return( ret );
+
+ if( mtu <= overhead )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) );
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ if( max_len > mtu - overhead )
+ max_len = mtu - overhead;
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \
+ !defined(MBEDTLS_SSL_PROTO_DTLS)
+ ((void) ssl);
+#endif
+
+ return( (int) max_len );
+}
+
#if defined(MBEDTLS_X509_CRT_PARSE_C)
const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl )
{
@@ -6744,9 +8108,9 @@ static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST;
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
return( ret );
}
@@ -6876,7 +8240,7 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
ssl->conf->renego_period + ep_len, 8 - ep_len );
- out_ctr_cmp = memcmp( ssl->out_ctr + ep_len,
+ out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
ssl->conf->renego_period + ep_len, 8 - ep_len );
if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
@@ -6911,7 +8275,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
if( ssl->handshake != NULL &&
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
{
- if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
return( ret );
}
}
@@ -6960,7 +8324,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
ssl_set_timer( ssl, ssl->conf->read_timeout );
}
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
return( 0 );
@@ -6975,7 +8339,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
/*
* OpenSSL sends empty messages to randomize the IV
*/
- if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
return( 0 );
@@ -7194,18 +8558,29 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
}
/*
- * Send application data to be encrypted by the SSL layer,
- * taking care of max fragment length and buffer size
+ * Send application data to be encrypted by the SSL layer, taking care of max
+ * fragment length and buffer size.
+ *
+ * According to RFC 5246 Section 6.2.1:
+ *
+ * Zero-length fragments of Application data MAY be sent as they are
+ * potentially useful as a traffic analysis countermeasure.
+ *
+ * Therefore, it is possible that the input message length is 0 and the
+ * corresponding return code is 0 on success.
*/
static int ssl_write_real( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
- int ret;
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
- size_t max_len = mbedtls_ssl_get_max_frag_len( ssl );
-#else
- size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN;
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+ int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
+ const size_t max_len = (size_t) ret;
+
+ if( ret < 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
+ return( ret );
+ }
+
if( len > max_len )
{
#if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -7223,6 +8598,12 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
if( ssl->out_left != 0 )
{
+ /*
+ * The user has previously tried to send the data and
+ * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
+ * written. In this case, we expect the high-level write function
+ * (e.g. mbedtls_ssl_write()) to be called with the same parameters
+ */
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
@@ -7231,11 +8612,16 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
}
else
{
+ /*
+ * The user is trying to send a message the first time, so we need to
+ * copy the data into the internal buffers and setup the data structure
+ * to keep track of partial writes
+ */
ssl->out_msglen = len;
ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
memcpy( ssl->out_msg, buf, len );
- if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
return( ret );
@@ -7387,11 +8773,56 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert )
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
-void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static void ssl_buffering_free( mbedtls_ssl_context *ssl )
{
+ unsigned offset;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+ if( hs == NULL )
+ return;
+
+ ssl_free_buffered_record( ssl );
+
+ for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+ ssl_buffering_free_slot( ssl, offset );
+}
+
+static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
+ uint8_t slot )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];
+
+ if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+ return;
+
+ if( hs_buf->is_valid == 1 )
+ {
+ hs->buffering.total_bytes_buffered -= hs_buf->data_len;
+ mbedtls_free( hs_buf->data );
+ memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
+ }
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
if( handshake == NULL )
return;
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 )
+ {
+ ssl->conf->f_async_cancel( ssl );
+ handshake->async_in_progress = 0;
+ }
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
mbedtls_md5_free( &handshake->fin_md5 );
@@ -7454,10 +8885,14 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake )
}
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */
+#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+ mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx );
+#endif
+
#if defined(MBEDTLS_SSL_PROTO_DTLS)
mbedtls_free( handshake->verify_cookie );
- mbedtls_free( handshake->hs_msg );
ssl_flight_free( handshake->flight );
+ ssl_buffering_free( ssl );
#endif
mbedtls_platform_zeroize( handshake,
@@ -7496,20 +8931,20 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
if( ssl->out_buf != NULL )
{
- mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN );
+ mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN );
mbedtls_free( ssl->out_buf );
}
if( ssl->in_buf != NULL )
{
- mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN );
+ mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN );
mbedtls_free( ssl->in_buf );
}
#if defined(MBEDTLS_ZLIB_SUPPORT)
if( ssl->compress_buf != NULL )
{
- mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN );
+ mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
mbedtls_free( ssl->compress_buf );
}
#endif
@@ -7522,7 +8957,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
if( ssl->handshake )
{
- mbedtls_ssl_handshake_free( ssl->handshake );
+ mbedtls_ssl_handshake_free( ssl );
mbedtls_ssl_transform_free( ssl->transform_negotiate );
mbedtls_ssl_session_free( ssl->session_negotiate );
@@ -8289,13 +9724,14 @@ exit:
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
- unsigned char *output,
- unsigned char *data, size_t data_len,
- mbedtls_md_type_t md_alg )
+ unsigned char *hash, size_t *hashlen,
+ unsigned char *data, size_t data_len,
+ mbedtls_md_type_t md_alg )
{
int ret = 0;
mbedtls_md_context_t ctx;
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
+ *hashlen = mbedtls_md_get_size( md_info );
mbedtls_md_init( &ctx );
@@ -8326,7 +9762,7 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret );
goto exit;
}
- if( ( ret = mbedtls_md_finish( &ctx, output ) ) != 0 )
+ if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret );
goto exit;
diff --git a/library/threading.c b/library/threading.c
index f1c37245c7..7c90c7c595 100644
--- a/library/threading.c
+++ b/library/threading.c
@@ -19,6 +19,14 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
+/*
+ * Ensure gmtime_r is available even with -std=c99; must be defined before
+ * config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ */
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 200112L
+#endif
+
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@@ -29,6 +37,36 @@
#include "mbedtls/threading.h"
+#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+
+#if !defined(_WIN32) && (defined(unix) || \
+ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
+ defined(__MACH__)))
+#include
+#endif /* !_WIN32 && (unix || __unix || __unix__ ||
+ * (__APPLE__ && __MACH__)) */
+
+#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
+ _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
+/*
+ * This is a convenience shorthand macro to avoid checking the long
+ * preprocessor conditions above. Ideally, we could expose this macro in
+ * platform_util.h and simply use it in platform_util.c, threading.c and
+ * threading.h. However, this macro is not part of the Mbed TLS public API, so
+ * we keep it private by only defining it in this file
+ */
+
+#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
+#define THREADING_USE_GMTIME
+#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
+
+#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
+ _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
+
+#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
+
#if defined(MBEDTLS_THREADING_PTHREAD)
static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
{
@@ -114,7 +152,7 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t *
#if defined(MBEDTLS_FS_IO)
mbedtls_mutex_init( &mbedtls_threading_readdir_mutex );
#endif
-#if defined(MBEDTLS_HAVE_TIME_DATE)
+#if defined(THREADING_USE_GMTIME)
mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex );
#endif
}
@@ -127,7 +165,7 @@ void mbedtls_threading_free_alt( void )
#if defined(MBEDTLS_FS_IO)
mbedtls_mutex_free( &mbedtls_threading_readdir_mutex );
#endif
-#if defined(MBEDTLS_HAVE_TIME_DATE)
+#if defined(THREADING_USE_GMTIME)
mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex );
#endif
}
@@ -142,7 +180,7 @@ void mbedtls_threading_free_alt( void )
#if defined(MBEDTLS_FS_IO)
mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;
#endif
-#if defined(MBEDTLS_HAVE_TIME_DATE)
+#if defined(THREADING_USE_GMTIME)
mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
#endif
diff --git a/library/timing.c b/library/timing.c
index 6a30e51259..3e8139f1f9 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -39,7 +39,8 @@
#if !defined(MBEDTLS_TIMING_ALT)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
- !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
+ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
+ !defined(__HAIKU__)
#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h"
#endif
diff --git a/library/version_features.c b/library/version_features.c
index a452caf5e9..f1798a7ff8 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -39,6 +39,9 @@ static const char *features[] = {
#if defined(MBEDTLS_NO_UDBL_DIVISION)
"MBEDTLS_NO_UDBL_DIVISION",
#endif /* MBEDTLS_NO_UDBL_DIVISION */
+#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
+ "MBEDTLS_NO_64BIT_MULTIPLICATION",
+#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */
#if defined(MBEDTLS_HAVE_SSE2)
"MBEDTLS_HAVE_SSE2",
#endif /* MBEDTLS_HAVE_SSE2 */
@@ -90,6 +93,9 @@ static const char *features[] = {
#if defined(MBEDTLS_ARC4_ALT)
"MBEDTLS_ARC4_ALT",
#endif /* MBEDTLS_ARC4_ALT */
+#if defined(MBEDTLS_ARIA_ALT)
+ "MBEDTLS_ARIA_ALT",
+#endif /* MBEDTLS_ARIA_ALT */
#if defined(MBEDTLS_BLOWFISH_ALT)
"MBEDTLS_BLOWFISH_ALT",
#endif /* MBEDTLS_BLOWFISH_ALT */
@@ -99,6 +105,12 @@ static const char *features[] = {
#if defined(MBEDTLS_CCM_ALT)
"MBEDTLS_CCM_ALT",
#endif /* MBEDTLS_CCM_ALT */
+#if defined(MBEDTLS_CHACHA20_ALT)
+ "MBEDTLS_CHACHA20_ALT",
+#endif /* MBEDTLS_CHACHA20_ALT */
+#if defined(MBEDTLS_CHACHAPOLY_ALT)
+ "MBEDTLS_CHACHAPOLY_ALT",
+#endif /* MBEDTLS_CHACHAPOLY_ALT */
#if defined(MBEDTLS_CMAC_ALT)
"MBEDTLS_CMAC_ALT",
#endif /* MBEDTLS_CMAC_ALT */
@@ -114,6 +126,9 @@ static const char *features[] = {
#if defined(MBEDTLS_GCM_ALT)
"MBEDTLS_GCM_ALT",
#endif /* MBEDTLS_GCM_ALT */
+#if defined(MBEDTLS_NIST_KW_ALT)
+ "MBEDTLS_NIST_KW_ALT",
+#endif /* MBEDTLS_NIST_KW_ALT */
#if defined(MBEDTLS_MD2_ALT)
"MBEDTLS_MD2_ALT",
#endif /* MBEDTLS_MD2_ALT */
@@ -123,6 +138,9 @@ static const char *features[] = {
#if defined(MBEDTLS_MD5_ALT)
"MBEDTLS_MD5_ALT",
#endif /* MBEDTLS_MD5_ALT */
+#if defined(MBEDTLS_POLY1305_ALT)
+ "MBEDTLS_POLY1305_ALT",
+#endif /* MBEDTLS_POLY1305_ALT */
#if defined(MBEDTLS_RIPEMD160_ALT)
"MBEDTLS_RIPEMD160_ALT",
#endif /* MBEDTLS_RIPEMD160_ALT */
@@ -252,6 +270,12 @@ static const char *features[] = {
#if defined(MBEDTLS_CIPHER_MODE_CTR)
"MBEDTLS_CIPHER_MODE_CTR",
#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ "MBEDTLS_CIPHER_MODE_OFB",
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ "MBEDTLS_CIPHER_MODE_XTS",
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
"MBEDTLS_CIPHER_NULL_CIPHER",
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */
@@ -315,6 +339,9 @@ static const char *features[] = {
#if defined(MBEDTLS_ECP_NIST_OPTIM)
"MBEDTLS_ECP_NIST_OPTIM",
#endif /* MBEDTLS_ECP_NIST_OPTIM */
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+ "MBEDTLS_ECP_RESTARTABLE",
+#endif /* MBEDTLS_ECP_RESTARTABLE */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
"MBEDTLS_ECDSA_DETERMINISTIC",
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
@@ -402,6 +429,9 @@ static const char *features[] = {
#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
"MBEDTLS_SSL_ALL_ALERT_MESSAGES",
#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+ "MBEDTLS_SSL_ASYNC_PRIVATE",
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_SSL_DEBUG_ALL)
"MBEDTLS_SSL_DEBUG_ALL",
#endif /* MBEDTLS_SSL_DEBUG_ALL */
@@ -531,12 +561,21 @@ static const char *features[] = {
#if defined(MBEDTLS_CAMELLIA_C)
"MBEDTLS_CAMELLIA_C",
#endif /* MBEDTLS_CAMELLIA_C */
+#if defined(MBEDTLS_ARIA_C)
+ "MBEDTLS_ARIA_C",
+#endif /* MBEDTLS_ARIA_C */
#if defined(MBEDTLS_CCM_C)
"MBEDTLS_CCM_C",
#endif /* MBEDTLS_CCM_C */
#if defined(MBEDTLS_CERTS_C)
"MBEDTLS_CERTS_C",
#endif /* MBEDTLS_CERTS_C */
+#if defined(MBEDTLS_CHACHA20_C)
+ "MBEDTLS_CHACHA20_C",
+#endif /* MBEDTLS_CHACHA20_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ "MBEDTLS_CHACHAPOLY_C",
+#endif /* MBEDTLS_CHACHAPOLY_C */
#if defined(MBEDTLS_CIPHER_C)
"MBEDTLS_CIPHER_C",
#endif /* MBEDTLS_CIPHER_C */
@@ -579,9 +618,15 @@ static const char *features[] = {
#if defined(MBEDTLS_HAVEGE_C)
"MBEDTLS_HAVEGE_C",
#endif /* MBEDTLS_HAVEGE_C */
+#if defined(MBEDTLS_HKDF_C)
+ "MBEDTLS_HKDF_C",
+#endif /* MBEDTLS_HKDF_C */
#if defined(MBEDTLS_HMAC_DRBG_C)
"MBEDTLS_HMAC_DRBG_C",
#endif /* MBEDTLS_HMAC_DRBG_C */
+#if defined(MBEDTLS_NIST_KW_C)
+ "MBEDTLS_NIST_KW_C",
+#endif /* MBEDTLS_NIST_KW_C */
#if defined(MBEDTLS_MD_C)
"MBEDTLS_MD_C",
#endif /* MBEDTLS_MD_C */
@@ -633,6 +678,9 @@ static const char *features[] = {
#if defined(MBEDTLS_PLATFORM_C)
"MBEDTLS_PLATFORM_C",
#endif /* MBEDTLS_PLATFORM_C */
+#if defined(MBEDTLS_POLY1305_C)
+ "MBEDTLS_POLY1305_C",
+#endif /* MBEDTLS_POLY1305_C */
#if defined(MBEDTLS_RIPEMD160_C)
"MBEDTLS_RIPEMD160_C",
#endif /* MBEDTLS_RIPEMD160_C */
diff --git a/library/x509.c b/library/x509.c
index 371d6da1dc..52b5b649f7 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -59,26 +59,14 @@
#define mbedtls_snprintf snprintf
#endif
-
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
#endif
-
-#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
-#include
-#else
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+#include "mbedtls/platform_util.h"
#include
#endif
-#if defined(MBEDTLS_FS_IO)
-#include
-#if !defined(_WIN32)
-#include
-#include
-#include
-#endif
-#endif
-
#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
@@ -903,36 +891,14 @@ int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
* Set the time structure to the current time.
* Return 0 on success, non-zero on failure.
*/
-#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
static int x509_get_current_time( mbedtls_x509_time *now )
{
- SYSTEMTIME st;
-
- GetSystemTime( &st );
-
- now->year = st.wYear;
- now->mon = st.wMonth;
- now->day = st.wDay;
- now->hour = st.wHour;
- now->min = st.wMinute;
- now->sec = st.wSecond;
-
- return( 0 );
-}
-#else
-static int x509_get_current_time( mbedtls_x509_time *now )
-{
- struct tm *lt;
+ struct tm *lt, tm_buf;
mbedtls_time_t tt;
int ret = 0;
-#if defined(MBEDTLS_THREADING_C)
- if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
- return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
-#endif
-
tt = mbedtls_time( NULL );
- lt = gmtime( &tt );
+ lt = mbedtls_platform_gmtime_r( &tt, &tm_buf );
if( lt == NULL )
ret = -1;
@@ -946,14 +912,8 @@ static int x509_get_current_time( mbedtls_x509_time *now )
now->sec = lt->tm_sec;
}
-#if defined(MBEDTLS_THREADING_C)
- if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
- return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
-#endif
-
return( ret );
}
-#endif /* _WIN32 && !EFIX64 && !EFI32 */
/*
* Return 0 if before <= after, 1 otherwise
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 290c1eb3d1..97a4bbf245 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -163,6 +163,9 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
mbedtls_md_type_t md_alg )
{
+ if( md_alg == MBEDTLS_MD_NONE )
+ return( -1 );
+
if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
return( 0 );
@@ -176,6 +179,9 @@ static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
mbedtls_pk_type_t pk_alg )
{
+ if( pk_alg == MBEDTLS_PK_NONE )
+ return( -1 );
+
if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
return( 0 );
@@ -208,6 +214,9 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
{
const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
+ if( gid == MBEDTLS_ECP_DP_NONE )
+ return( -1 );
+
if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
return( 0 );
@@ -218,6 +227,153 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
return( -1 );
}
+/*
+ * Like memcmp, but case-insensitive and always returns -1 if different
+ */
+static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
+{
+ size_t i;
+ unsigned char diff;
+ const unsigned char *n1 = s1, *n2 = s2;
+
+ for( i = 0; i < len; i++ )
+ {
+ diff = n1[i] ^ n2[i];
+
+ if( diff == 0 )
+ continue;
+
+ if( diff == 32 &&
+ ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
+ ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
+ {
+ continue;
+ }
+
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Return 0 if name matches wildcard, -1 otherwise
+ */
+static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
+{
+ size_t i;
+ size_t cn_idx = 0, cn_len = strlen( cn );
+
+ /* We can't have a match if there is no wildcard to match */
+ if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
+ return( -1 );
+
+ for( i = 0; i < cn_len; ++i )
+ {
+ if( cn[i] == '.' )
+ {
+ cn_idx = i;
+ break;
+ }
+ }
+
+ if( cn_idx == 0 )
+ return( -1 );
+
+ if( cn_len - cn_idx == name->len - 1 &&
+ x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
+ {
+ return( 0 );
+ }
+
+ return( -1 );
+}
+
+/*
+ * Compare two X.509 strings, case-insensitive, and allowing for some encoding
+ * variations (but not all).
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
+{
+ if( a->tag == b->tag &&
+ a->len == b->len &&
+ memcmp( a->p, b->p, b->len ) == 0 )
+ {
+ return( 0 );
+ }
+
+ if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+ ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+ a->len == b->len &&
+ x509_memcasecmp( a->p, b->p, b->len ) == 0 )
+ {
+ return( 0 );
+ }
+
+ return( -1 );
+}
+
+/*
+ * Compare two X.509 Names (aka rdnSequence).
+ *
+ * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
+ * we sometimes return unequal when the full algorithm would return equal,
+ * but never the other way. (In particular, we don't do Unicode normalisation
+ * or space folding.)
+ *
+ * Return 0 if equal, -1 otherwise.
+ */
+static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
+{
+ /* Avoid recursion, it might not be optimised by the compiler */
+ while( a != NULL || b != NULL )
+ {
+ if( a == NULL || b == NULL )
+ return( -1 );
+
+ /* type */
+ if( a->oid.tag != b->oid.tag ||
+ a->oid.len != b->oid.len ||
+ memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
+ {
+ return( -1 );
+ }
+
+ /* value */
+ if( x509_string_cmp( &a->val, &b->val ) != 0 )
+ return( -1 );
+
+ /* structure of the list of sets */
+ if( a->next_merged != b->next_merged )
+ return( -1 );
+
+ a = a->next;
+ b = b->next;
+ }
+
+ /* a == NULL == b */
+ return( 0 );
+}
+
+/*
+ * Reset (init or clear) a verify_chain
+ */
+static void x509_crt_verify_chain_reset(
+ mbedtls_x509_crt_verify_chain *ver_chain )
+{
+ size_t i;
+
+ for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
+ {
+ ver_chain->items[i].crt = NULL;
+ ver_chain->items[i].flags = -1;
+ }
+
+ ver_chain->len = 0;
+}
+
/*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
*/
@@ -570,18 +726,14 @@ static int x509_get_crt_ext( unsigned char **p,
end_ext_data = *p + len;
/* Get extension ID */
- extn_oid.tag = **p;
-
- if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
+ if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
+ MBEDTLS_ASN1_OID ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+ extn_oid.tag = MBEDTLS_ASN1_OID;
extn_oid.p = *p;
*p += extn_oid.len;
- if( ( end - *p ) < 1 )
- return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
- MBEDTLS_ERR_ASN1_OUT_OF_DATA );
-
/* Get optional critical */
if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
@@ -1662,9 +1814,7 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
while( crl_list != NULL )
{
if( crl_list->version == 0 ||
- crl_list->issuer_raw.len != ca->subject_raw.len ||
- memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
- crl_list->issuer_raw.len ) != 0 )
+ x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
{
crl_list = crl_list->next;
continue;
@@ -1674,7 +1824,8 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
* Check if the CA is configured to sign CRLs
*/
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
- if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
+ if( mbedtls_x509_crt_check_key_usage( ca,
+ MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
{
flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
break;
@@ -1734,141 +1885,12 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
}
#endif /* MBEDTLS_X509_CRL_PARSE_C */
-/*
- * Like memcmp, but case-insensitive and always returns -1 if different
- */
-static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
-{
- size_t i;
- unsigned char diff;
- const unsigned char *n1 = s1, *n2 = s2;
-
- for( i = 0; i < len; i++ )
- {
- diff = n1[i] ^ n2[i];
-
- if( diff == 0 )
- continue;
-
- if( diff == 32 &&
- ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
- ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
- {
- continue;
- }
-
- return( -1 );
- }
-
- return( 0 );
-}
-
-/*
- * Return 0 if name matches wildcard, -1 otherwise
- */
-static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
-{
- size_t i;
- size_t cn_idx = 0, cn_len = strlen( cn );
-
- /* We can't have a match if there is no wildcard to match */
- if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
- return( -1 );
-
- for( i = 0; i < cn_len; ++i )
- {
- if( cn[i] == '.' )
- {
- cn_idx = i;
- break;
- }
- }
-
- if( cn_idx == 0 )
- return( -1 );
-
- if( cn_len - cn_idx == name->len - 1 &&
- x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
- {
- return( 0 );
- }
-
- return( -1 );
-}
-
-/*
- * Compare two X.509 strings, case-insensitive, and allowing for some encoding
- * variations (but not all).
- *
- * Return 0 if equal, -1 otherwise.
- */
-static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
-{
- if( a->tag == b->tag &&
- a->len == b->len &&
- memcmp( a->p, b->p, b->len ) == 0 )
- {
- return( 0 );
- }
-
- if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
- ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
- a->len == b->len &&
- x509_memcasecmp( a->p, b->p, b->len ) == 0 )
- {
- return( 0 );
- }
-
- return( -1 );
-}
-
-/*
- * Compare two X.509 Names (aka rdnSequence).
- *
- * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
- * we sometimes return unequal when the full algorithm would return equal,
- * but never the other way. (In particular, we don't do Unicode normalisation
- * or space folding.)
- *
- * Return 0 if equal, -1 otherwise.
- */
-static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
-{
- /* Avoid recursion, it might not be optimised by the compiler */
- while( a != NULL || b != NULL )
- {
- if( a == NULL || b == NULL )
- return( -1 );
-
- /* type */
- if( a->oid.tag != b->oid.tag ||
- a->oid.len != b->oid.len ||
- memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
- {
- return( -1 );
- }
-
- /* value */
- if( x509_string_cmp( &a->val, &b->val ) != 0 )
- return( -1 );
-
- /* structure of the list of sets */
- if( a->next_merged != b->next_merged )
- return( -1 );
-
- a = a->next;
- b = b->next;
- }
-
- /* a == NULL == b */
- return( 0 );
-}
-
/*
* Check the signature of a certificate by its parent
*/
static int x509_crt_check_signature( const mbedtls_x509_crt *child,
- mbedtls_x509_crt *parent )
+ mbedtls_x509_crt *parent,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
const mbedtls_md_info_t *md_info;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
@@ -1880,14 +1902,24 @@ static int x509_crt_check_signature( const mbedtls_x509_crt *child,
return( -1 );
}
- if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
- child->sig_md, hash, mbedtls_md_get_size( md_info ),
- child->sig.p, child->sig.len ) != 0 )
- {
+ /* Skip expensive computation on obvious mismatch */
+ if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
return( -1 );
- }
- return( 0 );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
+ {
+ return( mbedtls_pk_verify_restartable( &parent->pk,
+ child->sig_md, hash, mbedtls_md_get_size( md_info ),
+ child->sig.p, child->sig.len, &rs_ctx->pk ) );
+ }
+#else
+ (void) rs_ctx;
+#endif
+
+ return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
+ child->sig_md, hash, mbedtls_md_get_size( md_info ),
+ child->sig.p, child->sig.len ) );
}
/*
@@ -1934,6 +1966,7 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child,
* 1. subject name matches child's issuer
* 2. if necessary, the CA bit is set and key usage allows signing certs
* 3. for trusted roots, the signature is correct
+ * (for intermediates, the signature is checked and the result reported)
* 4. pathlen constraints are satisfied
*
* If there's a suitable candidate which is also time-valid, return the first
@@ -1956,23 +1989,54 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child,
* Arguments:
* - [in] child: certificate for which we're looking for a parent
* - [in] candidates: chained list of potential parents
+ * - [out] r_parent: parent found (or NULL)
+ * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
* - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
* of the chain, 0 otherwise
* - [in] path_cnt: number of intermediates seen so far
* - [in] self_cnt: number of self-signed intermediates seen so far
* (will never be greater than path_cnt)
+ * - [in-out] rs_ctx: context for restarting operations
*
* Return value:
- * - the first suitable parent found (see above regarding time-validity)
- * - NULL if no suitable parent was found
+ * - 0 on success
+ * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
*/
-static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
- mbedtls_x509_crt *candidates,
- int top,
- size_t path_cnt,
- size_t self_cnt )
+static int x509_crt_find_parent_in(
+ mbedtls_x509_crt *child,
+ mbedtls_x509_crt *candidates,
+ mbedtls_x509_crt **r_parent,
+ int *r_signature_is_good,
+ int top,
+ unsigned path_cnt,
+ unsigned self_cnt,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- mbedtls_x509_crt *parent, *badtime_parent = NULL;
+ int ret;
+ mbedtls_x509_crt *parent, *fallback_parent;
+ int signature_is_good, fallback_signature_is_good;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* did we have something in progress? */
+ if( rs_ctx != NULL && rs_ctx->parent != NULL )
+ {
+ /* restore saved state */
+ parent = rs_ctx->parent;
+ fallback_parent = rs_ctx->fallback_parent;
+ fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
+
+ /* clear saved state */
+ rs_ctx->parent = NULL;
+ rs_ctx->fallback_parent = NULL;
+ rs_ctx->fallback_signature_is_good = 0;
+
+ /* resume where we left */
+ goto check_signature;
+ }
+#endif
+
+ fallback_parent = NULL;
+ fallback_signature_is_good = 0;
for( parent = candidates; parent != NULL; parent = parent->next )
{
@@ -1988,17 +2052,38 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
}
/* Signature */
- if( top && x509_crt_check_signature( child, parent ) != 0 )
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+check_signature:
+#endif
+ ret = x509_crt_check_signature( child, parent, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
{
- continue;
+ /* save state */
+ rs_ctx->parent = parent;
+ rs_ctx->fallback_parent = fallback_parent;
+ rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
+
+ return( ret );
}
+#else
+ (void) ret;
+#endif
+
+ signature_is_good = ret == 0;
+ if( top && ! signature_is_good )
+ continue;
/* optional time check */
if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
mbedtls_x509_time_is_future( &parent->valid_from ) )
{
- if( badtime_parent == NULL )
- badtime_parent = parent;
+ if( fallback_parent == NULL )
+ {
+ fallback_parent = parent;
+ fallback_signature_is_good = signature_is_good;
+ }
continue;
}
@@ -2006,10 +2091,18 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
break;
}
- if( parent == NULL )
- parent = badtime_parent;
+ if( parent != NULL )
+ {
+ *r_parent = parent;
+ *r_signature_is_good = signature_is_good;
+ }
+ else
+ {
+ *r_parent = fallback_parent;
+ *r_signature_is_good = fallback_signature_is_good;
+ }
- return( parent );
+ return( 0 );
}
/*
@@ -2021,34 +2114,78 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
* Arguments:
* - [in] child: certificate for which we're looking for a parent, followed
* by a chain of possible intermediates
- * - [in] trust_ca: locally trusted CAs
- * - [out] 1 if parent was found in trust_ca, 0 if found in provided chain
- * - [in] path_cnt: number of intermediates seen so far
- * - [in] self_cnt: number of self-signed intermediates seen so far
+ * - [in] trust_ca: list of locally trusted certificates
+ * - [out] parent: parent found (or NULL)
+ * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
+ * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
+ * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
+ * - [in] self_cnt: number of self-signed certs in the chain so far
* (will always be no greater than path_cnt)
+ * - [in-out] rs_ctx: context for restarting operations
*
* Return value:
- * - the first suitable parent found (see find_parent_in() for "suitable")
- * - NULL if no suitable parent was found
+ * - 0 on success
+ * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
*/
-static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child,
- mbedtls_x509_crt *trust_ca,
- int *parent_is_trusted,
- size_t path_cnt,
- size_t self_cnt )
+static int x509_crt_find_parent(
+ mbedtls_x509_crt *child,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crt **parent,
+ int *parent_is_trusted,
+ int *signature_is_good,
+ unsigned path_cnt,
+ unsigned self_cnt,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- mbedtls_x509_crt *parent;
+ int ret;
+ mbedtls_x509_crt *search_list;
- /* Look for a parent in trusted CAs */
*parent_is_trusted = 1;
- parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt );
- if( parent != NULL )
- return( parent );
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* restore then clear saved state if we have some stored */
+ if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
+ {
+ *parent_is_trusted = rs_ctx->parent_is_trusted;
+ rs_ctx->parent_is_trusted = -1;
+ }
+#endif
- /* Look for a parent upwards the chain */
- *parent_is_trusted = 0;
- return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) );
+ while( 1 ) {
+ search_list = *parent_is_trusted ? trust_ca : child->next;
+
+ ret = x509_crt_find_parent_in( child, search_list,
+ parent, signature_is_good,
+ *parent_is_trusted,
+ path_cnt, self_cnt, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ {
+ /* save state */
+ rs_ctx->parent_is_trusted = *parent_is_trusted;
+ return( ret );
+ }
+#else
+ (void) ret;
+#endif
+
+ /* stop here if found or already in second iteration */
+ if( *parent != NULL || *parent_is_trusted == 0 )
+ break;
+
+ /* prepare second iteration */
+ *parent_is_trusted = 0;
+ }
+
+ /* extra precaution against mistakes in the caller */
+ if( parent == NULL )
+ {
+ *parent_is_trusted = 0;
+ *signature_is_good = 0;
+ }
+
+ return( 0 );
}
/*
@@ -2097,11 +2234,24 @@ static int x509_crt_check_ee_locally_trusted(
* - EE, Ci1, ..., Ciq cannot be continued with a trusted root
* -> return that chain with NOT_TRUSTED set on Ciq
*
+ * Tests for (aspects of) this function should include at least:
+ * - trusted EE
+ * - EE -> trusted root
+ * - EE -> intermedate CA -> trusted root
+ * - if relevant: EE untrusted
+ * - if relevant: EE -> intermediate, untrusted
+ * with the aspect under test checked at each relevant level (EE, int, root).
+ * For some aspects longer chains are required, but usually length 2 is
+ * enough (but length 1 is not in general).
+ *
* Arguments:
* - [in] crt: the cert list EE, C1, ..., Cn
* - [in] trust_ca: the trusted list R1, ..., Rp
* - [in] ca_crl, profile: as in verify_with_profile()
- * - [out] ver_chain, chain_len: the built and verified chain
+ * - [out] ver_chain: the built and verified chain
+ * Only valid when return value is 0, may contain garbage otherwise!
+ * Restart note: need not be the same when calling again to resume.
+ * - [in-out] rs_ctx: context for restarting operations
*
* Return value:
* - non-zero if the chain could not be fully built and examined
@@ -2113,24 +2263,50 @@ static int x509_crt_verify_chain(
mbedtls_x509_crt *trust_ca,
mbedtls_x509_crl *ca_crl,
const mbedtls_x509_crt_profile *profile,
- x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
- size_t *chain_len )
+ mbedtls_x509_crt_verify_chain *ver_chain,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
+ /* Don't initialize any of those variables here, so that the compiler can
+ * catch potential issues with jumping ahead when restarting */
+ int ret;
uint32_t *flags;
+ mbedtls_x509_crt_verify_chain_item *cur;
mbedtls_x509_crt *child;
mbedtls_x509_crt *parent;
- int parent_is_trusted = 0;
- int child_is_trusted = 0;
- size_t self_cnt = 0;
+ int parent_is_trusted;
+ int child_is_trusted;
+ int signature_is_good;
+ unsigned self_cnt;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ /* resume if we had an operation in progress */
+ if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
+ {
+ /* restore saved state */
+ *ver_chain = rs_ctx->ver_chain; /* struct copy */
+ self_cnt = rs_ctx->self_cnt;
+
+ /* restore derived state */
+ cur = &ver_chain->items[ver_chain->len - 1];
+ child = cur->crt;
+ flags = &cur->flags;
+
+ goto find_parent;
+ }
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
child = crt;
- *chain_len = 0;
+ self_cnt = 0;
+ parent_is_trusted = 0;
+ child_is_trusted = 0;
while( 1 ) {
/* Add certificate to the verification chain */
- ver_chain[*chain_len].crt = child;
- flags = &ver_chain[*chain_len].flags;
- ++*chain_len;
+ cur = &ver_chain->items[ver_chain->len];
+ cur->crt = child;
+ cur->flags = 0;
+ ver_chain->len++;
+ flags = &cur->flags;
/* Check time-validity (all certificates) */
if( mbedtls_x509_time_is_past( &child->valid_to ) )
@@ -2151,15 +2327,33 @@ static int x509_crt_verify_chain(
*flags |= MBEDTLS_X509_BADCERT_BAD_PK;
/* Special case: EE certs that are locally trusted */
- if( *chain_len == 1 &&
+ if( ver_chain->len == 1 &&
x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
{
return( 0 );
}
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+find_parent:
+#endif
/* Look for a parent in trusted CAs or up the chain */
- parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted,
- *chain_len - 1, self_cnt );
+ ret = x509_crt_find_parent( child, trust_ca, &parent,
+ &parent_is_trusted, &signature_is_good,
+ ver_chain->len - 1, self_cnt, rs_ctx );
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ {
+ /* save state */
+ rs_ctx->in_progress = x509_crt_rs_find_parent;
+ rs_ctx->self_cnt = self_cnt;
+ rs_ctx->ver_chain = *ver_chain; /* struct copy */
+
+ return( ret );
+ }
+#else
+ (void) ret;
+#endif
/* No parent? We're done here */
if( parent == NULL )
@@ -2171,7 +2365,7 @@ static int x509_crt_verify_chain(
/* Count intermediate self-issued (not necessarily self-signed) certs.
* These can occur with some strategies for key rollover, see [SIRO],
* and should be excluded from max_pathlen checks. */
- if( *chain_len != 1 &&
+ if( ver_chain->len != 1 &&
x509_name_cmp( &child->issuer, &child->subject ) == 0 )
{
self_cnt++;
@@ -2180,14 +2374,14 @@ static int x509_crt_verify_chain(
/* path_cnt is 0 for the first intermediate CA,
* and if parent is trusted it's not an intermediate CA */
if( ! parent_is_trusted &&
- *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
+ ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
{
/* return immediately to avoid overflow the chain array */
return( MBEDTLS_ERR_X509_FATAL_ERROR );
}
- /* if parent is trusted, the signature was checked by find_parent() */
- if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 )
+ /* signature was checked while searching parent */
+ if( ! signature_is_good )
*flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
/* check size of signing key */
@@ -2205,6 +2399,7 @@ static int x509_crt_verify_chain(
child = parent;
parent = NULL;
child_is_trusted = parent_is_trusted;
+ signature_is_good = 0;
}
}
@@ -2273,21 +2468,22 @@ static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
*/
static int x509_crt_merge_flags_with_cb(
uint32_t *flags,
- x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
- size_t chain_len,
+ const mbedtls_x509_crt_verify_chain *ver_chain,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy )
{
int ret;
- size_t i;
+ unsigned i;
uint32_t cur_flags;
+ const mbedtls_x509_crt_verify_chain_item *cur;
- for( i = chain_len; i != 0; --i )
+ for( i = ver_chain->len; i != 0; --i )
{
- cur_flags = ver_chain[i-1].flags;
+ cur = &ver_chain->items[i-1];
+ cur_flags = cur->flags;
if( NULL != f_vrfy )
- if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 )
+ if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
return( ret );
*flags |= cur_flags;
@@ -2297,7 +2493,7 @@ static int x509_crt_merge_flags_with_cb(
}
/*
- * Verify the certificate validity
+ * Verify the certificate validity (default profile, not restartable)
*/
int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
@@ -2306,19 +2502,13 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy )
{
- return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl,
- &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) );
+ return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
+ &mbedtls_x509_crt_profile_default, cn, flags,
+ f_vrfy, p_vrfy, NULL ) );
}
/*
- * Verify the certificate validity, with profile
- *
- * This function:
- * - checks the requested CN (if any)
- * - checks the type and size of the EE cert's key,
- * as that isn't done as part of chain building/verification currently
- * - builds and verifies the chain
- * - then calls the callback and merges the flags
+ * Verify the certificate validity (user-chosen profile, not restartable)
*/
int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
@@ -2327,16 +2517,38 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
const char *cn, uint32_t *flags,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy )
+{
+ return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
+ profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
+}
+
+/*
+ * Verify the certificate validity, with profile, restartable version
+ *
+ * This function:
+ * - checks the requested CN (if any)
+ * - checks the type and size of the EE cert's key,
+ * as that isn't done as part of chain building/verification currently
+ * - builds and verifies the chain
+ * - then calls the callback and merges the flags
+ */
+int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crl *ca_crl,
+ const mbedtls_x509_crt_profile *profile,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
{
int ret;
mbedtls_pk_type_t pk_type;
- x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE];
- size_t chain_len;
- uint32_t *ee_flags = &ver_chain[0].flags;
+ mbedtls_x509_crt_verify_chain ver_chain;
+ uint32_t ee_flags;
*flags = 0;
- memset( ver_chain, 0, sizeof( ver_chain ) );
- chain_len = 0;
+ ee_flags = 0;
+ x509_crt_verify_chain_reset( &ver_chain );
if( profile == NULL )
{
@@ -2346,28 +2558,36 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
/* check name if requested */
if( cn != NULL )
- x509_crt_verify_name( crt, cn, ee_flags );
+ x509_crt_verify_name( crt, cn, &ee_flags );
/* Check the type and size of the key */
pk_type = mbedtls_pk_get_type( &crt->pk );
if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
- *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+ ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
if( x509_profile_check_key( profile, &crt->pk ) != 0 )
- *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+ ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
/* Check the chain */
ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
- ver_chain, &chain_len );
+ &ver_chain, rs_ctx );
+
if( ret != 0 )
goto exit;
+ /* Merge end-entity flags */
+ ver_chain.items[0].flags |= ee_flags;
+
/* Build final flags, calling callback on the way if any */
- ret = x509_crt_merge_flags_with_cb( flags,
- ver_chain, chain_len, f_vrfy, p_vrfy );
+ ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
exit:
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
+ mbedtls_x509_crt_restart_free( rs_ctx );
+#endif
+
/* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
* the SSL module for authmode optional, but non-zero return from the
* callback means a fatal error so it shouldn't be ignored */
@@ -2478,4 +2698,36 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
while( cert_cur != NULL );
}
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/*
+ * Initialize a restart context
+ */
+void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
+{
+ mbedtls_pk_restart_init( &ctx->pk );
+
+ ctx->parent = NULL;
+ ctx->fallback_parent = NULL;
+ ctx->fallback_signature_is_good = 0;
+
+ ctx->parent_is_trusted = -1;
+
+ ctx->in_progress = x509_crt_rs_none;
+ ctx->self_cnt = 0;
+ x509_crt_verify_chain_reset( &ctx->ver_chain );
+}
+
+/*
+ * Free the components of a restart context
+ */
+void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_pk_restart_free( &ctx->pk );
+ mbedtls_x509_crt_restart_init( ctx );
+}
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
#endif /* MBEDTLS_X509_CRT_PARSE_C */
diff --git a/library/x509_csr.c b/library/x509_csr.c
index 3e8e8fbc6a..f84425728a 100644
--- a/library/x509_csr.c
+++ b/library/x509_csr.c
@@ -274,34 +274,25 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
#if defined(MBEDTLS_PEM_PARSE_C)
- mbedtls_pem_init( &pem );
-
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
- if( buf[buflen - 1] != '\0' )
- ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
- else
+ if( buf[buflen - 1] == '\0' )
+ {
+ mbedtls_pem_init( &pem );
ret = mbedtls_pem_read_buffer( &pem,
"-----BEGIN CERTIFICATE REQUEST-----",
"-----END CERTIFICATE REQUEST-----",
buf, NULL, 0, &use_len );
- if( ret == 0 )
- {
- /*
- * Was PEM encoded, parse the result
- */
- if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 )
- return( ret );
+ if( ret == 0 )
+ /*
+ * Was PEM encoded, parse the result
+ */
+ ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen );
mbedtls_pem_free( &pem );
- return( 0 );
+ if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+ return( ret );
}
- else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
- {
- mbedtls_pem_free( &pem );
- return( ret );
- }
- else
#endif /* MBEDTLS_PEM_PARSE_C */
return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) );
}
diff --git a/programs/.gitignore b/programs/.gitignore
index ddfa1a4266..02418966f8 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -45,6 +45,7 @@ ssl/mini_client
test/benchmark
test/ecp-bench
test/selftest
+test/cpp_dummy_build
test/ssl_cert_test
test/udp_proxy
test/zeroize
diff --git a/programs/Makefile b/programs/Makefile
index 080e82d88c..b6d1fa25b5 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -4,9 +4,11 @@
CFLAGS ?= -O2
WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement
+WARNING_CXXFLAGS ?= -Wall -W
LDFLAGS ?=
LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../include -D_FILE_OFFSET_BITS=64
+LOCAL_CXXFLAGS = $(WARNING_CXXFLAGS) -I../include -D_FILE_OFFSET_BITS=64
LOCAL_LDFLAGS = -L../library \
-lmbedtls$(SHARED_SUFFIX) \
-lmbedx509$(SHARED_SUFFIX) \
@@ -77,6 +79,10 @@ ifdef PTHREAD
APPS += ssl/ssl_pthread_server$(EXEXT)
endif
+ifdef TEST_CPP
+APPS += test/cpp_dummy_build$(EXEXT)
+endif
+
.SILENT:
.PHONY: all clean list
@@ -242,6 +248,10 @@ test/benchmark$(EXEXT): test/benchmark.c $(DEP)
echo " CC test/benchmark.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/benchmark.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+test/cpp_dummy_build$(EXEXT): test/cpp_dummy_build.cpp $(DEP)
+ echo " CXX test/cpp_dummy_build.cpp"
+ $(CXX) $(LOCAL_CXXFLAGS) $(CXXFLAGS) test/cpp_dummy_build.cpp $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
test/selftest$(EXEXT): test/selftest.c $(DEP)
echo " CC test/selftest.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/selftest.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/programs/README.md b/programs/README.md
new file mode 100644
index 0000000000..eb25a7f694
--- /dev/null
+++ b/programs/README.md
@@ -0,0 +1,125 @@
+Mbed TLS sample programs
+========================
+
+This subdirectory mostly contains sample programs that illustrate specific features of the library, as well as a few test and support programs.
+
+## Symmetric cryptography (AES) examples
+
+* [`aes/aescrypt2.c`](aes/aescrypt2.c): file encryption and authentication with a key derived from a low-entropy secret, demonstrating the low-level AES interface, the digest interface and HMAC.
+ Warning: this program illustrates how to use low-level functions in the library. It should not be taken as an example of how to build a secure encryption mechanism. To derive a key from a low-entropy secret such as a password, use a standard key stretching mechanism such as PBKDF2 (provided by the `pkcs5` module). To encrypt and authenticate data, use a standard mode such as GCM or CCM (both available as library module).
+
+* [`aes/crypt_and_hash.c`](aes/crypt_and_hash.c): file encryption and authentication, demonstrating the generic cipher interface and the generic hash interface.
+
+## Hash (digest) examples
+
+* [`hash/generic_sum.c`](hash/generic_sum.c): file hash calculator and verifier, demonstrating the message digest (`md`) interface.
+
+* [`hash/hello.c`](hash/hello.c): hello-world program for MD5.
+
+## Public-key cryptography examples
+
+### Generic public-key cryptography (`pk`) examples
+
+* [`pkey/gen_key.c`](pkey/gen_key.c): generates a key for any of the supported public-key algorithms (RSA or ECC) and writes it to a file that can be used by the other pk sample programs.
+
+* [`pkey/key_app.c`](pkey/key_app.c): loads a PEM or DER public key or private key file and dumps its content.
+
+* [`pkey/key_app_writer.c`](pkey/key_app_writer.c): loads a PEM or DER public key or private key file and writes it to a new PEM or DER file.
+
+* [`pkey/pk_encrypt.c`](pkey/pk_encrypt.c), [`pkey/pk_decrypt.c`](pkey/pk_decrypt.c): loads a PEM or DER public/private key file and uses the key to encrypt/decrypt a short string through the generic public-key interface.
+
+* [`pkey/pk_sign.c`](pkey/pk_sign.c), [`pkey/pk_verify.c`](pkey/pk_verify.c): loads a PEM or DER private/public key file and uses the key to sign/verify a short string.
+
+### ECDSA and RSA signature examples
+
+* [`pkey/ecdsa.c`](pkey/ecdsa.c): generates an ECDSA key, signs a fixed message and verifies the signature.
+
+* [`pkey/rsa_encrypt.c`](pkey/rsa_encrypt.c), [`pkey/rsa_decrypt.c`](pkey/rsa_decrypt.c): loads an RSA public/private key and uses it to encrypt/decrypt a short string through the low-level RSA interface.
+
+* [`pkey/rsa_genkey.c`](pkey/rsa_genkey.c): generates an RSA key and writes it to a file that can be used with the other RSA sample programs.
+
+* [`pkey/rsa_sign.c`](pkey/rsa_sign.c), [`pkey/rsa_verify.c`](pkey/rsa_verify.c): loads an RSA private/public key and uses it to sign/verify a short string with the RSA PKCS#1 v1.5 algorithm.
+
+* [`pkey/rsa_sign_pss.c`](pkey/rsa_sign_pss.c), [`pkey/rsa_verify_pss.c`](pkey/rsa_verify_pss.c): loads an RSA private/public key and uses it to sign/verify a short string with the RSASSA-PSS algorithm.
+
+### Diffie-Hellman key exchange examples
+
+* [`pkey/dh_client.c`](pkey/dh_client.c), [`pkey/dh_server.c`](pkey/dh_server.c): secure channel demonstrators (client, server). This pair of programs illustrates how to set up a secure channel using RSA for authentication and Diffie-Hellman to generate a shared AES session key.
+
+* [`pkey/ecdh_curve25519.c`](pkey/ecdh_curve25519.c): demonstration of a elliptic curve Diffie-Hellman (ECDH) key agreement.
+
+### Bignum (`mpi`) usage examples
+
+* [`pkey/dh_genprime.c`](pkey/dh_genprime.c): shows how to use the bignum (`mpi`) interface to generate Diffie-Hellman parameters.
+
+* [`pkey/mpi_demo.c`](pkey/mpi_demo.c): demonstrates operations on big integers.
+
+## Random number generator (RNG) examples
+
+* [`random/gen_entropy.c`](random/gen_entropy.c): shows how to use the default entropy sources to generate random data.
+ Note: most applications should only use the entropy generator to seed a cryptographic pseudorandom generator, as illustrated by `random/gen_random_ctr_drbg.c`.
+
+* [`random/gen_random_ctr_drbg.c`](random/gen_random_ctr_drbg.c): shows how to use the default entropy sources to seed a pseudorandom generator, and how to use the resulting random generator to generate random data.
+
+* [`random/gen_random_havege.c`](random/gen_random_havege.c): demonstrates the HAVEGE entropy collector.
+
+## SSL/TLS examples
+
+### SSL/TLS sample applications
+
+* [`ssl/dtls_client.c`](ssl/dtls_client.c): a simple DTLS client program, which sends one datagram to the server and reads one datagram in response.
+
+* [`ssl/dtls_server.c`](ssl/dtls_server.c): a simple DTLS server program, which expects one datagram from the client and writes one datagram in response. This program supports DTLS cookies for hello verification.
+
+* [`ssl/mini_client.c`](ssl/mini_client.c): a minimalistic SSL client, which sends a short string and disconnects. This is primarily intended as a benchmark; for a better example of a typical TLS client, see `ssl/ssl_client1.c`.
+
+* [`ssl/ssl_client1.c`](ssl/ssl_client1.c): a simple HTTPS client that sends a fixed request and displays the response.
+
+* [`ssl/ssl_fork_server.c`](ssl/ssl_fork_server.c): a simple HTTPS server using one process per client to send a fixed response. This program requires a Unix/POSIX environment implementing the `fork` system call.
+
+* [`ssl/ssl_mail_client.c`](ssl/ssl_mail_client.c): a simple SMTP-over-TLS or SMTP-STARTTLS client. This client sends an email with fixed content.
+
+* [`ssl/ssl_pthread_server.c`](ssl/ssl_pthread_server.c): a simple HTTPS server using one thread per client to send a fixed response. This program requires the pthread library.
+
+* [`ssl/ssl_server.c`](ssl/ssl_server.c): a simple HTTPS server that sends a fixed response. It serves a single client at a time.
+
+### SSL/TLS feature demonstrators
+
+Note: unlike most of the other programs under the `programs/` directory, these two programs are not intended as a basis for writing an application. They combine most of the features supported by the library, and most applications require only a few features. To write a new application, we recommended that you start with `ssl_client1.c` or `ssl_server.c`, and then look inside `ssl/ssl_client2.c` or `ssl/ssl_server2.c` to see how to use the specific features that your application needs.
+
+* [`ssl/ssl_client2.c`](ssl/ssl_client2.c): an HTTPS client that sends a fixed request and displays the response, with options to select TLS protocol features and Mbed TLS library features.
+
+* [`ssl/ssl_server2.c`](ssl/ssl_server2.c): an HTTPS server that sends a fixed response, with options to select TLS protocol features and Mbed TLS library features.
+
+In addition to providing options for testing client-side features, the `ssl_client2` program has options that allow you to trigger certain behaviors in the server. For example, there are options to select ciphersuites, or to force a renegotiation. These options are useful for testing the corresponding features in a TLS server. Likewise, `ssl_server2` has options to activate certain behaviors that are useful for testing a TLS client.
+
+## Test utilities
+
+* [`test/benchmark.c`](test/benchmark.c): benchmark for cryptographic algorithms.
+
+* [`test/selftest.c`](test/selftest.c): runs the self-test function in each library module.
+
+* [`test/ssl_cert_test.c`](test/ssl_cert_test.c): demonstrates how to verify X.509 certificates, and (for RSA keys only) how to check that each certificate matches the corresponding private key. This program requires some test data which is not provided.
+
+* [`test/udp_proxy.c`](test/udp_proxy.c): a UDP proxy that can inject certain failures (delay, duplicate, drop). Useful for testing DTLS.
+
+* [`test/zeroize.c`](test/zeroize.c): a test program for `mbedtls_platform_zeroize`, used by [`tests/scripts/test_zeroize.gdb`](tests/scripts/test_zeroize.gdb).
+
+## Development utilities
+
+* [`util/pem2der.c`](util/pem2der.c): a PEM to DER converter. Mbed TLS can read PEM files directly, but this utility can be useful for interacting with other tools or with minimal Mbed TLS builds that lack PEM support.
+
+* [`util/strerror.c`](util/strerror.c): prints the error description corresponding to an integer status returned by an Mbed TLS function.
+
+## X.509 certificate examples
+
+* [`x509/cert_app.c`](x509/cert_app.c): connects to a TLS server and verifies its certificate chain.
+
+* [`x509/cert_req.c`](x509/cert_req.c): generates a certificate signing request (CSR) for a private key.
+
+* [`x509/cert_write.c`](x509/cert_write.c): signs a certificate signing request, or self-signs a certificate.
+
+* [`x509/crl_app.c`](x509/crl_app.c): loads and dumps a certificate revocation list (CRL).
+
+* [`x509/req_app.c`](x509/req_app.c): loads and dumps a certificate signing request (CSR).
+
diff --git a/programs/aes/aescrypt2.c b/programs/aes/aescrypt2.c
index 4acf38dd74..69c4060009 100644
--- a/programs/aes/aescrypt2.c
+++ b/programs/aes/aescrypt2.c
@@ -19,6 +19,11 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
+/* Enable definition of fileno() even when compiling with -std=c99. Must be
+ * set before config.h, which pulls in glibc's features.h indirectly.
+ * Harmless on other platforms. */
+#define _POSIX_C_SOURCE 1
+
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@@ -29,9 +34,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_fprintf fprintf
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_fprintf fprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#include "mbedtls/aes.h"
#include "mbedtls/md.h"
@@ -71,7 +79,8 @@ int main( void )
#else
int main( int argc, char *argv[] )
{
- int ret = 1;
+ int ret = 0;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
unsigned int i, n;
int mode, lastn;
@@ -429,7 +438,7 @@ int main( int argc, char *argv[] )
}
}
- ret = 0;
+ exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
if( fin )
@@ -452,6 +461,6 @@ exit:
mbedtls_aes_free( &aes_ctx );
mbedtls_md_free( &sha_ctx );
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_AES_C && MBEDTLS_SHA256_C && MBEDTLS_FS_IO */
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index 0e272ebe48..bc95eb9be5 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -20,6 +20,11 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
+/* Enable definition of fileno() even when compiling with -std=c99. Must be
+ * set before config.h, which pulls in glibc's features.h indirectly.
+ * Harmless on other platforms. */
+#define _POSIX_C_SOURCE 1
+
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@@ -30,9 +35,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_fprintf fprintf
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_fprintf fprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_MD_C) && \
defined(MBEDTLS_FS_IO)
@@ -74,6 +82,7 @@ int main( void )
int main( int argc, char *argv[] )
{
int ret = 1, i, n;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
int mode;
size_t keylen, ilen, olen;
FILE *fkey, *fin = NULL, *fout = NULL;
@@ -526,7 +535,7 @@ int main( int argc, char *argv[] )
}
}
- ret = 0;
+ exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
if( fin )
@@ -549,6 +558,6 @@ exit:
mbedtls_cipher_free( &cipher_ctx );
mbedtls_md_free( &md_ctx );
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_CIPHER_C && MBEDTLS_MD_C && MBEDTLS_FS_IO */
diff --git a/programs/hash/generic_sum.c b/programs/hash/generic_sum.c
index d1e81d4918..bbe8d92a20 100644
--- a/programs/hash/generic_sum.c
+++ b/programs/hash/generic_sum.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_fprintf fprintf
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_fprintf fprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_MD_C) && defined(MBEDTLS_FS_IO)
#include "mbedtls/md.h"
@@ -169,7 +172,8 @@ static int generic_check( const mbedtls_md_info_t *md_info, char *filename )
int main( int argc, char *argv[] )
{
- int ret, i;
+ int ret = 1, i;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
@@ -196,7 +200,7 @@ int main( int argc, char *argv[] )
fflush( stdout ); getchar();
#endif
- return( 1 );
+ return( exit_code );
}
/*
@@ -206,12 +210,12 @@ int main( int argc, char *argv[] )
if( md_info == NULL )
{
mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[1] );
- return( 1 );
+ return( exit_code );
}
if( mbedtls_md_setup( &md_ctx, md_info, 0 ) )
{
mbedtls_fprintf( stderr, "Failed to initialize context.\n" );
- return( 1 );
+ return( exit_code );
}
ret = 0;
@@ -224,9 +228,12 @@ int main( int argc, char *argv[] )
for( i = 2; i < argc; i++ )
ret |= generic_print( md_info, argv[i] );
+ if ( ret == 0 )
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_md_free( &md_ctx );
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_MD_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index 0978408c1c..3dadf48e6f 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#define mbedtls_time_t time_t
-#endif
+#include
+#define mbedtls_printf printf
+#define mbedtls_time_t time_t
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
@@ -71,7 +74,8 @@ int main( void )
{
FILE *f;
- int ret;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t n, buflen;
mbedtls_net_context server_fd;
@@ -115,7 +119,6 @@ int main( void )
if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not open rsa_pub.txt\n" \
" ! Please run rsa_genkey first\n\n" );
goto exit;
@@ -191,7 +194,6 @@ int main( void )
if( dhm.len < 64 || dhm.len > 512 )
{
- ret = 1;
mbedtls_printf( " failed\n ! Invalid DHM modulus size\n\n" );
goto exit;
}
@@ -207,7 +209,6 @@ int main( void )
if( ( n = (size_t) ( end - p ) ) != rsa.len )
{
- ret = 1;
mbedtls_printf( " failed\n ! Invalid RSA signature size\n\n" );
goto exit;
}
@@ -286,6 +287,8 @@ int main( void )
buf[16] = '\0';
mbedtls_printf( "\n . Plaintext is \"%s\"\n\n", (char *) buf );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_net_free( &server_fd );
@@ -301,7 +304,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
diff --git a/programs/pkey/dh_genprime.c b/programs/pkey/dh_genprime.c
index 84a94a18bd..dbe9153386 100644
--- a/programs/pkey/dh_genprime.c
+++ b/programs/pkey/dh_genprime.c
@@ -30,9 +30,11 @@
#else
#include
#include
-#define mbedtls_printf printf
-#define mbedtls_time_t time_t
-#endif
+#define mbedtls_printf printf
+#define mbedtls_time_t time_t
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \
@@ -69,6 +71,7 @@ int main( void )
int main( int argc, char **argv )
{
int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_mpi G, P, Q;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
@@ -86,7 +89,7 @@ int main( int argc, char **argv )
{
usage:
mbedtls_printf( USAGE );
- return( 1 );
+ return( exit_code );
}
for( i = 1; i < argc; i++ )
@@ -164,7 +167,6 @@ int main( int argc, char **argv )
if( ( fout = fopen( "dh_prime.txt", "wb+" ) ) == NULL )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not create dh_prime.txt\n\n" );
goto exit;
}
@@ -180,6 +182,8 @@ int main( int argc, char **argv )
mbedtls_printf( " ok\n\n" );
fclose( fout );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_mpi_free( &G ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
@@ -191,7 +195,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_FS_IO &&
MBEDTLS_CTR_DRBG_C && MBEDTLS_GENPRIME */
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index 430423154d..c4e2c391e2 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#define mbedtls_time_t time_t
-#endif
+#include
+#define mbedtls_printf printf
+#define mbedtls_time_t time_t
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
@@ -71,7 +74,8 @@ int main( void )
{
FILE *f;
- int ret;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t n, buflen;
mbedtls_net_context listen_fd, client_fd;
@@ -121,7 +125,6 @@ int main( void )
if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not open rsa_priv.txt\n" \
" ! Please run rsa_genkey first\n\n" );
goto exit;
@@ -164,7 +167,6 @@ int main( void )
if( ( f = fopen( "dh_prime.txt", "rb" ) ) == NULL )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not open dh_prime.txt\n" \
" ! Please run dh_genprime first\n\n" );
goto exit;
@@ -304,6 +306,8 @@ int main( void )
mbedtls_printf( "\n\n" );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
@@ -323,7 +327,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
diff --git a/programs/pkey/ecdh_curve25519.c b/programs/pkey/ecdh_curve25519.c
index e7ead9a938..5db04088f9 100644
--- a/programs/pkey/ecdh_curve25519.c
+++ b/programs/pkey/ecdh_curve25519.c
@@ -29,8 +29,11 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_ECDH_C) || \
!defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
@@ -51,7 +54,8 @@ int main( void )
int main( int argc, char *argv[] )
{
- int ret;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_ecdh_context ctx_cli, ctx_srv;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
@@ -218,6 +222,7 @@ int main( int argc, char *argv[] )
mbedtls_printf( " ok\n" );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
@@ -231,7 +236,7 @@ exit:
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
- return( ret != 0 );
+ return( exit_code );
}
#endif /* MBEDTLS_ECDH_C && MBEDTLS_ECP_DP_CURVE25519_ENABLED &&
MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/ecdsa.c b/programs/pkey/ecdsa.c
index b47406010d..c653df9e42 100644
--- a/programs/pkey/ecdsa.c
+++ b/programs/pkey/ecdsa.c
@@ -29,8 +29,11 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_ECDSA_C) && \
defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
@@ -98,7 +101,8 @@ static void dump_pubkey( const char *title, mbedtls_ecdsa_context *key )
int main( int argc, char *argv[] )
{
- int ret;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_ecdsa_context ctx_sign, ctx_verify;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
@@ -115,7 +119,6 @@ int main( int argc, char *argv[] )
memset( sig, 0, sizeof( sig ) );
memset( message, 0x25, sizeof( message ) );
- ret = 1;
if( argc != 1 )
{
@@ -213,8 +216,6 @@ int main( int argc, char *argv[] )
goto exit;
}
- ret = 0;
-
/*
* Verify signature
*/
@@ -231,6 +232,8 @@ int main( int argc, char *argv[] )
mbedtls_printf( " ok\n" );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
#if defined(_WIN32)
@@ -243,7 +246,7 @@ exit:
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
ECPARAMS */
diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c
index a7f5c90a6c..f01bf5fcdd 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -29,8 +29,11 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO) && \
defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
@@ -186,7 +189,8 @@ static int write_private_key( mbedtls_pk_context *key, const char *output_file )
int main( int argc, char *argv[] )
{
- int ret = 0;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_pk_context key;
char buf[1024];
int i;
@@ -214,7 +218,6 @@ int main( int argc, char *argv[] )
if( argc == 0 )
{
usage:
- ret = 1;
mbedtls_printf( USAGE );
#if defined(MBEDTLS_ECP_C)
mbedtls_printf( " available ec_curve values:\n" );
@@ -222,7 +225,7 @@ int main( int argc, char *argv[] )
mbedtls_printf( " %s (default)\n", curve_info->name );
while( ( ++curve_info )->name != NULL )
mbedtls_printf( " %s\n", curve_info->name );
-#endif
+#endif /* MBEDTLS_ECP_C */
goto exit;
}
@@ -411,9 +414,11 @@ int main( int argc, char *argv[] )
mbedtls_printf( " ok\n" );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
- if( ret != 0 && ret != 1)
+ if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror( ret, buf, sizeof( buf ) );
@@ -436,7 +441,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_PEM_WRITE_C && MBEDTLS_FS_IO &&
* MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/key_app.c b/programs/pkey/key_app.c
index f1b548d05f..027b95f9d1 100644
--- a/programs/pkey/key_app.c
+++ b/programs/pkey/key_app.c
@@ -29,8 +29,11 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_BIGNUM_C) && \
defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO)
@@ -83,7 +86,8 @@ struct options
int main( int argc, char *argv[] )
{
- int ret = 0;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
char buf[1024];
int i;
char *p, *q;
@@ -105,7 +109,7 @@ int main( int argc, char *argv[] )
{
usage:
mbedtls_printf( USAGE );
- goto exit;
+ goto cleanup;
}
opt.mode = DFL_MODE;
@@ -155,13 +159,13 @@ int main( int argc, char *argv[] )
if( ( f = fopen( opt.password_file, "rb" ) ) == NULL )
{
mbedtls_printf( " failed\n ! fopen returned NULL\n" );
- goto exit;
+ goto cleanup;
}
if( fgets( buf, sizeof(buf), f ) == NULL )
{
fclose( f );
mbedtls_printf( "Error: fgets() failed to retrieve password\n" );
- goto exit;
+ goto cleanup;
}
fclose( f );
@@ -182,7 +186,7 @@ int main( int argc, char *argv[] )
if( ret != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret );
- goto exit;
+ goto cleanup;
}
mbedtls_printf( " ok\n" );
@@ -200,17 +204,17 @@ int main( int argc, char *argv[] )
( ret = mbedtls_rsa_export_crt( rsa, &DP, &DQ, &QP ) ) != 0 )
{
mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" );
- goto exit;
+ goto cleanup;
}
- mbedtls_mpi_write_file( "N: ", &N, 16, NULL );
- mbedtls_mpi_write_file( "E: ", &E, 16, NULL );
- mbedtls_mpi_write_file( "D: ", &D, 16, NULL );
- mbedtls_mpi_write_file( "P: ", &P, 16, NULL );
- mbedtls_mpi_write_file( "Q: ", &Q, 16, NULL );
- mbedtls_mpi_write_file( "DP: ", &DP, 16, NULL );
- mbedtls_mpi_write_file( "DQ: ", &DQ, 16, NULL );
- mbedtls_mpi_write_file( "QP: ", &QP, 16, NULL );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "N: ", &N, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "E: ", &E, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "D: ", &D, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "P: ", &P, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q: ", &Q, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "DP: ", &DP, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "DQ: ", &DQ, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "QP: ", &QP, 16, NULL ) );
}
else
#endif
@@ -218,16 +222,16 @@ int main( int argc, char *argv[] )
if( mbedtls_pk_get_type( &pk ) == MBEDTLS_PK_ECKEY )
{
mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( pk );
- mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL );
- mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL );
- mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL );
- mbedtls_mpi_write_file( "D : ", &ecp->d , 16, NULL );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "D : ", &ecp->d , 16, NULL ) );
}
else
#endif
{
mbedtls_printf("Do not know how to print key information for this type\n" );
- goto exit;
+ goto cleanup;
}
}
else if( opt.mode == MODE_PUBLIC )
@@ -243,7 +247,7 @@ int main( int argc, char *argv[] )
if( ret != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret );
- goto exit;
+ goto cleanup;
}
mbedtls_printf( " ok\n" );
@@ -258,10 +262,10 @@ int main( int argc, char *argv[] )
NULL, &E ) ) != 0 )
{
mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" );
- goto exit;
+ goto cleanup;
}
- mbedtls_mpi_write_file( "N: ", &N, 16, NULL );
- mbedtls_mpi_write_file( "E: ", &E, 16, NULL );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "N: ", &N, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "E: ", &E, 16, NULL ) );
}
else
#endif
@@ -269,26 +273,28 @@ int main( int argc, char *argv[] )
if( mbedtls_pk_get_type( &pk ) == MBEDTLS_PK_ECKEY )
{
mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( pk );
- mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL );
- mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL );
- mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ) );
}
else
#endif
{
mbedtls_printf("Do not know how to print key information for this type\n" );
- goto exit;
+ goto cleanup;
}
}
else
goto usage;
-exit:
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
+cleanup:
#if defined(MBEDTLS_ERROR_C)
- if( ret != 0 )
+ if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
- mbedtls_strerror( ret, buf, sizeof(buf) );
+ mbedtls_strerror( ret, buf, sizeof( buf ) );
mbedtls_printf( " ! Last error was: %s\n", buf );
}
#endif
@@ -303,6 +309,6 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c
index 52b0f8e744..13602c2e53 100644
--- a/programs/pkey/key_app_writer.c
+++ b/programs/pkey/key_app_writer.c
@@ -29,8 +29,11 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO)
#include "mbedtls/error.h"
@@ -128,7 +131,7 @@ static int write_public_key( mbedtls_pk_context *key, const char *output_file )
return( ret );
len = ret;
- c = output_buf + sizeof(output_buf) - len - 1;
+ c = output_buf + sizeof(output_buf) - len;
}
if( ( f = fopen( output_file, "w" ) ) == NULL )
@@ -189,7 +192,8 @@ static int write_private_key( mbedtls_pk_context *key, const char *output_file )
int main( int argc, char *argv[] )
{
- int ret = 0;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
char buf[1024];
int i;
char *p, *q;
@@ -210,7 +214,6 @@ int main( int argc, char *argv[] )
if( argc == 0 )
{
usage:
- ret = 1;
mbedtls_printf( USAGE );
goto exit;
}
@@ -403,9 +406,11 @@ int main( int argc, char *argv[] )
write_private_key( &key, opt.output_file );
}
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
- if( ret != 0 && ret != 1)
+ if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror( ret, buf, sizeof( buf ) );
@@ -426,6 +431,6 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/mpi_demo.c b/programs/pkey/mpi_demo.c
index afe8957e79..365bdc4806 100644
--- a/programs/pkey/mpi_demo.c
+++ b/programs/pkey/mpi_demo.c
@@ -29,8 +29,11 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_FS_IO)
#include "mbedtls/bignum.h"
@@ -47,7 +50,8 @@ int main( void )
#else
int main( void )
{
- int ret;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_mpi E, P, Q, N, H, D, X, Y, Z;
mbedtls_mpi_init( &E ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &N );
@@ -88,15 +92,16 @@ int main( void )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Z (decrypted) = Y^D mod N = ", &Z, 10, NULL ) );
mbedtls_printf( "\n" );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
cleanup:
mbedtls_mpi_free( &E ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); mbedtls_mpi_free( &N );
mbedtls_mpi_free( &H ); mbedtls_mpi_free( &D ); mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
mbedtls_mpi_free( &Z );
- if( ret != 0 )
+ if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
mbedtls_printf( "\nAn error occurred.\n" );
- ret = 1;
}
#if defined(_WIN32)
@@ -104,6 +109,6 @@ cleanup:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/pk_decrypt.c b/programs/pkey/pk_decrypt.c
index 32fbc7545a..1d8c959a09 100644
--- a/programs/pkey/pk_decrypt.c
+++ b/programs/pkey/pk_decrypt.c
@@ -29,8 +29,11 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_PK_PARSE_C) && \
defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_C) && \
@@ -59,7 +62,8 @@ int main( void )
int main( int argc, char *argv[] )
{
FILE *f;
- int ret, c;
+ int ret = 1, c;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t i, olen = 0;
mbedtls_pk_context pk;
mbedtls_entropy_context entropy;
@@ -69,9 +73,11 @@ int main( int argc, char *argv[] )
const char *pers = "mbedtls_pk_decrypt";
((void) argv);
+ mbedtls_pk_init( &pk );
+ mbedtls_entropy_init( &entropy );
mbedtls_ctr_drbg_init( &ctr_drbg );
+
memset(result, 0, sizeof( result ) );
- ret = 1;
if( argc != 2 )
{
@@ -87,20 +93,18 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Seeding the random number generator..." );
fflush( stdout );
- mbedtls_entropy_init( &entropy );
- if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
- (const unsigned char *) pers,
- strlen( pers ) ) ) != 0 )
+ if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
+ &entropy, (const unsigned char *) pers,
+ strlen( pers ) ) ) != 0 )
{
- mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
+ mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n",
+ -ret );
goto exit;
}
mbedtls_printf( "\n . Reading private key from '%s'", argv[1] );
fflush( stdout );
- mbedtls_pk_init( &pk );
-
if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret );
@@ -110,19 +114,19 @@ int main( int argc, char *argv[] )
/*
* Extract the RSA encrypted value from the text file
*/
- ret = 1;
-
if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL )
{
mbedtls_printf( "\n ! Could not open %s\n\n", "result-enc.txt" );
+ ret = 1;
goto exit;
}
i = 0;
-
while( fscanf( f, "%02X", &c ) > 0 &&
i < (int) sizeof( buf ) )
+ {
buf[i++] = (unsigned char) c;
+ }
fclose( f );
@@ -135,7 +139,8 @@ int main( int argc, char *argv[] )
if( ( ret = mbedtls_pk_decrypt( &pk, buf, i, result, &olen, sizeof(result),
mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
{
- mbedtls_printf( " failed\n ! mbedtls_pk_decrypt returned -0x%04x\n", -ret );
+ mbedtls_printf( " failed\n ! mbedtls_pk_decrypt returned -0x%04x\n",
+ -ret );
goto exit;
}
@@ -143,16 +148,18 @@ int main( int argc, char *argv[] )
mbedtls_printf( "The decrypted result is: '%s'\n\n", result );
- ret = 0;
+ exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
- mbedtls_ctr_drbg_free( &ctr_drbg );
+
+ mbedtls_pk_free( &pk );
mbedtls_entropy_free( &entropy );
+ mbedtls_ctr_drbg_free( &ctr_drbg );
#if defined(MBEDTLS_ERROR_C)
- if( ret != 0 )
+ if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
- mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
+ mbedtls_strerror( ret, (char *) buf, sizeof( buf ) );
mbedtls_printf( " ! Last error was: %s\n", buf );
}
#endif
@@ -162,7 +169,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/pk_encrypt.c b/programs/pkey/pk_encrypt.c
index 7ca9d5ad9b..22dedba103 100644
--- a/programs/pkey/pk_encrypt.c
+++ b/programs/pkey/pk_encrypt.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_fprintf fprintf
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_fprintf fprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_PK_PARSE_C) && \
defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO) && \
@@ -59,7 +62,8 @@ int main( void )
int main( int argc, char *argv[] )
{
FILE *f;
- int ret;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t i, olen = 0;
mbedtls_pk_context pk;
mbedtls_entropy_context entropy;
@@ -68,8 +72,9 @@ int main( int argc, char *argv[] )
unsigned char buf[512];
const char *pers = "mbedtls_pk_encrypt";
- ret = 1;
mbedtls_ctr_drbg_init( &ctr_drbg );
+ mbedtls_entropy_init( &entropy );
+ mbedtls_pk_init( &pk );
if( argc != 3 )
{
@@ -85,20 +90,18 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Seeding the random number generator..." );
fflush( stdout );
- mbedtls_entropy_init( &entropy );
- if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
- (const unsigned char *) pers,
- strlen( pers ) ) ) != 0 )
+ if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
+ &entropy, (const unsigned char *) pers,
+ strlen( pers ) ) ) != 0 )
{
- mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret );
+ mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n",
+ -ret );
goto exit;
}
mbedtls_printf( "\n . Reading public key from '%s'", argv[1] );
fflush( stdout );
- mbedtls_pk_init( &pk );
-
if( ( ret = mbedtls_pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret );
@@ -123,7 +126,8 @@ int main( int argc, char *argv[] )
buf, &olen, sizeof(buf),
mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
{
- mbedtls_printf( " failed\n ! mbedtls_pk_encrypt returned -0x%04x\n", -ret );
+ mbedtls_printf( " failed\n ! mbedtls_pk_encrypt returned -0x%04x\n",
+ -ret );
goto exit;
}
@@ -132,27 +136,34 @@ int main( int argc, char *argv[] )
*/
if( ( f = fopen( "result-enc.txt", "wb+" ) ) == NULL )
{
+ mbedtls_printf( " failed\n ! Could not create %s\n\n",
+ "result-enc.txt" );
ret = 1;
- mbedtls_printf( " failed\n ! Could not create %s\n\n", "result-enc.txt" );
goto exit;
}
for( i = 0; i < olen; i++ )
+ {
mbedtls_fprintf( f, "%02X%s", buf[i],
( i + 1 ) % 16 == 0 ? "\r\n" : " " );
+ }
fclose( f );
mbedtls_printf( "\n . Done (created \"%s\")\n\n", "result-enc.txt" );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
- mbedtls_ctr_drbg_free( &ctr_drbg );
+
+ mbedtls_pk_free( &pk );
mbedtls_entropy_free( &entropy );
+ mbedtls_ctr_drbg_free( &ctr_drbg );
#if defined(MBEDTLS_ERROR_C)
- if( ret != 0 )
+ if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
- mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
+ mbedtls_strerror( ret, (char *) buf, sizeof( buf ) );
mbedtls_printf( " ! Last error was: %s\n", buf );
}
#endif
@@ -162,7 +173,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c
index 55df95e49d..7ec46752ad 100644
--- a/programs/pkey/pk_sign.c
+++ b/programs/pkey/pk_sign.c
@@ -30,9 +30,11 @@
#else
#include
#include
-#define mbedtls_snprintf snprintf
-#define mbedtls_printf printf
-#endif
+#define mbedtls_snprintf snprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \
@@ -61,6 +63,7 @@ int main( int argc, char *argv[] )
{
FILE *f;
int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_pk_context pk;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
@@ -134,14 +137,12 @@ int main( int argc, char *argv[] )
if( ( f = fopen( filename, "wb+" ) ) == NULL )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not create %s\n\n", filename );
goto exit;
}
if( fwrite( buf, 1, olen, f ) != olen )
{
- ret = 1;
mbedtls_printf( "failed\n ! fwrite failed\n\n" );
fclose( f );
goto exit;
@@ -151,13 +152,15 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_pk_free( &pk );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
#if defined(MBEDTLS_ERROR_C)
- if( ret != 0 )
+ if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
mbedtls_printf( " ! Last error was: %s\n", buf );
@@ -169,7 +172,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret ? EXIT_FAILURE : EXIT_SUCCESS );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
diff --git a/programs/pkey/pk_verify.c b/programs/pkey/pk_verify.c
index d35d17f69d..3c7709f9d5 100644
--- a/programs/pkey/pk_verify.c
+++ b/programs/pkey/pk_verify.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_snprintf snprintf
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_snprintf snprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_MD_C) || \
!defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_PK_PARSE_C) || \
@@ -56,6 +59,7 @@ int main( int argc, char *argv[] )
{
FILE *f;
int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t i;
mbedtls_pk_context pk;
unsigned char hash[32];
@@ -87,7 +91,6 @@ int main( int argc, char *argv[] )
/*
* Extract the signature from the file
*/
- ret = 1;
mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[2] );
if( ( f = fopen( filename, "rb" ) ) == NULL )
@@ -125,13 +128,13 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . OK (the signature is valid)\n\n" );
- ret = 0;
+ exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
mbedtls_pk_free( &pk );
#if defined(MBEDTLS_ERROR_C)
- if( ret != 0 )
+ if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
mbedtls_printf( " ! Last error was: %s\n", buf );
@@ -143,7 +146,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_SHA256_C &&
MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_decrypt.c b/programs/pkey/rsa_decrypt.c
index 2da3fbf110..0a252d2ada 100644
--- a/programs/pkey/rsa_decrypt.c
+++ b/programs/pkey/rsa_decrypt.c
@@ -30,11 +30,11 @@
#else
#include
#include
-#define mbedtls_printf printf
-#define mbedtls_exit exit
+#define mbedtls_printf printf
+#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
-#endif
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_RSA_C) && \
defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_C) && \
@@ -61,7 +61,9 @@ int main( void )
int main( int argc, char *argv[] )
{
FILE *f;
- int return_val, exit_val, c;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
+ int c;
size_t i;
mbedtls_rsa_context rsa;
mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
@@ -73,7 +75,6 @@ int main( int argc, char *argv[] )
((void) argv);
memset(result, 0, sizeof( result ) );
- exit_val = MBEDTLS_EXIT_SUCCESS;
if( argc != 1 )
{
@@ -83,7 +84,7 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n" );
#endif
- mbedtls_exit( MBEDTLS_EXIT_FAILURE );
+ mbedtls_exit( exit_code );
}
mbedtls_printf( "\n . Seeding the random number generator..." );
@@ -96,14 +97,13 @@ int main( int argc, char *argv[] )
mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP );
mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP );
- return_val = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
+ ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
&entropy, (const unsigned char *) pers,
strlen( pers ) );
- if( return_val != 0 )
+ if( ret != 0 )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n",
- return_val );
+ ret );
goto exit;
}
@@ -112,40 +112,38 @@ int main( int argc, char *argv[] )
if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! Could not open rsa_priv.txt\n" \
" ! Please run rsa_genkey first\n\n" );
goto exit;
}
- if( ( return_val = mbedtls_mpi_read_file( &N , 16, f ) ) != 0 ||
- ( return_val = mbedtls_mpi_read_file( &E , 16, f ) ) != 0 ||
- ( return_val = mbedtls_mpi_read_file( &D , 16, f ) ) != 0 ||
- ( return_val = mbedtls_mpi_read_file( &P , 16, f ) ) != 0 ||
- ( return_val = mbedtls_mpi_read_file( &Q , 16, f ) ) != 0 ||
- ( return_val = mbedtls_mpi_read_file( &DP , 16, f ) ) != 0 ||
- ( return_val = mbedtls_mpi_read_file( &DQ , 16, f ) ) != 0 ||
- ( return_val = mbedtls_mpi_read_file( &QP , 16, f ) ) != 0 )
+ if( ( ret = mbedtls_mpi_read_file( &N , 16, f ) ) != 0 ||
+ ( ret = mbedtls_mpi_read_file( &E , 16, f ) ) != 0 ||
+ ( ret = mbedtls_mpi_read_file( &D , 16, f ) ) != 0 ||
+ ( ret = mbedtls_mpi_read_file( &P , 16, f ) ) != 0 ||
+ ( ret = mbedtls_mpi_read_file( &Q , 16, f ) ) != 0 ||
+ ( ret = mbedtls_mpi_read_file( &DP , 16, f ) ) != 0 ||
+ ( ret = mbedtls_mpi_read_file( &DQ , 16, f ) ) != 0 ||
+ ( ret = mbedtls_mpi_read_file( &QP , 16, f ) ) != 0 )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n",
- return_val );
+ ret );
fclose( f );
goto exit;
}
fclose( f );
- if( ( return_val = mbedtls_rsa_import( &rsa, &N, &P, &Q, &D, &E ) ) != 0 )
+ if( ( ret = mbedtls_rsa_import( &rsa, &N, &P, &Q, &D, &E ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_rsa_import returned %d\n\n",
- return_val );
+ ret );
goto exit;
}
- if( ( return_val = mbedtls_rsa_complete( &rsa ) ) != 0 )
+ if( ( ret = mbedtls_rsa_complete( &rsa ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_rsa_complete returned %d\n\n",
- return_val );
+ ret );
goto exit;
}
@@ -154,7 +152,6 @@ int main( int argc, char *argv[] )
*/
if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( "\n ! Could not open %s\n\n", "result-enc.txt" );
goto exit;
}
@@ -169,7 +166,6 @@ int main( int argc, char *argv[] )
if( i != rsa.len )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( "\n ! Invalid RSA signature format\n\n" );
goto exit;
}
@@ -180,14 +176,13 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Decrypting the encrypted data" );
fflush( stdout );
- return_val = mbedtls_rsa_pkcs1_decrypt( &rsa, mbedtls_ctr_drbg_random,
+ ret = mbedtls_rsa_pkcs1_decrypt( &rsa, mbedtls_ctr_drbg_random,
&ctr_drbg, MBEDTLS_RSA_PRIVATE, &i,
buf, result, 1024 );
- if( return_val != 0 )
+ if( ret != 0 )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_decrypt returned %d\n\n",
- return_val );
+ ret );
goto exit;
}
@@ -195,6 +190,8 @@ int main( int argc, char *argv[] )
mbedtls_printf( "The decrypted result is: '%s'\n\n", result );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
@@ -208,6 +205,6 @@ exit:
fflush( stdout ); getchar();
#endif
- return( exit_val );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_encrypt.c b/programs/pkey/rsa_encrypt.c
index 81c27d888f..411657a07c 100644
--- a/programs/pkey/rsa_encrypt.c
+++ b/programs/pkey/rsa_encrypt.c
@@ -30,12 +30,12 @@
#else
#include
#include
-#define mbedtls_fprintf fprintf
-#define mbedtls_printf printf
-#define mbedtls_exit exit
-#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
-#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
-#endif
+#define mbedtls_fprintf fprintf
+#define mbedtls_printf printf
+#define mbedtls_exit exit
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_RSA_C) && \
defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO) && \
@@ -61,7 +61,8 @@ int main( void )
int main( int argc, char *argv[] )
{
FILE *f;
- int return_val, exit_val;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t i;
mbedtls_rsa_context rsa;
mbedtls_entropy_context entropy;
@@ -71,8 +72,6 @@ int main( int argc, char *argv[] )
const char *pers = "rsa_encrypt";
mbedtls_mpi N, E;
- exit_val = MBEDTLS_EXIT_SUCCESS;
-
if( argc != 2 )
{
mbedtls_printf( "usage: rsa_encrypt \n" );
@@ -81,7 +80,7 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n" );
#endif
- mbedtls_exit( MBEDTLS_EXIT_FAILURE );
+ mbedtls_exit( exit_code );
}
mbedtls_printf( "\n . Seeding the random number generator..." );
@@ -92,14 +91,13 @@ int main( int argc, char *argv[] )
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );
- return_val = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
- &entropy, (const unsigned char *) pers,
- strlen( pers ) );
- if( return_val != 0 )
+ ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
+ &entropy, (const unsigned char *) pers,
+ strlen( pers ) );
+ if( ret != 0 )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n",
- return_val );
+ ret );
goto exit;
}
@@ -108,35 +106,30 @@ int main( int argc, char *argv[] )
if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! Could not open rsa_pub.txt\n" \
" ! Please run rsa_genkey first\n\n" );
goto exit;
}
- if( ( return_val = mbedtls_mpi_read_file( &N, 16, f ) ) != 0 ||
- ( return_val = mbedtls_mpi_read_file( &E, 16, f ) ) != 0 )
+ if( ( ret = mbedtls_mpi_read_file( &N, 16, f ) ) != 0 ||
+ ( ret = mbedtls_mpi_read_file( &E, 16, f ) ) != 0 )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n",
- return_val );
+ ret );
fclose( f );
goto exit;
}
fclose( f );
- if( ( return_val = mbedtls_rsa_import( &rsa, &N, NULL,
- NULL, NULL, &E ) ) != 0 )
+ if( ( ret = mbedtls_rsa_import( &rsa, &N, NULL, NULL, NULL, &E ) ) != 0 )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! mbedtls_rsa_import returned %d\n\n",
- return_val );
+ ret );
goto exit;
}
if( strlen( argv[1] ) > 100 )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " Input data larger than 100 characters.\n\n" );
goto exit;
}
@@ -149,14 +142,13 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Generating the RSA encrypted value" );
fflush( stdout );
- return_val = mbedtls_rsa_pkcs1_encrypt( &rsa, mbedtls_ctr_drbg_random,
- &ctr_drbg, MBEDTLS_RSA_PUBLIC,
- strlen( argv[1] ), input, buf );
- if( return_val != 0 )
+ ret = mbedtls_rsa_pkcs1_encrypt( &rsa, mbedtls_ctr_drbg_random,
+ &ctr_drbg, MBEDTLS_RSA_PUBLIC,
+ strlen( argv[1] ), input, buf );
+ if( ret != 0 )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_encrypt returned %d\n\n",
- return_val );
+ ret );
goto exit;
}
@@ -165,7 +157,6 @@ int main( int argc, char *argv[] )
*/
if( ( f = fopen( "result-enc.txt", "wb+" ) ) == NULL )
{
- exit_val = MBEDTLS_EXIT_FAILURE;
mbedtls_printf( " failed\n ! Could not create %s\n\n", "result-enc.txt" );
goto exit;
}
@@ -178,6 +169,8 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Done (created \"%s\")\n\n", "result-enc.txt" );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_mpi_free( &N ); mbedtls_mpi_free( &E );
mbedtls_ctr_drbg_free( &ctr_drbg );
@@ -189,7 +182,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( exit_val );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/rsa_genkey.c b/programs/pkey/rsa_genkey.c
index 9399217612..3359e14074 100644
--- a/programs/pkey/rsa_genkey.c
+++ b/programs/pkey/rsa_genkey.c
@@ -29,8 +29,11 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \
defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) && \
@@ -61,7 +64,8 @@ int main( void )
#else
int main( void )
{
- int ret;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_rsa_context rsa;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
@@ -105,14 +109,12 @@ int main( void )
( ret = mbedtls_rsa_export_crt( &rsa, &DP, &DQ, &QP ) ) != 0 )
{
mbedtls_printf( " failed\n ! could not export RSA parameters\n\n" );
- ret = 1;
goto exit;
}
if( ( fpub = fopen( "rsa_pub.txt", "wb+" ) ) == NULL )
{
mbedtls_printf( " failed\n ! could not open rsa_pub.txt for writing\n\n" );
- ret = 1;
goto exit;
}
@@ -129,7 +131,6 @@ int main( void )
if( ( fpriv = fopen( "rsa_priv.txt", "wb+" ) ) == NULL )
{
mbedtls_printf( " failed\n ! could not open rsa_priv.txt for writing\n" );
- ret = 1;
goto exit;
}
@@ -160,6 +161,8 @@ int main( void )
*/
mbedtls_printf( " ok\n\n" );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
if( fpub != NULL )
@@ -180,7 +183,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_RSA_C &&
MBEDTLS_GENPRIME && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c
index 89018cb765..b16fe5d226 100644
--- a/programs/pkey/rsa_sign.c
+++ b/programs/pkey/rsa_sign.c
@@ -29,10 +29,13 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_fprintf fprintf
-#define mbedtls_printf printf
-#define mbedtls_snprintf snprintf
-#endif
+#include
+#define mbedtls_fprintf fprintf
+#define mbedtls_printf printf
+#define mbedtls_snprintf snprintf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \
@@ -55,7 +58,8 @@ int main( void )
int main( int argc, char *argv[] )
{
FILE *f;
- int ret;
+ int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t i;
mbedtls_rsa_context rsa;
unsigned char hash[32];
@@ -69,8 +73,6 @@ int main( int argc, char *argv[] )
mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP );
mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP );
- ret = 1;
-
if( argc != 2 )
{
mbedtls_printf( "usage: rsa_sign \n" );
@@ -87,7 +89,6 @@ int main( int argc, char *argv[] )
if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not open rsa_priv.txt\n" \
" ! Please run rsa_genkey first\n\n" );
goto exit;
@@ -159,7 +160,6 @@ int main( int argc, char *argv[] )
if( ( f = fopen( filename, "wb+" ) ) == NULL )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not create %s\n\n", argv[1] );
goto exit;
}
@@ -172,6 +172,8 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_rsa_free( &rsa );
@@ -184,7 +186,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_sign_pss.c b/programs/pkey/rsa_sign_pss.c
index 7b6f14dd8e..b0b0f7ecf4 100644
--- a/programs/pkey/rsa_sign_pss.c
+++ b/programs/pkey/rsa_sign_pss.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_snprintf snprintf
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_snprintf snprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) || \
@@ -61,6 +64,7 @@ int main( int argc, char *argv[] )
{
FILE *f;
int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_pk_context pk;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
@@ -101,7 +105,6 @@ int main( int argc, char *argv[] )
if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not read key from '%s'\n", argv[1] );
mbedtls_printf( " ! mbedtls_pk_parse_public_keyfile returned %d\n\n", ret );
goto exit;
@@ -109,7 +112,6 @@ int main( int argc, char *argv[] )
if( !mbedtls_pk_can_do( &pk, MBEDTLS_PK_RSA ) )
{
- ret = 1;
mbedtls_printf( " failed\n ! Key is not an RSA key\n" );
goto exit;
}
@@ -145,7 +147,6 @@ int main( int argc, char *argv[] )
if( ( f = fopen( filename, "wb+" ) ) == NULL )
{
- ret = 1;
mbedtls_printf( " failed\n ! Could not create %s\n\n", filename );
goto exit;
}
@@ -161,6 +162,8 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename );
+ exit_code = MBEDTLS_EXIT_SUCCESS;
+
exit:
mbedtls_pk_free( &pk );
mbedtls_ctr_drbg_free( &ctr_drbg );
@@ -171,7 +174,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_RSA_C &&
MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c
index 1f827aa072..6f88345f2e 100644
--- a/programs/pkey/rsa_verify.c
+++ b/programs/pkey/rsa_verify.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_printf printf
-#define mbedtls_snprintf snprintf
-#endif
+#include
+#define mbedtls_printf printf
+#define mbedtls_snprintf snprintf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \
@@ -54,7 +57,8 @@ int main( void )
int main( int argc, char *argv[] )
{
FILE *f;
- int ret, c;
+ int ret = 1, c;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t i;
mbedtls_rsa_context rsa;
unsigned char hash[32];
@@ -62,7 +66,6 @@ int main( int argc, char *argv[] )
char filename[512];
mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
- ret = 1;
if( argc != 2 )
{
@@ -100,7 +103,6 @@ int main( int argc, char *argv[] )
/*
* Extract the RSA signature from the text file
*/
- ret = 1;
mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[1] );
if( ( f = fopen( filename, "rb" ) ) == NULL )
@@ -146,7 +148,7 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . OK (the signature is valid)\n\n" );
- ret = 0;
+ exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
@@ -157,7 +159,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_verify_pss.c b/programs/pkey/rsa_verify_pss.c
index 31b720f360..7c9c68f229 100644
--- a/programs/pkey/rsa_verify_pss.c
+++ b/programs/pkey/rsa_verify_pss.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_snprintf snprintf
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_snprintf snprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) || \
@@ -60,6 +63,7 @@ int main( int argc, char *argv[] )
{
FILE *f;
int ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
size_t i;
mbedtls_pk_context pk;
unsigned char hash[32];
@@ -91,7 +95,6 @@ int main( int argc, char *argv[] )
if( !mbedtls_pk_can_do( &pk, MBEDTLS_PK_RSA ) )
{
- ret = 1;
mbedtls_printf( " failed\n ! Key is not an RSA key\n" );
goto exit;
}
@@ -101,7 +104,6 @@ int main( int argc, char *argv[] )
/*
* Extract the RSA signature from the file
*/
- ret = 1;
mbedtls_snprintf( filename, 512, "%s.sig", argv[2] );
if( ( f = fopen( filename, "rb" ) ) == NULL )
@@ -139,7 +141,7 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . OK (the signature is valid)\n\n" );
- ret = 0;
+ exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
mbedtls_pk_free( &pk );
@@ -149,7 +151,7 @@ exit:
fflush( stdout ); getchar();
#endif
- return( ret );
+ return( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/random/gen_entropy.c b/programs/random/gen_entropy.c
index 792d3818ab..a1eb3868a4 100644
--- a/programs/random/gen_entropy.c
+++ b/programs/random/gen_entropy.c
@@ -29,9 +29,12 @@
#include "mbedtls/platform.h"
#else
#include
-#define mbedtls_fprintf fprintf
-#define mbedtls_printf printf
-#endif
+#include
+#define mbedtls_fprintf fprintf
+#define mbedtls_printf printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO)
#include "mbedtls/entropy.h"
@@ -49,20 +52,21 @@ int main( void )
int main( int argc, char *argv[] )
{
FILE *f;
- int i, k, ret;
+ int i, k, ret = 1;
+ int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_entropy_context entropy;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
if( argc < 2 )
{
mbedtls_fprintf( stderr, "usage: %s