ext: Pull in tinycrypt v0.2.6
Zephyr 1.9 moves to tinycrypt v0.2.7. This introduces a breaking API
change. This makes things challenging for mcuboot, which would like to
be able to work across multiple platforms.
To help with this, bring in the last working version of Tinycrypt v0.2.6
from https://github.com/01org/tinycrypt. Tinycrypt is released under a
3-clause BSD-style license, with parts under the micro-ecc license,
which is a 2-clause license. Please see ext/tinycrypt/LICENSE for
details.
Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/ext/tinycrypt/lib/Makefile b/ext/tinycrypt/lib/Makefile
new file mode 100644
index 0000000..ee831e8
--- /dev/null
+++ b/ext/tinycrypt/lib/Makefile
@@ -0,0 +1,39 @@
+################################################################################
+#
+# Copyright (C) 2015 by Intel Corporation, All Rights Reserved.
+#
+# Cryptographic Primitives Makefile.
+#
+################################################################################
+
+include ../config.mk
+
+# Edit the OBJS content to add/remove primitives needed from TinyCrypt library:
+OBJS:=aes_decrypt.o \
+ aes_encrypt.o \
+ cbc_mode.o \
+ ctr_mode.o \
+ ctr_prng.o \
+ hmac.o \
+ hmac_prng.o \
+ sha256.o \
+ ecc.o \
+ ecc_dh.o \
+ ecc_dsa.o \
+ ccm_mode.o \
+ cmac_mode.o \
+ utils.o
+
+DEPS:=$(OBJS:.o=.d)
+
+all: libtinycrypt.a
+
+libtinycrypt.a: $(OBJS)
+ $(AR) $(ARFLAGS) $@ $^
+
+.PHONY: clean
+
+clean:
+ -$(RM) *.exe $(OBJS) $(DEPS) *~ libtinycrypt.a
+
+-include $(DEPS)
diff --git a/ext/tinycrypt/lib/include/tinycrypt/aes.h b/ext/tinycrypt/lib/include/tinycrypt/aes.h
new file mode 100644
index 0000000..b6dbbb5
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/aes.h
@@ -0,0 +1,133 @@
+/* aes.h - TinyCrypt interface to an AES-128 implementation */
+
+/*
+ * Copyright (C) 2015 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)
+
+struct tc_aes_key_sched_struct {
+ uint32_t words[Nb*(Nr+1)];
+};
+typedef struct tc_aes_key_sched_struct *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
+ */
+int32_t 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
+ */
+int32_t 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
+ */
+int32_t 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
+ */
+int32_t tc_aes_decrypt(uint8_t *out,
+ const uint8_t *in,
+ const TCAesKeySched_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/cbc_mode.h b/ext/tinycrypt/lib/include/tinycrypt/cbc_mode.h
new file mode 100644
index 0000000..74d2914
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/cbc_mode.h
@@ -0,0 +1,151 @@
+/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */
+
+/*
+ * Copyright (C) 2015 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
+ */
+int32_t tc_cbc_mode_encrypt(uint8_t *out, uint32_t outlen, const uint8_t *in,
+ uint32_t 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
+ *
+ */
+int32_t tc_cbc_mode_decrypt(uint8_t *out, uint32_t outlen, const uint8_t *in,
+ uint32_t inlen, const uint8_t *iv,
+ const TCAesKeySched_t sched);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/ccm_mode.h b/ext/tinycrypt/lib/include/tinycrypt/ccm_mode.h
new file mode 100644
index 0000000..9fa5915
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/ccm_mode.h
@@ -0,0 +1,201 @@
+/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */
+
+/*
+ * Copyright (C) 2015 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 */
+ uint32_t 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)
+ */
+int32_t tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
+ uint32_t nlen, uint32_t 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)
+ *
+ * @param out OUT -- encrypted 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: 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
+ */
+int32_t tc_ccm_generation_encryption(uint8_t *out, const uint8_t *associated_data,
+ uint32_t alen, const uint8_t *payload,
+ uint32_t 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)
+ *
+ * @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: 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
+ */
+int32_t tc_ccm_decryption_verification(uint8_t *out, const uint8_t *associated_data,
+ uint32_t alen, const uint8_t *payload, uint32_t plen,
+ TCCcmMode_t c);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/cmac_mode.h b/ext/tinycrypt/lib/include/tinycrypt/cmac_mode.h
new file mode 100644
index 0000000..9d3f130
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/cmac_mode.h
@@ -0,0 +1,194 @@
+/* cmac_mode.h -- interface to a CMAC implementation */
+
+/*
+ * Copyright (C) 2015 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 */
+ uint32_t keyid;
+/* next available leftover location */
+ uint32_t 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
+ */
+int32_t 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
+ */
+int32_t 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
+ */
+int32_t 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
+ */
+int32_t 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
+ */
+int32_t tc_cmac_final(uint8_t *tag, TCCmacState_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/constants.h b/ext/tinycrypt/lib/include/tinycrypt/constants.h
new file mode 100644
index 0000000..1a7c9df
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/constants.h
@@ -0,0 +1,59 @@
+/* constants.h - TinyCrypt interface to constants */
+
+/*
+ * Copyright (C) 2015 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
+
+#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
diff --git a/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h b/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h
new file mode 100644
index 0000000..5f7766d
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/ctr_mode.h
@@ -0,0 +1,108 @@
+/* ctr_mode.h - TinyCrypt interface to CTR mode */
+
+/*
+ * Copyright (C) 2015 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
+ */
+int32_t tc_ctr_mode(uint8_t *out, uint32_t outlen, const uint8_t *in,
+ uint32_t inlen, uint8_t *ctr, const TCAesKeySched_t sched);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/ctr_prng.h b/ext/tinycrypt/lib/include/tinycrypt/ctr_prng.h
new file mode 100644
index 0000000..12cac8f
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/ctr_prng.h
@@ -0,0 +1,167 @@
+/* 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
+ *
+ */
+int32_t tc_ctr_prng_init(TCCtrPrng_t * const ctx,
+ uint8_t const * const entropy,
+ uint32_t entropyLen,
+ uint8_t const * const personalization,
+ uint32_t 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
+ */
+int32_t tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
+ uint8_t const * const entropy,
+ uint32_t entropyLen,
+ uint8_t const * const additional_input,
+ uint32_t 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
+ */
+int32_t tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
+ uint8_t const * const additional_input,
+ uint32_t additionallen,
+ uint8_t * const out,
+ uint32_t 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
diff --git a/ext/tinycrypt/lib/include/tinycrypt/ecc.h b/ext/tinycrypt/lib/include/tinycrypt/ecc.h
new file mode 100644
index 0000000..74324f9
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/ecc.h
@@ -0,0 +1,357 @@
+/* ecc.h - TinyCrypt interface to ECC auxiliary functions */
+
+/*
+ * =============================================================================
+ * Copyright (c) 2013, 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.
+ *
+ * =============================================================================
+ * Copyright (C) 2015 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 ECC auxiliary functions.
+ *
+ * Overview: This software is an implementation of auxiliary 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_ECC_H__
+#define __TC_ECC_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Word size (4 bytes considering 32-bits architectures) */
+#define WORD_SIZE 4
+/* Number of words of 32 bits to represent an element of the the curve p-256: */
+#define NUM_ECC_DIGITS 8
+/* Number of bytes to represent an element of the the curve p-256: */
+#define NUM_ECC_BYTES (WORD_SIZE*NUM_ECC_DIGITS)
+
+/* struct to represent a point of the curve (uses X and Y coordinates): */
+typedef struct EccPoint {
+ uint32_t x[NUM_ECC_DIGITS];
+ uint32_t y[NUM_ECC_DIGITS];
+} EccPoint;
+
+/* struct to represent a point of the curve in Jacobian coordinates
+ * (uses X, Y and Z coordinates):
+ */
+typedef struct EccPointJacobi {
+ uint32_t X[NUM_ECC_DIGITS];
+ uint32_t Y[NUM_ECC_DIGITS];
+ uint32_t Z[NUM_ECC_DIGITS];
+} EccPointJacobi;
+
+/*
+ * @brief Check if p_vli is zero.
+ * @return returns non-zero if p_vli == 0, zero otherwise.
+ *
+ * @param p_native OUT -- will be filled in with the native integer value.
+ * @param p_bytes IN -- standard octet representation of the integer to convert.
+ *
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+uint32_t vli_isZero(uint32_t *p_vli);
+
+/*
+ * @brief Set the content of p_src in p_dest.
+ *
+ * @param p_dest OUT -- Destination buffer.
+ * @param p_src IN -- Origin buffer.
+ *
+ */
+void vli_set(uint32_t *p_dest, uint32_t *p_src);
+
+/*
+ * @brief Computes the sign of p_left - p_right.
+ * @return returns the sign of p_left - p_right.
+ *
+ * @param p_left IN -- buffer to be compared.
+ * @param p_right IN -- buffer to be compared.
+ * @param word_size IN -- size of the word.
+ *
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+int32_t vli_cmp(uint32_t *p_left, uint32_t *p_right, int32_t word_size);
+
+/*
+ * @brief Computes p_result = p_left - p_right, returns borrow.
+ * @return returns the sign of p_left - p_right.
+ *
+ * @param p_result IN -- buffer to be compared.
+ * @param p_left IN -- buffer p_left in (p_left - p_right).
+ * @param p_right IN -- buffer p_right in (p_left - p_right).
+ * @param word_size IN -- size of the word.
+ *
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ * @note Can modify in place.
+ */
+uint32_t vli_sub(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
+ uint32_t word_size);
+
+/*
+ * @brief Conditional set: sets either 'p_true' or 'p_false' to 'output',
+ * depending on the value of 'cond'.
+ *
+ * @param output OUT -- result buffer after setting either p_true or p_false.
+ * @param p_true IN -- buffer to be used if cond is true.
+ * @param p_false IN -- buffer to be used if cond is false.
+ * @param cond IN -- boolean value that will determine which value will be set
+ * to output.
+ */
+void vli_cond_set(uint32_t *output, uint32_t *p_true, uint32_t *p_false,
+ uint32_t cond);
+
+/*
+ * @brief Computes p_result = (p_left + p_right) % p_mod.
+ *
+ * @param p_result OUT -- result buffer.
+ * @param p_left IN -- buffer p_left in (p_left + p_right) % p_mod.
+ * @param p_right IN -- buffer p_right in (p_left + p_right) % p_mod.
+ * @param p_mod IN -- module.
+ *
+ * @note Assumes that p_left < p_mod and p_right < p_mod, p_result != p_mod.
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+void vli_modAdd(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
+ uint32_t *p_mod);
+
+/*
+ * @brief Computes p_result = (p_left - p_right) % p_mod.
+ *
+ * @param p_result OUT -- result buffer.
+ * @param p_left IN -- buffer p_left in (p_left - p_right) % p_mod.
+ * @param p_right IN -- buffer p_right in (p_left - p_right) % p_mod.
+ * @param p_mod IN -- module.
+ *
+ * @note Assumes that p_left < p_mod and p_right < p_mod, p_result != p_mod.
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+void vli_modSub(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
+ uint32_t *p_mod);
+
+/*
+ * @brief Computes p_result = (p_left * p_right) % curve_p.
+ *
+ * @param p_result OUT -- result buffer.
+ * @param p_left IN -- buffer p_left in (p_left * p_right) % curve_p.
+ * @param p_right IN -- buffer p_right in (p_left * p_right) % curve_p.
+ */
+void vli_modMult_fast(uint32_t *p_result, uint32_t *p_left,
+ uint32_t *p_right);
+
+/*
+ * @brief Computes p_result = p_left^2 % curve_p.
+ *
+ * @param p_result OUT -- result buffer.
+ * @param p_left IN -- buffer p_left in (p_left^2 % curve_p).
+ */
+void vli_modSquare_fast(uint32_t *p_result, uint32_t *p_left);
+
+/*
+ * @brief Computes p_result = (p_left * p_right) % p_mod.
+ *
+ * @param p_result OUT -- result buffer.
+ * @param p_left IN -- buffer p_left in (p_left * p_right) % p_mod.
+ * @param p_right IN -- buffer p_right in (p_left * p_right) % p_mod.
+ * @param p_mod IN -- module.
+ * @param p_barrett IN -- used for Barrett reduction.
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+void vli_modMult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
+ uint32_t *p_mod, uint32_t *p_barrett);
+
+/*
+ * @brief Computes modular inversion: (1/p_intput) % p_mod.
+ *
+ * @param p_result OUT -- result buffer.
+ * @param p_input IN -- buffer p_input in (1/p_intput) % p_mod.
+ * @param p_mod IN -- module.
+ * @param p_barrett IN -- used for Barrett reduction.
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+void vli_modInv(uint32_t *p_result, uint32_t *p_input,
+ uint32_t *p_mod, uint32_t *p_barrett);
+
+/*
+ * @brief modular reduction based on Barrett's method
+ * @param p_result OUT -- p_product % p_mod.
+ * @param p_product IN -- buffer p_product in (p_product % p_mod).
+ * @param p_mod IN -- buffer p_mod in (p_product % p_mod).
+ * @param p_barrett -- used for Barrett reduction.
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+void vli_mmod_barrett(
+ uint32_t *p_result,
+ uint32_t *p_product,
+ uint32_t *p_mod,
+ uint32_t *p_barrett);
+
+/*
+ * @brief Check if a point is zero.
+ * @return Returns 1 if p_point is the point at infinity, 0 otherwise.
+ *
+ * @param p_point IN -- point to be checked.
+ */
+uint32_t EccPoint_isZero(EccPoint *p_point);
+
+/*
+ * @brief Check if point in Jacobi coordinates is zero.
+ * @return Returns 1 if p_point_jacobi is the point at infinity, 0 otherwise.
+ *
+ * @param p_point IN -- point to be checked.
+ */
+uint32_t EccPointJacobi_isZero(EccPointJacobi *p_point_jacobi);
+
+/*
+ * @brief Conversion from Jacobi coordinates to Affine coordinates.
+ *
+ * @param p_point OUT -- point in Affine coordinates.
+ * @param p_point_jacobi OUT -- point in Jacobi coordinates.
+ */
+void EccPoint_toAffine(EccPoint *p_point, EccPointJacobi *p_point_jacobi);
+
+/*
+ * @brief Elliptic curve point addition in Jacobi coordinates: P1 = P1 + P2.
+ *
+ * @param P1 IN/OUT -- P1 in P1 = P1 + P2.
+ * @param P2 IN -- P2 in P1 = P1 + P2.
+ */
+void EccPoint_add(EccPointJacobi *P1, EccPointJacobi *P2);
+
+/*
+ * @brief Elliptic curve scalar multiplication with result in Jacobi coordinates
+ *
+ * @param p_result OUT -- Product of p_point by p_scalar.
+ * @param p_point IN -- Elliptic curve point
+ * @param p_scalar IN -- Scalar integer
+ * @note Side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+void EccPoint_mult_safe(EccPointJacobi *p_result, EccPoint *p_point,
+ uint32_t *p_scalar);
+
+/*
+ * @brief Fast elliptic curve scalar multiplication with result in Jacobi
+ * coordinates
+ * @note non constant time
+ * @param p_result OUT -- Product of p_point by p_scalar.
+ * @param p_point IN -- Elliptic curve point
+ * @param p_scalar IN -- Scalar integer
+ * @note algorithm NOT strengthened against timing attack.
+ */
+void EccPoint_mult_unsafe(
+ EccPointJacobi *p_result,
+ EccPoint *p_point,
+ uint32_t *p_scalar);
+
+/*
+ * @brief Convert an integer in standard octet representation to native format.
+ * @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)
+ *
+ * @param p_native OUT -- will be filled in with the native integer value.
+ * @param p_bytes IN -- standard octet representation of the integer to convert.
+ *
+ */
+void ecc_bytes2native(uint32_t p_native[NUM_ECC_DIGITS],
+ uint8_t p_bytes[NUM_ECC_DIGITS*4]);
+
+
+/*
+ * @brief Convert an integer in native format to standard octet representation.
+ * @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)
+ *
+ * @param p_bytes OUT -- will be filled in with the standard octet
+ * representation of the integer.
+ * @param p_native IN -- native integer value to convert.
+ *
+ */
+void ecc_native2bytes(uint8_t p_bytes[NUM_ECC_DIGITS*4],
+ uint32_t p_native[NUM_ECC_DIGITS]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/ecc_dh.h b/ext/tinycrypt/lib/include/tinycrypt/ecc_dh.h
new file mode 100644
index 0000000..778fee2
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/ecc_dh.h
@@ -0,0 +1,142 @@
+/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */
+
+/*
+ * =============================================================================
+ * Copyright (c) 2013, 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.
+ *
+ * =============================================================================
+ * Copyright (C) 2015 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 key pair was generated successfully
+ * returns TC_CRYPTO_FAIL (0) if:
+ * the private key is 0
+ *
+ * @param p_publicKey OUT -- the point representing the public key.
+ * @param p_privateKey OUT -- the private key.
+ * @param p_random IN -- The random number to use to generate the key pair.
+ *
+ * @note You must use a new non-predictable random number to generate each
+ * new key pair.
+ * @note p_random must have NUM_ECC_DIGITS*2 bits of entropy to eliminate
+ * bias in keys.
+ *
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+int32_t ecc_make_key(EccPoint *p_publicKey,
+ uint32_t p_privateKey[NUM_ECC_DIGITS],
+ uint32_t p_random[2 * NUM_ECC_DIGITS]);
+
+/**
+ * @brief Determine whether or not a given point is on the chosen elliptic curve
+ * (ie, is a valid public key).
+ * @return returns 0 if the given point is valid
+ * returns -1 if: the point is zero
+ * returns -2 if: curve_p - p_publicKey->x != 1 or
+ * curve_p - p_publicKey->y != 1
+ * returns -3 if: y^2 != x^3 + ax + b
+ * returns -4 if: public key is the group generator
+ *
+ * @param p_publicKey IN -- The point to be checked.
+ */
+int32_t ecc_valid_public_key(EccPoint *p_publicKey);
+
+/**
+ * @brief Compute a shared secret given your secret key and someone else's
+ * public key.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the secret was computed successfully
+ * returns TC_CRYPTO_FAIL (0) otherwise
+ *
+ * @param p_secret OUT -- The shared secret value.
+ * @param p_publicKey IN -- The public key of the remote party.
+ * @param p_privateKey IN -- Your private key.
+ *
+ * @note Optionally, you can provide a random multiplier for resistance to DPA
+ * attacks. The random multiplier should probably be different for each
+ * invocation of ecdh_shared_secret().
+ *
+ * @warning It is recommended to use the output of ecdh_shared_secret() as the
+ * input of a recommended Key Derivation Function (see NIST SP 800-108) in
+ * order to produce a symmetric key.
+ */
+int32_t ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey,
+ uint32_t p_privateKey[NUM_ECC_DIGITS]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/ecc_dsa.h b/ext/tinycrypt/lib/include/tinycrypt/ecc_dsa.h
new file mode 100644
index 0000000..a037fa5
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/ecc_dsa.h
@@ -0,0 +1,135 @@
+/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
+
+/*
+ * =============================================================================
+ * Copyright (c) 2013, 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.
+ *
+ * =============================================================================
+ * Copyright (C) 2015 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 the signature generated successfully
+ * returns TC_CRYPTO_FAIL (0) if:
+ * r == 0 or
+ * p_random == 0
+ *
+ * @param r OUT -- to be filled with the signature values.
+ * @param s OUT -- to be filled with the signature values.
+ * @param p_privateKey IN -- Your private key.
+ * @param p_random IN -- The random number to use in generating ephemeral DSA
+ * keys.
+ * @param p_hash IN -- The message hash to sign.
+ *
+ * @note p_random must have NUM_ECC_DIGITS*2 bits of entropy to eliminate
+ * bias in keys.
+ *
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+int32_t ecdsa_sign(uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS],
+ uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS * 2],
+ uint32_t p_hash[NUM_ECC_DIGITS]);
+
+
+/**
+ * @brief Verify an ECDSA signature.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the the signature generated successfully
+ * returns TC_CRYPTO_FAIL (0) if:
+ * r == 0 or
+ * p_random == 0
+ *
+ * @param p_publicKey IN -- The signer's public key.
+ * @param p_hash IN -- The hash of the signed data.
+ * @param r IN -- The signature values.
+ * @param s IN -- The signature values.
+ *
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+int32_t ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS],
+ uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/hmac.h b/ext/tinycrypt/lib/include/tinycrypt/hmac.h
new file mode 100644
index 0000000..26f6cfe
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/hmac.h
@@ -0,0 +1,141 @@
+/* hmac.h - TinyCrypt interface to an HMAC implementation */
+
+/*
+ * Copyright (C) 2015 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
+ */
+int32_t tc_hmac_set_key(TCHmacState_t ctx,
+ const uint8_t *key,
+ uint32_t 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
+ */
+int32_t 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
+ */
+int32_t tc_hmac_update(TCHmacState_t ctx,
+ const void *data,
+ uint32_t 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 must 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
+ */
+int32_t tc_hmac_final(uint8_t *tag, uint32_t taglen, TCHmacState_t ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/hmac_prng.h b/ext/tinycrypt/lib/include/tinycrypt/hmac_prng.h
new file mode 100644
index 0000000..b631c2c
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/hmac_prng.h
@@ -0,0 +1,164 @@
+/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */
+
+/*
+ * Copyright (C) 2015 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 */
+ uint32_t 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
+ */
+int32_t tc_hmac_prng_init(TCHmacPrng_t prng,
+ const uint8_t *personalization,
+ uint32_t 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
+ */
+int32_t tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed,
+ uint32_t seedlen, const uint8_t *additional_input,
+ uint32_t 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
+ */
+int32_t tc_hmac_prng_generate(uint8_t *out, uint32_t outlen, TCHmacPrng_t prng);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/sha256.h b/ext/tinycrypt/lib/include/tinycrypt/sha256.h
new file mode 100644
index 0000000..d1e1f61
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/sha256.h
@@ -0,0 +1,131 @@
+/* sha256.h - TinyCrypt interface to a SHA-256 implementation */
+
+/*
+ * Copyright (C) 2015 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 {
+ uint32_t 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
+ */
+int32_t 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
+ */
+int32_t 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
+ */
+int32_t tc_sha256_final(uint8_t *digest, TCSha256State_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/include/tinycrypt/utils.h b/ext/tinycrypt/lib/include/tinycrypt/utils.h
new file mode 100644
index 0000000..429934e
--- /dev/null
+++ b/ext/tinycrypt/lib/include/tinycrypt/utils.h
@@ -0,0 +1,95 @@
+/* utils.h - TinyCrypt interface to platform-dependent run-time operations */
+
+/*
+ * Copyright (C) 2015 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
+ */
+uint32_t _copy(uint8_t *to, uint32_t to_len,
+ const uint8_t *from, uint32_t 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, uint32_t 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
+ */
+int32_t _compare(const uint8_t *a, const uint8_t *b, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ext/tinycrypt/lib/source/aes_decrypt.c b/ext/tinycrypt/lib/source/aes_decrypt.c
new file mode 100644
index 0000000..2e4e3bc
--- /dev/null
+++ b/ext/tinycrypt/lib/source/aes_decrypt.c
@@ -0,0 +1,164 @@
+/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */
+
+/*
+ * Copyright (C) 2015 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>
+
+#define ZERO_BYTE 0x00
+
+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
+};
+
+int32_t 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 uint32_t *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)
+{
+ uint32_t 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));
+}
+
+int32_t tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
+{
+ uint8_t state[Nk*Nb];
+ uint32_t 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 one byte state buffer */
+ _set(state, ZERO_BYTE, sizeof(state));
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/ext/tinycrypt/lib/source/aes_encrypt.c b/ext/tinycrypt/lib/source/aes_encrypt.c
new file mode 100644
index 0000000..6bc73a5
--- /dev/null
+++ b/ext/tinycrypt/lib/source/aes_encrypt.c
@@ -0,0 +1,191 @@
+/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */
+
+/*
+ * Copyright (C) 2015 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 uint32_t rotword(uint32_t 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))
+
+int32_t tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k)
+{
+ const uint32_t rconst[11] = {
+ 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
+ 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
+ };
+ uint32_t i;
+ uint32_t 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 uint32_t *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)
+{
+ uint32_t 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));
+}
+
+int32_t tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
+{
+ uint8_t state[Nk*Nb];
+ uint32_t 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;
+}
diff --git a/ext/tinycrypt/lib/source/cbc_mode.c b/ext/tinycrypt/lib/source/cbc_mode.c
new file mode 100644
index 0000000..8163e0d
--- /dev/null
+++ b/ext/tinycrypt/lib/source/cbc_mode.c
@@ -0,0 +1,113 @@
+/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */
+
+/*
+ * Copyright (C) 2015 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>
+
+int32_t tc_cbc_mode_encrypt(uint8_t *out, uint32_t outlen, const uint8_t *in,
+ uint32_t inlen, const uint8_t *iv,
+ const TCAesKeySched_t sched)
+{
+
+ uint8_t buffer[TC_AES_BLOCK_SIZE];
+ uint32_t 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;
+}
+
+int32_t tc_cbc_mode_decrypt(uint8_t *out, uint32_t outlen, const uint8_t *in,
+ uint32_t inlen, const uint8_t *iv,
+ const TCAesKeySched_t sched)
+{
+ uint8_t buffer[TC_AES_BLOCK_SIZE];
+ const uint8_t *p;
+ uint32_t 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;
+}
diff --git a/ext/tinycrypt/lib/source/ccm_mode.c b/ext/tinycrypt/lib/source/ccm_mode.c
new file mode 100644
index 0000000..7b6d485
--- /dev/null
+++ b/ext/tinycrypt/lib/source/ccm_mode.c
@@ -0,0 +1,260 @@
+/* ccm_mode.c - TinyCrypt implementation of CCM mode */
+
+/*
+ * Copyright (C) 2015 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>
+
+int32_t tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
+ uint32_t nlen, uint32_t 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, uint32_t dlen,
+ uint32_t flag, TCAesKeySched_t sched)
+{
+
+ uint32_t 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 int32_t ccm_ctr_mode(uint8_t *out, uint32_t outlen, const uint8_t *in,
+ uint32_t 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;
+ uint32_t 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;
+}
+
+int32_t tc_ccm_generation_encryption(uint8_t *out, const uint8_t *associated_data,
+ uint32_t alen, const uint8_t *payload,
+ uint32_t 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 */
+ return TC_CRYPTO_FAIL;
+ }
+
+ uint8_t b[Nb * Nk];
+ uint8_t tag[Nb * Nk];
+ uint32_t 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;
+}
+
+int32_t tc_ccm_decryption_verification(uint8_t *out, const uint8_t *associated_data,
+ uint32_t alen, const uint8_t *payload,
+ uint32_t 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 */
+ return TC_CRYPTO_FAIL;
+ }
+
+ uint8_t b[Nb * Nk];
+ uint8_t tag[Nb * Nk];
+ uint32_t 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) {
+ /* erase the decrypted buffer in case of mac validation failure: */
+ _set(out, 0, sizeof(*out));
+ return TC_CRYPTO_FAIL;
+ }
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/ext/tinycrypt/lib/source/cmac_mode.c b/ext/tinycrypt/lib/source/cmac_mode.c
new file mode 100644
index 0000000..3b31c3e
--- /dev/null
+++ b/ext/tinycrypt/lib/source/cmac_mode.c
@@ -0,0 +1,254 @@
+/* cmac_mode.c - TinyCrypt CMAC mode implementation */
+
+/*
+ * Copyright (C) 2015 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).*/
+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;
+ }
+}
+
+int32_t 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;
+}
+
+int32_t 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;
+}
+
+int32_t 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;
+}
+
+int32_t tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
+{
+ uint32_t 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;
+}
+
+int32_t tc_cmac_final(uint8_t *tag, TCCmacState_t s)
+{
+ uint8_t *k;
+ uint32_t 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;
+}
diff --git a/ext/tinycrypt/lib/source/ctr_mode.c b/ext/tinycrypt/lib/source/ctr_mode.c
new file mode 100644
index 0000000..7ba53d0
--- /dev/null
+++ b/ext/tinycrypt/lib/source/ctr_mode.c
@@ -0,0 +1,85 @@
+/* ctr_mode.c - TinyCrypt CTR mode implementation */
+
+/*
+ * Copyright (C) 2015 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>
+
+int32_t tc_ctr_mode(uint8_t *out, uint32_t outlen, const uint8_t *in,
+ uint32_t inlen, uint8_t *ctr, const TCAesKeySched_t sched)
+{
+
+ uint8_t buffer[TC_AES_BLOCK_SIZE];
+ uint8_t nonce[TC_AES_BLOCK_SIZE];
+ uint32_t block_num;
+ uint32_t 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;
+}
diff --git a/ext/tinycrypt/lib/source/ctr_prng.c b/ext/tinycrypt/lib/source/ctr_prng.c
new file mode 100644
index 0000000..bac81d8
--- /dev/null
+++ b/ext/tinycrypt/lib/source/ctr_prng.c
@@ -0,0 +1,308 @@
+/* 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[], uint32_t len)
+{
+ uint32_t 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];
+ uint32_t len = 0U;
+
+ /* 10.2.1.2 step 2 */
+ while (len < sizeof temp)
+ {
+ uint32_t 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)
+ {
+ uint32_t 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);
+ }
+}
+
+int32_t tc_ctr_prng_init(TCCtrPrng_t * const ctx,
+ uint8_t const * const entropy,
+ uint32_t entropyLen,
+ uint8_t const * const personalization,
+ uint32_t pLen)
+{
+ int32_t result = TC_CRYPTO_FAIL;
+ uint32_t 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 */
+ uint32_t 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;
+}
+
+int32_t tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
+ uint8_t const * const entropy,
+ uint32_t entropyLen,
+ uint8_t const * const additional_input,
+ uint32_t additionallen)
+{
+ uint32_t i;
+ int32_t 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 */
+ uint32_t 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);
+ }
+
+ uint32_t seedlen = (uint32_t)TC_AES_KEY_SIZE + (uint32_t)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;
+}
+
+int32_t tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
+ uint8_t const * const additional_input,
+ uint32_t additionallen,
+ uint8_t * const out,
+ uint32_t 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 uint32_t MAX_BYTES_PER_REQ = 65536U;
+
+ int32_t 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 */
+ uint32_t 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 */
+ uint32_t len = 0U;
+ while (len < outlen)
+ {
+ uint32_t 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;
+ }
+}
+
+
+
+
diff --git a/ext/tinycrypt/lib/source/ecc.c b/ext/tinycrypt/lib/source/ecc.c
new file mode 100644
index 0000000..bfe6c5f
--- /dev/null
+++ b/ext/tinycrypt/lib/source/ecc.c
@@ -0,0 +1,625 @@
+/* ecc.c - TinyCrypt implementation of ECC auxiliary functions */
+
+/*
+ *
+ * Copyright (c) 2013, 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.
+ *
+ * Copyright (C) 2015 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>
+
+/* ------ Curve NIST P-256 constants: ------ */
+
+#define Curve_P {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, \
+ 0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF}
+
+#define Curve_B {0x27D2604B, 0x3BCE3C3E, 0xCC53B0F6, 0x651D06B0, \
+ 0x769886BC, 0xB3EBBD55, 0xAA3A93E7, 0x5AC635D8}
+
+#define Curve_N {0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, \
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF}
+
+#define Curve_G {{0xD898C296, 0xF4A13945, 0x2DEB33A0, 0x77037D81, \
+ 0x63A440F2, 0xF8BCE6E5, 0xE12C4247, 0x6B17D1F2}, \
+ {0x37BF51F5, 0xCBB64068, 0x6B315ECE, 0x2BCE3357, \
+ 0x7C0F9E16, 0x8EE7EB4A, 0xFE1A7F9B, 0x4FE342E2} }
+
+#define Curve_P_Barrett {0x00000003, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, \
+ 0xFFFFFFFE, 0xFFFFFFFE, 0xFFFFFFFF, 0x00000000, 0x00000001}
+
+#define Curve_N_Barrett {0xEEDF9BFE, 0x012FFD85, 0xDF1A6C21, 0x43190552, \
+ 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x00000000, 0x00000001}
+
+uint32_t curve_p[NUM_ECC_DIGITS] = Curve_P;
+uint32_t curve_b[NUM_ECC_DIGITS] = Curve_B;
+EccPoint curve_G = Curve_G;
+uint32_t curve_n[NUM_ECC_DIGITS] = Curve_N;
+uint32_t curve_pb[NUM_ECC_DIGITS + 1] = Curve_P_Barrett;
+uint32_t curve_nb[NUM_ECC_DIGITS + 1] = Curve_N_Barrett;
+
+/* ------ Static functions: ------ */
+
+/* Zeroing out p_vli. */
+static void vli_clear(uint32_t *p_vli)
+{
+ uint32_t i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; ++i) {
+ p_vli[i] = 0;
+ }
+}
+
+/* Returns nonzero if bit p_bit of p_vli is set.
+ * It is assumed that the value provided in 'bit' is within
+ * the boundaries of the word-array 'p_vli'.*/
+static uint32_t vli_testBit(uint32_t *p_vli, uint32_t p_bit)
+{
+ return (p_vli[p_bit / 32] & (1 << (p_bit % 32)));
+}
+
+uint32_t vli_isZero(uint32_t *p_vli)
+{
+ uint32_t acc = 0;
+
+ for (uint32_t i = 0; i < NUM_ECC_DIGITS; ++i) {
+ acc |= p_vli[i];
+ }
+
+ return (!acc);
+}
+
+/*
+ * Find the right-most nonzero 32-bit "digits" in p_vli.
+ *
+ * Side-channel countermeasure: algorithm strengthened against timing attack.
+ */
+static uint32_t vli_numDigits(uint32_t *p_vli)
+{
+ int32_t i;
+ uint32_t digits = 0;
+
+ for (i = NUM_ECC_DIGITS - 1; i >= 0 ; --i) {
+ digits += p_vli[i] || digits;
+ }
+
+ return digits;
+}
+
+/*
+ * Find the left-most non-zero bit in p_vli.
+ *
+ * Side-channel countermeasure: algorithm strengthened against timing attack.
+ */
+static uint32_t vli_numBits(uint32_t *p_vli)
+{
+ uint32_t l_digit;
+ uint32_t i, acc = 32;
+ uint32_t l_numDigits = vli_numDigits(p_vli);
+
+ l_digit = p_vli[l_numDigits - 1];
+
+ for (i = 0; i < 32; ++i) {
+ acc -= !l_digit;
+ l_digit >>= 1;
+ }
+
+ return ((l_numDigits - 1) * 32 + acc);
+}
+
+/*
+ * Computes p_result = p_left + p_right, returns carry.
+ *
+ * Side-channel countermeasure: algorithm strengthened against timing attack.
+ */
+static uint32_t vli_add(uint32_t *p_result, uint32_t *p_left,
+ uint32_t *p_right)
+{
+
+ uint32_t l_carry = 0;
+
+ for (uint32_t i = 0; i < NUM_ECC_DIGITS; ++i) {
+ uint32_t l_sum = p_left[i] + p_right[i] + l_carry;
+
+ l_carry = (l_sum < p_left[i]) | ((l_sum == p_left[i]) && l_carry);
+ p_result[i] = l_sum;
+ }
+
+ return l_carry;
+}
+
+
+/* Computes p_result = p_left * p_right. */
+static void vli_mult(uint32_t *p_result, uint32_t *p_left,
+ uint32_t *p_right, uint32_t word_size)
+{
+
+ uint64_t r01 = 0;
+ uint32_t r2 = 0;
+
+ /* Compute each digit of p_result in sequence, maintaining the carries. */
+ for (uint32_t k = 0; k < word_size*2 - 1; ++k) {
+
+ uint32_t l_min = (k < word_size ? 0 : (k + 1) - word_size);
+
+ for (uint32_t i = l_min; i <= k && i < word_size; ++i) {
+
+ uint64_t l_product = (uint64_t)p_left[i] * p_right[k - i];
+
+ r01 += l_product;
+ r2 += (r01 < l_product);
+ }
+ p_result[k] = (uint32_t)r01;
+ r01 = (r01 >> 32) | (((uint64_t)r2) << 32);
+ r2 = 0;
+ }
+
+ p_result[word_size * 2 - 1] = (uint32_t)r01;
+}
+
+/* Computes p_result = p_left^2. */
+static void vli_square(uint32_t *p_result, uint32_t *p_left)
+{
+
+ uint64_t r01 = 0;
+ uint32_t r2 = 0;
+ uint32_t i, k;
+
+ for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; ++k) {
+
+ uint32_t l_min = (k < NUM_ECC_DIGITS ? 0 : (k + 1) - NUM_ECC_DIGITS);
+
+ for (i = l_min; i <= k && i <= k - i; ++i) {
+
+ uint64_t l_product = (uint64_t)p_left[i] * p_left[k - i];
+
+ if (i < k - i) {
+
+ r2 += l_product >> 63;
+ l_product *= 2;
+ }
+ r01 += l_product;
+ r2 += (r01 < l_product);
+ }
+ p_result[k] = (uint32_t)r01;
+ r01 = (r01 >> 32) | (((uint64_t)r2) << 32);
+ r2 = 0;
+ }
+
+ p_result[NUM_ECC_DIGITS * 2 - 1] = (uint32_t)r01;
+}
+
+/* Computes p_result = p_product % curve_p using Barrett reduction. */
+void vli_mmod_barrett(uint32_t *p_result, uint32_t *p_product,
+ uint32_t *p_mod, uint32_t *p_barrett)
+{
+ uint32_t i;
+ uint32_t q1[NUM_ECC_DIGITS + 1];
+
+ for (i = NUM_ECC_DIGITS - 1; i < 2 * NUM_ECC_DIGITS; i++) {
+ q1[i - (NUM_ECC_DIGITS - 1)] = p_product[i];
+ }
+
+ uint32_t q2[2*NUM_ECC_DIGITS + 2];
+
+ vli_mult(q2, q1, p_barrett, NUM_ECC_DIGITS + 1);
+ for (i = NUM_ECC_DIGITS + 1; i < 2 * NUM_ECC_DIGITS + 2; i++) {
+ q1[i - (NUM_ECC_DIGITS + 1)] = q2[i];
+ }
+
+ uint32_t prime2[2*NUM_ECC_DIGITS];
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ prime2[i] = p_mod[i];
+ prime2[NUM_ECC_DIGITS + i] = 0;
+ }
+
+ vli_mult(q2, q1, prime2, NUM_ECC_DIGITS + 1);
+ vli_sub(p_product, p_product, q2, 2 * NUM_ECC_DIGITS);
+
+ uint32_t borrow;
+
+ borrow = vli_sub(q1, p_product, prime2, NUM_ECC_DIGITS + 1);
+ vli_cond_set(p_product, p_product, q1, borrow);
+ p_product[NUM_ECC_DIGITS] = q1[NUM_ECC_DIGITS] * (!borrow);
+ borrow = vli_sub(q1, p_product, prime2, NUM_ECC_DIGITS + 1);
+ vli_cond_set(p_product, p_product, q1, borrow);
+ p_product[NUM_ECC_DIGITS] = q1[NUM_ECC_DIGITS] * (!borrow);
+ borrow = vli_sub(q1, p_product, prime2, NUM_ECC_DIGITS + 1);
+ vli_cond_set(p_product, p_product, q1, borrow);
+ p_product[NUM_ECC_DIGITS] = q1[NUM_ECC_DIGITS] * (!borrow);
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ p_result[i] = p_product[i];
+ }
+}
+
+/*
+ * Computes modular exponentiation.
+ *
+ * Side-channel countermeasure: algorithm strengthened against timing attack.
+ */
+static void vli_modExp(uint32_t *p_result, uint32_t *p_base,
+ uint32_t *p_exp, uint32_t *p_mod, uint32_t *p_barrett)
+{
+
+ uint32_t acc[NUM_ECC_DIGITS], tmp[NUM_ECC_DIGITS], product[2 * NUM_ECC_DIGITS];
+ uint32_t j;
+ int32_t i;
+
+ vli_clear(acc);
+ acc[0] = 1;
+
+ for (i = NUM_ECC_DIGITS - 1; i >= 0; i--) {
+ for (j = 1 << 31; j > 0; j = j >> 1) {
+ vli_square(product, acc);
+ vli_mmod_barrett(acc, product, p_mod, p_barrett);
+ vli_mult(product, acc, p_base, NUM_ECC_DIGITS);
+ vli_mmod_barrett(tmp, product, p_mod, p_barrett);
+ vli_cond_set(acc, tmp, acc, j & p_exp[i]);
+ }
+ }
+
+ vli_set(p_result, acc);
+}
+
+/* Conversion from Affine coordinates to Jacobi coordinates. */
+static void EccPoint_fromAffine(EccPointJacobi *p_point_jacobi,
+ EccPoint *p_point) {
+
+ vli_set(p_point_jacobi->X, p_point->x);
+ vli_set(p_point_jacobi->Y, p_point->y);
+ vli_clear(p_point_jacobi->Z);
+ p_point_jacobi->Z[0] = 1;
+}
+
+/*
+ * Elliptic curve point doubling in Jacobi coordinates: P = P + P.
+ *
+ * Requires 4 squares and 4 multiplications.
+ */
+static void EccPoint_double(EccPointJacobi *P)
+{
+
+ uint32_t m[NUM_ECC_DIGITS], s[NUM_ECC_DIGITS], t[NUM_ECC_DIGITS];
+
+ vli_modSquare_fast(t, P->Z);
+ vli_modSub(m, P->X, t, curve_p);
+ vli_modAdd(s, P->X, t, curve_p);
+ vli_modMult_fast(m, m, s);
+ vli_modAdd(s, m, m, curve_p);
+ vli_modAdd(m, s, m, curve_p); /* m = 3X^2 - 3Z^4 */
+ vli_modSquare_fast(t, P->Y);
+ vli_modMult_fast(s, P->X, t);
+ vli_modAdd(s, s, s, curve_p);
+ vli_modAdd(s, s, s, curve_p); /* s = 4XY^2 */
+ vli_modMult_fast(P->Z, P->Y, P->Z);
+ vli_modAdd(P->Z, P->Z, P->Z, curve_p); /* Z' = 2YZ */
+ vli_modSquare_fast(P->X, m);
+ vli_modSub(P->X, P->X, s, curve_p);
+ vli_modSub(P->X, P->X, s, curve_p); /* X' = m^2 - 2s */
+ vli_modSquare_fast(P->Y, t);
+ vli_modAdd(P->Y, P->Y, P->Y, curve_p);
+ vli_modAdd(P->Y, P->Y, P->Y, curve_p);
+ vli_modAdd(P->Y, P->Y, P->Y, curve_p);
+ vli_modSub(t, s, P->X, curve_p);
+ vli_modMult_fast(t, t, m);
+ vli_modSub(P->Y, t, P->Y, curve_p); /* Y' = m(s - X') - 8Y^4 */
+
+}
+
+/* Copy input to target. */
+static void EccPointJacobi_set(EccPointJacobi *target, EccPointJacobi *input)
+{
+ vli_set(target->X, input->X);
+ vli_set(target->Y, input->Y);
+ vli_set(target->Z, input->Z);
+}
+
+/* ------ Externally visible functions (see header file for comments): ------ */
+
+void vli_set(uint32_t *p_dest, uint32_t *p_src)
+{
+
+ uint32_t i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; ++i) {
+ p_dest[i] = p_src[i];
+ }
+}
+
+int32_t vli_cmp(uint32_t *p_left, uint32_t *p_right, int32_t word_size)
+{
+
+ int32_t i, cmp = 0;
+
+ for (i = word_size-1; i >= 0; --i) {
+ cmp |= ((p_left[i] > p_right[i]) - (p_left[i] < p_right[i])) * (!cmp);
+ }
+
+ return cmp;
+}
+
+uint32_t vli_sub(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
+ uint32_t word_size)
+{
+
+ uint32_t l_borrow = 0;
+
+ for (uint32_t i = 0; i < word_size; ++i) {
+ uint32_t l_diff = p_left[i] - p_right[i] - l_borrow;
+
+ l_borrow = (l_diff > p_left[i]) | ((l_diff == p_left[i]) && l_borrow);
+ p_result[i] = l_diff;
+ }
+
+ return l_borrow;
+}
+
+void vli_cond_set(uint32_t *output, uint32_t *p_true, uint32_t *p_false,
+ uint32_t cond)
+{
+ uint32_t i;
+
+ cond = (!cond);
+
+ for (i = 0; i < NUM_ECC_DIGITS; i++) {
+ output[i] = (p_true[i]*(!cond)) | (p_false[i]*cond);
+ }
+}
+
+void vli_modAdd(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
+ uint32_t *p_mod)
+{
+ uint32_t l_carry = vli_add(p_result, p_left, p_right);
+ uint32_t p_temp[NUM_ECC_DIGITS];
+
+ l_carry = l_carry == vli_sub(p_temp, p_result, p_mod, NUM_ECC_DIGITS);
+ vli_cond_set(p_result, p_temp, p_result, l_carry);
+}
+
+void vli_modSub(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
+ uint32_t *p_mod)
+{
+ uint32_t l_borrow = vli_sub(p_result, p_left, p_right, NUM_ECC_DIGITS);
+ uint32_t p_temp[NUM_ECC_DIGITS];
+
+ vli_add(p_temp, p_result, p_mod);
+ vli_cond_set(p_result, p_temp, p_result, l_borrow);
+}
+
+void vli_modMult_fast(uint32_t *p_result, uint32_t *p_left,
+ uint32_t *p_right)
+{
+ uint32_t l_product[2 * NUM_ECC_DIGITS];
+
+ vli_mult(l_product, p_left, p_right, NUM_ECC_DIGITS);
+ vli_mmod_barrett(p_result, l_product, curve_p, curve_pb);
+}
+
+void vli_modSquare_fast(uint32_t *p_result, uint32_t *p_left)
+{
+ uint32_t l_product[2 * NUM_ECC_DIGITS];
+
+ vli_square(l_product, p_left);
+ vli_mmod_barrett(p_result, l_product, curve_p, curve_pb);
+}
+
+void vli_modMult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right,
+ uint32_t *p_mod, uint32_t *p_barrett)
+{
+
+ uint32_t l_product[2 * NUM_ECC_DIGITS];
+
+ vli_mult(l_product, p_left, p_right, NUM_ECC_DIGITS);
+ vli_mmod_barrett(p_result, l_product, p_mod, p_barrett);
+}
+
+void vli_modInv(uint32_t *p_result, uint32_t *p_input, uint32_t *p_mod,
+ uint32_t *p_barrett)
+{
+ uint32_t p_power[NUM_ECC_DIGITS];
+
+ vli_set(p_power, p_mod);
+ p_power[0] -= 2;
+ vli_modExp(p_result, p_input, p_power, p_mod, p_barrett);
+}
+
+uint32_t EccPoint_isZero(EccPoint *p_point)
+{
+ return (vli_isZero(p_point->x) && vli_isZero(p_point->y));
+}
+
+uint32_t EccPointJacobi_isZero(EccPointJacobi *p_point_jacobi)
+{
+ return vli_isZero(p_point_jacobi->Z);
+}
+
+void EccPoint_toAffine(EccPoint *p_point, EccPointJacobi *p_point_jacobi)
+{
+
+ if (vli_isZero(p_point_jacobi->Z)) {
+ vli_clear(p_point->x);
+ vli_clear(p_point->y);
+ return;
+ }
+
+ uint32_t z[NUM_ECC_DIGITS];
+
+ vli_set(z, p_point_jacobi->Z);
+ vli_modInv(z, z, curve_p, curve_pb);
+ vli_modSquare_fast(p_point->x, z);
+ vli_modMult_fast(p_point->y, p_point->x, z);
+ vli_modMult_fast(p_point->x, p_point->x, p_point_jacobi->X);
+ vli_modMult_fast(p_point->y, p_point->y, p_point_jacobi->Y);
+}
+
+void EccPoint_add(EccPointJacobi *P1, EccPointJacobi *P2)
+{
+
+ uint32_t s1[NUM_ECC_DIGITS], u1[NUM_ECC_DIGITS], t[NUM_ECC_DIGITS];
+ uint32_t h[NUM_ECC_DIGITS], r[NUM_ECC_DIGITS];
+
+ vli_modSquare_fast(r, P1->Z);
+ vli_modSquare_fast(s1, P2->Z);
+ vli_modMult_fast(u1, P1->X, s1); /* u1 = X1 Z2^2 */
+ vli_modMult_fast(h, P2->X, r);
+ vli_modMult_fast(s1, P1->Y, s1);
+ vli_modMult_fast(s1, s1, P2->Z); /* s1 = Y1 Z2^3 */
+ vli_modMult_fast(r, P2->Y, r);
+ vli_modMult_fast(r, r, P1->Z);
+ vli_modSub(h, h, u1, curve_p); /* h = X2 Z1^2 - u1 */
+ vli_modSub(r, r, s1, curve_p); /* r = Y2 Z1^3 - s1 */
+
+ if (vli_isZero(h)) {
+ if (vli_isZero(r)) {
+ /* P1 = P2 */
+ EccPoint_double(P1);
+ return;
+ }
+ /* point at infinity */
+ vli_clear(P1->Z);
+ return;
+ }
+
+ vli_modMult_fast(P1->Z, P1->Z, P2->Z);
+ vli_modMult_fast(P1->Z, P1->Z, h); /* Z3 = h Z1 Z2 */
+ vli_modSquare_fast(t, h);
+ vli_modMult_fast(h, t, h);
+ vli_modMult_fast(u1, u1, t);
+ vli_modSquare_fast(P1->X, r);
+ vli_modSub(P1->X, P1->X, h, curve_p);
+ vli_modSub(P1->X, P1->X, u1, curve_p);
+ vli_modSub(P1->X, P1->X, u1, curve_p); /* X3 = r^2 - h^3 - 2 u1 h^2 */
+ vli_modMult_fast(t, s1, h);
+ vli_modSub(P1->Y, u1, P1->X, curve_p);
+ vli_modMult_fast(P1->Y, P1->Y, r);
+ vli_modSub(P1->Y, P1->Y, t, curve_p); /* Y3 = r(u1 h^2 - X3) - s1 h^3 */
+}
+
+/*
+ * Elliptic curve scalar multiplication with result in Jacobi coordinates:
+ *
+ * p_result = p_scalar * p_point.
+ */
+void EccPoint_mult_safe(EccPointJacobi *p_result, EccPoint *p_point, uint32_t *p_scalar)
+{
+
+ int32_t i;
+ uint32_t bit;
+ EccPointJacobi p_point_jacobi, p_tmp;
+
+ EccPoint_fromAffine(p_result, p_point);
+ EccPoint_fromAffine(&p_point_jacobi, p_point);
+
+ for (i = vli_numBits(p_scalar) - 2; i >= 0; i--) {
+ EccPoint_double(p_result);
+ EccPointJacobi_set(&p_tmp, p_result);
+ EccPoint_add(&p_tmp, &p_point_jacobi);
+ bit = vli_testBit(p_scalar, i);
+ vli_cond_set(p_result->X, p_tmp.X, p_result->X, bit);
+ vli_cond_set(p_result->Y, p_tmp.Y, p_result->Y, bit);
+ vli_cond_set(p_result->Z, p_tmp.Z, p_result->Z, bit);
+ }
+}
+
+/* Ellptic curve scalar multiplication with result in Jacobi coordinates */
+/* p_result = p_scalar * p_point */
+void EccPoint_mult_unsafe(EccPointJacobi *p_result, EccPoint *p_point, uint32_t *p_scalar)
+{
+ int i;
+ EccPointJacobi p_point_jacobi;
+ EccPoint_fromAffine(p_result, p_point);
+ EccPoint_fromAffine(&p_point_jacobi, p_point);
+
+ for(i = vli_numBits(p_scalar) - 2; i >= 0; i--)
+ {
+ EccPoint_double(p_result);
+ if (vli_testBit(p_scalar, i))
+ {
+ EccPoint_add(p_result, &p_point_jacobi);
+ }
+ }
+}
+
+/* -------- Conversions between big endian and little endian: -------- */
+
+void ecc_bytes2native(uint32_t p_native[NUM_ECC_DIGITS],
+ uint8_t p_bytes[NUM_ECC_DIGITS * 4])
+{
+
+ uint32_t i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; ++i) {
+ uint8_t *p_digit = p_bytes + 4 * (NUM_ECC_DIGITS - 1 - i);
+
+ p_native[i] = ((uint32_t)p_digit[0] << 24) |
+ ((uint32_t)p_digit[1] << 16) |
+ ((uint32_t)p_digit[2] << 8) |
+ (uint32_t)p_digit[3];
+ }
+}
+
+void ecc_native2bytes(uint8_t p_bytes[NUM_ECC_DIGITS * 4],
+ uint32_t p_native[NUM_ECC_DIGITS])
+{
+
+ uint32_t i;
+
+ for (i = 0; i < NUM_ECC_DIGITS; ++i) {
+ uint8_t *p_digit = p_bytes + 4 * (NUM_ECC_DIGITS - 1 - i);
+
+ p_digit[0] = p_native[i] >> 24;
+ p_digit[1] = p_native[i] >> 16;
+ p_digit[2] = p_native[i] >> 8;
+ p_digit[3] = p_native[i];
+ }
+}
+
diff --git a/ext/tinycrypt/lib/source/ecc_dh.c b/ext/tinycrypt/lib/source/ecc_dh.c
new file mode 100644
index 0000000..c2ab414
--- /dev/null
+++ b/ext/tinycrypt/lib/source/ecc_dh.c
@@ -0,0 +1,132 @@
+/* ec_dh.c - TinyCrypt implementation of EC-DH */
+
+/*
+ * Copyright (C) 2015 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>
+
+extern uint32_t curve_p[NUM_ECC_DIGITS];
+extern uint32_t curve_b[NUM_ECC_DIGITS];
+extern uint32_t curve_n[NUM_ECC_DIGITS];
+extern uint32_t curve_pb[NUM_ECC_DIGITS + 1];
+extern EccPoint curve_G;
+
+int32_t ecc_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS],
+ uint32_t p_random[NUM_ECC_DIGITS * 2])
+{
+ // computing modular reduction of p_random (see FIPS 186.4 B.4.1):
+ vli_mmod_barrett(p_privateKey, p_random, curve_p, curve_pb);
+
+ /* Make sure the private key is in the range [1, n-1].
+ * For the supported curve, n is always large enough
+ * that we only need to subtract once at most.
+ */
+ uint32_t p_tmp[NUM_ECC_DIGITS];
+ vli_sub(p_tmp, p_privateKey, curve_n, NUM_ECC_DIGITS);
+
+ vli_cond_set(p_privateKey, p_privateKey, p_tmp,
+ vli_cmp(curve_n, p_privateKey, NUM_ECC_DIGITS) == 1);
+
+ /* erasing temporary buffer used to store secret: */
+ for (uint32_t i = 0; i < NUM_ECC_DIGITS; i++)
+ p_tmp[i] = 0;
+
+ if (vli_isZero(p_privateKey)) {
+ return TC_CRYPTO_FAIL; /* The private key cannot be 0 (mod p). */
+ }
+
+ EccPointJacobi P;
+
+ EccPoint_mult_safe(&P, &curve_G, p_privateKey);
+ EccPoint_toAffine(p_publicKey, &P);
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+/* Compute p_result = x^3 - 3x + b */
+static void curve_x_side(uint32_t p_result[NUM_ECC_DIGITS],
+ uint32_t x[NUM_ECC_DIGITS])
+{
+
+ uint32_t _3[NUM_ECC_DIGITS] = {3}; /* -a = 3 */
+
+ vli_modSquare_fast(p_result, x); /* r = x^2 */
+ vli_modSub(p_result, p_result, _3, curve_p); /* r = x^2 - 3 */
+ vli_modMult_fast(p_result, p_result, x); /* r = x^3 - 3x */
+ vli_modAdd(p_result, p_result, curve_b, curve_p); /* r = x^3 - 3x + b */
+
+}
+
+int32_t ecc_valid_public_key(EccPoint *p_publicKey)
+{
+ uint32_t l_tmp1[NUM_ECC_DIGITS];
+ uint32_t l_tmp2[NUM_ECC_DIGITS];
+
+ if (EccPoint_isZero(p_publicKey)) {
+ return -1;
+ }
+
+ if ((vli_cmp(curve_p, p_publicKey->x, NUM_ECC_DIGITS) != 1) ||
+ (vli_cmp(curve_p, p_publicKey->y, NUM_ECC_DIGITS) != 1)) {
+ return -2;
+ }
+
+ vli_modSquare_fast(l_tmp1, p_publicKey->y); /* tmp1 = y^2 */
+
+ curve_x_side(l_tmp2, p_publicKey->x); /* tmp2 = x^3 - 3x + b */
+
+ /* Make sure that y^2 == x^3 + ax + b */
+ if (vli_cmp(l_tmp1, l_tmp2, NUM_ECC_DIGITS) != 0) {
+ return -3;
+ }
+
+ if (vli_cmp(p_publicKey->x, curve_G.x, NUM_ECC_DIGITS) == 0 &&
+ vli_cmp(p_publicKey->y, curve_G.y, NUM_ECC_DIGITS) == 0 )
+ return -4;
+
+ return 0;
+}
+
+int32_t ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS],
+ EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS])
+{
+
+ EccPoint p_point;
+ EccPointJacobi P;
+
+ EccPoint_mult_safe(&P, p_publicKey, p_privateKey);
+ if (EccPointJacobi_isZero(&P)) {
+ return TC_CRYPTO_FAIL;
+ }
+ EccPoint_toAffine(&p_point, &P);
+ vli_set(p_secret, p_point.x);
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/ext/tinycrypt/lib/source/ecc_dsa.c b/ext/tinycrypt/lib/source/ecc_dsa.c
new file mode 100644
index 0000000..dd84a18
--- /dev/null
+++ b/ext/tinycrypt/lib/source/ecc_dsa.c
@@ -0,0 +1,115 @@
+/* ec_dsa.c - TinyCrypt implementation of EC-DSA */
+
+/*
+ * Copyright (C) 2015 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>
+
+extern uint32_t curve_n[NUM_ECC_DIGITS];
+extern EccPoint curve_G;
+extern uint32_t curve_nb[NUM_ECC_DIGITS + 1];
+
+int32_t ecdsa_sign(uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS],
+ uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS],
+ uint32_t p_hash[NUM_ECC_DIGITS])
+{
+
+ uint32_t k[NUM_ECC_DIGITS], tmp[NUM_ECC_DIGITS];
+ EccPoint p_point;
+ EccPointJacobi P;
+
+ if (vli_isZero(p_random)) {
+ return TC_CRYPTO_FAIL; /* The random number must not be 0. */
+ }
+
+ vli_set(k, p_random);
+
+ vli_sub(tmp, k, curve_n, NUM_ECC_DIGITS);
+ vli_cond_set(k, k, tmp, vli_cmp(curve_n, k, NUM_ECC_DIGITS) == 1);
+
+ /* tmp = k * G */
+ EccPoint_mult_safe(&P, &curve_G, k);
+ EccPoint_toAffine(&p_point, &P);
+
+ /* r = x1 (mod n) */
+ vli_set(r, p_point.x);
+ if (vli_cmp(curve_n, r, NUM_ECC_DIGITS) != 1) {
+ vli_sub(r, r, curve_n, NUM_ECC_DIGITS);
+ }
+
+ if (vli_isZero(r)) {
+ return TC_CRYPTO_FAIL; /* If r == 0, fail (need a different random number). */
+ }
+
+ vli_modMult(s, r, p_privateKey, curve_n, curve_nb); /* s = r*d */
+ vli_modAdd(s, p_hash, s, curve_n); /* s = e + r*d */
+ vli_modInv(k, k, curve_n, curve_nb); /* k = 1 / k */
+ vli_modMult(s, s, k, curve_n, curve_nb); /* s = (e + r*d) / k */
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int32_t ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS],
+ uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS])
+{
+
+ uint32_t u1[NUM_ECC_DIGITS], u2[NUM_ECC_DIGITS];
+ uint32_t z[NUM_ECC_DIGITS];
+ EccPointJacobi P, R;
+ EccPoint p_point;
+
+ if (vli_isZero(r) || vli_isZero(s)) {
+ return TC_CRYPTO_FAIL; /* r, s must not be 0. */
+ }
+
+ if ((vli_cmp(curve_n, r, NUM_ECC_DIGITS) != 1) ||
+ (vli_cmp(curve_n, s, NUM_ECC_DIGITS) != 1)) {
+ return TC_CRYPTO_FAIL; /* r, s must be < n. */
+ }
+
+ /* Calculate u1 and u2. */
+ vli_modInv(z, s, curve_n, curve_nb); /* Z = s^-1 */
+ vli_modMult(u1, p_hash, z, curve_n, curve_nb); /* u1 = e/s */
+ vli_modMult(u2, r, z, curve_n, curve_nb); /* u2 = r/s */
+
+ /* calculate P = u1*G + u2*Q */
+ EccPoint_mult_unsafe(&P, &curve_G, u1);
+ EccPoint_mult_unsafe(&R, p_publicKey, u2);
+ EccPoint_add(&P, &R);
+ EccPoint_toAffine(&p_point, &P);
+
+ /* Accept only if P.x == r. */
+ if (!vli_sub(z, p_point.x, curve_n, NUM_ECC_DIGITS)) {
+ vli_set(p_point.x, z);
+ }
+
+ return (vli_cmp(p_point.x, r, NUM_ECC_DIGITS) == 0);
+}
diff --git a/ext/tinycrypt/lib/source/hmac.c b/ext/tinycrypt/lib/source/hmac.c
new file mode 100644
index 0000000..e256846
--- /dev/null
+++ b/ext/tinycrypt/lib/source/hmac.c
@@ -0,0 +1,147 @@
+/* hmac.c - TinyCrypt implementation of the HMAC algorithm */
+
+/*
+ * Copyright (C) 2015 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, uint32_t key_size)
+{
+ const uint8_t inner_pad = (uint8_t) 0x36;
+ const uint8_t outer_pad = (uint8_t) 0x5c;
+ uint32_t 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;
+ }
+}
+
+int32_t tc_hmac_set_key(TCHmacState_t ctx,
+ const uint8_t *key,
+ uint32_t 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;
+}
+
+int32_t 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;
+}
+
+int32_t tc_hmac_update(TCHmacState_t ctx,
+ const void *data,
+ uint32_t 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;
+}
+
+int32_t tc_hmac_final(uint8_t *tag, uint32_t 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;
+}
diff --git a/ext/tinycrypt/lib/source/hmac_prng.c b/ext/tinycrypt/lib/source/hmac_prng.c
new file mode 100644
index 0000000..ceac27f
--- /dev/null
+++ b/ext/tinycrypt/lib/source/hmac_prng.c
@@ -0,0 +1,210 @@
+/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */
+
+/*
+ * Copyright (C) 2015 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 uint32_t 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 uint32_t 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 uint32_t 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 uint32_t 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 uint32_t variable, while SP800-90A specifies a maximum of 2^48.
+ */
+static const uint32_t MAX_GENS = UINT32_MAX;
+
+/*
+ * maximum bytes per generate call;
+ * SP800-90A specifies a maximum up to 2^19.
+ */
+static const uint32_t MAX_OUT = (1 << 19);
+
+/*
+ * Assumes: prng != NULL, e != NULL, len >= 0.
+ */
+static void update(TCHmacPrng_t prng, const uint8_t *e, uint32_t 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);
+}
+
+int32_t tc_hmac_prng_init(TCHmacPrng_t prng,
+ const uint8_t *personalization,
+ uint32_t 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;
+}
+
+int32_t tc_hmac_prng_reseed(TCHmacPrng_t prng,
+ const uint8_t *seed,
+ uint32_t seedlen,
+ const uint8_t *additional_input,
+ uint32_t 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;
+}
+
+int32_t tc_hmac_prng_generate(uint8_t *out, uint32_t outlen, TCHmacPrng_t prng)
+{
+ uint32_t 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;
+}
diff --git a/ext/tinycrypt/lib/source/sha256.c b/ext/tinycrypt/lib/source/sha256.c
new file mode 100644
index 0000000..c27d3e1
--- /dev/null
+++ b/ext/tinycrypt/lib/source/sha256.c
@@ -0,0 +1,217 @@
+/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */
+
+/*
+ * Copyright (C) 2015 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(uint32_t *iv, const uint8_t *data);
+
+int32_t 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;
+}
+
+int32_t 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;
+}
+
+int32_t tc_sha256_final(uint8_t *digest, TCSha256State_t s)
+{
+ uint32_t 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) {
+ uint32_t t = *((uint32_t *) &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 uint32_t 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 uint32_t ROTR(uint32_t a, uint32_t 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 uint32_t BigEndian(const uint8_t **c)
+{
+ uint32_t n = 0;
+
+ n = (((uint32_t)(*((*c)++))) << 24);
+ n |= ((uint32_t)(*((*c)++)) << 16);
+ n |= ((uint32_t)(*((*c)++)) << 8);
+ n |= ((uint32_t)(*((*c)++)));
+ return n;
+}
+
+static void compress(uint32_t *iv, const uint8_t *data)
+{
+ uint32_t a, b, c, d, e, f, g, h;
+ uint32_t s0, s1;
+ uint32_t t1, t2;
+ uint32_t work_space[16];
+ uint32_t n;
+ uint32_t 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;
+}
diff --git a/ext/tinycrypt/lib/source/utils.c b/ext/tinycrypt/lib/source/utils.c
new file mode 100644
index 0000000..147d8d4
--- /dev/null
+++ b/ext/tinycrypt/lib/source/utils.c
@@ -0,0 +1,75 @@
+/* utils.c - TinyCrypt platform-dependent run-time operations */
+
+/*
+ * Copyright (C) 2015 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_MOST_SIG_BIT 0x80
+#define MASK_TWENTY_SEVEN 0x1b
+
+uint32_t _copy(uint8_t *to, uint32_t to_len,
+ const uint8_t *from, uint32_t 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, uint32_t 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));
+}
+
+int32_t _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 (uint32_t i = 0; i < size; i++) {
+ result |= tempa[i] ^ tempb[i];
+ }
+ return result;
+}