Merge pull request #72 from andrzej-kaczmarek/porting-wip

Porting NimBLE
This commit is contained in:
Andrzej Kaczmarek
2018-05-09 10:07:04 +02:00
committed by GitHub
107 changed files with 15207 additions and 287 deletions
+3
View File
@@ -0,0 +1,3 @@
# Dummy NPL build
*.o
/porting/examples/dummy/dummy
+15
View File
@@ -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
+61
View File
@@ -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.
================================================================================
+71
View File
@@ -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/
================================================================================
+1
View File
@@ -0,0 +1 @@
0.2.8
+352
View File
@@ -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
+130
View File
@@ -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__ */
+151
View File
@@ -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__ */
+211
View File
@@ -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__ */
+194
View File
@@ -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__ */
+108
View File
@@ -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__ */
+166
View File
@@ -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__ */
+545
View File
@@ -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__ */
+131
View File
@@ -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__ */
+139
View File
@@ -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_ */
+139
View File
@@ -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__*/
+164
View File
@@ -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__ */
+129
View File
@@ -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__ */
+95
View File
@@ -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__ */
+164
View File
@@ -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;
}
+191
View File
@@ -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;
}
+114
View File
@@ -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;
}
+266
View File
@@ -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;
}
}
+254
View File
@@ -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;
}
+85
View File
@@ -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;
}
+283
View File
@@ -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;
}
}
+942
View File
@@ -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;
}
+200
View File
@@ -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;
}
+295
View File
@@ -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);
}
+105
View File
@@ -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 */
+148
View File
@@ -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;
}
+212
View File
@@ -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;
}
+217
View File
@@ -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;
}
+74
View File
@@ -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)
+26 -26
View File
@@ -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();
+23 -25
View File
@@ -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)
+16 -18
View File
@@ -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);
+4 -4
View File
@@ -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);
}
}
+1 -1
View File
@@ -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);
+9 -9
View File
@@ -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));
}
}
}
+9 -10
View File
@@ -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;
+13 -13
View File
@@ -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 */
+7 -8
View File
@@ -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 */
+9
View File
@@ -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;
}
+12 -3
View File
@@ -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 */
+3 -4
View File
@@ -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
+4 -4
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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);
+9 -9
View File
@@ -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
View File
@@ -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");
+2 -2
View File
@@ -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();
+1 -1
View File
@@ -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
+10 -10
View File
@@ -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);
}
+82
View File
@@ -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);
}
+10 -1
View File
@@ -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
+1 -1
View File
@@ -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
+7 -6
View File
@@ -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. */
+15 -15
View File
@@ -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;
}
+6 -6
View File
@@ -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. */
+1 -1
View File
@@ -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;
+2 -4
View File
@@ -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)
+199
View File
@@ -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_ */
+1
View File
@@ -26,4 +26,5 @@ pkg.keywords:
- bluetooth
pkg.deps:
- porting/npl/mynewt
- "@apache-mynewt-core/kernel/os"
+35
View File
@@ -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 $@ $^
+8
View File
@@ -0,0 +1,8 @@
#include "nimble/nimble_port.h"
int main(int argc, char **argv)
{
nimble_port_init();
return 0;
}
+30
View File
@@ -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 \
+96
View File
@@ -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)
+10
View File
@@ -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 \
+173
View File
@@ -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
*/
+45
View File
@@ -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__ */
+68
View File
@@ -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 */
+225
View File
@@ -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
+60
View File
@@ -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 */
+240
View File
@@ -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
*/
+43
View File
@@ -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
+627
View File
@@ -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
*/
+255
View File
@@ -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
*/
+54
View File
@@ -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
+522
View File
@@ -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_ */
+80
View File
@@ -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__ */
+886
View File
@@ -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
+37
View File
@@ -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__ */
+43
View File
@@ -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"
+218
View File
@@ -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];
}
}
+840
View File
@@ -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;
}
+302
View File
@@ -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;
}
+74
View File
@@ -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
+126
View File
@@ -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;
}
+109
View File
@@ -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
+303
View File
@@ -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);
}
+84
View File
@@ -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