mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-24 01:47:22 +00:00
Merge pull request #72 from andrzej-kaczmarek/porting-wip
Porting NimBLE
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# Dummy NPL build
|
||||
*.o
|
||||
/porting/examples/dummy/dummy
|
||||
@@ -0,0 +1,15 @@
|
||||
Architect:
|
||||
Rafael Misoczki <[email protected]>
|
||||
|
||||
Open Source Maintainer:
|
||||
Constanza Heath <[email protected]>
|
||||
Rafael Misoczki <[email protected]>
|
||||
|
||||
Contributors:
|
||||
Constanza Heath <[email protected]>
|
||||
Rafael Misoczki <[email protected]>
|
||||
Flavio Santes <[email protected]>
|
||||
Jarkko Sakkinen <[email protected]>
|
||||
Chris Morrison
|
||||
Marti Bolivar
|
||||
Colin Ian King
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
================================================================================
|
||||
|
||||
TinyCrypt Cryptographic Library
|
||||
|
||||
================================================================================
|
||||
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Intel Corporation nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
================================================================================
|
||||
Copyright (c) 2014, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
https://github.com/kmackay/micro-ecc
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
================================================================================
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
================================================================================
|
||||
|
||||
TinyCrypt Cryptographic Library
|
||||
|
||||
================================================================================
|
||||
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Intel Corporation nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
================================================================================
|
||||
|
||||
Overview:
|
||||
|
||||
The TinyCrypt Library provides an implementation for constrained devices of a
|
||||
minimal set of standard cryptography primitives.
|
||||
|
||||
Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported
|
||||
cryptographic primitives and the limitations of TinyCrypt library. For usage,
|
||||
security and technicalities, please see the corresponding header file of each
|
||||
cryptographic primitive.
|
||||
|
||||
================================================================================
|
||||
|
||||
Organization:
|
||||
|
||||
/lib: C source code of the cryptographic primitives.
|
||||
/lib/include/tinycrypt: C header files of the cryptographic primitives.
|
||||
/tests: Test vectors of the cryptographic primitives.
|
||||
/doc: Documentation of TinyCrypt.
|
||||
|
||||
================================================================================
|
||||
|
||||
Building:
|
||||
|
||||
1) In Makefile.conf set:
|
||||
- CFLAGS for compiler flags.
|
||||
- CC for compiler.
|
||||
- ENABLE_TESTS for enabling (true) or disabling (false) tests compilation.
|
||||
2) In lib/Makefile select the primitives required by your project.
|
||||
3) In tests/Makefile select the corresponding tests of the selected primitives.
|
||||
4) make
|
||||
5) run tests in tests/
|
||||
|
||||
================================================================================
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
0.2.8
|
||||
@@ -0,0 +1,352 @@
|
||||
|
||||
TinyCrypt Cryptographic Library
|
||||
###############################
|
||||
Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
|
||||
Overview
|
||||
********
|
||||
The TinyCrypt Library provides an implementation for targeting constrained devices
|
||||
with a minimal set of standard cryptography primitives, as listed below. To better
|
||||
serve applications targeting constrained devices, TinyCrypt implementations differ
|
||||
from the standard specifications (see the Important Remarks section for some
|
||||
important differences). Certain cryptographic primitives depend on other
|
||||
primitives, as mentioned in the list below.
|
||||
|
||||
Aside from the Important Remarks section below, valuable information on the usage,
|
||||
security and technicalities of each cryptographic primitive are found in the
|
||||
corresponding header file.
|
||||
|
||||
* SHA-256:
|
||||
|
||||
* Type of primitive: Hash function.
|
||||
* Standard Specification: NIST FIPS PUB 180-4.
|
||||
* Requires: --
|
||||
|
||||
* HMAC-SHA256:
|
||||
|
||||
* Type of primitive: Message authentication code.
|
||||
* Standard Specification: RFC 2104.
|
||||
* Requires: SHA-256
|
||||
|
||||
* HMAC-PRNG:
|
||||
|
||||
* Type of primitive: Pseudo-random number generator (256-bit strength).
|
||||
* Standard Specification: NIST SP 800-90A.
|
||||
* Requires: SHA-256 and HMAC-SHA256.
|
||||
|
||||
* AES-128:
|
||||
|
||||
* Type of primitive: Block cipher.
|
||||
* Standard Specification: NIST FIPS PUB 197.
|
||||
* Requires: --
|
||||
|
||||
* AES-CBC mode:
|
||||
|
||||
* Type of primitive: Encryption mode of operation.
|
||||
* Standard Specification: NIST SP 800-38A.
|
||||
* Requires: AES-128.
|
||||
|
||||
* AES-CTR mode:
|
||||
|
||||
* Type of primitive: Encryption mode of operation.
|
||||
* Standard Specification: NIST SP 800-38A.
|
||||
* Requires: AES-128.
|
||||
|
||||
* AES-CMAC mode:
|
||||
|
||||
* Type of primitive: Message authentication code.
|
||||
* Standard Specification: NIST SP 800-38B.
|
||||
* Requires: AES-128.
|
||||
|
||||
* AES-CCM mode:
|
||||
|
||||
* Type of primitive: Authenticated encryption.
|
||||
* Standard Specification: NIST SP 800-38C.
|
||||
* Requires: AES-128.
|
||||
|
||||
* CTR-PRNG:
|
||||
|
||||
* Type of primitive: Pseudo-random number generator (128-bit strength).
|
||||
* Standard Specification: NIST SP 800-90A.
|
||||
* Requires: AES-128.
|
||||
|
||||
* ECC-DH:
|
||||
|
||||
* Type of primitive: Key exchange based on curve NIST p-256.
|
||||
* Standard Specification: RFC 6090.
|
||||
* Requires: ECC auxiliary functions (ecc.h/c).
|
||||
|
||||
* ECC-DSA:
|
||||
|
||||
* Type of primitive: Digital signature based on curve NIST p-256.
|
||||
* Standard Specification: RFC 6090.
|
||||
* Requires: ECC auxiliary functions (ecc.h/c).
|
||||
|
||||
Design Goals
|
||||
************
|
||||
|
||||
* Minimize the code size of each cryptographic primitive. This means minimize
|
||||
the size of a platform-independent implementation, as presented in TinyCrypt.
|
||||
Note that various applications may require further features, optimizations with
|
||||
respect to other metrics and countermeasures for particular threats. These
|
||||
peculiarities would increase the code size and thus are not considered here.
|
||||
|
||||
* Minimize the dependencies among the cryptographic primitives. This means
|
||||
that it is unnecessary to build and allocate object code for more primitives
|
||||
than the ones strictly required by the intended application. In other words,
|
||||
one can select and compile only the primitives required by the application.
|
||||
|
||||
|
||||
Important Remarks
|
||||
*****************
|
||||
|
||||
The cryptographic implementations in TinyCrypt library have some limitations.
|
||||
Some of these limitations are inherent to the cryptographic primitives
|
||||
themselves, while others are specific to TinyCrypt. These limitations were accepted
|
||||
in order to meet its design goals (in special, minimal code size) and to better
|
||||
serve applications targeting constrained devices in general. Some of these
|
||||
limitations are discussed in-depth below.
|
||||
|
||||
General Remarks
|
||||
***************
|
||||
|
||||
* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the
|
||||
variety of side-channel attacks, many of them only relevant to certain
|
||||
platforms. In this sense, instead of penalizing all library users with
|
||||
side-channel countermeasures such as increasing the overall code size,
|
||||
TinyCrypt only implements certain generic timing-attack countermeasures.
|
||||
|
||||
Specific Remarks
|
||||
****************
|
||||
|
||||
* SHA-256:
|
||||
|
||||
* The number of bits_hashed in the state is not checked for overflow. Note
|
||||
however that this will only be a problem if you intend to hash more than
|
||||
2^64 bits, which is an extremely large window.
|
||||
|
||||
* HMAC:
|
||||
|
||||
* The HMAC verification process is assumed to be performed by the application.
|
||||
This compares the computed tag with some given tag.
|
||||
Note that conventional memory-comparison methods (such as memcmp function)
|
||||
might be vulnerable to timing attacks; thus be sure to use a constant-time
|
||||
memory comparison function (such as compare_constant_time
|
||||
function provided in lib/utils.c).
|
||||
|
||||
* The tc_hmac_final function, responsible for computing the message tag,
|
||||
cleans the state context before exiting. Thus, applications do not need to
|
||||
clean the TCHmacState_t ctx after calling tc_hmac_final. This should not
|
||||
be changed in future versions of the library as there are applications
|
||||
currently relying on this good-practice/feature of TinyCrypt.
|
||||
|
||||
* HMAC-PRNG:
|
||||
|
||||
* Before using HMAC-PRNG, you *must* find an entropy source to produce a seed.
|
||||
PRNGs only stretch the seed into a seemingly random output of arbitrary
|
||||
length. The security of the output is exactly equal to the
|
||||
unpredictability of the seed.
|
||||
|
||||
* NIST SP 800-90A requires three items as seed material in the initialization
|
||||
step: entropy seed, personalization and a nonce (which is not implemented).
|
||||
TinyCrypt requires the personalization byte array and automatically creates
|
||||
the entropy seed using a mandatory call to the re-seed function.
|
||||
|
||||
* AES-128:
|
||||
|
||||
* The current implementation does not support other key-lengths (such as 256
|
||||
bits). Note that if you need AES-256, it doesn't sound as though your
|
||||
application is running in a constrained environment. AES-256 requires keys
|
||||
twice the size as for AES-128, and the key schedule is 40% larger.
|
||||
|
||||
* CTR mode:
|
||||
|
||||
* The AES-CTR mode limits the size of a data message they encrypt to 2^32
|
||||
blocks. If you need to encrypt larger data sets, your application would
|
||||
need to replace the key after 2^32 block encryptions.
|
||||
|
||||
* CTR-PRNG:
|
||||
|
||||
* Before using CTR-PRNG, you *must* find an entropy source to produce a seed.
|
||||
PRNGs only stretch the seed into a seemingly random output of arbitrary
|
||||
length. The security of the output is exactly equal to the
|
||||
unpredictability of the seed.
|
||||
|
||||
* CBC mode:
|
||||
|
||||
* TinyCrypt CBC decryption assumes that the iv and the ciphertext are
|
||||
contiguous (as produced by TinyCrypt CBC encryption). This allows for a
|
||||
very efficient decryption algorithm that would not otherwise be possible.
|
||||
|
||||
* CMAC mode:
|
||||
|
||||
* AES128-CMAC mode of operation offers 64 bits of security against collision
|
||||
attacks. Note however that an external attacker cannot generate the tags
|
||||
him/herself without knowing the MAC key. In this sense, to attack the
|
||||
collision property of AES128-CMAC, an external attacker would need the
|
||||
cooperation of the legal user to produce an exponentially high number of
|
||||
tags (e.g. 2^64) to finally be able to look for collisions and benefit
|
||||
from them. As an extra precaution, the current implementation allows to at
|
||||
most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup
|
||||
(allowing a new key to be set), as suggested in Appendix B of SP 800-38B.
|
||||
|
||||
* CCM mode:
|
||||
|
||||
* There are a few tradeoffs for the selection of the parameters of CCM mode.
|
||||
In special, there is a tradeoff between the maximum number of invocations
|
||||
of CCM under a given key and the maximum payload length for those
|
||||
invocations. Both things are related to the parameter 'q' of CCM mode. The
|
||||
maximum number of invocations of CCM under a given key is determined by
|
||||
the nonce size, which is: 15-q bytes. The maximum payload length for those
|
||||
invocations is defined as 2^(8q) bytes.
|
||||
|
||||
To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2,
|
||||
which is a quite reasonable choice for constrained applications. The
|
||||
implications of this choice are:
|
||||
|
||||
The nonce size is: 13 bytes.
|
||||
|
||||
The maximum payload length is: 2^16 bytes = 65 KB.
|
||||
|
||||
The mac size parameter is an important parameter to estimate the security
|
||||
against collision attacks (that aim at finding different messages that
|
||||
produce the same authentication tag). TinyCrypt CCM implementation
|
||||
accepts any even integer between 4 and 16, as suggested in SP 800-38C.
|
||||
|
||||
* TinyCrypt CCM implementation accepts associated data of any length between
|
||||
0 and (2^16 - 2^8) = 65280 bytes.
|
||||
|
||||
* TinyCrypt CCM implementation accepts:
|
||||
|
||||
* Both non-empty payload and associated data (it encrypts and
|
||||
authenticates the payload and only authenticates the associated data);
|
||||
|
||||
* Non-empty payload and empty associated data (it encrypts and
|
||||
authenticates the payload);
|
||||
|
||||
* Non-empty associated data and empty payload (it degenerates to an
|
||||
authentication-only mode on the associated data).
|
||||
|
||||
* RFC-3610, which also specifies CCM, presents a few relevant security
|
||||
suggestions, such as: it is recommended for most applications to use a
|
||||
mac size greater than 8. Besides, it is emphasized that the usage of the
|
||||
same nonce for two different messages which are encrypted with the same
|
||||
key obviously destroys the security properties of CCM mode.
|
||||
|
||||
* ECC-DH and ECC-DSA:
|
||||
|
||||
* TinyCrypt ECC implementation is based on micro-ecc (see
|
||||
https://github.com/kmackay/micro-ecc). In the original micro-ecc
|
||||
documentation, there is an important remark about the way integers are
|
||||
represented:
|
||||
|
||||
"Integer representation: To reduce code size, all large integers are
|
||||
represented using little-endian words - so the least significant word is
|
||||
first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()'
|
||||
functions to convert between the native integer representation and the
|
||||
standardized octet representation."
|
||||
|
||||
Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32},
|
||||
{95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli)
|
||||
consisting of 4 unsigned integers (as an example).
|
||||
|
||||
* A cryptographically-secure PRNG function must be set (using uECC_set_rng())
|
||||
before calling uECC_make_key() or uECC_sign().
|
||||
|
||||
Examples of Applications
|
||||
************************
|
||||
It is possible to do useful cryptography with only the given small set of
|
||||
primitives. With this list of primitives it becomes feasible to support a range
|
||||
of cryptography usages:
|
||||
|
||||
* Measurement of code, data structures, and other digital artifacts (SHA256);
|
||||
|
||||
* Generate commitments (SHA256);
|
||||
|
||||
* Construct keys (HMAC-SHA256);
|
||||
|
||||
* Extract entropy from strings containing some randomness (HMAC-SHA256);
|
||||
|
||||
* Construct random mappings (HMAC-SHA256);
|
||||
|
||||
* Construct nonces and challenges (HMAC-PRNG, CTR-PRNG);
|
||||
|
||||
* Authenticate using a shared secret (HMAC-SHA256);
|
||||
|
||||
* Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG);
|
||||
|
||||
* Authenticated encryption (AES-128 + AES-CCM);
|
||||
|
||||
* Key-exchange (EC-DH);
|
||||
|
||||
* Digital signature (EC-DSA);
|
||||
|
||||
Test Vectors
|
||||
************
|
||||
|
||||
The library provides a test program for each cryptographic primitive (see 'test'
|
||||
folder). Besides illustrating how to use the primitives, these tests evaluate
|
||||
the correctness of the implementations by checking the results against
|
||||
well-known publicly validated test vectors.
|
||||
|
||||
For the case of the HMAC-PRNG, due to the necessity of performing an extensive
|
||||
battery test to produce meaningful conclusions, we suggest the user to evaluate
|
||||
the unpredictability of the implementation by using the NIST Statistical Test
|
||||
Suite (see References).
|
||||
|
||||
For the case of the EC-DH and EC-DSA implementations, most of the test vectors
|
||||
were obtained from the site of the NIST Cryptographic Algorithm Validation
|
||||
Program (CAVP), see References.
|
||||
|
||||
References
|
||||
**********
|
||||
|
||||
* `NIST FIPS PUB 180-4 (SHA-256)`_
|
||||
|
||||
.. _NIST FIPS PUB 180-4 (SHA-256):
|
||||
http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
|
||||
|
||||
* `NIST FIPS PUB 197 (AES-128)`_
|
||||
|
||||
.. _NIST FIPS PUB 197 (AES-128):
|
||||
http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
|
||||
* `NIST SP800-90A (HMAC-PRNG)`_
|
||||
|
||||
.. _NIST SP800-90A (HMAC-PRNG):
|
||||
http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
|
||||
|
||||
* `NIST SP 800-38A (AES-CBC and AES-CTR)`_
|
||||
|
||||
.. _NIST SP 800-38A (AES-CBC and AES-CTR):
|
||||
http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
|
||||
* `NIST SP 800-38B (AES-CMAC)`_
|
||||
|
||||
.. _NIST SP 800-38B (AES-CMAC):
|
||||
http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
|
||||
|
||||
* `NIST SP 800-38C (AES-CCM)`_
|
||||
|
||||
.. _NIST SP 800-38C (AES-CCM):
|
||||
http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
|
||||
|
||||
* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_
|
||||
|
||||
.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG):
|
||||
http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html
|
||||
|
||||
* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_
|
||||
|
||||
.. _NIST Cryptographic Algorithm Validation Program (CAVP) site:
|
||||
http://csrc.nist.gov/groups/STM/cavp/
|
||||
|
||||
* `RFC 2104 (HMAC-SHA256)`_
|
||||
|
||||
.. _RFC 2104 (HMAC-SHA256):
|
||||
https://www.ietf.org/rfc/rfc2104.txt
|
||||
|
||||
* `RFC 6090 (ECC-DH and ECC-DSA)`_
|
||||
|
||||
.. _RFC 6090 (ECC-DH and ECC-DSA):
|
||||
https://www.ietf.org/rfc/rfc6090.txt
|
||||
@@ -0,0 +1,130 @@
|
||||
/* aes.h - TinyCrypt interface to an AES-128 implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to an AES-128 implementation.
|
||||
*
|
||||
* Overview: AES-128 is a NIST approved block cipher specified in
|
||||
* FIPS 197. Block ciphers are deterministic algorithms that
|
||||
* perform a transformation specified by a symmetric key in fixed-
|
||||
* length data sets, also called blocks.
|
||||
*
|
||||
* Security: AES-128 provides approximately 128 bits of security.
|
||||
*
|
||||
* Usage: 1) call tc_aes128_set_encrypt/decrypt_key to set the key.
|
||||
*
|
||||
* 2) call tc_aes_encrypt/decrypt to process the data.
|
||||
*/
|
||||
|
||||
#ifndef __TC_AES_H__
|
||||
#define __TC_AES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define Nb (4) /* number of columns (32-bit words) comprising the state */
|
||||
#define Nk (4) /* number of 32-bit words comprising the key */
|
||||
#define Nr (10) /* number of rounds */
|
||||
#define TC_AES_BLOCK_SIZE (Nb*Nk)
|
||||
#define TC_AES_KEY_SIZE (Nb*Nk)
|
||||
|
||||
typedef struct tc_aes_key_sched_struct {
|
||||
unsigned int words[Nb*(Nr+1)];
|
||||
} *TCAesKeySched_t;
|
||||
|
||||
/**
|
||||
* @brief Set AES-128 encryption key
|
||||
* Uses key k to initialize s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
|
||||
* @note This implementation skips the additional steps required for keys
|
||||
* larger than 128 bits, and must not be used for AES-192 or
|
||||
* AES-256 key schedule -- see FIPS 197 for details
|
||||
* @param s IN/OUT -- initialized struct tc_aes_key_sched_struct
|
||||
* @param k IN -- points to the AES key
|
||||
*/
|
||||
int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k);
|
||||
|
||||
/**
|
||||
* @brief AES-128 Encryption procedure
|
||||
* Encrypts contents of in buffer into out buffer under key;
|
||||
* schedule s
|
||||
* @note Assumes s was initialized by aes_set_encrypt_key;
|
||||
* out and in point to 16 byte buffers
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL
|
||||
* @param out IN/OUT -- buffer to receive ciphertext block
|
||||
* @param in IN -- a plaintext block to encrypt
|
||||
* @param s IN -- initialized AES key schedule
|
||||
*/
|
||||
int tc_aes_encrypt(uint8_t *out, const uint8_t *in,
|
||||
const TCAesKeySched_t s);
|
||||
|
||||
/**
|
||||
* @brief Set the AES-128 decryption key
|
||||
* Uses key k to initialize s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
|
||||
* @note This is the implementation of the straightforward inverse cipher
|
||||
* using the cipher documented in FIPS-197 figure 12, not the
|
||||
* equivalent inverse cipher presented in Figure 15
|
||||
* @warning This routine skips the additional steps required for keys larger
|
||||
* than 128, and must not be used for AES-192 or AES-256 key
|
||||
* schedule -- see FIPS 197 for details
|
||||
* @param s IN/OUT -- initialized struct tc_aes_key_sched_struct
|
||||
* @param k IN -- points to the AES key
|
||||
*/
|
||||
int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k);
|
||||
|
||||
/**
|
||||
* @brief AES-128 Encryption procedure
|
||||
* Decrypts in buffer into out buffer under key schedule s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL
|
||||
* @note Assumes s was initialized by aes_set_encrypt_key
|
||||
* out and in point to 16 byte buffers
|
||||
* @param out IN/OUT -- buffer to receive ciphertext block
|
||||
* @param in IN -- a plaintext block to encrypt
|
||||
* @param s IN -- initialized AES key schedule
|
||||
*/
|
||||
int tc_aes_decrypt(uint8_t *out, const uint8_t *in,
|
||||
const TCAesKeySched_t s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_AES_H__ */
|
||||
@@ -0,0 +1,151 @@
|
||||
/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a CBC mode implementation.
|
||||
*
|
||||
* Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of
|
||||
* operation defined in SP 800-38a. It can be used with any block
|
||||
* cipher to provide confidentiality of strings whose lengths are
|
||||
* multiples of the block_size of the underlying block cipher.
|
||||
* TinyCrypt hard codes AES as the block cipher.
|
||||
*
|
||||
* Security: CBC mode provides data confidentiality given that the maximum
|
||||
* number q of blocks encrypted under a single key satisfies
|
||||
* q < 2^63, which is not a practical constraint (it is considered a
|
||||
* good practice to replace the encryption when q == 2^56). CBC mode
|
||||
* provides NO data integrity.
|
||||
*
|
||||
* CBC mode assumes that the IV value input into the
|
||||
* tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library
|
||||
* provides HMAC-PRNG module, which generates suitable IVs. Other
|
||||
* methods for generating IVs are acceptable, provided that the
|
||||
* values of the IVs generated appear random to any adversary,
|
||||
* including someone with complete knowledge of the system design.
|
||||
*
|
||||
* The randomness property on which CBC mode's security depends is
|
||||
* the unpredictability of the IV. Since it is unpredictable, this
|
||||
* means in practice that CBC mode requires that the IV is stored
|
||||
* somehow with the ciphertext in order to recover the plaintext.
|
||||
*
|
||||
* TinyCrypt CBC encryption prepends the IV to the ciphertext,
|
||||
* because this affords a more efficient (few buffers) decryption.
|
||||
* Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always
|
||||
* 16 bytes larger than the plaintext buffer.
|
||||
*
|
||||
* Requires: AES-128
|
||||
*
|
||||
* Usage: 1) call tc_cbc_mode_encrypt to encrypt data.
|
||||
*
|
||||
* 2) call tc_cbc_mode_decrypt to decrypt data.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_CBC_MODE_H__
|
||||
#define __TC_CBC_MODE_H__
|
||||
|
||||
#include <tinycrypt/aes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CBC encryption procedure
|
||||
* CBC encrypts inlen bytes of the in buffer into the out buffer
|
||||
* using the encryption key schedule provided, prepends iv to out
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* in == NULL or
|
||||
* ctr == NULL or
|
||||
* sched == NULL or
|
||||
* inlen == 0 or
|
||||
* (inlen % TC_AES_BLOCK_SIZE) != 0 or
|
||||
* (outlen % TC_AES_BLOCK_SIZE) != 0 or
|
||||
* outlen != inlen + TC_AES_BLOCK_SIZE
|
||||
* @note Assumes: - sched has been configured by aes_set_encrypt_key
|
||||
* - iv contains a 16 byte random string
|
||||
* - out buffer is large enough to hold the ciphertext + iv
|
||||
* - out buffer is a contiguous buffer
|
||||
* - in holds the plaintext and is a contiguous buffer
|
||||
* - inlen gives the number of bytes in the in buffer
|
||||
* @param out IN/OUT -- buffer to receive the ciphertext
|
||||
* @param outlen IN -- length of ciphertext buffer in bytes
|
||||
* @param in IN -- plaintext to encrypt
|
||||
* @param inlen IN -- length of plaintext buffer in bytes
|
||||
* @param iv IN -- the IV for the this encrypt/decrypt
|
||||
* @param sched IN -- AES key schedule for this encrypt
|
||||
*/
|
||||
int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, const uint8_t *iv,
|
||||
const TCAesKeySched_t sched);
|
||||
|
||||
/**
|
||||
* @brief CBC decryption procedure
|
||||
* CBC decrypts inlen bytes of the in buffer into the out buffer
|
||||
* using the provided encryption key schedule
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* in == NULL or
|
||||
* sched == NULL or
|
||||
* inlen == 0 or
|
||||
* outlen == 0 or
|
||||
* (inlen % TC_AES_BLOCK_SIZE) != 0 or
|
||||
* (outlen % TC_AES_BLOCK_SIZE) != 0 or
|
||||
* outlen != inlen + TC_AES_BLOCK_SIZE
|
||||
* @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are
|
||||
* contiguous. This allows for a very efficient decryption
|
||||
* algorithm that would not otherwise be possible
|
||||
* - sched was configured by aes_set_decrypt_key
|
||||
* - out buffer is large enough to hold the decrypted plaintext
|
||||
* and is a contiguous buffer
|
||||
* - inlen gives the number of bytes in the in buffer
|
||||
* @param out IN/OUT -- buffer to receive decrypted data
|
||||
* @param outlen IN -- length of plaintext buffer in bytes
|
||||
* @param in IN -- ciphertext to decrypt, including IV
|
||||
* @param inlen IN -- length of ciphertext buffer in bytes
|
||||
* @param iv IN -- the IV for the this encrypt/decrypt
|
||||
* @param sched IN -- AES key schedule for this decrypt
|
||||
*
|
||||
*/
|
||||
int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, const uint8_t *iv,
|
||||
const TCAesKeySched_t sched);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CBC_MODE_H__ */
|
||||
@@ -0,0 +1,211 @@
|
||||
/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a CCM mode implementation.
|
||||
*
|
||||
* Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of
|
||||
* operation defined in SP 800-38C.
|
||||
*
|
||||
* TinyCrypt CCM implementation accepts:
|
||||
*
|
||||
* 1) Both non-empty payload and associated data (it encrypts and
|
||||
* authenticates the payload and also authenticates the associated
|
||||
* data);
|
||||
* 2) Non-empty payload and empty associated data (it encrypts and
|
||||
* authenticates the payload);
|
||||
* 3) Non-empty associated data and empty payload (it degenerates to
|
||||
* an authentication mode on the associated data).
|
||||
*
|
||||
* TinyCrypt CCM implementation accepts associated data of any length
|
||||
* between 0 and (2^16 - 2^8) bytes.
|
||||
*
|
||||
* Security: The mac length parameter is an important parameter to estimate the
|
||||
* security against collision attacks (that aim at finding different
|
||||
* messages that produce the same authentication tag). TinyCrypt CCM
|
||||
* implementation accepts any even integer between 4 and 16, as
|
||||
* suggested in SP 800-38C.
|
||||
*
|
||||
* RFC-3610, which also specifies CCM, presents a few relevant
|
||||
* security suggestions, such as: it is recommended for most
|
||||
* applications to use a mac length greater than 8. Besides, the
|
||||
* usage of the same nonce for two different messages which are
|
||||
* encrypted with the same key destroys the security of CCM mode.
|
||||
*
|
||||
* Requires: AES-128
|
||||
*
|
||||
* Usage: 1) call tc_ccm_config to configure.
|
||||
*
|
||||
* 2) call tc_ccm_mode_encrypt to encrypt data and generate tag.
|
||||
*
|
||||
* 3) call tc_ccm_mode_decrypt to decrypt data and verify tag.
|
||||
*/
|
||||
|
||||
#ifndef __TC_CCM_MODE_H__
|
||||
#define __TC_CCM_MODE_H__
|
||||
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */
|
||||
#define TC_CCM_AAD_MAX_BYTES 0xff00
|
||||
|
||||
/* max message size in bytes: 2^(8L) = 2^16 = 65536 */
|
||||
#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000
|
||||
|
||||
/* struct tc_ccm_mode_struct represents the state of a CCM computation */
|
||||
typedef struct tc_ccm_mode_struct {
|
||||
TCAesKeySched_t sched; /* AES key schedule */
|
||||
uint8_t *nonce; /* nonce required by CCM */
|
||||
unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */
|
||||
} *TCCcmMode_t;
|
||||
|
||||
/**
|
||||
* @brief CCM configuration procedure
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* c == NULL or
|
||||
* sched == NULL or
|
||||
* nonce == NULL or
|
||||
* mlen != {4, 6, 8, 10, 12, 16}
|
||||
* @param c -- CCM state
|
||||
* @param sched IN -- AES key schedule
|
||||
* @param nonce IN - nonce
|
||||
* @param nlen -- nonce length in bytes
|
||||
* @param mlen -- mac length in bytes (parameter t in SP-800 38C)
|
||||
*/
|
||||
int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
|
||||
unsigned int nlen, unsigned int mlen);
|
||||
|
||||
/**
|
||||
* @brief CCM tag generation and encryption procedure
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* c == NULL or
|
||||
* ((plen > 0) and (payload == NULL)) or
|
||||
* ((alen > 0) and (associated_data == NULL)) or
|
||||
* (alen >= TC_CCM_AAD_MAX_BYTES) or
|
||||
* (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
|
||||
* (olen < plen + maclength)
|
||||
*
|
||||
* @param out OUT -- encrypted data
|
||||
* @param olen IN -- output length in bytes
|
||||
* @param associated_data IN -- associated data
|
||||
* @param alen IN -- associated data length in bytes
|
||||
* @param payload IN -- payload
|
||||
* @param plen IN -- payload length in bytes
|
||||
* @param c IN -- CCM state
|
||||
*
|
||||
* @note: out buffer should be at least (plen + c->mlen) bytes long.
|
||||
*
|
||||
* @note: The sequence b for encryption is formatted as follows:
|
||||
* b = [FLAGS | nonce | counter ], where:
|
||||
* FLAGS is 1 byte long
|
||||
* nonce is 13 bytes long
|
||||
* counter is 2 bytes long
|
||||
* The byte FLAGS is composed by the following 8 bits:
|
||||
* 0-2 bits: used to represent the value of q-1
|
||||
* 3-7 btis: always 0's
|
||||
*
|
||||
* @note: The sequence b for authentication is formatted as follows:
|
||||
* b = [FLAGS | nonce | length(mac length)], where:
|
||||
* FLAGS is 1 byte long
|
||||
* nonce is 13 bytes long
|
||||
* length(mac length) is 2 bytes long
|
||||
* The byte FLAGS is composed by the following 8 bits:
|
||||
* 0-2 bits: used to represent the value of q-1
|
||||
* 3-5 bits: mac length (encoded as: (mlen-2)/2)
|
||||
* 6: Adata (0 if alen == 0, and 1 otherwise)
|
||||
* 7: always 0
|
||||
*/
|
||||
int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
|
||||
const uint8_t *associated_data,
|
||||
unsigned int alen, const uint8_t *payload,
|
||||
unsigned int plen, TCCcmMode_t c);
|
||||
|
||||
/**
|
||||
* @brief CCM decryption and tag verification procedure
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* c == NULL or
|
||||
* ((plen > 0) and (payload == NULL)) or
|
||||
* ((alen > 0) and (associated_data == NULL)) or
|
||||
* (alen >= TC_CCM_AAD_MAX_BYTES) or
|
||||
* (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
|
||||
* (olen < plen - c->mlen)
|
||||
*
|
||||
* @param out OUT -- decrypted data
|
||||
* @param associated_data IN -- associated data
|
||||
* @param alen IN -- associated data length in bytes
|
||||
* @param payload IN -- payload
|
||||
* @param plen IN -- payload length in bytes
|
||||
* @param c IN -- CCM state
|
||||
*
|
||||
* @note: out buffer should be at least (plen - c->mlen) bytes long.
|
||||
*
|
||||
* @note: The sequence b for encryption is formatted as follows:
|
||||
* b = [FLAGS | nonce | counter ], where:
|
||||
* FLAGS is 1 byte long
|
||||
* nonce is 13 bytes long
|
||||
* counter is 2 bytes long
|
||||
* The byte FLAGS is composed by the following 8 bits:
|
||||
* 0-2 bits: used to represent the value of q-1
|
||||
* 3-7 btis: always 0's
|
||||
*
|
||||
* @note: The sequence b for authentication is formatted as follows:
|
||||
* b = [FLAGS | nonce | length(mac length)], where:
|
||||
* FLAGS is 1 byte long
|
||||
* nonce is 13 bytes long
|
||||
* length(mac length) is 2 bytes long
|
||||
* The byte FLAGS is composed by the following 8 bits:
|
||||
* 0-2 bits: used to represent the value of q-1
|
||||
* 3-5 bits: mac length (encoded as: (mlen-2)/2)
|
||||
* 6: Adata (0 if alen == 0, and 1 otherwise)
|
||||
* 7: always 0
|
||||
*/
|
||||
int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
|
||||
const uint8_t *associated_data,
|
||||
unsigned int alen, const uint8_t *payload, unsigned int plen,
|
||||
TCCcmMode_t c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CCM_MODE_H__ */
|
||||
@@ -0,0 +1,194 @@
|
||||
/* cmac_mode.h -- interface to a CMAC implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a CMAC implementation.
|
||||
*
|
||||
* Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm
|
||||
* for computing a MAC using a block cipher. It can compute the MAC
|
||||
* for a byte string of any length. It is distinguished from CBC-MAC
|
||||
* in the processing of the final message block; CMAC uses a
|
||||
* different technique to compute the final message block is full
|
||||
* size or only partial, while CBC-MAC uses the same technique for
|
||||
* both. This difference permits CMAC to be applied to variable
|
||||
* length messages, while all messages authenticated by CBC-MAC must
|
||||
* be the same length.
|
||||
*
|
||||
* Security: AES128-CMAC mode of operation offers 64 bits of security against
|
||||
* collision attacks. Note however that an external attacker cannot
|
||||
* generate the tags him/herself without knowing the MAC key. In this
|
||||
* sense, to attack the collision property of AES128-CMAC, an
|
||||
* external attacker would need the cooperation of the legal user to
|
||||
* produce an exponentially high number of tags (e.g. 2^64) to
|
||||
* finally be able to look for collisions and benefit from them. As
|
||||
* an extra precaution, the current implementation allows to at most
|
||||
* 2^48 calls to the tc_cmac_update function before re-calling
|
||||
* tc_cmac_setup (allowing a new key to be set), as suggested in
|
||||
* Appendix B of SP 800-38B.
|
||||
*
|
||||
* Requires: AES-128
|
||||
*
|
||||
* Usage: This implementation provides a "scatter-gather" interface, so that
|
||||
* the CMAC value can be computed incrementally over a message
|
||||
* scattered in different segments throughout memory. Experience shows
|
||||
* this style of interface tends to minimize the burden of programming
|
||||
* correctly. Like all symmetric key operations, it is session
|
||||
* oriented.
|
||||
*
|
||||
* To begin a CMAC session, use tc_cmac_setup to initialize a struct
|
||||
* tc_cmac_struct with encryption key and buffer. Our implementation
|
||||
* always assume that the AES key to be the same size as the block
|
||||
* cipher block size. Once setup, this data structure can be used for
|
||||
* many CMAC computations.
|
||||
*
|
||||
* Once the state has been setup with a key, computing the CMAC of
|
||||
* some data requires three steps:
|
||||
*
|
||||
* (1) first use tc_cmac_init to initialize a new CMAC computation.
|
||||
* (2) next mix all of the data into the CMAC computation state using
|
||||
* tc_cmac_update. If all of the data resides in a single data
|
||||
* segment then only one tc_cmac_update call is needed; if data
|
||||
* is scattered throughout memory in n data segments, then n calls
|
||||
* will be needed. CMAC IS ORDER SENSITIVE, to be able to detect
|
||||
* attacks that swap bytes, so the order in which data is mixed
|
||||
* into the state is critical!
|
||||
* (3) Once all of the data for a message has been mixed, use
|
||||
* tc_cmac_final to compute the CMAC tag value.
|
||||
*
|
||||
* Steps (1)-(3) can be repeated as many times as you want to CMAC
|
||||
* multiple messages. A practical limit is 2^48 1K messages before you
|
||||
* have to change the key.
|
||||
*
|
||||
* Once you are done computing CMAC with a key, it is a good idea to
|
||||
* destroy the state so an attacker cannot recover the key; use
|
||||
* tc_cmac_erase to accomplish this.
|
||||
*/
|
||||
|
||||
#ifndef __TC_CMAC_MODE_H__
|
||||
#define __TC_CMAC_MODE_H__
|
||||
|
||||
#include <tinycrypt/aes.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* padding for last message block */
|
||||
#define TC_CMAC_PADDING 0x80
|
||||
|
||||
/* struct tc_cmac_struct represents the state of a CMAC computation */
|
||||
typedef struct tc_cmac_struct {
|
||||
/* initialization vector */
|
||||
uint8_t iv[TC_AES_BLOCK_SIZE];
|
||||
/* used if message length is a multiple of block_size bytes */
|
||||
uint8_t K1[TC_AES_BLOCK_SIZE];
|
||||
/* used if message length isn't a multiple block_size bytes */
|
||||
uint8_t K2[TC_AES_BLOCK_SIZE];
|
||||
/* where to put bytes that didn't fill a block */
|
||||
uint8_t leftover[TC_AES_BLOCK_SIZE];
|
||||
/* identifies the encryption key */
|
||||
unsigned int keyid;
|
||||
/* next available leftover location */
|
||||
unsigned int leftover_offset;
|
||||
/* AES key schedule */
|
||||
TCAesKeySched_t sched;
|
||||
/* calls to tc_cmac_update left before re-key */
|
||||
uint64_t countdown;
|
||||
} *TCCmacState_t;
|
||||
|
||||
/**
|
||||
* @brief Configures the CMAC state to use the given AES key
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL or
|
||||
* key == NULL
|
||||
*
|
||||
* @param s IN/OUT -- the state to set up
|
||||
* @param key IN -- the key to use
|
||||
* @param sched IN -- AES key schedule
|
||||
*/
|
||||
int tc_cmac_setup(TCCmacState_t s, const uint8_t *key,
|
||||
TCAesKeySched_t sched);
|
||||
|
||||
/**
|
||||
* @brief Erases the CMAC state
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL
|
||||
*
|
||||
* @param s IN/OUT -- the state to erase
|
||||
*/
|
||||
int tc_cmac_erase(TCCmacState_t s);
|
||||
|
||||
/**
|
||||
* @brief Initializes a new CMAC computation
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL
|
||||
*
|
||||
* @param s IN/OUT -- the state to initialize
|
||||
*/
|
||||
int tc_cmac_init(TCCmacState_t s);
|
||||
|
||||
/**
|
||||
* @brief Incrementally computes CMAC over the next data segment
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL or
|
||||
* if data == NULL when dlen > 0
|
||||
*
|
||||
* @param s IN/OUT -- the CMAC state
|
||||
* @param data IN -- the next data segment to MAC
|
||||
* @param dlen IN -- the length of data in bytes
|
||||
*/
|
||||
int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen);
|
||||
|
||||
/**
|
||||
* @brief Generates the tag from the CMAC state
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* tag == NULL or
|
||||
* s == NULL
|
||||
*
|
||||
* @param tag OUT -- the CMAC tag
|
||||
* @param s IN -- CMAC state
|
||||
*/
|
||||
int tc_cmac_final(uint8_t *tag, TCCmacState_t s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CMAC_MODE_H__ */
|
||||
@@ -0,0 +1,61 @@
|
||||
/* constants.h - TinyCrypt interface to constants */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to constants.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_CONSTANTS_H__
|
||||
#define __TC_CONSTANTS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#define TC_CRYPTO_SUCCESS 1
|
||||
#define TC_CRYPTO_FAIL 0
|
||||
|
||||
#define TC_ZERO_BYTE 0x00
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CONSTANTS_H__ */
|
||||
@@ -0,0 +1,108 @@
|
||||
/* ctr_mode.h - TinyCrypt interface to CTR mode */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to CTR mode.
|
||||
*
|
||||
* Overview: CTR (pronounced "counter") mode is a NIST approved mode of
|
||||
* operation defined in SP 800-38a. It can be used with any
|
||||
* block cipher to provide confidentiality of strings of any
|
||||
* length. TinyCrypt hard codes AES128 as the block cipher.
|
||||
*
|
||||
* Security: CTR mode achieves confidentiality only if the counter value is
|
||||
* never reused with a same encryption key. If the counter is
|
||||
* repeated, than an adversary might be able to defeat the scheme.
|
||||
*
|
||||
* A usual method to ensure different counter values refers to
|
||||
* initialize the counter in a given value (0, for example) and
|
||||
* increases it every time a new block is enciphered. This naturally
|
||||
* leaves to a limitation on the number q of blocks that can be
|
||||
* enciphered using a same key: q < 2^(counter size).
|
||||
*
|
||||
* TinyCrypt uses a counter of 32 bits. This means that after 2^32
|
||||
* block encryptions, the counter will be reused (thus losing CBC
|
||||
* security). 2^32 block encryptions should be enough for most of
|
||||
* applications targeting constrained devices. Applications intended
|
||||
* to encrypt a larger number of blocks must replace the key after
|
||||
* 2^32 block encryptions.
|
||||
*
|
||||
* CTR mode provides NO data integrity.
|
||||
*
|
||||
* Requires: AES-128
|
||||
*
|
||||
* Usage: 1) call tc_ctr_mode to process the data to encrypt/decrypt.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_CTR_MODE_H__
|
||||
#define __TC_CTR_MODE_H__
|
||||
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CTR mode encryption/decryption procedure.
|
||||
* CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* in == NULL or
|
||||
* ctr == NULL or
|
||||
* sched == NULL or
|
||||
* inlen == 0 or
|
||||
* outlen == 0 or
|
||||
* inlen != outlen
|
||||
* @note Assumes:- The current value in ctr has NOT been used with sched
|
||||
* - out points to inlen bytes
|
||||
* - in points to inlen bytes
|
||||
* - ctr is an integer counter in littleEndian format
|
||||
* - sched was initialized by aes_set_encrypt_key
|
||||
* @param out OUT -- produced ciphertext (plaintext)
|
||||
* @param outlen IN -- length of ciphertext buffer in bytes
|
||||
* @param in IN -- data to encrypt (or decrypt)
|
||||
* @param inlen IN -- length of input data in bytes
|
||||
* @param ctr IN/OUT -- the current counter value
|
||||
* @param sched IN -- an initialized AES key schedule
|
||||
*/
|
||||
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CTR_MODE_H__ */
|
||||
@@ -0,0 +1,166 @@
|
||||
/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016, Chris Morrison
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a CTR-PRNG implementation.
|
||||
*
|
||||
* Overview: A pseudo-random number generator (PRNG) generates a sequence
|
||||
* of numbers that have a distribution close to the one expected
|
||||
* for a sequence of truly random numbers. The NIST Special
|
||||
* Publication 800-90A specifies several mechanisms to generate
|
||||
* sequences of pseudo random numbers, including the CTR-PRNG one
|
||||
* which is based on AES. TinyCrypt implements CTR-PRNG with
|
||||
* AES-128.
|
||||
*
|
||||
* Security: A cryptographically secure PRNG depends on the existence of an
|
||||
* entropy source to provide a truly random seed as well as the
|
||||
* security of the primitives used as the building blocks (AES-128
|
||||
* in this instance).
|
||||
*
|
||||
* Requires: - AES-128
|
||||
*
|
||||
* Usage: 1) call tc_ctr_prng_init to seed the prng context
|
||||
*
|
||||
* 2) call tc_ctr_prng_reseed to mix in additional entropy into
|
||||
* the prng context
|
||||
*
|
||||
* 3) call tc_ctr_prng_generate to output the pseudo-random data
|
||||
*
|
||||
* 4) call tc_ctr_prng_uninstantiate to zero out the prng context
|
||||
*/
|
||||
|
||||
#ifndef __TC_CTR_PRNG_H__
|
||||
#define __TC_CTR_PRNG_H__
|
||||
|
||||
#include <tinycrypt/aes.h>
|
||||
|
||||
#define TC_CTR_PRNG_RESEED_REQ -1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/* updated each time another BLOCKLEN_BYTES bytes are produced */
|
||||
uint8_t V[TC_AES_BLOCK_SIZE];
|
||||
|
||||
/* updated whenever the PRNG is reseeded */
|
||||
struct tc_aes_key_sched_struct key;
|
||||
|
||||
/* number of requests since initialization/reseeding */
|
||||
uint64_t reseedCount;
|
||||
} TCCtrPrng_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief CTR-PRNG initialization procedure
|
||||
* Initializes prng context with entropy and personalization string (if any)
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* ctx == NULL,
|
||||
* entropy == NULL,
|
||||
* entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
|
||||
* @note Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of
|
||||
* both the entropy and personalization inputs are used -
|
||||
* supplying additional bytes has no effect.
|
||||
* @param ctx IN/OUT -- the PRNG context to initialize
|
||||
* @param entropy IN -- entropy used to seed the PRNG
|
||||
* @param entropyLen IN -- entropy length in bytes
|
||||
* @param personalization IN -- personalization string used to seed the PRNG
|
||||
* (may be null)
|
||||
* @param plen IN -- personalization length in bytes
|
||||
*
|
||||
*/
|
||||
int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const entropy,
|
||||
unsigned int entropyLen,
|
||||
uint8_t const * const personalization,
|
||||
unsigned int pLen);
|
||||
|
||||
/**
|
||||
* @brief CTR-PRNG reseed procedure
|
||||
* Mixes entropy and additional_input into the prng context
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* ctx == NULL,
|
||||
* entropy == NULL,
|
||||
* entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
|
||||
* @note It is better to reseed an existing prng context rather than
|
||||
* re-initialise, so that any existing entropy in the context is
|
||||
* presereved. This offers some protection against undetected failures
|
||||
* of the entropy source.
|
||||
* @note Assumes tc_ctr_prng_init has been called for ctx
|
||||
* @param ctx IN/OUT -- the PRNG state
|
||||
* @param entropy IN -- entropy to mix into the prng
|
||||
* @param entropylen IN -- length of entropy in bytes
|
||||
* @param additional_input IN -- additional input to the prng (may be null)
|
||||
* @param additionallen IN -- additional input length in bytes
|
||||
*/
|
||||
int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const entropy,
|
||||
unsigned int entropyLen,
|
||||
uint8_t const * const additional_input,
|
||||
unsigned int additionallen);
|
||||
|
||||
/**
|
||||
* @brief CTR-PRNG generate procedure
|
||||
* Generates outlen pseudo-random bytes into out buffer, updates prng
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* ctx == NULL,
|
||||
* out == NULL,
|
||||
* outlen >= 2^16
|
||||
* @note Assumes tc_ctr_prng_init has been called for ctx
|
||||
* @param ctx IN/OUT -- the PRNG context
|
||||
* @param additional_input IN -- additional input to the prng (may be null)
|
||||
* @param additionallen IN -- additional input length in bytes
|
||||
* @param out IN/OUT -- buffer to receive output
|
||||
* @param outlen IN -- size of out buffer in bytes
|
||||
*/
|
||||
int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const additional_input,
|
||||
unsigned int additionallen,
|
||||
uint8_t * const out,
|
||||
unsigned int outlen);
|
||||
|
||||
/**
|
||||
* @brief CTR-PRNG uninstantiate procedure
|
||||
* Zeroes the internal state of the supplied prng context
|
||||
* @return none
|
||||
* @param ctx IN/OUT -- the PRNG context
|
||||
*/
|
||||
void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CTR_PRNG_H__ */
|
||||
@@ -0,0 +1,545 @@
|
||||
/* ecc.h - TinyCrypt interface to common ECC functions */
|
||||
|
||||
/* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to common ECC functions.
|
||||
*
|
||||
* Overview: This software is an implementation of common functions
|
||||
* necessary to elliptic curve cryptography. This implementation uses
|
||||
* curve NIST p-256.
|
||||
*
|
||||
* Security: The curve NIST p-256 provides approximately 128 bits of security.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_UECC_H__
|
||||
#define __TC_UECC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Word size (4 bytes considering 32-bits architectures) */
|
||||
#define uECC_WORD_SIZE 4
|
||||
|
||||
/* setting max number of calls to prng: */
|
||||
#ifndef uECC_RNG_MAX_TRIES
|
||||
#define uECC_RNG_MAX_TRIES 64
|
||||
#endif
|
||||
|
||||
/* defining data types to store word and bit counts: */
|
||||
typedef int8_t wordcount_t;
|
||||
typedef int16_t bitcount_t;
|
||||
/* defining data type for comparison result: */
|
||||
typedef int8_t cmpresult_t;
|
||||
/* defining data type to store ECC coordinate/point in 32bits words: */
|
||||
typedef unsigned int uECC_word_t;
|
||||
/* defining data type to store an ECC coordinate/point in 64bits words: */
|
||||
typedef uint64_t uECC_dword_t;
|
||||
|
||||
/* defining masks useful for ecc computations: */
|
||||
#define HIGH_BIT_SET 0x80000000
|
||||
#define uECC_WORD_BITS 32
|
||||
#define uECC_WORD_BITS_SHIFT 5
|
||||
#define uECC_WORD_BITS_MASK 0x01F
|
||||
|
||||
/* Number of words of 32 bits to represent an element of the the curve p-256: */
|
||||
#define NUM_ECC_WORDS 8
|
||||
/* Number of bytes to represent an element of the the curve p-256: */
|
||||
#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS)
|
||||
|
||||
/* structure that represents an elliptic curve (e.g. p256):*/
|
||||
struct uECC_Curve_t;
|
||||
typedef const struct uECC_Curve_t * uECC_Curve;
|
||||
struct uECC_Curve_t {
|
||||
wordcount_t num_words;
|
||||
wordcount_t num_bytes;
|
||||
bitcount_t num_n_bits;
|
||||
uECC_word_t p[NUM_ECC_WORDS];
|
||||
uECC_word_t n[NUM_ECC_WORDS];
|
||||
uECC_word_t G[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t b[NUM_ECC_WORDS];
|
||||
void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1,
|
||||
uECC_Curve curve);
|
||||
void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
|
||||
void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief computes doubling of point ion jacobian coordinates, in place.
|
||||
* @param X1 IN/OUT -- x coordinate
|
||||
* @param Y1 IN/OUT -- y coordinate
|
||||
* @param Z1 IN/OUT -- z coordinate
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * Z1, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Computes x^3 + ax + b. result must not overlap x.
|
||||
* @param result OUT -- x^3 + ax + b
|
||||
* @param x IN -- value of x
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void x_side_default(uECC_word_t *result, const uECC_word_t *x,
|
||||
uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Computes result = product % curve_p
|
||||
* from http://www.nsa.gov/ia/_files/nist-routines.pdf
|
||||
* @param result OUT -- product % curve_p
|
||||
* @param product IN -- value to be reduced mod curve_p
|
||||
*/
|
||||
void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product);
|
||||
|
||||
/* Bytes to words ordering: */
|
||||
#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
|
||||
#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
|
||||
#define BITS_TO_WORDS(num_bits) \
|
||||
((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
|
||||
#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
|
||||
|
||||
/* definition of curve NIST p-256: */
|
||||
static const struct uECC_Curve_t curve_secp256r1 = {
|
||||
NUM_ECC_WORDS,
|
||||
NUM_ECC_BYTES,
|
||||
256, /* num_n_bits */ {
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
|
||||
}, {
|
||||
BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
|
||||
BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
|
||||
}, {
|
||||
BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
|
||||
BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
|
||||
BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
|
||||
BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
|
||||
|
||||
BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
|
||||
BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
|
||||
BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
|
||||
BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
|
||||
}, {
|
||||
BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
|
||||
BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
|
||||
BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
|
||||
BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
|
||||
},
|
||||
&double_jacobian_default,
|
||||
&x_side_default,
|
||||
&vli_mmod_fast_secp256r1
|
||||
};
|
||||
|
||||
uECC_Curve uECC_secp256r1(void);
|
||||
|
||||
/*
|
||||
* @brief Generates a random integer in the range 0 < random < top.
|
||||
* Both random and top have num_words words.
|
||||
* @param random OUT -- random integer in the range 0 < random < top
|
||||
* @param top IN -- upper limit
|
||||
* @param num_words IN -- number of words
|
||||
* @return a random integer in the range 0 < random < top
|
||||
*/
|
||||
int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
|
||||
wordcount_t num_words);
|
||||
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
* The RNG function should fill 'size' random bytes into 'dest'. It should
|
||||
* return 1 if 'dest' was filled with random data, or 0 if the random data could
|
||||
* not be generated. The filled-in values should be either truly random, or from
|
||||
* a cryptographically-secure PRNG.
|
||||
*
|
||||
* A correctly functioning RNG function must be set (using uECC_set_rng())
|
||||
* before calling uECC_make_key() or uECC_sign().
|
||||
*
|
||||
* Setting a correctly functioning RNG function improves the resistance to
|
||||
* side-channel attacks for uECC_shared_secret().
|
||||
*
|
||||
* A correct RNG function is set by default. If you are building on another
|
||||
* POSIX-compliant system that supports /dev/random or /dev/urandom, you can
|
||||
* define uECC_POSIX to use the predefined RNG.
|
||||
*/
|
||||
typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size);
|
||||
|
||||
/*
|
||||
* @brief Set the function that will be used to generate random bytes. The RNG
|
||||
* function should return 1 if the random data was generated, or 0 if the random
|
||||
* data could not be generated.
|
||||
*
|
||||
* @note On platforms where there is no predefined RNG function, this must be
|
||||
* called before uECC_make_key() or uECC_sign() are used.
|
||||
*
|
||||
* @param rng_function IN -- function that will be used to generate random bytes
|
||||
*/
|
||||
void uECC_set_rng(uECC_RNG_Function rng_function);
|
||||
|
||||
/*
|
||||
* @brief provides current uECC_RNG_Function.
|
||||
* @return Returns the function that will be used to generate random bytes.
|
||||
*/
|
||||
uECC_RNG_Function uECC_get_rng(void);
|
||||
|
||||
/*
|
||||
* @brief computes the size of a private key for the curve in bytes.
|
||||
* @param curve IN -- elliptic curve
|
||||
* @return size of a private key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_private_key_size(uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief computes the size of a public key for the curve in bytes.
|
||||
* @param curve IN -- elliptic curve
|
||||
* @return the size of a public key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_public_key_size(uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Compute the corresponding public key for a private key.
|
||||
* @param private_key IN -- The private key to compute the public key for
|
||||
* @param public_key OUT -- Will be filled in with the corresponding public key
|
||||
* @param curve
|
||||
* @return Returns 1 if key was computed successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_compute_public_key(const uint8_t *private_key,
|
||||
uint8_t *public_key, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Compute public-key.
|
||||
* @return corresponding public-key.
|
||||
* @param result OUT -- public-key
|
||||
* @param private_key IN -- private-key
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
||||
uECC_word_t *private_key, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Regularize the bitcount for the private key so that attackers cannot
|
||||
* use a side channel attack to learn the number of leading zeros.
|
||||
* @return Regularized k
|
||||
* @param k IN -- private-key
|
||||
* @param k0 IN/OUT -- regularized k
|
||||
* @param k1 IN/OUT -- regularized k
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
|
||||
uECC_word_t *k1, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Point multiplication algorithm using Montgomery's ladder with co-Z
|
||||
* coordinates. See http://eprint.iacr.org/2011/338.pdf.
|
||||
* @note Result may overlap point.
|
||||
* @param result OUT -- returns scalar*point
|
||||
* @param point IN -- elliptic curve point
|
||||
* @param scalar IN -- scalar
|
||||
* @param initial_Z IN -- initial value for z
|
||||
* @param num_bits IN -- number of bits in scalar
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
|
||||
const uECC_word_t * scalar, const uECC_word_t * initial_Z,
|
||||
bitcount_t num_bits, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Constant-time comparison to zero - secure way to compare long integers
|
||||
* @param vli IN -- very long integer
|
||||
* @param num_words IN -- number of words in the vli
|
||||
* @return 1 if vli == 0, 0 otherwise.
|
||||
*/
|
||||
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Check if 'point' is the point at infinity
|
||||
* @param point IN -- elliptic curve point
|
||||
* @param curve IN -- elliptic curve
|
||||
* @return if 'point' is the point at infinity, 0 otherwise.
|
||||
*/
|
||||
uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief computes the sign of left - right, in constant time.
|
||||
* @param left IN -- left term to be compared
|
||||
* @param right IN -- right term to be compared
|
||||
* @param num_words IN -- number of words
|
||||
* @return the sign of left - right
|
||||
*/
|
||||
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief computes sign of left - right, not in constant time.
|
||||
* @note should not be used if inputs are part of a secret
|
||||
* @param left IN -- left term to be compared
|
||||
* @param right IN -- right term to be compared
|
||||
* @param num_words IN -- number of words
|
||||
* @return the sign of left - right
|
||||
*/
|
||||
cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes result = (left - right) % mod.
|
||||
* @note Assumes that (left < mod) and (right < mod), and that result does not
|
||||
* overlap mod.
|
||||
* @param result OUT -- (left - right) % mod
|
||||
* @param left IN -- leftright term in modular subtraction
|
||||
* @param right IN -- right term in modular subtraction
|
||||
* @param mod IN -- mod
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or
|
||||
* P => P', Q => P + Q
|
||||
* @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z)
|
||||
* @param X1 IN -- x coordinate of P
|
||||
* @param Y1 IN -- y coordinate of P
|
||||
* @param X2 IN -- x coordinate of Q
|
||||
* @param Y2 IN -- y coordinate of Q
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2,
|
||||
uECC_word_t * Y2, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Computes (x1 * z^2, y1 * z^3)
|
||||
* @param X1 IN -- previous x1 coordinate
|
||||
* @param Y1 IN -- previous y1 coordinate
|
||||
* @param Z IN -- z value
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
|
||||
uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Check if bit is set.
|
||||
* @return Returns nonzero if bit 'bit' of vli is set.
|
||||
* @warning It is assumed that the value provided in 'bit' is within the
|
||||
* boundaries of the word-array 'vli'.
|
||||
* @note The bit ordering layout assumed for vli is: {31, 30, ..., 0},
|
||||
* {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting
|
||||
* of 4 uECC_word_t elements.
|
||||
*/
|
||||
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
|
||||
|
||||
/*
|
||||
* @brief Computes result = product % mod, where product is 2N words long.
|
||||
* @param result OUT -- product % mod
|
||||
* @param mod IN -- module
|
||||
* @param num_words IN -- number of words
|
||||
* @warning Currently only designed to work for curve_p or curve_n.
|
||||
*/
|
||||
void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
|
||||
const uECC_word_t *mod, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes modular product (using curve->mmod_fast)
|
||||
* @param result OUT -- (left * right) mod % curve_p
|
||||
* @param left IN -- left term in product
|
||||
* @param right IN -- right term in product
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Computes result = left - right.
|
||||
* @note Can modify in place.
|
||||
* @param result OUT -- left - right
|
||||
* @param left IN -- left term in subtraction
|
||||
* @param right IN -- right term in subtraction
|
||||
* @param num_words IN -- number of words
|
||||
* @return borrow
|
||||
*/
|
||||
uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Constant-time comparison function(secure way to compare long ints)
|
||||
* @param left IN -- left term in comparison
|
||||
* @param right IN -- right term in comparison
|
||||
* @param num_words IN -- number of words
|
||||
* @return Returns 0 if left == right, 1 otherwise.
|
||||
*/
|
||||
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes (left * right) % mod
|
||||
* @param result OUT -- (left * right) % mod
|
||||
* @param left IN -- left term in product
|
||||
* @param right IN -- right term in product
|
||||
* @param mod IN -- mod
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes (1 / input) % mod
|
||||
* @note All VLIs are the same size.
|
||||
* @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide"
|
||||
* @param result OUT -- (1 / input) % mod
|
||||
* @param input IN -- value to be modular inverted
|
||||
* @param mod IN -- mod
|
||||
* @param num_words -- number of words
|
||||
*/
|
||||
void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
|
||||
const uECC_word_t *mod, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Sets dest = src.
|
||||
* @param dest OUT -- destination buffer
|
||||
* @param src IN -- origin buffer
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes (left + right) % mod.
|
||||
* @note Assumes that (left < mod) and right < mod), and that result does not
|
||||
* overlap mod.
|
||||
* @param result OUT -- (left + right) % mod.
|
||||
* @param left IN -- left term in addition
|
||||
* @param right IN -- right term in addition
|
||||
* @param mod IN -- mod
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Counts the number of bits required to represent vli.
|
||||
* @param vli IN -- very long integer
|
||||
* @param max_words IN -- number of words
|
||||
* @return number of bits in given vli
|
||||
*/
|
||||
bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
|
||||
const wordcount_t max_words);
|
||||
|
||||
/*
|
||||
* @brief Erases (set to 0) vli
|
||||
* @param vli IN -- very long integer
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief check if it is a valid point in the curve
|
||||
* @param point IN -- point to be checked
|
||||
* @param curve IN -- elliptic curve
|
||||
* @return 0 if point is valid
|
||||
* @exception returns -1 if it is a point at infinity
|
||||
* @exception returns -2 if x or y is smaller than p,
|
||||
* @exception returns -3 if y^2 != x^3 + ax + b.
|
||||
*/
|
||||
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Check if a public key is valid.
|
||||
* @param public_key IN -- The public key to be checked.
|
||||
* @return returns 0 if the public key is valid
|
||||
* @exception returns -1 if it is a point at infinity
|
||||
* @exception returns -2 if x or y is smaller than p,
|
||||
* @exception returns -3 if y^2 != x^3 + ax + b.
|
||||
* @exception returns -4 if public key is the group generator.
|
||||
*
|
||||
* @note Note that you are not required to check for a valid public key before
|
||||
* using any other uECC functions. However, you may wish to avoid spending CPU
|
||||
* time computing a shared secret or verifying a signature using an invalid
|
||||
* public key.
|
||||
*/
|
||||
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Converts an integer in uECC native format to big-endian bytes.
|
||||
* @param bytes OUT -- bytes representation
|
||||
* @param num_bytes IN -- number of bytes
|
||||
* @param native IN -- uECC native representation
|
||||
*/
|
||||
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
|
||||
const unsigned int *native);
|
||||
|
||||
/*
|
||||
* @brief Converts big-endian bytes to an integer in uECC native format.
|
||||
* @param native OUT -- uECC native representation
|
||||
* @param bytes IN -- bytes representation
|
||||
* @param num_bytes IN -- number of bytes
|
||||
*/
|
||||
void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
|
||||
int num_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_UECC_H__ */
|
||||
@@ -0,0 +1,131 @@
|
||||
/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to EC-DH implementation.
|
||||
*
|
||||
* Overview: This software is an implementation of EC-DH. This implementation
|
||||
* uses curve NIST p-256.
|
||||
*
|
||||
* Security: The curve NIST p-256 provides approximately 128 bits of security.
|
||||
*/
|
||||
|
||||
#ifndef __TC_ECC_DH_H__
|
||||
#define __TC_ECC_DH_H__
|
||||
|
||||
#include <tinycrypt/ecc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Create a public/private key pair.
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully
|
||||
* returns TC_CRYPTO_FAIL (0) if error while generating key pair
|
||||
*
|
||||
* @param p_public_key OUT -- Will be filled in with the public key. Must be at
|
||||
* least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
|
||||
* must be 64 bytes long.
|
||||
* @param p_private_key OUT -- Will be filled in with the private key. Must be as
|
||||
* long as the curve order (for secp256r1, p_private_key must be 32 bytes long).
|
||||
*
|
||||
* @note side-channel countermeasure: algorithm strengthened against timing
|
||||
* attack.
|
||||
* @warning A cryptographically-secure PRNG function must be set (using
|
||||
* uECC_set_rng()) before calling uECC_make_key().
|
||||
*/
|
||||
int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve);
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
|
||||
/**
|
||||
* @brief Create a public/private key pair given a specific d.
|
||||
*
|
||||
* @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to
|
||||
* uECC_make_key() function for real applications.
|
||||
*/
|
||||
int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key,
|
||||
unsigned int *d, uECC_Curve curve);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Compute a shared secret given your secret key and someone else's
|
||||
* public key.
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully
|
||||
* returns TC_CRYPTO_FAIL (0) otherwise
|
||||
*
|
||||
* @param p_secret OUT -- Will be filled in with the shared secret value. Must be
|
||||
* the same size as the curve size (for curve secp256r1, secret must be 32 bytes
|
||||
* long.
|
||||
* @param p_public_key IN -- The public key of the remote party.
|
||||
* @param p_private_key IN -- Your private key.
|
||||
*
|
||||
* @warning It is recommended to use the output of uECC_shared_secret() as the
|
||||
* input of a recommended Key Derivation Function (see NIST SP 800-108) in
|
||||
* order to produce a cryptographically secure symmetric key.
|
||||
*/
|
||||
int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key,
|
||||
uint8_t *p_secret, uECC_Curve curve);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_ECC_DH_H__ */
|
||||
@@ -0,0 +1,139 @@
|
||||
/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to EC-DSA implementation.
|
||||
*
|
||||
* Overview: This software is an implementation of EC-DSA. This implementation
|
||||
* uses curve NIST p-256.
|
||||
*
|
||||
* Security: The curve NIST p-256 provides approximately 128 bits of security.
|
||||
*
|
||||
* Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is
|
||||
* recommended) and pass it in to ecdsa_sign function along with your
|
||||
* private key and a random number. You must use a new non-predictable
|
||||
* random number to generate each new signature.
|
||||
* - To verify a signature: Compute the hash of the signed data using
|
||||
* the same hash as the signer and pass it to this function along with
|
||||
* the signer's public key and the signature values (r and s).
|
||||
*/
|
||||
|
||||
#ifndef __TC_ECC_DSA_H__
|
||||
#define __TC_ECC_DSA_H__
|
||||
|
||||
#include <tinycrypt/ecc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Generate an ECDSA signature for a given hash value.
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully
|
||||
* returns TC_CRYPTO_FAIL (0) if an error occurred.
|
||||
*
|
||||
* @param p_private_key IN -- Your private key.
|
||||
* @param p_message_hash IN -- The hash of the message to sign.
|
||||
* @param p_hash_size IN -- The size of p_message_hash in bytes.
|
||||
* @param p_signature OUT -- Will be filled in with the signature value. Must be
|
||||
* at least 2 * curve size long (for secp256r1, signature must be 64 bytes long).
|
||||
*
|
||||
* @warning A cryptographically-secure PRNG function must be set (using
|
||||
* uECC_set_rng()) before calling uECC_sign().
|
||||
* @note Usage: Compute a hash of the data you wish to sign (SHA-2 is
|
||||
* recommended) and pass it in to this function along with your private key.
|
||||
* @note side-channel countermeasure: algorithm strengthened against timing
|
||||
* attack.
|
||||
*/
|
||||
int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash,
|
||||
unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve);
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
/*
|
||||
* THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY.
|
||||
* Refer to uECC_sign() function for real applications.
|
||||
*/
|
||||
int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned int hash_size, uECC_word_t *k, uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Verify an ECDSA signature.
|
||||
* @return returns TC_SUCCESS (1) if the signature is valid
|
||||
* returns TC_FAIL (0) if the signature is invalid.
|
||||
*
|
||||
* @param p_public_key IN -- The signer's public key.
|
||||
* @param p_message_hash IN -- The hash of the signed data.
|
||||
* @param p_hash_size IN -- The size of p_message_hash in bytes.
|
||||
* @param p_signature IN -- The signature values.
|
||||
*
|
||||
* @note Usage: Compute the hash of the signed data using the same hash as the
|
||||
* signer and pass it to this function along with the signer's public key and
|
||||
* the signature values (hash_size and signature).
|
||||
*/
|
||||
int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash,
|
||||
unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_ECC_DSA_H__ */
|
||||
@@ -0,0 +1,81 @@
|
||||
/* uECC_platform_specific.h - Interface to platform specific functions*/
|
||||
|
||||
/* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* uECC_platform_specific.h -- Interface to platform specific functions
|
||||
*/
|
||||
|
||||
#ifndef __UECC_PLATFORM_SPECIFIC_H_
|
||||
#define __UECC_PLATFORM_SPECIFIC_H_
|
||||
|
||||
/*
|
||||
* The RNG function should fill 'size' random bytes into 'dest'. It should
|
||||
* return 1 if 'dest' was filled with random data, or 0 if the random data could
|
||||
* not be generated. The filled-in values should be either truly random, or from
|
||||
* a cryptographically-secure PRNG.
|
||||
*
|
||||
* A cryptographically-secure PRNG function must be set (using uECC_set_rng())
|
||||
* before calling uECC_make_key() or uECC_sign().
|
||||
*
|
||||
* Setting a cryptographically-secure PRNG function improves the resistance to
|
||||
* side-channel attacks for uECC_shared_secret().
|
||||
*
|
||||
* A correct PRNG function is set by default (default_RNG_defined = 1) and works
|
||||
* for some platforms, such as Unix and Linux. For other platforms, you may need
|
||||
* to provide another PRNG function.
|
||||
*/
|
||||
#define default_RNG_defined 0
|
||||
|
||||
int default_CSPRNG(uint8_t *dest, unsigned int size);
|
||||
|
||||
#endif /* __UECC_PLATFORM_SPECIFIC_H_ */
|
||||
@@ -0,0 +1,139 @@
|
||||
/* hmac.h - TinyCrypt interface to an HMAC implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to an HMAC implementation.
|
||||
*
|
||||
* Overview: HMAC is a message authentication code based on hash functions.
|
||||
* TinyCrypt hard codes SHA-256 as the hash function. A message
|
||||
* authentication code based on hash functions is also called a
|
||||
* keyed cryptographic hash function since it performs a
|
||||
* transformation specified by a key in an arbitrary length data
|
||||
* set into a fixed length data set (also called tag).
|
||||
*
|
||||
* Security: The security of the HMAC depends on the length of the key and
|
||||
* on the security of the hash function. Note that HMAC primitives
|
||||
* are much less affected by collision attacks than their
|
||||
* corresponding hash functions.
|
||||
*
|
||||
* Requires: SHA-256
|
||||
*
|
||||
* Usage: 1) call tc_hmac_set_key to set the HMAC key.
|
||||
*
|
||||
* 2) call tc_hmac_init to initialize a struct hash_state before
|
||||
* processing the data.
|
||||
*
|
||||
* 3) call tc_hmac_update to process the next input segment;
|
||||
* tc_hmac_update can be called as many times as needed to process
|
||||
* all of the segments of the input; the order is important.
|
||||
*
|
||||
* 4) call tc_hmac_final to out put the tag.
|
||||
*/
|
||||
|
||||
#ifndef __TC_HMAC_H__
|
||||
#define __TC_HMAC_H__
|
||||
|
||||
#include <tinycrypt/sha256.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct tc_hmac_state_struct {
|
||||
/* the internal state required by h */
|
||||
struct tc_sha256_state_struct hash_state;
|
||||
/* HMAC key schedule */
|
||||
uint8_t key[2*TC_SHA256_BLOCK_SIZE];
|
||||
};
|
||||
typedef struct tc_hmac_state_struct *TCHmacState_t;
|
||||
|
||||
/**
|
||||
* @brief HMAC set key procedure
|
||||
* Configures ctx to use key
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if
|
||||
* ctx == NULL or
|
||||
* key == NULL or
|
||||
* key_size == 0
|
||||
* @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial
|
||||
* @param key IN -- the HMAC key to configure
|
||||
* @param key_size IN -- the HMAC key size
|
||||
*/
|
||||
int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
|
||||
unsigned int key_size);
|
||||
|
||||
/**
|
||||
* @brief HMAC init procedure
|
||||
* Initializes ctx to begin the next HMAC operation
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
|
||||
* @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init
|
||||
*/
|
||||
int tc_hmac_init(TCHmacState_t ctx);
|
||||
|
||||
/**
|
||||
* @brief HMAC update procedure
|
||||
* Mixes data_length bytes addressed by data into state
|
||||
* @return returns TC_CRYPTO_SUCCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
|
||||
* @note Assumes state has been initialized by tc_hmac_init
|
||||
* @param ctx IN/OUT -- state of HMAC computation so far
|
||||
* @param data IN -- data to incorporate into state
|
||||
* @param data_length IN -- size of data in bytes
|
||||
*/
|
||||
int tc_hmac_update(TCHmacState_t ctx, const void *data,
|
||||
unsigned int data_length);
|
||||
|
||||
/**
|
||||
* @brief HMAC final procedure
|
||||
* Writes the HMAC tag into the tag buffer
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* tag == NULL or
|
||||
* ctx == NULL or
|
||||
* key == NULL or
|
||||
* taglen != TC_SHA256_DIGEST_SIZE
|
||||
* @note ctx is erased before exiting. This should never be changed/removed.
|
||||
* @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes
|
||||
* state has been initialized by tc_hmac_init
|
||||
* @param tag IN/OUT -- buffer to receive computed HMAC tag
|
||||
* @param taglen IN -- size of tag in bytes
|
||||
* @param ctx IN/OUT -- the HMAC state for computing tag
|
||||
*/
|
||||
int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__TC_HMAC_H__*/
|
||||
@@ -0,0 +1,164 @@
|
||||
/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to an HMAC-PRNG implementation.
|
||||
*
|
||||
* Overview: A pseudo-random number generator (PRNG) generates a sequence
|
||||
* of numbers that have a distribution close to the one expected
|
||||
* for a sequence of truly random numbers. The NIST Special
|
||||
* Publication 800-90A specifies several mechanisms to generate
|
||||
* sequences of pseudo random numbers, including the HMAC-PRNG one
|
||||
* which is based on HMAC. TinyCrypt implements HMAC-PRNG with
|
||||
* certain modifications from the NIST SP 800-90A spec.
|
||||
*
|
||||
* Security: A cryptographically secure PRNG depends on the existence of an
|
||||
* entropy source to provide a truly random seed as well as the
|
||||
* security of the primitives used as the building blocks (HMAC and
|
||||
* SHA256, for TinyCrypt).
|
||||
*
|
||||
* The NIST SP 800-90A standard tolerates a null personalization,
|
||||
* while TinyCrypt requires a non-null personalization. This is
|
||||
* because a personalization string (the host name concatenated
|
||||
* with a time stamp, for example) is easily computed and might be
|
||||
* the last line of defense against failure of the entropy source.
|
||||
*
|
||||
* Requires: - SHA-256
|
||||
* - HMAC
|
||||
*
|
||||
* Usage: 1) call tc_hmac_prng_init to set the HMAC key and process the
|
||||
* personalization data.
|
||||
*
|
||||
* 2) call tc_hmac_prng_reseed to process the seed and additional
|
||||
* input.
|
||||
*
|
||||
* 3) call tc_hmac_prng_generate to out put the pseudo-random data.
|
||||
*/
|
||||
|
||||
#ifndef __TC_HMAC_PRNG_H__
|
||||
#define __TC_HMAC_PRNG_H__
|
||||
|
||||
#include <tinycrypt/sha256.h>
|
||||
#include <tinycrypt/hmac.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TC_HMAC_PRNG_RESEED_REQ -1
|
||||
|
||||
struct tc_hmac_prng_struct {
|
||||
/* the HMAC instance for this PRNG */
|
||||
struct tc_hmac_state_struct h;
|
||||
/* the PRNG key */
|
||||
uint8_t key[TC_SHA256_DIGEST_SIZE];
|
||||
/* PRNG state */
|
||||
uint8_t v[TC_SHA256_DIGEST_SIZE];
|
||||
/* calls to tc_hmac_prng_generate left before re-seed */
|
||||
unsigned int countdown;
|
||||
};
|
||||
|
||||
typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
|
||||
|
||||
/**
|
||||
* @brief HMAC-PRNG initialization procedure
|
||||
* Initializes prng with personalization, disables tc_hmac_prng_generate
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* prng == NULL,
|
||||
* personalization == NULL,
|
||||
* plen > MAX_PLEN
|
||||
* @note Assumes: - personalization != NULL.
|
||||
* The personalization is a platform unique string (e.g., the host
|
||||
* name) and is the last line of defense against failure of the
|
||||
* entropy source
|
||||
* @warning NIST SP 800-90A specifies 3 items as seed material during
|
||||
* initialization: entropy seed, personalization, and an optional
|
||||
* nonce. TinyCrypts requires instead a non-null personalization
|
||||
* (which is easily computed) and indirectly requires an entropy
|
||||
* seed (since the reseed function is mandatorily called after
|
||||
* init)
|
||||
* @param prng IN/OUT -- the PRNG state to initialize
|
||||
* @param personalization IN -- personalization string
|
||||
* @param plen IN -- personalization length in bytes
|
||||
*/
|
||||
int tc_hmac_prng_init(TCHmacPrng_t prng,
|
||||
const uint8_t *personalization,
|
||||
unsigned int plen);
|
||||
|
||||
/**
|
||||
* @brief HMAC-PRNG reseed procedure
|
||||
* Mixes seed into prng, enables tc_hmac_prng_generate
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* prng == NULL,
|
||||
* seed == NULL,
|
||||
* seedlen < MIN_SLEN,
|
||||
* seendlen > MAX_SLEN,
|
||||
* additional_input != (const uint8_t *) 0 && additionallen == 0,
|
||||
* additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN
|
||||
* @note Assumes:- tc_hmac_prng_init has been called for prng
|
||||
* - seed has sufficient entropy.
|
||||
*
|
||||
* @param prng IN/OUT -- the PRNG state
|
||||
* @param seed IN -- entropy to mix into the prng
|
||||
* @param seedlen IN -- length of seed in bytes
|
||||
* @param additional_input IN -- additional input to the prng
|
||||
* @param additionallen IN -- additional input length in bytes
|
||||
*/
|
||||
int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed,
|
||||
unsigned int seedlen, const uint8_t *additional_input,
|
||||
unsigned int additionallen);
|
||||
|
||||
/**
|
||||
* @brief HMAC-PRNG generate procedure
|
||||
* Generates outlen pseudo-random bytes into out buffer, updates prng
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL,
|
||||
* prng == NULL,
|
||||
* outlen == 0,
|
||||
* outlen >= MAX_OUT
|
||||
* @note Assumes tc_hmac_prng_init has been called for prng
|
||||
* @param out IN/OUT -- buffer to receive output
|
||||
* @param outlen IN -- size of out buffer in bytes
|
||||
* @param prng IN/OUT -- the PRNG state
|
||||
*/
|
||||
int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_HMAC_PRNG_H__ */
|
||||
@@ -0,0 +1,129 @@
|
||||
/* sha256.h - TinyCrypt interface to a SHA-256 implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a SHA-256 implementation.
|
||||
*
|
||||
* Overview: SHA-256 is a NIST approved cryptographic hashing algorithm
|
||||
* specified in FIPS 180. A hash algorithm maps data of arbitrary
|
||||
* size to data of fixed length.
|
||||
*
|
||||
* Security: SHA-256 provides 128 bits of security against collision attacks
|
||||
* and 256 bits of security against pre-image attacks. SHA-256 does
|
||||
* NOT behave like a random oracle, but it can be used as one if
|
||||
* the string being hashed is prefix-free encoded before hashing.
|
||||
*
|
||||
* Usage: 1) call tc_sha256_init to initialize a struct
|
||||
* tc_sha256_state_struct before hashing a new string.
|
||||
*
|
||||
* 2) call tc_sha256_update to hash the next string segment;
|
||||
* tc_sha256_update can be called as many times as needed to hash
|
||||
* all of the segments of a string; the order is important.
|
||||
*
|
||||
* 3) call tc_sha256_final to out put the digest from a hashing
|
||||
* operation.
|
||||
*/
|
||||
|
||||
#ifndef __TC_SHA256_H__
|
||||
#define __TC_SHA256_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TC_SHA256_BLOCK_SIZE (64)
|
||||
#define TC_SHA256_DIGEST_SIZE (32)
|
||||
#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4)
|
||||
|
||||
struct tc_sha256_state_struct {
|
||||
unsigned int iv[TC_SHA256_STATE_BLOCKS];
|
||||
uint64_t bits_hashed;
|
||||
uint8_t leftover[TC_SHA256_BLOCK_SIZE];
|
||||
size_t leftover_offset;
|
||||
};
|
||||
|
||||
typedef struct tc_sha256_state_struct *TCSha256State_t;
|
||||
|
||||
/**
|
||||
* @brief SHA256 initialization procedure
|
||||
* Initializes s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if s == NULL
|
||||
* @param s Sha256 state struct
|
||||
*/
|
||||
int tc_sha256_init(TCSha256State_t s);
|
||||
|
||||
/**
|
||||
* @brief SHA256 update procedure
|
||||
* Hashes data_length bytes addressed by data into state s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL,
|
||||
* s->iv == NULL,
|
||||
* data == NULL
|
||||
* @note Assumes s has been initialized by tc_sha256_init
|
||||
* @warning The state buffer 'leftover' is left in memory after processing
|
||||
* If your application intends to have sensitive data in this
|
||||
* buffer, remind to erase it after the data has been processed
|
||||
* @param s Sha256 state struct
|
||||
* @param data message to hash
|
||||
* @param datalen length of message to hash
|
||||
*/
|
||||
int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen);
|
||||
|
||||
/**
|
||||
* @brief SHA256 final procedure
|
||||
* Inserts the completed hash computation into digest
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL,
|
||||
* s->iv == NULL,
|
||||
* digest == NULL
|
||||
* @note Assumes: s has been initialized by tc_sha256_init
|
||||
* digest points to at least TC_SHA256_DIGEST_SIZE bytes
|
||||
* @warning The state buffer 'leftover' is left in memory after processing
|
||||
* If your application intends to have sensitive data in this
|
||||
* buffer, remind to erase it after the data has been processed
|
||||
* @param digest unsigned eight bit integer
|
||||
* @param Sha256 state struct
|
||||
*/
|
||||
int tc_sha256_final(uint8_t *digest, TCSha256State_t s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_SHA256_H__ */
|
||||
@@ -0,0 +1,95 @@
|
||||
/* utils.h - TinyCrypt interface to platform-dependent run-time operations */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to platform-dependent run-time operations.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_UTILS_H__
|
||||
#define __TC_UTILS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Copy the the buffer 'from' to the buffer 'to'.
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* from_len > to_len.
|
||||
*
|
||||
* @param to OUT -- destination buffer
|
||||
* @param to_len IN -- length of destination buffer
|
||||
* @param from IN -- origin buffer
|
||||
* @param from_len IN -- length of origin buffer
|
||||
*/
|
||||
unsigned int _copy(uint8_t *to, unsigned int to_len,
|
||||
const uint8_t *from, unsigned int from_len);
|
||||
|
||||
/**
|
||||
* @brief Set the value 'val' into the buffer 'to', 'len' times.
|
||||
*
|
||||
* @param to OUT -- destination buffer
|
||||
* @param val IN -- value to be set in 'to'
|
||||
* @param len IN -- number of times the value will be copied
|
||||
*/
|
||||
void _set(void *to, uint8_t val, unsigned int len);
|
||||
|
||||
/*
|
||||
* @brief AES specific doubling function, which utilizes
|
||||
* the finite field used by AES.
|
||||
* @return Returns a^2
|
||||
*
|
||||
* @param a IN/OUT -- value to be doubled
|
||||
*/
|
||||
uint8_t _double_byte(uint8_t a);
|
||||
|
||||
/*
|
||||
* @brief Constant-time algorithm to compare if two sequences of bytes are equal
|
||||
* @return Returns 0 if equal, and non-zero otherwise
|
||||
*
|
||||
* @param a IN -- sequence of bytes a
|
||||
* @param b IN -- sequence of bytes b
|
||||
* @param size IN -- size of sequences a and b
|
||||
*/
|
||||
int _compare(const uint8_t *a, const uint8_t *b, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_UTILS_H__ */
|
||||
@@ -0,0 +1,164 @@
|
||||
/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
static const uint8_t inv_sbox[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
|
||||
0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
|
||||
0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
|
||||
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
|
||||
0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
|
||||
0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
|
||||
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
|
||||
0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
|
||||
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
|
||||
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
|
||||
0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
|
||||
0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
|
||||
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
|
||||
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
|
||||
0x55, 0x21, 0x0c, 0x7d
|
||||
};
|
||||
|
||||
int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k)
|
||||
{
|
||||
return tc_aes128_set_encrypt_key(s, k);
|
||||
}
|
||||
|
||||
#define mult8(a)(_double_byte(_double_byte(_double_byte(a))))
|
||||
#define mult9(a)(mult8(a)^(a))
|
||||
#define multb(a)(mult8(a)^_double_byte(a)^(a))
|
||||
#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a))
|
||||
#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a))
|
||||
|
||||
static inline void mult_row_column(uint8_t *out, const uint8_t *in)
|
||||
{
|
||||
out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]);
|
||||
out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]);
|
||||
out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]);
|
||||
out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]);
|
||||
}
|
||||
|
||||
static inline void inv_mix_columns(uint8_t *s)
|
||||
{
|
||||
uint8_t t[Nb*Nk];
|
||||
|
||||
mult_row_column(t, s);
|
||||
mult_row_column(&t[Nb], s+Nb);
|
||||
mult_row_column(&t[2*Nb], s+(2*Nb));
|
||||
mult_row_column(&t[3*Nb], s+(3*Nb));
|
||||
(void)_copy(s, sizeof(t), t, sizeof(t));
|
||||
}
|
||||
|
||||
static inline void add_round_key(uint8_t *s, const unsigned int *k)
|
||||
{
|
||||
s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
|
||||
s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
|
||||
s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
|
||||
s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
|
||||
s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
|
||||
s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
|
||||
s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
|
||||
s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
|
||||
}
|
||||
|
||||
static inline void inv_sub_bytes(uint8_t *s)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < (Nb*Nk); ++i) {
|
||||
s[i] = inv_sbox[s[i]];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This inv_shift_rows also implements the matrix flip required for
|
||||
* inv_mix_columns, but performs it here to reduce the number of memory
|
||||
* operations.
|
||||
*/
|
||||
static inline void inv_shift_rows(uint8_t *s)
|
||||
{
|
||||
uint8_t t[Nb*Nk];
|
||||
|
||||
t[0] = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7];
|
||||
t[4] = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11];
|
||||
t[8] = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15];
|
||||
t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3];
|
||||
(void)_copy(s, sizeof(t), t, sizeof(t));
|
||||
}
|
||||
|
||||
int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
|
||||
{
|
||||
uint8_t state[Nk*Nb];
|
||||
unsigned int i;
|
||||
|
||||
if (out == (uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (in == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (s == (TCAesKeySched_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void)_copy(state, sizeof(state), in, sizeof(state));
|
||||
|
||||
add_round_key(state, s->words + Nb*Nr);
|
||||
|
||||
for (i = Nr - 1; i > 0; --i) {
|
||||
inv_shift_rows(state);
|
||||
inv_sub_bytes(state);
|
||||
add_round_key(state, s->words + Nb*i);
|
||||
inv_mix_columns(state);
|
||||
}
|
||||
|
||||
inv_shift_rows(state);
|
||||
inv_sub_bytes(state);
|
||||
add_round_key(state, s->words);
|
||||
|
||||
(void)_copy(out, sizeof(state), state, sizeof(state));
|
||||
|
||||
/*zeroing out the state buffer */
|
||||
_set(state, TC_ZERO_BYTE, sizeof(state));
|
||||
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
|
||||
static const uint8_t sbox[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
|
||||
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
||||
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
|
||||
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
|
||||
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
|
||||
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
|
||||
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
|
||||
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
|
||||
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
|
||||
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
|
||||
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
|
||||
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
|
||||
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
|
||||
0xb0, 0x54, 0xbb, 0x16
|
||||
};
|
||||
|
||||
static inline unsigned int rotword(unsigned int a)
|
||||
{
|
||||
return (((a) >> 24)|((a) << 8));
|
||||
}
|
||||
|
||||
#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o))
|
||||
#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0))
|
||||
|
||||
int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k)
|
||||
{
|
||||
const unsigned int rconst[11] = {
|
||||
0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
|
||||
0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
|
||||
};
|
||||
unsigned int i;
|
||||
unsigned int t;
|
||||
|
||||
if (s == (TCAesKeySched_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (k == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
for (i = 0; i < Nk; ++i) {
|
||||
s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) |
|
||||
(k[Nb*i+2]<<8) | (k[Nb*i+3]);
|
||||
}
|
||||
|
||||
for (; i < (Nb * (Nr + 1)); ++i) {
|
||||
t = s->words[i-1];
|
||||
if ((i % Nk) == 0) {
|
||||
t = subword(rotword(t)) ^ rconst[i/Nk];
|
||||
}
|
||||
s->words[i] = s->words[i-Nk] ^ t;
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
static inline void add_round_key(uint8_t *s, const unsigned int *k)
|
||||
{
|
||||
s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
|
||||
s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
|
||||
s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
|
||||
s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
|
||||
s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
|
||||
s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
|
||||
s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
|
||||
s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
|
||||
}
|
||||
|
||||
static inline void sub_bytes(uint8_t *s)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < (Nb * Nk); ++i) {
|
||||
s[i] = sbox[s[i]];
|
||||
}
|
||||
}
|
||||
|
||||
#define triple(a)(_double_byte(a)^(a))
|
||||
|
||||
static inline void mult_row_column(uint8_t *out, const uint8_t *in)
|
||||
{
|
||||
out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3];
|
||||
out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3];
|
||||
out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]);
|
||||
out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]);
|
||||
}
|
||||
|
||||
static inline void mix_columns(uint8_t *s)
|
||||
{
|
||||
uint8_t t[Nb*Nk];
|
||||
|
||||
mult_row_column(t, s);
|
||||
mult_row_column(&t[Nb], s+Nb);
|
||||
mult_row_column(&t[2 * Nb], s + (2 * Nb));
|
||||
mult_row_column(&t[3 * Nb], s + (3 * Nb));
|
||||
(void) _copy(s, sizeof(t), t, sizeof(t));
|
||||
}
|
||||
|
||||
/*
|
||||
* This shift_rows also implements the matrix flip required for mix_columns, but
|
||||
* performs it here to reduce the number of memory operations.
|
||||
*/
|
||||
static inline void shift_rows(uint8_t *s)
|
||||
{
|
||||
uint8_t t[Nb * Nk];
|
||||
|
||||
t[0] = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15];
|
||||
t[4] = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3];
|
||||
t[8] = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7];
|
||||
t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11];
|
||||
(void) _copy(s, sizeof(t), t, sizeof(t));
|
||||
}
|
||||
|
||||
int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
|
||||
{
|
||||
uint8_t state[Nk*Nb];
|
||||
unsigned int i;
|
||||
|
||||
if (out == (uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (in == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (s == (TCAesKeySched_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void)_copy(state, sizeof(state), in, sizeof(state));
|
||||
add_round_key(state, s->words);
|
||||
|
||||
for (i = 0; i < (Nr - 1); ++i) {
|
||||
sub_bytes(state);
|
||||
shift_rows(state);
|
||||
mix_columns(state);
|
||||
add_round_key(state, s->words + Nb*(i+1));
|
||||
}
|
||||
|
||||
sub_bytes(state);
|
||||
shift_rows(state);
|
||||
add_round_key(state, s->words + Nb*(i+1));
|
||||
|
||||
(void)_copy(out, sizeof(state), state, sizeof(state));
|
||||
|
||||
/* zeroing out the state buffer */
|
||||
_set(state, TC_ZERO_BYTE, sizeof(state));
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/cbc_mode.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, const uint8_t *iv,
|
||||
const TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
uint8_t buffer[TC_AES_BLOCK_SIZE];
|
||||
unsigned int n, m;
|
||||
|
||||
/* input sanity check: */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
in == (const uint8_t *) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
inlen == 0 ||
|
||||
outlen == 0 ||
|
||||
(inlen % TC_AES_BLOCK_SIZE) != 0 ||
|
||||
(outlen % TC_AES_BLOCK_SIZE) != 0 ||
|
||||
outlen != inlen + TC_AES_BLOCK_SIZE) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* copy iv to the buffer */
|
||||
(void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
|
||||
/* copy iv to the output buffer */
|
||||
(void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
|
||||
out += TC_AES_BLOCK_SIZE;
|
||||
|
||||
for (n = m = 0; n < inlen; ++n) {
|
||||
buffer[m++] ^= *in++;
|
||||
if (m == TC_AES_BLOCK_SIZE) {
|
||||
(void)tc_aes_encrypt(buffer, buffer, sched);
|
||||
(void)_copy(out, TC_AES_BLOCK_SIZE,
|
||||
buffer, TC_AES_BLOCK_SIZE);
|
||||
out += TC_AES_BLOCK_SIZE;
|
||||
m = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, const uint8_t *iv,
|
||||
const TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
uint8_t buffer[TC_AES_BLOCK_SIZE];
|
||||
const uint8_t *p;
|
||||
unsigned int n, m;
|
||||
|
||||
/* sanity check the inputs */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
in == (const uint8_t *) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
inlen == 0 ||
|
||||
outlen == 0 ||
|
||||
(inlen % TC_AES_BLOCK_SIZE) != 0 ||
|
||||
(outlen % TC_AES_BLOCK_SIZE) != 0 ||
|
||||
outlen != inlen - TC_AES_BLOCK_SIZE) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that in == iv + ciphertext, i.e. the iv and the ciphertext are
|
||||
* contiguous. This allows for a very efficient decryption algorithm
|
||||
* that would not otherwise be possible.
|
||||
*/
|
||||
p = iv;
|
||||
for (n = m = 0; n < inlen; ++n) {
|
||||
if ((n % TC_AES_BLOCK_SIZE) == 0) {
|
||||
(void)tc_aes_decrypt(buffer, in, sched);
|
||||
in += TC_AES_BLOCK_SIZE;
|
||||
m = 0;
|
||||
}
|
||||
*out++ = buffer[m++] ^ *p++;
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/* ccm_mode.c - TinyCrypt implementation of CCM mode */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/ccm_mode.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
|
||||
unsigned int nlen, unsigned int mlen)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (c == (TCCcmMode_t) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
nonce == (uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (nlen != 13) {
|
||||
return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/
|
||||
} else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
|
||||
return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
|
||||
}
|
||||
|
||||
c->mlen = mlen;
|
||||
c->sched = sched;
|
||||
c->nonce = nonce;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variation of CBC-MAC mode used in CCM.
|
||||
*/
|
||||
static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen,
|
||||
unsigned int flag, TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
unsigned int i;
|
||||
|
||||
if (flag > 0) {
|
||||
T[0] ^= (uint8_t)(dlen >> 8);
|
||||
T[1] ^= (uint8_t)(dlen);
|
||||
dlen += 2; i = 2;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
while (i < dlen) {
|
||||
T[i++ % (Nb * Nk)] ^= *data++;
|
||||
if (((i % (Nb * Nk)) == 0) || dlen == i) {
|
||||
(void) tc_aes_encrypt(T, T, sched);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Variation of CTR mode used in CCM.
|
||||
* The CTR mode used by CCM is slightly different than the conventional CTR
|
||||
* mode (the counter is increased before encryption, instead of after
|
||||
* encryption). Besides, it is assumed that the counter is stored in the last
|
||||
* 2 bytes of the nonce.
|
||||
*/
|
||||
static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
uint8_t buffer[TC_AES_BLOCK_SIZE];
|
||||
uint8_t nonce[TC_AES_BLOCK_SIZE];
|
||||
uint16_t block_num;
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
in == (uint8_t *) 0 ||
|
||||
ctr == (uint8_t *) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
inlen == 0 ||
|
||||
outlen == 0 ||
|
||||
outlen != inlen) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* copy the counter to the nonce */
|
||||
(void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
|
||||
|
||||
/* select the last 2 bytes of the nonce to be incremented */
|
||||
block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
|
||||
for (i = 0; i < inlen; ++i) {
|
||||
if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
|
||||
block_num++;
|
||||
nonce[14] = (uint8_t)(block_num >> 8);
|
||||
nonce[15] = (uint8_t)(block_num);
|
||||
if (!tc_aes_encrypt(buffer, nonce, sched)) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
}
|
||||
/* update the output */
|
||||
*out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
|
||||
}
|
||||
|
||||
/* update the counter */
|
||||
ctr[14] = nonce[14]; ctr[15] = nonce[15];
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
|
||||
const uint8_t *associated_data,
|
||||
unsigned int alen, const uint8_t *payload,
|
||||
unsigned int plen, TCCcmMode_t c)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if ((out == (uint8_t *) 0) ||
|
||||
(c == (TCCcmMode_t) 0) ||
|
||||
((plen > 0) && (payload == (uint8_t *) 0)) ||
|
||||
((alen > 0) && (associated_data == (uint8_t *) 0)) ||
|
||||
(alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
|
||||
(plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
|
||||
(olen < (plen + c->mlen))) { /* invalid output buffer size */
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
uint8_t b[Nb * Nk];
|
||||
uint8_t tag[Nb * Nk];
|
||||
unsigned int i;
|
||||
|
||||
/* GENERATING THE AUTHENTICATION TAG: */
|
||||
|
||||
/* formatting the sequence b for authentication: */
|
||||
b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
|
||||
for (i = 1; i <= 13; ++i) {
|
||||
b[i] = c->nonce[i - 1];
|
||||
}
|
||||
b[14] = (uint8_t)(plen >> 8);
|
||||
b[15] = (uint8_t)(plen);
|
||||
|
||||
/* computing the authentication tag using cbc-mac: */
|
||||
(void) tc_aes_encrypt(tag, b, c->sched);
|
||||
if (alen > 0) {
|
||||
ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
|
||||
}
|
||||
if (plen > 0) {
|
||||
ccm_cbc_mac(tag, payload, plen, 0, c->sched);
|
||||
}
|
||||
|
||||
/* ENCRYPTION: */
|
||||
|
||||
/* formatting the sequence b for encryption: */
|
||||
b[0] = 1; /* q - 1 = 2 - 1 = 1 */
|
||||
b[14] = b[15] = TC_ZERO_BYTE;
|
||||
|
||||
/* encrypting payload using ctr mode: */
|
||||
ccm_ctr_mode(out, plen, payload, plen, b, c->sched);
|
||||
|
||||
b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/
|
||||
|
||||
/* encrypting b and adding the tag to the output: */
|
||||
(void) tc_aes_encrypt(b, b, c->sched);
|
||||
out += plen;
|
||||
for (i = 0; i < c->mlen; ++i) {
|
||||
*out++ = tag[i] ^ b[i];
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
|
||||
const uint8_t *associated_data,
|
||||
unsigned int alen, const uint8_t *payload,
|
||||
unsigned int plen, TCCcmMode_t c)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if ((out == (uint8_t *) 0) ||
|
||||
(c == (TCCcmMode_t) 0) ||
|
||||
((plen > 0) && (payload == (uint8_t *) 0)) ||
|
||||
((alen > 0) && (associated_data == (uint8_t *) 0)) ||
|
||||
(alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
|
||||
(plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
|
||||
(olen < plen - c->mlen)) { /* invalid output buffer size */
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
uint8_t b[Nb * Nk];
|
||||
uint8_t tag[Nb * Nk];
|
||||
unsigned int i;
|
||||
|
||||
/* DECRYPTION: */
|
||||
|
||||
/* formatting the sequence b for decryption: */
|
||||
b[0] = 1; /* q - 1 = 2 - 1 = 1 */
|
||||
for (i = 1; i < 14; ++i) {
|
||||
b[i] = c->nonce[i - 1];
|
||||
}
|
||||
b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */
|
||||
|
||||
/* decrypting payload using ctr mode: */
|
||||
ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);
|
||||
|
||||
b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */
|
||||
|
||||
/* encrypting b and restoring the tag from input: */
|
||||
(void) tc_aes_encrypt(b, b, c->sched);
|
||||
for (i = 0; i < c->mlen; ++i) {
|
||||
tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
|
||||
}
|
||||
|
||||
/* VERIFYING THE AUTHENTICATION TAG: */
|
||||
|
||||
/* formatting the sequence b for authentication: */
|
||||
b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
|
||||
for (i = 1; i < 14; ++i) {
|
||||
b[i] = c->nonce[i - 1];
|
||||
}
|
||||
b[14] = (uint8_t)((plen - c->mlen) >> 8);
|
||||
b[15] = (uint8_t)(plen - c->mlen);
|
||||
|
||||
/* computing the authentication tag using cbc-mac: */
|
||||
(void) tc_aes_encrypt(b, b, c->sched);
|
||||
if (alen > 0) {
|
||||
ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
|
||||
}
|
||||
if (plen > 0) {
|
||||
ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
|
||||
}
|
||||
|
||||
/* comparing the received tag and the computed one: */
|
||||
if (_compare(b, tag, c->mlen) == 0) {
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
} else {
|
||||
/* erase the decrypted buffer in case of mac validation failure: */
|
||||
_set(out, 0, plen - c->mlen);
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
/* cmac_mode.c - TinyCrypt CMAC mode implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/cmac_mode.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
/* max number of calls until change the key (2^48).*/
|
||||
const static uint64_t MAX_CALLS = ((uint64_t)1 << 48);
|
||||
|
||||
/*
|
||||
* gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte
|
||||
* array with byte 0 the most significant and byte 15 the least significant.
|
||||
* High bit carry reduction is based on the primitive polynomial
|
||||
*
|
||||
* X^128 + X^7 + X^2 + X + 1,
|
||||
*
|
||||
* which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed,
|
||||
* since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since
|
||||
* addition of polynomials with coefficients in Z/Z(2) is just XOR, we can
|
||||
* add X^128 to both sides to get
|
||||
*
|
||||
* X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1)
|
||||
*
|
||||
* and the coefficients of the polynomial on the right hand side form the
|
||||
* string 1000 0111 = 0x87, which is the value of gf_wrap.
|
||||
*
|
||||
* This gets used in the following way. Doubling in GF(2^128) is just a left
|
||||
* shift by 1 bit, except when the most significant bit is 1. In the latter
|
||||
* case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit
|
||||
* that overflows beyond 128 bits can be replaced by addition of
|
||||
* X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition
|
||||
* in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87
|
||||
* into the low order byte after a left shift when the starting high order
|
||||
* bit is 1.
|
||||
*/
|
||||
const unsigned char gf_wrap = 0x87;
|
||||
|
||||
/*
|
||||
* assumes: out != NULL and points to a GF(2^n) value to receive the
|
||||
* doubled value;
|
||||
* in != NULL and points to a 16 byte GF(2^n) value
|
||||
* to double;
|
||||
* the in and out buffers do not overlap.
|
||||
* effects: doubles the GF(2^n) value pointed to by "in" and places
|
||||
* the result in the GF(2^n) value pointed to by "out."
|
||||
*/
|
||||
void gf_double(uint8_t *out, uint8_t *in)
|
||||
{
|
||||
|
||||
/* start with low order byte */
|
||||
uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1);
|
||||
|
||||
/* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */
|
||||
uint8_t carry = (in[0] >> 7) ? gf_wrap : 0;
|
||||
|
||||
out += (TC_AES_BLOCK_SIZE - 1);
|
||||
for (;;) {
|
||||
*out-- = (*x << 1) ^ carry;
|
||||
if (x == in) {
|
||||
break;
|
||||
}
|
||||
carry = *x-- >> 7;
|
||||
}
|
||||
}
|
||||
|
||||
int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (s == (TCCmacState_t) 0 ||
|
||||
key == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* put s into a known state */
|
||||
_set(s, 0, sizeof(*s));
|
||||
s->sched = sched;
|
||||
|
||||
/* configure the encryption key used by the underlying block cipher */
|
||||
tc_aes128_set_encrypt_key(s->sched, key);
|
||||
|
||||
/* compute s->K1 and s->K2 from s->iv using s->keyid */
|
||||
_set(s->iv, 0, TC_AES_BLOCK_SIZE);
|
||||
tc_aes_encrypt(s->iv, s->iv, s->sched);
|
||||
gf_double (s->K1, s->iv);
|
||||
gf_double (s->K2, s->K1);
|
||||
|
||||
/* reset s->iv to 0 in case someone wants to compute now */
|
||||
tc_cmac_init(s);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cmac_erase(TCCmacState_t s)
|
||||
{
|
||||
if (s == (TCCmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* destroy the current state */
|
||||
_set(s, 0, sizeof(*s));
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cmac_init(TCCmacState_t s)
|
||||
{
|
||||
/* input sanity check: */
|
||||
if (s == (TCCmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* CMAC starts with an all zero initialization vector */
|
||||
_set(s->iv, 0, TC_AES_BLOCK_SIZE);
|
||||
|
||||
/* and the leftover buffer is empty */
|
||||
_set(s->leftover, 0, TC_AES_BLOCK_SIZE);
|
||||
s->leftover_offset = 0;
|
||||
|
||||
/* Set countdown to max number of calls allowed before re-keying: */
|
||||
s->countdown = MAX_CALLS;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (s == (TCCmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
if (data_length == 0) {
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
if (data == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
if (s->countdown == 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
s->countdown--;
|
||||
|
||||
if (s->leftover_offset > 0) {
|
||||
/* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */
|
||||
size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset;
|
||||
|
||||
if (data_length < remaining_space) {
|
||||
/* still not enough data to encrypt this time either */
|
||||
_copy(&s->leftover[s->leftover_offset], data_length, data, data_length);
|
||||
s->leftover_offset += data_length;
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
/* leftover block is now full; encrypt it first */
|
||||
_copy(&s->leftover[s->leftover_offset],
|
||||
remaining_space,
|
||||
data,
|
||||
remaining_space);
|
||||
data_length -= remaining_space;
|
||||
data += remaining_space;
|
||||
s->leftover_offset = 0;
|
||||
|
||||
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
|
||||
s->iv[i] ^= s->leftover[i];
|
||||
}
|
||||
tc_aes_encrypt(s->iv, s->iv, s->sched);
|
||||
}
|
||||
|
||||
/* CBC encrypt each (except the last) of the data blocks */
|
||||
while (data_length > TC_AES_BLOCK_SIZE) {
|
||||
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
|
||||
s->iv[i] ^= data[i];
|
||||
}
|
||||
tc_aes_encrypt(s->iv, s->iv, s->sched);
|
||||
data += TC_AES_BLOCK_SIZE;
|
||||
data_length -= TC_AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if (data_length > 0) {
|
||||
/* save leftover data for next time */
|
||||
_copy(s->leftover, data_length, data, data_length);
|
||||
s->leftover_offset = data_length;
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cmac_final(uint8_t *tag, TCCmacState_t s)
|
||||
{
|
||||
uint8_t *k;
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (tag == (uint8_t *) 0 ||
|
||||
s == (TCCmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
if (s->leftover_offset == TC_AES_BLOCK_SIZE) {
|
||||
/* the last message block is a full-sized block */
|
||||
k = (uint8_t *) s->K1;
|
||||
} else {
|
||||
/* the final message block is not a full-sized block */
|
||||
size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset;
|
||||
|
||||
_set(&s->leftover[s->leftover_offset], 0, remaining);
|
||||
s->leftover[s->leftover_offset] = TC_CMAC_PADDING;
|
||||
k = (uint8_t *) s->K2;
|
||||
}
|
||||
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
|
||||
s->iv[i] ^= s->leftover[i] ^ k[i];
|
||||
}
|
||||
|
||||
tc_aes_encrypt(tag, s->iv, s->sched);
|
||||
|
||||
/* erasing state: */
|
||||
tc_cmac_erase(s);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/* ctr_mode.c - TinyCrypt CTR mode implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/ctr_mode.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
uint8_t buffer[TC_AES_BLOCK_SIZE];
|
||||
uint8_t nonce[TC_AES_BLOCK_SIZE];
|
||||
unsigned int block_num;
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
in == (uint8_t *) 0 ||
|
||||
ctr == (uint8_t *) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
inlen == 0 ||
|
||||
outlen == 0 ||
|
||||
outlen != inlen) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* copy the ctr to the nonce */
|
||||
(void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
|
||||
|
||||
/* select the last 4 bytes of the nonce to be incremented */
|
||||
block_num = (nonce[12] << 24) | (nonce[13] << 16) |
|
||||
(nonce[14] << 8) | (nonce[15]);
|
||||
for (i = 0; i < inlen; ++i) {
|
||||
if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
|
||||
/* encrypt data using the current nonce */
|
||||
if (tc_aes_encrypt(buffer, nonce, sched)) {
|
||||
block_num++;
|
||||
nonce[12] = (uint8_t)(block_num >> 24);
|
||||
nonce[13] = (uint8_t)(block_num >> 16);
|
||||
nonce[14] = (uint8_t)(block_num >> 8);
|
||||
nonce[15] = (uint8_t)(block_num);
|
||||
} else {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
}
|
||||
/* update the output */
|
||||
*out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++;
|
||||
}
|
||||
|
||||
/* update the counter */
|
||||
ctr[12] = nonce[12]; ctr[13] = nonce[13];
|
||||
ctr[14] = nonce[14]; ctr[15] = nonce[15];
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016, Chris Morrison
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/ctr_prng.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* This PRNG is based on the CTR_DRBG described in Recommendation for Random
|
||||
* Number Generation Using Deterministic Random Bit Generators,
|
||||
* NIST SP 800-90A Rev. 1.
|
||||
*
|
||||
* Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps
|
||||
* described in that document.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Array incrementer
|
||||
* Treats the supplied array as one contiguous number (MSB in arr[0]), and
|
||||
* increments it by one
|
||||
* @return none
|
||||
* @param arr IN/OUT -- array to be incremented
|
||||
* @param len IN -- size of arr in bytes
|
||||
*/
|
||||
static void arrInc(uint8_t arr[], unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
if (0 != arr) {
|
||||
for (i = len; i > 0U; i--) {
|
||||
if (++arr[i-1] != 0U) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CTR PRNG update
|
||||
* Updates the internal state of supplied the CTR PRNG context
|
||||
* increments it by one
|
||||
* @return none
|
||||
* @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long
|
||||
* @param ctx IN/OUT -- CTR PRNG state
|
||||
* @param providedData IN -- data used when updating the internal state
|
||||
*/
|
||||
static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData)
|
||||
{
|
||||
if (0 != ctx) {
|
||||
/* 10.2.1.2 step 1 */
|
||||
uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
|
||||
unsigned int len = 0U;
|
||||
|
||||
/* 10.2.1.2 step 2 */
|
||||
while (len < sizeof temp) {
|
||||
unsigned int blocklen = sizeof(temp) - len;
|
||||
uint8_t output_block[TC_AES_BLOCK_SIZE];
|
||||
|
||||
/* 10.2.1.2 step 2.1 */
|
||||
arrInc(ctx->V, sizeof ctx->V);
|
||||
|
||||
/* 10.2.1.2 step 2.2 */
|
||||
if (blocklen > TC_AES_BLOCK_SIZE) {
|
||||
blocklen = TC_AES_BLOCK_SIZE;
|
||||
}
|
||||
(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
|
||||
|
||||
/* 10.2.1.2 step 2.3/step 3 */
|
||||
memcpy(&(temp[len]), output_block, blocklen);
|
||||
|
||||
len += blocklen;
|
||||
}
|
||||
|
||||
/* 10.2.1.2 step 4 */
|
||||
if (0 != providedData) {
|
||||
unsigned int i;
|
||||
for (i = 0U; i < sizeof temp; i++) {
|
||||
temp[i] ^= providedData[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* 10.2.1.2 step 5 */
|
||||
(void)tc_aes128_set_encrypt_key(&ctx->key, temp);
|
||||
|
||||
/* 10.2.1.2 step 6 */
|
||||
memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const entropy,
|
||||
unsigned int entropyLen,
|
||||
uint8_t const * const personalization,
|
||||
unsigned int pLen)
|
||||
{
|
||||
int result = TC_CRYPTO_FAIL;
|
||||
unsigned int i;
|
||||
uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
|
||||
uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
|
||||
uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U};
|
||||
|
||||
if (0 != personalization) {
|
||||
/* 10.2.1.3.1 step 1 */
|
||||
unsigned int len = pLen;
|
||||
if (len > sizeof personalization_buf) {
|
||||
len = sizeof personalization_buf;
|
||||
}
|
||||
|
||||
/* 10.2.1.3.1 step 2 */
|
||||
memcpy(personalization_buf, personalization, len);
|
||||
}
|
||||
|
||||
if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) {
|
||||
/* 10.2.1.3.1 step 3 */
|
||||
memcpy(seed_material, entropy, sizeof seed_material);
|
||||
for (i = 0U; i < sizeof seed_material; i++) {
|
||||
seed_material[i] ^= personalization_buf[i];
|
||||
}
|
||||
|
||||
/* 10.2.1.3.1 step 4 */
|
||||
(void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr);
|
||||
|
||||
/* 10.2.1.3.1 step 5 */
|
||||
memset(ctx->V, 0x00, sizeof ctx->V);
|
||||
|
||||
/* 10.2.1.3.1 step 6 */
|
||||
tc_ctr_prng_update(ctx, seed_material);
|
||||
|
||||
/* 10.2.1.3.1 step 7 */
|
||||
ctx->reseedCount = 1U;
|
||||
|
||||
result = TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const entropy,
|
||||
unsigned int entropyLen,
|
||||
uint8_t const * const additional_input,
|
||||
unsigned int additionallen)
|
||||
{
|
||||
unsigned int i;
|
||||
int result = TC_CRYPTO_FAIL;
|
||||
uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
|
||||
uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
|
||||
|
||||
if (0 != additional_input) {
|
||||
/* 10.2.1.4.1 step 1 */
|
||||
unsigned int len = additionallen;
|
||||
if (len > sizeof additional_input_buf) {
|
||||
len = sizeof additional_input_buf;
|
||||
}
|
||||
|
||||
/* 10.2.1.4.1 step 2 */
|
||||
memcpy(additional_input_buf, additional_input, len);
|
||||
}
|
||||
|
||||
unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE;
|
||||
if ((0 != ctx) && (entropyLen >= seedlen)) {
|
||||
/* 10.2.1.4.1 step 3 */
|
||||
memcpy(seed_material, entropy, sizeof seed_material);
|
||||
for (i = 0U; i < sizeof seed_material; i++) {
|
||||
seed_material[i] ^= additional_input_buf[i];
|
||||
}
|
||||
|
||||
/* 10.2.1.4.1 step 4 */
|
||||
tc_ctr_prng_update(ctx, seed_material);
|
||||
|
||||
/* 10.2.1.4.1 step 5 */
|
||||
ctx->reseedCount = 1U;
|
||||
|
||||
result = TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const additional_input,
|
||||
unsigned int additionallen,
|
||||
uint8_t * const out,
|
||||
unsigned int outlen)
|
||||
{
|
||||
/* 2^48 - see section 10.2.1 */
|
||||
static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL;
|
||||
|
||||
/* 2^19 bits - see section 10.2.1 */
|
||||
static const unsigned int MAX_BYTES_PER_REQ = 65536U;
|
||||
|
||||
unsigned int result = TC_CRYPTO_FAIL;
|
||||
|
||||
if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) {
|
||||
/* 10.2.1.5.1 step 1 */
|
||||
if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) {
|
||||
result = TC_CTR_PRNG_RESEED_REQ;
|
||||
} else {
|
||||
uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
|
||||
if (0 != additional_input) {
|
||||
/* 10.2.1.5.1 step 2 */
|
||||
unsigned int len = additionallen;
|
||||
if (len > sizeof additional_input_buf) {
|
||||
len = sizeof additional_input_buf;
|
||||
}
|
||||
memcpy(additional_input_buf, additional_input, len);
|
||||
tc_ctr_prng_update(ctx, additional_input_buf);
|
||||
}
|
||||
|
||||
/* 10.2.1.5.1 step 3 - implicit */
|
||||
|
||||
/* 10.2.1.5.1 step 4 */
|
||||
unsigned int len = 0U;
|
||||
while (len < outlen) {
|
||||
unsigned int blocklen = outlen - len;
|
||||
uint8_t output_block[TC_AES_BLOCK_SIZE];
|
||||
|
||||
/* 10.2.1.5.1 step 4.1 */
|
||||
arrInc(ctx->V, sizeof ctx->V);
|
||||
|
||||
/* 10.2.1.5.1 step 4.2 */
|
||||
(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
|
||||
|
||||
/* 10.2.1.5.1 step 4.3/step 5 */
|
||||
if (blocklen > TC_AES_BLOCK_SIZE) {
|
||||
blocklen = TC_AES_BLOCK_SIZE;
|
||||
}
|
||||
memcpy(&(out[len]), output_block, blocklen);
|
||||
|
||||
len += blocklen;
|
||||
}
|
||||
|
||||
/* 10.2.1.5.1 step 6 */
|
||||
tc_ctr_prng_update(ctx, additional_input_buf);
|
||||
|
||||
/* 10.2.1.5.1 step 7 */
|
||||
ctx->reseedCount++;
|
||||
|
||||
/* 10.2.1.5.1 step 8 */
|
||||
result = TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx)
|
||||
{
|
||||
if (0 != ctx) {
|
||||
memset(ctx->key.words, 0x00, sizeof ctx->key.words);
|
||||
memset(ctx->V, 0x00, sizeof ctx->V);
|
||||
ctx->reseedCount = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,942 @@
|
||||
/* ecc.c - TinyCrypt implementation of common ECC functions */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/ecc.h>
|
||||
#include <tinycrypt/ecc_platform_specific.h>
|
||||
#include <string.h>
|
||||
|
||||
/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
|
||||
* has access to enough entropy in order to feed the PRNG regularly. */
|
||||
#if default_RNG_defined
|
||||
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
|
||||
#else
|
||||
static uECC_RNG_Function g_rng_function = 0;
|
||||
#endif
|
||||
|
||||
void uECC_set_rng(uECC_RNG_Function rng_function)
|
||||
{
|
||||
g_rng_function = rng_function;
|
||||
}
|
||||
|
||||
uECC_RNG_Function uECC_get_rng(void)
|
||||
{
|
||||
return g_rng_function;
|
||||
}
|
||||
|
||||
int uECC_curve_private_key_size(uECC_Curve curve)
|
||||
{
|
||||
return BITS_TO_BYTES(curve->num_n_bits);
|
||||
}
|
||||
|
||||
int uECC_curve_public_key_size(uECC_Curve curve)
|
||||
{
|
||||
return 2 * curve->num_bytes;
|
||||
}
|
||||
|
||||
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words)
|
||||
{
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
vli[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t bits = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
bits |= vli[i];
|
||||
}
|
||||
return (bits == 0);
|
||||
}
|
||||
|
||||
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
|
||||
{
|
||||
return (vli[bit >> uECC_WORD_BITS_SHIFT] &
|
||||
((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
|
||||
}
|
||||
|
||||
/* Counts the number of words in vli. */
|
||||
static wordcount_t vli_numDigits(const uECC_word_t *vli,
|
||||
const wordcount_t max_words)
|
||||
{
|
||||
|
||||
wordcount_t i;
|
||||
/* Search from the end until we find a non-zero digit. We do it in reverse
|
||||
* because we expect that most digits will be nonzero. */
|
||||
for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
|
||||
}
|
||||
|
||||
return (i + 1);
|
||||
}
|
||||
|
||||
bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
|
||||
const wordcount_t max_words)
|
||||
{
|
||||
|
||||
uECC_word_t i;
|
||||
uECC_word_t digit;
|
||||
|
||||
wordcount_t num_digits = vli_numDigits(vli, max_words);
|
||||
if (num_digits == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
digit = vli[num_digits - 1];
|
||||
for (i = 0; digit; ++i) {
|
||||
digit >>= 1;
|
||||
}
|
||||
|
||||
return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
|
||||
}
|
||||
|
||||
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
wordcount_t i;
|
||||
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
wordcount_t i;
|
||||
|
||||
for (i = num_words - 1; i >= 0; --i) {
|
||||
if (left[i] > right[i]) {
|
||||
return 1;
|
||||
} else if (left[i] < right[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
|
||||
uECC_word_t diff = 0;
|
||||
wordcount_t i;
|
||||
|
||||
for (i = num_words - 1; i >= 0; --i) {
|
||||
diff |= (left[i] ^ right[i]);
|
||||
}
|
||||
return !(diff == 0);
|
||||
}
|
||||
|
||||
uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
|
||||
{
|
||||
return (p_true*(cond)) | (p_false*(!cond));
|
||||
}
|
||||
|
||||
/* Computes result = left - right, returning borrow, in constant time.
|
||||
* Can modify in place. */
|
||||
uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t borrow = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
uECC_word_t diff = left[i] - right[i] - borrow;
|
||||
uECC_word_t val = (diff > left[i]);
|
||||
borrow = cond_set(val, borrow, (diff != left[i]));
|
||||
|
||||
result[i] = diff;
|
||||
}
|
||||
return borrow;
|
||||
}
|
||||
|
||||
/* Computes result = left + right, returning carry, in constant time.
|
||||
* Can modify in place. */
|
||||
static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t carry = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
uECC_word_t sum = left[i] + right[i] + carry;
|
||||
uECC_word_t val = (sum < left[i]);
|
||||
carry = cond_set(val, carry, (sum != left[i]));
|
||||
result[i] = sum;
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t tmp[NUM_ECC_WORDS];
|
||||
uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
|
||||
uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
|
||||
return (!equal - 2 * neg);
|
||||
}
|
||||
|
||||
/* Computes vli = vli >> 1. */
|
||||
static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t *end = vli;
|
||||
uECC_word_t carry = 0;
|
||||
|
||||
vli += num_words;
|
||||
while (vli-- > end) {
|
||||
uECC_word_t temp = *vli;
|
||||
*vli = (temp >> 1) | carry;
|
||||
carry = temp << (uECC_WORD_BITS - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0,
|
||||
uECC_word_t *r1, uECC_word_t *r2)
|
||||
{
|
||||
|
||||
uECC_dword_t p = (uECC_dword_t)a * b;
|
||||
uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
|
||||
r01 += p;
|
||||
*r2 += (r01 < p);
|
||||
*r1 = r01 >> uECC_WORD_BITS;
|
||||
*r0 = (uECC_word_t)r01;
|
||||
|
||||
}
|
||||
|
||||
/* Computes result = left * right. Result must be 2 * num_words long. */
|
||||
static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words)
|
||||
{
|
||||
|
||||
uECC_word_t r0 = 0;
|
||||
uECC_word_t r1 = 0;
|
||||
uECC_word_t r2 = 0;
|
||||
wordcount_t i, k;
|
||||
|
||||
/* Compute each digit of result in sequence, maintaining the carries. */
|
||||
for (k = 0; k < num_words; ++k) {
|
||||
|
||||
for (i = 0; i <= k; ++i) {
|
||||
muladd(left[i], right[k - i], &r0, &r1, &r2);
|
||||
}
|
||||
|
||||
result[k] = r0;
|
||||
r0 = r1;
|
||||
r1 = r2;
|
||||
r2 = 0;
|
||||
}
|
||||
|
||||
for (k = num_words; k < num_words * 2 - 1; ++k) {
|
||||
|
||||
for (i = (k + 1) - num_words; i < num_words; ++i) {
|
||||
muladd(left[i], right[k - i], &r0, &r1, &r2);
|
||||
}
|
||||
result[k] = r0;
|
||||
r0 = r1;
|
||||
r1 = r2;
|
||||
r2 = 0;
|
||||
}
|
||||
result[num_words * 2 - 1] = r0;
|
||||
}
|
||||
|
||||
void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
|
||||
if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
|
||||
/* result > mod (result = mod + remainder), so subtract mod to get
|
||||
* remainder. */
|
||||
uECC_vli_sub(result, result, mod, num_words);
|
||||
}
|
||||
}
|
||||
|
||||
void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
|
||||
if (l_borrow) {
|
||||
/* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
|
||||
* we can get the correct result from result + mod (with overflow). */
|
||||
uECC_vli_add(result, result, mod, num_words);
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes result = product % mod, where product is 2N words long. */
|
||||
/* Currently only designed to work for curve_p or curve_n. */
|
||||
void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
|
||||
const uECC_word_t *mod, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
|
||||
uECC_word_t tmp[2 * NUM_ECC_WORDS];
|
||||
uECC_word_t *v[2] = {tmp, product};
|
||||
uECC_word_t index;
|
||||
|
||||
/* Shift mod so its highest set bit is at the maximum position. */
|
||||
bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
|
||||
uECC_vli_numBits(mod, num_words);
|
||||
wordcount_t word_shift = shift / uECC_WORD_BITS;
|
||||
wordcount_t bit_shift = shift % uECC_WORD_BITS;
|
||||
uECC_word_t carry = 0;
|
||||
uECC_vli_clear(mod_multiple, word_shift);
|
||||
if (bit_shift > 0) {
|
||||
for(index = 0; index < (uECC_word_t)num_words; ++index) {
|
||||
mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
|
||||
carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
|
||||
}
|
||||
} else {
|
||||
uECC_vli_set(mod_multiple + word_shift, mod, num_words);
|
||||
}
|
||||
|
||||
for (index = 1; shift >= 0; --shift) {
|
||||
uECC_word_t borrow = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words * 2; ++i) {
|
||||
uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
|
||||
if (diff != v[index][i]) {
|
||||
borrow = (diff > v[index][i]);
|
||||
}
|
||||
v[1 - index][i] = diff;
|
||||
}
|
||||
/* Swap the index if there was no borrow */
|
||||
index = !(index ^ borrow);
|
||||
uECC_vli_rshift1(mod_multiple, num_words);
|
||||
mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
|
||||
(uECC_WORD_BITS - 1);
|
||||
uECC_vli_rshift1(mod_multiple + num_words, num_words);
|
||||
}
|
||||
uECC_vli_set(result, v[index], num_words);
|
||||
}
|
||||
|
||||
void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t product[2 * NUM_ECC_WORDS];
|
||||
uECC_vli_mult(product, left, right, num_words);
|
||||
uECC_vli_mmod(result, product, mod, num_words);
|
||||
}
|
||||
|
||||
void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t product[2 * NUM_ECC_WORDS];
|
||||
uECC_vli_mult(product, left, right, curve->num_words);
|
||||
|
||||
curve->mmod_fast(result, product);
|
||||
}
|
||||
|
||||
static void uECC_vli_modSquare_fast(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
uECC_vli_modMult_fast(result, left, left, curve);
|
||||
}
|
||||
|
||||
|
||||
#define EVEN(vli) (!(vli[0] & 1))
|
||||
|
||||
static void vli_modInv_update(uECC_word_t *uv,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
|
||||
uECC_word_t carry = 0;
|
||||
|
||||
if (!EVEN(uv)) {
|
||||
carry = uECC_vli_add(uv, uv, mod, num_words);
|
||||
}
|
||||
uECC_vli_rshift1(uv, num_words);
|
||||
if (carry) {
|
||||
uv[num_words - 1] |= HIGH_BIT_SET;
|
||||
}
|
||||
}
|
||||
|
||||
void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
|
||||
const uECC_word_t *mod, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
|
||||
uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
|
||||
cmpresult_t cmpResult;
|
||||
|
||||
if (uECC_vli_isZero(input, num_words)) {
|
||||
uECC_vli_clear(result, num_words);
|
||||
return;
|
||||
}
|
||||
|
||||
uECC_vli_set(a, input, num_words);
|
||||
uECC_vli_set(b, mod, num_words);
|
||||
uECC_vli_clear(u, num_words);
|
||||
u[0] = 1;
|
||||
uECC_vli_clear(v, num_words);
|
||||
while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
|
||||
if (EVEN(a)) {
|
||||
uECC_vli_rshift1(a, num_words);
|
||||
vli_modInv_update(u, mod, num_words);
|
||||
} else if (EVEN(b)) {
|
||||
uECC_vli_rshift1(b, num_words);
|
||||
vli_modInv_update(v, mod, num_words);
|
||||
} else if (cmpResult > 0) {
|
||||
uECC_vli_sub(a, a, b, num_words);
|
||||
uECC_vli_rshift1(a, num_words);
|
||||
if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
|
||||
uECC_vli_add(u, u, mod, num_words);
|
||||
}
|
||||
uECC_vli_sub(u, u, v, num_words);
|
||||
vli_modInv_update(u, mod, num_words);
|
||||
} else {
|
||||
uECC_vli_sub(b, b, a, num_words);
|
||||
uECC_vli_rshift1(b, num_words);
|
||||
if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
|
||||
uECC_vli_add(v, v, mod, num_words);
|
||||
}
|
||||
uECC_vli_sub(v, v, u, num_words);
|
||||
vli_modInv_update(v, mod, num_words);
|
||||
}
|
||||
}
|
||||
uECC_vli_set(result, u, num_words);
|
||||
}
|
||||
|
||||
/* ------ Point operations ------ */
|
||||
|
||||
void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * Z1, uECC_Curve curve)
|
||||
{
|
||||
/* t1 = X, t2 = Y, t3 = Z */
|
||||
uECC_word_t t4[NUM_ECC_WORDS];
|
||||
uECC_word_t t5[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
if (uECC_vli_isZero(Z1, num_words)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
|
||||
uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
|
||||
uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
|
||||
uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
|
||||
uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
|
||||
|
||||
uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
|
||||
uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
|
||||
uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
|
||||
uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
|
||||
|
||||
uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
|
||||
uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
|
||||
if (uECC_vli_testBit(X1, 0)) {
|
||||
uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
|
||||
uECC_vli_rshift1(X1, num_words);
|
||||
X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
|
||||
} else {
|
||||
uECC_vli_rshift1(X1, num_words);
|
||||
}
|
||||
|
||||
/* t1 = 3/2*(x1^2 - z1^4) = B */
|
||||
uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
|
||||
uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
|
||||
uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
|
||||
uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
|
||||
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
|
||||
/* t4 = B * (A - x3) - y1^4 = y3: */
|
||||
uECC_vli_modSub(t4, X1, t4, curve->p, num_words);
|
||||
|
||||
uECC_vli_set(X1, Z1, num_words);
|
||||
uECC_vli_set(Z1, Y1, num_words);
|
||||
uECC_vli_set(Y1, t4, num_words);
|
||||
}
|
||||
|
||||
void x_side_default(uECC_word_t *result,
|
||||
const uECC_word_t *x,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
|
||||
uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
|
||||
uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
|
||||
/* r = x^3 - 3x + b: */
|
||||
uECC_vli_modAdd(result, result, curve->b, curve->p, num_words);
|
||||
}
|
||||
|
||||
uECC_Curve uECC_secp256r1(void)
|
||||
{
|
||||
return &curve_secp256r1;
|
||||
}
|
||||
|
||||
void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
|
||||
{
|
||||
unsigned int tmp[NUM_ECC_WORDS];
|
||||
int carry;
|
||||
|
||||
/* t */
|
||||
uECC_vli_set(result, product, NUM_ECC_WORDS);
|
||||
|
||||
/* s1 */
|
||||
tmp[0] = tmp[1] = tmp[2] = 0;
|
||||
tmp[3] = product[11];
|
||||
tmp[4] = product[12];
|
||||
tmp[5] = product[13];
|
||||
tmp[6] = product[14];
|
||||
tmp[7] = product[15];
|
||||
carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
|
||||
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* s2 */
|
||||
tmp[3] = product[12];
|
||||
tmp[4] = product[13];
|
||||
tmp[5] = product[14];
|
||||
tmp[6] = product[15];
|
||||
tmp[7] = 0;
|
||||
carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
|
||||
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* s3 */
|
||||
tmp[0] = product[8];
|
||||
tmp[1] = product[9];
|
||||
tmp[2] = product[10];
|
||||
tmp[3] = tmp[4] = tmp[5] = 0;
|
||||
tmp[6] = product[14];
|
||||
tmp[7] = product[15];
|
||||
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* s4 */
|
||||
tmp[0] = product[9];
|
||||
tmp[1] = product[10];
|
||||
tmp[2] = product[11];
|
||||
tmp[3] = product[13];
|
||||
tmp[4] = product[14];
|
||||
tmp[5] = product[15];
|
||||
tmp[6] = product[13];
|
||||
tmp[7] = product[8];
|
||||
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* d1 */
|
||||
tmp[0] = product[11];
|
||||
tmp[1] = product[12];
|
||||
tmp[2] = product[13];
|
||||
tmp[3] = tmp[4] = tmp[5] = 0;
|
||||
tmp[6] = product[8];
|
||||
tmp[7] = product[10];
|
||||
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* d2 */
|
||||
tmp[0] = product[12];
|
||||
tmp[1] = product[13];
|
||||
tmp[2] = product[14];
|
||||
tmp[3] = product[15];
|
||||
tmp[4] = tmp[5] = 0;
|
||||
tmp[6] = product[9];
|
||||
tmp[7] = product[11];
|
||||
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* d3 */
|
||||
tmp[0] = product[13];
|
||||
tmp[1] = product[14];
|
||||
tmp[2] = product[15];
|
||||
tmp[3] = product[8];
|
||||
tmp[4] = product[9];
|
||||
tmp[5] = product[10];
|
||||
tmp[6] = 0;
|
||||
tmp[7] = product[12];
|
||||
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* d4 */
|
||||
tmp[0] = product[14];
|
||||
tmp[1] = product[15];
|
||||
tmp[2] = 0;
|
||||
tmp[3] = product[9];
|
||||
tmp[4] = product[10];
|
||||
tmp[5] = product[11];
|
||||
tmp[6] = 0;
|
||||
tmp[7] = product[13];
|
||||
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
if (carry < 0) {
|
||||
do {
|
||||
carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
|
||||
}
|
||||
while (carry < 0);
|
||||
} else {
|
||||
while (carry ||
|
||||
uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) {
|
||||
carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve)
|
||||
{
|
||||
return uECC_vli_isZero(point, curve->num_words * 2);
|
||||
}
|
||||
|
||||
void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t t1[NUM_ECC_WORDS];
|
||||
|
||||
uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */
|
||||
uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
|
||||
uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */
|
||||
uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
|
||||
}
|
||||
|
||||
/* P = (x1, y1) => 2P, (x2, y2) => P' */
|
||||
static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * X2, uECC_word_t * Y2,
|
||||
const uECC_word_t * const initial_Z,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t z[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
if (initial_Z) {
|
||||
uECC_vli_set(z, initial_Z, num_words);
|
||||
} else {
|
||||
uECC_vli_clear(z, num_words);
|
||||
z[0] = 1;
|
||||
}
|
||||
|
||||
uECC_vli_set(X2, X1, num_words);
|
||||
uECC_vli_set(Y2, Y1, num_words);
|
||||
|
||||
apply_z(X1, Y1, z, curve);
|
||||
curve->double_jacobian(X1, Y1, z, curve);
|
||||
apply_z(X2, Y2, z, curve);
|
||||
}
|
||||
|
||||
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * X2, uECC_word_t * Y2,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
|
||||
uECC_word_t t5[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
|
||||
uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
|
||||
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
|
||||
uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
|
||||
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
|
||||
uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
|
||||
|
||||
uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
|
||||
uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
|
||||
uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
|
||||
uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
|
||||
uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
|
||||
uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
|
||||
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
|
||||
|
||||
uECC_vli_set(X2, t5, num_words);
|
||||
}
|
||||
|
||||
/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
|
||||
Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
|
||||
or P => P - Q, Q => P + Q
|
||||
*/
|
||||
static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * X2, uECC_word_t * Y2,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
|
||||
uECC_word_t t5[NUM_ECC_WORDS];
|
||||
uECC_word_t t6[NUM_ECC_WORDS];
|
||||
uECC_word_t t7[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
|
||||
uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
|
||||
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
|
||||
uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
|
||||
uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
|
||||
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
|
||||
|
||||
uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
|
||||
uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
|
||||
uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
|
||||
uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
|
||||
uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
|
||||
|
||||
uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
|
||||
uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
|
||||
/* t4 = (y2 - y1)*(B - x3) - E = y3: */
|
||||
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words);
|
||||
|
||||
uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
|
||||
uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
|
||||
uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
|
||||
uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
|
||||
/* t2 = (y2+y1)*(x3' - B) - E = y3': */
|
||||
uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words);
|
||||
|
||||
uECC_vli_set(X1, t7, num_words);
|
||||
}
|
||||
|
||||
void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
|
||||
const uECC_word_t * scalar,
|
||||
const uECC_word_t * initial_Z,
|
||||
bitcount_t num_bits, uECC_Curve curve)
|
||||
{
|
||||
/* R0 and R1 */
|
||||
uECC_word_t Rx[2][NUM_ECC_WORDS];
|
||||
uECC_word_t Ry[2][NUM_ECC_WORDS];
|
||||
uECC_word_t z[NUM_ECC_WORDS];
|
||||
bitcount_t i;
|
||||
uECC_word_t nb;
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
uECC_vli_set(Rx[1], point, num_words);
|
||||
uECC_vli_set(Ry[1], point + num_words, num_words);
|
||||
|
||||
XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
|
||||
|
||||
for (i = num_bits - 2; i > 0; --i) {
|
||||
nb = !uECC_vli_testBit(scalar, i);
|
||||
XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
|
||||
XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
|
||||
}
|
||||
|
||||
nb = !uECC_vli_testBit(scalar, 0);
|
||||
XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
|
||||
|
||||
/* Find final 1/Z value. */
|
||||
uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
|
||||
uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
|
||||
uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/
|
||||
/* yP / (xP * Yb * (X1 - X0)) */
|
||||
uECC_vli_modMult_fast(z, z, point + num_words, curve);
|
||||
/* Xb * yP / (xP * Yb * (X1 - X0)) */
|
||||
uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve);
|
||||
/* End 1/Z calculation */
|
||||
|
||||
XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
|
||||
apply_z(Rx[0], Ry[0], z, curve);
|
||||
|
||||
uECC_vli_set(result, Rx[0], num_words);
|
||||
uECC_vli_set(result + num_words, Ry[0], num_words);
|
||||
}
|
||||
|
||||
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
|
||||
uECC_word_t *k1, uECC_Curve curve)
|
||||
{
|
||||
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
|
||||
bitcount_t num_n_bits = curve->num_n_bits;
|
||||
|
||||
uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
|
||||
(num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
|
||||
uECC_vli_testBit(k0, num_n_bits));
|
||||
|
||||
uECC_vli_add(k1, k0, curve->n, num_n_words);
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
||||
uECC_word_t *private_key,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t tmp1[NUM_ECC_WORDS];
|
||||
uECC_word_t tmp2[NUM_ECC_WORDS];
|
||||
uECC_word_t *p2[2] = {tmp1, tmp2};
|
||||
uECC_word_t carry;
|
||||
|
||||
/* Regularize the bitcount for the private key so that attackers cannot
|
||||
* use a side channel attack to learn the number of leading zeros. */
|
||||
carry = regularize_k(private_key, tmp1, tmp2, curve);
|
||||
|
||||
EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
|
||||
|
||||
if (EccPoint_isZero(result, curve)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Converts an integer in uECC native format to big-endian bytes. */
|
||||
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
|
||||
const unsigned int *native)
|
||||
{
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_bytes; ++i) {
|
||||
unsigned b = num_bytes - 1 - i;
|
||||
bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Converts big-endian bytes to an integer in uECC native format. */
|
||||
void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
|
||||
int num_bytes)
|
||||
{
|
||||
wordcount_t i;
|
||||
uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
|
||||
for (i = 0; i < num_bytes; ++i) {
|
||||
unsigned b = num_bytes - 1 - i;
|
||||
native[b / uECC_WORD_SIZE] |=
|
||||
(uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t mask = (uECC_word_t)-1;
|
||||
uECC_word_t tries;
|
||||
bitcount_t num_bits = uECC_vli_numBits(top, num_words);
|
||||
|
||||
if (!g_rng_function) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
|
||||
if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
random[num_words - 1] &=
|
||||
mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
|
||||
if (!uECC_vli_isZero(random, num_words) &&
|
||||
uECC_vli_cmp(top, random, num_words) == 1) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t tmp1[NUM_ECC_WORDS];
|
||||
uECC_word_t tmp2[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
/* The point at infinity is invalid. */
|
||||
if (EccPoint_isZero(point, curve)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* x and y must be smaller than p. */
|
||||
if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
|
||||
uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
|
||||
curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
|
||||
|
||||
/* Make sure that y^2 == x^3 + ax + b */
|
||||
if (uECC_vli_equal(tmp1, tmp2, num_words) != 0)
|
||||
return -3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
|
||||
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(
|
||||
_public + curve->num_words,
|
||||
public_key + curve->num_bytes,
|
||||
curve->num_bytes);
|
||||
|
||||
if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
return uECC_valid_point(_public, curve);
|
||||
}
|
||||
|
||||
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
|
||||
uECC_vli_bytesToNative(
|
||||
_private,
|
||||
private_key,
|
||||
BITS_TO_BYTES(curve->num_n_bits));
|
||||
|
||||
/* Make sure the private key is in the range [1, n-1]. */
|
||||
if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute public key. */
|
||||
if (!EccPoint_compute_public_key(_public, _private, curve)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
|
||||
uECC_vli_nativeToBytes(
|
||||
public_key +
|
||||
curve->num_bytes, curve->num_bytes, _public + curve->num_words);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/* ec_dh.c - TinyCrypt implementation of EC-DH */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/ecc.h>
|
||||
#include <tinycrypt/ecc_dh.h>
|
||||
#include <string.h>
|
||||
|
||||
#if default_RNG_defined
|
||||
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
|
||||
#else
|
||||
static uECC_RNG_Function g_rng_function = 0;
|
||||
#endif
|
||||
|
||||
int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
|
||||
unsigned int *d, uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
|
||||
/* This function is designed for test purposes-only (such as validating NIST
|
||||
* test vectors) as it uses a provided value for d instead of generating
|
||||
* it uniformly at random. */
|
||||
memcpy (_private, d, NUM_ECC_BYTES);
|
||||
|
||||
/* Computing public-key from private: */
|
||||
if (EccPoint_compute_public_key(_public, _private, curve)) {
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_nativeToBytes(private_key,
|
||||
BITS_TO_BYTES(curve->num_n_bits),
|
||||
_private);
|
||||
uECC_vli_nativeToBytes(public_key,
|
||||
curve->num_bytes,
|
||||
_public);
|
||||
uECC_vli_nativeToBytes(public_key + curve->num_bytes,
|
||||
curve->num_bytes,
|
||||
_public + curve->num_words);
|
||||
|
||||
/* erasing temporary buffer used to store secret: */
|
||||
memset(_private, 0, NUM_ECC_BYTES);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _random[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t tries;
|
||||
|
||||
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
|
||||
/* Generating _private uniformly at random: */
|
||||
uECC_RNG_Function rng_function = uECC_get_rng();
|
||||
if (!rng_function ||
|
||||
!rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
|
||||
uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
|
||||
|
||||
/* Computing public-key from private: */
|
||||
if (EccPoint_compute_public_key(_public, _private, curve)) {
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_nativeToBytes(private_key,
|
||||
BITS_TO_BYTES(curve->num_n_bits),
|
||||
_private);
|
||||
uECC_vli_nativeToBytes(public_key,
|
||||
curve->num_bytes,
|
||||
_public);
|
||||
uECC_vli_nativeToBytes(public_key + curve->num_bytes,
|
||||
curve->num_bytes,
|
||||
_public + curve->num_words);
|
||||
|
||||
/* erasing temporary buffer that stored secret: */
|
||||
memset(_private, 0, NUM_ECC_BYTES);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
uint8_t *secret, uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
|
||||
uECC_word_t tmp[NUM_ECC_WORDS];
|
||||
uECC_word_t *p2[2] = {_private, tmp};
|
||||
uECC_word_t *initial_Z = 0;
|
||||
uECC_word_t carry;
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_bytes = curve->num_bytes;
|
||||
int r;
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_bytesToNative(_private,
|
||||
private_key,
|
||||
BITS_TO_BYTES(curve->num_n_bits));
|
||||
uECC_vli_bytesToNative(_public,
|
||||
public_key,
|
||||
num_bytes);
|
||||
uECC_vli_bytesToNative(_public + num_words,
|
||||
public_key + num_bytes,
|
||||
num_bytes);
|
||||
|
||||
/* Regularize the bitcount for the private key so that attackers cannot use a
|
||||
* side channel attack to learn the number of leading zeros. */
|
||||
carry = regularize_k(_private, _private, tmp, curve);
|
||||
|
||||
/* If an RNG function was specified, try to get a random initial Z value to
|
||||
* improve protection against side-channel attacks. */
|
||||
if (g_rng_function) {
|
||||
if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
|
||||
r = 0;
|
||||
goto clear_and_out;
|
||||
}
|
||||
initial_Z = p2[carry];
|
||||
}
|
||||
|
||||
EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
|
||||
curve);
|
||||
|
||||
uECC_vli_nativeToBytes(secret, num_bytes, _public);
|
||||
r = !EccPoint_isZero(_public, curve);
|
||||
|
||||
clear_and_out:
|
||||
/* erasing temporary buffer used to store secret: */
|
||||
memset(p2, 0, sizeof(p2));
|
||||
__asm__ __volatile__("" :: "g"(p2) : "memory");
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
__asm__ __volatile__("" :: "g"(tmp) : "memory");
|
||||
memset(_private, 0, sizeof(_private));
|
||||
__asm__ __volatile__("" :: "g"(_private) : "memory");
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
/* ec_dsa.c - TinyCrypt implementation of EC-DSA */
|
||||
|
||||
/* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/ecc.h>
|
||||
#include <tinycrypt/ecc_dsa.h>
|
||||
|
||||
#if default_RNG_defined
|
||||
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
|
||||
#else
|
||||
static uECC_RNG_Function g_rng_function = 0;
|
||||
#endif
|
||||
|
||||
static void bits2int(uECC_word_t *native, const uint8_t *bits,
|
||||
unsigned bits_size, uECC_Curve curve)
|
||||
{
|
||||
unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
|
||||
unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
int shift;
|
||||
uECC_word_t carry;
|
||||
uECC_word_t *ptr;
|
||||
|
||||
if (bits_size > num_n_bytes) {
|
||||
bits_size = num_n_bytes;
|
||||
}
|
||||
|
||||
uECC_vli_clear(native, num_n_words);
|
||||
uECC_vli_bytesToNative(native, bits, bits_size);
|
||||
if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
|
||||
return;
|
||||
}
|
||||
shift = bits_size * 8 - curve->num_n_bits;
|
||||
carry = 0;
|
||||
ptr = native + num_n_words;
|
||||
while (ptr-- > native) {
|
||||
uECC_word_t temp = *ptr;
|
||||
*ptr = (temp >> shift) | carry;
|
||||
carry = temp << (uECC_WORD_BITS - shift);
|
||||
}
|
||||
|
||||
/* Reduce mod curve_n */
|
||||
if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
|
||||
uECC_vli_sub(native, native, curve->n, num_n_words);
|
||||
}
|
||||
}
|
||||
|
||||
int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, uECC_word_t *k, uint8_t *signature,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t tmp[NUM_ECC_WORDS];
|
||||
uECC_word_t s[NUM_ECC_WORDS];
|
||||
uECC_word_t *k2[2] = {tmp, s};
|
||||
uECC_word_t p[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t carry;
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
bitcount_t num_n_bits = curve->num_n_bits;
|
||||
|
||||
/* Make sure 0 < k < curve_n */
|
||||
if (uECC_vli_isZero(k, num_words) ||
|
||||
uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
carry = regularize_k(k, tmp, s, curve);
|
||||
EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
|
||||
if (uECC_vli_isZero(p, num_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If an RNG function was specified, get a random number
|
||||
to prevent side channel analysis of k. */
|
||||
if (!g_rng_function) {
|
||||
uECC_vli_clear(tmp, num_n_words);
|
||||
tmp[0] = 1;
|
||||
}
|
||||
else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prevent side channel analysis of uECC_vli_modInv() to determine
|
||||
bits of k / the private key by premultiplying by a random number */
|
||||
uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
|
||||
uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */
|
||||
uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
|
||||
|
||||
uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
|
||||
|
||||
/* tmp = d: */
|
||||
uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
|
||||
|
||||
s[num_n_words - 1] = 0;
|
||||
uECC_vli_set(s, p, num_words);
|
||||
uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
|
||||
|
||||
bits2int(tmp, message_hash, hash_size, curve);
|
||||
uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
|
||||
uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
|
||||
if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, uint8_t *signature, uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t _random[2*NUM_ECC_WORDS];
|
||||
uECC_word_t k[NUM_ECC_WORDS];
|
||||
uECC_word_t tries;
|
||||
|
||||
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
|
||||
/* Generating _random uniformly at random: */
|
||||
uECC_RNG_Function rng_function = uECC_get_rng();
|
||||
if (!rng_function ||
|
||||
!rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
|
||||
uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
|
||||
|
||||
if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature,
|
||||
curve)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bitcount_t smax(bitcount_t a, bitcount_t b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, const uint8_t *signature,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS];
|
||||
uECC_word_t z[NUM_ECC_WORDS];
|
||||
uECC_word_t sum[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t rx[NUM_ECC_WORDS];
|
||||
uECC_word_t ry[NUM_ECC_WORDS];
|
||||
uECC_word_t tx[NUM_ECC_WORDS];
|
||||
uECC_word_t ty[NUM_ECC_WORDS];
|
||||
uECC_word_t tz[NUM_ECC_WORDS];
|
||||
const uECC_word_t *points[4];
|
||||
const uECC_word_t *point;
|
||||
bitcount_t num_bits;
|
||||
bitcount_t i;
|
||||
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
|
||||
rx[num_n_words - 1] = 0;
|
||||
r[num_n_words - 1] = 0;
|
||||
s[num_n_words - 1] = 0;
|
||||
|
||||
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes,
|
||||
curve->num_bytes);
|
||||
uECC_vli_bytesToNative(r, signature, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
|
||||
|
||||
/* r, s must not be 0. */
|
||||
if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* r, s must be < n. */
|
||||
if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
|
||||
uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate u1 and u2. */
|
||||
uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
|
||||
u1[num_n_words - 1] = 0;
|
||||
bits2int(u1, message_hash, hash_size, curve);
|
||||
uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
|
||||
uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
|
||||
|
||||
/* Calculate sum = G + Q. */
|
||||
uECC_vli_set(sum, _public, num_words);
|
||||
uECC_vli_set(sum + num_words, _public + num_words, num_words);
|
||||
uECC_vli_set(tx, curve->G, num_words);
|
||||
uECC_vli_set(ty, curve->G + num_words, num_words);
|
||||
uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
|
||||
XYcZ_add(tx, ty, sum, sum + num_words, curve);
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
|
||||
apply_z(sum, sum + num_words, z, curve);
|
||||
|
||||
/* Use Shamir's trick to calculate u1*G + u2*Q */
|
||||
points[0] = 0;
|
||||
points[1] = curve->G;
|
||||
points[2] = _public;
|
||||
points[3] = sum;
|
||||
num_bits = smax(uECC_vli_numBits(u1, num_n_words),
|
||||
uECC_vli_numBits(u2, num_n_words));
|
||||
|
||||
point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
|
||||
((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
|
||||
uECC_vli_set(rx, point, num_words);
|
||||
uECC_vli_set(ry, point + num_words, num_words);
|
||||
uECC_vli_clear(z, num_words);
|
||||
z[0] = 1;
|
||||
|
||||
for (i = num_bits - 2; i >= 0; --i) {
|
||||
uECC_word_t index;
|
||||
curve->double_jacobian(rx, ry, z, curve);
|
||||
|
||||
index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
|
||||
point = points[index];
|
||||
if (point) {
|
||||
uECC_vli_set(tx, point, num_words);
|
||||
uECC_vli_set(ty, point + num_words, num_words);
|
||||
apply_z(tx, ty, z, curve);
|
||||
uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
|
||||
XYcZ_add(tx, ty, rx, ry, curve);
|
||||
uECC_vli_modMult_fast(z, z, tz, curve);
|
||||
}
|
||||
}
|
||||
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
|
||||
apply_z(rx, ry, z, curve);
|
||||
|
||||
/* v = x1 (mod n) */
|
||||
if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
|
||||
uECC_vli_sub(rx, rx, curve->n, num_n_words);
|
||||
}
|
||||
|
||||
/* Accept only if v == r. */
|
||||
return (int)(uECC_vli_equal(rx, r, num_words) == 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/* uECC_platform_specific.c - Implementation of platform specific functions*/
|
||||
|
||||
/* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* uECC_platform_specific.c -- Implementation of platform specific functions
|
||||
*/
|
||||
|
||||
|
||||
#if defined(unix) || defined(__linux__) || defined(__unix__) || \
|
||||
defined(__unix) | (defined(__APPLE__) && defined(__MACH__)) || \
|
||||
defined(uECC_POSIX)
|
||||
|
||||
/* Some POSIX-like system with /dev/urandom or /dev/random. */
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
int default_CSPRNG(uint8_t *dest, unsigned int size) {
|
||||
|
||||
/* input sanity check: */
|
||||
if (dest == (uint8_t *) 0 || (size <= 0))
|
||||
return 0;
|
||||
|
||||
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *ptr = (char *)dest;
|
||||
size_t left = (size_t) size;
|
||||
while (left > 0) {
|
||||
ssize_t bytes_read = read(fd, ptr, left);
|
||||
if (bytes_read <= 0) { // read failed
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
left -= bytes_read;
|
||||
ptr += bytes_read;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* platform */
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/* hmac.c - TinyCrypt implementation of the HMAC algorithm */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/hmac.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size)
|
||||
{
|
||||
const uint8_t inner_pad = (uint8_t) 0x36;
|
||||
const uint8_t outer_pad = (uint8_t) 0x5c;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < key_size; ++i) {
|
||||
key[i] = inner_pad ^ new_key[i];
|
||||
key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i];
|
||||
}
|
||||
for (; i < TC_SHA256_BLOCK_SIZE; ++i) {
|
||||
key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad;
|
||||
}
|
||||
}
|
||||
|
||||
int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
|
||||
unsigned int key_size)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (ctx == (TCHmacState_t) 0 ||
|
||||
key == (const uint8_t *) 0 ||
|
||||
key_size == 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
const uint8_t dummy_key[key_size];
|
||||
struct tc_hmac_state_struct dummy_state;
|
||||
|
||||
if (key_size <= TC_SHA256_BLOCK_SIZE) {
|
||||
/*
|
||||
* The next three lines consist of dummy calls just to avoid
|
||||
* certain timing attacks. Without these dummy calls,
|
||||
* adversaries would be able to learn whether the key_size is
|
||||
* greater than TC_SHA256_BLOCK_SIZE by measuring the time
|
||||
* consumed in this process.
|
||||
*/
|
||||
(void)tc_sha256_init(&dummy_state.hash_state);
|
||||
(void)tc_sha256_update(&dummy_state.hash_state,
|
||||
dummy_key,
|
||||
key_size);
|
||||
(void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE],
|
||||
&dummy_state.hash_state);
|
||||
|
||||
/* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */
|
||||
rekey(ctx->key, key, key_size);
|
||||
} else {
|
||||
(void)tc_sha256_init(&ctx->hash_state);
|
||||
(void)tc_sha256_update(&ctx->hash_state, key, key_size);
|
||||
(void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE],
|
||||
&ctx->hash_state);
|
||||
rekey(ctx->key,
|
||||
&ctx->key[TC_SHA256_DIGEST_SIZE],
|
||||
TC_SHA256_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_init(TCHmacState_t ctx)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (ctx == (TCHmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void) tc_sha256_init(&ctx->hash_state);
|
||||
(void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_update(TCHmacState_t ctx,
|
||||
const void *data,
|
||||
unsigned int data_length)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (ctx == (TCHmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void)tc_sha256_update(&ctx->hash_state, data, data_length);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (tag == (uint8_t *) 0 ||
|
||||
taglen != TC_SHA256_DIGEST_SIZE ||
|
||||
ctx == (TCHmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void) tc_sha256_final(tag, &ctx->hash_state);
|
||||
|
||||
(void)tc_sha256_init(&ctx->hash_state);
|
||||
(void)tc_sha256_update(&ctx->hash_state,
|
||||
&ctx->key[TC_SHA256_BLOCK_SIZE],
|
||||
TC_SHA256_BLOCK_SIZE);
|
||||
(void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE);
|
||||
(void)tc_sha256_final(tag, &ctx->hash_state);
|
||||
|
||||
/* destroy the current state */
|
||||
_set(ctx, 0, sizeof(*ctx));
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/hmac_prng.h>
|
||||
#include <tinycrypt/hmac.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
/*
|
||||
* min bytes in the seed string.
|
||||
* MIN_SLEN*8 must be at least the expected security level.
|
||||
*/
|
||||
static const unsigned int MIN_SLEN = 32;
|
||||
|
||||
/*
|
||||
* max bytes in the seed string;
|
||||
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
|
||||
*/
|
||||
static const unsigned int MAX_SLEN = UINT32_MAX;
|
||||
|
||||
/*
|
||||
* max bytes in the personalization string;
|
||||
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
|
||||
*/
|
||||
static const unsigned int MAX_PLEN = UINT32_MAX;
|
||||
|
||||
/*
|
||||
* max bytes in the additional_info string;
|
||||
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
|
||||
*/
|
||||
static const unsigned int MAX_ALEN = UINT32_MAX;
|
||||
|
||||
/*
|
||||
* max number of generates between re-seeds;
|
||||
* TinyCrypt accepts up to (2^32 - 1) which is the maximal value of
|
||||
* a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48.
|
||||
*/
|
||||
static const unsigned int MAX_GENS = UINT32_MAX;
|
||||
|
||||
/*
|
||||
* maximum bytes per generate call;
|
||||
* SP800-90A specifies a maximum up to 2^19.
|
||||
*/
|
||||
static const unsigned int MAX_OUT = (1 << 19);
|
||||
|
||||
/*
|
||||
* Assumes: prng != NULL, e != NULL, len >= 0.
|
||||
*/
|
||||
static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
|
||||
{
|
||||
const uint8_t separator0 = 0x00;
|
||||
const uint8_t separator1 = 0x01;
|
||||
|
||||
/* use current state, e and separator 0 to compute a new prng key: */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0));
|
||||
(void)tc_hmac_update(&prng->h, e, len);
|
||||
(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
|
||||
/* configure the new prng key into the prng's instance of hmac */
|
||||
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
|
||||
|
||||
/* use the new key to compute a new state variable v */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
|
||||
|
||||
/* use current state, e and separator 1 to compute a new prng key: */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1));
|
||||
(void)tc_hmac_update(&prng->h, e, len);
|
||||
(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
|
||||
/* configure the new prng key into the prng's instance of hmac */
|
||||
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
|
||||
|
||||
/* use the new key to compute a new state variable v */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
|
||||
}
|
||||
|
||||
int tc_hmac_prng_init(TCHmacPrng_t prng,
|
||||
const uint8_t *personalization,
|
||||
unsigned int plen)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (prng == (TCHmacPrng_t) 0 ||
|
||||
personalization == (uint8_t *) 0 ||
|
||||
plen > MAX_PLEN) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* put the generator into a known state: */
|
||||
_set(prng->key, 0x00, sizeof(prng->key));
|
||||
_set(prng->v, 0x01, sizeof(prng->v));
|
||||
tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
|
||||
/* update assumes SOME key has been configured into HMAC */
|
||||
|
||||
update(prng, personalization, plen);
|
||||
|
||||
/* force a reseed before allowing tc_hmac_prng_generate to succeed: */
|
||||
prng->countdown = 0;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_prng_reseed(TCHmacPrng_t prng,
|
||||
const uint8_t *seed,
|
||||
unsigned int seedlen,
|
||||
const uint8_t *additional_input,
|
||||
unsigned int additionallen)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (prng == (TCHmacPrng_t) 0 ||
|
||||
seed == (const uint8_t *) 0 ||
|
||||
seedlen < MIN_SLEN ||
|
||||
seedlen > MAX_SLEN) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
if (additional_input != (const uint8_t *) 0) {
|
||||
/*
|
||||
* Abort if additional_input is provided but has inappropriate
|
||||
* length
|
||||
*/
|
||||
if (additionallen == 0 ||
|
||||
additionallen > MAX_ALEN) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else {
|
||||
/* call update for the seed and additional_input */
|
||||
update(prng, seed, seedlen);
|
||||
update(prng, additional_input, additionallen);
|
||||
}
|
||||
} else {
|
||||
/* call update only for the seed */
|
||||
update(prng, seed, seedlen);
|
||||
}
|
||||
|
||||
/* ... and enable hmac_prng_generate */
|
||||
prng->countdown = MAX_GENS;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng)
|
||||
{
|
||||
unsigned int bufferlen;
|
||||
|
||||
/* input sanity check: */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
prng == (TCHmacPrng_t) 0 ||
|
||||
outlen == 0 ||
|
||||
outlen > MAX_OUT) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (prng->countdown == 0) {
|
||||
return TC_HMAC_PRNG_RESEED_REQ;
|
||||
}
|
||||
|
||||
prng->countdown--;
|
||||
|
||||
while (outlen != 0) {
|
||||
/* operate HMAC in OFB mode to create "random" outputs */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
|
||||
|
||||
bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ?
|
||||
outlen : TC_SHA256_DIGEST_SIZE;
|
||||
(void)_copy(out, bufferlen, prng->v, bufferlen);
|
||||
|
||||
out += bufferlen;
|
||||
outlen = (outlen > TC_SHA256_DIGEST_SIZE) ?
|
||||
(outlen - TC_SHA256_DIGEST_SIZE) : 0;
|
||||
}
|
||||
|
||||
/* block future PRNG compromises from revealing past state */
|
||||
update(prng, prng->v, TC_SHA256_DIGEST_SIZE);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/sha256.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
|
||||
static void compress(unsigned int *iv, const uint8_t *data);
|
||||
|
||||
int tc_sha256_init(TCSha256State_t s)
|
||||
{
|
||||
/* input sanity check: */
|
||||
if (s == (TCSha256State_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting the initial state values.
|
||||
* These values correspond to the first 32 bits of the fractional parts
|
||||
* of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17
|
||||
* and 19.
|
||||
*/
|
||||
_set((uint8_t *) s, 0x00, sizeof(*s));
|
||||
s->iv[0] = 0x6a09e667;
|
||||
s->iv[1] = 0xbb67ae85;
|
||||
s->iv[2] = 0x3c6ef372;
|
||||
s->iv[3] = 0xa54ff53a;
|
||||
s->iv[4] = 0x510e527f;
|
||||
s->iv[5] = 0x9b05688c;
|
||||
s->iv[6] = 0x1f83d9ab;
|
||||
s->iv[7] = 0x5be0cd19;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
/* input sanity check: */
|
||||
if (s == (TCSha256State_t) 0 ||
|
||||
data == (void *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (datalen == 0) {
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
while (datalen-- > 0) {
|
||||
s->leftover[s->leftover_offset++] = *(data++);
|
||||
if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) {
|
||||
compress(s->iv, s->leftover);
|
||||
s->leftover_offset = 0;
|
||||
s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3);
|
||||
}
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_sha256_final(uint8_t *digest, TCSha256State_t s)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (digest == (uint8_t *) 0 ||
|
||||
s == (TCSha256State_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
s->bits_hashed += (s->leftover_offset << 3);
|
||||
|
||||
s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */
|
||||
if (s->leftover_offset > (sizeof(s->leftover) - 8)) {
|
||||
/* there is not room for all the padding in this block */
|
||||
_set(s->leftover + s->leftover_offset, 0x00,
|
||||
sizeof(s->leftover) - s->leftover_offset);
|
||||
compress(s->iv, s->leftover);
|
||||
s->leftover_offset = 0;
|
||||
}
|
||||
|
||||
/* add the padding and the length in big-Endian format */
|
||||
_set(s->leftover + s->leftover_offset, 0x00,
|
||||
sizeof(s->leftover) - 8 - s->leftover_offset);
|
||||
s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed);
|
||||
s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8);
|
||||
s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16);
|
||||
s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24);
|
||||
s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32);
|
||||
s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40);
|
||||
s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48);
|
||||
s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56);
|
||||
|
||||
/* hash the padding and length */
|
||||
compress(s->iv, s->leftover);
|
||||
|
||||
/* copy the iv out to digest */
|
||||
for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) {
|
||||
unsigned int t = *((unsigned int *) &s->iv[i]);
|
||||
*digest++ = (uint8_t)(t >> 24);
|
||||
*digest++ = (uint8_t)(t >> 16);
|
||||
*digest++ = (uint8_t)(t >> 8);
|
||||
*digest++ = (uint8_t)(t);
|
||||
}
|
||||
|
||||
/* destroy the current state */
|
||||
_set(s, 0, sizeof(*s));
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializing SHA-256 Hash constant words K.
|
||||
* These values correspond to the first 32 bits of the fractional parts of the
|
||||
* cube roots of the first 64 primes between 2 and 311.
|
||||
*/
|
||||
static const unsigned int k256[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
static inline unsigned int ROTR(unsigned int a, unsigned int n)
|
||||
{
|
||||
return (((a) >> n) | ((a) << (32 - n)));
|
||||
}
|
||||
|
||||
#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22))
|
||||
#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25))
|
||||
#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3))
|
||||
#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10))
|
||||
|
||||
#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c)))
|
||||
#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
|
||||
|
||||
static inline unsigned int BigEndian(const uint8_t **c)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
n = (((unsigned int)(*((*c)++))) << 24);
|
||||
n |= ((unsigned int)(*((*c)++)) << 16);
|
||||
n |= ((unsigned int)(*((*c)++)) << 8);
|
||||
n |= ((unsigned int)(*((*c)++)));
|
||||
return n;
|
||||
}
|
||||
|
||||
static void compress(unsigned int *iv, const uint8_t *data)
|
||||
{
|
||||
unsigned int a, b, c, d, e, f, g, h;
|
||||
unsigned int s0, s1;
|
||||
unsigned int t1, t2;
|
||||
unsigned int work_space[16];
|
||||
unsigned int n;
|
||||
unsigned int i;
|
||||
|
||||
a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3];
|
||||
e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7];
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
n = BigEndian(&data);
|
||||
t1 = work_space[i] = n;
|
||||
t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
|
||||
t2 = Sigma0(a) + Maj(a, b, c);
|
||||
h = g; g = f; f = e; e = d + t1;
|
||||
d = c; c = b; b = a; a = t1 + t2;
|
||||
}
|
||||
|
||||
for ( ; i < 64; ++i) {
|
||||
s0 = work_space[(i+1)&0x0f];
|
||||
s0 = sigma0(s0);
|
||||
s1 = work_space[(i+14)&0x0f];
|
||||
s1 = sigma1(s1);
|
||||
|
||||
t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf];
|
||||
t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
|
||||
t2 = Sigma0(a) + Maj(a, b, c);
|
||||
h = g; g = f; f = e; e = d + t1;
|
||||
d = c; c = b; b = a; a = t1 + t2;
|
||||
}
|
||||
|
||||
iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d;
|
||||
iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* utils.c - TinyCrypt platform-dependent run-time operations */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <tinycrypt/utils.h>
|
||||
#include <tinycrypt/constants.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MASK_TWENTY_SEVEN 0x1b
|
||||
|
||||
unsigned int _copy(uint8_t *to, unsigned int to_len,
|
||||
const uint8_t *from, unsigned int from_len)
|
||||
{
|
||||
if (from_len <= to_len) {
|
||||
(void)memcpy(to, from, from_len);
|
||||
return from_len;
|
||||
} else {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
void _set(void *to, uint8_t val, unsigned int len)
|
||||
{
|
||||
(void)memset(to, val, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Doubles the value of a byte for values up to 127.
|
||||
*/
|
||||
uint8_t _double_byte(uint8_t a)
|
||||
{
|
||||
return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN));
|
||||
}
|
||||
|
||||
int _compare(const uint8_t *a, const uint8_t *b, size_t size)
|
||||
{
|
||||
const uint8_t *tempa = a;
|
||||
const uint8_t *tempb = b;
|
||||
uint8_t result = 0;
|
||||
|
||||
for (unsigned int i = 0; i < size; i++) {
|
||||
result |= tempa[i] ^ tempb[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -21,10 +21,9 @@
|
||||
#define H_BLE_LL_
|
||||
|
||||
#include "stats/stats.h"
|
||||
#include "os/os_eventq.h"
|
||||
#include "os/os_callout.h"
|
||||
#include "os/os_cputime.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
#include "controller/ble_phy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -103,27 +102,27 @@ struct ble_ll_obj
|
||||
#endif
|
||||
|
||||
/* Task event queue */
|
||||
struct os_eventq ll_evq;
|
||||
struct ble_npl_eventq ll_evq;
|
||||
|
||||
/* Wait for response timer */
|
||||
struct hal_timer ll_wfr_timer;
|
||||
|
||||
/* Packet receive queue (and event). Holds received packets from PHY */
|
||||
struct os_event ll_rx_pkt_ev;
|
||||
struct ble_npl_event ll_rx_pkt_ev;
|
||||
struct ble_ll_pkt_q ll_rx_pkt_q;
|
||||
|
||||
/* Packet transmit queue */
|
||||
struct os_event ll_tx_pkt_ev;
|
||||
struct ble_npl_event ll_tx_pkt_ev;
|
||||
struct ble_ll_pkt_q ll_tx_pkt_q;
|
||||
|
||||
/* Data buffer overflow event */
|
||||
struct os_event ll_dbuf_overflow_ev;
|
||||
struct ble_npl_event ll_dbuf_overflow_ev;
|
||||
|
||||
/* Number of completed packets event */
|
||||
struct os_event ll_comp_pkt_ev;
|
||||
struct ble_npl_event ll_comp_pkt_ev;
|
||||
|
||||
/* HW error callout */
|
||||
struct os_callout ll_hw_err_timer;
|
||||
struct ble_npl_callout ll_hw_err_timer;
|
||||
};
|
||||
extern struct ble_ll_obj g_ble_ll_data;
|
||||
|
||||
@@ -441,7 +440,7 @@ void ble_ll_state_set(uint8_t ll_state);
|
||||
uint8_t ble_ll_state_get(void);
|
||||
|
||||
/* Send an event to LL task */
|
||||
void ble_ll_event_send(struct os_event *ev);
|
||||
void ble_ll_event_send(struct ble_npl_event *ev);
|
||||
|
||||
/* Hand received pdu's to LL task */
|
||||
void ble_ll_rx_pdu_in(struct os_mbuf *rxpdu);
|
||||
|
||||
@@ -274,7 +274,7 @@ struct ble_ll_conn_sm
|
||||
* on a singly linked list. Only would need list pointer here.
|
||||
*/
|
||||
/* Connection end event */
|
||||
struct os_event conn_ev_end;
|
||||
struct ble_npl_event conn_ev_end;
|
||||
|
||||
/* Packet transmit queue */
|
||||
struct os_mbuf *cur_tx_pdu;
|
||||
@@ -287,13 +287,13 @@ struct ble_ll_conn_sm
|
||||
};
|
||||
|
||||
/* LL control procedure response timer */
|
||||
struct os_callout ctrl_proc_rsp_timer;
|
||||
struct ble_npl_callout ctrl_proc_rsp_timer;
|
||||
|
||||
/* For scheduling connections */
|
||||
struct ble_ll_sched_item conn_sch;
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) == 1)
|
||||
struct os_callout auth_pyld_timer;
|
||||
struct ble_npl_callout auth_pyld_timer;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "controller/ble_ll_sched.h"
|
||||
#include "hal/hal_timer.h"
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -120,7 +121,7 @@ struct ble_ll_scan_sm
|
||||
int8_t scan_rpa_index;
|
||||
uint8_t scan_peer_rpa[BLE_DEV_ADDR_LEN];
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
uint32_t scan_nrpa_timer;
|
||||
ble_npl_time_t scan_nrpa_timer;
|
||||
uint8_t scan_nrpa[BLE_DEV_ADDR_LEN];
|
||||
#endif
|
||||
|
||||
@@ -129,7 +130,7 @@ struct ble_ll_scan_sm
|
||||
uint16_t backoff_count;
|
||||
uint32_t scan_win_start_time;
|
||||
struct os_mbuf *scan_req_pdu;
|
||||
struct os_event scan_sched_ev;
|
||||
struct ble_npl_event scan_sched_ev;
|
||||
struct hal_timer scan_timer;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
|
||||
@@ -204,9 +204,9 @@ STATS_NAME_START(ble_ll_stats)
|
||||
STATS_NAME(ble_ll_stats, scan_timer_restarted)
|
||||
STATS_NAME_END(ble_ll_stats)
|
||||
|
||||
static void ble_ll_event_rx_pkt(struct os_event *ev);
|
||||
static void ble_ll_event_tx_pkt(struct os_event *ev);
|
||||
static void ble_ll_event_dbuf_overflow(struct os_event *ev);
|
||||
static void ble_ll_event_rx_pkt(struct ble_npl_event *ev);
|
||||
static void ble_ll_event_tx_pkt(struct ble_npl_event *ev);
|
||||
static void ble_ll_event_dbuf_overflow(struct ble_npl_event *ev);
|
||||
|
||||
#if MYNEWT
|
||||
|
||||
@@ -797,7 +797,7 @@ ble_ll_rx_pdu_in(struct os_mbuf *rxpdu)
|
||||
|
||||
pkthdr = OS_MBUF_PKTHDR(rxpdu);
|
||||
STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_rx_pkt_q, pkthdr, omp_next);
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -815,7 +815,7 @@ ble_ll_acl_data_in(struct os_mbuf *txpkt)
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_tx_pkt_q, pkthdr, omp_next);
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_tx_pkt_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_tx_pkt_ev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -828,7 +828,7 @@ ble_ll_acl_data_in(struct os_mbuf *txpkt)
|
||||
void
|
||||
ble_ll_data_buffer_overflow(void)
|
||||
{
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -839,7 +839,7 @@ ble_ll_data_buffer_overflow(void)
|
||||
void
|
||||
ble_ll_hw_error(void)
|
||||
{
|
||||
os_callout_reset(&g_ble_ll_data.ll_hw_err_timer, 0);
|
||||
ble_npl_callout_reset(&g_ble_ll_data.ll_hw_err_timer, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -848,7 +848,7 @@ ble_ll_hw_error(void)
|
||||
* @param arg
|
||||
*/
|
||||
static void
|
||||
ble_ll_hw_err_timer_cb(struct os_event *ev)
|
||||
ble_ll_hw_err_timer_cb(struct ble_npl_event *ev)
|
||||
{
|
||||
if (ble_ll_hci_ev_hw_err(BLE_HW_ERR_HCI_SYNC_LOSS)) {
|
||||
/*
|
||||
@@ -856,8 +856,8 @@ ble_ll_hw_err_timer_cb(struct os_event *ev)
|
||||
* event every 50 milliseconds (or each OS tick if a tick is longer
|
||||
* than 100 msecs).
|
||||
*/
|
||||
os_callout_reset(&g_ble_ll_data.ll_hw_err_timer,
|
||||
os_time_ms_to_ticks32(50));
|
||||
ble_npl_callout_reset(&g_ble_ll_data.ll_hw_err_timer,
|
||||
ble_npl_time_ms_to_ticks32(50));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1055,25 +1055,25 @@ ble_ll_tx_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_event_rx_pkt(struct os_event *ev)
|
||||
ble_ll_event_rx_pkt(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_ll_rx_pkt_in();
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_event_tx_pkt(struct os_event *ev)
|
||||
ble_ll_event_tx_pkt(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_ll_tx_pkt_in();
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_event_dbuf_overflow(struct os_event *ev)
|
||||
ble_ll_event_dbuf_overflow(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_ll_hci_ev_databuf_overflow();
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_event_comp_pkts(struct os_event *ev)
|
||||
ble_ll_event_comp_pkts(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_ll_conn_num_comp_pkts_event_send(NULL);
|
||||
}
|
||||
@@ -1100,7 +1100,7 @@ ble_ll_task(void *arg)
|
||||
ble_ll_rand_start();
|
||||
|
||||
while (1) {
|
||||
os_eventq_run(&g_ble_ll_data.ll_evq);
|
||||
ble_npl_eventq_run(&g_ble_ll_data.ll_evq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1142,9 +1142,9 @@ ble_ll_state_get(void)
|
||||
* @param ev Event to add to the Link Layer event queue.
|
||||
*/
|
||||
void
|
||||
ble_ll_event_send(struct os_event *ev)
|
||||
ble_ll_event_send(struct ble_npl_event *ev)
|
||||
{
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1453,25 +1453,25 @@ ble_ll_init(void)
|
||||
lldata->ll_acl_pkt_size = MYNEWT_VAL(BLE_ACL_BUF_SIZE);
|
||||
|
||||
/* Initialize eventq */
|
||||
os_eventq_init(&lldata->ll_evq);
|
||||
ble_npl_eventq_init(&lldata->ll_evq);
|
||||
|
||||
/* Initialize the transmit (from host) and receive (from phy) queues */
|
||||
STAILQ_INIT(&lldata->ll_tx_pkt_q);
|
||||
STAILQ_INIT(&lldata->ll_rx_pkt_q);
|
||||
|
||||
/* Initialize transmit (from host) and receive packet (from phy) event */
|
||||
lldata->ll_rx_pkt_ev.ev_cb = ble_ll_event_rx_pkt;
|
||||
lldata->ll_tx_pkt_ev.ev_cb = ble_ll_event_tx_pkt;
|
||||
ble_npl_event_init(&lldata->ll_rx_pkt_ev, ble_ll_event_rx_pkt, NULL);
|
||||
ble_npl_event_init(&lldata->ll_tx_pkt_ev, ble_ll_event_tx_pkt, NULL);
|
||||
|
||||
/* Initialize data buffer overflow event and completed packets */
|
||||
lldata->ll_dbuf_overflow_ev.ev_cb = ble_ll_event_dbuf_overflow;
|
||||
lldata->ll_comp_pkt_ev.ev_cb = ble_ll_event_comp_pkts;
|
||||
ble_npl_event_init(&lldata->ll_dbuf_overflow_ev, ble_ll_event_dbuf_overflow, NULL);
|
||||
ble_npl_event_init(&lldata->ll_comp_pkt_ev, ble_ll_event_comp_pkts, NULL);
|
||||
|
||||
/* Initialize the HW error timer */
|
||||
os_callout_init(&g_ble_ll_data.ll_hw_err_timer,
|
||||
&g_ble_ll_data.ll_evq,
|
||||
ble_ll_hw_err_timer_cb,
|
||||
NULL);
|
||||
ble_npl_callout_init(&g_ble_ll_data.ll_hw_err_timer,
|
||||
&g_ble_ll_data.ll_evq,
|
||||
ble_ll_hw_err_timer_cb,
|
||||
NULL);
|
||||
|
||||
/* Initialize LL HCI */
|
||||
ble_ll_hci_init();
|
||||
|
||||
@@ -104,7 +104,7 @@ struct ble_ll_adv_sm
|
||||
struct os_mbuf *adv_data;
|
||||
struct os_mbuf *scan_rsp_data;
|
||||
uint8_t *conn_comp_ev;
|
||||
struct os_event adv_txdone_ev;
|
||||
struct ble_npl_event adv_txdone_ev;
|
||||
struct ble_ll_sched_item adv_sch;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
uint8_t aux_active : 1;
|
||||
@@ -114,7 +114,7 @@ struct ble_ll_adv_sm
|
||||
struct ble_mbuf_hdr *rx_ble_hdr;
|
||||
struct os_mbuf **aux_data;
|
||||
struct ble_ll_adv_aux aux[2];
|
||||
struct os_event adv_sec_txdone_ev;
|
||||
struct ble_npl_event adv_sec_txdone_ev;
|
||||
uint16_t duration;
|
||||
uint16_t adi;
|
||||
uint8_t adv_secondary_chan;
|
||||
@@ -245,7 +245,7 @@ ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm)
|
||||
return;
|
||||
}
|
||||
|
||||
now = os_time_get();
|
||||
now = ble_npl_time_get();
|
||||
if ((int32_t)(now - advsm->adv_rpa_timer) >= 0) {
|
||||
ble_ll_adv_rpa_update(advsm);
|
||||
advsm->adv_rpa_timer = now + ble_ll_resolv_get_rpa_tmo();
|
||||
@@ -778,15 +778,15 @@ ble_ll_adv_tx_done(void *arg)
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
if (ble_ll_adv_active_chanset_is_pri(advsm)) {
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
} else if (ble_ll_adv_active_chanset_is_sec(advsm)) {
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
#else
|
||||
assert(ble_ll_adv_active_chanset_is_pri(advsm));
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
#endif
|
||||
|
||||
ble_ll_log(BLE_LL_LOG_ID_ADV_TXDONE, ble_ll_state_get(),
|
||||
@@ -812,7 +812,7 @@ ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm)
|
||||
* scheduled.
|
||||
*/
|
||||
advsm->adv_chan = ble_ll_adv_final_chan(advsm);
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1359,10 +1359,10 @@ ble_ll_adv_halt(void)
|
||||
|
||||
ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM));
|
||||
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) {
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1473,7 +1473,7 @@ ble_ll_adv_set_adv_params(uint8_t *cmd)
|
||||
memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
|
||||
|
||||
/* Reset RPA timer so we generate a new RPA */
|
||||
advsm->adv_rpa_timer = os_time_get();
|
||||
advsm->adv_rpa_timer = ble_npl_time_get();
|
||||
}
|
||||
#else
|
||||
/* If we dont support privacy some address types wont work */
|
||||
@@ -1550,9 +1550,9 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
|
||||
#endif
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
#endif
|
||||
|
||||
/* If there is an event buf we need to free it */
|
||||
@@ -2217,7 +2217,7 @@ ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
|
||||
/* Reset RPA timer so we generate a new RPA */
|
||||
advsm->adv_rpa_timer = os_time_get();
|
||||
advsm->adv_rpa_timer = ble_npl_time_get();
|
||||
}
|
||||
#else
|
||||
/* If we dont support privacy some address types wont work */
|
||||
@@ -2947,12 +2947,12 @@ ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm)
|
||||
ble_ll_sched_rmv_elem(&advsm->aux[0].sch);
|
||||
ble_ll_sched_rmv_elem(&advsm->aux[1].sch);
|
||||
|
||||
os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
advsm->aux_active = 0;
|
||||
#endif
|
||||
|
||||
advsm->adv_chan = ble_ll_adv_final_chan(advsm);
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3027,7 +3027,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
|
||||
/* Remove the element from the schedule if it is still there. */
|
||||
ble_ll_sched_rmv_elem(&advsm->adv_sch);
|
||||
|
||||
os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
|
||||
|
||||
/*
|
||||
* Check if we have ended our advertising event. If our last advertising
|
||||
@@ -3173,9 +3173,9 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_adv_event_done(struct os_event *ev)
|
||||
ble_ll_adv_event_done(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_ll_adv_done(ev->ev_arg);
|
||||
ble_ll_adv_done(ble_npl_event_get_arg(ev));
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
@@ -3204,7 +3204,7 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
|
||||
|
||||
/* Remove anything else scheduled for secondary channel */
|
||||
ble_ll_sched_rmv_elem(&aux->sch);
|
||||
os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
|
||||
|
||||
/* Stop advertising due to transmitting connection response */
|
||||
if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) {
|
||||
@@ -3239,9 +3239,9 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_adv_sec_event_done(struct os_event *ev)
|
||||
ble_ll_adv_sec_event_done(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_ll_adv_sec_done(ev->ev_arg);
|
||||
ble_ll_adv_sec_done(ble_npl_event_get_arg(ev));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3432,11 +3432,9 @@ ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm)
|
||||
advsm->adv_chanmask = BLE_HCI_ADV_CHANMASK_DEF;
|
||||
|
||||
/* Initialize advertising tx done event */
|
||||
advsm->adv_txdone_ev.ev_cb = ble_ll_adv_event_done;
|
||||
advsm->adv_txdone_ev.ev_arg = advsm;
|
||||
ble_npl_event_init(&advsm->adv_txdone_ev, ble_ll_adv_event_done, advsm);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
advsm->adv_sec_txdone_ev.ev_cb = ble_ll_adv_sec_event_done;
|
||||
advsm->adv_sec_txdone_ev.ev_arg = advsm;
|
||||
ble_npl_event_init(&advsm->adv_sec_txdone_ev, ble_ll_adv_sec_event_done, advsm);
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
|
||||
@@ -215,7 +215,7 @@ STATS_NAME_START(ble_ll_conn_stats)
|
||||
STATS_NAME(ble_ll_conn_stats, mic_failures)
|
||||
STATS_NAME_END(ble_ll_conn_stats)
|
||||
|
||||
static void ble_ll_conn_event_end(struct os_event *ev);
|
||||
static void ble_ll_conn_event_end(struct ble_npl_event *ev);
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
/**
|
||||
@@ -1638,22 +1638,22 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime,
|
||||
* @param arg
|
||||
*/
|
||||
void
|
||||
ble_ll_conn_auth_pyld_timer_cb(struct os_event *ev)
|
||||
ble_ll_conn_auth_pyld_timer_cb(struct ble_npl_event *ev)
|
||||
{
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
connsm = (struct ble_ll_conn_sm *)ev->ev_arg;
|
||||
connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev);
|
||||
ble_ll_auth_pyld_tmo_event_send(connsm);
|
||||
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_LE_PING);
|
||||
ble_ll_conn_auth_pyld_timer_start(connsm);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_conn_rd_features_timer_cb(struct os_event *ev)
|
||||
ble_ll_conn_rd_features_timer_cb(struct ble_npl_event *ev)
|
||||
{
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
connsm = (struct ble_ll_conn_sm *)ev->ev_arg;
|
||||
connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev);
|
||||
|
||||
if (!connsm->csmflags.cfbit.pending_hci_rd_features ||
|
||||
!connsm->csmflags.cfbit.rxd_features) {
|
||||
@@ -1676,7 +1676,7 @@ ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm)
|
||||
|
||||
/* Timeout in is in 10 msec units */
|
||||
tmo = (int32_t)BLE_LL_CONN_AUTH_PYLD_OS_TMO(connsm->auth_pyld_tmo);
|
||||
os_callout_reset(&connsm->auth_pyld_timer, tmo);
|
||||
ble_npl_callout_reset(&connsm->auth_pyld_timer, tmo);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1980,9 +1980,7 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
|
||||
connsm->conn_param_req.handle = 0;
|
||||
|
||||
/* Connection end event */
|
||||
connsm->conn_ev_end.ev_arg = connsm;
|
||||
connsm->conn_ev_end.ev_queued = 0;
|
||||
connsm->conn_ev_end.ev_cb = ble_ll_conn_event_end;
|
||||
ble_npl_event_init(&connsm->conn_ev_end, ble_ll_conn_event_end, connsm);
|
||||
|
||||
/* Initialize transmit queue and ack/flow control elements */
|
||||
STAILQ_INIT(&connsm->conn_txq);
|
||||
@@ -2019,7 +2017,7 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
connsm->auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO;
|
||||
CONN_F_LE_PING_SUPP(connsm) = 1;
|
||||
os_callout_init(&connsm->auth_pyld_timer,
|
||||
ble_npl_callout_init(&connsm->auth_pyld_timer,
|
||||
&g_ble_ll_data.ll_evq,
|
||||
ble_ll_conn_auth_pyld_timer_cb,
|
||||
connsm);
|
||||
@@ -2106,10 +2104,10 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
|
||||
ble_ll_sched_rmv_elem(&connsm->conn_sch);
|
||||
|
||||
/* Stop any control procedures that might be running */
|
||||
os_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
os_callout_stop(&connsm->auth_pyld_timer);
|
||||
ble_npl_callout_stop(&connsm->auth_pyld_timer);
|
||||
#endif
|
||||
|
||||
/* Remove from the active connection list */
|
||||
@@ -2135,7 +2133,7 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
|
||||
}
|
||||
|
||||
/* Make sure events off queue */
|
||||
os_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end);
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
|
||||
/* Remove from occupied periods */
|
||||
@@ -2557,14 +2555,14 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
|
||||
*
|
||||
*/
|
||||
static void
|
||||
ble_ll_conn_event_end(struct os_event *ev)
|
||||
ble_ll_conn_event_end(struct ble_npl_event *ev)
|
||||
{
|
||||
uint8_t ble_err;
|
||||
uint32_t tmo;
|
||||
struct ble_ll_conn_sm *connsm;
|
||||
|
||||
/* Better be a connection state machine! */
|
||||
connsm = (struct ble_ll_conn_sm *)ev->ev_arg;
|
||||
connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev);
|
||||
assert(connsm);
|
||||
|
||||
/* Check if we need to resume scanning */
|
||||
@@ -2591,7 +2589,7 @@ ble_ll_conn_event_end(struct os_event *ev)
|
||||
}
|
||||
|
||||
/* Remove any connection end events that might be enqueued */
|
||||
os_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end);
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end);
|
||||
|
||||
/*
|
||||
* If we have received a packet, we can set the current transmit window
|
||||
@@ -3813,8 +3811,8 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
#endif
|
||||
++connsm->completed_pkts;
|
||||
if (connsm->completed_pkts > 2) {
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq,
|
||||
&g_ble_ll_data.ll_comp_pkt_ev);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq,
|
||||
&g_ble_ll_data.ll_comp_pkt_ev);
|
||||
}
|
||||
}
|
||||
os_mbuf_free_chain(txpdu);
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
* Used to limit the rate at which we send the number of completed packets
|
||||
* event to the host. This is the os time at which we can send an event.
|
||||
*/
|
||||
static uint32_t g_ble_ll_last_num_comp_pkt_evt;
|
||||
static ble_npl_time_t g_ble_ll_last_num_comp_pkt_evt;
|
||||
extern uint8_t *g_ble_ll_conn_comp_ev;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
@@ -283,7 +283,7 @@ ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm)
|
||||
* have completed but there are data packets in the controller buffers
|
||||
* (i.e. enqueued in a connection state machine).
|
||||
*/
|
||||
if ((int32_t)(os_time_get() - g_ble_ll_last_num_comp_pkt_evt) <
|
||||
if ((ble_npl_stime_t)(ble_npl_time_get() - g_ble_ll_last_num_comp_pkt_evt) <
|
||||
MYNEWT_VAL(BLE_NUM_COMP_PKT_RATE)) {
|
||||
/*
|
||||
* If this connection has completed packets, send an event right away.
|
||||
@@ -358,7 +358,7 @@ skip_conn:
|
||||
}
|
||||
|
||||
if (event_sent) {
|
||||
g_ble_ll_last_num_comp_pkt_evt = os_time_get();
|
||||
g_ble_ll_last_num_comp_pkt_evt = ble_npl_time_get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,7 +1464,7 @@ ble_ll_conn_hci_wr_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen)
|
||||
rc = BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
} else {
|
||||
connsm->auth_pyld_tmo = tmo;
|
||||
if (os_callout_queued(&connsm->auth_pyld_timer)) {
|
||||
if (ble_npl_callout_queued(&connsm->auth_pyld_timer)) {
|
||||
ble_ll_conn_auth_pyld_timer_start(connsm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ extern "C" {
|
||||
|
||||
/* Default authenticated payload timeout (30 seconds; in 10 msecs increments) */
|
||||
#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO (3000)
|
||||
#define BLE_LL_CONN_AUTH_PYLD_OS_TMO(x) os_time_ms_to_ticks32((x) * 10)
|
||||
#define BLE_LL_CONN_AUTH_PYLD_OS_TMO(x) ble_npl_time_ms_to_ticks32((x) * 10)
|
||||
|
||||
|
||||
typedef void (*ble_ll_hci_post_cmd_complete_cb)(void);
|
||||
|
||||
@@ -681,7 +681,7 @@ ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req,
|
||||
/* XXX: deal with other control procedures that we need to stop */
|
||||
if (err) {
|
||||
if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
|
||||
os_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
|
||||
}
|
||||
|
||||
@@ -722,7 +722,7 @@ ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
|
||||
if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
|
||||
if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
|
||||
ble_ll_ctrl_phy_update_ind_make(connsm, dptr, rsp, 0);
|
||||
os_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND;
|
||||
}
|
||||
|
||||
@@ -764,7 +764,7 @@ ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
* complete the procedure
|
||||
*/
|
||||
if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
|
||||
os_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1773,10 +1773,10 @@ ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
|
||||
* @param arg Pointer to connection state machine.
|
||||
*/
|
||||
void
|
||||
ble_ll_ctrl_proc_rsp_timer_cb(struct os_event *ev)
|
||||
ble_ll_ctrl_proc_rsp_timer_cb(struct ble_npl_event *ev)
|
||||
{
|
||||
/* Control procedure has timed out. Kill the connection */
|
||||
ble_ll_conn_timeout((struct ble_ll_conn_sm *)ev->ev_arg,
|
||||
ble_ll_conn_timeout((struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev),
|
||||
BLE_ERR_LMP_LL_RSP_TMO);
|
||||
}
|
||||
|
||||
@@ -1914,7 +1914,7 @@ void
|
||||
ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc)
|
||||
{
|
||||
if (connsm->cur_ctrl_proc == ctrl_proc) {
|
||||
os_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
|
||||
connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
|
||||
}
|
||||
CLR_PENDING_CTRL_PROC(connsm, ctrl_proc);
|
||||
@@ -1977,14 +1977,14 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc)
|
||||
|
||||
/* Initialize the procedure response timeout */
|
||||
if (ctrl_proc != BLE_LL_CTRL_PROC_CHAN_MAP_UPD) {
|
||||
os_callout_init(&connsm->ctrl_proc_rsp_timer,
|
||||
ble_npl_callout_init(&connsm->ctrl_proc_rsp_timer,
|
||||
&g_ble_ll_data.ll_evq,
|
||||
ble_ll_ctrl_proc_rsp_timer_cb,
|
||||
connsm);
|
||||
|
||||
/* Re-start timer. Control procedure timeout is 40 seconds */
|
||||
os_callout_reset(&connsm->ctrl_proc_rsp_timer,
|
||||
os_time_ms_to_ticks32(BLE_LL_CTRL_PROC_TIMEOUT_MS));
|
||||
ble_npl_callout_reset(&connsm->ctrl_proc_rsp_timer,
|
||||
ble_npl_time_ms_to_ticks32(BLE_LL_CTRL_PROC_TIMEOUT_MS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@
|
||||
#include <ble_ll_dtm_priv.h>
|
||||
#endif
|
||||
|
||||
static void ble_ll_hci_cmd_proc(struct os_event *ev);
|
||||
static void ble_ll_hci_cmd_proc(struct ble_npl_event *ev);
|
||||
|
||||
/* OS event to enqueue command */
|
||||
static struct os_event g_ble_ll_hci_cmd_ev;
|
||||
static struct ble_npl_event g_ble_ll_hci_cmd_ev;
|
||||
|
||||
/* LE event mask */
|
||||
static uint8_t g_ble_ll_hci_le_event_mask[BLE_HCI_SET_LE_EVENT_MASK_LEN];
|
||||
@@ -1159,7 +1159,7 @@ ble_ll_hci_status_params_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen
|
||||
* @param ev Pointer to os event containing a pointer to command buffer
|
||||
*/
|
||||
static void
|
||||
ble_ll_hci_cmd_proc(struct os_event *ev)
|
||||
ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
|
||||
{
|
||||
int rc;
|
||||
uint8_t ogf;
|
||||
@@ -1170,7 +1170,7 @@ ble_ll_hci_cmd_proc(struct os_event *ev)
|
||||
ble_ll_hci_post_cmd_complete_cb post_cb = NULL;
|
||||
|
||||
/* The command buffer is the event argument */
|
||||
cmdbuf = (uint8_t *)ev->ev_arg;
|
||||
cmdbuf = (uint8_t *)ble_npl_event_get_arg(ev);
|
||||
assert(cmdbuf != NULL);
|
||||
|
||||
/* Get the opcode from the command buffer */
|
||||
@@ -1252,18 +1252,17 @@ ble_ll_hci_cmd_proc(struct os_event *ev)
|
||||
int
|
||||
ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
|
||||
{
|
||||
struct os_event *ev;
|
||||
struct ble_npl_event *ev;
|
||||
|
||||
/* Get an event structure off the queue */
|
||||
ev = &g_ble_ll_hci_cmd_ev;
|
||||
if (ev->ev_queued) {
|
||||
if (ble_npl_event_is_queued(ev)) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/* Fill out the event and post to Link Layer */
|
||||
ev->ev_queued = 0;
|
||||
ev->ev_arg = cmd;
|
||||
os_eventq_put(&g_ble_ll_data.ll_evq, ev);
|
||||
ble_npl_event_set_arg(ev, cmd);
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1286,7 +1285,7 @@ void
|
||||
ble_ll_hci_init(void)
|
||||
{
|
||||
/* Set event callback for command processing */
|
||||
g_ble_ll_hci_cmd_ev.ev_cb = ble_ll_hci_cmd_proc;
|
||||
ble_npl_event_init(&g_ble_ll_hci_cmd_ev, ble_ll_hci_cmd_proc, NULL);
|
||||
|
||||
/* Set defaults for LE events: Vol 2 Part E 7.8.1 */
|
||||
g_ble_ll_hci_le_event_mask[0] = 0x1f;
|
||||
|
||||
@@ -38,7 +38,7 @@ struct ble_ll_resolv_data
|
||||
uint8_t rl_size;
|
||||
uint8_t rl_cnt;
|
||||
uint32_t rpa_tmo;
|
||||
struct os_callout rpa_timer;
|
||||
struct ble_npl_callout rpa_timer;
|
||||
};
|
||||
struct ble_ll_resolv_data g_ble_ll_resolv_data;
|
||||
|
||||
@@ -77,7 +77,7 @@ ble_ll_resolv_list_chg_allowed(void)
|
||||
* is used to regenerate local RPA's in the resolving list.
|
||||
*/
|
||||
void
|
||||
ble_ll_resolv_rpa_timer_cb(struct os_event *ev)
|
||||
ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev)
|
||||
{
|
||||
int i;
|
||||
os_sr_t sr;
|
||||
@@ -92,7 +92,7 @@ ble_ll_resolv_rpa_timer_cb(struct os_event *ev)
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
++rl;
|
||||
}
|
||||
os_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
|
||||
ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
|
||||
(int32_t)g_ble_ll_resolv_data.rpa_tmo);
|
||||
}
|
||||
|
||||
@@ -324,9 +324,9 @@ ble_ll_resolv_enable_cmd(uint8_t *cmdbuf)
|
||||
if ((enabled ^ g_ble_ll_resolv_data.addr_res_enabled) != 0) {
|
||||
if (enabled) {
|
||||
tmo = (int32_t)g_ble_ll_resolv_data.rpa_tmo;
|
||||
os_callout_reset(&g_ble_ll_resolv_data.rpa_timer, tmo);
|
||||
ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, tmo);
|
||||
} else {
|
||||
os_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
|
||||
ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
|
||||
}
|
||||
g_ble_ll_resolv_data.addr_res_enabled = enabled;
|
||||
}
|
||||
@@ -368,7 +368,7 @@ ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf)
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
g_ble_ll_resolv_data.rpa_tmo = os_time_ms_to_ticks32(tmo_secs * 1000);
|
||||
g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(tmo_secs * 1000);
|
||||
|
||||
/* If resolving is not enabled, we are done here. */
|
||||
if (!ble_ll_resolv_enabled()) {
|
||||
@@ -376,7 +376,7 @@ ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf)
|
||||
}
|
||||
|
||||
/* Reset timeout if resolving is enabled */
|
||||
os_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
|
||||
ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
|
||||
(int32_t)g_ble_ll_resolv_data.rpa_tmo);
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
@@ -579,7 +579,7 @@ void
|
||||
ble_ll_resolv_list_reset(void)
|
||||
{
|
||||
g_ble_ll_resolv_data.addr_res_enabled = 0;
|
||||
os_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
|
||||
ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
|
||||
ble_ll_resolv_list_clr();
|
||||
ble_ll_resolv_init();
|
||||
}
|
||||
@@ -590,7 +590,7 @@ ble_ll_resolv_init(void)
|
||||
uint8_t hw_size;
|
||||
|
||||
/* Default is 15 minutes */
|
||||
g_ble_ll_resolv_data.rpa_tmo = os_time_ms_to_ticks32(15 * 60 * 1000);
|
||||
g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(15 * 60 * 1000);
|
||||
|
||||
hw_size = ble_hw_resolv_list_size();
|
||||
if (hw_size > MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) {
|
||||
@@ -598,10 +598,10 @@ ble_ll_resolv_init(void)
|
||||
}
|
||||
g_ble_ll_resolv_data.rl_size = hw_size;
|
||||
|
||||
os_callout_init(&g_ble_ll_resolv_data.rpa_timer,
|
||||
&g_ble_ll_data.ll_evq,
|
||||
ble_ll_resolv_rpa_timer_cb,
|
||||
NULL);
|
||||
ble_npl_callout_init(&g_ble_ll_resolv_data.rpa_timer,
|
||||
&g_ble_ll_data.ll_evq,
|
||||
ble_ll_resolv_rpa_timer_cb,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#endif /* if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1 */
|
||||
|
||||
@@ -267,10 +267,10 @@ ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success)
|
||||
static void
|
||||
ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm)
|
||||
{
|
||||
uint32_t now;
|
||||
ble_npl_time_t now;
|
||||
|
||||
now = os_time_get();
|
||||
if ((int32_t)(now - scansm->scan_nrpa_timer) >= 0) {
|
||||
now = ble_npl_time_get();
|
||||
if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) {
|
||||
/* Generate new NRPA */
|
||||
ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN);
|
||||
scansm->scan_nrpa[5] &= ~0xc0;
|
||||
@@ -1308,7 +1308,7 @@ ble_ll_aux_scan_rsp_failed(void)
|
||||
* @param arg
|
||||
*/
|
||||
static void
|
||||
ble_ll_scan_event_proc(struct os_event *ev)
|
||||
ble_ll_scan_event_proc(struct ble_npl_event *ev)
|
||||
{
|
||||
os_sr_t sr;
|
||||
int inside_window;
|
||||
@@ -1330,7 +1330,7 @@ ble_ll_scan_event_proc(struct os_event *ev)
|
||||
* Get the scanning state machine. If not enabled (this is possible), just
|
||||
* leave and do nothing (just make sure timer is stopped).
|
||||
*/
|
||||
scansm = (struct ble_ll_scan_sm *)ev->ev_arg;
|
||||
scansm = (struct ble_ll_scan_sm *)ble_npl_event_get_arg(ev);
|
||||
scanphy = &scansm->phy_data[scansm->cur_phy];
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
@@ -3157,8 +3157,7 @@ ble_ll_scan_common_init(void)
|
||||
memset(g_ble_ll_scan_params, 0, sizeof(g_ble_ll_scan_params));
|
||||
|
||||
/* Initialize scanning window end event */
|
||||
scansm->scan_sched_ev.ev_cb = ble_ll_scan_event_proc;
|
||||
scansm->scan_sched_ev.ev_arg = scansm;
|
||||
ble_npl_event_init(&scansm->scan_sched_ev, ble_ll_scan_event_proc, scansm);
|
||||
|
||||
for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) {
|
||||
/* Set all non-zero default parameters */
|
||||
@@ -3174,7 +3173,7 @@ ble_ll_scan_common_init(void)
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
/* Make sure we'll generate new NRPA if necessary */
|
||||
scansm->scan_nrpa_timer = os_time_get();
|
||||
scansm->scan_nrpa_timer = ble_npl_time_get();
|
||||
#endif
|
||||
|
||||
/* Initialize scanning timer */
|
||||
|
||||
@@ -27,7 +27,12 @@
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "nrfx.h"
|
||||
#include "controller/ble_hw.h"
|
||||
#if MYNEWT
|
||||
#include "mcu/cmsis_nvic.h"
|
||||
#else
|
||||
#include "core_cm4.h"
|
||||
#include <nimble/nimble_npl_os.h>
|
||||
#endif
|
||||
#include "os/os_trace_api.h"
|
||||
|
||||
/* Total number of resolving list elements */
|
||||
@@ -324,7 +329,11 @@ ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
/* If we were passed a function pointer we need to enable the interrupt */
|
||||
if (cb != NULL) {
|
||||
NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
#if MYNEWT
|
||||
NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
|
||||
#else
|
||||
ble_npl_hw_set_isr(RNG_IRQn, (uint32_t)ble_rng_isr);
|
||||
#endif
|
||||
NVIC_EnableIRQ(RNG_IRQn);
|
||||
g_ble_rng_isr_cb = cb;
|
||||
}
|
||||
|
||||
@@ -23,13 +23,18 @@
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/os.h"
|
||||
#include "ble/xcvr.h"
|
||||
#include "mcu/cmsis_nvic.h"
|
||||
#include "hal/hal_gpio.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
#include "controller/ble_phy.h"
|
||||
#include "controller/ble_ll.h"
|
||||
#include "nrf.h"
|
||||
#include "nrfx.h"
|
||||
#if MYNEWT
|
||||
#include "mcu/cmsis_nvic.h"
|
||||
#include "hal/hal_gpio.h"
|
||||
#else
|
||||
#include "core_cm4.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NOTE: This code uses a couple of PPI channels so care should be taken when
|
||||
@@ -1401,7 +1406,11 @@ ble_phy_init(void)
|
||||
|
||||
/* Set isr in vector table and enable interrupt */
|
||||
NVIC_SetPriority(RADIO_IRQn, 0);
|
||||
#if MYNEWT
|
||||
NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr);
|
||||
#else
|
||||
ble_npl_hw_set_isr(RADIO_IRQn, (uint32_t)ble_phy_isr);
|
||||
#endif
|
||||
NVIC_EnableIRQ(RADIO_IRQn);
|
||||
|
||||
/* Register phy statistics */
|
||||
|
||||
@@ -37,13 +37,12 @@
|
||||
#include "host/ble_sm.h"
|
||||
#include "host/ble_store.h"
|
||||
#include "host/ble_uuid.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct os_eventq;
|
||||
struct os_event;
|
||||
|
||||
#define BLE_HS_FOREVER INT32_MAX
|
||||
|
||||
#define BLE_HS_CONN_HANDLE_NONE 0xffff
|
||||
@@ -174,7 +173,7 @@ extern struct ble_hs_cfg ble_hs_cfg;
|
||||
int ble_hs_synced(void);
|
||||
int ble_hs_start(void);
|
||||
void ble_hs_sched_reset(int reason);
|
||||
void ble_hs_evq_set(struct os_eventq *evq);
|
||||
void ble_hs_evq_set(struct ble_npl_eventq *evq);
|
||||
void ble_hs_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "stats/stats.h"
|
||||
#include "os/os_time.h"
|
||||
#include "os/queue.h"
|
||||
#include "host/ble_att.h"
|
||||
#include "host/ble_uuid.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -122,7 +122,7 @@ SLIST_HEAD(ble_att_prep_entry_list, ble_att_prep_entry);
|
||||
struct ble_att_svr_conn {
|
||||
/** This list is sorted by attribute handle ID. */
|
||||
struct ble_att_prep_entry_list basc_prep_list;
|
||||
os_time_t basc_prep_timeout_at;
|
||||
ble_npl_time_t basc_prep_timeout_at;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -188,7 +188,7 @@ uint16_t ble_att_svr_prev_handle(void);
|
||||
int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom);
|
||||
struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id);
|
||||
int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr,
|
||||
os_time_t now);
|
||||
ble_npl_time_t now);
|
||||
int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom);
|
||||
int ble_att_svr_rx_find_type_value(uint16_t conn_handle,
|
||||
struct os_mbuf **rxom);
|
||||
|
||||
@@ -333,7 +333,7 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read,
|
||||
* write times out.
|
||||
*/
|
||||
int32_t
|
||||
ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, os_time_t now)
|
||||
ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, ble_npl_time_t now)
|
||||
{
|
||||
#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO == 0
|
||||
return BLE_HS_FOREVER;
|
||||
@@ -2358,7 +2358,7 @@ ble_att_svr_insert_prep_entry(uint16_t conn_handle,
|
||||
|
||||
#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO != 0
|
||||
conn->bhc_att_svr.basc_prep_timeout_at =
|
||||
os_time_get() + BLE_HS_ATT_SVR_QUEUED_WRITE_TMO;
|
||||
ble_npl_time_get() + BLE_HS_ATT_SVR_QUEUED_WRITE_TMO;
|
||||
|
||||
ble_hs_timer_resched();
|
||||
#endif
|
||||
|
||||
+22
-23
@@ -20,7 +20,6 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "os/os.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "host/ble_hs_adv.h"
|
||||
#include "host/ble_hs_hci.h"
|
||||
@@ -109,7 +108,7 @@ struct ble_gap_master_state {
|
||||
uint8_t op;
|
||||
|
||||
uint8_t exp_set:1;
|
||||
os_time_t exp_os_ticks;
|
||||
ble_npl_time_t exp_os_ticks;
|
||||
|
||||
ble_gap_event_fn *cb;
|
||||
void *cb_arg;
|
||||
@@ -162,7 +161,7 @@ struct ble_gap_slave_state {
|
||||
/* timer is used only with legacy advertising */
|
||||
#if !MYNEWT_VAL(BLE_EXT_ADV)
|
||||
unsigned int exp_set:1;
|
||||
os_time_t exp_os_ticks;
|
||||
ble_npl_time_t exp_os_ticks;
|
||||
#endif
|
||||
|
||||
ble_gap_event_fn *cb;
|
||||
@@ -174,7 +173,7 @@ static bssnz_t struct ble_gap_slave_state ble_gap_slave[BLE_ADV_INSTANCES];
|
||||
struct ble_gap_update_entry {
|
||||
SLIST_ENTRY(ble_gap_update_entry) next;
|
||||
struct ble_gap_upd_params params;
|
||||
os_time_t exp_os_ticks;
|
||||
ble_npl_time_t exp_os_ticks;
|
||||
uint16_t conn_handle;
|
||||
};
|
||||
SLIST_HEAD(ble_gap_update_entry_list, ble_gap_update_entry);
|
||||
@@ -853,14 +852,14 @@ ble_gap_update_notify(uint16_t conn_handle, int status)
|
||||
static uint32_t
|
||||
ble_gap_master_ticks_until_exp(void)
|
||||
{
|
||||
int32_t ticks;
|
||||
ble_npl_stime_t ticks;
|
||||
|
||||
if (ble_gap_master.op == BLE_GAP_OP_NULL || !ble_gap_master.exp_set) {
|
||||
/* Timer not set; infinity ticks until next event. */
|
||||
return BLE_HS_FOREVER;
|
||||
}
|
||||
|
||||
ticks = ble_gap_master.exp_os_ticks - os_time_get();
|
||||
ticks = ble_gap_master.exp_os_ticks - ble_npl_time_get();
|
||||
if (ticks > 0) {
|
||||
/* Timer not expired yet. */
|
||||
return ticks;
|
||||
@@ -874,14 +873,14 @@ ble_gap_master_ticks_until_exp(void)
|
||||
static uint32_t
|
||||
ble_gap_slave_ticks_until_exp(void)
|
||||
{
|
||||
int32_t ticks;
|
||||
ble_npl_stime_t ticks;
|
||||
|
||||
if (ble_gap_slave[0].op == BLE_GAP_OP_NULL || !ble_gap_slave[0].exp_set) {
|
||||
/* Timer not set; infinity ticks until next event. */
|
||||
return BLE_HS_FOREVER;
|
||||
}
|
||||
|
||||
ticks = ble_gap_slave[0].exp_os_ticks - os_time_get();
|
||||
ticks = ble_gap_slave[0].exp_os_ticks - ble_npl_time_get();
|
||||
if (ticks > 0) {
|
||||
/* Timer not expired yet. */
|
||||
return ticks;
|
||||
@@ -907,7 +906,7 @@ static uint16_t
|
||||
ble_gap_update_next_exp(int32_t *out_ticks_from_now)
|
||||
{
|
||||
struct ble_gap_update_entry *entry;
|
||||
os_time_t now;
|
||||
ble_npl_time_t now;
|
||||
uint16_t conn_handle;
|
||||
int32_t best_ticks;
|
||||
int32_t ticks;
|
||||
@@ -916,7 +915,7 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now)
|
||||
|
||||
conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||
best_ticks = BLE_HS_FOREVER;
|
||||
now = os_time_get();
|
||||
now = ble_npl_time_get();
|
||||
|
||||
SLIST_FOREACH(entry, &ble_gap_update_entries, next) {
|
||||
ticks = entry->exp_os_ticks - now;
|
||||
@@ -941,7 +940,7 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now)
|
||||
static void
|
||||
ble_gap_master_set_timer(uint32_t ticks_from_now)
|
||||
{
|
||||
ble_gap_master.exp_os_ticks = os_time_get() + ticks_from_now;
|
||||
ble_gap_master.exp_os_ticks = ble_npl_time_get() + ticks_from_now;
|
||||
ble_gap_master.exp_set = 1;
|
||||
|
||||
ble_hs_timer_resched();
|
||||
@@ -951,7 +950,7 @@ ble_gap_master_set_timer(uint32_t ticks_from_now)
|
||||
static void
|
||||
ble_gap_slave_set_timer(uint32_t ticks_from_now)
|
||||
{
|
||||
ble_gap_slave[0].exp_os_ticks = os_time_get() + ticks_from_now;
|
||||
ble_gap_slave[0].exp_os_ticks = ble_npl_time_get() + ticks_from_now;
|
||||
ble_gap_slave[0].exp_set = 1;
|
||||
|
||||
ble_hs_timer_resched();
|
||||
@@ -1530,7 +1529,7 @@ ble_gap_master_timer(void)
|
||||
rc = ble_gap_conn_cancel_tx();
|
||||
if (rc != 0) {
|
||||
/* Failed to stop connecting; try again in 100 ms. */
|
||||
return os_time_ms_to_ticks32(BLE_GAP_CANCEL_RETRY_TIMEOUT_MS);
|
||||
return ble_npl_time_ms_to_ticks32(BLE_GAP_CANCEL_RETRY_TIMEOUT_MS);
|
||||
} else {
|
||||
/* Stop the timer now that the cancel command has been acked. */
|
||||
ble_gap_master.exp_set = 0;
|
||||
@@ -1550,7 +1549,7 @@ ble_gap_master_timer(void)
|
||||
rc = ble_gap_disc_enable_tx(0, 0);
|
||||
if (rc != 0) {
|
||||
/* Failed to stop discovery; try again in 100 ms. */
|
||||
return os_time_ms_to_ticks32(BLE_GAP_CANCEL_RETRY_TIMEOUT_MS);
|
||||
return ble_npl_time_ms_to_ticks32(BLE_GAP_CANCEL_RETRY_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
ble_gap_disc_complete();
|
||||
@@ -2132,7 +2131,7 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
|
||||
}
|
||||
|
||||
if (duration_ms != BLE_HS_FOREVER) {
|
||||
rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
|
||||
rc = ble_npl_time_ms_to_ticks(duration_ms, &duration_ticks);
|
||||
if (rc != 0) {
|
||||
/* Duration too great. */
|
||||
rc = BLE_HS_EINVAL;
|
||||
@@ -3426,7 +3425,7 @@ ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms,
|
||||
}
|
||||
|
||||
if (duration_ms != BLE_HS_FOREVER) {
|
||||
rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
|
||||
rc = ble_npl_time_ms_to_ticks(duration_ms, &duration_ticks);
|
||||
if (rc != 0) {
|
||||
/* Duration too great. */
|
||||
rc = BLE_HS_EINVAL;
|
||||
@@ -3882,7 +3881,7 @@ ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
|
||||
}
|
||||
|
||||
if (duration_ms != BLE_HS_FOREVER) {
|
||||
rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
|
||||
rc = ble_npl_time_ms_to_ticks(duration_ms, &duration_ticks);
|
||||
if (rc != 0) {
|
||||
/* Duration too great. */
|
||||
rc = BLE_HS_EINVAL;
|
||||
@@ -4412,8 +4411,8 @@ ble_gap_update_params(uint16_t conn_handle,
|
||||
entry->conn_handle = conn_handle;
|
||||
entry->params = *params;
|
||||
|
||||
entry->exp_os_ticks = os_time_get() +
|
||||
os_time_ms_to_ticks32(BLE_GAP_UPDATE_TIMEOUT_MS);
|
||||
entry->exp_os_ticks = ble_npl_time_get() +
|
||||
ble_npl_time_ms_to_ticks32(BLE_GAP_UPDATE_TIMEOUT_MS);
|
||||
|
||||
BLE_HS_LOG(INFO, "GAP procedure initiated: ");
|
||||
ble_gap_log_update(conn_handle, params);
|
||||
@@ -4840,7 +4839,7 @@ ble_gap_preempt(void)
|
||||
* `ble_gap_preempt()`.
|
||||
*/
|
||||
|
||||
static struct os_mutex preempt_done_mutex;
|
||||
static struct ble_npl_mutex preempt_done_mutex;
|
||||
|
||||
void
|
||||
ble_gap_preempt_done(void)
|
||||
@@ -4858,7 +4857,7 @@ ble_gap_preempt_done(void)
|
||||
disc_preempted = 0;
|
||||
|
||||
/* protects slaves from accessing by multiple threads */
|
||||
os_mutex_pend(&preempt_done_mutex, 0xFFFFFFFF);
|
||||
ble_npl_mutex_pend(&preempt_done_mutex, 0xFFFFFFFF);
|
||||
memset(slaves, 0, sizeof(slaves));
|
||||
|
||||
ble_hs_lock();
|
||||
@@ -4892,7 +4891,7 @@ ble_gap_preempt_done(void)
|
||||
ble_gap_call_event_cb(&event, slaves[i].cb, slaves[i].arg);
|
||||
}
|
||||
}
|
||||
os_mutex_release(&preempt_done_mutex);
|
||||
ble_npl_mutex_release(&preempt_done_mutex);
|
||||
|
||||
if (disc_preempted) {
|
||||
event.type = BLE_GAP_EVENT_DISC_COMPLETE;
|
||||
@@ -4913,7 +4912,7 @@ ble_gap_init(void)
|
||||
memset(&ble_gap_master, 0, sizeof ble_gap_master);
|
||||
memset(ble_gap_slave, 0, sizeof ble_gap_slave);
|
||||
|
||||
os_mutex_init(&preempt_done_mutex);
|
||||
ble_npl_mutex_init(&preempt_done_mutex);
|
||||
|
||||
SLIST_INIT(&ble_gap_update_entries);
|
||||
|
||||
|
||||
@@ -418,7 +418,7 @@ static struct ble_gattc_proc_list ble_gattc_procs;
|
||||
/* The time when we should attempt to resume stalled procedures, in OS ticks.
|
||||
* A value of 0 indicates no stalled procedures.
|
||||
*/
|
||||
static os_time_t ble_gattc_resume_at;
|
||||
static ble_npl_time_t ble_gattc_resume_at;
|
||||
|
||||
/* Statistics. */
|
||||
STATS_SECT_DECL(ble_gattc_stats) ble_gattc_stats;
|
||||
@@ -731,8 +731,8 @@ ble_gattc_proc_insert(struct ble_gattc_proc *proc)
|
||||
static void
|
||||
ble_gattc_proc_set_exp_timer(struct ble_gattc_proc *proc)
|
||||
{
|
||||
proc->exp_os_ticks = os_time_get() +
|
||||
os_time_ms_to_ticks32(BLE_GATTC_UNRESPONSIVE_TIMEOUT_MS);
|
||||
proc->exp_os_ticks = ble_npl_time_get() +
|
||||
ble_npl_time_ms_to_ticks32(BLE_GATTC_UNRESPONSIVE_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -744,8 +744,8 @@ ble_gattc_proc_set_resume_timer(struct ble_gattc_proc *proc)
|
||||
* instead.
|
||||
*/
|
||||
if (ble_gattc_resume_at == 0) {
|
||||
ble_gattc_resume_at = os_time_get() +
|
||||
os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE));
|
||||
ble_gattc_resume_at = ble_npl_time_get() +
|
||||
ble_npl_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE));
|
||||
|
||||
/* A value of 0 indicates the timer is unset. Disambiguate this. */
|
||||
if (ble_gattc_resume_at == 0) {
|
||||
@@ -862,7 +862,7 @@ ble_gattc_proc_matches_conn_op(struct ble_gattc_proc *proc, void *arg)
|
||||
}
|
||||
|
||||
struct ble_gattc_criteria_exp {
|
||||
os_time_t now;
|
||||
ble_npl_time_t now;
|
||||
int32_t next_exp_in;
|
||||
};
|
||||
|
||||
@@ -1012,7 +1012,7 @@ ble_gattc_extract_expired(struct ble_gattc_proc_list *dst_list)
|
||||
{
|
||||
struct ble_gattc_criteria_exp criteria;
|
||||
|
||||
criteria.now = os_time_get();
|
||||
criteria.now = ble_npl_time_get();
|
||||
criteria.next_exp_in = BLE_HS_FOREVER;
|
||||
|
||||
STAILQ_INIT(dst_list);
|
||||
@@ -1116,7 +1116,7 @@ ble_gattc_resume_procs(void)
|
||||
static int32_t
|
||||
ble_gattc_ticks_until_resume(void)
|
||||
{
|
||||
os_time_t now;
|
||||
ble_npl_time_t now;
|
||||
int32_t diff;
|
||||
|
||||
/* Resume timer not set. */
|
||||
@@ -1124,7 +1124,7 @@ ble_gattc_ticks_until_resume(void)
|
||||
return BLE_HS_FOREVER;
|
||||
}
|
||||
|
||||
now = os_time_get();
|
||||
now = ble_npl_time_get();
|
||||
diff = ble_gattc_resume_at - now;
|
||||
if (diff <= 0) {
|
||||
/* Timer already expired; resume immediately. */
|
||||
|
||||
+55
-67
@@ -23,59 +23,53 @@
|
||||
#include "sysinit/sysinit.h"
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "stats/stats.h"
|
||||
#include "os/os.h"
|
||||
#include "nimble/ble_hci_trans.h"
|
||||
#include "ble_hs_priv.h"
|
||||
#include "ble_monitor_priv.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
|
||||
#define BLE_HS_HCI_EVT_COUNT \
|
||||
(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + \
|
||||
MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
|
||||
|
||||
static void ble_hs_event_rx_hci_ev(struct os_event *ev);
|
||||
static void ble_hs_event_tx_notify(struct os_event *ev);
|
||||
static void ble_hs_event_reset(struct os_event *ev);
|
||||
static void ble_hs_event_start(struct os_event *ev);
|
||||
static void ble_hs_event_rx_hci_ev(struct ble_npl_event *ev);
|
||||
static void ble_hs_event_tx_notify(struct ble_npl_event *ev);
|
||||
static void ble_hs_event_reset(struct ble_npl_event *ev);
|
||||
static void ble_hs_event_start(struct ble_npl_event *ev);
|
||||
static void ble_hs_timer_sched(int32_t ticks_from_now);
|
||||
|
||||
struct os_mempool ble_hs_hci_ev_pool;
|
||||
static os_membuf_t ble_hs_hci_os_event_buf[
|
||||
OS_MEMPOOL_SIZE(BLE_HS_HCI_EVT_COUNT, sizeof (struct os_event))
|
||||
OS_MEMPOOL_SIZE(BLE_HS_HCI_EVT_COUNT, sizeof (struct ble_npl_event))
|
||||
];
|
||||
|
||||
/** OS event - triggers tx of pending notifications and indications. */
|
||||
static struct os_event ble_hs_ev_tx_notifications = {
|
||||
.ev_cb = ble_hs_event_tx_notify,
|
||||
};
|
||||
static struct ble_npl_event ble_hs_ev_tx_notifications;
|
||||
|
||||
/** OS event - triggers a full reset. */
|
||||
static struct os_event ble_hs_ev_reset = {
|
||||
.ev_cb = ble_hs_event_reset,
|
||||
};
|
||||
static struct ble_npl_event ble_hs_ev_reset;
|
||||
|
||||
static struct os_event ble_hs_ev_start = {
|
||||
.ev_cb = ble_hs_event_start,
|
||||
};
|
||||
static struct ble_npl_event ble_hs_ev_start;
|
||||
|
||||
uint8_t ble_hs_sync_state;
|
||||
static int ble_hs_reset_reason;
|
||||
|
||||
#define BLE_HS_SYNC_RETRY_TIMEOUT_MS 100 /* ms */
|
||||
|
||||
static struct os_task *ble_hs_parent_task;
|
||||
static void *ble_hs_parent_task;
|
||||
|
||||
/**
|
||||
* Handles unresponsive timeouts and periodic retries in case of resource
|
||||
* shortage.
|
||||
*/
|
||||
static struct os_callout ble_hs_timer_timer;
|
||||
static struct ble_npl_callout ble_hs_timer_timer;
|
||||
|
||||
/* Shared queue that the host uses for work items. */
|
||||
static struct os_eventq *ble_hs_evq;
|
||||
static struct ble_npl_eventq *ble_hs_evq;
|
||||
|
||||
static struct os_mqueue ble_hs_rx_q;
|
||||
static struct ble_mqueue ble_hs_rx_q;
|
||||
|
||||
static struct os_mutex ble_hs_mutex;
|
||||
static struct ble_npl_mutex ble_hs_mutex;
|
||||
|
||||
/** These values keep track of required ATT and GATT resources counts. They
|
||||
* increase as services are added, and are read when the ATT server and GATT
|
||||
@@ -104,7 +98,7 @@ STATS_NAME_START(ble_hs_stats)
|
||||
STATS_NAME(ble_hs_stats, pvcy_add_entry_fail)
|
||||
STATS_NAME_END(ble_hs_stats)
|
||||
|
||||
struct os_eventq *
|
||||
struct ble_npl_eventq *
|
||||
ble_hs_evq_get(void)
|
||||
{
|
||||
return ble_hs_evq;
|
||||
@@ -118,7 +112,7 @@ ble_hs_evq_get(void)
|
||||
* @param evq The event queue to use for host work.
|
||||
*/
|
||||
void
|
||||
ble_hs_evq_set(struct os_eventq *evq)
|
||||
ble_hs_evq_set(struct ble_npl_eventq *evq)
|
||||
{
|
||||
ble_hs_evq = evq;
|
||||
}
|
||||
@@ -144,8 +138,8 @@ ble_hs_locked_by_cur_task(void)
|
||||
int
|
||||
ble_hs_is_parent_task(void)
|
||||
{
|
||||
return !os_started() ||
|
||||
os_sched_get_current_task() == ble_hs_parent_task;
|
||||
return !ble_npl_os_started() ||
|
||||
ble_npl_get_current_task_id() == ble_hs_parent_task;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +157,7 @@ ble_hs_lock_nested(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = os_mutex_pend(&ble_hs_mutex, 0xffffffff);
|
||||
rc = ble_npl_mutex_pend(&ble_hs_mutex, 0xffffffff);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
|
||||
}
|
||||
|
||||
@@ -182,7 +176,7 @@ ble_hs_unlock_nested(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = os_mutex_release(&ble_hs_mutex);
|
||||
rc = ble_npl_mutex_release(&ble_hs_mutex);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
|
||||
}
|
||||
|
||||
@@ -222,7 +216,7 @@ ble_hs_process_rx_data_queue(void)
|
||||
{
|
||||
struct os_mbuf *om;
|
||||
|
||||
while ((om = os_mqueue_get(&ble_hs_rx_q)) != NULL) {
|
||||
while ((om = ble_mqueue_get(&ble_hs_rx_q)) != NULL) {
|
||||
#if BLE_MONITOR
|
||||
ble_monitor_send_om(BLE_MONITOR_OPCODE_ACL_RX_PKT, om);
|
||||
#endif
|
||||
@@ -305,7 +299,7 @@ ble_hs_clear_rx_queue(void)
|
||||
{
|
||||
struct os_mbuf *om;
|
||||
|
||||
while ((om = os_mqueue_get(&ble_hs_rx_q)) != NULL) {
|
||||
while ((om = ble_mqueue_get(&ble_hs_rx_q)) != NULL) {
|
||||
os_mbuf_free_chain(om);
|
||||
}
|
||||
}
|
||||
@@ -326,7 +320,7 @@ ble_hs_synced(void)
|
||||
static int
|
||||
ble_hs_sync(void)
|
||||
{
|
||||
uint32_t retry_tmo_ticks;
|
||||
ble_npl_time_t retry_tmo_ticks;
|
||||
int rc;
|
||||
|
||||
/* Set the sync state to "bringup." This allows the parent task to send
|
||||
@@ -342,7 +336,7 @@ ble_hs_sync(void)
|
||||
ble_hs_sync_state = BLE_HS_SYNC_STATE_BAD;
|
||||
}
|
||||
|
||||
retry_tmo_ticks = os_time_ms_to_ticks32(BLE_HS_SYNC_RETRY_TIMEOUT_MS);
|
||||
retry_tmo_ticks = ble_npl_time_ms_to_ticks32(BLE_HS_SYNC_RETRY_TIMEOUT_MS);
|
||||
ble_hs_timer_sched(retry_tmo_ticks);
|
||||
|
||||
if (rc == 0) {
|
||||
@@ -403,7 +397,7 @@ ble_hs_reset(void)
|
||||
* periodic retries in case of resource shortage.
|
||||
*/
|
||||
static void
|
||||
ble_hs_timer_exp(struct os_event *ev)
|
||||
ble_hs_timer_exp(struct ble_npl_event *ev)
|
||||
{
|
||||
int32_t ticks_until_next;
|
||||
|
||||
@@ -433,14 +427,14 @@ ble_hs_timer_reset(uint32_t ticks)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = os_callout_reset(&ble_hs_timer_timer, ticks);
|
||||
rc = ble_npl_callout_reset(&ble_hs_timer_timer, ticks);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_hs_timer_sched(int32_t ticks_from_now)
|
||||
{
|
||||
os_time_t abs_time;
|
||||
ble_npl_time_t abs_time;
|
||||
|
||||
if (ticks_from_now == BLE_HS_FOREVER) {
|
||||
return;
|
||||
@@ -449,10 +443,10 @@ ble_hs_timer_sched(int32_t ticks_from_now)
|
||||
/* Reset timer if it is not currently scheduled or if the specified time is
|
||||
* sooner than the previous expiration time.
|
||||
*/
|
||||
abs_time = os_time_get() + ticks_from_now;
|
||||
if (!os_callout_queued(&ble_hs_timer_timer) ||
|
||||
OS_TIME_TICK_LT(abs_time, ble_hs_timer_timer.c_ticks)) {
|
||||
|
||||
abs_time = ble_npl_time_get() + ticks_from_now;
|
||||
if (!ble_npl_callout_queued(&ble_hs_timer_timer) ||
|
||||
((ble_npl_stime_t)(abs_time -
|
||||
ble_npl_callout_get_ticks(&ble_hs_timer_timer))) < 0) {
|
||||
ble_hs_timer_reset(ticks_from_now);
|
||||
}
|
||||
}
|
||||
@@ -467,12 +461,13 @@ ble_hs_timer_resched(void)
|
||||
}
|
||||
|
||||
static void
|
||||
ble_hs_event_rx_hci_ev(struct os_event *ev)
|
||||
ble_hs_event_rx_hci_ev(struct ble_npl_event *ev)
|
||||
{
|
||||
uint8_t *hci_evt;
|
||||
int rc;
|
||||
|
||||
hci_evt = ev->ev_arg;
|
||||
hci_evt = ble_npl_event_get_arg(ev);
|
||||
|
||||
rc = os_memblock_put(&ble_hs_hci_ev_pool, ev);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
|
||||
|
||||
@@ -485,25 +480,25 @@ ble_hs_event_rx_hci_ev(struct os_event *ev)
|
||||
}
|
||||
|
||||
static void
|
||||
ble_hs_event_tx_notify(struct os_event *ev)
|
||||
ble_hs_event_tx_notify(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_gatts_tx_notifications();
|
||||
}
|
||||
|
||||
static void
|
||||
ble_hs_event_rx_data(struct os_event *ev)
|
||||
ble_hs_event_rx_data(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_hs_process_rx_data_queue();
|
||||
}
|
||||
|
||||
static void
|
||||
ble_hs_event_reset(struct os_event *ev)
|
||||
ble_hs_event_reset(struct ble_npl_event *ev)
|
||||
{
|
||||
ble_hs_reset();
|
||||
}
|
||||
|
||||
static void
|
||||
ble_hs_event_start(struct os_event *ev)
|
||||
ble_hs_event_start(struct ble_npl_event *ev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -514,16 +509,14 @@ ble_hs_event_start(struct os_event *ev)
|
||||
void
|
||||
ble_hs_enqueue_hci_event(uint8_t *hci_evt)
|
||||
{
|
||||
struct os_event *ev;
|
||||
struct ble_npl_event *ev;
|
||||
|
||||
ev = os_memblock_get(&ble_hs_hci_ev_pool);
|
||||
if (ev == NULL) {
|
||||
ble_hci_trans_buf_free(hci_evt);
|
||||
} else {
|
||||
ev->ev_queued = 0;
|
||||
ev->ev_cb = ble_hs_event_rx_hci_ev;
|
||||
ev->ev_arg = hci_evt;
|
||||
os_eventq_put(ble_hs_evq, ev);
|
||||
ble_npl_event_init(ev, ble_hs_event_rx_hci_ev, hci_evt);
|
||||
ble_npl_eventq_put(ble_hs_evq, ev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,7 +534,7 @@ ble_hs_notifications_sched(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
os_eventq_put(ble_hs_evq, &ble_hs_ev_tx_notifications);
|
||||
ble_npl_eventq_put(ble_hs_evq, &ble_hs_ev_tx_notifications);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -557,7 +550,7 @@ ble_hs_sched_reset(int reason)
|
||||
BLE_HS_DBG_ASSERT(ble_hs_reset_reason == 0);
|
||||
|
||||
ble_hs_reset_reason = reason;
|
||||
os_eventq_put(ble_hs_evq, &ble_hs_ev_reset);
|
||||
ble_npl_eventq_put(ble_hs_evq, &ble_hs_ev_reset);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -584,9 +577,9 @@ ble_hs_start(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
ble_hs_parent_task = os_sched_get_current_task();
|
||||
ble_hs_parent_task = ble_npl_get_current_task_id();
|
||||
|
||||
os_callout_init(&ble_hs_timer_timer, ble_hs_evq,
|
||||
ble_npl_callout_init(&ble_hs_timer_timer, ble_hs_evq,
|
||||
ble_hs_timer_exp, NULL);
|
||||
|
||||
rc = ble_gatts_start();
|
||||
@@ -618,7 +611,7 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg)
|
||||
*/
|
||||
ble_hs_flow_fill_acl_usrhdr(om);
|
||||
|
||||
rc = os_mqueue_put(&ble_hs_rx_q, ble_hs_evq, om);
|
||||
rc = ble_mqueue_put(&ble_hs_rx_q, ble_hs_evq, om);
|
||||
if (rc != 0) {
|
||||
os_mbuf_free_chain(om);
|
||||
return BLE_HS_EOS;
|
||||
@@ -664,7 +657,7 @@ ble_hs_init(void)
|
||||
|
||||
/* Create memory pool of OS events */
|
||||
rc = os_mempool_init(&ble_hs_hci_ev_pool, BLE_HS_HCI_EVT_COUNT,
|
||||
sizeof (struct os_event), ble_hs_hci_os_event_buf,
|
||||
sizeof (struct ble_npl_event), ble_hs_hci_os_event_buf,
|
||||
"ble_hs_hci_ev_pool");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
@@ -672,15 +665,10 @@ ble_hs_init(void)
|
||||
* bss.
|
||||
*/
|
||||
ble_hs_reset_reason = 0;
|
||||
ble_hs_ev_tx_notifications = (struct os_event) {
|
||||
.ev_cb = ble_hs_event_tx_notify,
|
||||
};
|
||||
ble_hs_ev_reset = (struct os_event) {
|
||||
.ev_cb = ble_hs_event_reset,
|
||||
};
|
||||
ble_hs_ev_start = (struct os_event) {
|
||||
.ev_cb = ble_hs_event_start,
|
||||
};
|
||||
|
||||
ble_npl_event_init(&ble_hs_ev_tx_notifications, ble_hs_event_tx_notify, NULL);
|
||||
ble_npl_event_init(&ble_hs_ev_reset, ble_hs_event_reset, NULL);
|
||||
ble_npl_event_init(&ble_hs_ev_start, ble_hs_event_start, NULL);
|
||||
|
||||
#if BLE_MONITOR
|
||||
rc = ble_monitor_init();
|
||||
@@ -710,14 +698,14 @@ ble_hs_init(void)
|
||||
rc = ble_gatts_init();
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
os_mqueue_init(&ble_hs_rx_q, ble_hs_event_rx_data, NULL);
|
||||
ble_mqueue_init(&ble_hs_rx_q, ble_hs_event_rx_data, NULL);
|
||||
|
||||
rc = stats_init_and_reg(
|
||||
STATS_HDR(ble_hs_stats), STATS_SIZE_INIT_PARMS(ble_hs_stats,
|
||||
STATS_SIZE_32), STATS_NAME_INIT_PARMS(ble_hs_stats), "ble_hs");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = os_mutex_init(&ble_hs_mutex);
|
||||
rc = ble_npl_mutex_init(&ble_hs_mutex);
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
#if MYNEWT_VAL(BLE_HS_DEBUG)
|
||||
@@ -727,13 +715,13 @@ ble_hs_init(void)
|
||||
/* Configure the HCI transport to communicate with a host. */
|
||||
ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL);
|
||||
|
||||
ble_hs_evq_set(os_eventq_dflt_get());
|
||||
ble_hs_evq_set(ble_npl_eventq_dflt_get());
|
||||
|
||||
/* Enqueue the start event to the default event queue. Using the default
|
||||
* queue ensures the event won't run until the end of main(). This allows
|
||||
* the application to configure this package in the meantime.
|
||||
*/
|
||||
os_eventq_put(os_eventq_dflt_get(), &ble_hs_ev_start);
|
||||
ble_npl_eventq_put(ble_npl_eventq_dflt_get(), &ble_hs_ev_start);
|
||||
|
||||
#if BLE_MONITOR
|
||||
ble_monitor_new_index(0, (uint8_t[6]){ }, "nimble0");
|
||||
|
||||
@@ -411,14 +411,14 @@ ble_hs_conn_timer(void)
|
||||
#endif
|
||||
|
||||
struct ble_hs_conn *conn;
|
||||
os_time_t now;
|
||||
ble_npl_time_t now;
|
||||
int32_t next_exp_in;
|
||||
int32_t time_diff;
|
||||
uint16_t conn_handle;
|
||||
|
||||
conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||
next_exp_in = BLE_HS_FOREVER;
|
||||
now = os_time_get();
|
||||
now = ble_npl_time_get();
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ struct ble_hs_conn {
|
||||
|
||||
struct ble_l2cap_chan_list bhc_channels;
|
||||
struct ble_l2cap_chan *bhc_rx_chan; /* Channel rxing current packet. */
|
||||
uint32_t bhc_rx_timeout;
|
||||
ble_npl_time_t bhc_rx_timeout;
|
||||
|
||||
/**
|
||||
* Count of packets sent over this connection that the controller has not
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
#define BLE_HCI_CMD_TIMEOUT_MS 2000
|
||||
|
||||
static struct os_mutex ble_hs_hci_mutex;
|
||||
static struct os_sem ble_hs_hci_sem;
|
||||
static struct ble_npl_mutex ble_hs_hci_mutex;
|
||||
static struct ble_npl_sem ble_hs_hci_sem;
|
||||
|
||||
static uint8_t *ble_hs_hci_ack;
|
||||
static uint16_t ble_hs_hci_buf_sz;
|
||||
@@ -62,7 +62,7 @@ ble_hs_hci_lock(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = os_mutex_pend(&ble_hs_hci_mutex, 0xffffffff);
|
||||
rc = ble_npl_mutex_pend(&ble_hs_hci_mutex, BLE_NPL_TIME_FOREVER);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ ble_hs_hci_unlock(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = os_mutex_release(&ble_hs_hci_mutex);
|
||||
rc = ble_npl_mutex_release(&ble_hs_hci_mutex);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
|
||||
}
|
||||
|
||||
@@ -255,8 +255,8 @@ ble_hs_hci_wait_for_ack(void)
|
||||
rc = ble_hs_hci_phony_ack_cb(ble_hs_hci_ack, 260);
|
||||
}
|
||||
#else
|
||||
rc = os_sem_pend(&ble_hs_hci_sem,
|
||||
os_time_ms_to_ticks32(BLE_HCI_CMD_TIMEOUT_MS));
|
||||
rc = ble_npl_sem_pend(&ble_hs_hci_sem,
|
||||
ble_npl_time_ms_to_ticks32(BLE_HCI_CMD_TIMEOUT_MS));
|
||||
switch (rc) {
|
||||
case 0:
|
||||
BLE_HS_DBG_ASSERT(ble_hs_hci_ack != NULL);
|
||||
@@ -340,7 +340,7 @@ ble_hs_hci_cmd_tx_empty_ack(uint16_t opcode, void *cmd, uint8_t cmd_len)
|
||||
void
|
||||
ble_hs_hci_rx_ack(uint8_t *ack_ev)
|
||||
{
|
||||
if (os_sem_get_count(&ble_hs_hci_sem) > 0) {
|
||||
if (ble_npl_sem_get_count(&ble_hs_hci_sem) > 0) {
|
||||
/* This ack is unexpected; ignore it. */
|
||||
ble_hci_trans_buf_free(ack_ev);
|
||||
return;
|
||||
@@ -351,7 +351,7 @@ ble_hs_hci_rx_ack(uint8_t *ack_ev)
|
||||
* with the acknowledgement.
|
||||
*/
|
||||
ble_hs_hci_ack = ack_ev;
|
||||
os_sem_release(&ble_hs_hci_sem);
|
||||
ble_npl_sem_release(&ble_hs_hci_sem);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -565,9 +565,9 @@ ble_hs_hci_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = os_sem_init(&ble_hs_hci_sem, 0);
|
||||
rc = ble_npl_sem_init(&ble_hs_hci_sem, 0);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
|
||||
|
||||
rc = os_mutex_init(&ble_hs_hci_mutex);
|
||||
rc = ble_npl_mutex_init(&ble_hs_hci_mutex);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "ble_hs_priv.h"
|
||||
|
||||
int
|
||||
ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg)
|
||||
{
|
||||
STAILQ_INIT(&mq->head);
|
||||
|
||||
ble_npl_event_init(&mq->ev, ev_fn, ev_arg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct os_mbuf *
|
||||
ble_mqueue_get(struct ble_mqueue *mq)
|
||||
{
|
||||
struct os_mbuf_pkthdr *mp;
|
||||
struct os_mbuf *om;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
mp = STAILQ_FIRST(&mq->head);
|
||||
if (mp) {
|
||||
STAILQ_REMOVE_HEAD(&mq->head, omp_next);
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
if (mp) {
|
||||
om = OS_MBUF_PKTHDR_TO_MBUF(mp);
|
||||
} else {
|
||||
om = NULL;
|
||||
}
|
||||
|
||||
return (om);
|
||||
}
|
||||
|
||||
int
|
||||
ble_mqueue_put(struct ble_mqueue *mq, struct ble_npl_eventq *evq, struct os_mbuf *om)
|
||||
{
|
||||
struct os_mbuf_pkthdr *mp;
|
||||
os_sr_t sr;
|
||||
int rc;
|
||||
|
||||
/* Can only place the head of a chained mbuf on the queue. */
|
||||
if (!OS_MBUF_IS_PKTHDR(om)) {
|
||||
rc = OS_EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
mp = OS_MBUF_PKTHDR(om);
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
STAILQ_INSERT_TAIL(&mq->head, mp, omp_next);
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
/* Only post an event to the queue if its specified */
|
||||
if (evq) {
|
||||
ble_npl_eventq_put(evq, &mq->ev);
|
||||
}
|
||||
|
||||
return (0);
|
||||
err:
|
||||
return (rc);
|
||||
}
|
||||
@@ -124,7 +124,16 @@ void ble_hs_unlock(void);
|
||||
void ble_hs_hw_error(uint8_t hw_code);
|
||||
void ble_hs_timer_resched(void);
|
||||
void ble_hs_notifications_sched(void);
|
||||
struct os_eventq *ble_hs_evq_get(void);
|
||||
struct ble_npl_eventq *ble_hs_evq_get(void);
|
||||
|
||||
struct ble_mqueue {
|
||||
STAILQ_HEAD(, os_mbuf_pkthdr) head;
|
||||
struct ble_npl_event ev;
|
||||
};
|
||||
|
||||
int ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg);
|
||||
struct os_mbuf *ble_mqueue_get(struct ble_mqueue *mq);
|
||||
int ble_mqueue_put(struct ble_mqueue *mq, struct ble_npl_eventq *evq, struct os_mbuf *om);
|
||||
|
||||
#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_DEBUG && !BLE_MONITOR
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ ble_l2cap_rx_payload(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
|
||||
/* More fragments remain. */
|
||||
#if MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT) != 0
|
||||
conn->bhc_rx_timeout =
|
||||
os_time_get() + MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT);
|
||||
ble_npl_time_get() + MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT);
|
||||
|
||||
ble_hs_timer_resched();
|
||||
#endif
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
struct ble_l2cap_sig_proc {
|
||||
STAILQ_ENTRY(ble_l2cap_sig_proc) next;
|
||||
|
||||
uint32_t exp_os_ticks;
|
||||
ble_npl_time_t exp_os_ticks;
|
||||
uint16_t conn_handle;
|
||||
uint8_t op;
|
||||
uint8_t id;
|
||||
@@ -304,7 +304,8 @@ ble_l2cap_sig_rx_noop(uint16_t conn_handle,
|
||||
static void
|
||||
ble_l2cap_sig_proc_set_timer(struct ble_l2cap_sig_proc *proc)
|
||||
{
|
||||
proc->exp_os_ticks = os_time_get() + BLE_L2CAP_SIG_UNRESPONSIVE_TIMEOUT;
|
||||
proc->exp_os_ticks = ble_npl_time_get() +
|
||||
ble_npl_time_ms_to_ticks32(BLE_L2CAP_SIG_UNRESPONSIVE_TIMEOUT);
|
||||
ble_hs_timer_resched();
|
||||
}
|
||||
|
||||
@@ -1176,11 +1177,11 @@ ble_l2cap_sig_extract_expired(struct ble_l2cap_sig_proc_list *dst_list)
|
||||
struct ble_l2cap_sig_proc *proc;
|
||||
struct ble_l2cap_sig_proc *prev;
|
||||
struct ble_l2cap_sig_proc *next;
|
||||
uint32_t now;
|
||||
int32_t next_exp_in;
|
||||
int32_t time_diff;
|
||||
ble_npl_time_t now;
|
||||
ble_npl_stime_t next_exp_in;
|
||||
ble_npl_stime_t time_diff;
|
||||
|
||||
now = os_time_get();
|
||||
now = ble_npl_time_get();
|
||||
STAILQ_INIT(dst_list);
|
||||
|
||||
/* Assume each event is either expired or has infinite duration. */
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include "ble_hs_priv.h"
|
||||
#include "ble_monitor_priv.h"
|
||||
|
||||
struct os_mutex lock;
|
||||
struct ble_npl_mutex lock;
|
||||
|
||||
#if MYNEWT_VAL(BLE_MONITOR_UART)
|
||||
struct uart_dev *uart;
|
||||
@@ -57,7 +57,7 @@ static uint8_t rtt_pktbuf[MYNEWT_VAL(BLE_MONITOR_RTT_BUFFER_SIZE)];
|
||||
static size_t rtt_pktbuf_pos;
|
||||
static struct {
|
||||
bool dropped;
|
||||
struct os_callout tmo;
|
||||
struct ble_npl_callout tmo;
|
||||
struct ble_monitor_drops_hdr drops_hdr;
|
||||
} rtt_drops;
|
||||
|
||||
@@ -154,7 +154,7 @@ update_drop_counters(struct ble_monitor_hdr *failed_hdr)
|
||||
|
||||
if (*cnt < UINT8_MAX) {
|
||||
(*cnt)++;
|
||||
os_callout_reset(&rtt_drops.tmo, OS_TICKS_PER_SEC);
|
||||
ble_npl_callout_reset(&rtt_drops.tmo, OS_TICKS_PER_SEC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ reset_drop_counters(void)
|
||||
rtt_drops.drops_hdr.acl_rx = 0;
|
||||
rtt_drops.drops_hdr.other = 0;
|
||||
|
||||
os_callout_stop(&rtt_drops.tmo);
|
||||
ble_npl_callout_stop(&rtt_drops.tmo);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -268,9 +268,9 @@ static FILE *btmon = (FILE *) &(struct File) {
|
||||
|
||||
#if MYNEWT_VAL(BLE_MONITOR_RTT) && MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED)
|
||||
static void
|
||||
drops_tmp_cb(struct os_event *ev)
|
||||
drops_tmp_cb(struct ble_npl_event *ev)
|
||||
{
|
||||
os_mutex_pend(&lock, OS_TIMEOUT_NEVER);
|
||||
ble_npl_mutex_pend(&lock, OS_TIMEOUT_NEVER);
|
||||
|
||||
/*
|
||||
* There's no "nop" in btsnoop protocol so we just send empty system note
|
||||
@@ -280,7 +280,7 @@ drops_tmp_cb(struct os_event *ev)
|
||||
monitor_write_header(BLE_MONITOR_OPCODE_SYSTEM_NOTE, 1);
|
||||
monitor_write("", 1);
|
||||
|
||||
os_mutex_release(&lock);
|
||||
ble_npl_mutex_release(&lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -308,7 +308,7 @@ ble_monitor_init(void)
|
||||
|
||||
#if MYNEWT_VAL(BLE_MONITOR_RTT)
|
||||
#if MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED)
|
||||
os_callout_init(&rtt_drops.tmo, ble_hs_evq_get(), drops_tmp_cb, NULL);
|
||||
ble_npl_callout_init(&rtt_drops.tmo, ble_hs_evq_get(), drops_tmp_cb, NULL);
|
||||
|
||||
/* Initialize types in header (we won't touch them later) */
|
||||
rtt_drops.drops_hdr.type_cmd = BLE_MONITOR_EXTHDR_COMMAND_DROPS;
|
||||
@@ -331,7 +331,7 @@ ble_monitor_init(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
os_mutex_init(&lock);
|
||||
ble_npl_mutex_init(&lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -339,12 +339,12 @@ ble_monitor_init(void)
|
||||
int
|
||||
ble_monitor_send(uint16_t opcode, const void *data, size_t len)
|
||||
{
|
||||
os_mutex_pend(&lock, OS_TIMEOUT_NEVER);
|
||||
ble_npl_mutex_pend(&lock, OS_TIMEOUT_NEVER);
|
||||
|
||||
monitor_write_header(opcode, len);
|
||||
monitor_write(data, len);
|
||||
|
||||
os_mutex_release(&lock);
|
||||
ble_npl_mutex_release(&lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -361,7 +361,7 @@ ble_monitor_send_om(uint16_t opcode, const struct os_mbuf *om)
|
||||
om_tmp = SLIST_NEXT(om_tmp, om_next);
|
||||
}
|
||||
|
||||
os_mutex_pend(&lock, OS_TIMEOUT_NEVER);
|
||||
ble_npl_mutex_pend(&lock, OS_TIMEOUT_NEVER);
|
||||
|
||||
monitor_write_header(opcode, length);
|
||||
|
||||
@@ -370,7 +370,7 @@ ble_monitor_send_om(uint16_t opcode, const struct os_mbuf *om)
|
||||
om = SLIST_NEXT(om, om_next);
|
||||
}
|
||||
|
||||
os_mutex_release(&lock);
|
||||
ble_npl_mutex_release(&lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -423,7 +423,7 @@ ble_monitor_log(int level, const char *fmt, ...)
|
||||
|
||||
ulog.ident_len = sizeof(id);
|
||||
|
||||
os_mutex_pend(&lock, OS_TIMEOUT_NEVER);
|
||||
ble_npl_mutex_pend(&lock, OS_TIMEOUT_NEVER);
|
||||
|
||||
monitor_write_header(BLE_MONITOR_OPCODE_USER_LOGGING,
|
||||
sizeof(ulog) + sizeof(id) + len + 1);
|
||||
@@ -437,7 +437,7 @@ ble_monitor_log(int level, const char *fmt, ...)
|
||||
/* null-terminate string */
|
||||
monitor_write("", 1);
|
||||
|
||||
os_mutex_release(&lock);
|
||||
ble_npl_mutex_release(&lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -352,8 +352,8 @@ ble_sm_gen_csrk(struct ble_sm_proc *proc, uint8_t *csrk)
|
||||
static void
|
||||
ble_sm_proc_set_timer(struct ble_sm_proc *proc)
|
||||
{
|
||||
proc->exp_os_ticks = os_time_get() +
|
||||
os_time_ms_to_ticks32(BLE_SM_TIMEOUT_MS);
|
||||
proc->exp_os_ticks = ble_npl_time_get() +
|
||||
ble_npl_time_ms_to_ticks32(BLE_SM_TIMEOUT_MS);
|
||||
ble_hs_timer_resched();
|
||||
}
|
||||
|
||||
@@ -652,11 +652,11 @@ ble_sm_extract_expired(struct ble_sm_proc_list *dst_list)
|
||||
struct ble_sm_proc *proc;
|
||||
struct ble_sm_proc *prev;
|
||||
struct ble_sm_proc *next;
|
||||
uint32_t now;
|
||||
int32_t next_exp_in;
|
||||
int32_t time_diff;
|
||||
ble_npl_time_t now;
|
||||
ble_npl_stime_t next_exp_in;
|
||||
ble_npl_stime_t time_diff;
|
||||
|
||||
now = os_time_get();
|
||||
now = ble_npl_time_get();
|
||||
STAILQ_INIT(dst_list);
|
||||
|
||||
/* Assume each event is either expired or has infinite duration. */
|
||||
|
||||
@@ -244,7 +244,7 @@ struct ble_sm_keys {
|
||||
struct ble_sm_proc {
|
||||
STAILQ_ENTRY(ble_sm_proc) next;
|
||||
|
||||
uint32_t exp_os_ticks;
|
||||
ble_npl_time_t exp_os_ticks;
|
||||
ble_sm_proc_flags flags;
|
||||
uint16_t conn_handle;
|
||||
uint8_t pair_alg;
|
||||
|
||||
@@ -22,15 +22,13 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* XXX: some or all of these should not be here */
|
||||
#include "os/os.h"
|
||||
#include "syscfg/syscfg.h"
|
||||
|
||||
/* The number of advertising instances */
|
||||
#define BLE_ADV_INSTANCES (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) + 1)
|
||||
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _NIMBLE_NPL_H_
|
||||
#define _NIMBLE_NPL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef BLE_NPL_STORAGE_DECL
|
||||
#define BLE_NPL_STORAGE_DECL static inline
|
||||
#endif
|
||||
|
||||
struct ble_npl_event;
|
||||
typedef void ble_npl_event_fn(struct ble_npl_event *ev);
|
||||
|
||||
enum ble_npl_error {
|
||||
BLE_NPL_OK = 0,
|
||||
BLE_NPL_ENOMEM = 1,
|
||||
BLE_NPL_EINVAL = 2,
|
||||
BLE_NPL_INVALID_PARAM = 3,
|
||||
BLE_NPL_MEM_NOT_ALIGNED = 4,
|
||||
BLE_NPL_BAD_MUTEX = 5,
|
||||
BLE_NPL_TIMEOUT = 6,
|
||||
BLE_NPL_ERR_IN_ISR = 7,
|
||||
BLE_NPL_ERR_PRIV = 8,
|
||||
BLE_NPL_OS_NOT_STARTED = 9,
|
||||
BLE_NPL_ENOENT = 10,
|
||||
BLE_NPL_EBUSY = 11,
|
||||
BLE_NPL_ERROR = 12,
|
||||
};
|
||||
|
||||
typedef enum ble_npl_error ble_npl_error_t;
|
||||
|
||||
/* Include OS-specific definitions */
|
||||
#include "nimble/nimble_npl_os.h"
|
||||
|
||||
/*
|
||||
* Generic
|
||||
*/
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
bool ble_npl_os_started(void);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void *ble_npl_get_current_task_id(void);
|
||||
|
||||
/*
|
||||
* Event queue
|
||||
*/
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
struct ble_npl_eventq *ble_npl_eventq_dflt_get(void);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_eventq_init(struct ble_npl_eventq *evq);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *evq);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_eventq_remove(struct ble_npl_eventq *evq,
|
||||
struct ble_npl_event *ev);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_eventq_run(struct ble_npl_eventq *evq);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
|
||||
void *arg);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
bool ble_npl_event_is_queued(struct ble_npl_event *ev);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void *ble_npl_event_get_arg(struct ble_npl_event *ev);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg);
|
||||
|
||||
/*
|
||||
* Mutexes
|
||||
*/
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu,
|
||||
ble_npl_time_t timeout);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu);
|
||||
|
||||
/*
|
||||
* Semaphores
|
||||
*/
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem,
|
||||
ble_npl_time_t timeout);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem);
|
||||
|
||||
/*
|
||||
* Callouts
|
||||
*/
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
|
||||
ble_npl_event_fn *ev_cb, void *ev_arg);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
int ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_callout_stop(struct ble_npl_callout *co);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
int ble_npl_callout_queued(struct ble_npl_callout *co);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
uint32_t ble_npl_callout_get_ticks(struct ble_npl_callout *co);
|
||||
|
||||
/*
|
||||
* Time functions
|
||||
*/
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_time_t ble_npl_time_get(void);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_error_t ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks);
|
||||
|
||||
/*
|
||||
* Hardware-specific
|
||||
*
|
||||
* These symbols should be most likely defined by application since they are
|
||||
* specific to hardware, not to OS.
|
||||
*/
|
||||
|
||||
#if NIMBLE_CFG_CONTROLLER
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_hw_set_isr(int irqn, uint32_t addr);
|
||||
|
||||
#endif
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
uint32_t ble_npl_hw_enter_critical(void);
|
||||
|
||||
BLE_NPL_STORAGE_DECL
|
||||
void ble_npl_hw_exit_critical(uint32_t ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NIMBLE_NPL_H_ */
|
||||
@@ -26,4 +26,5 @@ pkg.keywords:
|
||||
- bluetooth
|
||||
|
||||
pkg.deps:
|
||||
- porting/npl/mynewt
|
||||
- "@apache-mynewt-core/kernel/os"
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Configure NimBLE variables
|
||||
NIMBLE_ROOT := ../../..
|
||||
NIMBLE_CFG_TINYCRYPT := 1
|
||||
include $(NIMBLE_ROOT)/porting/nimble/Makefile.defs
|
||||
|
||||
# Add dummy NPL, dummy HCI transport and all NimBLE sources to build
|
||||
SRC = \
|
||||
$(NIMBLE_ROOT)/porting/npl/dummy/src/npl_os_dummy.c \
|
||||
$(NIMBLE_ROOT)/porting/npl/dummy/src/hci_dummy.c \
|
||||
$(NIMBLE_SRC) \
|
||||
main.c \
|
||||
|
||||
# Add dummy NPL and all NimBLE directories to include paths
|
||||
INC = \
|
||||
$(NIMBLE_ROOT)/porting/npl/dummy/include \
|
||||
$(NIMBLE_INCLUDE) \
|
||||
|
||||
OBJ := $(SRC:.c=.o)
|
||||
|
||||
CFLAGS := $(NIMBLE_CFLAGS) -DBLE_NPL_STORAGE_DECL=
|
||||
|
||||
.PHONY: all clean
|
||||
.DEFAULT: all
|
||||
|
||||
all: dummy
|
||||
|
||||
clean:
|
||||
rm $(OBJ) -f
|
||||
rm dummy -f
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -m32 -c $(addprefix -I, $(INC)) $(CFLAGS) -o $@ $<
|
||||
|
||||
dummy: $(OBJ)
|
||||
$(CC) -m32 -o $@ $^
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "nimble/nimble_port.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
nimble_port_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
NIMBLE_CFLAGS += \
|
||||
-DNIMBLE_CFG_CONTROLLER=1 \
|
||||
|
||||
NIMBLE_INCLUDE += \
|
||||
$(NIMBLE_ROOT)/nimble/transport/ram/include \
|
||||
$(NIMBLE_ROOT)/nimble/controller/include \
|
||||
$(NIMBLE_ROOT)/nimble/drivers/nrf52/include \
|
||||
|
||||
NIMBLE_SRC += \
|
||||
$(NIMBLE_ROOT)/nimble/transport/ram/src/ble_hci_ram.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_sched.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_xcvr.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_whitelist.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_ctrl.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_hci.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_supp_cmd.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_adv.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_conn.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_resolv.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_conn_hci.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_rand.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_scan.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_dtm.c \
|
||||
$(NIMBLE_ROOT)/nimble/controller/src/ble_ll_hci_ev.c \
|
||||
$(NIMBLE_ROOT)/nimble/drivers/nrf52/src/ble_hw.c \
|
||||
$(NIMBLE_ROOT)/nimble/drivers/nrf52/src/ble_phy.c \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/os_cputime.c \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/os_cputime_pwr2.c \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/hal_timer.c \
|
||||
@@ -0,0 +1,96 @@
|
||||
ifeq (,$(NIMBLE_ROOT))
|
||||
$(error NIMBLE_ROOT shall be defined)
|
||||
endif
|
||||
|
||||
NIMBLE_CFLAGS :=
|
||||
|
||||
NIMBLE_INCLUDE := \
|
||||
$(NIMBLE_ROOT)/nimble/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/ans/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/bas/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/bleuart/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/gap/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/gatt/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/ias/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/lls/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/tps/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/store/ram/include \
|
||||
$(NIMBLE_ROOT)/nimble/host/util/include \
|
||||
$(NIMBLE_ROOT)/porting/nimble/include \
|
||||
|
||||
NIMBLE_SRC := \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_att.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_att_clt.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_att_cmd.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_att_svr.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_eddystone.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_gap.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_gattc.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_gatts.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_adv.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_atomic.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_cfg.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_conn.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_dbg.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_flow.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_hci.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_hci_cmd.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_hci_evt.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_hci_util.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_id.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_log.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_mbuf.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_mqueue.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_misc.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_pvcy.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_hs_startup.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_ibeacon.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_l2cap.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_l2cap_coc.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_l2cap_sig.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_l2cap_sig_cmd.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_monitor.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_sm_alg.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_sm.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_sm_cmd.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_sm_lgcy.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_sm_sc.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_store.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_store_util.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/src/ble_uuid.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/ans/src/ble_svc_ans.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/bas/src/ble_svc_bas.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/gap/src/ble_svc_gap.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/gatt/src/ble_svc_gatt.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/ias/src/ble_svc_ias.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/lls/src/ble_svc_lls.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/services/tps/src/ble_svc_tps.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/store/ram/src/ble_store_ram.c \
|
||||
$(NIMBLE_ROOT)/nimble/host/util/src/addr.c \
|
||||
$(NIMBLE_ROOT)/nimble/src/ble_util.c \
|
||||
$(NIMBLE_ROOT)/nimble/src/hci_common.c \
|
||||
|
||||
# Few utils and data structures copied from Mynewt
|
||||
NIMBLE_SRC += \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/nimble_port.c \
|
||||
|
||||
# Few utils and data structures copied from Mynewt
|
||||
NIMBLE_SRC += \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/endian.c \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/mem.c \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/os_mbuf.c \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/os_mempool.c \
|
||||
$(NIMBLE_ROOT)/porting/nimble/src/os_msys_init.c \
|
||||
|
||||
ifneq (,$(NIMBLE_CFG_CONTROLLER))
|
||||
include $(NIMBLE_ROOT)/porting/nimble/Makefile.controller
|
||||
endif
|
||||
|
||||
# TinyCrypt (for SM)
|
||||
ifneq (,$(NIMBLE_CFG_TINYCRYPT))
|
||||
include $(NIMBLE_ROOT)/porting/nimble/Makefile.tinycrypt
|
||||
endif
|
||||
|
||||
NIMBLE_OBJ := $(NIMBLE_SRC:.c=.o)
|
||||
@@ -0,0 +1,10 @@
|
||||
NIMBLE_INCLUDE += \
|
||||
$(NIMBLE_ROOT)/ext/tinycrypt/include \
|
||||
|
||||
NIMBLE_SRC += \
|
||||
$(NIMBLE_ROOT)/ext/tinycrypt/src/aes_decrypt.c \
|
||||
$(NIMBLE_ROOT)/ext/tinycrypt/src/aes_encrypt.c \
|
||||
$(NIMBLE_ROOT)/ext/tinycrypt/src/cmac_mode.c \
|
||||
$(NIMBLE_ROOT)/ext/tinycrypt/src/ecc.c \
|
||||
$(NIMBLE_ROOT)/ext/tinycrypt/src/ecc_dh.c \
|
||||
$(NIMBLE_ROOT)/ext/tinycrypt/src/utils.c \
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup HAL
|
||||
* @{
|
||||
* @defgroup HALTimer HAL Timer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef H_HAL_TIMER_
|
||||
#define H_HAL_TIMER_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "os/queue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* HAL timer callback */
|
||||
typedef void (*hal_timer_cb)(void *arg);
|
||||
|
||||
/**
|
||||
* The HAL timer structure. The user can declare as many of these structures
|
||||
* as desired. They are enqueued on a particular HW timer queue when the user
|
||||
* calls the :c:func:`hal_timer_start()` or :c:func:`hal_timer_start_at()` API.
|
||||
* The user must have called :c:func:`hal_timer_set_cb()` before starting a
|
||||
* timer.
|
||||
*
|
||||
* NOTE: the user should not have to modify/examine the contents of this
|
||||
* structure; the hal timer API should be used.
|
||||
*/
|
||||
struct hal_timer {
|
||||
/** Internal platform specific pointer */
|
||||
void *bsp_timer;
|
||||
/** Callback function */
|
||||
hal_timer_cb cb_func;
|
||||
/** Callback argument */
|
||||
void *cb_arg;
|
||||
/** Tick at which timer should expire */
|
||||
uint32_t expiry;
|
||||
TAILQ_ENTRY(hal_timer) link; /* Queue linked list structure */
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize a HW timer.
|
||||
*
|
||||
* @param timer_num The number of the HW timer to initialize
|
||||
* @param cfg Hardware specific timer configuration. This is
|
||||
* passed from BSP directly to the MCU specific driver.
|
||||
*/
|
||||
int hal_timer_init(int timer_num, void *cfg);
|
||||
|
||||
/**
|
||||
* Un-initialize a HW timer.
|
||||
*
|
||||
* @param timer_num The number of the HW timer to un-initialize
|
||||
*/
|
||||
int hal_timer_deinit(int timer_num);
|
||||
|
||||
/**
|
||||
* Config a HW timer at the given frequency and start it. If the exact
|
||||
* frequency is not obtainable the closest obtainable frequency is set.
|
||||
*
|
||||
* @param timer_num The number of the HW timer to configure
|
||||
* @param freq_hz The frequency in Hz to configure the timer at
|
||||
*
|
||||
* @return 0 on success, non-zero error code on failure
|
||||
*/
|
||||
int hal_timer_config(int timer_num, uint32_t freq_hz);
|
||||
|
||||
/**
|
||||
* Returns the resolution of the HW timer. NOTE: the frequency may not be
|
||||
* obtainable so the caller can use this to determine the resolution.
|
||||
* Returns resolution in nanoseconds. A return value of 0 indicates an invalid
|
||||
* timer was used.
|
||||
*
|
||||
* @param timer_num The number of the HW timer to get resolution for
|
||||
*
|
||||
* @return The resolution of the timer
|
||||
*/
|
||||
uint32_t hal_timer_get_resolution(int timer_num);
|
||||
|
||||
/**
|
||||
* Returns the HW timer current tick value
|
||||
*
|
||||
* @param timer_num The HW timer to read the tick value from
|
||||
*
|
||||
* @return The current tick value
|
||||
*/
|
||||
uint32_t hal_timer_read(int timer_num);
|
||||
|
||||
/**
|
||||
* Perform a blocking delay for a number of ticks.
|
||||
*
|
||||
* @param timer_num The timer number to use for the blocking delay
|
||||
* @param ticks The number of ticks to delay for
|
||||
*
|
||||
* @return 0 on success, non-zero error code on failure
|
||||
*/
|
||||
int hal_timer_delay(int timer_num, uint32_t ticks);
|
||||
|
||||
/**
|
||||
* Set the timer structure prior to use. Should not be called if the timer
|
||||
* is running. Must be called at least once prior to using timer.
|
||||
*
|
||||
* @param timer_num The number of the HW timer to configure the callback on
|
||||
* @param tmr The timer structure to use for this timer
|
||||
* @param cb_func The timer callback to call when the timer fires
|
||||
* @param arg An opaque argument to provide the timer callback
|
||||
*
|
||||
* @return 0 on success, non-zero error code on failure.
|
||||
*/
|
||||
int hal_timer_set_cb(int timer_num, struct hal_timer *tmr, hal_timer_cb cb_func,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Start a timer that will expire in 'ticks' ticks. Ticks cannot be 0
|
||||
*
|
||||
* @param tmr The timer to start
|
||||
* @param ticks The number of ticks to expire the timer in
|
||||
*
|
||||
* @return 0 on success, non-zero error code on failure.
|
||||
*/
|
||||
int hal_timer_start(struct hal_timer *tmr, uint32_t ticks);
|
||||
|
||||
/**
|
||||
* Start a timer that will expire when the timer reaches 'tick'. If tick
|
||||
* has already passed the timer callback will be called "immediately" (at
|
||||
* interrupt context).
|
||||
*
|
||||
* @param tmr The timer to start
|
||||
* @param tick The absolute tick value to fire the timer at
|
||||
*
|
||||
* @return 0 on success, non-zero error code on failure.
|
||||
*/
|
||||
int hal_timer_start_at(struct hal_timer *tmr, uint32_t tick);
|
||||
|
||||
/**
|
||||
* Stop a currently running timer; associated callback will NOT be called
|
||||
*
|
||||
* @param tmr The timer to stop
|
||||
*/
|
||||
int hal_timer_stop(struct hal_timer *tmr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_HAL_TIMER_ */
|
||||
|
||||
/**
|
||||
* @} HALTimer
|
||||
* @} HAL
|
||||
*/
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef __LOG_H__
|
||||
#define __LOG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
log_dummy(void *log, ...)
|
||||
{
|
||||
}
|
||||
|
||||
#define LOG_DEBUG(_log, _mod, ...) log_dummy(_log, ## __VA_ARGS__)
|
||||
#define LOG_INFO(_log, _mod, ...) log_dummy(_log, ## __VA_ARGS__)
|
||||
#define LOG_WARN(_log, _mod, ...) log_dummy(_log, ## __VA_ARGS__)
|
||||
#define LOG_ERROR(_log, _mod, ...) log_dummy(_log, ## __VA_ARGS__)
|
||||
#define LOG_CRITICAL(_log, _mod, ...) log_dummy(_log, ## __VA_ARGS__)
|
||||
|
||||
struct log {
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LOG_H__ */
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_UTIL_MEM_
|
||||
#define H_UTIL_MEM_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct os_mempool;
|
||||
struct os_mbuf_pool;
|
||||
|
||||
int mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks,
|
||||
uint32_t block_size, char *name, void **out_buf);
|
||||
int mem_malloc_mempool_ext(struct os_mempool_ext *mempool, uint16_t num_blocks,
|
||||
uint32_t block_size, char *name, void **out_buf);
|
||||
|
||||
int mem_malloc_mbuf_pool(struct os_mempool *mempool,
|
||||
struct os_mbuf_pool *mbuf_pool, uint16_t num_blocks,
|
||||
uint32_t block_size, char *name,
|
||||
void **out_buf);
|
||||
int mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
|
||||
struct os_mbuf_pool *mbuf_pool, int num_blocks,
|
||||
int block_size, char *name,
|
||||
void **out_buf);
|
||||
int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
|
||||
struct os_mbuf_pool *mbuf_pool, int num_blocks,
|
||||
int block_size, char *name);
|
||||
|
||||
/**
|
||||
* Specifies a function used as a callback. Functions of this type allocate an
|
||||
* mbuf chain meant to hold a packet fragment. The resulting mbuf must contain
|
||||
* a pkthdr.
|
||||
*
|
||||
* @param frag_size The number of data bytes that the mbuf will
|
||||
* eventually contain.
|
||||
* @param arg A generic parameter.
|
||||
*
|
||||
* @return An allocated mbuf chain on success;
|
||||
* NULL on failure.
|
||||
*/
|
||||
typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);
|
||||
|
||||
struct os_mbuf *mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
|
||||
mem_frag_alloc_fn *alloc_cb, void *cb_arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _NIMBLE_PORT_H
|
||||
#define _NIMBLE_PORT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void nimble_port_init(void);
|
||||
|
||||
#if NIMBLE_CFG_CONTROLLER
|
||||
void nimble_port_ll_task_func(void *arg);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NIMBLE_PORT_H */
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_ENDIAN_
|
||||
#define H_ENDIAN_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Internal helpers */
|
||||
#ifndef os_bswap_64
|
||||
#define os_bswap_64(x) ((uint64_t) \
|
||||
((((x) & 0xff00000000000000ull) >> 56) | \
|
||||
(((x) & 0x00ff000000000000ull) >> 40) | \
|
||||
(((x) & 0x0000ff0000000000ull) >> 24) | \
|
||||
(((x) & 0x000000ff00000000ull) >> 8) | \
|
||||
(((x) & 0x00000000ff000000ull) << 8) | \
|
||||
(((x) & 0x0000000000ff0000ull) << 24) | \
|
||||
(((x) & 0x000000000000ff00ull) << 40) | \
|
||||
(((x) & 0x00000000000000ffull) << 56)))
|
||||
#endif
|
||||
|
||||
#ifndef os_bswap_32
|
||||
#define os_bswap_32(x) ((uint32_t) \
|
||||
((((x) & 0xff000000) >> 24) | \
|
||||
(((x) & 0x00ff0000) >> 8) | \
|
||||
(((x) & 0x0000ff00) << 8) | \
|
||||
(((x) & 0x000000ff) << 24)))
|
||||
#endif
|
||||
|
||||
#ifndef os_bswap_16
|
||||
#define os_bswap_16(x) ((uint16_t) \
|
||||
((((x) & 0xff00) >> 8) | \
|
||||
(((x) & 0x00ff) << 8)))
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
|
||||
#ifndef ntohll
|
||||
#define ntohll(x) ((uint64_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htonll
|
||||
#define htonll(x) ((uint64_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef ntohl
|
||||
#define ntohl(x) ((uint32_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htonl
|
||||
#define htonl(x) ((uint32_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef ntohs
|
||||
#define ntohs(x) ((uint16_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htons
|
||||
#define htons(x) ((uint16_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htobe16
|
||||
#define htobe16(x) ((uint16_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htole16
|
||||
#define htole16(x) os_bswap_16 (x)
|
||||
#endif
|
||||
|
||||
#ifndef be16toh
|
||||
#define be16toh(x) ((uint16_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef le16toh
|
||||
#define le16toh(x) os_bswap_16 (x)
|
||||
#endif
|
||||
|
||||
#ifndef htobe32
|
||||
#define htobe32(x) ((uint32_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htole32
|
||||
#define htole32(x) os_bswap_32 (x)
|
||||
#endif
|
||||
|
||||
#ifndef be32toh
|
||||
#define be32toh(x) ((uint32_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef le32toh
|
||||
#define le32toh(x) os_bswap_32 (x)
|
||||
#endif
|
||||
|
||||
#ifndef htobe64
|
||||
#define htobe64(x) ((uint64_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htole64
|
||||
#define htole64(x) os_bswap_64 (x)
|
||||
#endif
|
||||
|
||||
#ifndef be64toh
|
||||
#define be64toh(x) ((uint64_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef le64toh
|
||||
#define le64toh(x) os_bswap_64 (x)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef ntohll
|
||||
#define ntohll(x) os_bswap_64(x)
|
||||
#endif
|
||||
|
||||
#ifndef htonll
|
||||
#define htonll ntohll
|
||||
#endif
|
||||
|
||||
#ifndef ntohl
|
||||
#define ntohl(x) os_bswap_32(x)
|
||||
#endif
|
||||
|
||||
#ifndef htonl
|
||||
#define htonl ntohl
|
||||
#endif
|
||||
|
||||
#ifndef htons
|
||||
#define htons(x) os_bswap_16(x)
|
||||
#endif
|
||||
|
||||
#ifndef ntohs
|
||||
#define ntohs htons
|
||||
#endif
|
||||
|
||||
#ifndef htobe16
|
||||
#define htobe16(x) os_bswap_16(x)
|
||||
#endif
|
||||
|
||||
#ifndef htole16
|
||||
#define htole16(x) ((uint16_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef be16toh
|
||||
#define be16toh(x) os_bswap_16(x)
|
||||
#endif
|
||||
|
||||
#ifndef le16toh
|
||||
#define le16toh(x) ((uint16_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htobe32
|
||||
#define htobe32(x) os_bswap_32(x)
|
||||
#endif
|
||||
|
||||
#ifndef htole32
|
||||
#define htole32(x) ((uint32_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef be32toh
|
||||
#define be32toh(x) os_bswap_32(x)
|
||||
#endif
|
||||
|
||||
#ifndef le32toh
|
||||
#define le32toh(x) ((uint32_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef htobe64
|
||||
#define htobe64(x) os_bswap64(x)
|
||||
#endif
|
||||
|
||||
#ifndef htole64
|
||||
#define htole64(x) ((uint64_t)(x))
|
||||
#endif
|
||||
|
||||
#ifndef be64toh
|
||||
#define be64toh(x) os_bswap64(x)
|
||||
#endif
|
||||
|
||||
#ifndef le64toh
|
||||
#define le64toh(x) ((uint64_t)(x))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
void put_le16(void *buf, uint16_t x);
|
||||
void put_le32(void *buf, uint32_t x);
|
||||
void put_le64(void *buf, uint64_t x);
|
||||
uint16_t get_le16(const void *buf);
|
||||
uint32_t get_le32(const void *buf);
|
||||
uint64_t get_le64(const void *buf);
|
||||
void put_be16(void *buf, uint16_t x);
|
||||
void put_be32(void *buf, uint32_t x);
|
||||
void put_be64(void *buf, uint64_t x);
|
||||
uint16_t get_be16(const void *buf);
|
||||
uint32_t get_be32(const void *buf);
|
||||
uint64_t get_be64(const void *buf);
|
||||
void swap_in_place(void *buf, int len);
|
||||
void swap_buf(uint8_t *dst, const uint8_t *src, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _OS_H
|
||||
#define _OS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(a, b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
|
||||
#define OS_ALIGN(__n, __a) ( \
|
||||
(((__n) & ((__a) - 1)) == 0) ? \
|
||||
(__n) : \
|
||||
((__n) + ((__a) - ((__n) & ((__a) - 1)))) \
|
||||
)
|
||||
#define OS_ALIGNMENT (BLE_NPL_OS_ALIGNMENT)
|
||||
|
||||
typedef uint32_t os_sr_t;
|
||||
#define OS_ENTER_CRITICAL(_sr) (_sr = ble_npl_hw_enter_critical())
|
||||
#define OS_EXIT_CRITICAL(_sr) (ble_npl_hw_exit_critical(_sr))
|
||||
|
||||
/* Mynewt components (not abstracted in NPL) */
|
||||
#include "os/endian.h"
|
||||
#include "os/queue.h"
|
||||
#include "os/os_error.h"
|
||||
#include "os/os_mbuf.h"
|
||||
#include "os/os_mempool.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OS_H */
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup OSKernel
|
||||
* @{
|
||||
* @defgroup OSCPUTime High Resolution Timers
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef H_OS_CPUTIME_
|
||||
#define H_OS_CPUTIME_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "hal/hal_timer.h"
|
||||
#include "os/os.h"
|
||||
|
||||
/*
|
||||
* NOTE: these definitions allow one to override the cputime frequency used.
|
||||
* The reason these definitions exist is to make the code more
|
||||
* efficient/smaller when CPUTIME counts at 1 MHz.
|
||||
*
|
||||
* For those who want a different cputime frequency, you can set the config
|
||||
* definition for OS_CPUTIME_FREQ to the desired frequency in your project,
|
||||
* target or bsp.
|
||||
*/
|
||||
#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 1000000)
|
||||
|
||||
#define OS_CPUTIME_FREQ_1MHZ
|
||||
|
||||
#elif MYNEWT_VAL(OS_CPUTIME_FREQ) == 256 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 512 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 1024 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 2048 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 4096 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 8192 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 16384 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 65536 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 131072 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 262144 || \
|
||||
MYNEWT_VAL(OS_CPUTIME_FREQ) == 524288
|
||||
|
||||
#define OS_CPUTIME_FREQ_PWR2
|
||||
|
||||
#elif MYNEWT_VAL(OS_CPUTIME_FREQ) > 1000000
|
||||
|
||||
#define OS_CPUTIME_FREQ_HIGH
|
||||
|
||||
#else
|
||||
|
||||
#error "Invalid OS_CPUTIME_FREQ value. Value must be one of a) a power of 2" \
|
||||
">= 256Hz, or b) any value >= 1MHz"
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OS_CPUTIME_FREQ_HIGH)
|
||||
/* CPUTIME data. */
|
||||
struct os_cputime_data
|
||||
{
|
||||
uint32_t ticks_per_usec; /* number of ticks per usec */
|
||||
};
|
||||
extern struct os_cputime_data g_os_cputime;
|
||||
#endif
|
||||
|
||||
/* Helpful macros to compare cputimes */
|
||||
/** evaluates to true if t1 is before t2 in time */
|
||||
#define CPUTIME_LT(__t1, __t2) ((int32_t) ((__t1) - (__t2)) < 0)
|
||||
/** evaluates to true if t1 is after t2 in time */
|
||||
#define CPUTIME_GT(__t1, __t2) ((int32_t) ((__t1) - (__t2)) > 0)
|
||||
/** evaluates to true if t1 is after t2 in time */
|
||||
#define CPUTIME_GEQ(__t1, __t2) ((int32_t) ((__t1) - (__t2)) >= 0)
|
||||
/** evaluates to true if t1 is on or after t2 in time */
|
||||
#define CPUTIME_LEQ(__t1, __t2) ((int32_t) ((__t1) - (__t2)) <= 0)
|
||||
|
||||
/**
|
||||
* Initialize the cputime module. This must be called after os_init is called
|
||||
* and before any other timer API are used. This should be called only once
|
||||
* and should be called before the hardware timer is used.
|
||||
*
|
||||
* @param clock_freq The desired cputime frequency, in hertz (Hz).
|
||||
*
|
||||
* @return int 0 on success; -1 on error.
|
||||
*/
|
||||
int os_cputime_init(uint32_t clock_freq);
|
||||
|
||||
/**
|
||||
* Returns the low 32 bits of cputime.
|
||||
*
|
||||
* @return uint32_t The lower 32 bits of cputime
|
||||
*/
|
||||
uint32_t os_cputime_get32(void);
|
||||
|
||||
#if !defined(OS_CPUTIME_FREQ_PWR2)
|
||||
/**
|
||||
* Converts the given number of nanoseconds into cputime ticks.
|
||||
* Not defined if OS_CPUTIME_FREQ_PWR2 is defined.
|
||||
*
|
||||
* @param usecs The number of nanoseconds to convert to ticks
|
||||
*
|
||||
* @return uint32_t The number of ticks corresponding to 'nsecs'
|
||||
*/
|
||||
uint32_t os_cputime_nsecs_to_ticks(uint32_t nsecs);
|
||||
|
||||
/**
|
||||
* Convert the given number of ticks into nanoseconds.
|
||||
* Not defined if OS_CPUTIME_FREQ_PWR2 is defined.
|
||||
*
|
||||
* @param ticks The number of ticks to convert to nanoseconds.
|
||||
*
|
||||
* @return uint32_t The number of nanoseconds corresponding to 'ticks'
|
||||
*/
|
||||
uint32_t os_cputime_ticks_to_nsecs(uint32_t ticks);
|
||||
|
||||
/**
|
||||
* Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
|
||||
* Not defined if OS_CPUTIME_FREQ_PWR2 is defined.
|
||||
*
|
||||
*
|
||||
* @param nsecs The number of nanoseconds to wait.
|
||||
*/
|
||||
void os_cputime_delay_nsecs(uint32_t nsecs);
|
||||
#endif
|
||||
|
||||
#if defined(OS_CPUTIME_FREQ_1MHZ)
|
||||
#define os_cputime_usecs_to_ticks(x) (x)
|
||||
#define os_cputime_ticks_to_usecs(x) (x)
|
||||
#else
|
||||
|
||||
/**
|
||||
* Converts the given number of microseconds into cputime ticks.
|
||||
*
|
||||
* @param usecs The number of microseconds to convert to ticks
|
||||
*
|
||||
* @return uint32_t The number of ticks corresponding to 'usecs'
|
||||
*/
|
||||
uint32_t os_cputime_usecs_to_ticks(uint32_t usecs);
|
||||
|
||||
/**
|
||||
* Convert the given number of ticks into microseconds.
|
||||
*
|
||||
* @param ticks The number of ticks to convert to microseconds.
|
||||
*
|
||||
* @return uint32_t The number of microseconds corresponding to 'ticks'
|
||||
*/
|
||||
uint32_t os_cputime_ticks_to_usecs(uint32_t ticks);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Wait until the number of ticks has elapsed. This is a blocking delay.
|
||||
*
|
||||
* @param ticks The number of ticks to wait.
|
||||
*/
|
||||
void os_cputime_delay_ticks(uint32_t ticks);
|
||||
|
||||
/**
|
||||
* Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
|
||||
*
|
||||
* @param usecs The number of usecs to wait.
|
||||
*/
|
||||
void os_cputime_delay_usecs(uint32_t usecs);
|
||||
|
||||
/**
|
||||
* Initialize a CPU timer, using the given HAL timer.
|
||||
*
|
||||
* @param timer The timer to initialize. Cannot be NULL.
|
||||
* @param fp The timer callback function. Cannot be NULL.
|
||||
* @param arg Pointer to data object to pass to timer.
|
||||
*/
|
||||
void os_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Start a cputimer that will expire at 'cputime'. If cputime has already
|
||||
* passed, the timer callback will still be called (at interrupt context).
|
||||
*
|
||||
* NOTE: This must be called when the timer is stopped.
|
||||
*
|
||||
* @param timer Pointer to timer to start. Cannot be NULL.
|
||||
* @param cputime The cputime at which the timer should expire.
|
||||
*
|
||||
* @return int 0 on success; EINVAL if timer already started or timer struct
|
||||
* invalid
|
||||
*
|
||||
*/
|
||||
int os_cputime_timer_start(struct hal_timer *timer, uint32_t cputime);
|
||||
|
||||
/**
|
||||
* Sets a cpu timer that will expire 'usecs' microseconds from the current
|
||||
* cputime.
|
||||
*
|
||||
* NOTE: This must be called when the timer is stopped.
|
||||
*
|
||||
* @param timer Pointer to timer. Cannot be NULL.
|
||||
* @param usecs The number of usecs from now at which the timer will expire.
|
||||
*
|
||||
* @return int 0 on success; EINVAL if timer already started or timer struct
|
||||
* invalid
|
||||
*/
|
||||
int os_cputime_timer_relative(struct hal_timer *timer, uint32_t usecs);
|
||||
|
||||
/**
|
||||
* Stops a cputimer from running. The timer is removed from the timer queue
|
||||
* and interrupts are disabled if no timers are left on the queue. Can be
|
||||
* called even if timer is not running.
|
||||
*
|
||||
* @param timer Pointer to cputimer to stop. Cannot be NULL.
|
||||
*/
|
||||
void os_cputime_timer_stop(struct hal_timer *timer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_OS_CPUTIME_ */
|
||||
|
||||
/**
|
||||
* @} OSCPUTime
|
||||
* @} OSKernel
|
||||
*/
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_OS_ERROR_
|
||||
#define H_OS_ERROR_
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
enum os_error {
|
||||
OS_OK = 0,
|
||||
OS_ENOMEM = 1,
|
||||
OS_EINVAL = 2,
|
||||
OS_INVALID_PARM = 3,
|
||||
OS_MEM_NOT_ALIGNED = 4,
|
||||
OS_BAD_MUTEX = 5,
|
||||
OS_TIMEOUT = 6,
|
||||
OS_ERR_IN_ISR = 7, /* Function cannot be called from ISR */
|
||||
OS_ERR_PRIV = 8, /* Privileged access error */
|
||||
OS_NOT_STARTED = 9, /* OS must be started to call this function, but isn't */
|
||||
OS_ENOENT = 10, /* No such thing */
|
||||
OS_EBUSY = 11, /* Resource busy */
|
||||
OS_ERROR = 12, /* Generic Error */
|
||||
};
|
||||
|
||||
typedef enum os_error os_error_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,627 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup OSKernel
|
||||
* @{
|
||||
* @defgroup OSMbuf Chained Memory Buffers
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _OS_MBUF_H
|
||||
#define _OS_MBUF_H
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A mbuf pool from which to allocate mbufs. This contains a pointer to the os
|
||||
* mempool to allocate mbufs out of, the total number of elements in the pool,
|
||||
* and the amount of "user" data in a non-packet header mbuf. The total pool
|
||||
* size, in bytes, should be:
|
||||
* os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
|
||||
*/
|
||||
struct os_mbuf_pool {
|
||||
/**
|
||||
* Total length of the databuf in each mbuf. This is the size of the
|
||||
* mempool block, minus the mbuf header
|
||||
*/
|
||||
uint16_t omp_databuf_len;
|
||||
/**
|
||||
* The memory pool which to allocate mbufs out of
|
||||
*/
|
||||
struct os_mempool *omp_pool;
|
||||
|
||||
STAILQ_ENTRY(os_mbuf_pool) omp_next;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A packet header structure that preceeds the mbuf packet headers.
|
||||
*/
|
||||
struct os_mbuf_pkthdr {
|
||||
/**
|
||||
* Overall length of the packet.
|
||||
*/
|
||||
uint16_t omp_len;
|
||||
/**
|
||||
* Flags
|
||||
*/
|
||||
uint16_t omp_flags;
|
||||
|
||||
STAILQ_ENTRY(os_mbuf_pkthdr) omp_next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Chained memory buffer.
|
||||
*/
|
||||
struct os_mbuf {
|
||||
/**
|
||||
* Current pointer to data in the structure
|
||||
*/
|
||||
uint8_t *om_data;
|
||||
/**
|
||||
* Flags associated with this buffer, see OS_MBUF_F_* defintions
|
||||
*/
|
||||
uint8_t om_flags;
|
||||
/**
|
||||
* Length of packet header
|
||||
*/
|
||||
uint8_t om_pkthdr_len;
|
||||
/**
|
||||
* Length of data in this buffer
|
||||
*/
|
||||
uint16_t om_len;
|
||||
|
||||
/**
|
||||
* The mbuf pool this mbuf was allocated out of
|
||||
*/
|
||||
struct os_mbuf_pool *om_omp;
|
||||
|
||||
SLIST_ENTRY(os_mbuf) om_next;
|
||||
|
||||
/**
|
||||
* Pointer to the beginning of the data, after this buffer
|
||||
*/
|
||||
uint8_t om_databuf[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure representing a queue of mbufs.
|
||||
*/
|
||||
struct os_mqueue {
|
||||
STAILQ_HEAD(, os_mbuf_pkthdr) mq_head;
|
||||
/** Event to post when new buffers are available on the queue. */
|
||||
struct ble_npl_event mq_ev;
|
||||
};
|
||||
|
||||
/*
|
||||
* Given a flag number, provide the mask for it
|
||||
*
|
||||
* @param __n The number of the flag in the mask
|
||||
*/
|
||||
#define OS_MBUF_F_MASK(__n) (1 << (__n))
|
||||
|
||||
/*
|
||||
* Checks whether a given mbuf is a packet header mbuf
|
||||
*
|
||||
* @param __om The mbuf to check
|
||||
*/
|
||||
#define OS_MBUF_IS_PKTHDR(__om) \
|
||||
((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr))
|
||||
|
||||
/** Get a packet header pointer given an mbuf pointer */
|
||||
#define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *) \
|
||||
((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf)))
|
||||
|
||||
/** Given a mbuf packet header pointer, return a pointer to the mbuf */
|
||||
#define OS_MBUF_PKTHDR_TO_MBUF(__hdr) \
|
||||
(struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
|
||||
|
||||
/**
|
||||
* Gets the length of an entire mbuf chain. The specified mbuf must have a
|
||||
* packet header.
|
||||
*/
|
||||
#define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
|
||||
|
||||
/**
|
||||
* Access the data of a mbuf, and cast it to type
|
||||
*
|
||||
* @param __om The mbuf to access, and cast
|
||||
* @param __type The type to cast it to
|
||||
*/
|
||||
#define OS_MBUF_DATA(__om, __type) \
|
||||
(__type) ((__om)->om_data)
|
||||
|
||||
/**
|
||||
* Access the "user header" in the head of an mbuf chain.
|
||||
*
|
||||
* @param om Pointer to the head of an mbuf chain.
|
||||
*/
|
||||
#define OS_MBUF_USRHDR(om) \
|
||||
(void *)((uint8_t *)om + sizeof (struct os_mbuf) + \
|
||||
sizeof (struct os_mbuf_pkthdr))
|
||||
|
||||
/**
|
||||
* Retrieves the length of the user header in an mbuf.
|
||||
*
|
||||
* @param om Pointer to the mbuf to query.
|
||||
*/
|
||||
#define OS_MBUF_USRHDR_LEN(om) \
|
||||
((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr))
|
||||
|
||||
|
||||
/** @cond INTERNAL_HIDDEN */
|
||||
|
||||
/*
|
||||
* Called by OS_MBUF_LEADINGSPACE() macro
|
||||
*/
|
||||
static inline uint16_t
|
||||
_os_mbuf_leadingspace(struct os_mbuf *om)
|
||||
{
|
||||
uint16_t startoff;
|
||||
uint16_t leadingspace;
|
||||
|
||||
startoff = 0;
|
||||
if (OS_MBUF_IS_PKTHDR(om)) {
|
||||
startoff = om->om_pkthdr_len;
|
||||
}
|
||||
|
||||
leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) -
|
||||
((uint8_t *) &om->om_databuf[0] + startoff));
|
||||
|
||||
return (leadingspace);
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* Returns the leading space (space at the beginning) of the mbuf.
|
||||
* Works on both packet header, and regular mbufs, as it accounts
|
||||
* for the additional space allocated to the packet header.
|
||||
*
|
||||
* @param __omp Is the mbuf pool (which contains packet header length.)
|
||||
* @param __om Is the mbuf in that pool to get the leadingspace for
|
||||
*
|
||||
* @return Amount of leading space available in the mbuf
|
||||
*/
|
||||
#define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om)
|
||||
|
||||
|
||||
/** @cond INTERNAL_HIDDEN */
|
||||
|
||||
/* Called by OS_MBUF_TRAILINGSPACE() macro. */
|
||||
static inline uint16_t
|
||||
_os_mbuf_trailingspace(struct os_mbuf *om)
|
||||
{
|
||||
struct os_mbuf_pool *omp;
|
||||
|
||||
omp = om->om_omp;
|
||||
|
||||
return (&om->om_databuf[0] + omp->omp_databuf_len) -
|
||||
(om->om_data + om->om_len);
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* Returns the trailing space (space at the end) of the mbuf.
|
||||
* Works on both packet header and regular mbufs.
|
||||
*
|
||||
* @param __omp The mbuf pool for this mbuf
|
||||
* @param __om Is the mbuf in that pool to get trailing space for
|
||||
*
|
||||
* @return The amount of trailing space available in the mbuf
|
||||
*/
|
||||
#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
|
||||
|
||||
|
||||
/**
|
||||
* Initializes an mqueue. An mqueue is a queue of mbufs that ties to a
|
||||
* particular task's event queue. Mqueues form a helper API around a common
|
||||
* paradigm: wait on an event queue until at least one packet is available,
|
||||
* then process a queue of packets.
|
||||
*
|
||||
* When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
|
||||
* will be posted to the task's mbuf queue.
|
||||
*
|
||||
* @param mq The mqueue to initialize
|
||||
* @param ev_cb The callback to associate with the mqeueue
|
||||
* event. Typically, this callback pulls each
|
||||
* packet off the mqueue and processes them.
|
||||
* @param arg The argument to associate with the mqueue event.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
|
||||
|
||||
/**
|
||||
* Remove and return a single mbuf from the mbuf queue. Does not block.
|
||||
*
|
||||
* @param mq The mbuf queue to pull an element off of.
|
||||
*
|
||||
* @return The next mbuf in the queue, or NULL if queue has no mbufs.
|
||||
*/
|
||||
struct os_mbuf *os_mqueue_get(struct os_mqueue *);
|
||||
|
||||
/**
|
||||
* Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
|
||||
* with the mqueue gets posted to the specified eventq.
|
||||
*
|
||||
* @param mq The mbuf queue to append the mbuf to.
|
||||
* @param evq The event queue to post an event to.
|
||||
* @param m The mbuf to append to the mbuf queue.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
|
||||
|
||||
/**
|
||||
* MSYS is a system level mbuf registry. Allows the system to share
|
||||
* packet buffers amongst the various networking stacks that can be running
|
||||
* simultaeneously.
|
||||
*
|
||||
* Mbuf pools are created in the system initialization code, and then when
|
||||
* a mbuf is allocated out of msys, it will try and find the best fit based
|
||||
* upon estimated mbuf size.
|
||||
*
|
||||
* os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
|
||||
* allocate mbufs out of it.
|
||||
*
|
||||
* @param new_pool The pool to register with MSYS
|
||||
*
|
||||
* @return 0 on success, non-zero on failure
|
||||
*/
|
||||
int os_msys_register(struct os_mbuf_pool *);
|
||||
|
||||
/**
|
||||
* Allocate a mbuf from msys. Based upon the data size requested,
|
||||
* os_msys_get() will choose the mbuf pool that has the best fit.
|
||||
*
|
||||
* @param dsize The estimated size of the data being stored in the mbuf
|
||||
* @param leadingspace The amount of leadingspace to allocate in the mbuf
|
||||
*
|
||||
* @return A freshly allocated mbuf on success, NULL on failure.
|
||||
*/
|
||||
struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace);
|
||||
|
||||
/**
|
||||
* De-registers all mbuf pools from msys.
|
||||
*/
|
||||
void os_msys_reset(void);
|
||||
|
||||
/**
|
||||
* Allocate a packet header structure from the MSYS pool. See
|
||||
* os_msys_register() for a description of MSYS.
|
||||
*
|
||||
* @param dsize The estimated size of the data being stored in the mbuf
|
||||
* @param user_hdr_len The length to allocate for the packet header structure
|
||||
*
|
||||
* @return A freshly allocated mbuf on success, NULL on failure.
|
||||
*/
|
||||
struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
|
||||
|
||||
/**
|
||||
* Count the number of blocks in all the mbuf pools that are allocated.
|
||||
*
|
||||
* @return total number of blocks allocated in Msys
|
||||
*/
|
||||
int os_msys_count(void);
|
||||
|
||||
/**
|
||||
* Return the number of free blocks in Msys
|
||||
*
|
||||
* @return Number of free blocks available in Msys
|
||||
*/
|
||||
int os_msys_num_free(void);
|
||||
|
||||
/**
|
||||
* Initialize a pool of mbufs.
|
||||
*
|
||||
* @param omp The mbuf pool to initialize
|
||||
* @param mp The memory pool that will hold this mbuf pool
|
||||
* @param buf_len The length of the buffer itself.
|
||||
* @param nbufs The number of buffers in the pool
|
||||
*
|
||||
* @return 0 on success, error code on failure.
|
||||
*/
|
||||
int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
|
||||
uint16_t, uint16_t);
|
||||
|
||||
/**
|
||||
* Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized
|
||||
* prior to being returned.
|
||||
*
|
||||
* @param omp The mbuf pool to return the packet from
|
||||
* @param leadingspace The amount of leadingspace to put before the data
|
||||
* section by default.
|
||||
*
|
||||
* @return An initialized mbuf on success, and NULL on failure.
|
||||
*/
|
||||
struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
|
||||
|
||||
/**
|
||||
* Allocate a new packet header mbuf out of the os_mbuf_pool.
|
||||
*
|
||||
* @param omp The mbuf pool to allocate out of
|
||||
* @param user_pkthdr_len The packet header length to reserve for the caller.
|
||||
*
|
||||
* @return A freshly allocated mbuf on success, NULL on failure.
|
||||
*/
|
||||
struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
|
||||
uint8_t pkthdr_len);
|
||||
|
||||
/**
|
||||
* Duplicate a chain of mbufs. Return the start of the duplicated chain.
|
||||
*
|
||||
* @param omp The mbuf pool to duplicate out of
|
||||
* @param om The mbuf chain to duplicate
|
||||
*
|
||||
* @return A pointer to the new chain of mbufs
|
||||
*/
|
||||
struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
|
||||
|
||||
/**
|
||||
* Locates the specified absolute offset within an mbuf chain. The offset
|
||||
* can be one past than the total length of the chain, but no greater.
|
||||
*
|
||||
* @param om The start of the mbuf chain to seek within.
|
||||
* @param off The absolute address to find.
|
||||
* @param out_off On success, this points to the relative offset
|
||||
* within the returned mbuf.
|
||||
*
|
||||
* @return The mbuf containing the specified offset on
|
||||
* success.
|
||||
* NULL if the specified offset is out of bounds.
|
||||
*/
|
||||
struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
|
||||
uint16_t *out_off);
|
||||
|
||||
|
||||
/*
|
||||
* Copy data from an mbuf chain starting "off" bytes from the beginning,
|
||||
* continuing for "len" bytes, into the indicated buffer.
|
||||
*
|
||||
* @param m The mbuf chain to copy from
|
||||
* @param off The offset into the mbuf chain to begin copying from
|
||||
* @param len The length of the data to copy
|
||||
* @param dst The destination buffer to copy into
|
||||
*
|
||||
* @return 0 on success;
|
||||
* -1 if the mbuf does not contain enough data.
|
||||
*/
|
||||
int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
|
||||
|
||||
/**
|
||||
* Append data onto a mbuf
|
||||
*
|
||||
* @param om The mbuf to append the data onto
|
||||
* @param data The data to append onto the mbuf
|
||||
* @param len The length of the data to append
|
||||
*
|
||||
* @return 0 on success, and an error code on failure
|
||||
*/
|
||||
int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
|
||||
|
||||
/**
|
||||
* Reads data from one mbuf and appends it to another. On error, the specified
|
||||
* data range may be partially appended. Neither mbuf is required to contain
|
||||
* an mbuf packet header.
|
||||
*
|
||||
* @param dst The mbuf to append to.
|
||||
* @param src The mbuf to copy data from.
|
||||
* @param src_off The absolute offset within the source mbuf
|
||||
* chain to read from.
|
||||
* @param len The number of bytes to append.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* OS_EINVAL if the specified range extends beyond
|
||||
* the end of the source mbuf chain.
|
||||
*/
|
||||
int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
|
||||
uint16_t src_off, uint16_t len);
|
||||
|
||||
/**
|
||||
* Release a mbuf back to the pool
|
||||
*
|
||||
* @param omp The Mbuf pool to release back to
|
||||
* @param om The Mbuf to release back to the pool
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int os_mbuf_free(struct os_mbuf *mb);
|
||||
|
||||
/**
|
||||
* Free a chain of mbufs
|
||||
*
|
||||
* @param omp The mbuf pool to free the chain of mbufs into
|
||||
* @param om The starting mbuf of the chain to free back into the pool
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int os_mbuf_free_chain(struct os_mbuf *om);
|
||||
|
||||
/**
|
||||
* Adjust the length of a mbuf, trimming either from the head or the tail
|
||||
* of the mbuf.
|
||||
*
|
||||
* @param mp The mbuf chain to adjust
|
||||
* @param req_len The length to trim from the mbuf. If positive, trims
|
||||
* from the head of the mbuf, if negative, trims from the
|
||||
* tail of the mbuf.
|
||||
*/
|
||||
void os_mbuf_adj(struct os_mbuf *mp, int req_len);
|
||||
|
||||
|
||||
/**
|
||||
* Performs a memory compare of the specified region of an mbuf chain against a
|
||||
* flat buffer.
|
||||
*
|
||||
* @param om The start of the mbuf chain to compare.
|
||||
* @param off The offset within the mbuf chain to start the
|
||||
* comparison.
|
||||
* @param data The flat buffer to compare.
|
||||
* @param len The length of the flat buffer.
|
||||
*
|
||||
* @return 0 if both memory regions are identical;
|
||||
* A memcmp return code if there is a mismatch;
|
||||
* INT_MAX if the mbuf is too short.
|
||||
*/
|
||||
int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
|
||||
|
||||
/**
|
||||
* Compares the contents of two mbuf chains. The ranges of the two chains to
|
||||
* be compared are specified via the two offset parameters and the len
|
||||
* parameter. Neither mbuf chain is required to contain a packet header.
|
||||
*
|
||||
* @param om1 The first mbuf chain to compare.
|
||||
* @param offset1 The absolute offset within om1 at which to
|
||||
* start the comparison.
|
||||
* @param om2 The second mbuf chain to compare.
|
||||
* @param offset2 The absolute offset within om2 at which to
|
||||
* start the comparison.
|
||||
* @param len The number of bytes to compare.
|
||||
*
|
||||
* @return 0 if both mbuf segments are identical;
|
||||
* A memcmp() return code if the segment contents
|
||||
* differ;
|
||||
* INT_MAX if a specified range extends beyond the
|
||||
* end of its corresponding mbuf chain.
|
||||
*/
|
||||
int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
|
||||
const struct os_mbuf *om2, uint16_t offset2,
|
||||
uint16_t len);
|
||||
|
||||
/**
|
||||
* Increases the length of an mbuf chain by adding data to the front. If there
|
||||
* is insufficient room in the leading mbuf, additional mbufs are allocated and
|
||||
* prepended as necessary. If this function fails to allocate an mbuf, the
|
||||
* entire chain is freed.
|
||||
*
|
||||
* The specified mbuf chain does not need to contain a packet header.
|
||||
*
|
||||
* @param omp The mbuf pool to allocate from.
|
||||
* @param om The head of the mbuf chain.
|
||||
* @param len The number of bytes to prepend.
|
||||
*
|
||||
* @return The new head of the chain on success;
|
||||
* NULL on failure.
|
||||
*/
|
||||
struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
|
||||
|
||||
/**
|
||||
* Prepends a chunk of empty data to the specified mbuf chain and ensures the
|
||||
* chunk is contiguous. If either operation fails, the specified mbuf chain is
|
||||
* freed and NULL is returned.
|
||||
*
|
||||
* @param om The mbuf chain to prepend to.
|
||||
* @param len The number of bytes to prepend and pullup.
|
||||
*
|
||||
* @return The modified mbuf on success;
|
||||
* NULL on failure (and the mbuf chain is freed).
|
||||
*/
|
||||
struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
|
||||
|
||||
/**
|
||||
* Copies the contents of a flat buffer into an mbuf chain, starting at the
|
||||
* specified destination offset. If the mbuf is too small for the source data,
|
||||
* it is extended as necessary. If the destination mbuf contains a packet
|
||||
* header, the header length is updated.
|
||||
*
|
||||
* @param omp The mbuf pool to allocate from.
|
||||
* @param om The mbuf chain to copy into.
|
||||
* @param off The offset within the chain to copy to.
|
||||
* @param src The source buffer to copy from.
|
||||
* @param len The number of bytes to copy.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
|
||||
|
||||
/**
|
||||
* Attaches a second mbuf chain onto the end of the first. If the first chain
|
||||
* contains a packet header, the header's length is updated. If the second
|
||||
* chain has a packet header, its header is cleared.
|
||||
*
|
||||
* @param first The mbuf chain being attached to.
|
||||
* @param second The mbuf chain that gets attached.
|
||||
*/
|
||||
void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
|
||||
|
||||
|
||||
/**
|
||||
* Increases the length of an mbuf chain by the specified amount. If there is
|
||||
* not sufficient room in the last buffer, a new buffer is allocated and
|
||||
* appended to the chain. It is an error to request more data than can fit in
|
||||
* a single buffer.
|
||||
*
|
||||
* @param omp
|
||||
* @param om The head of the chain to extend.
|
||||
* @param len The number of bytes to extend by.
|
||||
*
|
||||
* @return A pointer to the new data on success;
|
||||
* NULL on failure.
|
||||
*/
|
||||
void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
|
||||
|
||||
/**
|
||||
* Rearrange a mbuf chain so that len bytes are contiguous,
|
||||
* and in the data area of an mbuf (so that OS_MBUF_DATA() will
|
||||
* work on a structure of size len.) Returns the resulting
|
||||
* mbuf chain on success, free's it and returns NULL on failure.
|
||||
*
|
||||
* If there is room, it will add up to "max_protohdr - len"
|
||||
* extra bytes to the contiguous region, in an attempt to avoid being
|
||||
* called next time.
|
||||
*
|
||||
* @param omp The mbuf pool to take the mbufs out of
|
||||
* @param om The mbuf chain to make contiguous
|
||||
* @param len The number of bytes in the chain to make contiguous
|
||||
*
|
||||
* @return The contiguous mbuf chain on success, NULL on failure.
|
||||
*/
|
||||
struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
|
||||
|
||||
|
||||
/**
|
||||
* Removes and frees empty mbufs from the front of a chain. If the chain
|
||||
* contains a packet header, it is preserved.
|
||||
*
|
||||
* @param om The mbuf chain to trim.
|
||||
*
|
||||
* @return The head of the trimmed mbuf chain.
|
||||
*/
|
||||
struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OS_MBUF_H */
|
||||
|
||||
|
||||
/**
|
||||
* @} OSMbuf
|
||||
* @} OSKernel
|
||||
*/
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup OSKernel
|
||||
* @{
|
||||
* @defgroup OSMempool Memory Pools
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _OS_MEMPOOL_H_
|
||||
#define _OS_MEMPOOL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "os/os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A memory block structure. This simply contains a pointer to the free list
|
||||
* chain and is only used when the block is on the free list. When the block
|
||||
* has been removed from the free list the entire memory block is usable by the
|
||||
* caller.
|
||||
*/
|
||||
struct os_memblock {
|
||||
SLIST_ENTRY(os_memblock) mb_next;
|
||||
};
|
||||
|
||||
/* XXX: Change this structure so that we keep the first address in the pool? */
|
||||
/* XXX: add memory debug structure and associated code */
|
||||
/* XXX: Change how I coded the SLIST_HEAD here. It should be named:
|
||||
SLIST_HEAD(,os_memblock) mp_head; */
|
||||
|
||||
/**
|
||||
* Memory pool
|
||||
*/
|
||||
struct os_mempool {
|
||||
/** Size of the memory blocks, in bytes. */
|
||||
uint32_t mp_block_size;
|
||||
/** The number of memory blocks. */
|
||||
uint16_t mp_num_blocks;
|
||||
/** The number of free blocks left */
|
||||
uint16_t mp_num_free;
|
||||
/** The lowest number of free blocks seen */
|
||||
uint16_t mp_min_free;
|
||||
/** Bitmap of OS_MEMPOOL_F_[...] values. */
|
||||
uint8_t mp_flags;
|
||||
/** Address of memory buffer used by pool */
|
||||
uint32_t mp_membuf_addr;
|
||||
STAILQ_ENTRY(os_mempool) mp_list;
|
||||
SLIST_HEAD(,os_memblock);
|
||||
/** Name for memory block */
|
||||
char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates an extended mempool. Address can be safely cast to
|
||||
* (struct os_mempool_ext *).
|
||||
*/
|
||||
#define OS_MEMPOOL_F_EXT 0x01
|
||||
|
||||
struct os_mempool_ext;
|
||||
|
||||
/**
|
||||
* Block put callback function. If configured, this callback gets executed
|
||||
* whenever a block is freed to the corresponding extended mempool. Note: The
|
||||
* os_memblock_put() function calls this callback instead of freeing the block
|
||||
* itself. Therefore, it is the callback's responsibility to free the block
|
||||
* via a call to os_memblock_put_from_cb().
|
||||
*
|
||||
* @param ome The extended mempool that a block is being
|
||||
* freed back to.
|
||||
* @param data The block being freed.
|
||||
* @param arg Optional argument configured along with the
|
||||
* callback.
|
||||
*
|
||||
* @return Indicates whether the block was successfully
|
||||
* freed. A non-zero value should only be
|
||||
* returned if the block was not successfully
|
||||
* released back to its pool.
|
||||
*/
|
||||
typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data,
|
||||
void *arg);
|
||||
|
||||
struct os_mempool_ext {
|
||||
struct os_mempool mpe_mp;
|
||||
|
||||
/* Callback that is executed immediately when a block is freed. */
|
||||
os_mempool_put_fn *mpe_put_cb;
|
||||
void *mpe_put_arg;
|
||||
};
|
||||
|
||||
#define OS_MEMPOOL_INFO_NAME_LEN (32)
|
||||
|
||||
/**
|
||||
* Information describing a memory pool, used to return OS information
|
||||
* to the management layer.
|
||||
*/
|
||||
struct os_mempool_info {
|
||||
/** Size of the memory blocks in the pool */
|
||||
int omi_block_size;
|
||||
/** Number of memory blocks in the pool */
|
||||
int omi_num_blocks;
|
||||
/** Number of free memory blocks */
|
||||
int omi_num_free;
|
||||
/** Minimum number of free memory blocks ever */
|
||||
int omi_min_free;
|
||||
/** Name of the memory pool */
|
||||
char omi_name[OS_MEMPOOL_INFO_NAME_LEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get information about the next system memory pool.
|
||||
*
|
||||
* @param mempool The current memory pool, or NULL if starting iteration.
|
||||
* @param info A pointer to the structure to return memory pool information
|
||||
* into.
|
||||
*
|
||||
* @return The next memory pool in the list to get information about, or NULL
|
||||
* when at the last memory pool.
|
||||
*/
|
||||
struct os_mempool *os_mempool_info_get_next(struct os_mempool *,
|
||||
struct os_mempool_info *);
|
||||
|
||||
/*
|
||||
* To calculate size of the memory buffer needed for the pool. NOTE: This size
|
||||
* is NOT in bytes! The size is the number of os_membuf_t elements required for
|
||||
* the memory pool.
|
||||
*/
|
||||
#if (OS_CFG_ALIGNMENT == OS_CFG_ALIGN_4)
|
||||
#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + 3) / 4) * (n))
|
||||
typedef uint32_t os_membuf_t;
|
||||
#else
|
||||
#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + 7) / 8) * (n))
|
||||
typedef uint64_t os_membuf_t;
|
||||
#endif
|
||||
|
||||
/** Calculates the number of bytes required to initialize a memory pool. */
|
||||
#define OS_MEMPOOL_BYTES(n,blksize) \
|
||||
(sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
|
||||
|
||||
/**
|
||||
* Initialize a memory pool.
|
||||
*
|
||||
* @param mp Pointer to a pointer to a mempool
|
||||
* @param blocks The number of blocks in the pool
|
||||
* @param blocks_size The size of the block, in bytes.
|
||||
* @param membuf Pointer to memory to contain blocks.
|
||||
* @param name Name of the pool.
|
||||
*
|
||||
* @return os_error_t
|
||||
*/
|
||||
os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks,
|
||||
uint32_t block_size, void *membuf, char *name);
|
||||
|
||||
/**
|
||||
* Initializes an extended memory pool. Extended attributes (e.g., callbacks)
|
||||
* are not specified when this function is called; they are assigned manually
|
||||
* after initialization.
|
||||
*
|
||||
* @param mpe The extended memory pool to initialize.
|
||||
* @param blocks The number of blocks in the pool.
|
||||
* @param block_size The size of each block, in bytes.
|
||||
* @param membuf Pointer to memory to contain blocks.
|
||||
* @param name Name of the pool.
|
||||
*
|
||||
* @return os_error_t
|
||||
*/
|
||||
os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
|
||||
uint32_t block_size, void *membuf, char *name);
|
||||
|
||||
/**
|
||||
* Performs an integrity check of the specified mempool. This function
|
||||
* attempts to detect memory corruption in the specified memory pool.
|
||||
*
|
||||
* @param mp The mempool to check.
|
||||
*
|
||||
* @return true if the memory pool passes the integrity
|
||||
* check;
|
||||
* false if the memory pool is corrupt.
|
||||
*/
|
||||
bool os_mempool_is_sane(const struct os_mempool *mp);
|
||||
|
||||
/**
|
||||
* Checks if a memory block was allocated from the specified mempool.
|
||||
*
|
||||
* @param mp The mempool to check as parent.
|
||||
* @param block_addr The memory block to check as child.
|
||||
*
|
||||
* @return 0 if the block does not belong to the mempool;
|
||||
* 1 if the block does belong to the mempool.
|
||||
*/
|
||||
int os_memblock_from(const struct os_mempool *mp, const void *block_addr);
|
||||
|
||||
/**
|
||||
* Get a memory block from a memory pool
|
||||
*
|
||||
* @param mp Pointer to the memory pool
|
||||
*
|
||||
* @return void* Pointer to block if available; NULL otherwise
|
||||
*/
|
||||
void *os_memblock_get(struct os_mempool *mp);
|
||||
|
||||
/**
|
||||
* Puts the memory block back into the pool, ignoring the put callback, if any.
|
||||
* This function should only be called from a put callback to free a block
|
||||
* without causing infinite recursion.
|
||||
*
|
||||
* @param mp Pointer to memory pool
|
||||
* @param block_addr Pointer to memory block
|
||||
*
|
||||
* @return os_error_t
|
||||
*/
|
||||
os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
|
||||
|
||||
/**
|
||||
* Puts the memory block back into the pool
|
||||
*
|
||||
* @param mp Pointer to memory pool
|
||||
* @param block_addr Pointer to memory block
|
||||
*
|
||||
* @return os_error_t
|
||||
*/
|
||||
os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OS_MEMPOOL_H_ */
|
||||
|
||||
|
||||
/**
|
||||
* @} OSMempool
|
||||
* @} OSKernel
|
||||
*/
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef OS_TRACE_API_H
|
||||
#define OS_TRACE_API_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define OS_TRACE_ID_OFFSET (32u)
|
||||
|
||||
#define OS_TRACE_ID_EVQ_PUT (1u + OS_TRACE_ID_OFFSET)
|
||||
#define OS_TRACE_ID_EVQ_GET (2u + OS_TRACE_ID_OFFSET)
|
||||
#define OS_TRACE_ID_MUTEX_INIT (3u + OS_TRACE_ID_OFFSET)
|
||||
#define OS_TRACE_ID_MUTEX_RELEASE (4u + OS_TRACE_ID_OFFSET)
|
||||
#define OS_TRACE_ID_MUTEX_PEND (5u + OS_TRACE_ID_OFFSET)
|
||||
|
||||
static inline void os_trace_enter_isr(void){}
|
||||
static inline void os_trace_exit_isr(void){}
|
||||
static inline void os_trace_exit_isr_to_scheduler(void){}
|
||||
static inline void os_trace_task_info(const void *p_task){}
|
||||
static inline void os_trace_task_create(uint32_t task_id){}
|
||||
static inline void os_trace_task_start_exec(uint32_t task_id){}
|
||||
static inline void os_trace_task_stop_exec(void){}
|
||||
static inline void os_trace_task_start_ready(uint32_t task_id){}
|
||||
static inline void os_trace_task_stop_ready(uint32_t task_id, unsigned reason){}
|
||||
static inline void os_trace_idle(void){}
|
||||
static inline void os_trace_void(unsigned id){}
|
||||
static inline void os_trace_u32(unsigned id, uint32_t para0){}
|
||||
static inline void os_trace_u32x2(unsigned id, uint32_t para0, uint32_t para1){}
|
||||
static inline void os_trace_u32x3(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2){}
|
||||
static inline void os_trace_u32x4(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3){}
|
||||
static inline void os_trace_u32x5(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3, uint32_t para4){}
|
||||
static inline void os_trace_enter_timer(uint32_t timer_id){}
|
||||
static inline void os_trace_exit_timer(void){}
|
||||
static inline void os_trace_end_call(unsigned id){}
|
||||
static inline void os_trace_end_call_return_value(unsigned id, uint32_t return_value){}
|
||||
|
||||
#endif
|
||||
Executable
+522
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $FreeBSD: src/sys/sys/queue.h,v 1.32.2.7 2002/04/17 14:21:02 des Exp $
|
||||
*/
|
||||
|
||||
#ifndef _QUEUE_H_
|
||||
#define _QUEUE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file defines five types of data structures: singly-linked lists,
|
||||
* singly-linked tail queues, lists, tail queues, and circular queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||
* head of the list and the other to the tail of the list. The elements are
|
||||
* singly linked for minimum space and pointer manipulation overhead at the
|
||||
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||
* to the list after an existing element, at the head of the list, or at the
|
||||
* end of the list. Elements being removed from the head of the tail queue
|
||||
* should use the explicit macro for this purpose for optimum efficiency.
|
||||
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||
* Singly-linked tail queues are ideal for applications with large datasets
|
||||
* and few or no removals or for implementing a FIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the list.
|
||||
* A circle queue may be traversed in either direction, but has a more
|
||||
* complex end of list detection.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*
|
||||
*
|
||||
* SLIST LIST STAILQ TAILQ CIRCLEQ
|
||||
* _HEAD + + + + +
|
||||
* _HEAD_INITIALIZER + + + + +
|
||||
* _ENTRY + + + + +
|
||||
* _INIT + + + + +
|
||||
* _EMPTY + + + + +
|
||||
* _FIRST + + + + +
|
||||
* _NEXT + + + + +
|
||||
* _PREV - - - + +
|
||||
* _LAST - - + + +
|
||||
* _FOREACH + + + + +
|
||||
* _FOREACH_REVERSE - - - + +
|
||||
* _INSERT_HEAD + + + + +
|
||||
* _INSERT_BEFORE - + - + +
|
||||
* _INSERT_AFTER + + + + +
|
||||
* _INSERT_TAIL - - + + +
|
||||
* _REMOVE_HEAD + - + - -
|
||||
* _REMOVE + + + + +
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_INIT(head) do { \
|
||||
SLIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||
SLIST_NEXT((slistelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||
SLIST_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_NEXT(curelm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first;/* first element */ \
|
||||
struct type **stqh_last;/* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head, type, field) \
|
||||
(STAILQ_EMPTY(head) ? \
|
||||
NULL : \
|
||||
((struct type *) \
|
||||
((char *)((head)->stqh_last) - offsetof(struct type, field))))
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD(head, field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
if ((STAILQ_NEXT(curelm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT(elm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
|
||||
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
LIST_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
|
||||
LIST_FIRST((head)) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue declarations.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
TAILQ_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
|
||||
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_FIRST((head)) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
TAILQ_NEXT((elm), field) = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Circular queue declarations.
|
||||
*/
|
||||
#define CIRCLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *cqh_first; /* first element */ \
|
||||
struct type *cqh_last; /* last element */ \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_HEAD_INITIALIZER(head) \
|
||||
{ (void *)&(head), (void *)&(head) }
|
||||
|
||||
#define CIRCLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *cqe_next; /* next element */ \
|
||||
struct type *cqe_prev; /* previous element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue functions.
|
||||
*/
|
||||
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
|
||||
|
||||
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
||||
|
||||
#define CIRCLEQ_FOREACH(var, head, field) \
|
||||
for ((var) = CIRCLEQ_FIRST((head)); \
|
||||
(var) != (void *)(head) || ((var) = NULL); \
|
||||
(var) = CIRCLEQ_NEXT((var), field))
|
||||
|
||||
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
|
||||
for ((var) = CIRCLEQ_LAST((head)); \
|
||||
(var) != (void *)(head) || ((var) = NULL); \
|
||||
(var) = CIRCLEQ_PREV((var), field))
|
||||
|
||||
#define CIRCLEQ_INIT(head) do { \
|
||||
CIRCLEQ_FIRST((head)) = (void *)(head); \
|
||||
CIRCLEQ_LAST((head)) = (void *)(head); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
|
||||
CIRCLEQ_PREV((elm), field) = (listelm); \
|
||||
if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
|
||||
CIRCLEQ_NEXT((listelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = (listelm); \
|
||||
CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
|
||||
if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
|
||||
CIRCLEQ_PREV((listelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
|
||||
CIRCLEQ_PREV((elm), field) = (void *)(head); \
|
||||
if (CIRCLEQ_LAST((head)) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = (void *)(head); \
|
||||
CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
|
||||
if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
||||
|
||||
#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
|
||||
|
||||
#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
|
||||
|
||||
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
||||
if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
|
||||
CIRCLEQ_PREV((elm), field); \
|
||||
if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
|
||||
CIRCLEQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_QUEUE_H_ */
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef __STATS_H__
|
||||
#define __STATS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define STATS_SECT_DECL(__name) struct stats_ ## __name
|
||||
#define STATS_SECT_END };
|
||||
|
||||
#define STATS_SECT_START(__name) STATS_SECT_DECL(__name) {
|
||||
#define STATS_SECT_VAR(__var)
|
||||
|
||||
#define STATS_HDR(__sectname) NULL
|
||||
|
||||
#define STATS_SECT_ENTRY(__var)
|
||||
#define STATS_SECT_ENTRY16(__var)
|
||||
#define STATS_SECT_ENTRY32(__var)
|
||||
#define STATS_SECT_ENTRY64(__var)
|
||||
#define STATS_RESET(__var)
|
||||
|
||||
#define STATS_SIZE_INIT_PARMS(__sectvarname, __size) \
|
||||
0, 0
|
||||
|
||||
#define STATS_INC(__sectvarname, __var)
|
||||
#define STATS_INCN(__sectvarname, __var, __n)
|
||||
#define STATS_CLEAR(__sectvarname, __var)
|
||||
|
||||
#define STATS_NAME_START(__name)
|
||||
#define STATS_NAME(__name, __entry)
|
||||
#define STATS_NAME_END(__name)
|
||||
#define STATS_NAME_INIT_PARMS(__name) NULL, 0
|
||||
|
||||
static inline int
|
||||
stats_init(void *a, uint8_t b, uint8_t c, void *d, uint8_t e)
|
||||
{
|
||||
/* dummy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
stats_register(void *a, void *b)
|
||||
{
|
||||
/* dummy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
stats_init_and_reg(void *a, uint8_t b, uint8_t c, void *d, uint8_t e, void *f)
|
||||
{
|
||||
/* dummy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STATS_H__ */
|
||||
@@ -0,0 +1,886 @@
|
||||
/**
|
||||
* This file was generated by Apache Newt version: 1.4.0-dev
|
||||
*/
|
||||
|
||||
#ifndef H_MYNEWT_SYSCFG_
|
||||
#define H_MYNEWT_SYSCFG_
|
||||
|
||||
/**
|
||||
* This macro exists to ensure code includes this header when needed. If code
|
||||
* checks the existence of a setting directly via ifdef without including this
|
||||
* header, the setting macro will silently evaluate to 0. In contrast, an
|
||||
* attempt to use these macros without including this header will result in a
|
||||
* compiler error.
|
||||
*/
|
||||
#define MYNEWT_VAL(x) MYNEWT_VAL_ ## x
|
||||
|
||||
|
||||
|
||||
/*** compiler/arm-none-eabi-m4 */
|
||||
#ifndef MYNEWT_VAL_HARDFLOAT
|
||||
#define MYNEWT_VAL_HARDFLOAT (0)
|
||||
#endif
|
||||
|
||||
/*** hw/bsp/nrf52840pdk */
|
||||
#ifndef MYNEWT_VAL_BSP_NRF52840
|
||||
#define MYNEWT_VAL_BSP_NRF52840 (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_I2C_0_FREQ_KHZ
|
||||
#define MYNEWT_VAL_I2C_0_FREQ_KHZ (100)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_I2C_0_PIN_SCL
|
||||
#define MYNEWT_VAL_I2C_0_PIN_SCL (27)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_I2C_0_PIN_SDA
|
||||
#define MYNEWT_VAL_I2C_0_PIN_SDA (26)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_PWM_3
|
||||
#define MYNEWT_VAL_PWM_3 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_MASTER_PIN_MISO
|
||||
#define MYNEWT_VAL_SPI_0_MASTER_PIN_MISO (47)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_MASTER_PIN_MOSI
|
||||
#define MYNEWT_VAL_SPI_0_MASTER_PIN_MOSI (46)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_MASTER_PIN_SCK
|
||||
#define MYNEWT_VAL_SPI_0_MASTER_PIN_SCK (45)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_SLAVE_PIN_MISO
|
||||
#define MYNEWT_VAL_SPI_0_SLAVE_PIN_MISO (47)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_SLAVE_PIN_MOSI
|
||||
#define MYNEWT_VAL_SPI_0_SLAVE_PIN_MOSI (46)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_SLAVE_PIN_SCK
|
||||
#define MYNEWT_VAL_SPI_0_SLAVE_PIN_SCK (45)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_SLAVE_PIN_SS
|
||||
#define MYNEWT_VAL_SPI_0_SLAVE_PIN_SS (44)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_TIMER_0
|
||||
#define MYNEWT_VAL_TIMER_0 (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_TIMER_1
|
||||
#define MYNEWT_VAL_TIMER_1 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_TIMER_2
|
||||
#define MYNEWT_VAL_TIMER_2 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_TIMER_3
|
||||
#define MYNEWT_VAL_TIMER_3 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_TIMER_4
|
||||
#define MYNEWT_VAL_TIMER_4 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_TIMER_5
|
||||
#define MYNEWT_VAL_TIMER_5 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_0
|
||||
#define MYNEWT_VAL_UART_0 (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_0_PIN_CTS
|
||||
#define MYNEWT_VAL_UART_0_PIN_CTS (7)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_0_PIN_RTS
|
||||
#define MYNEWT_VAL_UART_0_PIN_RTS (5)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_0_PIN_RX
|
||||
#define MYNEWT_VAL_UART_0_PIN_RX (8)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_0_PIN_TX
|
||||
#define MYNEWT_VAL_UART_0_PIN_TX (6)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_1
|
||||
#define MYNEWT_VAL_UART_1 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_1_PIN_CTS
|
||||
#define MYNEWT_VAL_UART_1_PIN_CTS (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_1_PIN_RTS
|
||||
#define MYNEWT_VAL_UART_1_PIN_RTS (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_1_PIN_RX
|
||||
#define MYNEWT_VAL_UART_1_PIN_RX (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_UART_1_PIN_TX
|
||||
#define MYNEWT_VAL_UART_1_PIN_TX (-1)
|
||||
#endif
|
||||
|
||||
/*** hw/mcu/nordic/nrf52xxx */
|
||||
#ifndef MYNEWT_VAL_ADC_0
|
||||
#define MYNEWT_VAL_ADC_0 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_ADC_0_REFMV_0
|
||||
#define MYNEWT_VAL_ADC_0_REFMV_0 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_I2C_0
|
||||
#define MYNEWT_VAL_I2C_0 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_I2C_1
|
||||
#define MYNEWT_VAL_I2C_1 (0)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_MCU_DCDC_ENABLED
|
||||
#define MYNEWT_VAL_MCU_DCDC_ENABLED (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE
|
||||
#define MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_PWM_0
|
||||
#define MYNEWT_VAL_PWM_0 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_PWM_1
|
||||
#define MYNEWT_VAL_PWM_1 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_PWM_2
|
||||
#define MYNEWT_VAL_PWM_2 (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_QSPI_ADDRMODE
|
||||
#define MYNEWT_VAL_QSPI_ADDRMODE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_QSPI_DPMCONFIG
|
||||
#define MYNEWT_VAL_QSPI_DPMCONFIG (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_QSPI_ENABLE
|
||||
#define MYNEWT_VAL_QSPI_ENABLE (0)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_FLASH_PAGE_SIZE
|
||||
#define MYNEWT_VAL_QSPI_FLASH_PAGE_SIZE (256)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_FLASH_SECTOR_COUNT
|
||||
#define MYNEWT_VAL_QSPI_FLASH_SECTOR_COUNT (4096)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_FLASH_SECTOR_SIZE
|
||||
#define MYNEWT_VAL_QSPI_FLASH_SECTOR_SIZE (4096)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_PIN_CS
|
||||
#define MYNEWT_VAL_QSPI_PIN_CS (17)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_PIN_DIO0
|
||||
#define MYNEWT_VAL_QSPI_PIN_DIO0 (20)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_PIN_DIO1
|
||||
#define MYNEWT_VAL_QSPI_PIN_DIO1 (21)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_PIN_DIO2
|
||||
#define MYNEWT_VAL_QSPI_PIN_DIO2 (22)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_PIN_DIO3
|
||||
#define MYNEWT_VAL_QSPI_PIN_DIO3 (23)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_QSPI_PIN_SCK
|
||||
#define MYNEWT_VAL_QSPI_PIN_SCK (19)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_QSPI_READOC
|
||||
#define MYNEWT_VAL_QSPI_READOC (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_QSPI_SCK_DELAY
|
||||
#define MYNEWT_VAL_QSPI_SCK_DELAY (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_QSPI_SCK_FREQ
|
||||
#define MYNEWT_VAL_QSPI_SCK_FREQ (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_QSPI_SPI_MODE
|
||||
#define MYNEWT_VAL_QSPI_SPI_MODE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_QSPI_WRITEOC
|
||||
#define MYNEWT_VAL_QSPI_WRITEOC (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SOFT_PWM
|
||||
#define MYNEWT_VAL_SOFT_PWM (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_MASTER
|
||||
#define MYNEWT_VAL_SPI_0_MASTER (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_0_SLAVE
|
||||
#define MYNEWT_VAL_SPI_0_SLAVE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_1_MASTER
|
||||
#define MYNEWT_VAL_SPI_1_MASTER (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_1_SLAVE
|
||||
#define MYNEWT_VAL_SPI_1_SLAVE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_2_MASTER
|
||||
#define MYNEWT_VAL_SPI_2_MASTER (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SPI_2_SLAVE
|
||||
#define MYNEWT_VAL_SPI_2_SLAVE (0)
|
||||
#endif
|
||||
|
||||
/* Overridden by hw/bsp/nrf52840pdk (defined by hw/mcu/nordic/nrf52xxx) */
|
||||
#ifndef MYNEWT_VAL_XTAL_32768
|
||||
#define MYNEWT_VAL_XTAL_32768 (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_XTAL_32768_SYNTH
|
||||
#define MYNEWT_VAL_XTAL_32768_SYNTH (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_XTAL_RC
|
||||
#define MYNEWT_VAL_XTAL_RC (0)
|
||||
#endif
|
||||
|
||||
/*** kernel/os */
|
||||
#ifndef MYNEWT_VAL_FLOAT_USER
|
||||
#define MYNEWT_VAL_FLOAT_USER (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT
|
||||
#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE
|
||||
#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_MSYS_2_BLOCK_COUNT
|
||||
#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_MSYS_2_BLOCK_SIZE
|
||||
#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_CLI
|
||||
#define MYNEWT_VAL_OS_CLI (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_COREDUMP
|
||||
#define MYNEWT_VAL_OS_COREDUMP (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_CPUTIME_FREQ
|
||||
#define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_CPUTIME_TIMER_NUM
|
||||
#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_CTX_SW_STACK_CHECK
|
||||
#define MYNEWT_VAL_OS_CTX_SW_STACK_CHECK (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_CTX_SW_STACK_GUARD
|
||||
#define MYNEWT_VAL_OS_CTX_SW_STACK_GUARD (4)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_MAIN_STACK_SIZE
|
||||
#define MYNEWT_VAL_OS_MAIN_STACK_SIZE (1024)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_MAIN_TASK_PRIO
|
||||
#define MYNEWT_VAL_OS_MAIN_TASK_PRIO (127)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_MEMPOOL_CHECK
|
||||
#define MYNEWT_VAL_OS_MEMPOOL_CHECK (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_MEMPOOL_POISON
|
||||
#define MYNEWT_VAL_OS_MEMPOOL_POISON (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_SCHEDULING
|
||||
#define MYNEWT_VAL_OS_SCHEDULING (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_OS_SYSVIEW
|
||||
#define MYNEWT_VAL_OS_SYSVIEW (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SANITY_INTERVAL
|
||||
#define MYNEWT_VAL_SANITY_INTERVAL (15000)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_WATCHDOG_INTERVAL
|
||||
#define MYNEWT_VAL_WATCHDOG_INTERVAL (30000)
|
||||
#endif
|
||||
|
||||
/*** libc/baselibc */
|
||||
#ifndef MYNEWT_VAL_BASELIBC_ASSERT_FILE_LINE
|
||||
#define MYNEWT_VAL_BASELIBC_ASSERT_FILE_LINE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BASELIBC_PRESENT
|
||||
#define MYNEWT_VAL_BASELIBC_PRESENT (1)
|
||||
#endif
|
||||
|
||||
/*** nimble */
|
||||
#ifndef MYNEWT_VAL_BLE_EXT_ADV
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE
|
||||
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
|
||||
#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES
|
||||
#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER
|
||||
#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ROLE_CENTRAL
|
||||
#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ROLE_OBSERVER
|
||||
#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ROLE_PERIPHERAL
|
||||
#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_WHITELIST
|
||||
#define MYNEWT_VAL_BLE_WHITELIST (1)
|
||||
#endif
|
||||
|
||||
/*** nimble/host */
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU
|
||||
#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_INDICATE
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_READ (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_MULT
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP
|
||||
#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS
|
||||
#define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS
|
||||
#define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS
|
||||
#define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID
|
||||
#define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID
|
||||
#define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS
|
||||
#define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_INDICATE
|
||||
#define MYNEWT_VAL_BLE_GATT_INDICATE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_MAX_PROCS
|
||||
#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY
|
||||
#define MYNEWT_VAL_BLE_GATT_NOTIFY (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_READ
|
||||
#define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_READ_LONG
|
||||
#define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS
|
||||
#define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT
|
||||
#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID
|
||||
#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_RESUME_RATE
|
||||
#define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_SIGNED_WRITE
|
||||
#define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_WRITE
|
||||
#define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_WRITE_LONG
|
||||
#define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS
|
||||
#define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP
|
||||
#define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE
|
||||
#define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HOST
|
||||
#define MYNEWT_VAL_BLE_HOST (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_DEBUG
|
||||
#define MYNEWT_VAL_BLE_HS_DEBUG (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL
|
||||
#define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL
|
||||
#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH
|
||||
#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT
|
||||
#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS
|
||||
#define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_REQUIRE_OS
|
||||
#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM
|
||||
#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS
|
||||
#define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_L2CAP_MAX_CHANS
|
||||
#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT
|
||||
#define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS
|
||||
#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MESH
|
||||
#define MYNEWT_VAL_BLE_MESH (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE
|
||||
#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_RTT
|
||||
#define MYNEWT_VAL_BLE_MONITOR_RTT (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED
|
||||
#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME
|
||||
#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("monitor")
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE
|
||||
#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_UART
|
||||
#define MYNEWT_VAL_BLE_MONITOR_UART (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE
|
||||
#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE
|
||||
#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_MONITOR_UART_DEV
|
||||
#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0")
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT
|
||||
#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_BONDING
|
||||
#define MYNEWT_VAL_BLE_SM_BONDING (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_IO_CAP
|
||||
#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_KEYPRESS
|
||||
#define MYNEWT_VAL_BLE_SM_KEYPRESS (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_LEGACY
|
||||
#define MYNEWT_VAL_BLE_SM_LEGACY (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS
|
||||
#define MYNEWT_VAL_BLE_SM_MAX_PROCS (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_MITM
|
||||
#define MYNEWT_VAL_BLE_SM_MITM (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG
|
||||
#define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST
|
||||
#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_SC
|
||||
#define MYNEWT_VAL_BLE_SM_SC (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST
|
||||
#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_STORE_MAX_CCCDS
|
||||
#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
|
||||
#endif
|
||||
|
||||
/*** nimble/host/services/ans */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT
|
||||
#define MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT (0)
|
||||
#endif
|
||||
|
||||
/*** nimble/host/services/bas */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE
|
||||
#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM (0)
|
||||
#endif
|
||||
|
||||
/*** nimble/host/services/gap */
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("nimble")
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH (31)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO
|
||||
#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0)
|
||||
#endif
|
||||
|
||||
/*** nimble/transport */
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_EMSPI
|
||||
#define MYNEWT_VAL_BLE_HCI_TRANSPORT_EMSPI (0)
|
||||
#endif
|
||||
|
||||
/* Overridden by targets/porting-nimble (defined by nimble/transport) */
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_NIMBLE_BUILTIN
|
||||
#define MYNEWT_VAL_BLE_HCI_TRANSPORT_NIMBLE_BUILTIN (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_RAM
|
||||
#define MYNEWT_VAL_BLE_HCI_TRANSPORT_RAM (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET
|
||||
#define MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET (0)
|
||||
#endif
|
||||
|
||||
/* Overridden by targets/porting-nimble (defined by nimble/transport) */
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_UART
|
||||
#define MYNEWT_VAL_BLE_HCI_TRANSPORT_UART (1)
|
||||
#endif
|
||||
|
||||
/*** nimble/transport/uart */
|
||||
#ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT
|
||||
#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (12)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE
|
||||
#define MYNEWT_VAL_BLE_ACL_BUF_SIZE (255)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT
|
||||
#define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (12)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE
|
||||
#define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE (70)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT
|
||||
#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (8)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT
|
||||
#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (8)
|
||||
#endif
|
||||
|
||||
/* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_UART_BAUD
|
||||
#define MYNEWT_VAL_BLE_HCI_UART_BAUD (115200)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_UART_DATA_BITS
|
||||
#define MYNEWT_VAL_BLE_HCI_UART_DATA_BITS (8)
|
||||
#endif
|
||||
|
||||
/* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL
|
||||
#define MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_UART_PARITY
|
||||
#define MYNEWT_VAL_BLE_HCI_UART_PARITY (HAL_UART_PARITY_NONE)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_UART_PORT
|
||||
#define MYNEWT_VAL_BLE_HCI_UART_PORT (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HCI_UART_STOP_BITS
|
||||
#define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1)
|
||||
#endif
|
||||
|
||||
/*** sys/console/stub */
|
||||
#ifndef MYNEWT_VAL_CONSOLE_UART_BAUD
|
||||
#define MYNEWT_VAL_CONSOLE_UART_BAUD (115200)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_CONSOLE_UART_DEV
|
||||
#define MYNEWT_VAL_CONSOLE_UART_DEV ("uart0")
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL
|
||||
#define MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL (UART_FLOW_CTL_NONE)
|
||||
#endif
|
||||
|
||||
/*** sys/flash_map */
|
||||
#ifndef MYNEWT_VAL_FLASH_MAP_MAX_AREAS
|
||||
#define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10)
|
||||
#endif
|
||||
|
||||
/*** sys/log/stub */
|
||||
#ifndef MYNEWT_VAL_LOG_CONSOLE
|
||||
#define MYNEWT_VAL_LOG_CONSOLE (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_LOG_FCB
|
||||
#define MYNEWT_VAL_LOG_FCB (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_LOG_LEVEL
|
||||
#define MYNEWT_VAL_LOG_LEVEL (255)
|
||||
#endif
|
||||
|
||||
/*** sys/sysinit */
|
||||
#ifndef MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT
|
||||
#define MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT (1)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE
|
||||
#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_SYSINIT_PANIC_MESSAGE
|
||||
#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef __SYSINIT_H__
|
||||
#define __SYSINIT_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SYSINIT_ASSERT_ACTIVE()
|
||||
|
||||
#define SYSINIT_PANIC_ASSERT(rc) assert(rc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYSINIT_H__ */
|
||||
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
pkg.name: porting/nimble
|
||||
pkg.type: app
|
||||
pkg.description: Stub for NimBLE porting
|
||||
pkg.author: "Apache Mynewt <[email protected]>"
|
||||
pkg.homepage: "http://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
|
||||
pkg.deps:
|
||||
- nimble/host
|
||||
- nimble/host/services/ans
|
||||
- nimble/host/services/bas
|
||||
- nimble/host/services/gap
|
||||
- nimble/host/services/gatt
|
||||
- nimble/host/services/ias
|
||||
- nimble/host/services/lls
|
||||
- nimble/host/services/tps
|
||||
- nimble/transport
|
||||
- "@apache-mynewt-core/sys/console/stub"
|
||||
- "@apache-mynewt-core/sys/log/stub"
|
||||
- "@apache-mynewt-core/sys/stats/stub"
|
||||
|
||||
# No need to build files from this package
|
||||
pkg.ign_files:
|
||||
- ".*\\.c"
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "os/endian.h"
|
||||
|
||||
void
|
||||
put_le16(void *buf, uint16_t x)
|
||||
{
|
||||
uint8_t *u8ptr;
|
||||
|
||||
u8ptr = buf;
|
||||
u8ptr[0] = (uint8_t)x;
|
||||
u8ptr[1] = (uint8_t)(x >> 8);
|
||||
}
|
||||
|
||||
void
|
||||
put_le32(void *buf, uint32_t x)
|
||||
{
|
||||
uint8_t *u8ptr;
|
||||
|
||||
u8ptr = buf;
|
||||
u8ptr[0] = (uint8_t)x;
|
||||
u8ptr[1] = (uint8_t)(x >> 8);
|
||||
u8ptr[2] = (uint8_t)(x >> 16);
|
||||
u8ptr[3] = (uint8_t)(x >> 24);
|
||||
}
|
||||
|
||||
void
|
||||
put_le64(void *buf, uint64_t x)
|
||||
{
|
||||
uint8_t *u8ptr;
|
||||
|
||||
u8ptr = buf;
|
||||
u8ptr[0] = (uint8_t)x;
|
||||
u8ptr[1] = (uint8_t)(x >> 8);
|
||||
u8ptr[2] = (uint8_t)(x >> 16);
|
||||
u8ptr[3] = (uint8_t)(x >> 24);
|
||||
u8ptr[4] = (uint8_t)(x >> 32);
|
||||
u8ptr[5] = (uint8_t)(x >> 40);
|
||||
u8ptr[6] = (uint8_t)(x >> 48);
|
||||
u8ptr[7] = (uint8_t)(x >> 56);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
get_le16(const void *buf)
|
||||
{
|
||||
const uint8_t *u8ptr;
|
||||
uint16_t x;
|
||||
|
||||
u8ptr = buf;
|
||||
x = u8ptr[0];
|
||||
x |= (uint16_t)u8ptr[1] << 8;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_le32(const void *buf)
|
||||
{
|
||||
const uint8_t *u8ptr;
|
||||
uint32_t x;
|
||||
|
||||
u8ptr = buf;
|
||||
x = u8ptr[0];
|
||||
x |= (uint32_t)u8ptr[1] << 8;
|
||||
x |= (uint32_t)u8ptr[2] << 16;
|
||||
x |= (uint32_t)u8ptr[3] << 24;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
get_le64(const void *buf)
|
||||
{
|
||||
const uint8_t *u8ptr;
|
||||
uint64_t x;
|
||||
|
||||
u8ptr = buf;
|
||||
x = u8ptr[0];
|
||||
x |= (uint64_t)u8ptr[1] << 8;
|
||||
x |= (uint64_t)u8ptr[2] << 16;
|
||||
x |= (uint64_t)u8ptr[3] << 24;
|
||||
x |= (uint64_t)u8ptr[4] << 32;
|
||||
x |= (uint64_t)u8ptr[5] << 40;
|
||||
x |= (uint64_t)u8ptr[6] << 48;
|
||||
x |= (uint64_t)u8ptr[7] << 56;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
put_be16(void *buf, uint16_t x)
|
||||
{
|
||||
uint8_t *u8ptr;
|
||||
|
||||
u8ptr = buf;
|
||||
u8ptr[0] = (uint8_t)(x >> 8);
|
||||
u8ptr[1] = (uint8_t)x;
|
||||
}
|
||||
|
||||
void
|
||||
put_be32(void *buf, uint32_t x)
|
||||
{
|
||||
uint8_t *u8ptr;
|
||||
|
||||
u8ptr = buf;
|
||||
u8ptr[0] = (uint8_t)(x >> 24);
|
||||
u8ptr[1] = (uint8_t)(x >> 16);
|
||||
u8ptr[2] = (uint8_t)(x >> 8);
|
||||
u8ptr[3] = (uint8_t)x;
|
||||
}
|
||||
|
||||
void
|
||||
put_be64(void *buf, uint64_t x)
|
||||
{
|
||||
uint8_t *u8ptr;
|
||||
|
||||
u8ptr = buf;
|
||||
u8ptr[0] = (uint8_t)(x >> 56);
|
||||
u8ptr[1] = (uint8_t)(x >> 48);
|
||||
u8ptr[2] = (uint8_t)(x >> 40);
|
||||
u8ptr[3] = (uint8_t)(x >> 32);
|
||||
u8ptr[4] = (uint8_t)(x >> 24);
|
||||
u8ptr[5] = (uint8_t)(x >> 16);
|
||||
u8ptr[6] = (uint8_t)(x >> 8);
|
||||
u8ptr[7] = (uint8_t)x;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
get_be16(const void *buf)
|
||||
{
|
||||
const uint8_t *u8ptr;
|
||||
uint16_t x;
|
||||
|
||||
u8ptr = buf;
|
||||
x = (uint16_t)u8ptr[0] << 8;
|
||||
x |= u8ptr[1];
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_be32(const void *buf)
|
||||
{
|
||||
const uint8_t *u8ptr;
|
||||
uint32_t x;
|
||||
|
||||
u8ptr = buf;
|
||||
x = (uint32_t)u8ptr[0] << 24;
|
||||
x |= (uint32_t)u8ptr[1] << 16;
|
||||
x |= (uint32_t)u8ptr[2] << 8;
|
||||
x |= u8ptr[3];
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
get_be64(const void *buf)
|
||||
{
|
||||
const uint8_t *u8ptr;
|
||||
uint64_t x;
|
||||
|
||||
u8ptr = buf;
|
||||
x = (uint64_t)u8ptr[0] << 56;
|
||||
x |= (uint64_t)u8ptr[1] << 48;
|
||||
x |= (uint64_t)u8ptr[2] << 40;
|
||||
x |= (uint64_t)u8ptr[3] << 32;
|
||||
x |= (uint64_t)u8ptr[4] << 24;
|
||||
x |= (uint64_t)u8ptr[5] << 16;
|
||||
x |= (uint64_t)u8ptr[6] << 8;
|
||||
x |= u8ptr[7];
|
||||
|
||||
return x;
|
||||
}
|
||||
void
|
||||
swap_in_place(void *buf, int len)
|
||||
{
|
||||
uint8_t *u8ptr;
|
||||
uint8_t tmp;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
u8ptr = buf;
|
||||
|
||||
for (i = 0, j = len - 1; i < j; i++, j--) {
|
||||
tmp = u8ptr[i];
|
||||
|
||||
u8ptr[i] = u8ptr[j];
|
||||
u8ptr[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* swap octets */
|
||||
void
|
||||
swap_buf(uint8_t *dst, const uint8_t *src, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
dst[len - 1 - i] = src[i];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,840 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include "os/os.h"
|
||||
#include "nrfx.h"
|
||||
#include "hal/hal_timer.h"
|
||||
|
||||
#define __HAL_DISABLE_INTERRUPTS(x) \
|
||||
do { \
|
||||
x = __get_PRIMASK(); \
|
||||
__disable_irq(); \
|
||||
} while(0);
|
||||
|
||||
#define __HAL_ENABLE_INTERRUPTS(x) \
|
||||
do { \
|
||||
if (!x) { \
|
||||
__enable_irq(); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
/* IRQ prototype */
|
||||
typedef void (*hal_timer_irq_handler_t)(void);
|
||||
|
||||
/* User CC 2 for reading counter, CC 3 for timer isr */
|
||||
#define NRF_TIMER_CC_READ (2)
|
||||
#define NRF_TIMER_CC_INT (3)
|
||||
|
||||
/* Output compare 2 used for RTC timers */
|
||||
#define NRF_RTC_TIMER_CC_INT (2)
|
||||
|
||||
/* Maximum number of hal timers used */
|
||||
#define NRF52_HAL_TIMER_MAX (6)
|
||||
|
||||
/* Maximum timer frequency */
|
||||
#define NRF52_MAX_TIMER_FREQ (16000000)
|
||||
|
||||
struct nrf52_hal_timer {
|
||||
uint8_t tmr_enabled;
|
||||
uint8_t tmr_irq_num;
|
||||
uint8_t tmr_rtc;
|
||||
uint8_t tmr_pad;
|
||||
uint32_t tmr_cntr;
|
||||
uint32_t timer_isrs;
|
||||
uint32_t tmr_freq;
|
||||
void *tmr_reg;
|
||||
TAILQ_HEAD(hal_timer_qhead, hal_timer) hal_timer_q;
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(TIMER_0)
|
||||
struct nrf52_hal_timer nrf52_hal_timer0;
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_1)
|
||||
struct nrf52_hal_timer nrf52_hal_timer1;
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_2)
|
||||
struct nrf52_hal_timer nrf52_hal_timer2;
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_3)
|
||||
struct nrf52_hal_timer nrf52_hal_timer3;
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_4)
|
||||
struct nrf52_hal_timer nrf52_hal_timer4;
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_5)
|
||||
struct nrf52_hal_timer nrf52_hal_timer5;
|
||||
#endif
|
||||
|
||||
static const struct nrf52_hal_timer *nrf52_hal_timers[NRF52_HAL_TIMER_MAX] = {
|
||||
#if MYNEWT_VAL(TIMER_0)
|
||||
&nrf52_hal_timer0,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_1)
|
||||
&nrf52_hal_timer1,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_2)
|
||||
&nrf52_hal_timer2,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_3)
|
||||
&nrf52_hal_timer3,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_4)
|
||||
&nrf52_hal_timer4,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#if MYNEWT_VAL(TIMER_5)
|
||||
&nrf52_hal_timer5
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Resolve timer number into timer structure */
|
||||
#define NRF52_HAL_TIMER_RESOLVE(__n, __v) \
|
||||
if ((__n) >= NRF52_HAL_TIMER_MAX) { \
|
||||
rc = EINVAL; \
|
||||
goto err; \
|
||||
} \
|
||||
(__v) = (struct nrf52_hal_timer *) nrf52_hal_timers[(__n)]; \
|
||||
if ((__v) == NULL) { \
|
||||
rc = EINVAL; \
|
||||
goto err; \
|
||||
}
|
||||
|
||||
/* Interrupt mask for interrupt enable/clear */
|
||||
#define NRF_TIMER_INT_MASK(x) ((1 << (uint32_t)(x)) << 16)
|
||||
|
||||
static uint32_t
|
||||
nrf_read_timer_cntr(NRF_TIMER_Type *hwtimer)
|
||||
{
|
||||
uint32_t tcntr;
|
||||
|
||||
/* Force a capture of the timer into 'cntr' capture channel; read it */
|
||||
hwtimer->TASKS_CAPTURE[NRF_TIMER_CC_READ] = 1;
|
||||
tcntr = hwtimer->CC[NRF_TIMER_CC_READ];
|
||||
|
||||
return tcntr;
|
||||
}
|
||||
|
||||
/**
|
||||
* nrf timer set ocmp
|
||||
*
|
||||
* Set the OCMP used by the timer to the desired expiration tick
|
||||
*
|
||||
* NOTE: Must be called with interrupts disabled.
|
||||
*
|
||||
* @param timer Pointer to timer.
|
||||
*/
|
||||
static void
|
||||
nrf_timer_set_ocmp(struct nrf52_hal_timer *bsptimer, uint32_t expiry)
|
||||
{
|
||||
int32_t delta_t;
|
||||
uint32_t temp;
|
||||
uint32_t cntr;
|
||||
NRF_TIMER_Type *hwtimer;
|
||||
NRF_RTC_Type *rtctimer;
|
||||
|
||||
if (bsptimer->tmr_rtc) {
|
||||
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
|
||||
rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
|
||||
temp = bsptimer->tmr_cntr;
|
||||
cntr = rtctimer->COUNTER;
|
||||
if (rtctimer->EVENTS_OVRFLW) {
|
||||
temp += (1UL << 24);
|
||||
cntr = rtctimer->COUNTER;
|
||||
}
|
||||
temp |= cntr;
|
||||
delta_t = (int32_t)(expiry - temp);
|
||||
|
||||
/*
|
||||
* The nrf documentation states that you must set the output
|
||||
* compare to 2 greater than the counter to guarantee an interrupt.
|
||||
* Since the counter can tick once while we check, we make sure
|
||||
* it is greater than 2.
|
||||
*/
|
||||
if (delta_t < 3) {
|
||||
NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
|
||||
} else {
|
||||
if (delta_t < (1UL << 24)) {
|
||||
rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry & 0x00ffffff;
|
||||
} else {
|
||||
/* CC too far ahead. Just make sure we set compare far ahead */
|
||||
rtctimer->CC[NRF_RTC_TIMER_CC_INT] = cntr + (1UL << 23);
|
||||
}
|
||||
rtctimer->INTENSET = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
|
||||
}
|
||||
} else {
|
||||
hwtimer = bsptimer->tmr_reg;
|
||||
|
||||
/* Disable ocmp interrupt and set new value */
|
||||
hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
|
||||
|
||||
/* Set output compare register to timer expiration */
|
||||
hwtimer->CC[NRF_TIMER_CC_INT] = expiry;
|
||||
|
||||
/* Clear interrupt flag */
|
||||
hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0;
|
||||
|
||||
/* Enable the output compare interrupt */
|
||||
hwtimer->INTENSET = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
|
||||
|
||||
/* Force interrupt to occur as we may have missed it */
|
||||
if ((int32_t)(nrf_read_timer_cntr(hwtimer) - expiry) >= 0) {
|
||||
NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable output compare used for timer */
|
||||
static void
|
||||
nrf_timer_disable_ocmp(NRF_TIMER_Type *hwtimer)
|
||||
{
|
||||
hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
|
||||
}
|
||||
|
||||
static void
|
||||
nrf_rtc_disable_ocmp(NRF_RTC_Type *rtctimer)
|
||||
{
|
||||
rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
hal_timer_read_bsptimer(struct nrf52_hal_timer *bsptimer)
|
||||
{
|
||||
uint32_t low32;
|
||||
uint32_t ctx;
|
||||
uint32_t tcntr;
|
||||
NRF_RTC_Type *rtctimer;
|
||||
|
||||
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
|
||||
__HAL_DISABLE_INTERRUPTS(ctx);
|
||||
tcntr = bsptimer->tmr_cntr;
|
||||
low32 = rtctimer->COUNTER;
|
||||
if (rtctimer->EVENTS_OVRFLW) {
|
||||
tcntr += (1UL << 24);
|
||||
bsptimer->tmr_cntr = tcntr;
|
||||
low32 = rtctimer->COUNTER;
|
||||
rtctimer->EVENTS_OVRFLW = 0;
|
||||
NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
|
||||
}
|
||||
tcntr |= low32;
|
||||
__HAL_ENABLE_INTERRUPTS(ctx);
|
||||
|
||||
return tcntr;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \
|
||||
MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4) || MYNEWT_VAL(TIMER_5))
|
||||
/**
|
||||
* hal timer chk queue
|
||||
*
|
||||
*
|
||||
* @param bsptimer
|
||||
*/
|
||||
static void
|
||||
hal_timer_chk_queue(struct nrf52_hal_timer *bsptimer)
|
||||
{
|
||||
int32_t delta;
|
||||
uint32_t tcntr;
|
||||
uint32_t ctx;
|
||||
struct hal_timer *timer;
|
||||
|
||||
/* disable interrupts */
|
||||
__HAL_DISABLE_INTERRUPTS(ctx);
|
||||
while ((timer = TAILQ_FIRST(&bsptimer->hal_timer_q)) != NULL) {
|
||||
if (bsptimer->tmr_rtc) {
|
||||
tcntr = hal_timer_read_bsptimer(bsptimer);
|
||||
/*
|
||||
* If we are within 3 ticks of RTC, we wont be able to set compare.
|
||||
* Thus, we have to service this timer early.
|
||||
*/
|
||||
delta = -3;
|
||||
} else {
|
||||
tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
|
||||
delta = 0;
|
||||
}
|
||||
if ((int32_t)(tcntr - timer->expiry) >= delta) {
|
||||
TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
|
||||
timer->link.tqe_prev = NULL;
|
||||
timer->cb_func(timer->cb_arg);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Any timers left on queue? If so, we need to set OCMP */
|
||||
timer = TAILQ_FIRST(&bsptimer->hal_timer_q);
|
||||
if (timer) {
|
||||
nrf_timer_set_ocmp(bsptimer, timer->expiry);
|
||||
} else {
|
||||
if (bsptimer->tmr_rtc) {
|
||||
nrf_rtc_disable_ocmp((NRF_RTC_Type *)bsptimer->tmr_reg);
|
||||
} else {
|
||||
nrf_timer_disable_ocmp(bsptimer->tmr_reg);
|
||||
}
|
||||
}
|
||||
__HAL_ENABLE_INTERRUPTS(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hal timer irq handler
|
||||
*
|
||||
* Generic HAL timer irq handler.
|
||||
*
|
||||
* @param tmr
|
||||
*/
|
||||
/**
|
||||
* hal timer irq handler
|
||||
*
|
||||
* This is the global timer interrupt routine.
|
||||
*
|
||||
*/
|
||||
#if (MYNEWT_VAL(TIMER_0) || MYNEWT_VAL(TIMER_1) || MYNEWT_VAL(TIMER_2) || \
|
||||
MYNEWT_VAL(TIMER_3) || MYNEWT_VAL(TIMER_4))
|
||||
|
||||
static void
|
||||
hal_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
|
||||
{
|
||||
uint32_t compare;
|
||||
NRF_TIMER_Type *hwtimer;
|
||||
|
||||
os_trace_enter_isr();
|
||||
|
||||
/* Check interrupt source. If set, clear them */
|
||||
hwtimer = bsptimer->tmr_reg;
|
||||
compare = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT];
|
||||
if (compare) {
|
||||
hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT] = 0;
|
||||
}
|
||||
|
||||
/* XXX: make these stats? */
|
||||
/* Count # of timer isrs */
|
||||
++bsptimer->timer_isrs;
|
||||
|
||||
/*
|
||||
* NOTE: we dont check the 'compare' variable here due to how the timer
|
||||
* is implemented on this chip. There is no way to force an output
|
||||
* compare, so if we are late setting the output compare (i.e. the timer
|
||||
* counter is already passed the output compare value), we use the NVIC
|
||||
* to set a pending interrupt. This means that there will be no compare
|
||||
* flag set, so all we do is check to see if the compare interrupt is
|
||||
* enabled.
|
||||
*/
|
||||
if (hwtimer->INTENCLR & NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT)) {
|
||||
hal_timer_chk_queue(bsptimer);
|
||||
/* XXX: Recommended by nordic to make sure interrupts are cleared */
|
||||
compare = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT];
|
||||
}
|
||||
|
||||
os_trace_exit_isr();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(TIMER_5)
|
||||
static void
|
||||
hal_rtc_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
|
||||
{
|
||||
uint32_t overflow;
|
||||
uint32_t compare;
|
||||
NRF_RTC_Type *rtctimer;
|
||||
|
||||
/* Check interrupt source. If set, clear them */
|
||||
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
|
||||
compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT];
|
||||
if (compare) {
|
||||
rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT] = 0;
|
||||
}
|
||||
|
||||
overflow = rtctimer->EVENTS_OVRFLW;
|
||||
if (overflow) {
|
||||
rtctimer->EVENTS_OVRFLW = 0;
|
||||
bsptimer->tmr_cntr += (1UL << 24);
|
||||
}
|
||||
|
||||
/* Count # of timer isrs */
|
||||
++bsptimer->timer_isrs;
|
||||
|
||||
/*
|
||||
* NOTE: we dont check the 'compare' variable here due to how the timer
|
||||
* is implemented on this chip. There is no way to force an output
|
||||
* compare, so if we are late setting the output compare (i.e. the timer
|
||||
* counter is already passed the output compare value), we use the NVIC
|
||||
* to set a pending interrupt. This means that there will be no compare
|
||||
* flag set, so all we do is check to see if the compare interrupt is
|
||||
* enabled.
|
||||
*/
|
||||
hal_timer_chk_queue(bsptimer);
|
||||
|
||||
/* Recommended by nordic to make sure interrupts are cleared */
|
||||
compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(TIMER_0)
|
||||
void
|
||||
nrf52_timer0_irq_handler(void)
|
||||
{
|
||||
hal_timer_irq_handler(&nrf52_hal_timer0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(TIMER_1)
|
||||
void
|
||||
nrf52_timer1_irq_handler(void)
|
||||
{
|
||||
hal_timer_irq_handler(&nrf52_hal_timer1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(TIMER_2)
|
||||
void
|
||||
nrf52_timer2_irq_handler(void)
|
||||
{
|
||||
hal_timer_irq_handler(&nrf52_hal_timer2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(TIMER_3)
|
||||
void
|
||||
nrf52_timer3_irq_handler(void)
|
||||
{
|
||||
hal_timer_irq_handler(&nrf52_hal_timer3);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(TIMER_4)
|
||||
void
|
||||
nrf52_timer4_irq_handler(void)
|
||||
{
|
||||
hal_timer_irq_handler(&nrf52_hal_timer4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(TIMER_5)
|
||||
void
|
||||
nrf52_timer5_irq_handler(void)
|
||||
{
|
||||
hal_rtc_timer_irq_handler(&nrf52_hal_timer5);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hal timer init
|
||||
*
|
||||
* Initialize platform specific timer items
|
||||
*
|
||||
* @param timer_num Timer number to initialize
|
||||
* @param cfg Pointer to platform specific configuration
|
||||
*
|
||||
* @return int 0: success; error code otherwise
|
||||
*/
|
||||
int
|
||||
hal_timer_init(int timer_num, void *cfg)
|
||||
{
|
||||
int rc;
|
||||
uint8_t irq_num;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
void *hwtimer;
|
||||
hal_timer_irq_handler_t irq_isr;
|
||||
|
||||
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
|
||||
|
||||
/* If timer is enabled do not allow init */
|
||||
if (bsptimer->tmr_enabled) {
|
||||
rc = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (timer_num) {
|
||||
#if MYNEWT_VAL(TIMER_5)
|
||||
case 5:
|
||||
irq_num = RTC0_IRQn;
|
||||
hwtimer = NRF_RTC0;
|
||||
irq_isr = nrf52_timer5_irq_handler;
|
||||
bsptimer->tmr_rtc = 1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
hwtimer = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hwtimer == NULL) {
|
||||
rc = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
bsptimer->tmr_reg = hwtimer;
|
||||
bsptimer->tmr_irq_num = irq_num;
|
||||
|
||||
/* Disable IRQ, set priority and set vector in table */
|
||||
NVIC_DisableIRQ(irq_num);
|
||||
NVIC_SetPriority(irq_num, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
#if MYNEWT
|
||||
NVIC_SetVector(irq_num, (uint32_t)irq_isr);
|
||||
#else
|
||||
ble_npl_hw_set_isr(irq_num, (uint32_t)irq_isr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal timer config
|
||||
*
|
||||
* Configure a timer to run at the desired frequency. This starts the timer.
|
||||
*
|
||||
* @param timer_num
|
||||
* @param freq_hz
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
hal_timer_config(int timer_num, uint32_t freq_hz)
|
||||
{
|
||||
int rc;
|
||||
uint32_t ctx;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
#if MYNEWT_VAL(TIMER_5)
|
||||
NRF_RTC_Type *rtctimer;
|
||||
#endif
|
||||
|
||||
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
|
||||
|
||||
#if MYNEWT_VAL(TIMER_5)
|
||||
if (timer_num == 5) {
|
||||
/* NOTE: we only allow the RTC frequency to be set at 32768 */
|
||||
if (bsptimer->tmr_enabled || (freq_hz != 32768) ||
|
||||
(bsptimer->tmr_reg == NULL)) {
|
||||
rc = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
bsptimer->tmr_freq = freq_hz;
|
||||
bsptimer->tmr_enabled = 1;
|
||||
|
||||
__HAL_DISABLE_INTERRUPTS(ctx);
|
||||
|
||||
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
|
||||
|
||||
/* Stop the timer first */
|
||||
rtctimer->TASKS_STOP = 1;
|
||||
|
||||
/* Always no prescaler */
|
||||
rtctimer->PRESCALER = 0;
|
||||
|
||||
/* Clear overflow events and set overflow interrupt */
|
||||
rtctimer->EVENTS_OVRFLW = 0;
|
||||
rtctimer->INTENSET = RTC_INTENSET_OVRFLW_Msk;
|
||||
|
||||
/* Start the timer */
|
||||
rtctimer->TASKS_START = 1;
|
||||
|
||||
/* Set isr in vector table and enable interrupt */
|
||||
NVIC_EnableIRQ(bsptimer->tmr_irq_num);
|
||||
|
||||
__HAL_ENABLE_INTERRUPTS(ctx);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(0);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal timer deinit
|
||||
*
|
||||
* De-initialize a HW timer.
|
||||
*
|
||||
* @param timer_num
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
hal_timer_deinit(int timer_num)
|
||||
{
|
||||
int rc;
|
||||
uint32_t ctx;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
NRF_TIMER_Type *hwtimer;
|
||||
NRF_RTC_Type *rtctimer;
|
||||
|
||||
rc = 0;
|
||||
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
|
||||
|
||||
__HAL_DISABLE_INTERRUPTS(ctx);
|
||||
if (bsptimer->tmr_rtc) {
|
||||
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
|
||||
rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
|
||||
rtctimer->TASKS_STOP = 1;
|
||||
} else {
|
||||
hwtimer = (NRF_TIMER_Type *)bsptimer->tmr_reg;
|
||||
hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
|
||||
hwtimer->TASKS_STOP = 1;
|
||||
}
|
||||
bsptimer->tmr_enabled = 0;
|
||||
bsptimer->tmr_reg = NULL;
|
||||
__HAL_ENABLE_INTERRUPTS(ctx);
|
||||
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal timer get resolution
|
||||
*
|
||||
* Get the resolution of the timer. This is the timer period, in nanoseconds
|
||||
*
|
||||
* @param timer_num
|
||||
*
|
||||
* @return uint32_t The
|
||||
*/
|
||||
uint32_t
|
||||
hal_timer_get_resolution(int timer_num)
|
||||
{
|
||||
int rc;
|
||||
uint32_t resolution;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
|
||||
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
|
||||
|
||||
resolution = 1000000000 / bsptimer->tmr_freq;
|
||||
return resolution;
|
||||
|
||||
err:
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal timer read
|
||||
*
|
||||
* Returns the timer counter. NOTE: if the timer is a 16-bit timer, only
|
||||
* the lower 16 bits are valid. If the timer is a 64-bit timer, only the
|
||||
* low 32-bits are returned.
|
||||
*
|
||||
* @return uint32_t The timer counter register.
|
||||
*/
|
||||
uint32_t
|
||||
hal_timer_read(int timer_num)
|
||||
{
|
||||
int rc;
|
||||
uint32_t tcntr;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
|
||||
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
|
||||
if (bsptimer->tmr_rtc) {
|
||||
tcntr = hal_timer_read_bsptimer(bsptimer);
|
||||
} else {
|
||||
tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
|
||||
}
|
||||
|
||||
return tcntr;
|
||||
|
||||
/* Assert here since there is no invalid return code */
|
||||
err:
|
||||
assert(0);
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal timer delay
|
||||
*
|
||||
* Blocking delay for n ticks
|
||||
*
|
||||
* @param timer_num
|
||||
* @param ticks
|
||||
*
|
||||
* @return int 0 on success; error code otherwise.
|
||||
*/
|
||||
int
|
||||
hal_timer_delay(int timer_num, uint32_t ticks)
|
||||
{
|
||||
uint32_t until;
|
||||
|
||||
until = hal_timer_read(timer_num) + ticks;
|
||||
while ((int32_t)(hal_timer_read(timer_num) - until) <= 0) {
|
||||
/* Loop here till finished */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Initialize the HAL timer structure with the callback and the callback
|
||||
* argument. Also initializes the HW specific timer pointer.
|
||||
*
|
||||
* @param cb_func
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
hal_timer_set_cb(int timer_num, struct hal_timer *timer, hal_timer_cb cb_func,
|
||||
void *arg)
|
||||
{
|
||||
int rc;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
|
||||
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
|
||||
|
||||
timer->cb_func = cb_func;
|
||||
timer->cb_arg = arg;
|
||||
timer->link.tqe_prev = NULL;
|
||||
timer->bsp_timer = bsptimer;
|
||||
|
||||
rc = 0;
|
||||
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
hal_timer_start(struct hal_timer *timer, uint32_t ticks)
|
||||
{
|
||||
int rc;
|
||||
uint32_t tick;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
|
||||
/* Set the tick value at which the timer should expire */
|
||||
bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
|
||||
if (bsptimer->tmr_rtc) {
|
||||
tick = hal_timer_read_bsptimer(bsptimer) + ticks;
|
||||
} else {
|
||||
tick = nrf_read_timer_cntr(bsptimer->tmr_reg) + ticks;
|
||||
}
|
||||
rc = hal_timer_start_at(timer, tick);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
hal_timer_start_at(struct hal_timer *timer, uint32_t tick)
|
||||
{
|
||||
uint32_t ctx;
|
||||
struct hal_timer *entry;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
|
||||
if ((timer == NULL) || (timer->link.tqe_prev != NULL) ||
|
||||
(timer->cb_func == NULL)) {
|
||||
return EINVAL;
|
||||
}
|
||||
bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
|
||||
timer->expiry = tick;
|
||||
|
||||
__HAL_DISABLE_INTERRUPTS(ctx);
|
||||
|
||||
if (TAILQ_EMPTY(&bsptimer->hal_timer_q)) {
|
||||
TAILQ_INSERT_HEAD(&bsptimer->hal_timer_q, timer, link);
|
||||
} else {
|
||||
TAILQ_FOREACH(entry, &bsptimer->hal_timer_q, link) {
|
||||
if ((int32_t)(timer->expiry - entry->expiry) < 0) {
|
||||
TAILQ_INSERT_BEFORE(entry, timer, link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!entry) {
|
||||
TAILQ_INSERT_TAIL(&bsptimer->hal_timer_q, timer, link);
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is the head, we need to set new OCMP */
|
||||
if (timer == TAILQ_FIRST(&bsptimer->hal_timer_q)) {
|
||||
nrf_timer_set_ocmp(bsptimer, timer->expiry);
|
||||
}
|
||||
|
||||
__HAL_ENABLE_INTERRUPTS(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal timer stop
|
||||
*
|
||||
* Stop a timer.
|
||||
*
|
||||
* @param timer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
hal_timer_stop(struct hal_timer *timer)
|
||||
{
|
||||
uint32_t ctx;
|
||||
int reset_ocmp;
|
||||
struct hal_timer *entry;
|
||||
struct nrf52_hal_timer *bsptimer;
|
||||
|
||||
if (timer == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
|
||||
|
||||
__HAL_DISABLE_INTERRUPTS(ctx);
|
||||
|
||||
if (timer->link.tqe_prev != NULL) {
|
||||
reset_ocmp = 0;
|
||||
if (timer == TAILQ_FIRST(&bsptimer->hal_timer_q)) {
|
||||
/* If first on queue, we will need to reset OCMP */
|
||||
entry = TAILQ_NEXT(timer, link);
|
||||
reset_ocmp = 1;
|
||||
}
|
||||
TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
|
||||
timer->link.tqe_prev = NULL;
|
||||
if (reset_ocmp) {
|
||||
if (entry) {
|
||||
nrf_timer_set_ocmp((struct nrf52_hal_timer *)entry->bsp_timer,
|
||||
entry->expiry);
|
||||
} else {
|
||||
if (bsptimer->tmr_rtc) {
|
||||
nrf_rtc_disable_ocmp((NRF_RTC_Type *)bsptimer->tmr_reg);
|
||||
} else {
|
||||
nrf_timer_disable_ocmp(bsptimer->tmr_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__HAL_ENABLE_INTERRUPTS(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "os/os.h"
|
||||
#include "mem/mem.h"
|
||||
|
||||
/**
|
||||
* Generic mempool allocation function. Used with basic and extended mempools.
|
||||
*/
|
||||
static int
|
||||
mem_malloc_mempool_gen(uint16_t num_blocks, uint32_t block_size,
|
||||
void **out_buf)
|
||||
{
|
||||
block_size = OS_ALIGN(block_size, OS_ALIGNMENT);
|
||||
|
||||
if (num_blocks > 0) {
|
||||
*out_buf = malloc(OS_MEMPOOL_BYTES(num_blocks, block_size));
|
||||
if (*out_buf == NULL) {
|
||||
return OS_ENOMEM;
|
||||
}
|
||||
} else {
|
||||
*out_buf = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mallocs a block of memory and initializes a mempool to use it.
|
||||
*
|
||||
* @param mempool The mempool to initialize.
|
||||
* @param num_blocks The total number of memory blocks in the
|
||||
* mempool.
|
||||
* @param block_size The size of each mempool entry.
|
||||
* @param name The name to give the mempool.
|
||||
* @param out_buf On success, this points to the malloced memory.
|
||||
* Pass NULL if you don't need this
|
||||
* information.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* OS_ENOMEM on malloc failure;
|
||||
* Other OS code on unexpected error.
|
||||
*/
|
||||
int
|
||||
mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks,
|
||||
uint32_t block_size, char *name, void **out_buf)
|
||||
{
|
||||
void *buf;
|
||||
int rc;
|
||||
|
||||
rc = mem_malloc_mempool_gen(num_blocks, block_size, &buf);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = os_mempool_init(mempool, num_blocks, block_size, buf, name);
|
||||
if (rc != 0) {
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (out_buf != NULL) {
|
||||
*out_buf = buf;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mallocs a block of memory and initializes an extended mempool to use it.
|
||||
*
|
||||
* @param mpe The extended mempool to initialize.
|
||||
* @param num_blocks The total number of memory blocks in the
|
||||
* mempool.
|
||||
* @param block_size The size of each mempool entry.
|
||||
* @param name The name to give the mempool.
|
||||
* @param out_buf On success, this points to the malloced memory.
|
||||
* Pass NULL if you don't need this
|
||||
* information.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* OS_ENOMEM on malloc failure;
|
||||
* Other OS code on unexpected error.
|
||||
*/
|
||||
int
|
||||
mem_malloc_mempool_ext(struct os_mempool_ext *mpe, uint16_t num_blocks,
|
||||
uint32_t block_size, char *name, void **out_buf)
|
||||
{
|
||||
void *buf;
|
||||
int rc;
|
||||
|
||||
rc = mem_malloc_mempool_gen(num_blocks, block_size, &buf);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = os_mempool_ext_init(mpe, num_blocks, block_size, buf, name);
|
||||
if (rc != 0) {
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (out_buf != NULL) {
|
||||
*out_buf = buf;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mallocs a block of memory and initializes an mbuf pool to use it. The
|
||||
* specified block_size indicates the size of an mbuf acquired from the pool if
|
||||
* it does not contain a pkthdr.
|
||||
*
|
||||
* @param mempool The mempool to initialize.
|
||||
* @param mbuf_pool The mbuf pool to initialize.
|
||||
* @param num_blocks The total number of mbufs in the pool.
|
||||
* @param block_size The size of each mbuf.
|
||||
* @param name The name to give the mempool.
|
||||
* @param out_buf On success, this points to the malloced memory.
|
||||
* Pass NULL if you don't need this
|
||||
* information.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* OS_ENOMEM on malloc failure;
|
||||
* Other OS code on unexpected error.
|
||||
*/
|
||||
int
|
||||
mem_malloc_mbuf_pool(struct os_mempool *mempool,
|
||||
struct os_mbuf_pool *mbuf_pool, uint16_t num_blocks,
|
||||
uint32_t block_size, char *name,
|
||||
void **out_buf)
|
||||
{
|
||||
void *buf;
|
||||
int rc;
|
||||
|
||||
block_size = OS_ALIGN(block_size + sizeof (struct os_mbuf), OS_ALIGNMENT);
|
||||
|
||||
rc = mem_malloc_mempool(mempool, num_blocks, block_size, name, &buf);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks);
|
||||
if (rc != 0) {
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (out_buf != NULL) {
|
||||
*out_buf = buf;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mallocs a block of memory and initializes an mbuf pool to use it. The
|
||||
* specified block_size indicates the size of an mbuf acquired from the pool if
|
||||
* it contains a pkthdr.
|
||||
*
|
||||
* @param mempool The mempool to initialize.
|
||||
* @param mbuf_pool The mbuf pool to initialize.
|
||||
* @param num_blocks The total number of mbufs in the pool.
|
||||
* @param block_size The size of each mbuf.
|
||||
* @param name The name to give the mempool.
|
||||
* @param out_buf On success, this points to the malloced memory.
|
||||
* Pass NULL if you don't need this
|
||||
* information.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* OS_ENOMEM on malloc failure;
|
||||
* Other OS code on unexpected error.
|
||||
*/
|
||||
int
|
||||
mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
|
||||
struct os_mbuf_pool *mbuf_pool, int num_blocks,
|
||||
int block_size, char *name,
|
||||
void **out_buf)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = mem_malloc_mbuf_pool(mempool, mbuf_pool, num_blocks,
|
||||
block_size + sizeof (struct os_mbuf_pkthdr),
|
||||
name, out_buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
|
||||
struct os_mbuf_pool *mbuf_pool, int num_blocks,
|
||||
int block_size, char *name)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = os_mempool_init(mempool, num_blocks, block_size, mem, name);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Splits an appropriately-sized fragment from the front of an mbuf chain, as
|
||||
* neeeded. If the length of the mbuf chain greater than specified maximum
|
||||
* fragment size, a new mbuf is allocated, and data is moved from the source
|
||||
* mbuf to the new mbuf. If the mbuf chain is small enough to fit in a single
|
||||
* fragment, the source mbuf itself is returned unmodified, and the suplied
|
||||
* pointer is set to NULL.
|
||||
*
|
||||
* This function is expected to be called in a loop until the entire mbuf chain
|
||||
* has been consumed. For example:
|
||||
*
|
||||
* struct os_mbuf *frag;
|
||||
* struct os_mbuf *rsp;
|
||||
* // [...]
|
||||
* while (rsp != NULL) {
|
||||
* frag = mem_split_frag(&rsp, get_mtu(), frag_alloc, NULL);
|
||||
* if (frag == NULL) {
|
||||
* os_mbuf_free_chain(rsp);
|
||||
* return SYS_ENOMEM;
|
||||
* }
|
||||
* send_packet(frag)
|
||||
* }
|
||||
*
|
||||
* @param om The packet to fragment. Upon fragmentation,
|
||||
* this mbuf is adjusted such that the
|
||||
* fragment data is removed. If the packet
|
||||
* constitutes a single fragment, this gets
|
||||
* set to NULL on success.
|
||||
* @param max_frag_sz The maximum payload size of a fragment.
|
||||
* Typically this is the MTU of the
|
||||
* connection.
|
||||
* @param alloc_cb Points to a function that allocates an mbuf to
|
||||
* hold a fragment. This function gets called
|
||||
* before the source mbuf chain is modified,
|
||||
* so it can safely inspect it.
|
||||
* @param cb_arg Generic parameter that gets passed to the
|
||||
* callback function.
|
||||
*
|
||||
* @return The next fragment to send on success;
|
||||
* NULL on failure.
|
||||
*/
|
||||
struct os_mbuf *
|
||||
mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
|
||||
mem_frag_alloc_fn *alloc_cb, void *cb_arg)
|
||||
{
|
||||
struct os_mbuf *frag;
|
||||
int rc;
|
||||
|
||||
if (OS_MBUF_PKTLEN(*om) <= max_frag_sz) {
|
||||
/* Final fragment. */
|
||||
frag = *om;
|
||||
*om = NULL;
|
||||
return frag;
|
||||
}
|
||||
|
||||
/* Packet needs to be split. Allocate a new buffer for the fragment. */
|
||||
frag = alloc_cb(max_frag_sz, cb_arg);
|
||||
if (frag == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Move data from the front of the packet into the fragment mbuf. */
|
||||
rc = os_mbuf_appendfrom(frag, *om, 0, max_frag_sz);
|
||||
if (rc != 0) {
|
||||
goto err;
|
||||
}
|
||||
os_mbuf_adj(*om, max_frag_sz);
|
||||
|
||||
/* Free unused portion of of source mbuf chain, if possible. */
|
||||
*om = os_mbuf_trim_front(*om);
|
||||
|
||||
return frag;
|
||||
|
||||
err:
|
||||
os_mbuf_free_chain(frag);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "os/os.h"
|
||||
#include "sysinit/sysinit.h"
|
||||
#include "host/ble_hs.h"
|
||||
#if NIMBLE_CFG_CONTROLLER
|
||||
#include "controller/ble_ll.h"
|
||||
#endif
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
#include "services/ans/ble_svc_ans.h"
|
||||
#include "services/ias/ble_svc_ias.h"
|
||||
#include "services/lls/ble_svc_lls.h"
|
||||
#include "services/tps/ble_svc_tps.h"
|
||||
|
||||
void
|
||||
nimble_port_init(void)
|
||||
{
|
||||
void os_msys_init(void);
|
||||
void ble_store_ram_init(void);
|
||||
#if NIMBLE_CFG_CONTROLLER
|
||||
void ble_hci_ram_init(void);
|
||||
#endif
|
||||
|
||||
os_msys_init();
|
||||
|
||||
ble_hs_init();
|
||||
|
||||
/* XXX These should be configurable somehow */
|
||||
ble_svc_gap_init();
|
||||
ble_svc_gatt_init();
|
||||
ble_svc_ans_init();
|
||||
ble_svc_ias_init();
|
||||
ble_svc_lls_init();
|
||||
ble_svc_tps_init();
|
||||
|
||||
/* XXX Need to have template for store */
|
||||
ble_store_ram_init();
|
||||
|
||||
#if NIMBLE_CFG_CONTROLLER
|
||||
hal_timer_init(5, NULL);
|
||||
os_cputime_init(32768);
|
||||
ble_ll_init();
|
||||
ble_hci_ram_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NIMBLE_CFG_CONTROLLER
|
||||
void
|
||||
nimble_port_ll_task_func(void *arg)
|
||||
{
|
||||
extern void ble_ll_task(void *);
|
||||
|
||||
ble_ll_task(arg);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/os_cputime.h"
|
||||
#include "hal/hal_timer.h"
|
||||
|
||||
#if defined(OS_CPUTIME_FREQ_HIGH)
|
||||
struct os_cputime_data g_os_cputime;
|
||||
#endif
|
||||
|
||||
int
|
||||
os_cputime_init(uint32_t clock_freq)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Set the ticks per microsecond. */
|
||||
#if defined(OS_CPUTIME_FREQ_HIGH)
|
||||
g_os_cputime.ticks_per_usec = clock_freq / 1000000U;
|
||||
#endif
|
||||
rc = hal_timer_config(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM), clock_freq);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the number of ticks has elapsed. This is a blocking delay.
|
||||
*
|
||||
* @param ticks The number of ticks to wait.
|
||||
*/
|
||||
void
|
||||
os_cputime_delay_ticks(uint32_t ticks)
|
||||
{
|
||||
uint32_t until;
|
||||
|
||||
until = os_cputime_get32() + ticks;
|
||||
while ((int32_t)(os_cputime_get32() - until) < 0) {
|
||||
/* Loop here till finished */
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(OS_CPUTIME_FREQ_PWR2)
|
||||
void
|
||||
os_cputime_delay_nsecs(uint32_t nsecs)
|
||||
{
|
||||
uint32_t ticks;
|
||||
|
||||
ticks = os_cputime_nsecs_to_ticks(nsecs);
|
||||
os_cputime_delay_ticks(ticks);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
os_cputime_delay_usecs(uint32_t usecs)
|
||||
{
|
||||
uint32_t ticks;
|
||||
|
||||
ticks = os_cputime_usecs_to_ticks(usecs);
|
||||
os_cputime_delay_ticks(ticks);
|
||||
}
|
||||
|
||||
void
|
||||
os_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp, void *arg)
|
||||
{
|
||||
assert(timer != NULL);
|
||||
assert(fp != NULL);
|
||||
|
||||
hal_timer_set_cb(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM), timer, fp, arg);
|
||||
}
|
||||
|
||||
int
|
||||
os_cputime_timer_start(struct hal_timer *timer, uint32_t cputime)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = hal_timer_start_at(timer, cputime);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
os_cputime_timer_relative(struct hal_timer *timer, uint32_t usecs)
|
||||
{
|
||||
int rc;
|
||||
uint32_t cputime;
|
||||
|
||||
assert(timer != NULL);
|
||||
|
||||
cputime = os_cputime_get32() + os_cputime_usecs_to_ticks(usecs);
|
||||
rc = hal_timer_start_at(timer, cputime);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
os_cputime_timer_stop(struct hal_timer *timer)
|
||||
{
|
||||
hal_timer_stop(timer);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
os_cputime_get32(void)
|
||||
{
|
||||
uint32_t cpu_time;
|
||||
|
||||
cpu_time = hal_timer_read(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM));
|
||||
return cpu_time;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "os/os_cputime.h"
|
||||
|
||||
/**
|
||||
* This module implements cputime functionality for timers for which:
|
||||
* a. freq is a power of 2 Hz, and
|
||||
* b. 256 Hz <= freq < 1 MHz
|
||||
*/
|
||||
|
||||
#if defined(OS_CPUTIME_FREQ_PWR2)
|
||||
|
||||
/**
|
||||
* @addtogroup OSKernel Operating System Kernel
|
||||
* @{
|
||||
* @defgroup OSCPUTime High Resolution Timers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* os cputime usecs to ticks
|
||||
*
|
||||
* Converts the given number of microseconds into cputime ticks.
|
||||
*
|
||||
* @param usecs The number of microseconds to convert to ticks
|
||||
*
|
||||
* @return uint32_t The number of ticks corresponding to 'usecs'
|
||||
*/
|
||||
uint32_t
|
||||
os_cputime_usecs_to_ticks(uint32_t usecs)
|
||||
{
|
||||
uint64_t ticks;
|
||||
|
||||
/*
|
||||
* Faster calculation but could be off 1 full tick since we do not
|
||||
* add residual back. Adding back the residual is commented out below, but
|
||||
* shown.
|
||||
*/
|
||||
ticks = (1ULL << 32) * MYNEWT_VAL(OS_CPUTIME_FREQ) / 1000000 * usecs;
|
||||
|
||||
/* Residual for 32768 Hz. */
|
||||
//ticks += ((uint64_t)usecs * (1526122139+1)) >> 32;
|
||||
|
||||
return ticks >> 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* cputime ticks to usecs
|
||||
*
|
||||
* Convert the given number of ticks into microseconds.
|
||||
*
|
||||
* @param ticks The number of ticks to convert to microseconds.
|
||||
*
|
||||
* @return uint32_t The number of microseconds corresponding to 'ticks'
|
||||
*
|
||||
* NOTE: This calculation will overflow if the value for ticks is greater
|
||||
* than 140737488. I am not going to check that here because that many ticks
|
||||
* is about 4222 seconds, way more than what this routine should be used for.
|
||||
*/
|
||||
uint32_t
|
||||
os_cputime_ticks_to_usecs(uint32_t ticks)
|
||||
{
|
||||
uint32_t usecs;
|
||||
uint32_t shift;
|
||||
uint32_t freq;
|
||||
|
||||
/* Given: `freq = 2^n`, calculate `n`. */
|
||||
/* Note: this looks like a lot of work, but gcc can optimize it away since
|
||||
* `freq` is known at compile time.
|
||||
*/
|
||||
freq = MYNEWT_VAL(OS_CPUTIME_FREQ);
|
||||
shift = 0;
|
||||
while (freq != 0) {
|
||||
freq >>= 1;
|
||||
shift++;
|
||||
}
|
||||
|
||||
if (shift <= 7) {
|
||||
return 0;
|
||||
}
|
||||
shift -= 7;
|
||||
|
||||
usecs = ((ticks >> shift) * 15625) + (((ticks & 0x1ff) * 15625) >> shift);
|
||||
return usecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} OSCPUTime
|
||||
* @} OSKernel
|
||||
*/
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define OS_MEM_TRUE_BLOCK_SIZE(bsize) OS_ALIGN(bsize, OS_ALIGNMENT)
|
||||
#define OS_MEMPOOL_TRUE_BLOCK_SIZE(mp) OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size)
|
||||
|
||||
STAILQ_HEAD(, os_mempool) g_os_mempool_list =
|
||||
STAILQ_HEAD_INITIALIZER(g_os_mempool_list);
|
||||
|
||||
#if MYNEWT_VAL(OS_MEMPOOL_POISON)
|
||||
static uint32_t os_mem_poison = 0xde7ec7ed;
|
||||
|
||||
static void
|
||||
os_mempool_poison(void *start, int sz)
|
||||
{
|
||||
int i;
|
||||
char *p = start;
|
||||
|
||||
for (i = sizeof(struct os_memblock); i < sz;
|
||||
i = i + sizeof(os_mem_poison)) {
|
||||
memcpy(p + i, &os_mem_poison, min(sizeof(os_mem_poison), sz - i));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
os_mempool_poison_check(void *start, int sz)
|
||||
{
|
||||
int i;
|
||||
char *p = start;
|
||||
|
||||
for (i = sizeof(struct os_memblock); i < sz;
|
||||
i = i + sizeof(os_mem_poison)) {
|
||||
assert(!memcmp(p + i, &os_mem_poison,
|
||||
min(sizeof(os_mem_poison), sz - i)));
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define os_mempool_poison(start, sz)
|
||||
#define os_mempool_poison_check(start, sz)
|
||||
#endif
|
||||
|
||||
os_error_t
|
||||
os_mempool_init(struct os_mempool *mp, uint16_t blocks, uint32_t block_size,
|
||||
void *membuf, char *name)
|
||||
{
|
||||
int true_block_size;
|
||||
uint8_t *block_addr;
|
||||
struct os_memblock *block_ptr;
|
||||
|
||||
/* Check for valid parameters */
|
||||
if (!mp || (blocks < 0) || (block_size <= 0)) {
|
||||
return OS_INVALID_PARM;
|
||||
}
|
||||
|
||||
if ((!membuf) && (blocks != 0)) {
|
||||
return OS_INVALID_PARM;
|
||||
}
|
||||
|
||||
if (membuf != NULL) {
|
||||
/* Blocks need to be sized properly and memory buffer should be
|
||||
* aligned
|
||||
*/
|
||||
if (((uint32_t)membuf & (OS_ALIGNMENT - 1)) != 0) {
|
||||
return OS_MEM_NOT_ALIGNED;
|
||||
}
|
||||
}
|
||||
true_block_size = OS_MEM_TRUE_BLOCK_SIZE(block_size);
|
||||
|
||||
/* Initialize the memory pool structure */
|
||||
mp->mp_block_size = block_size;
|
||||
mp->mp_num_free = blocks;
|
||||
mp->mp_min_free = blocks;
|
||||
mp->mp_flags = 0;
|
||||
mp->mp_num_blocks = blocks;
|
||||
mp->mp_membuf_addr = (uint32_t)membuf;
|
||||
mp->name = name;
|
||||
os_mempool_poison(membuf, true_block_size);
|
||||
SLIST_FIRST(mp) = membuf;
|
||||
|
||||
/* Chain the memory blocks to the free list */
|
||||
block_addr = (uint8_t *)membuf;
|
||||
block_ptr = (struct os_memblock *)block_addr;
|
||||
while (blocks > 1) {
|
||||
block_addr += true_block_size;
|
||||
os_mempool_poison(block_addr, true_block_size);
|
||||
SLIST_NEXT(block_ptr, mb_next) = (struct os_memblock *)block_addr;
|
||||
block_ptr = (struct os_memblock *)block_addr;
|
||||
--blocks;
|
||||
}
|
||||
|
||||
/* Last one in the list should be NULL */
|
||||
SLIST_NEXT(block_ptr, mb_next) = NULL;
|
||||
|
||||
STAILQ_INSERT_TAIL(&g_os_mempool_list, mp, mp_list);
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_error_t
|
||||
os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
|
||||
uint32_t block_size, void *membuf, char *name)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = os_mempool_init(&mpe->mpe_mp, blocks, block_size, membuf, name);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
mpe->mpe_mp.mp_flags = OS_MEMPOOL_F_EXT;
|
||||
mpe->mpe_put_cb = NULL;
|
||||
mpe->mpe_put_arg = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
os_mempool_is_sane(const struct os_mempool *mp)
|
||||
{
|
||||
struct os_memblock *block;
|
||||
|
||||
/* Verify that each block in the free list belongs to the mempool. */
|
||||
SLIST_FOREACH(block, mp, mb_next) {
|
||||
if (!os_memblock_from(mp, block)) {
|
||||
return false;
|
||||
}
|
||||
os_mempool_poison_check(block, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
os_memblock_from(const struct os_mempool *mp, const void *block_addr)
|
||||
{
|
||||
uint32_t true_block_size;
|
||||
uint32_t baddr32;
|
||||
uint32_t end;
|
||||
|
||||
_Static_assert(sizeof block_addr == sizeof baddr32,
|
||||
"Pointer to void must be 32-bits.");
|
||||
|
||||
baddr32 = (uint32_t)block_addr;
|
||||
true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
|
||||
end = mp->mp_membuf_addr + (mp->mp_num_blocks * true_block_size);
|
||||
|
||||
/* Check that the block is in the memory buffer range. */
|
||||
if ((baddr32 < mp->mp_membuf_addr) || (baddr32 >= end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* All freed blocks should be on true block size boundaries! */
|
||||
if (((baddr32 - mp->mp_membuf_addr) % true_block_size) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *
|
||||
os_memblock_get(struct os_mempool *mp)
|
||||
{
|
||||
os_sr_t sr;
|
||||
struct os_memblock *block;
|
||||
|
||||
/* Check to make sure they passed in a memory pool (or something) */
|
||||
block = NULL;
|
||||
if (mp) {
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
/* Check for any free */
|
||||
if (mp->mp_num_free) {
|
||||
/* Get a free block */
|
||||
block = SLIST_FIRST(mp);
|
||||
|
||||
os_mempool_poison_check(block, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
|
||||
|
||||
/* Set new free list head */
|
||||
SLIST_FIRST(mp) = SLIST_NEXT(block, mb_next);
|
||||
|
||||
/* Decrement number free by 1 */
|
||||
mp->mp_num_free--;
|
||||
if (mp->mp_min_free > mp->mp_num_free) {
|
||||
mp->mp_min_free = mp->mp_num_free;
|
||||
}
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
return (void *)block;
|
||||
}
|
||||
|
||||
os_error_t
|
||||
os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr)
|
||||
{
|
||||
os_sr_t sr;
|
||||
struct os_memblock *block;
|
||||
|
||||
os_mempool_poison(block_addr, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
|
||||
|
||||
block = (struct os_memblock *)block_addr;
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
/* Chain current free list pointer to this block; make this block head */
|
||||
SLIST_NEXT(block, mb_next) = SLIST_FIRST(mp);
|
||||
SLIST_FIRST(mp) = block;
|
||||
|
||||
/* XXX: Should we check that the number free <= number blocks? */
|
||||
/* Increment number free */
|
||||
mp->mp_num_free++;
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
os_error_t
|
||||
os_memblock_put(struct os_mempool *mp, void *block_addr)
|
||||
{
|
||||
struct os_mempool_ext *mpe;
|
||||
int rc;
|
||||
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
|
||||
struct os_memblock *block;
|
||||
#endif
|
||||
|
||||
/* Make sure parameters are valid */
|
||||
if ((mp == NULL) || (block_addr == NULL)) {
|
||||
return OS_INVALID_PARM;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
|
||||
/* Check that the block we are freeing is a valid block! */
|
||||
assert(os_memblock_from(mp, block_addr));
|
||||
|
||||
/*
|
||||
* Check for duplicate free.
|
||||
*/
|
||||
SLIST_FOREACH(block, mp, mb_next) {
|
||||
assert(block != (struct os_memblock *)block_addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If this is an extended mempool with a put callback, call the callback
|
||||
* instead of freeing the block directly.
|
||||
*/
|
||||
if (mp->mp_flags & OS_MEMPOOL_F_EXT) {
|
||||
mpe = (struct os_mempool_ext *)mp;
|
||||
if (mpe->mpe_put_cb != NULL) {
|
||||
rc = mpe->mpe_put_cb(mpe, block_addr, mpe->mpe_put_arg);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* No callback; free the block. */
|
||||
return os_memblock_put_from_cb(mp, block_addr);
|
||||
}
|
||||
|
||||
struct os_mempool *
|
||||
os_mempool_info_get_next(struct os_mempool *mp, struct os_mempool_info *omi)
|
||||
{
|
||||
struct os_mempool *cur;
|
||||
|
||||
if (mp == NULL) {
|
||||
cur = STAILQ_FIRST(&g_os_mempool_list);
|
||||
} else {
|
||||
cur = STAILQ_NEXT(mp, mp_list);
|
||||
}
|
||||
|
||||
if (cur == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
omi->omi_block_size = cur->mp_block_size;
|
||||
omi->omi_num_blocks = cur->mp_num_blocks;
|
||||
omi->omi_num_free = cur->mp_num_free;
|
||||
omi->omi_min_free = cur->mp_min_free;
|
||||
strncpy(omi->omi_name, cur->name, sizeof(omi->omi_name));
|
||||
|
||||
return (cur);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "os/os.h"
|
||||
#include "mem/mem.h"
|
||||
|
||||
#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
|
||||
#define SYSINIT_MSYS_1_MEMBLOCK_SIZE \
|
||||
OS_ALIGN(MYNEWT_VAL(MSYS_1_BLOCK_SIZE), 4)
|
||||
#define SYSINIT_MSYS_1_MEMPOOL_SIZE \
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_1_BLOCK_COUNT), \
|
||||
SYSINIT_MSYS_1_MEMBLOCK_SIZE)
|
||||
static os_membuf_t os_msys_init_1_data[SYSINIT_MSYS_1_MEMPOOL_SIZE];
|
||||
static struct os_mbuf_pool os_msys_init_1_mbuf_pool;
|
||||
static struct os_mempool os_msys_init_1_mempool;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
|
||||
#define SYSINIT_MSYS_2_MEMBLOCK_SIZE \
|
||||
OS_ALIGN(MYNEWT_VAL(MSYS_2_BLOCK_SIZE), 4)
|
||||
#define SYSINIT_MSYS_2_MEMPOOL_SIZE \
|
||||
OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_2_BLOCK_COUNT), \
|
||||
SYSINIT_MSYS_2_MEMBLOCK_SIZE)
|
||||
static os_membuf_t os_msys_init_2_data[SYSINIT_MSYS_2_MEMPOOL_SIZE];
|
||||
static struct os_mbuf_pool os_msys_init_2_mbuf_pool;
|
||||
static struct os_mempool os_msys_init_2_mempool;
|
||||
#endif
|
||||
|
||||
static void
|
||||
os_msys_init_once(void *data, struct os_mempool *mempool,
|
||||
struct os_mbuf_pool *mbuf_pool,
|
||||
int block_count, int block_size, char *name)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = mem_init_mbuf_pool(data, mempool, mbuf_pool, block_count, block_size,
|
||||
name);
|
||||
assert(rc == 0);
|
||||
|
||||
rc = os_msys_register(mbuf_pool);
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
void
|
||||
os_msys_init(void)
|
||||
{
|
||||
os_msys_reset();
|
||||
|
||||
(void)os_msys_init_once;
|
||||
#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
|
||||
os_msys_init_once(os_msys_init_1_data,
|
||||
&os_msys_init_1_mempool,
|
||||
&os_msys_init_1_mbuf_pool,
|
||||
MYNEWT_VAL(MSYS_1_BLOCK_COUNT),
|
||||
SYSINIT_MSYS_1_MEMBLOCK_SIZE,
|
||||
"msys_1");
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
|
||||
os_msys_init_once(os_msys_init_2_data,
|
||||
&os_msys_init_2_mempool,
|
||||
&os_msys_init_2_mbuf_pool,
|
||||
MYNEWT_VAL(MSYS_2_BLOCK_COUNT),
|
||||
SYSINIT_MSYS_2_MEMBLOCK_SIZE,
|
||||
"msys_2");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef _NIMBLE_NPL_OS_H_
|
||||
#define _NIMBLE_NPL_OS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_NPL_OS_ALIGNMENT 4
|
||||
|
||||
#define BLE_NPL_TIME_FOREVER UINT32_MAX
|
||||
|
||||
typedef uint32_t ble_npl_time_t;
|
||||
typedef int32_t ble_npl_stime_t;
|
||||
|
||||
struct ble_npl_event {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
struct ble_npl_eventq {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
struct ble_npl_callout {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
struct ble_npl_mutex {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
struct ble_npl_sem {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NPL_H_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user