Merge branch 'le-secure-connection' into develop

This commit is contained in:
Matthias Ringwald 2016-06-10 13:22:15 +02:00
commit e314fd6b1e
49 changed files with 18131 additions and 189 deletions

1943
3rd-party/mbedtls/ChangeLog vendored Normal file

File diff suppressed because it is too large Load Diff

2
3rd-party/mbedtls/LICENSE vendored Normal file
View File

@ -0,0 +1,2 @@
Unless specifically indicated otherwise in a file, files are licensed
under the Apache 2.0 license, as can be found in: apache-2.0.txt

173
3rd-party/mbedtls/README.md vendored Normal file
View File

@ -0,0 +1,173 @@
README for mbed TLS
===================
Configuration
-------------
mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully-documented configuration file `include/mbedtls/config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Perl script `scripts/config.pl` (use `--help` for usage instructions).
Compiler options can be set using standard variables such as `CC` and `CFLAGS` when using the Make and CMake build system (see below).
Compiling
---------
There are currently four active build systems within the mbed TLS releases:
- yotta
- Make
- CMake
- Microsoft Visual Studio (Visual Studio 6 and Visual Studio 2010)
The main systems used for development are CMake and yotta. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and yotta build system, but some features are not ported there by default.
Please note that the yotta option is slightly different from the other build systems:
- a more minimalistic configuration file is used by default
- depending on the yotta target, features of mbed OS will 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; it is the build system of mbed OS. 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 form 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 need first need to generate the yotta module by running:
yotta/create-module.sh
from the mbed TLS root directory. This will create the yotta module in the `yotta/module` directory. 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's already 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 intentionally only use the absolute minimum of `Make` functionality, as a lot of `Make` features are not supported on all different implementations of Make on different platforms. As such, the Makefiles sometimes require some handwork or export statements in order to work for your platform.
In order to build the source using Make, just enter at the command line:
make
In order to run the tests, enter:
make check
The tests need Perl to be built and run. If you don't have Perl installed, you can skip building the tests with:
make no_test
You'll still be able to run a much smaller set of tests with:
programs/test/selftest
In order to build for a Windows platform, you should use `WINDOWS_BUILD=1` if the target is Windows but the build environment is Unix-like (for instance when cross-compiling, or compiling from an MSYS shell), and `WINDOWS=1` if the build environment is a Windows shell (for instance using mingw32-make) (in that case some targets will not be available).
Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; if you do so, essential parts such as `-I` will still be preserved. Warning options may be overridden separately using `WARNING_CFLAGS`.
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 KB.
### CMake
In order to build the source using CMake, just enter at the command line:
cmake .
make
In order to run the tests, enter:
make test
The test suites need Perl to be built. If you don't have Perl installed, you'll want to disable the test suites with:
cmake -DENABLE_TESTING=Off .
If you disabled the test suites, but kept the programs enabled, you can still run a much smaller set of tests with:
programs/test/selftest
To configure CMake for building shared libraries, use:
cmake -DUSE_SHARED_MBEDTLS_LIBRARY=On .
There are many different build modes available within the CMake buildsystem. Most of them are available for gcc and clang, though some are compiler-specific:
- Release. This generates the default code without any unnecessary information in the binary files.
- Debug. This generates debug information and disables optimization of the code.
- Coverage. This generates code coverage information in addition to debug information.
- ASan. This instruments the code with AddressSanitizer to check for memory errors. (This includes LeakSanitizer, with recent version of gcc and clang.) (With recent version of clang, this mode also instruments the code with UndefinedSanitizer to check for undefined behaviour.)
- ASanDbg. Same as ASan but slower, with debug information and better stack traces.
- MemSan. This instruments the code with MemorySanitizer to check for uninitialised memory reads. Experimental, needs recent clang on Linux/x86\_64.
- MemSanDbg. Same as MemSan but slower, with debug information, better stack traces and origin tracking.
- Check. This activates the compiler warnings that depend on optimization and treats all warnings as errors.
Switching build modes in CMake is simple. For debug mode, enter at the command line:
cmake -D CMAKE_BUILD_TYPE=Debug .
To list other available CMake options, use:
cmake -LH
Note that, with CMake, if you want to change the compiler or its options after you already ran CMake, you need to clear its cache first, e.g. (using GNU find):
find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} +
CC=gcc CFLAGS='-fstack-protector-strong -Wa,--noexecstack' cmake .
### Microsoft Visual Studio
The build files for Microsoft Visual Studio are generated for Visual Studio 2010.
The solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need a perl environment as well. However, the selftest program in `programs/test/` is still available.
Example programs
----------------
We've included example programs for a lot of different features and uses in `programs/`. Most programs only focus on a single feature or usage scenario, so keep that in mind when copying parts of the code.
Tests
-----
mbed TLS includes an elaborate test suite in `tests/` that initially requires 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.
For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, additional test scripts are available:
- `tests/ssl-opt.sh` runs integration tests for various TLS options (renegotiation, resumption, etc.) and tests interoperability of these options with other implementations.
- `tests/compat.sh` tests interoperability of every ciphersuite with other implementations.
- `tests/scripts/test-ref-configs.pl` test builds in various reduced configurations.
- `tests/scripts/key-exchanges.pl` test builds in configurations with a single key exchange enabled
- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `config.h`, etc).
Configurations
--------------
We provide some non-standard configurations focused on specific use cases in the `configs/` directory. You can read more about those in `configs/README.txt`
Contributing
------------
We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions:
- Simple bug fixes to existing code do not contain copyright themselves and we can integrate without issue. The same is true of trivial contributions.
- For larger contributions, such as a new feature, the code can possibly fall under copyright law. We then need your consent to share in the ownership of the copyright. We have a form for this, which we will send to you in case you submit a contribution or pull request that we deem this necessary for.
### Process
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.
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. We will include your name in the ChangeLog :)

202
3rd-party/mbedtls/apache-2.0.txt vendored Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,717 @@
/**
* \file bignum.h
*
* \brief Multi-precision integer library
*
* Copyright (C) 2006-2015, 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_BIGNUM_H
#define MBEDTLS_BIGNUM_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#include <stdint.h>
#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
#endif
#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */
#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */
#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */
#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */
#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */
#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */
#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */
#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */
#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 )
/*
* Maximum size MPIs are allowed to grow to in number of limbs.
*/
#define MBEDTLS_MPI_MAX_LIMBS 10000
#if !defined(MBEDTLS_MPI_WINDOW_SIZE)
/*
* Maximum window size used for modular exponentiation. Default: 6
* Minimum value: 1. Maximum value: 6.
*
* Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used
* for the sliding window calculation. (So 64 by default)
*
* Reduction in size, reduces speed.
*/
#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
#endif /* !MBEDTLS_MPI_WINDOW_SIZE */
#if !defined(MBEDTLS_MPI_MAX_SIZE)
/*
* Maximum size of MPIs allowed in bits and bytes for user-MPIs.
* ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
*
* Note: Calculations can results temporarily in larger MPIs. So the number
* of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher.
*/
#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */
#endif /* !MBEDTLS_MPI_MAX_SIZE */
#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */
/*
* When reading from files with mbedtls_mpi_read_file() and writing to files with
* mbedtls_mpi_write_file() the buffer should have space
* for a (short) label, the MPI (in the provided radix), the newline
* characters and the '\0'.
*
* By default we assume at least a 10 char label, a minimum radix of 10
* (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
* Autosized at compile time for at least a 10 char label, a minimum radix
* of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size.
*
* This used to be statically sized to 1250 for a maximum of 4096 bit
* numbers (1234 decimal chars).
*
* Calculate using the formula:
* MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) +
* LabelSize + 6
*/
#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS )
#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332
#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 )
/*
* Define the base integer type, architecture-wise.
*
* 32-bit integers can be forced on 64-bit arches (eg. for testing purposes)
* by defining MBEDTLS_HAVE_INT32 and undefining MBEDTLS_HAVE_ASM
*/
#if ( ! defined(MBEDTLS_HAVE_INT32) && \
defined(_MSC_VER) && defined(_M_AMD64) )
#define MBEDTLS_HAVE_INT64
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#else
#if ( ! defined(MBEDTLS_HAVE_INT32) && \
defined(__GNUC__) && ( \
defined(__amd64__) || defined(__x86_64__) || \
defined(__ppc64__) || defined(__powerpc64__) || \
defined(__ia64__) || defined(__alpha__) || \
(defined(__sparc__) && defined(__arch64__)) || \
defined(__s390x__) || defined(__mips64) ) )
#define MBEDTLS_HAVE_INT64
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
/* mbedtls_t_udbl defined as 128-bit unsigned int */
typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
#define MBEDTLS_HAVE_UDBL
#else
#define MBEDTLS_HAVE_INT32
typedef int32_t mbedtls_mpi_sint;
typedef uint32_t mbedtls_mpi_uint;
typedef uint64_t mbedtls_t_udbl;
#define MBEDTLS_HAVE_UDBL
#endif /* !MBEDTLS_HAVE_INT32 && __GNUC__ && 64-bit platform */
#endif /* !MBEDTLS_HAVE_INT32 && _MSC_VER && _M_AMD64 */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MPI structure
*/
typedef struct
{
int s; /*!< integer sign */
size_t n; /*!< total # of limbs */
mbedtls_mpi_uint *p; /*!< pointer to limbs */
}
mbedtls_mpi;
/**
* \brief Initialize one MPI (make internal references valid)
* This just makes it ready to be set or freed,
* but does not define a value for the MPI.
*
* \param X One MPI to initialize.
*/
void mbedtls_mpi_init( mbedtls_mpi *X );
/**
* \brief Unallocate one MPI
*
* \param X One MPI to unallocate.
*/
void mbedtls_mpi_free( mbedtls_mpi *X );
/**
* \brief Enlarge to the specified number of limbs
*
* \param X MPI to grow
* \param nblimbs The target number of limbs
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs );
/**
* \brief Resize down, keeping at least the specified number of limbs
*
* \param X MPI to shrink
* \param nblimbs The minimum number of limbs to keep
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs );
/**
* \brief Copy the contents of Y into X
*
* \param X Destination MPI
* \param Y Source MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
* \brief Swap the contents of X and Y
*
* \param X First MPI value
* \param Y Second MPI value
*/
void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y );
/**
* \brief Safe conditional assignement X = Y if assign is 1
*
* \param X MPI to conditionally assign to
* \param Y Value to be assigned
* \param assign 1: perform the assignment, 0: keep X's original value
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
*
* \note This function is equivalent to
* if( assign ) mbedtls_mpi_copy( X, Y );
* except that it avoids leaking any information about whether
* the assignment was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
*/
int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign );
/**
* \brief Safe conditional swap X <-> Y if swap is 1
*
* \param X First mbedtls_mpi value
* \param Y Second mbedtls_mpi value
* \param assign 1: perform the swap, 0: keep X and Y's original values
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
*
* \note This function is equivalent to
* if( assign ) mbedtls_mpi_swap( X, Y );
* except that it avoids leaking any information about whether
* the assignment was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
*/
int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign );
/**
* \brief Set value from integer
*
* \param X MPI to set
* \param z Value to use
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z );
/**
* \brief Get a specific bit from X
*
* \param X MPI to use
* \param pos Zero-based index of the bit in X
*
* \return Either a 0 or a 1
*/
int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos );
/**
* \brief Set a bit of X to a specific value of 0 or 1
*
* \note Will grow X if necessary to set a bit to 1 in a not yet
* existing limb. Will not grow if bit should be set to 0
*
* \param X MPI to use
* \param pos Zero-based index of the bit in X
* \param val The value to set the bit to (0 or 1)
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
*/
int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val );
/**
* \brief Return the number of zero-bits before the least significant
* '1' bit
*
* Note: Thus also the zero-based index of the least significant '1' bit
*
* \param X MPI to use
*/
size_t mbedtls_mpi_lsb( const mbedtls_mpi *X );
/**
* \brief Return the number of bits up to and including the most
* significant '1' bit'
*
* Note: Thus also the one-based index of the most significant '1' bit
*
* \param X MPI to use
*/
size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X );
/**
* \brief Return the total size in bytes
*
* \param X MPI to use
*/
size_t mbedtls_mpi_size( const mbedtls_mpi *X );
/**
* \brief Import from an ASCII string
*
* \param X Destination MPI
* \param radix Input numeric base
* \param s Null-terminated string buffer
*
* \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
*/
int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s );
/**
* \brief Export into an ASCII string
*
* \param X Source MPI
* \param radix Output numeric base
* \param buf Buffer to write the string to
* \param buflen Length of buf
* \param olen Length of the string written, including final NUL byte
*
* \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code.
* *olen is always updated to reflect the amount
* of data that has (or would have) been written.
*
* \note Call this function with buflen = 0 to obtain the
* minimum required buffer size in *olen.
*/
int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
char *buf, size_t buflen, size_t *olen );
#if defined(MBEDTLS_FS_IO)
/**
* \brief Read X from an opened file
*
* \param X Destination MPI
* \param radix Input numeric base
* \param fin Input file handle
*
* \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if
* the file read buffer is too small or a
* MBEDTLS_ERR_MPI_XXX error code
*/
int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin );
/**
* \brief Write X into an opened file, or stdout if fout is NULL
*
* \param p Prefix, can be NULL
* \param X Source MPI
* \param radix Output numeric base
* \param fout Output file handle (can be NULL)
*
* \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
*
* \note Set fout == NULL to print X on the console.
*/
int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout );
#endif /* MBEDTLS_FS_IO */
/**
* \brief Import X from unsigned binary data, big endian
*
* \param X Destination MPI
* \param buf Input buffer
* \param buflen Input buffer size
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen );
/**
* \brief Export X into unsigned binary data, big endian.
* Always fills the whole buffer, which will start with zeros
* if the number is smaller.
*
* \param X Source MPI
* \param buf Output buffer
* \param buflen Output buffer size
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
*/
int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen );
/**
* \brief Left-shift: X <<= count
*
* \param X MPI to shift
* \param count Amount to shift
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count );
/**
* \brief Right-shift: X >>= count
*
* \param X MPI to shift
* \param count Amount to shift
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count );
/**
* \brief Compare unsigned values
*
* \param X Left-hand MPI
* \param Y Right-hand MPI
*
* \return 1 if |X| is greater than |Y|,
* -1 if |X| is lesser than |Y| or
* 0 if |X| is equal to |Y|
*/
int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
* \brief Compare signed values
*
* \param X Left-hand MPI
* \param Y Right-hand MPI
*
* \return 1 if X is greater than Y,
* -1 if X is lesser than Y or
* 0 if X is equal to Y
*/
int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
* \brief Compare signed values
*
* \param X Left-hand MPI
* \param z The integer value to compare to
*
* \return 1 if X is greater than z,
* -1 if X is lesser than z or
* 0 if X is equal to z
*/
int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z );
/**
* \brief Unsigned addition: X = |A| + |B|
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Unsigned subtraction: X = |A| - |B|
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A
*/
int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Signed addition: X = A + B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Signed subtraction: X = A - B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Signed addition: X = A + b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to add
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b );
/**
* \brief Signed subtraction: X = A - b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to subtract
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b );
/**
* \brief Baseline multiplication: X = A * B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Baseline multiplication: X = A * b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The unsigned integer value to multiply with
*
* \note b is unsigned
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b );
/**
* \brief Division by mbedtls_mpi: A = Q * B + R
*
* \param Q Destination MPI for the quotient
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0
*
* \note Either Q or R can be NULL.
*/
int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Division by int: A = Q * b + R
*
* \param Q Destination MPI for the quotient
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param b Integer to divide by
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0
*
* \note Either Q or R can be NULL.
*/
int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b );
/**
* \brief Modulo: R = A mod B
*
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0,
* MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0
*/
int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Modulo: r = A mod b
*
* \param r Destination mbedtls_mpi_uint
* \param A Left-hand MPI
* \param b Integer to divide by
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0,
* MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0
*/
int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b );
/**
* \brief Sliding-window exponentiation: X = A^E mod N
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param E Exponent MPI
* \param N Modular MPI
* \param _RR Speed-up MPI used for recalculations
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or
* if E is negative
*
* \note _RR is used to avoid re-computing R*R mod N across
* multiple calls, which speeds up things a bit. It can
* be set to NULL if the extra performance is unneeded.
*/
int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR );
/**
* \brief Fill an MPI X with size bytes of random
*
* \param X Destination MPI
* \param size Size in bytes
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Greatest common divisor: G = gcd(A, B)
*
* \param G Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Modular inverse: X = A^-1 mod N
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param N Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
*/
int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N );
/**
* \brief Miller-Rabin primality test
*
* \param X MPI to check
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime
*/
int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Prime number generation
*
* \param X Destination MPI
* \param nbits Required size of X in bits
* ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS )
* \param dh_flag If 1, then (X-1)/2 will be prime too
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
*/
int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int mbedtls_mpi_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* bignum.h */

View File

@ -0,0 +1,876 @@
/**
* \file bn_mul.h
*
* \brief Multi-precision integer library
*
* Copyright (C) 2006-2015, 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)
*/
/*
* Multiply source vector [s] with b, add result
* to destination vector [d] and set carry c.
*
* Currently supports:
*
* . IA-32 (386+) . AMD64 / EM64T
* . IA-32 (SSE2) . Motorola 68000
* . PowerPC, 32-bit . MicroBlaze
* . PowerPC, 64-bit . TriCore
* . SPARC v8 . ARM v3+
* . Alpha . MIPS32
* . C, longlong . C, generic
*/
#ifndef MBEDTLS_BN_MUL_H
#define MBEDTLS_BN_MUL_H
#include "bignum.h"
#if defined(MBEDTLS_HAVE_ASM)
#ifndef asm
#define asm __asm
#endif
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
#if defined(__GNUC__) && \
( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
#if defined(__i386__)
#define MULADDC_INIT \
asm( \
"movl %%ebx, %0 \n\t" \
"movl %5, %%esi \n\t" \
"movl %6, %%edi \n\t" \
"movl %7, %%ecx \n\t" \
"movl %8, %%ebx \n\t"
#define MULADDC_CORE \
"lodsl \n\t" \
"mull %%ebx \n\t" \
"addl %%ecx, %%eax \n\t" \
"adcl $0, %%edx \n\t" \
"addl (%%edi), %%eax \n\t" \
"adcl $0, %%edx \n\t" \
"movl %%edx, %%ecx \n\t" \
"stosl \n\t"
#if defined(MBEDTLS_HAVE_SSE2)
#define MULADDC_HUIT \
"movd %%ecx, %%mm1 \n\t" \
"movd %%ebx, %%mm0 \n\t" \
"movd (%%edi), %%mm3 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd (%%esi), %%mm2 \n\t" \
"pmuludq %%mm0, %%mm2 \n\t" \
"movd 4(%%esi), %%mm4 \n\t" \
"pmuludq %%mm0, %%mm4 \n\t" \
"movd 8(%%esi), %%mm6 \n\t" \
"pmuludq %%mm0, %%mm6 \n\t" \
"movd 12(%%esi), %%mm7 \n\t" \
"pmuludq %%mm0, %%mm7 \n\t" \
"paddq %%mm2, %%mm1 \n\t" \
"movd 4(%%edi), %%mm3 \n\t" \
"paddq %%mm4, %%mm3 \n\t" \
"movd 8(%%edi), %%mm5 \n\t" \
"paddq %%mm6, %%mm5 \n\t" \
"movd 12(%%edi), %%mm4 \n\t" \
"paddq %%mm4, %%mm7 \n\t" \
"movd %%mm1, (%%edi) \n\t" \
"movd 16(%%esi), %%mm2 \n\t" \
"pmuludq %%mm0, %%mm2 \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd 20(%%esi), %%mm4 \n\t" \
"pmuludq %%mm0, %%mm4 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd 24(%%esi), %%mm6 \n\t" \
"pmuludq %%mm0, %%mm6 \n\t" \
"movd %%mm1, 4(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd 28(%%esi), %%mm3 \n\t" \
"pmuludq %%mm0, %%mm3 \n\t" \
"paddq %%mm5, %%mm1 \n\t" \
"movd 16(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm2 \n\t" \
"movd %%mm1, 8(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm7, %%mm1 \n\t" \
"movd 20(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm4 \n\t" \
"movd %%mm1, 12(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm2, %%mm1 \n\t" \
"movd 24(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm6 \n\t" \
"movd %%mm1, 16(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm4, %%mm1 \n\t" \
"movd 28(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm3 \n\t" \
"movd %%mm1, 20(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm6, %%mm1 \n\t" \
"movd %%mm1, 24(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd %%mm1, 28(%%edi) \n\t" \
"addl $32, %%edi \n\t" \
"addl $32, %%esi \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd %%mm1, %%ecx \n\t"
#define MULADDC_STOP \
"emms \n\t" \
"movl %4, %%ebx \n\t" \
"movl %%ecx, %1 \n\t" \
"movl %%edi, %2 \n\t" \
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ecx", "edx", "esi", "edi" \
);
#else
#define MULADDC_STOP \
"movl %4, %%ebx \n\t" \
"movl %%ecx, %1 \n\t" \
"movl %%edi, %2 \n\t" \
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ecx", "edx", "esi", "edi" \
);
#endif /* SSE2 */
#endif /* i386 */
#if defined(__amd64__) || defined (__x86_64__)
#define MULADDC_INIT \
asm( \
"movq %3, %%rsi \n\t" \
"movq %4, %%rdi \n\t" \
"movq %5, %%rcx \n\t" \
"movq %6, %%rbx \n\t" \
"xorq %%r8, %%r8 \n\t"
#define MULADDC_CORE \
"movq (%%rsi), %%rax \n\t" \
"mulq %%rbx \n\t" \
"addq $8, %%rsi \n\t" \
"addq %%rcx, %%rax \n\t" \
"movq %%r8, %%rcx \n\t" \
"adcq $0, %%rdx \n\t" \
"nop \n\t" \
"addq %%rax, (%%rdi) \n\t" \
"adcq %%rdx, %%rcx \n\t" \
"addq $8, %%rdi \n\t"
#define MULADDC_STOP \
"movq %%rcx, %0 \n\t" \
"movq %%rdi, %1 \n\t" \
"movq %%rsi, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" \
);
#endif /* AMD64 */
#if defined(__mc68020__) || defined(__mcpu32__)
#define MULADDC_INIT \
asm( \
"movl %3, %%a2 \n\t" \
"movl %4, %%a3 \n\t" \
"movl %5, %%d3 \n\t" \
"movl %6, %%d2 \n\t" \
"moveq #0, %%d0 \n\t"
#define MULADDC_CORE \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"moveq #0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"addxl %%d4, %%d3 \n\t"
#define MULADDC_STOP \
"movl %%d3, %0 \n\t" \
"movl %%a3, %1 \n\t" \
"movl %%a2, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "d0", "d1", "d2", "d3", "d4", "a2", "a3" \
);
#define MULADDC_HUIT \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"addxl %%d0, %%d3 \n\t"
#endif /* MC68000 */
#if defined(__powerpc64__) || defined(__ppc64__)
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
asm( \
"ld r3, %3 \n\t" \
"ld r4, %4 \n\t" \
"ld r5, %5 \n\t" \
"ld r6, %6 \n\t" \
"addi r3, r3, -8 \n\t" \
"addi r4, r4, -8 \n\t" \
"addic r5, r5, 0 \n\t"
#define MULADDC_CORE \
"ldu r7, 8(r3) \n\t" \
"mulld r8, r7, r6 \n\t" \
"mulhdu r9, r7, r6 \n\t" \
"adde r8, r8, r5 \n\t" \
"ld r7, 8(r4) \n\t" \
"addze r5, r9 \n\t" \
"addc r8, r8, r7 \n\t" \
"stdu r8, 8(r4) \n\t"
#define MULADDC_STOP \
"addze r5, r5 \n\t" \
"addi r4, r4, 8 \n\t" \
"addi r3, r3, 8 \n\t" \
"std r5, %0 \n\t" \
"std r4, %1 \n\t" \
"std r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#else /* __MACH__ && __APPLE__ */
#define MULADDC_INIT \
asm( \
"ld %%r3, %3 \n\t" \
"ld %%r4, %4 \n\t" \
"ld %%r5, %5 \n\t" \
"ld %%r6, %6 \n\t" \
"addi %%r3, %%r3, -8 \n\t" \
"addi %%r4, %%r4, -8 \n\t" \
"addic %%r5, %%r5, 0 \n\t"
#define MULADDC_CORE \
"ldu %%r7, 8(%%r3) \n\t" \
"mulld %%r8, %%r7, %%r6 \n\t" \
"mulhdu %%r9, %%r7, %%r6 \n\t" \
"adde %%r8, %%r8, %%r5 \n\t" \
"ld %%r7, 8(%%r4) \n\t" \
"addze %%r5, %%r9 \n\t" \
"addc %%r8, %%r8, %%r7 \n\t" \
"stdu %%r8, 8(%%r4) \n\t"
#define MULADDC_STOP \
"addze %%r5, %%r5 \n\t" \
"addi %%r4, %%r4, 8 \n\t" \
"addi %%r3, %%r3, 8 \n\t" \
"std %%r5, %0 \n\t" \
"std %%r4, %1 \n\t" \
"std %%r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#endif /* __MACH__ && __APPLE__ */
#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
asm( \
"lwz r3, %3 \n\t" \
"lwz r4, %4 \n\t" \
"lwz r5, %5 \n\t" \
"lwz r6, %6 \n\t" \
"addi r3, r3, -4 \n\t" \
"addi r4, r4, -4 \n\t" \
"addic r5, r5, 0 \n\t"
#define MULADDC_CORE \
"lwzu r7, 4(r3) \n\t" \
"mullw r8, r7, r6 \n\t" \
"mulhwu r9, r7, r6 \n\t" \
"adde r8, r8, r5 \n\t" \
"lwz r7, 4(r4) \n\t" \
"addze r5, r9 \n\t" \
"addc r8, r8, r7 \n\t" \
"stwu r8, 4(r4) \n\t"
#define MULADDC_STOP \
"addze r5, r5 \n\t" \
"addi r4, r4, 4 \n\t" \
"addi r3, r3, 4 \n\t" \
"stw r5, %0 \n\t" \
"stw r4, %1 \n\t" \
"stw r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#else /* __MACH__ && __APPLE__ */
#define MULADDC_INIT \
asm( \
"lwz %%r3, %3 \n\t" \
"lwz %%r4, %4 \n\t" \
"lwz %%r5, %5 \n\t" \
"lwz %%r6, %6 \n\t" \
"addi %%r3, %%r3, -4 \n\t" \
"addi %%r4, %%r4, -4 \n\t" \
"addic %%r5, %%r5, 0 \n\t"
#define MULADDC_CORE \
"lwzu %%r7, 4(%%r3) \n\t" \
"mullw %%r8, %%r7, %%r6 \n\t" \
"mulhwu %%r9, %%r7, %%r6 \n\t" \
"adde %%r8, %%r8, %%r5 \n\t" \
"lwz %%r7, 4(%%r4) \n\t" \
"addze %%r5, %%r9 \n\t" \
"addc %%r8, %%r8, %%r7 \n\t" \
"stwu %%r8, 4(%%r4) \n\t"
#define MULADDC_STOP \
"addze %%r5, %%r5 \n\t" \
"addi %%r4, %%r4, 4 \n\t" \
"addi %%r3, %%r3, 4 \n\t" \
"stw %%r5, %0 \n\t" \
"stw %%r4, %1 \n\t" \
"stw %%r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#endif /* __MACH__ && __APPLE__ */
#endif /* PPC32 */
/*
* The Sparc(64) assembly is reported to be broken.
* Disable it for now, until we're able to fix it.
*/
#if 0 && defined(__sparc__)
#if defined(__sparc64__)
#define MULADDC_INIT \
asm( \
"ldx %3, %%o0 \n\t" \
"ldx %4, %%o1 \n\t" \
"ld %5, %%o2 \n\t" \
"ld %6, %%o3 \n\t"
#define MULADDC_CORE \
"ld [%%o0], %%o4 \n\t" \
"inc 4, %%o0 \n\t" \
"ld [%%o1], %%o5 \n\t" \
"umul %%o3, %%o4, %%o4 \n\t" \
"addcc %%o4, %%o2, %%o4 \n\t" \
"rd %%y, %%g1 \n\t" \
"addx %%g1, 0, %%g1 \n\t" \
"addcc %%o4, %%o5, %%o4 \n\t" \
"st %%o4, [%%o1] \n\t" \
"addx %%g1, 0, %%o2 \n\t" \
"inc 4, %%o1 \n\t"
#define MULADDC_STOP \
"st %%o2, %0 \n\t" \
"stx %%o1, %1 \n\t" \
"stx %%o0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "g1", "o0", "o1", "o2", "o3", "o4", \
"o5" \
);
#else /* __sparc64__ */
#define MULADDC_INIT \
asm( \
"ld %3, %%o0 \n\t" \
"ld %4, %%o1 \n\t" \
"ld %5, %%o2 \n\t" \
"ld %6, %%o3 \n\t"
#define MULADDC_CORE \
"ld [%%o0], %%o4 \n\t" \
"inc 4, %%o0 \n\t" \
"ld [%%o1], %%o5 \n\t" \
"umul %%o3, %%o4, %%o4 \n\t" \
"addcc %%o4, %%o2, %%o4 \n\t" \
"rd %%y, %%g1 \n\t" \
"addx %%g1, 0, %%g1 \n\t" \
"addcc %%o4, %%o5, %%o4 \n\t" \
"st %%o4, [%%o1] \n\t" \
"addx %%g1, 0, %%o2 \n\t" \
"inc 4, %%o1 \n\t"
#define MULADDC_STOP \
"st %%o2, %0 \n\t" \
"st %%o1, %1 \n\t" \
"st %%o0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "g1", "o0", "o1", "o2", "o3", "o4", \
"o5" \
);
#endif /* __sparc64__ */
#endif /* __sparc__ */
#if defined(__microblaze__) || defined(microblaze)
#define MULADDC_INIT \
asm( \
"lwi r3, %3 \n\t" \
"lwi r4, %4 \n\t" \
"lwi r5, %5 \n\t" \
"lwi r6, %6 \n\t" \
"andi r7, r6, 0xffff \n\t" \
"bsrli r6, r6, 16 \n\t"
#define MULADDC_CORE \
"lhui r8, r3, 0 \n\t" \
"addi r3, r3, 2 \n\t" \
"lhui r9, r3, 0 \n\t" \
"addi r3, r3, 2 \n\t" \
"mul r10, r9, r6 \n\t" \
"mul r11, r8, r7 \n\t" \
"mul r12, r9, r7 \n\t" \
"mul r13, r8, r6 \n\t" \
"bsrli r8, r10, 16 \n\t" \
"bsrli r9, r11, 16 \n\t" \
"add r13, r13, r8 \n\t" \
"add r13, r13, r9 \n\t" \
"bslli r10, r10, 16 \n\t" \
"bslli r11, r11, 16 \n\t" \
"add r12, r12, r10 \n\t" \
"addc r13, r13, r0 \n\t" \
"add r12, r12, r11 \n\t" \
"addc r13, r13, r0 \n\t" \
"lwi r10, r4, 0 \n\t" \
"add r12, r12, r10 \n\t" \
"addc r13, r13, r0 \n\t" \
"add r12, r12, r5 \n\t" \
"addc r5, r13, r0 \n\t" \
"swi r12, r4, 0 \n\t" \
"addi r4, r4, 4 \n\t"
#define MULADDC_STOP \
"swi r5, %0 \n\t" \
"swi r4, %1 \n\t" \
"swi r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4" "r5", "r6", "r7", "r8", \
"r9", "r10", "r11", "r12", "r13" \
);
#endif /* MicroBlaze */
#if defined(__tricore__)
#define MULADDC_INIT \
asm( \
"ld.a %%a2, %3 \n\t" \
"ld.a %%a3, %4 \n\t" \
"ld.w %%d4, %5 \n\t" \
"ld.w %%d1, %6 \n\t" \
"xor %%d5, %%d5 \n\t"
#define MULADDC_CORE \
"ld.w %%d0, [%%a2+] \n\t" \
"madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \
"ld.w %%d0, [%%a3] \n\t" \
"addx %%d2, %%d2, %%d0 \n\t" \
"addc %%d3, %%d3, 0 \n\t" \
"mov %%d4, %%d3 \n\t" \
"st.w [%%a3+], %%d2 \n\t"
#define MULADDC_STOP \
"st.w %0, %%d4 \n\t" \
"st.a %1, %%a3 \n\t" \
"st.a %2, %%a2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "d0", "d1", "e2", "d4", "a2", "a3" \
);
#endif /* TriCore */
#if defined(__arm__)
#if defined(__thumb__) && !defined(__thumb2__)
#define MULADDC_INIT \
asm( \
"ldr r0, %3 \n\t" \
"ldr r1, %4 \n\t" \
"ldr r2, %5 \n\t" \
"ldr r3, %6 \n\t" \
"lsr r7, r3, #16 \n\t" \
"mov r9, r7 \n\t" \
"lsl r7, r3, #16 \n\t" \
"lsr r7, r7, #16 \n\t" \
"mov r8, r7 \n\t"
#define MULADDC_CORE \
"ldmia r0!, {r6} \n\t" \
"lsr r7, r6, #16 \n\t" \
"lsl r6, r6, #16 \n\t" \
"lsr r6, r6, #16 \n\t" \
"mov r4, r8 \n\t" \
"mul r4, r6 \n\t" \
"mov r3, r9 \n\t" \
"mul r6, r3 \n\t" \
"mov r5, r9 \n\t" \
"mul r5, r7 \n\t" \
"mov r3, r8 \n\t" \
"mul r7, r3 \n\t" \
"lsr r3, r6, #16 \n\t" \
"add r5, r5, r3 \n\t" \
"lsr r3, r7, #16 \n\t" \
"add r5, r5, r3 \n\t" \
"add r4, r4, r2 \n\t" \
"mov r2, #0 \n\t" \
"adc r5, r2 \n\t" \
"lsl r3, r6, #16 \n\t" \
"add r4, r4, r3 \n\t" \
"adc r5, r2 \n\t" \
"lsl r3, r7, #16 \n\t" \
"add r4, r4, r3 \n\t" \
"adc r5, r2 \n\t" \
"ldr r3, [r1] \n\t" \
"add r4, r4, r3 \n\t" \
"adc r2, r5 \n\t" \
"stmia r1!, {r4} \n\t"
#define MULADDC_STOP \
"str r2, %0 \n\t" \
"str r1, %1 \n\t" \
"str r0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "r8", "r9", "cc" \
);
#else
#define MULADDC_INIT \
asm( \
"ldr r0, %3 \n\t" \
"ldr r1, %4 \n\t" \
"ldr r2, %5 \n\t" \
"ldr r3, %6 \n\t"
#define MULADDC_CORE \
"ldr r4, [r0], #4 \n\t" \
"mov r5, #0 \n\t" \
"ldr r6, [r1] \n\t" \
"umlal r2, r5, r3, r4 \n\t" \
"adds r7, r6, r2 \n\t" \
"adc r2, r5, #0 \n\t" \
"str r7, [r1], #4 \n\t"
#define MULADDC_STOP \
"str r2, %0 \n\t" \
"str r1, %1 \n\t" \
"str r0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "cc" \
);
#endif /* Thumb */
#endif /* ARMv3 */
#if defined(__alpha__)
#define MULADDC_INIT \
asm( \
"ldq $1, %3 \n\t" \
"ldq $2, %4 \n\t" \
"ldq $3, %5 \n\t" \
"ldq $4, %6 \n\t"
#define MULADDC_CORE \
"ldq $6, 0($1) \n\t" \
"addq $1, 8, $1 \n\t" \
"mulq $6, $4, $7 \n\t" \
"umulh $6, $4, $6 \n\t" \
"addq $7, $3, $7 \n\t" \
"cmpult $7, $3, $3 \n\t" \
"ldq $5, 0($2) \n\t" \
"addq $7, $5, $7 \n\t" \
"cmpult $7, $5, $5 \n\t" \
"stq $7, 0($2) \n\t" \
"addq $2, 8, $2 \n\t" \
"addq $6, $3, $3 \n\t" \
"addq $5, $3, $3 \n\t"
#define MULADDC_STOP \
"stq $3, %0 \n\t" \
"stq $2, %1 \n\t" \
"stq $1, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "$1", "$2", "$3", "$4", "$5", "$6", "$7" \
);
#endif /* Alpha */
#if defined(__mips__) && !defined(__mips64)
#define MULADDC_INIT \
asm( \
"lw $10, %3 \n\t" \
"lw $11, %4 \n\t" \
"lw $12, %5 \n\t" \
"lw $13, %6 \n\t"
#define MULADDC_CORE \
"lw $14, 0($10) \n\t" \
"multu $13, $14 \n\t" \
"addi $10, $10, 4 \n\t" \
"mflo $14 \n\t" \
"mfhi $9 \n\t" \
"addu $14, $12, $14 \n\t" \
"lw $15, 0($11) \n\t" \
"sltu $12, $14, $12 \n\t" \
"addu $15, $14, $15 \n\t" \
"sltu $14, $15, $14 \n\t" \
"addu $12, $12, $9 \n\t" \
"sw $15, 0($11) \n\t" \
"addu $12, $12, $14 \n\t" \
"addi $11, $11, 4 \n\t"
#define MULADDC_STOP \
"sw $12, %0 \n\t" \
"sw $11, %1 \n\t" \
"sw $10, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "$9", "$10", "$11", "$12", "$13", "$14", "$15" \
);
#endif /* MIPS */
#endif /* GNUC */
#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
#define MULADDC_INIT \
__asm mov esi, s \
__asm mov edi, d \
__asm mov ecx, c \
__asm mov ebx, b
#define MULADDC_CORE \
__asm lodsd \
__asm mul ebx \
__asm add eax, ecx \
__asm adc edx, 0 \
__asm add eax, [edi] \
__asm adc edx, 0 \
__asm mov ecx, edx \
__asm stosd
#if defined(MBEDTLS_HAVE_SSE2)
#define EMIT __asm _emit
#define MULADDC_HUIT \
EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
EMIT 0x0F EMIT 0x6E EMIT 0x1F \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x16 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
EMIT 0x0F EMIT 0x7E EMIT 0x0F \
EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x7E EMIT 0xC9
#define MULADDC_STOP \
EMIT 0x0F EMIT 0x77 \
__asm mov c, ecx \
__asm mov d, edi \
__asm mov s, esi \
#else
#define MULADDC_STOP \
__asm mov c, ecx \
__asm mov d, edi \
__asm mov s, esi \
#endif /* SSE2 */
#endif /* MSVC */
#endif /* MBEDTLS_HAVE_ASM */
#if !defined(MULADDC_CORE)
#if defined(MBEDTLS_HAVE_UDBL)
#define MULADDC_INIT \
{ \
mbedtls_t_udbl r; \
mbedtls_mpi_uint r0, r1;
#define MULADDC_CORE \
r = *(s++) * (mbedtls_t_udbl) b; \
r0 = (mbedtls_mpi_uint) r; \
r1 = (mbedtls_mpi_uint)( r >> biL ); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#else
#define MULADDC_INIT \
{ \
mbedtls_mpi_uint s0, s1, b0, b1; \
mbedtls_mpi_uint r0, r1, rx, ry; \
b0 = ( b << biH ) >> biH; \
b1 = ( b >> biH );
#define MULADDC_CORE \
s0 = ( *s << biH ) >> biH; \
s1 = ( *s >> biH ); s++; \
rx = s0 * b1; r0 = s0 * b0; \
ry = s1 * b0; r1 = s1 * b1; \
r1 += ( rx >> biH ); \
r1 += ( ry >> biH ); \
rx <<= biH; ry <<= biH; \
r0 += rx; r1 += (r0 < rx); \
r0 += ry; r1 += (r0 < ry); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#endif /* C (generic) */
#endif /* C (longlong) */
#endif /* bn_mul.h */

View File

@ -0,0 +1,540 @@
/**
* \file check_config.h
*
* \brief Consistency checks for configuration options
*
* Copyright (C) 2006-2015, 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)
*/
/*
* It is recommended to include this file from your config.h
* in order to catch dependency issues early.
*/
#ifndef MBEDTLS_CHECK_CONFIG_H
#define MBEDTLS_CHECK_CONFIG_H
/*
* We assume CHAR_BIT is 8 in many places. In practice, this is true on our
* target platforms, so not an issue, but let's just be extra sure.
*/
#include <limits.h>
#if CHAR_BIT != 8
#error "mbed TLS requires a platform with 8-bit chars"
#endif
#if defined(_WIN32)
#if !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_C is required on Windows"
#endif
/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as
* it would confuse config.pl. */
#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \
!defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
#endif
#endif /* _WIN32 */
#if defined(TARGET_LIKE_MBED) && \
( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) )
#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS"
#endif
#if defined(MBEDTLS_DEPRECATED_WARNING) && \
!defined(__GNUC__) && !defined(__clang__)
#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang"
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME)
#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense"
#endif
#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_AESNI_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C)
#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C)
#error "MBEDTLS_DHM_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C)
#error "MBEDTLS_ECDH_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECDSA_C) && \
( !defined(MBEDTLS_ECP_C) || \
!defined(MBEDTLS_ASN1_PARSE_C) || \
!defined(MBEDTLS_ASN1_WRITE_C) )
#error "MBEDTLS_ECDSA_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECJPAKE_C) && \
( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) )
#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)
#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \
!defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) )
#error "MBEDTLS_ECP_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \
!defined(MBEDTLS_SHA256_C))
#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \
defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64)
#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high"
#endif
#if defined(MBEDTLS_ENTROPY_C) && \
( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \
&& defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32)
#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high"
#endif
#if defined(MBEDTLS_ENTROPY_C) && \
defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C)
#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_GCM_C) && ( \
!defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) )
#error "MBEDTLS_GCM_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C)
#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C)
#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C)
#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \
!defined(MBEDTLS_ECDH_C)
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \
( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
!defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
!defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \
!defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) )
#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C)
#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C)
#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PK_C) && \
( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) )
#error "MBEDTLS_PK_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C)
#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C)
#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C)
#error "MBEDTLS_PKCS11_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\
defined(MBEDTLS_PLATFORM_EXIT_ALT) )
#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\
defined(MBEDTLS_PLATFORM_FPRINTF_ALT) )
#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\
defined(MBEDTLS_PLATFORM_STD_FREE)
#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO)
#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is"
#endif
#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\
defined(MBEDTLS_PLATFORM_STD_CALLOC)
#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO)
#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is"
#endif
#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\
defined(MBEDTLS_PLATFORM_PRINTF_ALT) )
#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\
defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) )
#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\
!defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY)
#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY)
#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY)
#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\
!defined(MBEDTLS_PLATFORM_EXIT_ALT)
#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\
!defined(MBEDTLS_PLATFORM_FPRINTF_ALT)
#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\
!defined(MBEDTLS_PLATFORM_PRINTF_ALT)
#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\
!defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) )
#error "MBEDTLS_RSA_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) )
#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \
!defined(MBEDTLS_SHA1_C) )
#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \
!defined(MBEDTLS_SHA1_C) )
#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \
!defined(MBEDTLS_SHA1_C) )
#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \
!defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) )
#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C)
#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \
!defined(MBEDTLS_MD_C) )
#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C)
#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \
!defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2))
#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \
defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1))
#error "Illegal protocol selection"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \
defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1))
#error "Illegal protocol selection"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \
defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \
!defined(MBEDTLS_SSL_PROTO_TLS1_1)))
#error "Illegal protocol selection"
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS)
#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \
!defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \
!defined(MBEDTLS_SSL_PROTO_TLS1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites"
#endif
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
!defined(MBEDTLS_SSL_PROTO_TLS1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites"
#endif
#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C)
#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \
!defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1)
#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \
!defined(MBEDTLS_X509_CRT_PARSE_C)
#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_THREADING_PTHREAD)
#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)
#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites"
#endif
#define MBEDTLS_THREADING_IMPL
#endif
#if defined(MBEDTLS_THREADING_ALT)
#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)
#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites"
#endif
#define MBEDTLS_THREADING_IMPL
#endif
#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL)
#error "MBEDTLS_THREADING_C defined, single threading implementation required"
#endif
#undef MBEDTLS_THREADING_IMPL
#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C)
#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \
!defined(MBEDTLS_PK_PARSE_C) )
#error "MBEDTLS_X509_USE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \
!defined(MBEDTLS_PK_WRITE_C) )
#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )
#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )
#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )
#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) )
#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) )
#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites"
#endif
/*
* Avoid warning from -pedantic. This is a convenient place for this
* workaround since this is included by every single file before the
* #if defined(MBEDTLS_xxx_C) that results in emtpy translation units.
*/
typedef int mbedtls_iso_c_forbids_empty_translation_units;
#endif /* MBEDTLS_CHECK_CONFIG_H */

2529
3rd-party/mbedtls/include/mbedtls/config.h vendored Normal file

File diff suppressed because it is too large Load Diff

669
3rd-party/mbedtls/include/mbedtls/ecp.h vendored Normal file
View File

@ -0,0 +1,669 @@
/**
* \file ecp.h
*
* \brief Elliptic curves over GF(p)
*
* Copyright (C) 2006-2015, 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_ECP_H
#define MBEDTLS_ECP_H
#include "bignum.h"
/*
* ECP error codes
*/
#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */
#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */
#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */
#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */
#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */
#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */
#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */
#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */
#ifdef __cplusplus
extern "C" {
#endif
/**
* Domain parameters (curve, subgroup and generator) identifiers.
*
* Only curves over prime fields are supported.
*
* \warning This library does not support validation of arbitrary domain
* parameters. Therefore, only well-known domain parameters from trusted
* sources should be used. See mbedtls_ecp_group_load().
*/
typedef enum
{
MBEDTLS_ECP_DP_NONE = 0,
MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */
MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */
MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */
MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */
MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */
MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */
MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */
MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */
MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */
MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */
MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */
MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */
} mbedtls_ecp_group_id;
/**
* Number of supported curves (plus one for NONE).
*
* (Montgomery curves excluded for now.)
*/
#define MBEDTLS_ECP_DP_MAX 12
/**
* Curve information for use by other modules
*/
typedef struct
{
mbedtls_ecp_group_id grp_id; /*!< Internal identifier */
uint16_t tls_id; /*!< TLS NamedCurve identifier */
uint16_t bit_size; /*!< Curve size in bits */
const char *name; /*!< Human-friendly name */
} mbedtls_ecp_curve_info;
/**
* \brief ECP point structure (jacobian coordinates)
*
* \note All functions expect and return points satisfying
* the following condition: Z == 0 or Z == 1. (Other
* values of Z are used by internal functions only.)
* The point is zero, or "at infinity", if Z == 0.
* Otherwise, X and Y are its standard (affine) coordinates.
*/
typedef struct
{
mbedtls_mpi X; /*!< the point's X coordinate */
mbedtls_mpi Y; /*!< the point's Y coordinate */
mbedtls_mpi Z; /*!< the point's Z coordinate */
}
mbedtls_ecp_point;
/**
* \brief ECP group structure
*
* We consider two types of curves equations:
* 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492)
* 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft)
* In both cases, a generator G for a prime-order subgroup is fixed. In the
* short weierstrass, this subgroup is actually the whole curve, and its
* cardinal is denoted by N.
*
* In the case of Short Weierstrass curves, our code requires that N is an odd
* prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.)
*
* In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is
* the quantity actually used in the formulas. Also, nbits is not the size of N
* but the required size for private keys.
*
* If modp is NULL, reduction modulo P is done using a generic algorithm.
* Otherwise, it must point to a function that takes an mbedtls_mpi in the range
* 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more
* than pbits, so that the integer may be efficiently brought in the 0..P-1
* range by a few additions or substractions. It must return 0 on success and
* non-zero on failure.
*/
typedef struct
{
mbedtls_ecp_group_id id; /*!< internal group identifier */
mbedtls_mpi P; /*!< prime modulus of the base field */
mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */
mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */
mbedtls_ecp_point G; /*!< generator of the (sub)group used */
mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */
size_t pbits; /*!< number of bits in P */
size_t nbits; /*!< number of bits in 1. P, or 2. private keys */
unsigned int h; /*!< internal: 1 if the constants are static */
int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */
int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */
int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */
void *t_data; /*!< unused */
mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */
size_t T_size; /*!< number for pre-computed points */
}
mbedtls_ecp_group;
/**
* \brief ECP key pair structure
*
* A generic key pair that could be used for ECDSA, fixed ECDH, etc.
*
* \note Members purposefully in the same order as struc mbedtls_ecdsa_context.
*/
typedef struct
{
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
mbedtls_mpi d; /*!< our secret value */
mbedtls_ecp_point Q; /*!< our public value */
}
mbedtls_ecp_keypair;
/**
* \name SECTION: Module settings
*
* The configuration options you can set for this module are in this section.
* Either change them in config.h or define them on the compiler command line.
* \{
*/
#if !defined(MBEDTLS_ECP_MAX_BITS)
/**
* Maximum size of the groups (that is, of N and P)
*/
#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
#endif
#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 )
#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 )
#if !defined(MBEDTLS_ECP_WINDOW_SIZE)
/*
* Maximum "window" size used for point multiplication.
* Default: 6.
* Minimum value: 2. Maximum value: 7.
*
* Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
* points used for point multiplication. This value is directly tied to EC
* peak memory usage, so decreasing it by one should roughly cut memory usage
* by two (if large curves are in use).
*
* Reduction in size may reduce speed, but larger curves are impacted first.
* Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1):
* w-size: 6 5 4 3 2
* 521 145 141 135 120 97
* 384 214 209 198 177 146
* 256 320 320 303 262 226
* 224 475 475 453 398 342
* 192 640 640 633 587 476
*/
#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */
#endif /* MBEDTLS_ECP_WINDOW_SIZE */
#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM)
/*
* Trade memory for speed on fixed-point multiplication.
*
* This speeds up repeated multiplication of the generator (that is, the
* multiplication in ECDSA signatures, and half of the multiplications in
* ECDSA verification and ECDHE) by a factor roughly 3 to 4.
*
* The cost is increasing EC peak memory usage by a factor roughly 2.
*
* Change this value to 0 to reduce peak memory usage.
*/
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */
#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */
/* \} name SECTION: Module settings */
/*
* Point formats, from RFC 4492's enum ECPointFormat
*/
#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */
#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */
/*
* Some other constants from RFC 4492
*/
#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */
/**
* \brief Get the list of supported curves in order of preferrence
* (full information)
*
* \return A statically allocated array, the last entry is 0.
*/
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void );
/**
* \brief Get the list of supported curves in order of preferrence
* (grp_id only)
*
* \return A statically allocated array,
* terminated with MBEDTLS_ECP_DP_NONE.
*/
const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void );
/**
* \brief Get curve information from an internal group identifier
*
* \param grp_id A MBEDTLS_ECP_DP_XXX value
*
* \return The associated curve information or NULL
*/
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id );
/**
* \brief Get curve information from a TLS NamedCurve value
*
* \param tls_id A MBEDTLS_ECP_DP_XXX value
*
* \return The associated curve information or NULL
*/
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id );
/**
* \brief Get curve information from a human-readable name
*
* \param name The name
*
* \return The associated curve information or NULL
*/
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name );
/**
* \brief Initialize a point (as zero)
*/
void mbedtls_ecp_point_init( mbedtls_ecp_point *pt );
/**
* \brief Initialize a group (to something meaningless)
*/
void mbedtls_ecp_group_init( mbedtls_ecp_group *grp );
/**
* \brief Initialize a key pair (as an invalid one)
*/
void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key );
/**
* \brief Free the components of a point
*/
void mbedtls_ecp_point_free( mbedtls_ecp_point *pt );
/**
* \brief Free the components of an ECP group
*/
void mbedtls_ecp_group_free( mbedtls_ecp_group *grp );
/**
* \brief Free the components of a key pair
*/
void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key );
/**
* \brief Copy the contents of point Q into P
*
* \param P Destination point
* \param Q Source point
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q );
/**
* \brief Copy the contents of a group object
*
* \param dst Destination group
* \param src Source group
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src );
/**
* \brief Set a point to zero
*
* \param pt Destination point
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt );
/**
* \brief Tell if a point is zero
*
* \param pt Point to test
*
* \return 1 if point is zero, 0 otherwise
*/
int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt );
/**
* \brief Compare two points
*
* \note This assumes the points are normalized. Otherwise,
* they may compare as "not equal" even if they are.
*
* \param P First point to compare
* \param Q Second point to compare
*
* \return 0 if the points are equal,
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise
*/
int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q );
/**
* \brief Import a non-zero point from two ASCII strings
*
* \param P Destination point
* \param radix Input numeric base
* \param x First affine coordinate as a null-terminated string
* \param y Second affine coordinate as a null-terminated string
*
* \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
*/
int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
const char *x, const char *y );
/**
* \brief Export a point into unsigned binary data
*
* \param grp Group to which the point should belong
* \param P Point to export
* \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro
* \param olen Length of the actual output
* \param buf Output buffer
* \param buflen Length of the output buffer
*
* \return 0 if successful,
* or MBEDTLS_ERR_ECP_BAD_INPUT_DATA
* or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
*/
int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
int format, size_t *olen,
unsigned char *buf, size_t buflen );
/**
* \brief Import a point from unsigned binary data
*
* \param grp Group to which the point should belong
* \param P Point to import
* \param buf Input buffer
* \param ilen Actual length of input
*
* \return 0 if successful,
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
* is not implemented.
*
* \note This function does NOT check that the point actually
* belongs to the given group, see mbedtls_ecp_check_pubkey() for
* that.
*/
int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
const unsigned char *buf, size_t ilen );
/**
* \brief Import a point from a TLS ECPoint record
*
* \param grp ECP group used
* \param pt Destination point
* \param buf $(Start of input buffer)
* \param len Buffer length
*
* \note buf is updated to point right after the ECPoint on exit
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_XXX if initialization failed
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid
*/
int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
const unsigned char **buf, size_t len );
/**
* \brief Export a point as a TLS ECPoint record
*
* \param grp ECP group used
* \param pt Point to export
* \param format Export format
* \param olen length of data written
* \param buf Buffer to write to
* \param blen Buffer length
*
* \return 0 if successful,
* or MBEDTLS_ERR_ECP_BAD_INPUT_DATA
* or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
*/
int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
int format, size_t *olen,
unsigned char *buf, size_t blen );
/**
* \brief Set a group using well-known domain parameters
*
* \param grp Destination group
* \param index Index in the list of well-known domain parameters
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_XXX if initialization failed
* MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups
*
* \note Index should be a value of RFC 4492's enum NamedCurve,
* usually in the form of a MBEDTLS_ECP_DP_XXX macro.
*/
int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id index );
/**
* \brief Set a group from a TLS ECParameters record
*
* \param grp Destination group
* \param buf &(Start of input buffer)
* \param len Buffer length
*
* \note buf is updated to point right after ECParameters on exit
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_XXX if initialization failed
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid
*/
int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len );
/**
* \brief Write the TLS ECParameters record for a group
*
* \param grp ECP group used
* \param olen Number of bytes actually written
* \param buf Buffer to write to
* \param blen Buffer length
*
* \return 0 if successful,
* or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
*/
int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
unsigned char *buf, size_t blen );
/**
* \brief Multiplication by an integer: R = m * P
* (Not thread-safe to use same group in multiple threads)
*
* \note In order to prevent timing attacks, this function
* executes the exact same sequence of (base field)
* operations for any valid m. It avoids any if-branch or
* array index depending on the value of m.
*
* \note If f_rng is not NULL, it is used to randomize intermediate
* results in order to prevent potential timing attacks
* targeting these results. It is recommended to always
* provide a non-NULL f_rng (the overhead is negligible).
*
* \param grp ECP group
* \param R Destination point
* \param m Integer by which to multiply
* \param P Point to multiply
* \param f_rng RNG function (see notes)
* \param p_rng RNG parameter
*
* \return 0 if successful,
* MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey
* or P is not a valid pubkey,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
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 Multiplication and addition of two points by integers:
* R = m * P + n * Q
* (Not thread-safe to use same group in multiple threads)
*
* \note In contrast to mbedtls_ecp_mul(), this function does not guarantee
* a constant execution flow and timing.
*
* \param grp ECP group
* \param R Destination point
* \param m Integer by which to multiply P
* \param P Point to multiply by m
* \param n Integer by which to multiply Q
* \param Q Point to be multiplied by n
*
* \return 0 if successful,
* MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey
* or P or Q is not a valid pubkey,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
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 Check that a point is a valid public key on this curve
*
* \param grp Curve/group the point should belong to
* \param pt Point to check
*
* \return 0 if point is a valid public key,
* MBEDTLS_ERR_ECP_INVALID_KEY otherwise.
*
* \note This function only checks the point is non-zero, has valid
* coordinates and lies on the curve, but not that it is
* indeed a multiple of G. This is additional check is more
* expensive, isn't required by standards, and shouldn't be
* necessary if the group used has a small cofactor. In
* particular, it is useless for the NIST groups which all
* have a cofactor of 1.
*
* \note Uses bare components rather than an mbedtls_ecp_keypair structure
* in order to ease use with other structures such as
* mbedtls_ecdh_context of mbedtls_ecdsa_context.
*/
int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt );
/**
* \brief Check that an mbedtls_mpi is a valid private key for this curve
*
* \param grp Group used
* \param d Integer to check
*
* \return 0 if point is a valid private key,
* MBEDTLS_ERR_ECP_INVALID_KEY otherwise.
*
* \note Uses bare components rather than an mbedtls_ecp_keypair structure
* in order to ease use with other structures such as
* mbedtls_ecdh_context of mbedtls_ecdsa_context.
*/
int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d );
/**
* \brief Generate a keypair with configurable base point
*
* \param grp ECP group
* \param G Chosen base point
* \param d Destination MPI (secret part)
* \param Q Destination point (public part)
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful,
* or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
*
* \note Uses bare components rather than an mbedtls_ecp_keypair structure
* in order to ease use with other structures such as
* mbedtls_ecdh_context of mbedtls_ecdsa_context.
*/
int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
const mbedtls_ecp_point *G,
mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Generate a keypair
*
* \param grp ECP group
* \param d Destination MPI (secret part)
* \param Q Destination point (public part)
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful,
* or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
*
* \note Uses bare components rather than an mbedtls_ecp_keypair structure
* in order to ease use with other structures such as
* mbedtls_ecdh_context of mbedtls_ecdsa_context.
*/
int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Generate a keypair
*
* \param grp_id ECP group identifier
* \param key Destination keypair
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful,
* or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
*/
int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/**
* \brief Check a public-private key pair
*
* \param pub Keypair structure holding a public key
* \param prv Keypair structure holding a private (plus public) key
*
* \return 0 if successful (keys are valid and match), or
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or
* a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code.
*/
int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if a test failed
*/
int mbedtls_ecp_self_test( int verbose );
#endif
#ifdef __cplusplus
}
#endif
#endif /* ecp.h */

View File

@ -0,0 +1,146 @@
/**
* \file memory_buffer_alloc.h
*
* \brief Buffer-based memory allocator
*
* Copyright (C) 2006-2015, 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_MEMORY_BUFFER_ALLOC_H
#define MBEDTLS_MEMORY_BUFFER_ALLOC_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
/**
* \name SECTION: Module settings
*
* The configuration options you can set for this module are in this section.
* Either change them in config.h or define them on the compiler command line.
* \{
*/
#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE)
#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
#endif
/* \} name SECTION: Module settings */
#define MBEDTLS_MEMORY_VERIFY_NONE 0
#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0)
#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1)
#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE)
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Initialize use of stack-based memory allocator.
* The stack-based allocator does memory management inside the
* presented buffer and does not call calloc() and free().
* It sets the global mbedtls_calloc() and mbedtls_free() pointers
* to its own functions.
* (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if
* MBEDTLS_THREADING_C is defined)
*
* \note This code is not optimized and provides a straight-forward
* implementation of a stack-based memory allocator.
*
* \param buf buffer to use as heap
* \param len size of the buffer
*/
void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len );
/**
* \brief Free the mutex for thread-safety and clear remaining memory
*/
void mbedtls_memory_buffer_alloc_free( void );
/**
* \brief Determine when the allocator should automatically verify the state
* of the entire chain of headers / meta-data.
* (Default: MBEDTLS_MEMORY_VERIFY_NONE)
*
* \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC,
* MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS
*/
void mbedtls_memory_buffer_set_verify( int verify );
#if defined(MBEDTLS_MEMORY_DEBUG)
/**
* \brief Print out the status of the allocated memory (primarily for use
* after a program should have de-allocated all memory)
* Prints out a list of 'still allocated' blocks and their stack
* trace if MBEDTLS_MEMORY_BACKTRACE is defined.
*/
void mbedtls_memory_buffer_alloc_status( void );
/**
* \brief Get the peak heap usage so far
*
* \param max_used Peak number of bytes reauested by the application
* \param max_blocks Peak number of blocks reauested by the application
*/
void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks );
/**
* \brief Reset peak statistics
*/
void mbedtls_memory_buffer_alloc_max_reset( void );
/**
* \brief Get the current heap usage
*
* \param cur_used Number of bytes reauested by the application
* \param cur_blocks Number of blocks reauested by the application
*/
void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks );
#endif /* MBEDTLS_MEMORY_DEBUG */
/**
* \brief Verifies that all headers in the memory buffer are correct
* and contain sane values. Helps debug buffer-overflow errors.
*
* Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined.
* Prints out full header information if MBEDTLS_MEMORY_DEBUG
* is defined. (Includes stack trace information for each block if
* MBEDTLS_MEMORY_BACKTRACE is defined as well).
*
* \return 0 if verified, 1 otherwise
*/
int mbedtls_memory_buffer_alloc_verify( void );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if a test failed
*/
int mbedtls_memory_buffer_alloc_self_test( int verbose );
#endif
#ifdef __cplusplus
}
#endif
#endif /* memory_buffer_alloc.h */

View File

@ -0,0 +1,214 @@
/**
* \file platform.h
*
* \brief mbed TLS Platform abstraction layer
*
* Copyright (C) 2006-2015, 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_PLATFORM_H
#define MBEDTLS_PLATFORM_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* \name SECTION: Module settings
*
* The configuration options you can set for this module are in this section.
* Either change them in config.h or define them on the compiler command line.
* \{
*/
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#include <stdio.h>
#include <stdlib.h>
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)
#if defined(_WIN32)
#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< Default snprintf to use */
#else
#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use */
#endif
#endif
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)
#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF)
#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_FREE)
#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_EXIT)
#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default free to use */
#endif
#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR)
#include MBEDTLS_PLATFORM_STD_MEM_HDR
#endif
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
/* \} name SECTION: Module settings */
/*
* The function pointers for calloc and free
*/
#if defined(MBEDTLS_PLATFORM_MEMORY)
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \
defined(MBEDTLS_PLATFORM_CALLOC_MACRO)
#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO
#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO
#else
/* For size_t */
#include <stddef.h>
extern void * (*mbedtls_calloc)( size_t n, size_t size );
extern void (*mbedtls_free)( void *ptr );
/**
* \brief Set your own memory implementation function pointers
*
* \param calloc_func the calloc function implementation
* \param free_func the free function implementation
*
* \return 0 if successful
*/
int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
void (*free_func)( void * ) );
#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */
#else /* !MBEDTLS_PLATFORM_MEMORY */
#define mbedtls_free free
#define mbedtls_calloc calloc
#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */
/*
* The function pointers for fprintf
*/
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)
/* We need FILE * */
#include <stdio.h>
extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... );
/**
* \brief Set your own fprintf function pointer
*
* \param fprintf_func the fprintf function implementation
*
* \return 0
*/
int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *,
... ) );
#else
#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO)
#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO
#else
#define mbedtls_fprintf fprintf
#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */
#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */
/*
* The function pointers for printf
*/
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)
extern int (*mbedtls_printf)( const char *format, ... );
/**
* \brief Set your own printf function pointer
*
* \param printf_func the printf function implementation
*
* \return 0
*/
int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) );
#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO)
#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO
#else
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */
#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */
/*
* The function pointers for snprintf
*
* The snprintf implementation should conform to C99:
* - it *must* always correctly zero-terminate the buffer
* (except when n == 0, then it must leave the buffer untouched)
* - however it is acceptable to return -1 instead of the required length when
* the destination buffer is too short.
*/
#if defined(_WIN32)
/* For Windows (inc. MSYS2), we provide our own fixed implementation */
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... );
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... );
/**
* \brief Set your own snprintf function pointer
*
* \param snprintf_func the snprintf function implementation
*
* \return 0
*/
int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
const char * format, ... ) );
#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO
#else
#define mbedtls_snprintf snprintf
#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
/*
* The function pointers for exit
*/
#if defined(MBEDTLS_PLATFORM_EXIT_ALT)
extern void (*mbedtls_exit)( int status );
/**
* \brief Set your own exit function pointer
*
* \param exit_func the exit function implementation
*
* \return 0
*/
int mbedtls_platform_set_exit( void (*exit_func)( int status ) );
#else
#if defined(MBEDTLS_PLATFORM_EXIT_MACRO)
#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO
#else
#define mbedtls_exit exit
#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */
#endif /* MBEDTLS_PLATFORM_EXIT_ALT */
#ifdef __cplusplus
}
#endif
#endif /* platform.h */

2433
3rd-party/mbedtls/library/bignum.c vendored Normal file

File diff suppressed because it is too large Load Diff

2090
3rd-party/mbedtls/library/ecp.c vendored Normal file

File diff suppressed because it is too large Load Diff

1325
3rd-party/mbedtls/library/ecp_curves.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,750 @@
/*
* Buffer-based memory allocator
*
* Copyright (C) 2006-2015, 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_MEMORY_BUFFER_ALLOC_C)
#include "mbedtls/memory_buffer_alloc.h"
/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C
is dependent upon MBEDTLS_PLATFORM_C */
#include "mbedtls/platform.h"
#include <string.h>
#if defined(MBEDTLS_MEMORY_BACKTRACE)
#include <execinfo.h>
#endif
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#endif
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
#define MAGIC1 0xFF00AA55
#define MAGIC2 0xEE119966
#define MAX_BT 20
typedef struct _memory_header memory_header;
struct _memory_header
{
size_t magic1;
size_t size;
size_t alloc;
memory_header *prev;
memory_header *next;
memory_header *prev_free;
memory_header *next_free;
#if defined(MBEDTLS_MEMORY_BACKTRACE)
char **trace;
size_t trace_count;
#endif
size_t magic2;
};
typedef struct
{
unsigned char *buf;
size_t len;
memory_header *first;
memory_header *first_free;
int verify;
#if defined(MBEDTLS_MEMORY_DEBUG)
size_t alloc_count;
size_t free_count;
size_t total_used;
size_t maximum_used;
size_t header_count;
size_t maximum_header_count;
#endif
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
#endif
}
buffer_alloc_ctx;
static buffer_alloc_ctx heap;
#if defined(MBEDTLS_MEMORY_DEBUG)
static void debug_header( memory_header *hdr )
{
#if defined(MBEDTLS_MEMORY_BACKTRACE)
size_t i;
#endif
mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
"ALLOC(%zu), SIZE(%10zu)\n",
(size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
hdr->alloc, hdr->size );
mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n",
(size_t) hdr->prev_free, (size_t) hdr->next_free );
#if defined(MBEDTLS_MEMORY_BACKTRACE)
mbedtls_fprintf( stderr, "TRACE: \n" );
for( i = 0; i < hdr->trace_count; i++ )
mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] );
mbedtls_fprintf( stderr, "\n" );
#endif
}
static void debug_chain()
{
memory_header *cur = heap.first;
mbedtls_fprintf( stderr, "\nBlock list\n" );
while( cur != NULL )
{
debug_header( cur );
cur = cur->next;
}
mbedtls_fprintf( stderr, "Free list\n" );
cur = heap.first_free;
while( cur != NULL )
{
debug_header( cur );
cur = cur->next_free;
}
}
#endif /* MBEDTLS_MEMORY_DEBUG */
static int verify_header( memory_header *hdr )
{
if( hdr->magic1 != MAGIC1 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
#endif
return( 1 );
}
if( hdr->magic2 != MAGIC2 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
#endif
return( 1 );
}
if( hdr->alloc > 1 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" );
#endif
return( 1 );
}
if( hdr->prev != NULL && hdr->prev == hdr->next )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: prev == next\n" );
#endif
return( 1 );
}
if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" );
#endif
return( 1 );
}
return( 0 );
}
static int verify_chain()
{
memory_header *prv = heap.first, *cur = heap.first->next;
if( verify_header( heap.first ) != 0 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: verification of first header "
"failed\n" );
#endif
return( 1 );
}
if( heap.first->prev != NULL )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: verification failed: "
"first->prev != NULL\n" );
#endif
return( 1 );
}
while( cur != NULL )
{
if( verify_header( cur ) != 0 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: verification of header "
"failed\n" );
#endif
return( 1 );
}
if( cur->prev != prv )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: verification failed: "
"cur->prev != prv\n" );
#endif
return( 1 );
}
prv = cur;
cur = cur->next;
}
return( 0 );
}
static void *buffer_alloc_calloc( size_t n, size_t size )
{
memory_header *new, *cur = heap.first_free;
unsigned char *p;
void *ret;
size_t original_len, len;
#if defined(MBEDTLS_MEMORY_BACKTRACE)
void *trace_buffer[MAX_BT];
size_t trace_cnt;
#endif
if( heap.buf == NULL || heap.first == NULL )
return( NULL );
original_len = len = n * size;
if( n != 0 && len / n != size )
return( NULL );
if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
{
len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
}
// Find block that fits
//
while( cur != NULL )
{
if( cur->size >= len )
break;
cur = cur->next_free;
}
if( cur == NULL )
return( NULL );
if( cur->alloc != 0 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated "
"data\n" );
#endif
mbedtls_exit( 1 );
}
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.alloc_count++;
#endif
// Found location, split block if > memory_header + 4 room left
//
if( cur->size - len < sizeof(memory_header) +
MBEDTLS_MEMORY_ALIGN_MULTIPLE )
{
cur->alloc = 1;
// Remove from free_list
//
if( cur->prev_free != NULL )
cur->prev_free->next_free = cur->next_free;
else
heap.first_free = cur->next_free;
if( cur->next_free != NULL )
cur->next_free->prev_free = cur->prev_free;
cur->prev_free = NULL;
cur->next_free = NULL;
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.total_used += cur->size;
if( heap.total_used > heap.maximum_used )
heap.maximum_used = heap.total_used;
#endif
#if defined(MBEDTLS_MEMORY_BACKTRACE)
trace_cnt = backtrace( trace_buffer, MAX_BT );
cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
cur->trace_count = trace_cnt;
#endif
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
mbedtls_exit( 1 );
ret = (unsigned char *) cur + sizeof( memory_header );
memset( ret, 0, original_len );
return( ret );
}
p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
new = (memory_header *) p;
new->size = cur->size - len - sizeof(memory_header);
new->alloc = 0;
new->prev = cur;
new->next = cur->next;
#if defined(MBEDTLS_MEMORY_BACKTRACE)
new->trace = NULL;
new->trace_count = 0;
#endif
new->magic1 = MAGIC1;
new->magic2 = MAGIC2;
if( new->next != NULL )
new->next->prev = new;
// Replace cur with new in free_list
//
new->prev_free = cur->prev_free;
new->next_free = cur->next_free;
if( new->prev_free != NULL )
new->prev_free->next_free = new;
else
heap.first_free = new;
if( new->next_free != NULL )
new->next_free->prev_free = new;
cur->alloc = 1;
cur->size = len;
cur->next = new;
cur->prev_free = NULL;
cur->next_free = NULL;
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.header_count++;
if( heap.header_count > heap.maximum_header_count )
heap.maximum_header_count = heap.header_count;
heap.total_used += cur->size;
if( heap.total_used > heap.maximum_used )
heap.maximum_used = heap.total_used;
#endif
#if defined(MBEDTLS_MEMORY_BACKTRACE)
trace_cnt = backtrace( trace_buffer, MAX_BT );
cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
cur->trace_count = trace_cnt;
#endif
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
mbedtls_exit( 1 );
ret = (unsigned char *) cur + sizeof( memory_header );
memset( ret, 0, original_len );
return( ret );
}
static void buffer_alloc_free( void *ptr )
{
memory_header *hdr, *old = NULL;
unsigned char *p = (unsigned char *) ptr;
if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
return;
if( p < heap.buf || p > heap.buf + heap.len )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed "
"space\n" );
#endif
mbedtls_exit( 1 );
}
p -= sizeof(memory_header);
hdr = (memory_header *) p;
if( verify_header( hdr ) != 0 )
mbedtls_exit( 1 );
if( hdr->alloc != 1 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated "
"data\n" );
#endif
mbedtls_exit( 1 );
}
hdr->alloc = 0;
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.free_count++;
heap.total_used -= hdr->size;
#endif
// Regroup with block before
//
if( hdr->prev != NULL && hdr->prev->alloc == 0 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.header_count--;
#endif
hdr->prev->size += sizeof(memory_header) + hdr->size;
hdr->prev->next = hdr->next;
old = hdr;
hdr = hdr->prev;
if( hdr->next != NULL )
hdr->next->prev = hdr;
#if defined(MBEDTLS_MEMORY_BACKTRACE)
free( old->trace );
#endif
memset( old, 0, sizeof(memory_header) );
}
// Regroup with block after
//
if( hdr->next != NULL && hdr->next->alloc == 0 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.header_count--;
#endif
hdr->size += sizeof(memory_header) + hdr->next->size;
old = hdr->next;
hdr->next = hdr->next->next;
if( hdr->prev_free != NULL || hdr->next_free != NULL )
{
if( hdr->prev_free != NULL )
hdr->prev_free->next_free = hdr->next_free;
else
heap.first_free = hdr->next_free;
if( hdr->next_free != NULL )
hdr->next_free->prev_free = hdr->prev_free;
}
hdr->prev_free = old->prev_free;
hdr->next_free = old->next_free;
if( hdr->prev_free != NULL )
hdr->prev_free->next_free = hdr;
else
heap.first_free = hdr;
if( hdr->next_free != NULL )
hdr->next_free->prev_free = hdr;
if( hdr->next != NULL )
hdr->next->prev = hdr;
#if defined(MBEDTLS_MEMORY_BACKTRACE)
free( old->trace );
#endif
memset( old, 0, sizeof(memory_header) );
}
// Prepend to free_list if we have not merged
// (Does not have to stay in same order as prev / next list)
//
if( old == NULL )
{
hdr->next_free = heap.first_free;
if( heap.first_free != NULL )
heap.first_free->prev_free = hdr;
heap.first_free = hdr;
}
#if defined(MBEDTLS_MEMORY_BACKTRACE)
hdr->trace = NULL;
hdr->trace_count = 0;
#endif
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
mbedtls_exit( 1 );
}
void mbedtls_memory_buffer_set_verify( int verify )
{
heap.verify = verify;
}
int mbedtls_memory_buffer_alloc_verify()
{
return verify_chain();
}
#if defined(MBEDTLS_MEMORY_DEBUG)
void mbedtls_memory_buffer_alloc_status()
{
mbedtls_fprintf( stderr,
"Current use: %zu blocks / %zu bytes, max: %zu blocks / "
"%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n",
heap.header_count, heap.total_used,
heap.maximum_header_count, heap.maximum_used,
heap.maximum_header_count * sizeof( memory_header )
+ heap.maximum_used,
heap.alloc_count, heap.free_count );
if( heap.first->next == NULL )
mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
else
{
mbedtls_fprintf( stderr, "Memory currently allocated:\n" );
debug_chain();
}
}
void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks )
{
*max_used = heap.maximum_used;
*max_blocks = heap.maximum_header_count;
}
void mbedtls_memory_buffer_alloc_max_reset( void )
{
heap.maximum_used = 0;
heap.maximum_header_count = 0;
}
void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks )
{
*cur_used = heap.total_used;
*cur_blocks = heap.header_count;
}
#endif /* MBEDTLS_MEMORY_DEBUG */
#if defined(MBEDTLS_THREADING_C)
static void *buffer_alloc_calloc_mutexed( size_t n, size_t size )
{
void *buf;
if( mbedtls_mutex_lock( &heap.mutex ) != 0 )
return( NULL );
buf = buffer_alloc_calloc( n, size );
if( mbedtls_mutex_unlock( &heap.mutex ) )
return( NULL );
return( buf );
}
static void buffer_alloc_free_mutexed( void *ptr )
{
/* We have to good option here, but corrupting the heap seems
* worse than loosing memory. */
if( mbedtls_mutex_lock( &heap.mutex ) )
return;
buffer_alloc_free( ptr );
(void) mbedtls_mutex_unlock( &heap.mutex );
}
#endif /* MBEDTLS_THREADING_C */
void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
{
memset( &heap, 0, sizeof(buffer_alloc_ctx) );
memset( buf, 0, len );
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &heap.mutex );
mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed,
buffer_alloc_free_mutexed );
#else
mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free );
#endif
if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
{
/* Adjust len first since buf is used in the computation */
len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
- (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
- (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
}
heap.buf = buf;
heap.len = len;
heap.first = (memory_header *) buf;
heap.first->size = len - sizeof(memory_header);
heap.first->magic1 = MAGIC1;
heap.first->magic2 = MAGIC2;
heap.first_free = heap.first;
}
void mbedtls_memory_buffer_alloc_free()
{
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &heap.mutex );
#endif
mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) );
}
#if defined(MBEDTLS_SELF_TEST)
static int check_pointer( void *p )
{
if( p == NULL )
return( -1 );
if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 )
return( -1 );
return( 0 );
}
static int check_all_free( )
{
if(
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.total_used != 0 ||
#endif
heap.first != heap.first_free ||
(void *) heap.first != (void *) heap.buf )
{
return( -1 );
}
return( 0 );
}
#define TEST_ASSERT( condition ) \
if( ! (condition) ) \
{ \
if( verbose != 0 ) \
mbedtls_printf( "failed\n" ); \
\
ret = 1; \
goto cleanup; \
}
int mbedtls_memory_buffer_alloc_self_test( int verbose )
{
unsigned char buf[1024];
unsigned char *p, *q, *r, *end;
int ret = 0;
if( verbose != 0 )
mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " );
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
p = mbedtls_calloc( 1, 1 );
q = mbedtls_calloc( 1, 128 );
r = mbedtls_calloc( 1, 16 );
TEST_ASSERT( check_pointer( p ) == 0 &&
check_pointer( q ) == 0 &&
check_pointer( r ) == 0 );
mbedtls_free( r );
mbedtls_free( q );
mbedtls_free( p );
TEST_ASSERT( check_all_free( ) == 0 );
/* Memorize end to compare with the next test */
end = heap.buf + heap.len;
mbedtls_memory_buffer_alloc_free( );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
if( verbose != 0 )
mbedtls_printf( " MBA test #2 (buf not aligned): " );
mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 );
TEST_ASSERT( heap.buf + heap.len == end );
p = mbedtls_calloc( 1, 1 );
q = mbedtls_calloc( 1, 128 );
r = mbedtls_calloc( 1, 16 );
TEST_ASSERT( check_pointer( p ) == 0 &&
check_pointer( q ) == 0 &&
check_pointer( r ) == 0 );
mbedtls_free( r );
mbedtls_free( q );
mbedtls_free( p );
TEST_ASSERT( check_all_free( ) == 0 );
mbedtls_memory_buffer_alloc_free( );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
if( verbose != 0 )
mbedtls_printf( " MBA test #3 (full): " );
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) );
TEST_ASSERT( check_pointer( p ) == 0 );
TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
mbedtls_free( p );
p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 );
q = mbedtls_calloc( 1, 16 );
TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 );
TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
mbedtls_free( q );
TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL );
mbedtls_free( p );
TEST_ASSERT( check_all_free( ) == 0 );
mbedtls_memory_buffer_alloc_free( );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
cleanup:
mbedtls_memory_buffer_alloc_free( );
return( ret );
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */

193
3rd-party/mbedtls/library/platform.c vendored Normal file
View File

@ -0,0 +1,193 @@
/*
* Platform abstraction layer
*
* Copyright (C) 2006-2015, 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_PLATFORM_C)
#include "mbedtls/platform.h"
#if defined(MBEDTLS_PLATFORM_MEMORY)
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
static void *platform_calloc_uninit( size_t n, size_t size )
{
((void) n);
((void) size);
return( NULL );
}
#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit
#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */
#if !defined(MBEDTLS_PLATFORM_STD_FREE)
static void platform_free_uninit( void *ptr )
{
((void) ptr);
}
#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit
#endif /* !MBEDTLS_PLATFORM_STD_FREE */
void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC;
void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE;
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;
return( 0 );
}
#endif /* MBEDTLS_PLATFORM_MEMORY */
#if defined(_WIN32)
#include <stdarg.h>
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... )
{
int ret;
va_list argp;
/* Avoid calling the invalid parameter handler by checking ourselves */
if( s == NULL || n == 0 || fmt == NULL )
return( -1 );
va_start( argp, fmt );
#if defined(_TRUNCATE)
ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp );
#else
ret = _vsnprintf( s, n, fmt, argp );
if( ret < 0 || (size_t) ret == n )
{
s[n-1] = '\0';
ret = -1;
}
#endif
va_end( argp );
return( ret );
}
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_snprintf_uninit( char * s, size_t n,
const char * format, ... )
{
((void) s);
((void) n);
((void) format);
return( 0 );
}
#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit
#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */
int (*mbedtls_snprintf)( char * s, size_t n,
const char * format,
... ) = MBEDTLS_PLATFORM_STD_SNPRINTF;
int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
const char * format,
... ) )
{
mbedtls_snprintf = snprintf_func;
return( 0 );
}
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_printf_uninit( const char *format, ... )
{
((void) format);
return( 0 );
}
#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit
#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */
int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF;
int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) )
{
mbedtls_printf = printf_func;
return( 0 );
}
#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_fprintf_uninit( FILE *stream, const char *format, ... )
{
((void) stream);
((void) format);
return( 0 );
}
#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit
#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */
int (*mbedtls_fprintf)( FILE *, const char *, ... ) =
MBEDTLS_PLATFORM_STD_FPRINTF;
int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) )
{
mbedtls_fprintf = fprintf_func;
return( 0 );
}
#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_EXIT_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_EXIT)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static void platform_exit_uninit( int status )
{
((void) status);
}
#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit
#endif /* !MBEDTLS_PLATFORM_STD_EXIT */
void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT;
int mbedtls_platform_set_exit( void (*exit_func)( int status ) )
{
mbedtls_exit = exit_func;
return( 0 );
}
#endif /* MBEDTLS_PLATFORM_EXIT_ALT */
#endif /* MBEDTLS_PLATFORM_C */

View File

@ -41,7 +41,6 @@ System properties:
-----------------------------------|-------------------------------------
HAVE_MALLOC | Use dynamic memory
Embedded platform properties:
#define | Description
@ -65,16 +64,17 @@ HAVE_POSIX_TIME | System provides time function
### ENABLE_* directives {#sec:enableDirectives}
BTstack properties:
#define | Description
-------------------------|---------------------------------------------
ENABLE_CLASSIC | Enable Classic related code in HCI and L2CAP
ENABLE_BLE | Enable BLE related code in HCI and L2CAP
ENABLE_EHCILL | Enable eHCILL low power mode on TI CC256x/WL18xx chipsets
ENABLE_LOG_DEBUG | Enable log_debug messages
ENABLE_LOG_ERROR | Enable log_error messages
ENABLE_LOG_INFO | Enable log_info messages
ENABLE_LOG_INTO_HCI_DUMP | Log debug messages as part of packet log
ENABLE_SCO_OVER_HCI | Enable SCO over HCI for chipsets (only CC256x/WL18xx currently)
#define | Description
-----------------------------|---------------------------------------------
ENABLE_CLASSIC | Enable Classic related code in HCI and L2CAP
ENABLE_BLE | Enable BLE related code in HCI and L2CAP
ENABLE_EHCILL | Enable eHCILL low power mode on TI CC256x/WL18xx chipsets
ENABLE_LOG_DEBUG | Enable log_debug messages
ENABLE_LOG_ERROR | Enable log_error messages
ENABLE_LOG_INFO | Enable log_info messages
ENABLE_LOG_INTO_HCI_DUMP | Log debug messages as part of packet log
ENABLE_SCO_OVER_HCI | Enable SCO over HCI for chipsets (only CC256x/WL18xx and USB CSR controllers)
ENABLE_LE_SECURE_CONNECTIONS | Enable LE Secure Connections using [mbed TLS library](https://tls.mbed.org)
### Memory configuration directives {#sec:memoryConfigurationHowTo}

View File

@ -753,10 +753,34 @@ notifications and indications can be sent. Please see Section on
The SMP protocol allows to setup authenticated and encrypted LE
connection. After initialization and configuration, SMP handles security
related functions on its own but emits events when feedback from the
related functions on its own but emits events when feedback from the
main app or the user is required. The two main tasks of the SMP protocol
are: bonding and identity resolving.
### LE Legacy Pairing and LE Secure Connections
The original pairing algorithm introduced in Bluetooth Core V4.0 does not
provide security in case of an attacker present during the initial pairing.
To fix this, the Bluetooth Core V4.2 specification introduced the new
*LE Secure Connections* method, while referring to the original method as *LE Legacy Pairing*.
BTstack supports both pairing methods. To enable the more secure LE Secure Connections method,
*ENABLE_LE_SECURE_CONNECTIONS* needs to be defined in *btstack_config.h*.
LE Secure Connections are based on Elliptic Curve Diffie-Hellman (ECDH) algorithm for the key exchange.
On start, a new public/private key pair is generated. During pairing, the
Long Term Key (LTK) is generated based on the local keypair and the remote public key.
To facilitate the creation of such a keypairs and the calculation of the LTK,
the Bluetooth Core V4.2 specification introduced appropriate commands for the Bluetooth controller.
As an alternative for controllers that don't provide these primitives, BTstack provides the relevant crytographic functions in software via the Apache 2.0 licensed [mbed TLS library](https://tls.mbed.org).
There are two details to be aware about using LE Secure Connections:
- More RAM: It requires an additional 1.5 kB RAM when using mbed TLS instead of hardware support by the Bluetooth controller.
- Peripheral must store LTK: Even an LE Peripheral needs to store the LTK in non-volatile memory.
### Initialization
To activate the security manager, call *sm_init()*.
@ -793,7 +817,9 @@ The default SMP configuration in BTstack is to be as open as possible:
- accept encryption key size from 7..16 bytes,
- expect no authentication requirements, and
- expect no authentication requirements,
- don't support LE Secure Connections, and
- IO Capabilities set to *IO_CAPABILITY_NO_INPUT_NO_OUTPUT*.
@ -804,10 +830,11 @@ respectively:
- *sm_set_encryption_key_size_range*
- *sm_set_authentication_requirements*
- *sm_set_authentication_requirements* : add SM_AUTHREQ_SECURE_CONNECTION flag to enable LE Secure Connections
- *sm_set_io_capabilities*
### Identity Resolving
Identity resolving is the process of matching a private, resolvable
@ -824,35 +851,37 @@ and later:
- *SM_EVENT_IDENTITY_RESOLVING_FAILED* on lookup failure.
### Bonding process
### User interaction
In Bluetooth LE, there are three main methods of establishing an
encrypted connection. From the most to the least secure, these are:
Out-of-Band (OOB) Data , Passkey, and Just Works.
With OOB data, there needs to be a pre-shared secret 16 byte key. In
most cases, this is not an option, especially since popular OS like iOS
dont provide a way to specify it. It some applications, where both
sides of a Bluetooth link are developed together, this could provide a
viable option.
To provide OOB data, you can register an OOB data callback with
*sm_register_oob_data_callback*.
Depending on the authentication requirements, available OOB data, and
the enabled STK generation methods, BTstack will request feedback from
Depending on the authentication requirements, IO capabilities,
available OOB data, and the enabled STK generation methods,
BTstack will request feedback from
the app in the form of an event:
- *SM_EVENT_JUST_WORKS_REQUEST*: request a user to accept a Just Works
pairing
- *SM_EVENT_PASSKEY_INPUT_NUMBER*: request user to input a passkey
- *SM_EVENT_PASSKEY_DISPLAY_NUMBER*: show a passkey to the user
- *SM_EVENT_JUST_WORKS_REQUEST*: request a user to accept a Just Works
pairing
- *SM_EVENT_NUMERIC_COMPARISON_REQUEST*: show a passkey to the user and request confirmation
To stop the bonding process, *sm_bonding_decline* should be called.
Otherwise, *sm_just_works_confirm* or *sm_passkey_input* can be
called.
After the bonding process, *SM_EVENT_PASSKEY_DISPLAY_CANCEL* is emitted to
update the user interface.
After the bonding process, *SM_EVENT_JUST_WORKS_CANCEL*, *SM_EVENT_PASSKEY_DISPLAY_CANCEL*, or *SM_EVENT_NUMERIC_COMPARISON_CANCEL* is emitted to update the user interface if an Just Works request or a passkey has been shown before.
### Out-of-Band Data with LE Legacy Pairing
LE Legacy Pairing can be made secure by providing a way for both devices
to aquire a pre-shared secret 16 byte key by some fancy method.
In most cases, this is not an option, especially since popular OS like iOS
dont provide a way to specify it. In some applications, where both
sides of a Bluetooth link are developed together, this could provide a
viable option.
To provide OOB data, you can register an OOB data callback with
*sm_register_oob_data_callback*.

View File

@ -2,11 +2,14 @@ VPATH += ${BTSTACK_ROOT}/src
VPATH += ${BTSTACK_ROOT}/src/ble
VPATH += ${BTSTACK_ROOT}/src/classic
VPATH += ${BTSTACK_ROOT}/example
VPATH += ${BTSTACK_ROOT}/3rd-party/mbedtls/library
CFLAGS += -I.
CFLAGS += -I${BTSTACK_ROOT}/src/ble
CFLAGS += -I${BTSTACK_ROOT}/src/classic
CFLAGS += -I${BTSTACK_ROOT}/src
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/mbedtls/include
CFLAGS += -I${BTSTACK_ROOT}/test/security_manager
CORE += \
btstack_memory.c \
@ -50,6 +53,14 @@ SM_REAL += \
PAN += \
pan.c \
MBEDTLS = \
bignum.c \
ecp.c \
ecp_curves.c \
sm_mbedtls_allocator.c \
memory_buffer_alloc.c \
platform.c \
EXAMPLES = \
ancs_client_demo \
gap_dedicated_bonding \
@ -66,10 +77,12 @@ EXAMPLES = \
spp_counter \
spp_streamer \
gap_le_advertisements \
hsp_hs_demo \
hsp_ag_demo \
hfp_hf_demo \
hfp_ag_demo \
hfp_hf_demo \
hsp_ag_demo \
hsp_hs_demo \
sm_pairing_peripheral \
sm_pairing_central \
EXAMPLES_USING_LE = \
ancs_client_demo \
@ -79,11 +92,13 @@ EXAMPLES_USING_LE = \
le_streamer \
spp_and_le_counter \
gap_le_advertisements \
sm_pairing_peripheral \
sm_pairing_central \
# .o for .c
CORE_OBJ = $(CORE:.c=.o)
COMMON_OBJ = $(COMMON:.c=.o)
SM_REAL_OBJ = $(SM_REAL:.c=.o)
SM_REAL_OBJ = $(SM_REAL:.c=.o) $(MBEDTLS:.c=.o)
ATT_OBJ = $(ATT:.c=.o)
GATT_CLIENT_OBJ = $(GATT_CLIENT:.c=.o)
GATT_SERVER_OBJ = $(GATT_SERVER:.c=.o)
@ -102,6 +117,8 @@ le_counter.h: le_counter.gatt
python ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
le_streamer.h: le_streamer.gatt
python ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
sm_pairing_peripheral.h: sm_pairing_peripheral.gatt
python ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
# examples
sdp_rfcomm_query: ${CORE_OBJ} ${COMMON_OBJ} ${PAN_OBJ} ${SDP_CLIENT} sdp_rfcomm_query.c
@ -119,6 +136,12 @@ spp_counter: ${CORE_OBJ} ${COMMON_OBJ} spp_counter.c
le_counter: le_counter.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_REAL_OBJ} le_counter.c
${CC} $(filter-out le_counter.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
sm_pairing_peripheral: sm_pairing_peripheral.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_REAL_OBJ} sm_pairing_peripheral.c
${CC} $(filter-out sm_pairing_peripheral.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
sm_pairing_central: ${CORE_OBJ} ${COMMON_OBJ} ${SM_REAL_OBJ} ad_parser.o sm_pairing_central.o
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@
le_streamer: le_streamer.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_REAL_OBJ} le_streamer.c
${CC} $(filter-out le_streamer.h,$^) ${CFLAGS} ${LDFLAGS} -o $@

View File

@ -35,8 +35,6 @@
*
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

View File

@ -0,0 +1,195 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
// *****************************************************************************
/* EXAMPLE_START(sm_pairing_central): LE Peripheral - Test pairing combinations
*
* @text Depending on the Authentication requiremens and IO Capabilities,
* the pairing process uses different short and long term key generation method.
* This example helps explore the different options incl. LE Secure Connections.
* It scans for advertisements and connects to the first device that lists a
* random service.
*/
// *****************************************************************************
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "btstack.h"
// We're looking for a remote device that lists this service in the advertisement
// LightBlue assigns 0x1111 as the UUID for a Blank service.
#define REMOTE_SERVICE 0x1111
static btstack_packet_callback_registration_t hci_event_callback_registration;
static btstack_packet_callback_registration_t sm_event_callback_registration;
/* @section GAP LE setup for receiving advertisements
*
* @text GAP LE advertisements are received as custom HCI events of the
* GAP_EVENT_ADVERTISING_REPORT type. To receive them, you'll need to register
* the HCI packet handler, as shown in Listing GAPLEAdvSetup.
*/
/* LISTING_START(GAPLEAdvSetup): Setting up GAP LE client for receiving advertisements */
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void sm_pairing_central_setup(void){
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
l2cap_init();
// setup le device db
le_device_db_init();
// setup SM: Display only
sm_init();
sm_event_callback_registration.callback = &packet_handler;
sm_add_event_handler(&sm_event_callback_registration);
/**
* Choose ONE of the following configurations
*/
// LE Legacy Pairing, Just Works
sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
sm_set_authentication_requirements(0);
// LE Legacy Pairing, Passkey entry initiator enter, responder (us) displays
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
// sm_set_authentication_requirements(SM_AUTHREQ_MITM_PROTECTION);
#ifdef ENABLE_LE_SECURE_CONNECTIONS
// LE Secure Connetions, Just Works
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
// sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION);
// LE Secure Connections, Numeric Comparison
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
// sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION);
// LE Legacy Pairing, Passkey entry initiator enter, responder (us) displays
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
// sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION);
#endif
}
/* LISTING_END */
/* @section HCI packet handler
*
* @text The HCI packet handler has to start the scanning,
* and to handle received advertisements. Advertisements are received
* as HCI event packets of the GAP_EVENT_ADVERTISING_REPORT type,
* see Listing GAPLEAdvPacketHandler.
*/
/* LISTING_START(GAPLEAdvPacketHandler): Scanning and receiving advertisements */
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (packet_type != HCI_EVENT_PACKET) return;
hci_con_handle_t con_handle;
switch (hci_event_packet_get_type(packet)) {
case BTSTACK_EVENT_STATE:
// BTstack activated, get started
if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
printf("Start scaning!\n");
gap_set_scan_parameters(1,0x0030, 0x0030);
gap_start_scan();
}
break;
case GAP_EVENT_ADVERTISING_REPORT:{
bd_addr_t address;
gap_event_advertising_report_get_address(packet, address);
uint8_t address_type = gap_event_advertising_report_get_address_type(packet);
uint8_t length = gap_event_advertising_report_get_data_length(packet);
const uint8_t * data = gap_event_advertising_report_get_data(packet);
printf("Advertisement event: addr-type %u, addr %s, data[%u] ",
address_type, bd_addr_to_str(address), length);
printf_hexdump(data, length);
if (!ad_data_contains_uuid16(length, (uint8_t *) data, REMOTE_SERVICE)) break;
printf("Found remote with UUID %04x, connecting...\n", REMOTE_SERVICE);
gap_stop_scan();
gap_connect(address,address_type);
break;
}
case SM_EVENT_JUST_WORKS_REQUEST:
printf("Just works requested\n");
sm_just_works_confirm(sm_event_just_works_request_get_handle(packet));
break;
case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
printf("Confirming numeric comparison: %u\n", sm_event_numeric_comparison_request_get_passkey(packet));
sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet));
break;
case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
printf("Display Passkey: %u\n", sm_event_passkey_display_number_get_passkey(packet));
break;
case HCI_EVENT_LE_META:
// wait for connection complete
if (hci_event_le_meta_get_subevent_code(packet) != HCI_SUBEVENT_LE_CONNECTION_COMPLETE) break;
con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
// start pairing
sm_request_pairing(con_handle);
break;
default:
break;
}
}
/* LISTING_END */
int btstack_main(void);
int btstack_main(void)
{
sm_pairing_central_setup();
// turn on!
hci_power_control(HCI_POWER_ON);
return 0;
}
/* EXAMPLE_END */

View File

@ -0,0 +1,180 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
// *****************************************************************************
/* EXAMPLE_START(sm_pairing_peripheral): LE Peripheral - Test pairing combinations
*
* @text Depending on the Authentication requiremens and IO Capabilities,
* the pairing process uses different short and long term key generation method.
* This example helps explore the different options incl. LE Secure Connections.
*/
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sm_pairing_peripheral.h"
#include "btstack.h"
/* @section Main Application Setup
*
* @text Listing MainConfiguration shows main application code.
* It initializes L2CAP, the Security Manager and configures the ATT Server with the pre-compiled
* ATT Database generated from $sm_pairing_peripheral.gatt$. Finally, it configures the advertisements
* and boots the Bluetooth stack.
* In this example, the Advertisement contains the Flags attribute and the device name.
* The flag 0x06 indicates: LE General Discoverable Mode and BR/EDR not supported.
* Various examples for IO Capabilites and Authentication Requirements are given below.
*/
/* LISTING_START(MainConfiguration): Init L2CAP SM ATT Server and start heartbeat timer */
static btstack_packet_callback_registration_t hci_event_callback_registration;
static btstack_packet_callback_registration_t sm_event_callback_registration;
// static hci_con_handle_t con_handle;
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
const uint8_t adv_data[] = {
// Flags general discoverable, BR/EDR not supported
0x02, 0x01, 0x06,
// Name
0x0b, 0x09, 'S', 'M', ' ', 'P', 'a', 'i', 'r', 'i', 'n', 'g',
};
const uint8_t adv_data_len = sizeof(adv_data);
static void sm_peripheral_setup(void){
// register for HCI events
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
l2cap_init();
// setup le device db
le_device_db_init();
// setup SM: Display only
sm_init();
sm_event_callback_registration.callback = &packet_handler;
sm_add_event_handler(&sm_event_callback_registration);
/**
* Choose ONE of the following configurations
*/
// LE Legacy Pairing, Just Works
sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
sm_set_authentication_requirements(0);
// LE Legacy Pairing, Passkey entry initiator enter, responder (us) displays
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
// sm_set_authentication_requirements(SM_AUTHREQ_MITM_PROTECTION);
#ifdef ENABLE_LE_SECURE_CONNECTIONS
// LE Secure Connetions, Just Works
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
// sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION);
// LE Secure Connections, Numeric Comparison
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_YES_NO);
// sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION);
// LE Legacy Pairing, Passkey entry initiator enter, responder (us) displays
// sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
// sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION|SM_AUTHREQ_MITM_PROTECTION);
#endif
// setup ATT server
att_server_init(profile_data, NULL, NULL);
att_server_register_packet_handler(packet_handler);
// setup advertisements
uint16_t adv_int_min = 0x0030;
uint16_t adv_int_max = 0x0030;
uint8_t adv_type = 0;
bd_addr_t null_addr;
memset(null_addr, 0, 6);
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00);
gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
gap_advertisements_enable(1);
}
/* LISTING_END */
/*
* @section Packet Handler
*
* @text The packet handler is used to:
* - stop the counter after a disconnect
* - send a notification when the requested ATT_EVENT_CAN_SEND_NOW is received
*/
/* LISTING_START(packetHandler): Packet Handler */
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
case SM_EVENT_JUST_WORKS_REQUEST:
printf("Just Works requested\n");
sm_just_works_confirm(sm_event_just_works_request_get_handle(packet));
break;
case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
printf("Confirming numeric comparison: %u\n", sm_event_numeric_comparison_request_get_passkey(packet));
sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet));
break;
case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
printf("Display Passkey: %u\n", sm_event_passkey_display_number_get_passkey(packet));
break;
}
break;
}
}
/* LISTING_END */
int btstack_main(void);
int btstack_main(void)
{
sm_peripheral_setup();
// turn on!
hci_power_control(HCI_POWER_ON);
return 0;
}
/* EXAMPLE_END */

View File

@ -0,0 +1,10 @@
PRIMARY_SERVICE, GAP_SERVICE
CHARACTERISTIC, GAP_DEVICE_NAME, READ, "SM Pairing Peripheral"
PRIMARY_SERVICE, GATT_SERVICE
CHARACTERISTIC, GATT_SERVICE_CHANGED, READ,
// Dummy Service
PRIMARY_SERVICE, 0000FF10-0000-1000-8000-00805F9B34FB
// Dummy Service, Characteristic, with read and notify + authentication
CHARACTERISTIC, 0000FF12-0000-1000-8000-00805F9B34FB, READ | ENCRYPTION_KEY_SIZE_16, "Secure :)"

View File

@ -14,6 +14,7 @@
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_LOG_INTO_HCI_DUMP

View File

@ -11,6 +11,7 @@
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LOG_INFO
#define ENABLE_LOG_ERROR

View File

@ -14,6 +14,7 @@
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_LOG_INTO_HCI_DUMP

View File

@ -14,6 +14,7 @@
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_LOG_INTO_HCI_DUMP

View File

@ -12,8 +12,9 @@
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
#define ENABLE_LOG_INFO
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE 52

File diff suppressed because it is too large Load Diff

View File

@ -141,7 +141,7 @@ void sm_set_accepted_stk_generation_methods(uint8_t accepted_stk_generation_meth
void sm_set_encryption_key_size_range(uint8_t min_size, uint8_t max_size);
/**
* @brief Sets the requested authentication requirements, bonding yes/no, MITM yes/no
* @brief Sets the requested authentication requirements, bonding yes/no, MITM yes/no, SC yes/no, keypress yes/no
* @param OR combination of SM_AUTHREQ_ flags
*/
void sm_set_authentication_requirements(uint8_t auth_req);
@ -166,19 +166,25 @@ void sm_send_security_request(hci_con_handle_t con_handle);
/**
* @brief Decline bonding triggered by event before
* @param addr_type and address
* @param con_handle
*/
void sm_bonding_decline(hci_con_handle_t con_handle);
/**
* @brief Confirm Just Works bonding
* @param addr_type and address
* @param con_handle
*/
void sm_just_works_confirm(hci_con_handle_t con_handle);
/**
* @brief Confirm value from SM_EVENT_NUMERIC_COMPARISON_REQUEST for Numeric Comparison bonding
* @param con_handle
*/
void sm_numeric_comparison_confirm(hci_con_handle_t con_handle);
/**
* @brief Reports passkey input by user
* @param addr_type and address
* @param con_handle
* @param passkey in [0..999999]
*/
void sm_passkey_input(hci_con_handle_t con_handle, uint32_t passkey);
@ -186,50 +192,67 @@ void sm_passkey_input(hci_con_handle_t con_handle, uint32_t passkey);
/**
*
* @brief Get encryption key size.
* @param addr_type and address
* @param con_handle
* @return 0 if not encrypted, 7-16 otherwise
*/
int sm_encryption_key_size(hci_con_handle_t con_handle);
/**
* @brief Get authentication property.
* @param addr_type and address
* @param con_handle
* @return 1 if bonded with OOB/Passkey (AND MITM protection)
*/
int sm_authenticated(hci_con_handle_t con_handle);
/**
* @brief Queries authorization state.
* @param addr_type and address
* @param con_handle
* @return authorization_state for the current session
*/
authorization_state_t sm_authorization_state(hci_con_handle_t con_handle);
/**
* @brief Used by att_server.c to request user authorization.
* @param addr_type and address
* @param con_handle
*/
void sm_request_pairing(hci_con_handle_t con_handle);
/**
* @brief Report user authorization decline.
* @param addr_type and address
* @param con_handle
*/
void sm_authorization_decline(hci_con_handle_t con_handle);
/**
* @brief Report user authorization grant.
* @param addr_type and address
* @param con_handle
*/
void sm_authorization_grant(hci_con_handle_t con_handle);
/**
* @brief Support for signed writes, used by att_server.
* @note Message is in little endian to allows passing in ATT PDU without flipping.
* @note calculated hash in done_callback is big endian
* @note signing data: [opcode, attribute_handle, message, sign_counter]
* @note calculated hash in done_callback is big endian and has 16 byte.
* @param key
* @param opcde
* @param attribute_handle
* @param message_len
* @param message
* @param sign_counter
*/
int sm_cmac_ready(void);
void sm_cmac_start(sm_key_t k, uint8_t opcode, uint16_t attribute_handle, uint16_t message_len, uint8_t * message, uint32_t sign_counter, void (*done_handler)(uint8_t hash[8]));
void sm_cmac_start(const sm_key_t key, uint8_t opcode, uint16_t attribute_handle, uint16_t message_len, const uint8_t * message, uint32_t sign_counter, void (*done_callback)(uint8_t * hash));
/*
* @brief Generic CMAC AES
* @param key
* @param message_len
* @param get_byte_callback
* @param done_callback
* @note hash is 16 bytes in big endian
*/
void sm_cmac_general_start(const sm_key_t key, uint16_t message_len, uint8_t (*get_byte_callback)(uint16_t offset), void (*done_callback)(uint8_t * hash));
/*
* @brief Match address against bonded devices
@ -244,11 +267,23 @@ int sm_address_resolution_lookup(uint8_t addr_type, bd_addr_t addr);
* @return index from le_device_db or -1 if not found/identified
*/
int sm_le_device_index(hci_con_handle_t con_handle );
/**
* @brief Set Elliptic Key Public/Private Keypair
* @note Creating a new key pair requires about 4600 bytes additional when used with MBEDTLS EC
* @note Using the same key for more than one device is not recommended.
* @param qx 32 bytes
* @param qy 32 bytes
* @param d 32 bytes
*/
void sm_use_fixed_ec_keypair(uint8_t * qx, uint8_t * qy, uint8_t * d);
/* API_END */
// PTS testing
void sm_test_set_irk(sm_key_t irk);
void sm_test_use_fixed_local_csrk(void);
void sm_test_use_fixed_ec_keypair(void);
#if defined __cplusplus
}

View File

@ -0,0 +1,376 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#include "btstack_config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "sm_mbedtls_allocator.h"
#include "btstack_util.h"
#include "btstack_debug.h"
#ifdef ENABLE_LE_SECURE_CONNECTIONS
#ifdef HAVE_HCI_CONTROLLER_DHKEY_SUPPORT
#error "Support for DHKEY Support in HCI Controller not implemented yet. Please use software implementation"
#else
#define USE_MBEDTLS_FOR_ECDH
#endif
#endif
#ifdef USE_MBEDTLS_FOR_ECDH
#include "mbedtls/config.h"
#ifndef HAVE_MALLOC
// #define DEBUG_ALLOCATIONS
size_t mbed_memory_allocated_current;
size_t mbed_memory_allocated_max;
size_t mbed_memory_space_max;
size_t mbed_memory_max;
size_t mbed_memory_smallest_buffer = 0xfffffff;
int mbed_memory_num_allocations;
#define NUM_SIZES 150
int current_individual_allocation[NUM_SIZES];
int max_individual_allocation[NUM_SIZES];
int max_total_allocation[NUM_SIZES];
// customized allocator for use with BTstack's Security Manager
// assumptions:
// - allocations are multiple of 8
// - smallest allocation is 8
static uint32_t sm_allocator_size;
static uint8_t * sm_allocator_buffer;
static uint32_t sm_allocator_used;
static sm_allocator_node_t * sm_mbedtls_node_for_offset(uint32_t offset){
if (offset > sm_allocator_size){
printf("Error! offset %u\n", offset);
}
return (sm_allocator_node_t *) (sm_allocator_buffer + offset);
}
static void dump_allocations(void){
size_t overhead = mbed_memory_num_allocations * sizeof(void*);
printf("SM Per Block - Summary: Allocations %u. Current %lu (+ %zu = %zu used), Max %lu.\n",
mbed_memory_num_allocations,
mbed_memory_allocated_current, overhead, mbed_memory_allocated_current + overhead,
mbed_memory_allocated_max);
int i;
int total = 0;
printf("- current : [ ");
for (i=0;i<sizeof(current_individual_allocation) / sizeof(int);i++){
printf("%02u ", current_individual_allocation[i]);
total += current_individual_allocation[i] * i * 8;
if (i == 16) {
printf(" - ");
i = 40;
}
if (i == 46) {
printf(" - ");
i = 140;
}
}
printf(" = %u\n", total);
printf("- current max: [ ");
total = 0;
for (i=0;i<sizeof(max_individual_allocation) / sizeof(int);i++){
printf("%02u ", max_individual_allocation[i]);
total += max_individual_allocation[i] * i * 8;
if (i == 16) {
printf(" - ");
i = 40;
}
if (i == 46) {
printf(" - ");
i = 140;
}
}
printf(" = %u\n", total);
printf("- total max: [ ");
total = 0;
for (i=0;i<sizeof(max_total_allocation) / sizeof(int);i++){
printf("%02u ", max_total_allocation[i]);
total += max_total_allocation[i] * i * 8;
if (i == 16) {
printf(" - ");
i = 40;
}
if (i == 46) {
printf(" - ");
i = 140;
}
}
printf(" = %u\n", total);
}
void sm_mbedtls_allocator_status(void){
#ifdef DEBUG_ALLOCATIONS
uint32_t current_pos = 0;
sm_allocator_node_t * current = sm_mbedtls_node_for_offset(current_pos);
int i = 1;
size_t bytes_free = 0;
printf("SM Status:\n");
while (1){
printf("- SM ALLOC: Free %u: pos %u, size %u, next %u\n", i++, current_pos, current->size, current->next);
bytes_free += current->size;
current_pos = current->next;
current = sm_mbedtls_node_for_offset(current_pos);
if (current_pos == 0) break;
}
size_t overhead = mbed_memory_num_allocations * sizeof(void*);
printf("- Summary: Allocations %u. Current %lu (+ %zu = %zu used), Max %lu. Free %zu. Total: %zu\n",
mbed_memory_num_allocations,
mbed_memory_allocated_current, overhead, mbed_memory_allocated_current + overhead,
mbed_memory_allocated_max, bytes_free, bytes_free + mbed_memory_allocated_current + overhead );
dump_allocations();
#endif
}
static inline void sm_mbedtls_allocator_update_max(){
#if 1
uint32_t current_pos = 0;
sm_allocator_node_t * current = sm_mbedtls_node_for_offset(current_pos);
while (1){
if (current_pos + 8 > mbed_memory_space_max) {
mbed_memory_space_max = current_pos + 8;
printf("SM Alloc: space used %zu (%zu data + %u allocations)\n", mbed_memory_space_max, mbed_memory_allocated_current, mbed_memory_num_allocations);
}
current_pos = current->next;
current = sm_mbedtls_node_for_offset(current_pos);
if (current_pos == 0) break;
}
#endif
}
void * sm_mbedtls_allocator_calloc(size_t count, size_t size){
size_t num_bytes = count * size;
size_t total = num_bytes + sizeof(void *);
mbed_memory_allocated_current += num_bytes;
mbed_memory_smallest_buffer = btstack_min(mbed_memory_smallest_buffer, num_bytes);
mbed_memory_num_allocations++;
// printf("SM Alloc %zu bytes\n", num_bytes);
// if (num_bytes > 1000){
// printf("big alloc!\n");
// }
int index = num_bytes / 8;
current_individual_allocation[index]++;
if (current_individual_allocation[index] > max_individual_allocation[index]){
max_individual_allocation[index] = current_individual_allocation[index];
dump_allocations();
}
// mbed_memory_allocated_max = btstack_max(mbed_memory_allocated_max, mbed_memory_allocated_current);
if (mbed_memory_allocated_current > mbed_memory_allocated_max){
memcpy(max_total_allocation, current_individual_allocation, sizeof(max_total_allocation));
mbed_memory_allocated_max = mbed_memory_allocated_current;
dump_allocations();
}
uint32_t prev_pos, current_pos, node_pos;
sm_allocator_node_t * prev, * current, * node;
// find exact block
prev_pos = 0;
prev = sm_mbedtls_node_for_offset(prev_pos);
current_pos = prev->next;
while (current_pos){
current = sm_mbedtls_node_for_offset(current_pos);
if (current->size == total){
prev->next = current->next;
memset(current, 0, total);
*(uint32_t*)current = total;
sm_mbedtls_allocator_update_max();
#ifdef DEBUG_ALLOCATIONS
printf("sm_mbedtls_allocator_calloc(%zu,%zu) = total %zu -> pos %u\n", count, size, total, current_pos);
#endif
sm_mbedtls_allocator_status();
return &sm_allocator_buffer[current_pos + sizeof(void *)];
}
// next
prev = current;
prev_pos = current_pos;
current_pos = current->next;
}
// find first large enough block
prev_pos = 0;
prev = sm_mbedtls_node_for_offset(prev_pos);
current_pos = prev->next;
while (current_pos){
current = sm_mbedtls_node_for_offset(current_pos);
if (current->size > total){
#ifdef DEBUG_ALLOCATIONS
printf("sm_mbedtls_allocator_calloc splitting block at %u, size %u (prev %u)\n", current_pos, current->size, prev_pos);
#endif
node_pos = current_pos + total;
node = sm_mbedtls_node_for_offset(node_pos);
node->next = current->next;
node->size = current->size - total;
#ifdef DEBUG_ALLOCATIONS
printf("sm_mbedtls_allocator_calloc new block at %u, size %u\n", node_pos, node->size);
#endif
prev->next = node_pos;
memset(current, 0, total);
*(uint32_t*)current = total;
sm_mbedtls_allocator_update_max();
#ifdef DEBUG_ALLOCATIONS
printf("sm_mbedtls_allocator_calloc(%zu,%zu) = total %zu -> pos %u\n", count, size, total, current_pos);
#endif
sm_mbedtls_allocator_status();
return &sm_allocator_buffer[current_pos + sizeof(void *)];
}
// next
prev = current;
prev_pos = current_pos;
current_pos = current->next;
}
#ifdef DEBUG_ALLOCATIONS
// failed to allocate
printf("sm_mbedtls_allocator_calloc error, no free chunk found!\n");
exit(10);
#else
log_error("sm_mbedtls_allocator_calloc error, no free chunk found to allocate %zu bytes\n", total);
return 0;
#endif
}
void sm_mbedtls_allocator_free(void * data){
uint32_t prev_pos, current_pos, next_pos;
sm_allocator_node_t * current, * prev, * next;
current = (sm_allocator_node_t*) (((uint8_t *) data) - sizeof(void *));
current_pos = ((uint8_t *) current) - ((uint8_t *) sm_allocator_buffer);
size_t total = *(uint32_t*) current;
size_t num_bytes = total - sizeof(void *);
mbed_memory_allocated_current -= num_bytes;
mbed_memory_num_allocations--;
int index = num_bytes / 8;
current_individual_allocation[index]--;
// printf("SM Free %zu bytes\n", num_bytes);
#ifdef DEBUG_ALLOCATIONS
printf("sm_mbedtls_allocator_free: pos %u, total %zu\n", current_pos, total);
#endif
// find previous node
prev_pos = 0;
prev = sm_mbedtls_node_for_offset(prev_pos);
while (prev->next < current_pos){
prev_pos = prev->next;
prev = sm_mbedtls_node_for_offset(prev_pos);
}
// setup new node
current->next = prev->next;
current->size = total;
prev->next = current_pos;
// merge with previous ?
#ifdef DEBUG_ALLOCATIONS
printf("sm_mbedtls_allocator_free: prev %u, %u\n", prev_pos, prev->size);
#endif
if (prev_pos + prev->size == current_pos){
#ifdef DEBUG_ALLOCATIONS
printf("sm_mbedtls_allocator_free: merge with previous\n");
#endif
prev->size += current->size;
prev->next = current->next;
current = prev;
current_pos = prev_pos;
}
// merge with next node?
next_pos = current->next;
if (current_pos + current->size == next_pos){
next = sm_mbedtls_node_for_offset(next_pos);
#ifdef DEBUG_ALLOCATIONS
printf("sm_mbedtls_allocator_free: merge with next at pos %u, size %u\n", next_pos, next->size);
#endif
current->size += next->size;
current->next = next->next;
}
sm_mbedtls_allocator_status();
}
void sm_mbedtls_allocator_init(uint8_t * buffer, uint32_t size){
sm_allocator_buffer = buffer;
sm_allocator_size = size;
sm_allocator_node_t * anchor = sm_mbedtls_node_for_offset(0);
anchor->next = sizeof(sm_allocator_node_t);
anchor->size = 0;
sm_allocator_node_t * first = sm_mbedtls_node_for_offset(anchor->next);
first->next = 0;
first->size = size - sizeof(sm_allocator_node_t);
sm_allocator_used = 2 * sizeof(sm_allocator_node_t);
sm_mbedtls_allocator_status();
}
#if 0
void * sm_mbedtls_allocator_calloc(size_t count, size_t size){
size_t total = count * size;
mbed_memory_allocated_current += total;
mbed_memory_allocated_max = btstack_max(mbed_memory_allocated_max, mbed_memory_allocated_current);
mbed_memory_smallest_buffer = btstack_min(mbed_memory_smallest_buffer, total);
mbed_memory_num_allocations++;
void * result = calloc(4 + total, 1);
*(uint32_t*) result = total;
printf("sm_mbedtls_allocator_calloc(%zu, %zu) -> res %p. Total %lu, Max %lu, Smallest %lu, Count %u\n", count, size, result, mbed_memory_allocated_current, mbed_memory_allocated_max, mbed_memory_smallest_buffer, mbed_memory_num_allocations);
return ((uint8_t *) result) + 4;
}
void sm_mbedtls_allocator_free(void * data){
void * orig = ((uint8_t *) data) - 4;
size_t total = *(uint32_t *)orig;
mbed_memory_allocated_current -= total;
mbed_memory_num_allocations--;
printf("sm_mbedtls_allocator_free(%p) - %zu bytes. Total %lu, Count %u\n", data, total, mbed_memory_allocated_current, mbed_memory_num_allocations);
free(orig);
}
#endif
#endif
#endif

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#ifndef __SM_MBEDTLS_ALLOCATOR_H
#define __SM_MBEDTLS_ALLOCATOR_H
#if defined __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
typedef struct sm_allocator_node {
uint32_t next; // offset from sm_allocator_buffer, 0 == last item
uint32_t size; // size of free chunk incl. header
} sm_allocator_node_t;
void sm_mbedtls_allocator_init(uint8_t * buffer, uint32_t size);
void sm_mbedtls_allocator_status(void);
void * sm_mbedtls_allocator_calloc(size_t count, size_t size);
void sm_mbedtls_allocator_free(void * data);
#if defined __cplusplus
}
#endif
#endif

View File

@ -951,7 +951,9 @@ typedef enum {
SM_CODE_IDENTITY_INFORMATION,
SM_CODE_IDENTITY_ADDRESS_INFORMATION,
SM_CODE_SIGNING_INFORMATION,
SM_CODE_SECURITY_REQUEST
SM_CODE_SECURITY_REQUEST,
SM_CODE_PAIRING_PUBLIC_KEY,
SM_CODE_PAIRING_DHKEY_CHECK,
} SECURITY_MANAGER_COMMANDS;
// IO Capability Values
@ -964,14 +966,17 @@ typedef enum {
} io_capability_t;
// Authentication requirement flags
#define SM_AUTHREQ_NO_BONDING 0x00
#define SM_AUTHREQ_BONDING 0x01
#define SM_AUTHREQ_MITM_PROTECTION 0x04
#define SM_AUTHREQ_NO_BONDING 0x00
#define SM_AUTHREQ_BONDING 0x01
#define SM_AUTHREQ_MITM_PROTECTION 0x04
#define SM_AUTHREQ_SECURE_CONNECTION 0x08
#define SM_AUTHREQ_KEYPRESS 0x10
// Key distribution flags used by spec
#define SM_KEYDIST_ENC_KEY 0X01
#define SM_KEYDIST_ID_KEY 0x02
#define SM_KEYDIST_SIGN 0x04
#define SM_KEYDIST_ENC_KEY 0x01
#define SM_KEYDIST_ID_KEY 0x02
#define SM_KEYDIST_SIGN 0x04
#define SM_KEYDIST_LINK_KEY 0x08
// Key distribution flags used internally
#define SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION 0x01
@ -981,9 +986,10 @@ typedef enum {
#define SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION 0x10
// STK Generation Methods
#define SM_STK_GENERATION_METHOD_JUST_WORKS 0x01
#define SM_STK_GENERATION_METHOD_OOB 0x02
#define SM_STK_GENERATION_METHOD_PASSKEY 0x04
#define SM_STK_GENERATION_METHOD_JUST_WORKS 0x01
#define SM_STK_GENERATION_METHOD_OOB 0x02
#define SM_STK_GENERATION_METHOD_PASSKEY 0x04
#define SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON 0x08
// Pairing Failed Reasons
#define SM_REASON_RESERVED 0x00
@ -996,6 +1002,10 @@ typedef enum {
#define SM_REASON_COMMAND_NOT_SUPPORTED 0x07
#define SM_REASON_UNSPECIFIED_REASON 0x08
#define SM_REASON_REPEATED_ATTEMPTS 0x09
#define SM_REASON_INVALID_PARAMETERS 0x0a
#define SM_REASON_DHKEY_CHECK_FAILED 0x0b
#define SM_REASON_NUMERIC_COMPARISON_FAILED 0x0c
// also, invalid parameters
// and reserved

View File

@ -735,12 +735,21 @@ typedef uint8_t sm_key_t[16];
#define SM_EVENT_PASSKEY_INPUT_CANCEL 0xD5
/**
* @format H1B
* @format H1B4
* @param handle
* @param addr_type
* @param address
* @param passkey
*/
#define SM_EVENT_NUMERIC_COMPARISON_REQUEST 0xD6
/**
* @format H1B4
* @param handle
* @param addr_type
* @param address
*/
#define SM_EVENT_IDENTITY_RESOLVING_STARTED 0xD6
#define SM_EVENT_NUMERIC_COMPARISON_CANCEL 0xD7
/**
* @format H1B
@ -748,7 +757,15 @@ typedef uint8_t sm_key_t[16];
* @param addr_type
* @param address
*/
#define SM_EVENT_IDENTITY_RESOLVING_FAILED 0xD7
#define SM_EVENT_IDENTITY_RESOLVING_STARTED 0xD8
/**
* @format H1B
* @param handle
* @param addr_type
* @param address
*/
#define SM_EVENT_IDENTITY_RESOLVING_FAILED 0xD9
/**
* @format H1B2
@ -757,7 +774,7 @@ typedef uint8_t sm_key_t[16];
* @param address
* @param le_device_db_index
*/
#define SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED 0xD8
#define SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED 0xDA
/**
* @format H1B
@ -765,7 +782,7 @@ typedef uint8_t sm_key_t[16];
* @param addr_type
* @param address
*/
#define SM_EVENT_AUTHORIZATION_REQUEST 0xD9
#define SM_EVENT_AUTHORIZATION_REQUEST 0xDB
/**
* @format H1B1
@ -774,7 +791,7 @@ typedef uint8_t sm_key_t[16];
* @param address
* @param authorization_result
*/
#define SM_EVENT_AUTHORIZATION_RESULT 0xDA
#define SM_EVENT_AUTHORIZATION_RESULT 0xDC
// GAP

View File

@ -2180,6 +2180,75 @@ static inline void sm_event_passkey_input_cancel_get_address(const uint8_t * eve
}
#endif
#ifdef ENABLE_BLE
/**
* @brief Get field handle from event SM_EVENT_NUMERIC_COMPARISON_REQUEST
* @param event packet
* @return handle
* @note: btstack_type H
*/
static inline hci_con_handle_t sm_event_numeric_comparison_request_get_handle(const uint8_t * event){
return little_endian_read_16(event, 2);
}
/**
* @brief Get field addr_type from event SM_EVENT_NUMERIC_COMPARISON_REQUEST
* @param event packet
* @return addr_type
* @note: btstack_type 1
*/
static inline uint8_t sm_event_numeric_comparison_request_get_addr_type(const uint8_t * event){
return event[4];
}
/**
* @brief Get field address from event SM_EVENT_NUMERIC_COMPARISON_REQUEST
* @param event packet
* @param Pointer to storage for address
* @note: btstack_type B
*/
static inline void sm_event_numeric_comparison_request_get_address(const uint8_t * event, bd_addr_t address){
reverse_bd_addr(&event[5], address);
}
/**
* @brief Get field passkey from event SM_EVENT_NUMERIC_COMPARISON_REQUEST
* @param event packet
* @return passkey
* @note: btstack_type 4
*/
static inline uint32_t sm_event_numeric_comparison_request_get_passkey(const uint8_t * event){
return little_endian_read_32(event, 11);
}
#endif
#ifdef ENABLE_BLE
/**
* @brief Get field handle from event SM_EVENT_NUMERIC_COMPARISON_CANCEL
* @param event packet
* @return handle
* @note: btstack_type H
*/
static inline hci_con_handle_t sm_event_numeric_comparison_cancel_get_handle(const uint8_t * event){
return little_endian_read_16(event, 2);
}
/**
* @brief Get field addr_type from event SM_EVENT_NUMERIC_COMPARISON_CANCEL
* @param event packet
* @return addr_type
* @note: btstack_type 1
*/
static inline uint8_t sm_event_numeric_comparison_cancel_get_addr_type(const uint8_t * event){
return event[4];
}
/**
* @brief Get field address from event SM_EVENT_NUMERIC_COMPARISON_CANCEL
* @param event packet
* @param Pointer to storage for address
* @note: btstack_type B
*/
static inline void sm_event_numeric_comparison_cancel_get_address(const uint8_t * event, bd_addr_t address){
reverse_bd_addr(&event[5], address);
}
#endif
#ifdef ENABLE_BLE
/**
* @brief Get field handle from event SM_EVENT_IDENTITY_RESOLVING_STARTED

View File

@ -132,6 +132,9 @@ void reverse_64(const uint8_t * src, uint8_t * dst){
void reverse_128(const uint8_t * src, uint8_t * dst){
reverse_bytes(src, dst, 16);
}
void reverse_256(const uint8_t * src, uint8_t * dst){
reverse_bytes(src, dst, 32);
}
void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest){
reverse_bytes(src, dest, 6);

View File

@ -144,6 +144,7 @@ void reverse_48 (const uint8_t *src, uint8_t * dest);
void reverse_56 (const uint8_t *src, uint8_t * dest);
void reverse_64 (const uint8_t *src, uint8_t * dest);
void reverse_128(const uint8_t *src, uint8_t * dest);
void reverse_256(const uint8_t *src, uint8_t * dest);
void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest);

View File

@ -302,6 +302,38 @@ typedef enum {
SM_INITIATOR_PH2_W4_PAIRING_RANDOM,
SM_INITIATOR_PH3_SEND_START_ENCRYPTION,
// LE Secure Connections
SM_SC_SEND_PUBLIC_KEY_COMMAND,
SM_SC_W4_PUBLIC_KEY_COMMAND,
SM_SC_W2_GET_RANDOM_A,
SM_SC_W4_GET_RANDOM_A,
SM_SC_W2_GET_RANDOM_B,
SM_SC_W4_GET_RANDOM_B,
SM_SC_W2_CMAC_FOR_CONFIRMATION,
SM_SC_W4_CMAC_FOR_CONFIRMATION,
SM_SC_SEND_CONFIRMATION,
SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION,
SM_SC_W4_CMAC_FOR_CHECK_CONFIRMATION,
SM_SC_W4_CONFIRMATION,
SM_SC_SEND_PAIRING_RANDOM,
SM_SC_W4_PAIRING_RANDOM,
SM_SC_W2_CALCULATE_G2,
SM_SC_W4_CALCULATE_G2,
SM_SC_W2_CALCULATE_F5_SALT,
SM_SC_W4_CALCULATE_F5_SALT,
SM_SC_W2_CALCULATE_F5_MACKEY,
SM_SC_W4_CALCULATE_F5_MACKEY,
SM_SC_W2_CALCULATE_F5_LTK,
SM_SC_W4_CALCULATE_F5_LTK,
SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK,
SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK,
SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK,
SM_SC_W4_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK,
SM_SC_W4_USER_RESPONSE,
SM_SC_SEND_DHKEY_CHECK_COMMAND,
SM_SC_W4_DHKEY_CHECK_COMMAND,
SM_SC_W4_LTK_REQUEST_SC,
} security_manager_state_t;
typedef enum {

View File

@ -19,6 +19,7 @@
#define ENABLE_LOG_INTO_HCI_DUMP
#define ENABLE_SDP_DES_DUMP
#define ENABLE_SDP_EXTRA_QUERIES
#define ENABLE_LE_SECURE_CONNECTIONS
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE 52

View File

@ -1,3 +1,5 @@
destest
security_manager
aestest
aes_cmac_test
ectest

View File

@ -4,13 +4,16 @@ CC = g++
BTSTACK_ROOT = ../..
CFLAGS = -DUNIT_TEST -x c++ -g -Wall -Wno-unused
CFLAGS = -DUNIT_TEST -g
CPPFLAGS = -x c++ -Wall -Wno-unused
CFLAGS += -I. -I.. -I${BTSTACK_ROOT}/src -I${BTSTACK_ROOT}/ble -I${BTSTACK_ROOT}/platform/posix
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/mbedtls/include
LDFLAGS += -lCppUTest -lCppUTestExt
VPATH += ${BTSTACK_ROOT}/src
VPATH += ${BTSTACK_ROOT}/src/ble
VPATH += ${BTSTACK_ROOT}/platform/posix
VPATH += ${BTSTACK_ROOT}/3rd-party/mbedtls/library
COMMON = \
btstack_linked_list.c \
@ -28,16 +31,31 @@ COMMON = \
COMMON_OBJ = $(COMMON:.c=.o)
all: security_manager aestest
MBEDTLS = \
ecp.c \
ecp_curves.c \
bignum.c \
all: security_manager aestest ectest aes_cmac_test sm_mbedtls_allocator_test
security_manager: ${CORE_OBJ} ${COMMON_OBJ} security_manager.c
${CC} ${CORE_OBJ} ${COMMON_OBJ} security_manager.c ${CFLAGS} ${LDFLAGS} -o $@
${CC} ${CORE_OBJ} ${COMMON_OBJ} security_manager.c ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} -o $@
aestest: aestest.c rijndael.c
${CC} ${CFLAGS} rijndael.c aestest.c -o $@
aestest: aestest.o rijndael.o
${CC} ${CFLAGS} $^ -o $@
ectest: ectest.o ${MBEDTLS} rijndael.o
gcc ${CFLAGS} $^ -o $@
aes_cmac_test: aes_cmac_test.o aes_cmac.o rijndael.o
gcc ${CFLAGS} $^ -o $@
sm_mbedtls_allocator_test: sm_mbedtls_allocator.o hci_dump.o btstack_util.o sm_mbedtls_allocator_test.c
${CC} sm_mbedtls_allocator.o btstack_util.o hci_dump.o sm_mbedtls_allocator_test.c ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} -o $@
test: all
./security_manager
./aes_cmac_test
./aestest
clean:

View File

@ -0,0 +1,93 @@
#include "aes_cmac.h"
#include "rijndael.h"
#include <string.h>
static void sm_shift_left_by_one_bit_inplace(int len, uint8_t * data){
int i;
int carry = 0;
for (i=len-1; i >= 0 ; i--){
int new_carry = data[i] >> 7;
data[i] = data[i] << 1 | carry;
carry = new_carry;
}
}
void aes128_calc_cyphertext(const uint8_t key[16], const uint8_t plaintext[16], uint8_t cyphertext[16]){
uint32_t rk[RKLENGTH(KEYBITS)];
int nrounds = rijndaelSetupEncrypt(rk, &key[0], KEYBITS);
rijndaelEncrypt(rk, nrounds, plaintext, cyphertext);
}
void aes_cmac_calc_subkeys(sm_key_t k0, sm_key_t k1, sm_key_t k2){
memcpy(k1, k0, 16);
sm_shift_left_by_one_bit_inplace(16, k1);
if (k0[0] & 0x80){
k1[15] ^= 0x87;
}
memcpy(k2, k1, 16);
sm_shift_left_by_one_bit_inplace(16, k2);
if (k1[0] & 0x80){
k2[15] ^= 0x87;
}
}
void aes_cmac(sm_key_t aes_cmac, const sm_key_t key, const uint8_t * data, int sm_cmac_message_len){
sm_key_t k0, k1, k2, zero;
memset(zero, 0, 16);
aes128_calc_cyphertext(key, zero, k0);
aes_cmac_calc_subkeys(k0, k1, k2);
int sm_cmac_block_count = (sm_cmac_message_len + 15) / 16;
// step 3: ..
if (sm_cmac_block_count==0){
sm_cmac_block_count = 1;
}
// step 4: set m_last
sm_key_t sm_cmac_m_last;
int sm_cmac_last_block_complete = sm_cmac_message_len != 0 && (sm_cmac_message_len & 0x0f) == 0;
int i;
if (sm_cmac_last_block_complete){
for (i=0;i<16;i++){
sm_cmac_m_last[i] = data[sm_cmac_message_len - 16 + i] ^ k1[i];
}
} else {
int valid_octets_in_last_block = sm_cmac_message_len & 0x0f;
for (i=0;i<16;i++){
if (i < valid_octets_in_last_block){
sm_cmac_m_last[i] = data[(sm_cmac_message_len & 0xfff0) + i] ^ k2[i];
continue;
}
if (i == valid_octets_in_last_block){
sm_cmac_m_last[i] = 0x80 ^ k2[i];
continue;
}
sm_cmac_m_last[i] = k2[i];
}
}
// printf("sm_cmac_start: len %u, block count %u\n", sm_cmac_message_len, sm_cmac_block_count);
// LOG_KEY(sm_cmac_m_last);
// Step 5
sm_key_t sm_cmac_x;
memset(sm_cmac_x, 0, 16);
// Step 6
sm_key_t sm_cmac_y;
for (int block = 0 ; block < sm_cmac_block_count-1 ; block++){
for (i=0;i<16;i++){
sm_cmac_y[i] = sm_cmac_x[i] ^ data[block * 16 + i];
}
aes128_calc_cyphertext(key, sm_cmac_y, sm_cmac_x);
}
for (i=0;i<16;i++){
sm_cmac_y[i] = sm_cmac_x[i] ^ sm_cmac_m_last[i];
}
// Step 7
aes128_calc_cyphertext(key, sm_cmac_y, aes_cmac);
}

View File

@ -0,0 +1,10 @@
#ifndef __AES_CMAC_H
#define __AES_CMAC_H
#include <stdint.h>
typedef uint8_t sm_key_t[16];
void aes128_calc_cyphertext(const uint8_t key[16], const uint8_t plaintext[16], uint8_t cyphertext[16]);
void aes_cmac_calc_subkeys(sm_key_t k0, sm_key_t k1, sm_key_t k2);
void aes_cmac(sm_key_t aes_cmac, const sm_key_t key, const uint8_t * data, int sm_cmac_message_len);
#endif

View File

@ -0,0 +1,330 @@
#include <stdio.h>
#include <string.h>
#include "aes_cmac.h"
// #include "btstack_util.h"
typedef uint8_t sm_key24_t[3];
typedef uint8_t sm_key56_t[7];
typedef uint8_t sm_key256_t[32];
static const char * key_string = "2b7e1516 28aed2a6 abf71588 09cf4f3c";
static const char * k0_string = "7df76b0c 1ab899b3 3e42f047 b91b546f";
static const char * k1_string = "fbeed618 35713366 7c85e08f 7236a8de";
static const char * k2_string = "f7ddac30 6ae266cc f90bc11e e46d513b";
static const char * m0_string = "";
static const char * cmac_m0_string = "bb1d6929 e9593728 7fa37d12 9b756746";
static const char * m16_string = "6bc1bee2 2e409f96 e93d7e11 7393172a";
static const char * cmac_m16_string = "070a16b4 6b4d4144 f79bdd9d d04a287c";
static const char * m40_string = "6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411";
static const char * cmac_m40_string = "dfa66747 de9ae630 30ca3261 1497c827";
static const char * m64_string = "6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411 e5fbc119 1a0a52ef f69f2445 df4f9b17 ad2b417b e66c3710";
static const char * cmac_m64_string = "51f0bebf 7e3b9d92 fc497417 79363cfe";
// f4
static const char * f4_u_string = "20b003d2 f297be2c 5e2c83a7 e9f9a5b9 eff49111 acf4fddb cc030148 0e359de6";
static const char * f4_v_string = "55188b3d 32f6bb9a 900afcfb eed4e72a 59cb9ac2 f19d7cfb 6b4fdd49 f47fc5fd";
static const char * f4_x_string = "d5cb8454 d177733e ffffb2ec 712baeab";
static const char * f4_z_string = "00";
static const char * f4_cmac_string = "f2c916f1 07a9bd1c f1eda1be a974872d";
// f5
const char * f5_w_string = "ec0234a3 57c8ad05 341010a6 0a397d9b 99796b13 b4f866f1 868d34f3 73bfa698";
const char * f5_t_string = "3c128f20 de883288 97624bdb 8dac6989";
const char * f5_n1_string = "d5cb8454 d177733e ffffb2ec 712baeab";
const char * f5_n2_string = "a6e8e7cc 25a75f6e 216583f7 ff3dc4cf";
const char * f5_a1_string = "00561237 37bfce";
const char * f5_a2_string = "00a71370 2dcfc1";
const char * f5_cmac_string = "2965f176 a1084a02 fd3f6a20 ce636e20 69867911 69d7cd23 980522b5 94750a38";
// f6
const char * f6_n1_string = "d5cb8454 d177733e ffffb2ec 712baeab";
const char * f6_n2_string = "a6e8e7cc 25a75f6e 216583f7 ff3dc4cf";
const char * f6_mac_key_string = "2965f176 a1084a02 fd3f6a20 ce636e20";
const char * f6_r_string = "12a3343b b453bb54 08da42d2 0c2d0fc8";
const char * f6_io_cap_string = "010102";
const char * f6_a1_string = "00561237 37bfce";
const char * f6_a2_string = "00a71370 2dcfc1";
const char * f6_cmac_string = "e3c47398 9cd0e8c5 d26c0b09 da958f61";
// g2
const char * g2_u_string = "20b003d2 f297be2c 5e2c83a7 e9f9a5b9 eff49111 acf4fddb cc030148 0e359de6";
const char * g2_v_string = "55188b3d 32f6bb9a 900afcfb eed4e72a 59cb9ac2 f19d7cfb 6b4fdd49 f47fc5fd";
const char * g2_x_string = "d5cb8454 d177733e ffffb2ec 712baeab";
const char * g2_y_string = "a6e8e7cc 25a75f6e 216583f7 ff3dc4cf";
// const char * g2_cmac_string = "1536d18d e3d20df9 9b7044c1 2f9ed5ba";
const char * g2_res_string = "2f9ed5ba";
// h6
const char * h6_key_string = "ec0234a3 57c8ad05 341010a6 0a397d9b";
const char * h6_key_id_string = "6c656272";
const char * h6_cmac_string = "2d9ae102 e76dc91c e8d3a9e2 80b16399";
static uint32_t big_endian_read_32( const uint8_t * buffer, int pos) {
return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24);
}
static void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
buffer[pos++] = value >> 24;
buffer[pos++] = value >> 16;
buffer[pos++] = value >> 8;
buffer[pos++] = value;
}
static void hexdump2(void *data, int size){
if (size <= 0) return;
int i;
for (i=0; i<size;i++){
printf("%02X ", ((uint8_t *)data)[i]);
}
printf("\n");
}
static int nibble_for_char(char c){
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return -1;
}
static int parse_hex(uint8_t * buffer, const char * hex_string){
int len = 0;
while (*hex_string){
if (*hex_string == ' '){
hex_string++;
continue;
}
int high_nibble = nibble_for_char(*hex_string++);
int low_nibble = nibble_for_char(*hex_string++);
*buffer++ = (high_nibble << 4) | low_nibble;
len++;
}
return len;
}
#define LOG_KEY(NAME) { printf("%16s: ", #NAME); hexdump2(NAME, 16); }
#define PARSE_KEY(NAME) { parse_hex(NAME, NAME##_string); LOG_KEY(NAME); }
#define VALIDATE_KEY(NAME) { LOG_KEY(NAME); sm_key_t test; parse_hex(test, NAME##_string); if (memcmp(NAME, test, 16)){ printf("Error calculating key\n"); } }
#define VALIDATE_MESSAGE(NAME) validate_message(#NAME, NAME##_string, cmac_##NAME##_string)
static void validate_message(const char * name, const char * message_string, const char * cmac_string){
uint8_t m[128];
int len = parse_hex(m, message_string);
sm_key_t cmac;
parse_hex(cmac, cmac_string);
printf("-- verify message %s, len %u:\nm: %s\ncmac: %s\n", name, len, message_string, cmac_string);
sm_key_t key;
parse_hex(key, key_string);
sm_key_t cmac_test;
aes_cmac(cmac_test, key, m, len);
LOG_KEY(cmac_test);
if (memcmp(cmac_test, cmac, 16)){
printf("CMAC incorrect!\n");
} else {
printf("CMAC correct!\n");
}
}
static void f4(sm_key_t res, const sm_key256_t u, const sm_key256_t v, const sm_key_t x, uint8_t z){
uint8_t buffer[65];
memcpy(buffer, u, 32);
memcpy(buffer+32, v, 32);
buffer[64] = z;
// hexdump2(buffer, sizeof(buffer));
aes_cmac(res, x, buffer, sizeof(buffer));
}
const sm_key_t f5_salt = { 0x6C ,0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38, 0x60, 0x37, 0x0B, 0xDB, 0x5A, 0x60, 0x83, 0xBE};
const uint8_t f5_key_id[] = { 0x62, 0x74, 0x6c, 0x65 };
const uint8_t f5_length[] = { 0x01, 0x00};
static void f5(sm_key256_t res, const sm_key256_t w, const sm_key_t n1, const sm_key_t n2, const sm_key56_t a1, const sm_key56_t a2){
// T = AES-CMACSAL_T(W)
sm_key_t t;
aes_cmac(t, f5_salt, w, 32);
// f5(W, N1, N2, A1, A2) = AES-CMACT (Counter = 0 || keyID || N1 || N2|| A1|| A2 || Length = 256) -- this is the MacKey
uint8_t buffer[53];
buffer[0] = 0;
memcpy(buffer+01, f5_key_id, 4);
memcpy(buffer+05, n1, 16);
memcpy(buffer+21, n2, 16);
memcpy(buffer+37, a1, 7);
memcpy(buffer+44, a2, 7);
memcpy(buffer+51, f5_length, 2);
// hexdump2(buffer, sizeof(buffer));
aes_cmac(res, t, buffer, sizeof(buffer));
// hexdump2(res, 16);
// || AES-CMACT (Counter = 1 || keyID || N1 || N2|| A1|| A2 || Length = 256) -- this is the LTK
buffer[0] = 1;
// hexdump2(buffer, sizeof(buffer));
aes_cmac(res+16, t, buffer, sizeof(buffer));
// hexdump2(res+16, 16);
}
// f6(W, N1, N2, R, IOcap, A1, A2) = AES-CMACW (N1 || N2 || R || IOcap || A1 || A2
// - W is 128 bits
// - N1 is 128 bits
// - N2 is 128 bits
// - R is 128 bits
// - IOcap is 24 bits
// - A1 is 56 bits
// - A2 is 56 bits
static void f6(sm_key_t res, const sm_key_t w, const sm_key_t n1, const sm_key_t n2, const sm_key_t r, const sm_key24_t io_cap, const sm_key56_t a1, const sm_key56_t a2){
uint8_t buffer[65];
memcpy(buffer, n1, 16);
memcpy(buffer+16, n2, 16);
memcpy(buffer+32, r, 16);
memcpy(buffer+48, io_cap, 3);
memcpy(buffer+51, a1, 7);
memcpy(buffer+58, a2, 7);
aes_cmac(res, w, buffer,sizeof(buffer));
}
// g2(U, V, X, Y) = AES-CMACX(U || V || Y) mod 2^32
// - U is 256 bits
// - V is 256 bits
// - X is 128 bits
// - Y is 128 bits
static uint32_t g2(const sm_key256_t u, const sm_key256_t v, const sm_key_t x, const sm_key_t y){
uint8_t buffer[80];
memcpy(buffer, u, 32);
memcpy(buffer+32, v, 32);
memcpy(buffer+64, y, 16);
sm_key_t cmac;
aes_cmac(cmac, x, buffer, sizeof(buffer));
return big_endian_read_32(cmac, 12);
}
// h6(W, keyID) = AES-CMACW(keyID)
// - W is 128 bits
// - keyID is 32 bits
static void h6(sm_key_t res, const sm_key_t w, const uint32_t key_id){
uint8_t key_id_buffer[4];
big_endian_store_32(key_id_buffer, 0, key_id);
aes_cmac(res, w, key_id_buffer, 4);
}
int main(void){
sm_key_t key, k0, k1, k2, zero;
memset(zero, 0, 16);
PARSE_KEY(key);
// validate subkey k0,k1,k2 generation
aes128_calc_cyphertext(key, zero, k0);
VALIDATE_KEY(k0);
aes_cmac_calc_subkeys(k0, k1, k2);
VALIDATE_KEY(k1);
VALIDATE_KEY(k2);
// validate AES_CMAC for some messages
VALIDATE_MESSAGE(m0);
VALIDATE_MESSAGE(m16);
VALIDATE_MESSAGE(m40);
VALIDATE_MESSAGE(m64);
// validate f4
printf("-- verify f4\n");
sm_key_t f4_x, f4_cmac, f4_cmac_test;
sm_key256_t f4_u, f4_v;
uint8_t f4_z;
parse_hex(f4_cmac, f4_cmac_string);
parse_hex(f4_u, f4_u_string);
parse_hex(f4_v, f4_v_string);
parse_hex(f4_x, f4_x_string);
parse_hex(&f4_z, f4_z_string);
f4(f4_cmac_test, f4_u, f4_v, f4_x, f4_z);
if (memcmp(f4_cmac_test, f4_cmac, 16)){
printf("CMAC incorrect!\n");
} else {
printf("CMAC correct!\n");
}
// valdiate f5
printf("-- verify f5\n");
sm_key_t f5_cmac, f5_mackey, f5_n1, f5_n2;
sm_key56_t f5_a1, f5_a2;
sm_key256_t f5_w, f5_res;
uint8_t f5_z;
parse_hex(f5_w, f5_w_string);
parse_hex(f5_n1, f5_n1_string);
parse_hex(f5_n2, f5_n2_string);
parse_hex(f5_a1, f5_a1_string);
parse_hex(f5_a2, f5_a2_string);
f5(f5_res, f5_w, f5_n1, f5_n2, f5_a1, f5_a2);
printf("MacKey:");
hexdump2(f5_res, 16);
printf("LTK: ");
hexdump2(f5_res+16, 16);
parse_hex(f5_cmac, f5_cmac_string);
if (memcmp(f5_res, f5_cmac, 16)){
printf("CMAC incorrect!\n");
} else {
printf("CMAC correct!\n");
}
// validate f6
printf("-- verify f6\n");
sm_key_t f6_cmac, f6_mac_key, f6_n1, f6_n2, f6_r, f6_res;
sm_key24_t f6_io_cap;
sm_key56_t f6_a1, f6_a2;
uint8_t f6_z;
parse_hex(f6_n1, f6_n1_string);
parse_hex(f6_n2, f6_n2_string);
parse_hex(f6_a1, f6_a1_string);
parse_hex(f6_a2, f6_a2_string);
parse_hex(f6_mac_key, f6_mac_key_string);
parse_hex(f6_r, f6_r_string);
parse_hex(f6_io_cap, f6_io_cap_string);
f6(f6_res, f6_mac_key, f6_n1, f6_n2, f6_r, f6_io_cap, f6_a1, f6_a2);
hexdump2(f6_res, 16);
parse_hex(f6_cmac, f6_cmac_string);
if (memcmp(f6_res, f6_cmac, 16)){
printf("CMAC incorrect!\n");
} else {
printf("CMAC correct!\n");
}
// validate g2
printf("-- verify g2\n");
sm_key_t g2_cmac, g2_x, g2_y;
sm_key256_t g2_u, g2_v;
parse_hex(g2_x, g2_x_string);
parse_hex(g2_y, g2_y_string);
parse_hex(g2_u, g2_u_string);
parse_hex(g2_v, g2_v_string);
uint32_t g2_test = g2(g2_u, g2_v, g2_x, g2_y);
printf("%08x\n", g2_test);
uint8_t g2_res_buffer[4];
parse_hex(g2_res_buffer, g2_res_string);
uint32_t g2_res = big_endian_read_32(g2_res_buffer, 0);
if (g2_test != g2_res){
printf("G2 incorrect!\n");
} else {
printf("G2 correct!\n");
}
// validate h6
printf("-- verify h6\n");
sm_key_t h6_key, h6_res, h6_cmac;
uint8_t h6_key_id_buffer[4];
parse_hex(h6_key, h6_key_string);
parse_hex(h6_key_id_buffer, h6_key_id_string);
parse_hex(h6_cmac, h6_cmac_string);
uint32_t h6_key_id = big_endian_read_32(h6_key_id_buffer, 0);
h6(h6_res, h6_key, h6_key_id);
hexdump2(h6_res, 16);
if (memcmp(h6_res, h6_cmac, 16)){
printf("CMAC incorrect!\n");
} else {
printf("CMAC correct!\n");
}
}

View File

@ -0,0 +1,237 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif
#include "mbedtls/ecp.h"
typedef uint8_t sm_key24_t[3];
typedef uint8_t sm_key56_t[7];
typedef uint8_t sm_key_t[16];
typedef uint8_t sm_key256_t[32];
// P256 Set 1
static const char * set1_private_a_string = "3f49f6d4a3c55f3874c9b3e3d2103f504aff607beb40b7995899b8a6cd3c1abd";
static const char * set1_private_b_string = "55188b3d32f6bb9a900afcfbeed4e72a59cb9ac2f19d7cfb6b4fdd49f47fc5fd";
static const char * set1_public_ax_string = "20b003d2f297be2c5e2c83a7e9f9a5b9eff49111acf4fddbcc0301480e359de6";
static const char * set1_public_ay_string = "dc809c49652aeb6d63329abf5a52155c766345c28fed3024741c8ed01589d28b";
static const char * set1_public_bx_string = "1ea1f0f01faf1d9609592284f19e4c0047b58afd8615a69f559077b22faaa190";
static const char * set1_public_by_string = "4c55f33e429dad377356703a9ab85160472d1130e28e36765f89aff915b1214a";
static const char * set1_dh_key_string = "ec0234a357c8ad05341010a60a397d9b99796b13b4f866f1868d34f373bfa698";
// P256 Set 1
static const char * set2_private_a_string = "06a516693c9aa31a6084545d0c5db641b48572b97203ddffb7ac73f7d0457663";
static const char * set2_private_b_string = "529aa0670d72cd6497502ed473502b037e8803b5c60829a5a3caa219505530ba";
static const char * set2_public_ax_string = "2c31a47b5779809ef44cb5eaaf5c3e43d5f8faad4a8794cb987e9b03745c78dd";
static const char * set2_public_ay_string = "919512183898dfbecd52e2408e43871fd021109117bd3ed4eaf8437743715d4f";
static const char * set2_public_bx_string = "f465e43ff23d3f1b9dc7dfc04da8758184dbc966204796eccf0d6cf5e16500cc";
static const char * set2_public_by_string = "0201d048bcbbd899eeefc424164e33c201c2b010ca6b4d43a8a155cad8ecb279";
static const char * set2_dh_key_string = "ab85843a2f6d883f62e5684b38e307335fe6e1945ecd19604105c6f23221eb69";
uint32_t big_endian_read_32( const uint8_t * buffer, int pos) {
return ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos]) << 24);
}
void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
buffer[pos++] = value >> 24;
buffer[pos++] = value >> 16;
buffer[pos++] = value >> 8;
buffer[pos++] = value;
}
static int nibble_for_char(char c){
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'F' + 10;
return -1;
}
static int parse_hex(uint8_t * buffer, const char * hex_string){
int len = 0;
while (*hex_string){
if (*hex_string == ' '){
hex_string++;
continue;
}
int high_nibble = nibble_for_char(*hex_string++);
int low_nibble = nibble_for_char(*hex_string++);
*buffer++ = (high_nibble << 4) | low_nibble;
len++;
}
return len;
}
static void hexdump2(void *data, int size){
if (size <= 0) return;
int i;
for (i=0; i<size;i++){
printf("%02X ", ((uint8_t *)data)[i]);
}
printf("\n");
}
int test_set1(void){
mbedtls_ecp_group grp;
mbedtls_ecp_point R1, R2;
mbedtls_ecp_point Pa, Pb;
mbedtls_mpi da, db, dh_key;
mbedtls_ecp_group_init( &grp );
mbedtls_ecp_point_init( &R1 );
mbedtls_ecp_point_init( &R2 );
mbedtls_ecp_point_init( &Pa );
mbedtls_ecp_point_init( &Pb );
mbedtls_mpi_init(&da);
mbedtls_mpi_init(&db);
int res = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (res) {
printf("set1: error loading curve %d\n", res);
return 0;
}
// da * Pb
mbedtls_mpi_read_string( &da, 16, set1_private_a_string );
mbedtls_mpi_read_string( &Pb.X, 16, set1_public_bx_string );
mbedtls_mpi_read_string( &Pb.Y, 16, set1_public_by_string );
mbedtls_mpi_read_string( &Pb.Z, 16, "1" );
mbedtls_ecp_mul(&grp, &R1, &da, &Pb, NULL, NULL);
// db * Pa
mbedtls_mpi_read_string( &Pa.X, 16, set1_public_ax_string );
mbedtls_mpi_read_string( &Pa.Y, 16, set1_public_ay_string );
mbedtls_mpi_read_string( &Pa.Z, 16, "1" );
mbedtls_mpi_read_string( &db, 16, set1_private_b_string );
mbedtls_ecp_mul(&grp, &R2, &db, &Pa, NULL, NULL);
// checks
mbedtls_mpi_read_string( &dh_key, 16, set1_dh_key_string);
if (mbedtls_mpi_cmp_mpi(&R1.X, &dh_key)){
printf( "set1: da * Pb incorrect\n");
return 0;
} else {
printf( "set1: da * Pb correct\n");
}
if (mbedtls_mpi_cmp_mpi(&R2.X, &dh_key)){
printf( "set1: db * Pa incorrect\n");
return 0;
} else {
printf( "set1: db * Pa correct\n");
}
return 1;
}
int test_set2(void){
mbedtls_ecp_group grp;
mbedtls_ecp_point R1, R2;
mbedtls_ecp_point Pa, Pb;
mbedtls_mpi da, db, dh_key;
mbedtls_ecp_group_init( &grp );
mbedtls_ecp_point_init( &R1 );
mbedtls_ecp_point_init( &R2 );
mbedtls_ecp_point_init( &Pa );
mbedtls_ecp_point_init( &Pb );
mbedtls_mpi_init(&da);
mbedtls_mpi_init(&db);
int res = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (res) {
printf("set 2: error loading curve %d\n", res);
return 0;
}
// da * Pb
mbedtls_mpi_read_string( &da, 16, set2_private_a_string );
mbedtls_mpi_read_string( &Pb.X, 16, set2_public_bx_string );
mbedtls_mpi_read_string( &Pb.Y, 16, set2_public_by_string );
mbedtls_mpi_read_string( &Pb.Z, 16, "1" );
mbedtls_ecp_mul(&grp, &R1, &da, &Pb, NULL, NULL);
// db * Pa
mbedtls_mpi_read_string( &Pa.X, 16, set2_public_ax_string );
mbedtls_mpi_read_string( &Pa.Y, 16, set2_public_ay_string );
mbedtls_mpi_read_string( &Pa.Z, 16, "1" );
mbedtls_mpi_read_string( &db, 16, set2_private_b_string );
mbedtls_ecp_mul(&grp, &R2, &db, &Pa, NULL, NULL);
// checks
mbedtls_mpi_read_string( &dh_key, 16, set2_dh_key_string);
if (mbedtls_mpi_cmp_mpi(&R1.X, &dh_key)){
printf( "set2: da * Pb incorrect\n");
return 0;
} else {
printf( "set2: da * Pb correct\n");
}
if (mbedtls_mpi_cmp_mpi(&R2.X, &dh_key)){
printf( "set2: db * Pa incorrect\n");
return 0;
} else {
printf( "set2: db * Pa correct\n");
}
return 1;
}
int test_generate_f_rng(void * context, unsigned char * buffer, size_t size){
printf("test_generate_f_rng: size %u\n", (int)size);
while (size) {
*buffer++ = rand() & 0xff;
size--;
}
return 0;
}
int test_generate(void){
// use stdlib rand with fixed seed for testing
srand(0);
mbedtls_ecp_keypair keypair;
mbedtls_ecp_keypair_init(&keypair);
int res = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, &keypair, &test_generate_f_rng, NULL);
if (res){
printf("generate keypair failed %u\n", res);
return 0;
}
// print keypair
char buffer[100];
size_t len;
mbedtls_mpi_write_string( &keypair.d, 16, buffer, sizeof(buffer), &len);
printf("d: %s\n", buffer);
mbedtls_mpi_write_string( &keypair.Q.X, 16, buffer, sizeof(buffer), &len);
printf("X: %s\n", buffer);
mbedtls_mpi_write_string( &keypair.Q.Y, 16, buffer, sizeof(buffer), &len);
printf("Y: %s\n", buffer);
// verify
res = mbedtls_ecp_check_pubkey(&keypair.grp, &keypair.Q);
if (res){
printf("public key invalid\n");
return 0;
}
res = mbedtls_ecp_check_privkey(&keypair.grp, &keypair.d);
if (res){
printf("private key invalid\n");
return 0;
}
return 0;
}
int main(void){
test_set1();
test_set2();
test_generate();
return 0;
}

View File

@ -10,10 +10,6 @@
typedef uint32_t u32;
typedef uint8_t u8;
int rijndaelStartOfCode(void){
return 1;
}
static const u32 Te0[256] =
{
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
@ -1222,7 +1218,3 @@ u32 s0, s1, s2, s3, t0, t1, t2, t3;
}
int rijndaelEndOfCode(void){
return 1;
}

View File

@ -121,7 +121,6 @@ uint8_t * mock_packet_buffer(void);
uint16_t mock_packet_buffer_len(void);
void mock_clear_packet_buffer(void);
void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
uint16_t aHandle;
bd_addr_t event_address;
@ -174,11 +173,79 @@ void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
#define CHECK_HCI_COMMAND(packet) { printf("check " #packet "\n") ; CHECK_EQUAL_ARRAY(packet, mock_packet_buffer(), sizeof(packet)); mock_clear_packet_buffer(); }
#define CHECK_ACL_PACKET(packet) { printf("check " #packet "\n") ; CHECK_EQUAL_ARRAY(packet, mock_packet_buffer(), sizeof(packet)); mock_clear_packet_buffer(); }
static int parse_hex(uint8_t * buffer, const char * hex_string){
int len = 0;
while (*hex_string){
if (*hex_string == ' '){
hex_string++;
continue;
}
int high_nibble = nibble_for_char(*hex_string++);
int low_nibble = nibble_for_char(*hex_string++);
*buffer++ = (high_nibble << 4) | low_nibble;
len++;
}
return len;
}
static const char * key_string = "2b7e1516 28aed2a6 abf71588 09cf4f3c";
static const char * m0_string = "";
static const char * cmac_m0_string = "bb1d6929 e9593728 7fa37d12 9b756746";
static const char * m16_string = "6bc1bee2 2e409f96 e93d7e11 7393172a";
static const char * cmac_m16_string = "070a16b4 6b4d4144 f79bdd9d d04a287c";
static const char * m40_string = "6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411";
static const char * cmac_m40_string = "dfa66747 de9ae630 30ca3261 1497c827";
static const char * m64_string = "6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411 e5fbc119 1a0a52ef f69f2445 df4f9b17 ad2b417b e66c3710";
static const char * cmac_m64_string = "51f0bebf 7e3b9d92 fc497417 79363cfe";
static uint8_t cmac_hash[16];
static int cmac_hash_received;
static void cmac_done(uint8_t * hash){
memcpy(cmac_hash, hash, 16);
printf("cmac hash: ");
printf_hexdump(hash, 16);
cmac_hash_received = 1;
}
static uint8_t m[128];
static uint8_t get_byte(uint16_t offset){
// printf ("get byte %02u -> %02x\n", offset, m[offset]);
return m[offset];
}
static void validate_message(const char * name, const char * message_string, const char * cmac_string){
mock_clear_packet_buffer();
int len = parse_hex(m, message_string);
// expected result
sm_key_t cmac;
parse_hex(cmac, cmac_string);
printf("-- verify key %s message %s, len %u:\nm: %s\ncmac: %s\n", key_string, name, len, message_string, cmac_string);
sm_key_t key;
parse_hex(key, key_string);
// printf_hexdump(key, 16);
cmac_hash_received = 0;
sm_cmac_general_start(key, len, &get_byte, &cmac_done);
while (!cmac_hash_received){
aes128_report_result();
}
CHECK_EQUAL_ARRAY(cmac, cmac_hash, 16);
}
#define VALIDATE_MESSAGE(NAME) validate_message(#NAME, NAME##_string, cmac_##NAME##_string)
TEST_GROUP(SecurityManager){
void setup(void){
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_posix_get_instance());
static int first = 1;
if (first){
first = 0;
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_posix_get_instance());
}
sm_init();
sm_set_io_capabilities(IO_CAPABILITY_NO_INPUT_NO_OUTPUT);
sm_set_authentication_requirements( SM_AUTHREQ_BONDING );
@ -186,6 +253,42 @@ TEST_GROUP(SecurityManager){
sm_add_event_handler(&sm_event_callback_registration); }
};
TEST(SecurityManager, CMACTest){
mock_init();
mock_simulate_hci_state_working();
// expect le encrypt commmand
CHECK_HCI_COMMAND(test_command_packet_01);
aes128_report_result();
// expect le encrypt commmand
CHECK_HCI_COMMAND(test_command_packet_02);
aes128_report_result();
mock_clear_packet_buffer();
// additional test: cmac signing
// aes cmac tests
sm_key_t key;
parse_hex(key, key_string);
uint8_t message [] = "hallo";
cmac_hash_received = 0;
sm_cmac_start(key, 0x11, 0x1234, sizeof(message), message, 1, &cmac_done);
while (!cmac_hash_received){
aes128_report_result();
}
uint8_t expected_hash[] = { 0x40, 0x4E, 0xDC, 0x0F, 0x6E, 0x0F, 0xF9, 0x5C};
CHECK_EQUAL_ARRAY(expected_hash, cmac_hash, 8);
// generic aes cmac tests
VALIDATE_MESSAGE(m0);
VALIDATE_MESSAGE(m16);
VALIDATE_MESSAGE(m40);
VALIDATE_MESSAGE(m64);
}
TEST(SecurityManager, MainTest){
mock_init();
@ -337,6 +440,6 @@ TEST(SecurityManager, MainTest){
}
int main (int argc, const char * argv[]){
hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
// hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
return CommandLineTestRunner::RunAllTests(argc, argv);
}

View File

@ -0,0 +1,147 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ble/sm_mbedtls_allocator.h"
#include "CppUTest/TestHarness.h"
#include "CppUTest/CommandLineTestRunner.h"
static uint8_t mbedtls_memory_buffer[5000]; // experimental value on 64-bit system
uint32_t offset_for_buffer(void * buffer){
return (uint8_t*)buffer - mbedtls_memory_buffer;
}
TEST_GROUP(sm_mbedtls_allocator_test){
};
TEST(sm_mbedtls_allocator_test, init){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
sm_allocator_node_t * anchor = (sm_allocator_node_t*) mbedtls_memory_buffer;
sm_allocator_node_t * first = (sm_allocator_node_t*) &mbedtls_memory_buffer[8];
CHECK_EQUAL(8, anchor->next);
CHECK_EQUAL(0, anchor->size);
CHECK_EQUAL(0, first->next);
CHECK_EQUAL(sizeof(mbedtls_memory_buffer) - 8, first->size);
}
TEST(sm_mbedtls_allocator_test, alloc1){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
CHECK_EQUAL(8 + sizeof(void*), offset_for_buffer(buffer1));
}
TEST(sm_mbedtls_allocator_test, alloc_free){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
sm_mbedtls_allocator_free(buffer1);
sm_allocator_node_t * anchor = (sm_allocator_node_t*) mbedtls_memory_buffer;
sm_allocator_node_t * first = (sm_allocator_node_t*) &mbedtls_memory_buffer[8];
CHECK_EQUAL(8, anchor->next);
CHECK_EQUAL(0, anchor->size);
CHECK_EQUAL(0, first->next);
CHECK_EQUAL(sizeof(mbedtls_memory_buffer) - 8, first->size);
}
TEST(sm_mbedtls_allocator_test, alloc2){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(1,8);
CHECK_EQUAL(8 + sizeof(void*) + 8 + sizeof(void*), offset_for_buffer(buffer2));
}
TEST(sm_mbedtls_allocator_test, alloc_free_2){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(1,8);
sm_mbedtls_allocator_free(buffer1);
sm_mbedtls_allocator_free(buffer2);
sm_allocator_node_t * anchor = (sm_allocator_node_t*) mbedtls_memory_buffer;
sm_allocator_node_t * first = (sm_allocator_node_t*) &mbedtls_memory_buffer[8];
CHECK_EQUAL(8, anchor->next);
CHECK_EQUAL(0, anchor->size);
CHECK_EQUAL(0, first->next);
CHECK_EQUAL(sizeof(mbedtls_memory_buffer) - 8, first->size);
}
TEST(sm_mbedtls_allocator_test, alloc_free_3){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(1,8);
sm_mbedtls_allocator_free(buffer2);
sm_mbedtls_allocator_free(buffer1);
sm_allocator_node_t * anchor = (sm_allocator_node_t*) mbedtls_memory_buffer;
CHECK_EQUAL(8, anchor->next);
CHECK_EQUAL(0, anchor->size);
}
TEST(sm_mbedtls_allocator_test, alloc_alloc_free_alloc_1){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(1,8);
sm_mbedtls_allocator_free(buffer1);
buffer1 = sm_mbedtls_allocator_calloc(1,8);
CHECK_EQUAL(8 + sizeof(void*), offset_for_buffer(buffer1));
}
TEST(sm_mbedtls_allocator_test, alloc_alloc_free_alloc_2){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(1,8);
sm_mbedtls_allocator_free(buffer2);
buffer2 = sm_mbedtls_allocator_calloc(1,8);
CHECK_EQUAL(8 + sizeof(void*) + 8 + sizeof(void*), offset_for_buffer(buffer2));
}
TEST(sm_mbedtls_allocator_test, alloc_alloc_alloc_free_free_free_1){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(2,8);
void * buffer3 = sm_mbedtls_allocator_calloc(3,8);
sm_mbedtls_allocator_free(buffer1);
sm_mbedtls_allocator_free(buffer2);
sm_mbedtls_allocator_free(buffer3);
sm_allocator_node_t * anchor = (sm_allocator_node_t*) mbedtls_memory_buffer;
sm_allocator_node_t * first = (sm_allocator_node_t*) &mbedtls_memory_buffer[8];
CHECK_EQUAL(8, anchor->next);
CHECK_EQUAL(0, anchor->size);
CHECK_EQUAL(0, first->next);
CHECK_EQUAL(sizeof(mbedtls_memory_buffer) - 8, first->size);
}
TEST(sm_mbedtls_allocator_test, alloc_alloc_alloc_free_alloc_1){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(2,8);
void * buffer3 = sm_mbedtls_allocator_calloc(3,8);
sm_mbedtls_allocator_free(buffer1);
buffer1 = sm_mbedtls_allocator_calloc(1,8);
CHECK_EQUAL(8 + sizeof(void*), offset_for_buffer(buffer1));
}
TEST(sm_mbedtls_allocator_test, alloc_alloc_alloc_free_alloc_2){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(2,8);
void * buffer3 = sm_mbedtls_allocator_calloc(3,8);
sm_mbedtls_allocator_free(buffer2);
buffer2 = sm_mbedtls_allocator_calloc(1,8);
CHECK_EQUAL(8 + 2 * sizeof(void*) + 8, offset_for_buffer(buffer2));
}
TEST(sm_mbedtls_allocator_test, alloc_alloc_alloc_free_alloc_3){
sm_mbedtls_allocator_init(mbedtls_memory_buffer, sizeof(mbedtls_memory_buffer));
void * buffer1 = sm_mbedtls_allocator_calloc(1,8);
void * buffer2 = sm_mbedtls_allocator_calloc(2,8);
void * buffer3 = sm_mbedtls_allocator_calloc(3,8);
sm_mbedtls_allocator_free(buffer3);
buffer3 = sm_mbedtls_allocator_calloc(1,8);
CHECK_EQUAL(8 + 3 * sizeof(void*) + 8 + 16, offset_for_buffer(buffer3));
}
int main (int argc, const char * argv[]){
return CommandLineTestRunner::RunAllTests(argc, argv);
}

16
tool/state_enums.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
BTSTACK_ROOT=`dirname $0`'/..'
# SM
echo "Security Manager states"
grep SM_ $BTSTACK_ROOT/src/hci.h | nl -v0
echo
# RFCOMM
echo "RFCOMM Multiplexer states"
grep RFCOMM_MULTIPLEXER_ $BTSTACK_ROOT/src/classic/rfcomm.h | grep -v RFCOMM_MULTIPLEXER_EVENT | grep -v RFCOMM_MULTIPLEXER_STATE | nl
echo "RFCOMM Channel states"
grep RFCOMM_CHANNEL_ $BTSTACK_ROOT/src/classic/rfcomm.h | grep -v RFCOMM_CHANNEL_STATE | grep -v "// state variables" | nl
echo