Initial commit

Initial commit.
This commit is contained in:
kntran1
2026-03-23 14:40:39 -05:00
parent e84b2b4166
commit 4e2a5258a5
872 changed files with 165227 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
*.o
*~
*.d
*.exe
*.a

View File

@@ -0,0 +1,15 @@
Architect:
Rafael Misoczki <rafael.misoczki@intel.com>
Open Source Maintainer:
Constanza Heath <constanza.m.heath@intel.com>
Rafael Misoczki <rafael.misoczki@intel.com>
Contributors:
Constanza Heath <constanza.m.heath@intel.com>
Rafael Misoczki <rafael.misoczki@intel.com>
Flavio Santes <flavio.santes@intel.com>
Jarkko Sakkinen <jarkko.sakkinen@intel.com>
Chris Morrison
Marti Bolivar
Colin Ian King

View File

@@ -0,0 +1,61 @@
================================================================================
TinyCrypt Cryptographic Library
================================================================================
Copyright (c) 2017, Intel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
Copyright (c) 2014, Kenneth MacKay
All rights reserved.
https://github.com/kmackay/micro-ecc
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================

View File

@@ -0,0 +1,21 @@
################################################################################
#
# Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
#
# Global Makefile.
# See lib/Makefile and tests/Makefile for further configuration.
#
################################################################################
include config.mk
all:
$(MAKE) -C lib
ifeq ($(ENABLE_TESTS),true)
$(MAKE) -C tests
endif
clean:
$(MAKE) -C lib clean
$(MAKE) -C tests clean
$(RM) *~

View File

@@ -0,0 +1,71 @@
================================================================================
TinyCrypt Cryptographic Library
================================================================================
Copyright (c) 2017, Intel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
Overview:
The TinyCrypt Library provides an implementation for constrained devices of a
minimal set of standard cryptography primitives.
Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported
cryptographic primitives and the limitations of TinyCrypt library. For usage,
security and technicalities, please see the corresponding header file of each
cryptographic primitive.
================================================================================
Organization:
/lib: C source code of the cryptographic primitives.
/lib/include/tinycrypt: C header files of the cryptographic primitives.
/tests: Test vectors of the cryptographic primitives.
/doc: Documentation of TinyCrypt.
================================================================================
Building:
1) In Makefile.conf set:
- CFLAGS for compiler flags.
- CC for compiler.
- ENABLE_TESTS for enabling (true) or disabling (false) tests compilation.
2) In lib/Makefile select the primitives required by your project.
3) In tests/Makefile select the corresponding tests of the selected primitives.
4) make
5) run tests in tests/
================================================================================

View File

@@ -0,0 +1 @@
0.2.8

View File

@@ -0,0 +1,35 @@
################################################################################
#
# Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
#
# Global configuration Makefile. Included everywhere.
#
################################################################################
# EDIT HERE:
CC:=gcc
CFLAGS:=-Os -std=c99 -Wall -Wextra -D_ISOC99_SOURCE -MMD -I../lib/include/ -I../lib/source/ -I../tests/include/
vpath %.c ../lib/source/
ENABLE_TESTS=true
# override MinGW built-in recipe
%.o: %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
ifeq ($(OS),Windows_NT)
DOTEXE:=.exe
endif
# DO NOT EDIT AFTER THIS POINT:
ifeq ($(ENABLE_TESTS), true)
CFLAGS += -DENABLE_TESTS
else
CFLAGS += -DDISABLE_TESTS
endif
export CC
export CFLAGS
export VPATH
export ENABLE_TESTS
################################################################################

View File

@@ -0,0 +1,352 @@
TinyCrypt Cryptographic Library
###############################
Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
Overview
********
The TinyCrypt Library provides an implementation for targeting constrained devices
with a minimal set of standard cryptography primitives, as listed below. To better
serve applications targeting constrained devices, TinyCrypt implementations differ
from the standard specifications (see the Important Remarks section for some
important differences). Certain cryptographic primitives depend on other
primitives, as mentioned in the list below.
Aside from the Important Remarks section below, valuable information on the usage,
security and technicalities of each cryptographic primitive are found in the
corresponding header file.
* SHA-256:
* Type of primitive: Hash function.
* Standard Specification: NIST FIPS PUB 180-4.
* Requires: --
* HMAC-SHA256:
* Type of primitive: Message authentication code.
* Standard Specification: RFC 2104.
* Requires: SHA-256
* HMAC-PRNG:
* Type of primitive: Pseudo-random number generator (256-bit strength).
* Standard Specification: NIST SP 800-90A.
* Requires: SHA-256 and HMAC-SHA256.
* AES-128:
* Type of primitive: Block cipher.
* Standard Specification: NIST FIPS PUB 197.
* Requires: --
* AES-CBC mode:
* Type of primitive: Encryption mode of operation.
* Standard Specification: NIST SP 800-38A.
* Requires: AES-128.
* AES-CTR mode:
* Type of primitive: Encryption mode of operation.
* Standard Specification: NIST SP 800-38A.
* Requires: AES-128.
* AES-CMAC mode:
* Type of primitive: Message authentication code.
* Standard Specification: NIST SP 800-38B.
* Requires: AES-128.
* AES-CCM mode:
* Type of primitive: Authenticated encryption.
* Standard Specification: NIST SP 800-38C.
* Requires: AES-128.
* CTR-PRNG:
* Type of primitive: Pseudo-random number generator (128-bit strength).
* Standard Specification: NIST SP 800-90A.
* Requires: AES-128.
* ECC-DH:
* Type of primitive: Key exchange based on curve NIST p-256.
* Standard Specification: RFC 6090.
* Requires: ECC auxiliary functions (ecc.h/c).
* ECC-DSA:
* Type of primitive: Digital signature based on curve NIST p-256.
* Standard Specification: RFC 6090.
* Requires: ECC auxiliary functions (ecc.h/c).
Design Goals
************
* Minimize the code size of each cryptographic primitive. This means minimize
the size of a platform-independent implementation, as presented in TinyCrypt.
Note that various applications may require further features, optimizations with
respect to other metrics and countermeasures for particular threats. These
peculiarities would increase the code size and thus are not considered here.
* Minimize the dependencies among the cryptographic primitives. This means
that it is unnecessary to build and allocate object code for more primitives
than the ones strictly required by the intended application. In other words,
one can select and compile only the primitives required by the application.
Important Remarks
*****************
The cryptographic implementations in TinyCrypt library have some limitations.
Some of these limitations are inherent to the cryptographic primitives
themselves, while others are specific to TinyCrypt. These limitations were accepted
in order to meet its design goals (in special, minimal code size) and to better
serve applications targeting constrained devices in general. Some of these
limitations are discussed in-depth below.
General Remarks
***************
* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the
variety of side-channel attacks, many of them only relevant to certain
platforms. In this sense, instead of penalizing all library users with
side-channel countermeasures such as increasing the overall code size,
TinyCrypt only implements certain generic timing-attack countermeasures.
Specific Remarks
****************
* SHA-256:
* The number of bits_hashed in the state is not checked for overflow. Note
however that this will only be a problem if you intend to hash more than
2^64 bits, which is an extremely large window.
* HMAC:
* The HMAC verification process is assumed to be performed by the application.
This compares the computed tag with some given tag.
Note that conventional memory-comparison methods (such as memcmp function)
might be vulnerable to timing attacks; thus be sure to use a constant-time
memory comparison function (such as compare_constant_time
function provided in lib/utils.c).
* The tc_hmac_final function, responsible for computing the message tag,
cleans the state context before exiting. Thus, applications do not need to
clean the TCHmacState_t ctx after calling tc_hmac_final. This should not
be changed in future versions of the library as there are applications
currently relying on this good-practice/feature of TinyCrypt.
* HMAC-PRNG:
* Before using HMAC-PRNG, you *must* find an entropy source to produce a seed.
PRNGs only stretch the seed into a seemingly random output of arbitrary
length. The security of the output is exactly equal to the
unpredictability of the seed.
* NIST SP 800-90A requires three items as seed material in the initialization
step: entropy seed, personalization and a nonce (which is not implemented).
TinyCrypt requires the personalization byte array and automatically creates
the entropy seed using a mandatory call to the re-seed function.
* AES-128:
* The current implementation does not support other key-lengths (such as 256
bits). Note that if you need AES-256, it doesn't sound as though your
application is running in a constrained environment. AES-256 requires keys
twice the size as for AES-128, and the key schedule is 40% larger.
* CTR mode:
* The AES-CTR mode limits the size of a data message they encrypt to 2^32
blocks. If you need to encrypt larger data sets, your application would
need to replace the key after 2^32 block encryptions.
* CTR-PRNG:
* Before using CTR-PRNG, you *must* find an entropy source to produce a seed.
PRNGs only stretch the seed into a seemingly random output of arbitrary
length. The security of the output is exactly equal to the
unpredictability of the seed.
* CBC mode:
* TinyCrypt CBC decryption assumes that the iv and the ciphertext are
contiguous (as produced by TinyCrypt CBC encryption). This allows for a
very efficient decryption algorithm that would not otherwise be possible.
* CMAC mode:
* AES128-CMAC mode of operation offers 64 bits of security against collision
attacks. Note however that an external attacker cannot generate the tags
him/herself without knowing the MAC key. In this sense, to attack the
collision property of AES128-CMAC, an external attacker would need the
cooperation of the legal user to produce an exponentially high number of
tags (e.g. 2^64) to finally be able to look for collisions and benefit
from them. As an extra precaution, the current implementation allows to at
most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup
(allowing a new key to be set), as suggested in Appendix B of SP 800-38B.
* CCM mode:
* There are a few tradeoffs for the selection of the parameters of CCM mode.
In special, there is a tradeoff between the maximum number of invocations
of CCM under a given key and the maximum payload length for those
invocations. Both things are related to the parameter 'q' of CCM mode. The
maximum number of invocations of CCM under a given key is determined by
the nonce size, which is: 15-q bytes. The maximum payload length for those
invocations is defined as 2^(8q) bytes.
To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2,
which is a quite reasonable choice for constrained applications. The
implications of this choice are:
The nonce size is: 13 bytes.
The maximum payload length is: 2^16 bytes = 65 KB.
The mac size parameter is an important parameter to estimate the security
against collision attacks (that aim at finding different messages that
produce the same authentication tag). TinyCrypt CCM implementation
accepts any even integer between 4 and 16, as suggested in SP 800-38C.
* TinyCrypt CCM implementation accepts associated data of any length between
0 and (2^16 - 2^8) = 65280 bytes.
* TinyCrypt CCM implementation accepts:
* Both non-empty payload and associated data (it encrypts and
authenticates the payload and only authenticates the associated data);
* Non-empty payload and empty associated data (it encrypts and
authenticates the payload);
* Non-empty associated data and empty payload (it degenerates to an
authentication-only mode on the associated data).
* RFC-3610, which also specifies CCM, presents a few relevant security
suggestions, such as: it is recommended for most applications to use a
mac size greater than 8. Besides, it is emphasized that the usage of the
same nonce for two different messages which are encrypted with the same
key obviously destroys the security properties of CCM mode.
* ECC-DH and ECC-DSA:
* TinyCrypt ECC implementation is based on micro-ecc (see
https://github.com/kmackay/micro-ecc). In the original micro-ecc
documentation, there is an important remark about the way integers are
represented:
"Integer representation: To reduce code size, all large integers are
represented using little-endian words - so the least significant word is
first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()'
functions to convert between the native integer representation and the
standardized octet representation."
Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32},
{95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli)
consisting of 4 unsigned integers (as an example).
* A cryptographically-secure PRNG function must be set (using uECC_set_rng())
before calling uECC_make_key() or uECC_sign().
Examples of Applications
************************
It is possible to do useful cryptography with only the given small set of
primitives. With this list of primitives it becomes feasible to support a range
of cryptography usages:
* Measurement of code, data structures, and other digital artifacts (SHA256);
* Generate commitments (SHA256);
* Construct keys (HMAC-SHA256);
* Extract entropy from strings containing some randomness (HMAC-SHA256);
* Construct random mappings (HMAC-SHA256);
* Construct nonces and challenges (HMAC-PRNG, CTR-PRNG);
* Authenticate using a shared secret (HMAC-SHA256);
* Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG);
* Authenticated encryption (AES-128 + AES-CCM);
* Key-exchange (EC-DH);
* Digital signature (EC-DSA);
Test Vectors
************
The library provides a test program for each cryptographic primitive (see 'test'
folder). Besides illustrating how to use the primitives, these tests evaluate
the correctness of the implementations by checking the results against
well-known publicly validated test vectors.
For the case of the HMAC-PRNG, due to the necessity of performing an extensive
battery test to produce meaningful conclusions, we suggest the user to evaluate
the unpredictability of the implementation by using the NIST Statistical Test
Suite (see References).
For the case of the EC-DH and EC-DSA implementations, most of the test vectors
were obtained from the site of the NIST Cryptographic Algorithm Validation
Program (CAVP), see References.
References
**********
* `NIST FIPS PUB 180-4 (SHA-256)`_
.. _NIST FIPS PUB 180-4 (SHA-256):
http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
* `NIST FIPS PUB 197 (AES-128)`_
.. _NIST FIPS PUB 197 (AES-128):
http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
* `NIST SP800-90A (HMAC-PRNG)`_
.. _NIST SP800-90A (HMAC-PRNG):
http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
* `NIST SP 800-38A (AES-CBC and AES-CTR)`_
.. _NIST SP 800-38A (AES-CBC and AES-CTR):
http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
* `NIST SP 800-38B (AES-CMAC)`_
.. _NIST SP 800-38B (AES-CMAC):
http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
* `NIST SP 800-38C (AES-CCM)`_
.. _NIST SP 800-38C (AES-CCM):
http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_
.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG):
http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html
* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_
.. _NIST Cryptographic Algorithm Validation Program (CAVP) site:
http://csrc.nist.gov/groups/STM/cavp/
* `RFC 2104 (HMAC-SHA256)`_
.. _RFC 2104 (HMAC-SHA256):
https://www.ietf.org/rfc/rfc2104.txt
* `RFC 6090 (ECC-DH and ECC-DSA)`_
.. _RFC 6090 (ECC-DH and ECC-DSA):
https://www.ietf.org/rfc/rfc6090.txt

View File

@@ -0,0 +1,39 @@
################################################################################
#
# Copyright (C) 2017 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)

View File

@@ -0,0 +1,130 @@
/* aes.h - TinyCrypt interface to an AES-128 implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to an AES-128 implementation.
*
* Overview: AES-128 is a NIST approved block cipher specified in
* FIPS 197. Block ciphers are deterministic algorithms that
* perform a transformation specified by a symmetric key in fixed-
* length data sets, also called blocks.
*
* Security: AES-128 provides approximately 128 bits of security.
*
* Usage: 1) call tc_aes128_set_encrypt/decrypt_key to set the key.
*
* 2) call tc_aes_encrypt/decrypt to process the data.
*/
#ifndef __TC_AES_H__
#define __TC_AES_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define Nb (4) /* number of columns (32-bit words) comprising the state */
#define Nk (4) /* number of 32-bit words comprising the key */
#define Nr (10) /* number of rounds */
#define TC_AES_BLOCK_SIZE (Nb*Nk)
#define TC_AES_KEY_SIZE (Nb*Nk)
typedef struct tc_aes_key_sched_struct {
unsigned int words[Nb*(Nr+1)];
} *TCAesKeySched_t;
/**
* @brief Set AES-128 encryption key
* Uses key k to initialize s
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
* @note This implementation skips the additional steps required for keys
* larger than 128 bits, and must not be used for AES-192 or
* AES-256 key schedule -- see FIPS 197 for details
* @param s IN/OUT -- initialized struct tc_aes_key_sched_struct
* @param k IN -- points to the AES key
*/
int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k);
/**
* @brief AES-128 Encryption procedure
* Encrypts contents of in buffer into out buffer under key;
* schedule s
* @note Assumes s was initialized by aes_set_encrypt_key;
* out and in point to 16 byte buffers
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL
* @param out IN/OUT -- buffer to receive ciphertext block
* @param in IN -- a plaintext block to encrypt
* @param s IN -- initialized AES key schedule
*/
int tc_aes_encrypt(uint8_t *out, const uint8_t *in,
const TCAesKeySched_t s);
/**
* @brief Set the AES-128 decryption key
* Uses key k to initialize s
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
* @note This is the implementation of the straightforward inverse cipher
* using the cipher documented in FIPS-197 figure 12, not the
* equivalent inverse cipher presented in Figure 15
* @warning This routine skips the additional steps required for keys larger
* than 128, and must not be used for AES-192 or AES-256 key
* schedule -- see FIPS 197 for details
* @param s IN/OUT -- initialized struct tc_aes_key_sched_struct
* @param k IN -- points to the AES key
*/
int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k);
/**
* @brief AES-128 Encryption procedure
* Decrypts in buffer into out buffer under key schedule s
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL
* @note Assumes s was initialized by aes_set_encrypt_key
* out and in point to 16 byte buffers
* @param out IN/OUT -- buffer to receive ciphertext block
* @param in IN -- a plaintext block to encrypt
* @param s IN -- initialized AES key schedule
*/
int tc_aes_decrypt(uint8_t *out, const uint8_t *in,
const TCAesKeySched_t s);
#ifdef __cplusplus
}
#endif
#endif /* __TC_AES_H__ */

View File

@@ -0,0 +1,151 @@
/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to a CBC mode implementation.
*
* Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of
* operation defined in SP 800-38a. It can be used with any block
* cipher to provide confidentiality of strings whose lengths are
* multiples of the block_size of the underlying block cipher.
* TinyCrypt hard codes AES as the block cipher.
*
* Security: CBC mode provides data confidentiality given that the maximum
* number q of blocks encrypted under a single key satisfies
* q < 2^63, which is not a practical constraint (it is considered a
* good practice to replace the encryption when q == 2^56). CBC mode
* provides NO data integrity.
*
* CBC mode assumes that the IV value input into the
* tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library
* provides HMAC-PRNG module, which generates suitable IVs. Other
* methods for generating IVs are acceptable, provided that the
* values of the IVs generated appear random to any adversary,
* including someone with complete knowledge of the system design.
*
* The randomness property on which CBC mode's security depends is
* the unpredictability of the IV. Since it is unpredictable, this
* means in practice that CBC mode requires that the IV is stored
* somehow with the ciphertext in order to recover the plaintext.
*
* TinyCrypt CBC encryption prepends the IV to the ciphertext,
* because this affords a more efficient (few buffers) decryption.
* Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always
* 16 bytes larger than the plaintext buffer.
*
* Requires: AES-128
*
* Usage: 1) call tc_cbc_mode_encrypt to encrypt data.
*
* 2) call tc_cbc_mode_decrypt to decrypt data.
*
*/
#ifndef __TC_CBC_MODE_H__
#define __TC_CBC_MODE_H__
#include <tinycrypt/aes.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief CBC encryption procedure
* CBC encrypts inlen bytes of the in buffer into the out buffer
* using the encryption key schedule provided, prepends iv to out
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* out == NULL or
* in == NULL or
* ctr == NULL or
* sched == NULL or
* inlen == 0 or
* (inlen % TC_AES_BLOCK_SIZE) != 0 or
* (outlen % TC_AES_BLOCK_SIZE) != 0 or
* outlen != inlen + TC_AES_BLOCK_SIZE
* @note Assumes: - sched has been configured by aes_set_encrypt_key
* - iv contains a 16 byte random string
* - out buffer is large enough to hold the ciphertext + iv
* - out buffer is a contiguous buffer
* - in holds the plaintext and is a contiguous buffer
* - inlen gives the number of bytes in the in buffer
* @param out IN/OUT -- buffer to receive the ciphertext
* @param outlen IN -- length of ciphertext buffer in bytes
* @param in IN -- plaintext to encrypt
* @param inlen IN -- length of plaintext buffer in bytes
* @param iv IN -- the IV for the this encrypt/decrypt
* @param sched IN -- AES key schedule for this encrypt
*/
int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, const uint8_t *iv,
const TCAesKeySched_t sched);
/**
* @brief CBC decryption procedure
* CBC decrypts inlen bytes of the in buffer into the out buffer
* using the provided encryption key schedule
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* out == NULL or
* in == NULL or
* sched == NULL or
* inlen == 0 or
* outlen == 0 or
* (inlen % TC_AES_BLOCK_SIZE) != 0 or
* (outlen % TC_AES_BLOCK_SIZE) != 0 or
* outlen != inlen + TC_AES_BLOCK_SIZE
* @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are
* contiguous. This allows for a very efficient decryption
* algorithm that would not otherwise be possible
* - sched was configured by aes_set_decrypt_key
* - out buffer is large enough to hold the decrypted plaintext
* and is a contiguous buffer
* - inlen gives the number of bytes in the in buffer
* @param out IN/OUT -- buffer to receive decrypted data
* @param outlen IN -- length of plaintext buffer in bytes
* @param in IN -- ciphertext to decrypt, including IV
* @param inlen IN -- length of ciphertext buffer in bytes
* @param iv IN -- the IV for the this encrypt/decrypt
* @param sched IN -- AES key schedule for this decrypt
*
*/
int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, const uint8_t *iv,
const TCAesKeySched_t sched);
#ifdef __cplusplus
}
#endif
#endif /* __TC_CBC_MODE_H__ */

View File

@@ -0,0 +1,211 @@
/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to a CCM mode implementation.
*
* Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of
* operation defined in SP 800-38C.
*
* TinyCrypt CCM implementation accepts:
*
* 1) Both non-empty payload and associated data (it encrypts and
* authenticates the payload and also authenticates the associated
* data);
* 2) Non-empty payload and empty associated data (it encrypts and
* authenticates the payload);
* 3) Non-empty associated data and empty payload (it degenerates to
* an authentication mode on the associated data).
*
* TinyCrypt CCM implementation accepts associated data of any length
* between 0 and (2^16 - 2^8) bytes.
*
* Security: The mac length parameter is an important parameter to estimate the
* security against collision attacks (that aim at finding different
* messages that produce the same authentication tag). TinyCrypt CCM
* implementation accepts any even integer between 4 and 16, as
* suggested in SP 800-38C.
*
* RFC-3610, which also specifies CCM, presents a few relevant
* security suggestions, such as: it is recommended for most
* applications to use a mac length greater than 8. Besides, the
* usage of the same nonce for two different messages which are
* encrypted with the same key destroys the security of CCM mode.
*
* Requires: AES-128
*
* Usage: 1) call tc_ccm_config to configure.
*
* 2) call tc_ccm_mode_encrypt to encrypt data and generate tag.
*
* 3) call tc_ccm_mode_decrypt to decrypt data and verify tag.
*/
#ifndef __TC_CCM_MODE_H__
#define __TC_CCM_MODE_H__
#include <tinycrypt/aes.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */
#define TC_CCM_AAD_MAX_BYTES 0xff00
/* max message size in bytes: 2^(8L) = 2^16 = 65536 */
#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000
/* struct tc_ccm_mode_struct represents the state of a CCM computation */
typedef struct tc_ccm_mode_struct {
TCAesKeySched_t sched; /* AES key schedule */
uint8_t *nonce; /* nonce required by CCM */
unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */
} *TCCcmMode_t;
/**
* @brief CCM configuration procedure
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* c == NULL or
* sched == NULL or
* nonce == NULL or
* mlen != {4, 6, 8, 10, 12, 16}
* @param c -- CCM state
* @param sched IN -- AES key schedule
* @param nonce IN - nonce
* @param nlen -- nonce length in bytes
* @param mlen -- mac length in bytes (parameter t in SP-800 38C)
*/
int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
unsigned int nlen, unsigned int mlen);
/**
* @brief CCM tag generation and encryption procedure
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* out == NULL or
* c == NULL or
* ((plen > 0) and (payload == NULL)) or
* ((alen > 0) and (associated_data == NULL)) or
* (alen >= TC_CCM_AAD_MAX_BYTES) or
* (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
* (olen < plen + maclength)
*
* @param out OUT -- encrypted data
* @param olen IN -- output length in bytes
* @param associated_data IN -- associated data
* @param alen IN -- associated data length in bytes
* @param payload IN -- payload
* @param plen IN -- payload length in bytes
* @param c IN -- CCM state
*
* @note: out buffer should be at least (plen + c->mlen) bytes long.
*
* @note: The sequence b for encryption is formatted as follows:
* b = [FLAGS | nonce | counter ], where:
* FLAGS is 1 byte long
* nonce is 13 bytes long
* counter is 2 bytes long
* The byte FLAGS is composed by the following 8 bits:
* 0-2 bits: used to represent the value of q-1
* 3-7 btis: always 0's
*
* @note: The sequence b for authentication is formatted as follows:
* b = [FLAGS | nonce | length(mac length)], where:
* FLAGS is 1 byte long
* nonce is 13 bytes long
* length(mac length) is 2 bytes long
* The byte FLAGS is composed by the following 8 bits:
* 0-2 bits: used to represent the value of q-1
* 3-5 bits: mac length (encoded as: (mlen-2)/2)
* 6: Adata (0 if alen == 0, and 1 otherwise)
* 7: always 0
*/
int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
const uint8_t *associated_data,
unsigned int alen, const uint8_t *payload,
unsigned int plen, TCCcmMode_t c);
/**
* @brief CCM decryption and tag verification procedure
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* out == NULL or
* c == NULL or
* ((plen > 0) and (payload == NULL)) or
* ((alen > 0) and (associated_data == NULL)) or
* (alen >= TC_CCM_AAD_MAX_BYTES) or
* (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
* (olen < plen - c->mlen)
*
* @param out OUT -- decrypted data
* @param associated_data IN -- associated data
* @param alen IN -- associated data length in bytes
* @param payload IN -- payload
* @param plen IN -- payload length in bytes
* @param c IN -- CCM state
*
* @note: out buffer should be at least (plen - c->mlen) bytes long.
*
* @note: The sequence b for encryption is formatted as follows:
* b = [FLAGS | nonce | counter ], where:
* FLAGS is 1 byte long
* nonce is 13 bytes long
* counter is 2 bytes long
* The byte FLAGS is composed by the following 8 bits:
* 0-2 bits: used to represent the value of q-1
* 3-7 btis: always 0's
*
* @note: The sequence b for authentication is formatted as follows:
* b = [FLAGS | nonce | length(mac length)], where:
* FLAGS is 1 byte long
* nonce is 13 bytes long
* length(mac length) is 2 bytes long
* The byte FLAGS is composed by the following 8 bits:
* 0-2 bits: used to represent the value of q-1
* 3-5 bits: mac length (encoded as: (mlen-2)/2)
* 6: Adata (0 if alen == 0, and 1 otherwise)
* 7: always 0
*/
int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
const uint8_t *associated_data,
unsigned int alen, const uint8_t *payload, unsigned int plen,
TCCcmMode_t c);
#ifdef __cplusplus
}
#endif
#endif /* __TC_CCM_MODE_H__ */

View File

@@ -0,0 +1,194 @@
/* cmac_mode.h -- interface to a CMAC implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to a CMAC implementation.
*
* Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm
* for computing a MAC using a block cipher. It can compute the MAC
* for a byte string of any length. It is distinguished from CBC-MAC
* in the processing of the final message block; CMAC uses a
* different technique to compute the final message block is full
* size or only partial, while CBC-MAC uses the same technique for
* both. This difference permits CMAC to be applied to variable
* length messages, while all messages authenticated by CBC-MAC must
* be the same length.
*
* Security: AES128-CMAC mode of operation offers 64 bits of security against
* collision attacks. Note however that an external attacker cannot
* generate the tags him/herself without knowing the MAC key. In this
* sense, to attack the collision property of AES128-CMAC, an
* external attacker would need the cooperation of the legal user to
* produce an exponentially high number of tags (e.g. 2^64) to
* finally be able to look for collisions and benefit from them. As
* an extra precaution, the current implementation allows to at most
* 2^48 calls to the tc_cmac_update function before re-calling
* tc_cmac_setup (allowing a new key to be set), as suggested in
* Appendix B of SP 800-38B.
*
* Requires: AES-128
*
* Usage: This implementation provides a "scatter-gather" interface, so that
* the CMAC value can be computed incrementally over a message
* scattered in different segments throughout memory. Experience shows
* this style of interface tends to minimize the burden of programming
* correctly. Like all symmetric key operations, it is session
* oriented.
*
* To begin a CMAC session, use tc_cmac_setup to initialize a struct
* tc_cmac_struct with encryption key and buffer. Our implementation
* always assume that the AES key to be the same size as the block
* cipher block size. Once setup, this data structure can be used for
* many CMAC computations.
*
* Once the state has been setup with a key, computing the CMAC of
* some data requires three steps:
*
* (1) first use tc_cmac_init to initialize a new CMAC computation.
* (2) next mix all of the data into the CMAC computation state using
* tc_cmac_update. If all of the data resides in a single data
* segment then only one tc_cmac_update call is needed; if data
* is scattered throughout memory in n data segments, then n calls
* will be needed. CMAC IS ORDER SENSITIVE, to be able to detect
* attacks that swap bytes, so the order in which data is mixed
* into the state is critical!
* (3) Once all of the data for a message has been mixed, use
* tc_cmac_final to compute the CMAC tag value.
*
* Steps (1)-(3) can be repeated as many times as you want to CMAC
* multiple messages. A practical limit is 2^48 1K messages before you
* have to change the key.
*
* Once you are done computing CMAC with a key, it is a good idea to
* destroy the state so an attacker cannot recover the key; use
* tc_cmac_erase to accomplish this.
*/
#ifndef __TC_CMAC_MODE_H__
#define __TC_CMAC_MODE_H__
#include <tinycrypt/aes.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* padding for last message block */
#define TC_CMAC_PADDING 0x80
/* struct tc_cmac_struct represents the state of a CMAC computation */
typedef struct tc_cmac_struct {
/* initialization vector */
uint8_t iv[TC_AES_BLOCK_SIZE];
/* used if message length is a multiple of block_size bytes */
uint8_t K1[TC_AES_BLOCK_SIZE];
/* used if message length isn't a multiple block_size bytes */
uint8_t K2[TC_AES_BLOCK_SIZE];
/* where to put bytes that didn't fill a block */
uint8_t leftover[TC_AES_BLOCK_SIZE];
/* identifies the encryption key */
unsigned int keyid;
/* next available leftover location */
unsigned int leftover_offset;
/* AES key schedule */
TCAesKeySched_t sched;
/* calls to tc_cmac_update left before re-key */
uint64_t countdown;
} *TCCmacState_t;
/**
* @brief Configures the CMAC state to use the given AES key
* @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
* returns TC_CRYPTO_FAIL (0) if:
* s == NULL or
* key == NULL
*
* @param s IN/OUT -- the state to set up
* @param key IN -- the key to use
* @param sched IN -- AES key schedule
*/
int tc_cmac_setup(TCCmacState_t s, const uint8_t *key,
TCAesKeySched_t sched);
/**
* @brief Erases the CMAC state
* @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
* returns TC_CRYPTO_FAIL (0) if:
* s == NULL
*
* @param s IN/OUT -- the state to erase
*/
int tc_cmac_erase(TCCmacState_t s);
/**
* @brief Initializes a new CMAC computation
* @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state
* returns TC_CRYPTO_FAIL (0) if:
* s == NULL
*
* @param s IN/OUT -- the state to initialize
*/
int tc_cmac_init(TCCmacState_t s);
/**
* @brief Incrementally computes CMAC over the next data segment
* @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state
* returns TC_CRYPTO_FAIL (0) if:
* s == NULL or
* if data == NULL when dlen > 0
*
* @param s IN/OUT -- the CMAC state
* @param data IN -- the next data segment to MAC
* @param dlen IN -- the length of data in bytes
*/
int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen);
/**
* @brief Generates the tag from the CMAC state
* @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag
* returns TC_CRYPTO_FAIL (0) if:
* tag == NULL or
* s == NULL
*
* @param tag OUT -- the CMAC tag
* @param s IN -- CMAC state
*/
int tc_cmac_final(uint8_t *tag, TCCmacState_t s);
#ifdef __cplusplus
}
#endif
#endif /* __TC_CMAC_MODE_H__ */

View File

@@ -0,0 +1,61 @@
/* constants.h - TinyCrypt interface to constants */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to constants.
*
*/
#ifndef __TC_CONSTANTS_H__
#define __TC_CONSTANTS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#ifndef NULL
#define NULL ((void *)0)
#endif
#define TC_CRYPTO_SUCCESS 1
#define TC_CRYPTO_FAIL 0
#define TC_ZERO_BYTE 0x00
#ifdef __cplusplus
}
#endif
#endif /* __TC_CONSTANTS_H__ */

View File

@@ -0,0 +1,110 @@
/* ctr_mode.h - TinyCrypt interface to CTR mode */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to CTR mode.
*
* Overview: CTR (pronounced "counter") mode is a NIST approved mode of
* operation defined in SP 800-38a. It can be used with any
* block cipher to provide confidentiality of strings of any
* length. TinyCrypt hard codes AES128 as the block cipher.
*
* Security: CTR mode achieves confidentiality only if the counter value is
* never reused with a same encryption key. If the counter is
* repeated, than an adversary might be able to defeat the scheme.
*
* A usual method to ensure different counter values refers to
* initialize the counter in a given value (0, for example) and
* increases it every time a new block is enciphered. This naturally
* leaves to a limitation on the number q of blocks that can be
* enciphered using a same key: q < 2^(counter size).
*
* TinyCrypt uses a counter of 32 bits. This means that after 2^32
* block encryptions, the counter will be reused (thus losing CBC
* security). 2^32 block encryptions should be enough for most of
* applications targeting constrained devices. Applications intended
* to encrypt a larger number of blocks must replace the key after
* 2^32 block encryptions.
*
* CTR mode provides NO data integrity.
*
* Requires: AES-128
*
* Usage: 1) call tc_ctr_mode to process the data to encrypt/decrypt.
*
*/
#ifndef __TC_CTR_MODE_H__
#define __TC_CTR_MODE_H__
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief CTR mode encryption/decryption procedure.
* CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* out == NULL or
* in == NULL or
* ctr == NULL or
* sched == NULL or
* inlen == 0 or
* outlen == 0 or
* inlen != outlen
* @note Assumes:- The current value in ctr has NOT been used with sched
* - out points to inlen bytes
* - in points to inlen bytes
* - ctr is an integer counter in littleEndian format
* - sched was initialized by aes_set_encrypt_key
* @param out OUT -- produced ciphertext (plaintext)
* @param outlen IN -- length of ciphertext buffer in bytes
* @param in IN -- data to encrypt (or decrypt)
* @param inlen IN -- length of input data in bytes
* @param ctr IN/OUT -- the current counter value
* @param blk_off IN/OUT -- the offset in the block
* @param sched IN -- an initialized AES key schedule
*/
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, uint8_t *ctr, uint32_t *blk_off,
const TCAesKeySched_t sched);
#ifdef __cplusplus
}
#endif
#endif /* __TC_CTR_MODE_H__ */

View File

@@ -0,0 +1,166 @@
/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */
/*
* Copyright (c) 2016, Chris Morrison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to a CTR-PRNG implementation.
*
* Overview: A pseudo-random number generator (PRNG) generates a sequence
* of numbers that have a distribution close to the one expected
* for a sequence of truly random numbers. The NIST Special
* Publication 800-90A specifies several mechanisms to generate
* sequences of pseudo random numbers, including the CTR-PRNG one
* which is based on AES. TinyCrypt implements CTR-PRNG with
* AES-128.
*
* Security: A cryptographically secure PRNG depends on the existence of an
* entropy source to provide a truly random seed as well as the
* security of the primitives used as the building blocks (AES-128
* in this instance).
*
* Requires: - AES-128
*
* Usage: 1) call tc_ctr_prng_init to seed the prng context
*
* 2) call tc_ctr_prng_reseed to mix in additional entropy into
* the prng context
*
* 3) call tc_ctr_prng_generate to output the pseudo-random data
*
* 4) call tc_ctr_prng_uninstantiate to zero out the prng context
*/
#ifndef __TC_CTR_PRNG_H__
#define __TC_CTR_PRNG_H__
#include <tinycrypt/aes.h>
#define TC_CTR_PRNG_RESEED_REQ -1
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
/* updated each time another BLOCKLEN_BYTES bytes are produced */
uint8_t V[TC_AES_BLOCK_SIZE];
/* updated whenever the PRNG is reseeded */
struct tc_aes_key_sched_struct key;
/* number of requests since initialization/reseeding */
uint64_t reseedCount;
} TCCtrPrng_t;
/**
* @brief CTR-PRNG initialization procedure
* Initializes prng context with entropy and personalization string (if any)
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* ctx == NULL,
* entropy == NULL,
* entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
* @note Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of
* both the entropy and personalization inputs are used -
* supplying additional bytes has no effect.
* @param ctx IN/OUT -- the PRNG context to initialize
* @param entropy IN -- entropy used to seed the PRNG
* @param entropyLen IN -- entropy length in bytes
* @param personalization IN -- personalization string used to seed the PRNG
* (may be null)
* @param plen IN -- personalization length in bytes
*
*/
int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
uint8_t const * const entropy,
unsigned int entropyLen,
uint8_t const * const personalization,
unsigned int pLen);
/**
* @brief CTR-PRNG reseed procedure
* Mixes entropy and additional_input into the prng context
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* ctx == NULL,
* entropy == NULL,
* entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
* @note It is better to reseed an existing prng context rather than
* re-initialise, so that any existing entropy in the context is
* presereved. This offers some protection against undetected failures
* of the entropy source.
* @note Assumes tc_ctr_prng_init has been called for ctx
* @param ctx IN/OUT -- the PRNG state
* @param entropy IN -- entropy to mix into the prng
* @param entropylen IN -- length of entropy in bytes
* @param additional_input IN -- additional input to the prng (may be null)
* @param additionallen IN -- additional input length in bytes
*/
int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
uint8_t const * const entropy,
unsigned int entropyLen,
uint8_t const * const additional_input,
unsigned int additionallen);
/**
* @brief CTR-PRNG generate procedure
* Generates outlen pseudo-random bytes into out buffer, updates prng
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed
* returns TC_CRYPTO_FAIL (0) if:
* ctx == NULL,
* out == NULL,
* outlen >= 2^16
* @note Assumes tc_ctr_prng_init has been called for ctx
* @param ctx IN/OUT -- the PRNG context
* @param additional_input IN -- additional input to the prng (may be null)
* @param additionallen IN -- additional input length in bytes
* @param out IN/OUT -- buffer to receive output
* @param outlen IN -- size of out buffer in bytes
*/
int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
uint8_t const * const additional_input,
unsigned int additionallen,
uint8_t * const out,
unsigned int outlen);
/**
* @brief CTR-PRNG uninstantiate procedure
* Zeroes the internal state of the supplied prng context
* @return none
* @param ctx IN/OUT -- the PRNG context
*/
void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx);
#ifdef __cplusplus
}
#endif
#endif /* __TC_CTR_PRNG_H__ */

View File

@@ -0,0 +1,545 @@
/* ecc.h - TinyCrypt interface to common ECC functions */
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to common ECC functions.
*
* Overview: This software is an implementation of common functions
* necessary to elliptic curve cryptography. This implementation uses
* curve NIST p-256.
*
* Security: The curve NIST p-256 provides approximately 128 bits of security.
*
*/
#ifndef __TC_UECC_H__
#define __TC_UECC_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Word size (4 bytes considering 32-bits architectures) */
#define uECC_WORD_SIZE 4
/* setting max number of calls to prng: */
#ifndef uECC_RNG_MAX_TRIES
#define uECC_RNG_MAX_TRIES 64
#endif
/* defining data types to store word and bit counts: */
typedef int8_t wordcount_t;
typedef int16_t bitcount_t;
/* defining data type for comparison result: */
typedef int8_t cmpresult_t;
/* defining data type to store ECC coordinate/point in 32bits words: */
typedef unsigned int uECC_word_t;
/* defining data type to store an ECC coordinate/point in 64bits words: */
typedef uint64_t uECC_dword_t;
/* defining masks useful for ecc computations: */
#define HIGH_BIT_SET 0x80000000
#define uECC_WORD_BITS 32
#define uECC_WORD_BITS_SHIFT 5
#define uECC_WORD_BITS_MASK 0x01F
/* Number of words of 32 bits to represent an element of the the curve p-256: */
#define NUM_ECC_WORDS 8
/* Number of bytes to represent an element of the the curve p-256: */
#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS)
/* structure that represents an elliptic curve (e.g. p256):*/
struct uECC_Curve_t;
typedef const struct uECC_Curve_t * uECC_Curve;
struct uECC_Curve_t {
wordcount_t num_words;
wordcount_t num_bytes;
bitcount_t num_n_bits;
uECC_word_t p[NUM_ECC_WORDS];
uECC_word_t n[NUM_ECC_WORDS];
uECC_word_t G[NUM_ECC_WORDS * 2];
uECC_word_t b[NUM_ECC_WORDS];
void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1,
uECC_Curve curve);
void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
};
/*
* @brief computes doubling of point ion jacobian coordinates, in place.
* @param X1 IN/OUT -- x coordinate
* @param Y1 IN/OUT -- y coordinate
* @param Z1 IN/OUT -- z coordinate
* @param curve IN -- elliptic curve
*/
void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * Z1, uECC_Curve curve);
/*
* @brief Computes x^3 + ax + b. result must not overlap x.
* @param result OUT -- x^3 + ax + b
* @param x IN -- value of x
* @param curve IN -- elliptic curve
*/
void x_side_default(uECC_word_t *result, const uECC_word_t *x,
uECC_Curve curve);
/*
* @brief Computes result = product % curve_p
* from http://www.nsa.gov/ia/_files/nist-routines.pdf
* @param result OUT -- product % curve_p
* @param product IN -- value to be reduced mod curve_p
*/
void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product);
/* Bytes to words ordering: */
#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
#define BITS_TO_WORDS(num_bits) \
((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
/* definition of curve NIST p-256: */
static const struct uECC_Curve_t curve_secp256r1 = {
NUM_ECC_WORDS,
NUM_ECC_BYTES,
256, /* num_n_bits */ {
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
}, {
BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
}, {
BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
}, {
BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
},
&double_jacobian_default,
&x_side_default,
&vli_mmod_fast_secp256r1
};
uECC_Curve uECC_secp256r1(void);
/*
* @brief Generates a random integer in the range 0 < random < top.
* Both random and top have num_words words.
* @param random OUT -- random integer in the range 0 < random < top
* @param top IN -- upper limit
* @param num_words IN -- number of words
* @return a random integer in the range 0 < random < top
*/
int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
wordcount_t num_words);
/* uECC_RNG_Function type
* The RNG function should fill 'size' random bytes into 'dest'. It should
* return 1 if 'dest' was filled with random data, or 0 if the random data could
* not be generated. The filled-in values should be either truly random, or from
* a cryptographically-secure PRNG.
*
* A correctly functioning RNG function must be set (using uECC_set_rng())
* before calling uECC_make_key() or uECC_sign().
*
* Setting a correctly functioning RNG function improves the resistance to
* side-channel attacks for uECC_shared_secret().
*
* A correct RNG function is set by default. If you are building on another
* POSIX-compliant system that supports /dev/random or /dev/urandom, you can
* define uECC_POSIX to use the predefined RNG.
*/
typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size);
/*
* @brief Set the function that will be used to generate random bytes. The RNG
* function should return 1 if the random data was generated, or 0 if the random
* data could not be generated.
*
* @note On platforms where there is no predefined RNG function, this must be
* called before uECC_make_key() or uECC_sign() are used.
*
* @param rng_function IN -- function that will be used to generate random bytes
*/
void uECC_set_rng(uECC_RNG_Function rng_function);
/*
* @brief provides current uECC_RNG_Function.
* @return Returns the function that will be used to generate random bytes.
*/
uECC_RNG_Function uECC_get_rng(void);
/*
* @brief computes the size of a private key for the curve in bytes.
* @param curve IN -- elliptic curve
* @return size of a private key for the curve in bytes.
*/
int uECC_curve_private_key_size(uECC_Curve curve);
/*
* @brief computes the size of a public key for the curve in bytes.
* @param curve IN -- elliptic curve
* @return the size of a public key for the curve in bytes.
*/
int uECC_curve_public_key_size(uECC_Curve curve);
/*
* @brief Compute the corresponding public key for a private key.
* @param private_key IN -- The private key to compute the public key for
* @param public_key OUT -- Will be filled in with the corresponding public key
* @param curve
* @return Returns 1 if key was computed successfully, 0 if an error occurred.
*/
int uECC_compute_public_key(const uint8_t *private_key,
uint8_t *public_key, uECC_Curve curve);
/*
* @brief Compute public-key.
* @return corresponding public-key.
* @param result OUT -- public-key
* @param private_key IN -- private-key
* @param curve IN -- elliptic curve
*/
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
uECC_word_t *private_key, uECC_Curve curve);
/*
* @brief Regularize the bitcount for the private key so that attackers cannot
* use a side channel attack to learn the number of leading zeros.
* @return Regularized k
* @param k IN -- private-key
* @param k0 IN/OUT -- regularized k
* @param k1 IN/OUT -- regularized k
* @param curve IN -- elliptic curve
*/
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
uECC_word_t *k1, uECC_Curve curve);
/*
* @brief Point multiplication algorithm using Montgomery's ladder with co-Z
* coordinates. See http://eprint.iacr.org/2011/338.pdf.
* @note Result may overlap point.
* @param result OUT -- returns scalar*point
* @param point IN -- elliptic curve point
* @param scalar IN -- scalar
* @param initial_Z IN -- initial value for z
* @param num_bits IN -- number of bits in scalar
* @param curve IN -- elliptic curve
*/
void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
const uECC_word_t * scalar, const uECC_word_t * initial_Z,
bitcount_t num_bits, uECC_Curve curve);
/*
* @brief Constant-time comparison to zero - secure way to compare long integers
* @param vli IN -- very long integer
* @param num_words IN -- number of words in the vli
* @return 1 if vli == 0, 0 otherwise.
*/
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
/*
* @brief Check if 'point' is the point at infinity
* @param point IN -- elliptic curve point
* @param curve IN -- elliptic curve
* @return if 'point' is the point at infinity, 0 otherwise.
*/
uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve);
/*
* @brief computes the sign of left - right, in constant time.
* @param left IN -- left term to be compared
* @param right IN -- right term to be compared
* @param num_words IN -- number of words
* @return the sign of left - right
*/
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
wordcount_t num_words);
/*
* @brief computes sign of left - right, not in constant time.
* @note should not be used if inputs are part of a secret
* @param left IN -- left term to be compared
* @param right IN -- right term to be compared
* @param num_words IN -- number of words
* @return the sign of left - right
*/
cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right,
wordcount_t num_words);
/*
* @brief Computes result = (left - right) % mod.
* @note Assumes that (left < mod) and (right < mod), and that result does not
* overlap mod.
* @param result OUT -- (left - right) % mod
* @param left IN -- leftright term in modular subtraction
* @param right IN -- right term in modular subtraction
* @param mod IN -- mod
* @param num_words IN -- number of words
*/
void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words);
/*
* @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or
* P => P', Q => P + Q
* @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z)
* @param X1 IN -- x coordinate of P
* @param Y1 IN -- y coordinate of P
* @param X2 IN -- x coordinate of Q
* @param Y2 IN -- y coordinate of Q
* @param curve IN -- elliptic curve
*/
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2,
uECC_word_t * Y2, uECC_Curve curve);
/*
* @brief Computes (x1 * z^2, y1 * z^3)
* @param X1 IN -- previous x1 coordinate
* @param Y1 IN -- previous y1 coordinate
* @param Z IN -- z value
* @param curve IN -- elliptic curve
*/
void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
uECC_Curve curve);
/*
* @brief Check if bit is set.
* @return Returns nonzero if bit 'bit' of vli is set.
* @warning It is assumed that the value provided in 'bit' is within the
* boundaries of the word-array 'vli'.
* @note The bit ordering layout assumed for vli is: {31, 30, ..., 0},
* {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting
* of 4 uECC_word_t elements.
*/
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
/*
* @brief Computes result = product % mod, where product is 2N words long.
* @param result OUT -- product % mod
* @param mod IN -- module
* @param num_words IN -- number of words
* @warning Currently only designed to work for curve_p or curve_n.
*/
void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
const uECC_word_t *mod, wordcount_t num_words);
/*
* @brief Computes modular product (using curve->mmod_fast)
* @param result OUT -- (left * right) mod % curve_p
* @param left IN -- left term in product
* @param right IN -- right term in product
* @param curve IN -- elliptic curve
*/
void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, uECC_Curve curve);
/*
* @brief Computes result = left - right.
* @note Can modify in place.
* @param result OUT -- left - right
* @param left IN -- left term in subtraction
* @param right IN -- right term in subtraction
* @param num_words IN -- number of words
* @return borrow
*/
uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, wordcount_t num_words);
/*
* @brief Constant-time comparison function(secure way to compare long ints)
* @param left IN -- left term in comparison
* @param right IN -- right term in comparison
* @param num_words IN -- number of words
* @return Returns 0 if left == right, 1 otherwise.
*/
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
wordcount_t num_words);
/*
* @brief Computes (left * right) % mod
* @param result OUT -- (left * right) % mod
* @param left IN -- left term in product
* @param right IN -- right term in product
* @param mod IN -- mod
* @param num_words IN -- number of words
*/
void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words);
/*
* @brief Computes (1 / input) % mod
* @note All VLIs are the same size.
* @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide"
* @param result OUT -- (1 / input) % mod
* @param input IN -- value to be modular inverted
* @param mod IN -- mod
* @param num_words -- number of words
*/
void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
const uECC_word_t *mod, wordcount_t num_words);
/*
* @brief Sets dest = src.
* @param dest OUT -- destination buffer
* @param src IN -- origin buffer
* @param num_words IN -- number of words
*/
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
wordcount_t num_words);
/*
* @brief Computes (left + right) % mod.
* @note Assumes that (left < mod) and right < mod), and that result does not
* overlap mod.
* @param result OUT -- (left + right) % mod.
* @param left IN -- left term in addition
* @param right IN -- right term in addition
* @param mod IN -- mod
* @param num_words IN -- number of words
*/
void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words);
/*
* @brief Counts the number of bits required to represent vli.
* @param vli IN -- very long integer
* @param max_words IN -- number of words
* @return number of bits in given vli
*/
bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
const wordcount_t max_words);
/*
* @brief Erases (set to 0) vli
* @param vli IN -- very long integer
* @param num_words IN -- number of words
*/
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
/*
* @brief check if it is a valid point in the curve
* @param point IN -- point to be checked
* @param curve IN -- elliptic curve
* @return 0 if point is valid
* @exception returns -1 if it is a point at infinity
* @exception returns -2 if x or y is smaller than p,
* @exception returns -3 if y^2 != x^3 + ax + b.
*/
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
/*
* @brief Check if a public key is valid.
* @param public_key IN -- The public key to be checked.
* @return returns 0 if the public key is valid
* @exception returns -1 if it is a point at infinity
* @exception returns -2 if x or y is smaller than p,
* @exception returns -3 if y^2 != x^3 + ax + b.
* @exception returns -4 if public key is the group generator.
*
* @note Note that you are not required to check for a valid public key before
* using any other uECC functions. However, you may wish to avoid spending CPU
* time computing a shared secret or verifying a signature using an invalid
* public key.
*/
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
/*
* @brief Converts an integer in uECC native format to big-endian bytes.
* @param bytes OUT -- bytes representation
* @param num_bytes IN -- number of bytes
* @param native IN -- uECC native representation
*/
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
const unsigned int *native);
/*
* @brief Converts big-endian bytes to an integer in uECC native format.
* @param native OUT -- uECC native representation
* @param bytes IN -- bytes representation
* @param num_bytes IN -- number of bytes
*/
void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
int num_bytes);
#ifdef __cplusplus
}
#endif
#endif /* __TC_UECC_H__ */

View File

@@ -0,0 +1,131 @@
/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */
/*
* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to EC-DH implementation.
*
* Overview: This software is an implementation of EC-DH. This implementation
* uses curve NIST p-256.
*
* Security: The curve NIST p-256 provides approximately 128 bits of security.
*/
#ifndef __TC_ECC_DH_H__
#define __TC_ECC_DH_H__
#include <tinycrypt/ecc.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create a public/private key pair.
* @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully
* returns TC_CRYPTO_FAIL (0) if error while generating key pair
*
* @param p_public_key OUT -- Will be filled in with the public key. Must be at
* least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
* must be 64 bytes long.
* @param p_private_key OUT -- Will be filled in with the private key. Must be as
* long as the curve order (for secp256r1, p_private_key must be 32 bytes long).
*
* @note side-channel countermeasure: algorithm strengthened against timing
* attack.
* @warning A cryptographically-secure PRNG function must be set (using
* uECC_set_rng()) before calling uECC_make_key().
*/
int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve);
#ifdef ENABLE_TESTS
/**
* @brief Create a public/private key pair given a specific d.
*
* @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to
* uECC_make_key() function for real applications.
*/
int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key,
unsigned int *d, uECC_Curve curve);
#endif
/**
* @brief Compute a shared secret given your secret key and someone else's
* public key.
* @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully
* returns TC_CRYPTO_FAIL (0) otherwise
*
* @param p_secret OUT -- Will be filled in with the shared secret value. Must be
* the same size as the curve size (for curve secp256r1, secret must be 32 bytes
* long.
* @param p_public_key IN -- The public key of the remote party.
* @param p_private_key IN -- Your private key.
*
* @warning It is recommended to use the output of uECC_shared_secret() as the
* input of a recommended Key Derivation Function (see NIST SP 800-108) in
* order to produce a cryptographically secure symmetric key.
*/
int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key,
uint8_t *p_secret, uECC_Curve curve);
#ifdef __cplusplus
}
#endif
#endif /* __TC_ECC_DH_H__ */

View File

@@ -0,0 +1,139 @@
/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
/*
* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to EC-DSA implementation.
*
* Overview: This software is an implementation of EC-DSA. This implementation
* uses curve NIST p-256.
*
* Security: The curve NIST p-256 provides approximately 128 bits of security.
*
* Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is
* recommended) and pass it in to ecdsa_sign function along with your
* private key and a random number. You must use a new non-predictable
* random number to generate each new signature.
* - To verify a signature: Compute the hash of the signed data using
* the same hash as the signer and pass it to this function along with
* the signer's public key and the signature values (r and s).
*/
#ifndef __TC_ECC_DSA_H__
#define __TC_ECC_DSA_H__
#include <tinycrypt/ecc.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Generate an ECDSA signature for a given hash value.
* @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully
* returns TC_CRYPTO_FAIL (0) if an error occurred.
*
* @param p_private_key IN -- Your private key.
* @param p_message_hash IN -- The hash of the message to sign.
* @param p_hash_size IN -- The size of p_message_hash in bytes.
* @param p_signature OUT -- Will be filled in with the signature value. Must be
* at least 2 * curve size long (for secp256r1, signature must be 64 bytes long).
*
* @warning A cryptographically-secure PRNG function must be set (using
* uECC_set_rng()) before calling uECC_sign().
* @note Usage: Compute a hash of the data you wish to sign (SHA-2 is
* recommended) and pass it in to this function along with your private key.
* @note side-channel countermeasure: algorithm strengthened against timing
* attack.
*/
int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash,
unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve);
#ifdef ENABLE_TESTS
/*
* THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY.
* Refer to uECC_sign() function for real applications.
*/
int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
unsigned int hash_size, uECC_word_t *k, uint8_t *signature,
uECC_Curve curve);
#endif
/**
* @brief Verify an ECDSA signature.
* @return returns TC_SUCCESS (1) if the signature is valid
* returns TC_FAIL (0) if the signature is invalid.
*
* @param p_public_key IN -- The signer's public key.
* @param p_message_hash IN -- The hash of the signed data.
* @param p_hash_size IN -- The size of p_message_hash in bytes.
* @param p_signature IN -- The signature values.
*
* @note Usage: Compute the hash of the signed data using the same hash as the
* signer and pass it to this function along with the signer's public key and
* the signature values (hash_size and signature).
*/
int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash,
unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve);
#ifdef __cplusplus
}
#endif
#endif /* __TC_ECC_DSA_H__ */

View File

@@ -0,0 +1,81 @@
/* uECC_platform_specific.h - Interface to platform specific functions*/
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* uECC_platform_specific.h -- Interface to platform specific functions
*/
#ifndef __UECC_PLATFORM_SPECIFIC_H_
#define __UECC_PLATFORM_SPECIFIC_H_
/*
* The RNG function should fill 'size' random bytes into 'dest'. It should
* return 1 if 'dest' was filled with random data, or 0 if the random data could
* not be generated. The filled-in values should be either truly random, or from
* a cryptographically-secure PRNG.
*
* A cryptographically-secure PRNG function must be set (using uECC_set_rng())
* before calling uECC_make_key() or uECC_sign().
*
* Setting a cryptographically-secure PRNG function improves the resistance to
* side-channel attacks for uECC_shared_secret().
*
* A correct PRNG function is set by default (default_RNG_defined = 1) and works
* for some platforms, such as Unix and Linux. For other platforms, you may need
* to provide another PRNG function.
*/
#define default_RNG_defined 1
int default_CSPRNG(uint8_t *dest, unsigned int size);
#endif /* __UECC_PLATFORM_SPECIFIC_H_ */

View File

@@ -0,0 +1,139 @@
/* hmac.h - TinyCrypt interface to an HMAC implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to an HMAC implementation.
*
* Overview: HMAC is a message authentication code based on hash functions.
* TinyCrypt hard codes SHA-256 as the hash function. A message
* authentication code based on hash functions is also called a
* keyed cryptographic hash function since it performs a
* transformation specified by a key in an arbitrary length data
* set into a fixed length data set (also called tag).
*
* Security: The security of the HMAC depends on the length of the key and
* on the security of the hash function. Note that HMAC primitives
* are much less affected by collision attacks than their
* corresponding hash functions.
*
* Requires: SHA-256
*
* Usage: 1) call tc_hmac_set_key to set the HMAC key.
*
* 2) call tc_hmac_init to initialize a struct hash_state before
* processing the data.
*
* 3) call tc_hmac_update to process the next input segment;
* tc_hmac_update can be called as many times as needed to process
* all of the segments of the input; the order is important.
*
* 4) call tc_hmac_final to out put the tag.
*/
#ifndef __TC_HMAC_H__
#define __TC_HMAC_H__
#include <tinycrypt/sha256.h>
#ifdef __cplusplus
extern "C" {
#endif
struct tc_hmac_state_struct {
/* the internal state required by h */
struct tc_sha256_state_struct hash_state;
/* HMAC key schedule */
uint8_t key[2*TC_SHA256_BLOCK_SIZE];
};
typedef struct tc_hmac_state_struct *TCHmacState_t;
/**
* @brief HMAC set key procedure
* Configures ctx to use key
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if
* ctx == NULL or
* key == NULL or
* key_size == 0
* @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial
* @param key IN -- the HMAC key to configure
* @param key_size IN -- the HMAC key size
*/
int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
unsigned int key_size);
/**
* @brief HMAC init procedure
* Initializes ctx to begin the next HMAC operation
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
* @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init
*/
int tc_hmac_init(TCHmacState_t ctx);
/**
* @brief HMAC update procedure
* Mixes data_length bytes addressed by data into state
* @return returns TC_CRYPTO_SUCCCESS (1)
* returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
* @note Assumes state has been initialized by tc_hmac_init
* @param ctx IN/OUT -- state of HMAC computation so far
* @param data IN -- data to incorporate into state
* @param data_length IN -- size of data in bytes
*/
int tc_hmac_update(TCHmacState_t ctx, const void *data,
unsigned int data_length);
/**
* @brief HMAC final procedure
* Writes the HMAC tag into the tag buffer
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* tag == NULL or
* ctx == NULL or
* key == NULL or
* taglen != TC_SHA256_DIGEST_SIZE
* @note ctx is erased before exiting. This should never be changed/removed.
* @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes
* state has been initialized by tc_hmac_init
* @param tag IN/OUT -- buffer to receive computed HMAC tag
* @param taglen IN -- size of tag in bytes
* @param ctx IN/OUT -- the HMAC state for computing tag
*/
int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx);
#ifdef __cplusplus
}
#endif
#endif /*__TC_HMAC_H__*/

View File

@@ -0,0 +1,164 @@
/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to an HMAC-PRNG implementation.
*
* Overview: A pseudo-random number generator (PRNG) generates a sequence
* of numbers that have a distribution close to the one expected
* for a sequence of truly random numbers. The NIST Special
* Publication 800-90A specifies several mechanisms to generate
* sequences of pseudo random numbers, including the HMAC-PRNG one
* which is based on HMAC. TinyCrypt implements HMAC-PRNG with
* certain modifications from the NIST SP 800-90A spec.
*
* Security: A cryptographically secure PRNG depends on the existence of an
* entropy source to provide a truly random seed as well as the
* security of the primitives used as the building blocks (HMAC and
* SHA256, for TinyCrypt).
*
* The NIST SP 800-90A standard tolerates a null personalization,
* while TinyCrypt requires a non-null personalization. This is
* because a personalization string (the host name concatenated
* with a time stamp, for example) is easily computed and might be
* the last line of defense against failure of the entropy source.
*
* Requires: - SHA-256
* - HMAC
*
* Usage: 1) call tc_hmac_prng_init to set the HMAC key and process the
* personalization data.
*
* 2) call tc_hmac_prng_reseed to process the seed and additional
* input.
*
* 3) call tc_hmac_prng_generate to out put the pseudo-random data.
*/
#ifndef __TC_HMAC_PRNG_H__
#define __TC_HMAC_PRNG_H__
#include <tinycrypt/sha256.h>
#include <tinycrypt/hmac.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TC_HMAC_PRNG_RESEED_REQ -1
struct tc_hmac_prng_struct {
/* the HMAC instance for this PRNG */
struct tc_hmac_state_struct h;
/* the PRNG key */
uint8_t key[TC_SHA256_DIGEST_SIZE];
/* PRNG state */
uint8_t v[TC_SHA256_DIGEST_SIZE];
/* calls to tc_hmac_prng_generate left before re-seed */
unsigned int countdown;
};
typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
/**
* @brief HMAC-PRNG initialization procedure
* Initializes prng with personalization, disables tc_hmac_prng_generate
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* prng == NULL,
* personalization == NULL,
* plen > MAX_PLEN
* @note Assumes: - personalization != NULL.
* The personalization is a platform unique string (e.g., the host
* name) and is the last line of defense against failure of the
* entropy source
* @warning NIST SP 800-90A specifies 3 items as seed material during
* initialization: entropy seed, personalization, and an optional
* nonce. TinyCrypts requires instead a non-null personalization
* (which is easily computed) and indirectly requires an entropy
* seed (since the reseed function is mandatorily called after
* init)
* @param prng IN/OUT -- the PRNG state to initialize
* @param personalization IN -- personalization string
* @param plen IN -- personalization length in bytes
*/
int tc_hmac_prng_init(TCHmacPrng_t prng,
const uint8_t *personalization,
unsigned int plen);
/**
* @brief HMAC-PRNG reseed procedure
* Mixes seed into prng, enables tc_hmac_prng_generate
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* prng == NULL,
* seed == NULL,
* seedlen < MIN_SLEN,
* seendlen > MAX_SLEN,
* additional_input != (const uint8_t *) 0 && additionallen == 0,
* additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN
* @note Assumes:- tc_hmac_prng_init has been called for prng
* - seed has sufficient entropy.
*
* @param prng IN/OUT -- the PRNG state
* @param seed IN -- entropy to mix into the prng
* @param seedlen IN -- length of seed in bytes
* @param additional_input IN -- additional input to the prng
* @param additionallen IN -- additional input length in bytes
*/
int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed,
unsigned int seedlen, const uint8_t *additional_input,
unsigned int additionallen);
/**
* @brief HMAC-PRNG generate procedure
* Generates outlen pseudo-random bytes into out buffer, updates prng
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed
* returns TC_CRYPTO_FAIL (0) if:
* out == NULL,
* prng == NULL,
* outlen == 0,
* outlen >= MAX_OUT
* @note Assumes tc_hmac_prng_init has been called for prng
* @param out IN/OUT -- buffer to receive output
* @param outlen IN -- size of out buffer in bytes
* @param prng IN/OUT -- the PRNG state
*/
int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng);
#ifdef __cplusplus
}
#endif
#endif /* __TC_HMAC_PRNG_H__ */

View File

@@ -0,0 +1,129 @@
/* sha256.h - TinyCrypt interface to a SHA-256 implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to a SHA-256 implementation.
*
* Overview: SHA-256 is a NIST approved cryptographic hashing algorithm
* specified in FIPS 180. A hash algorithm maps data of arbitrary
* size to data of fixed length.
*
* Security: SHA-256 provides 128 bits of security against collision attacks
* and 256 bits of security against pre-image attacks. SHA-256 does
* NOT behave like a random oracle, but it can be used as one if
* the string being hashed is prefix-free encoded before hashing.
*
* Usage: 1) call tc_sha256_init to initialize a struct
* tc_sha256_state_struct before hashing a new string.
*
* 2) call tc_sha256_update to hash the next string segment;
* tc_sha256_update can be called as many times as needed to hash
* all of the segments of a string; the order is important.
*
* 3) call tc_sha256_final to out put the digest from a hashing
* operation.
*/
#ifndef __TC_SHA256_H__
#define __TC_SHA256_H__
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TC_SHA256_BLOCK_SIZE (64)
#define TC_SHA256_DIGEST_SIZE (32)
#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4)
struct tc_sha256_state_struct {
unsigned int iv[TC_SHA256_STATE_BLOCKS];
uint64_t bits_hashed;
uint8_t leftover[TC_SHA256_BLOCK_SIZE];
size_t leftover_offset;
};
typedef struct tc_sha256_state_struct *TCSha256State_t;
/**
* @brief SHA256 initialization procedure
* Initializes s
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if s == NULL
* @param s Sha256 state struct
*/
int tc_sha256_init(TCSha256State_t s);
/**
* @brief SHA256 update procedure
* Hashes data_length bytes addressed by data into state s
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* s == NULL,
* s->iv == NULL,
* data == NULL
* @note Assumes s has been initialized by tc_sha256_init
* @warning The state buffer 'leftover' is left in memory after processing
* If your application intends to have sensitive data in this
* buffer, remind to erase it after the data has been processed
* @param s Sha256 state struct
* @param data message to hash
* @param datalen length of message to hash
*/
int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen);
/**
* @brief SHA256 final procedure
* Inserts the completed hash computation into digest
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* s == NULL,
* s->iv == NULL,
* digest == NULL
* @note Assumes: s has been initialized by tc_sha256_init
* digest points to at least TC_SHA256_DIGEST_SIZE bytes
* @warning The state buffer 'leftover' is left in memory after processing
* If your application intends to have sensitive data in this
* buffer, remind to erase it after the data has been processed
* @param digest unsigned eight bit integer
* @param Sha256 state struct
*/
int tc_sha256_final(uint8_t *digest, TCSha256State_t s);
#ifdef __cplusplus
}
#endif
#endif /* __TC_SHA256_H__ */

View File

@@ -0,0 +1,95 @@
/* utils.h - TinyCrypt interface to platform-dependent run-time operations */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief Interface to platform-dependent run-time operations.
*
*/
#ifndef __TC_UTILS_H__
#define __TC_UTILS_H__
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Copy the the buffer 'from' to the buffer 'to'.
* @return returns TC_CRYPTO_SUCCESS (1)
* returns TC_CRYPTO_FAIL (0) if:
* from_len > to_len.
*
* @param to OUT -- destination buffer
* @param to_len IN -- length of destination buffer
* @param from IN -- origin buffer
* @param from_len IN -- length of origin buffer
*/
unsigned int _copy(uint8_t *to, unsigned int to_len,
const uint8_t *from, unsigned int from_len);
/**
* @brief Set the value 'val' into the buffer 'to', 'len' times.
*
* @param to OUT -- destination buffer
* @param val IN -- value to be set in 'to'
* @param len IN -- number of times the value will be copied
*/
void _set(void *to, uint8_t val, unsigned int len);
/*
* @brief AES specific doubling function, which utilizes
* the finite field used by AES.
* @return Returns a^2
*
* @param a IN/OUT -- value to be doubled
*/
uint8_t _double_byte(uint8_t a);
/*
* @brief Constant-time algorithm to compare if two sequences of bytes are equal
* @return Returns 0 if equal, and non-zero otherwise
*
* @param a IN -- sequence of bytes a
* @param b IN -- sequence of bytes b
* @param size IN -- size of sequences a and b
*/
int _compare(const uint8_t *a, const uint8_t *b, size_t size);
#ifdef __cplusplus
}
#endif
#endif /* __TC_UTILS_H__ */

View File

@@ -0,0 +1,30 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
pkg.name: ext/tinycrypt/lib
pkg.description: "MCUboot's bundled tinycrypt"
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
pkg.src_dirs:
- "source"
pkg.cflags:
- "-std=c99"

View File

@@ -0,0 +1,164 @@
/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
static const uint8_t inv_sbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
0x55, 0x21, 0x0c, 0x7d
};
int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k)
{
return tc_aes128_set_encrypt_key(s, k);
}
#define mult8(a)(_double_byte(_double_byte(_double_byte(a))))
#define mult9(a)(mult8(a)^(a))
#define multb(a)(mult8(a)^_double_byte(a)^(a))
#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a))
#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a))
static inline void mult_row_column(uint8_t *out, const uint8_t *in)
{
out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]);
out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]);
out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]);
out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]);
}
static inline void inv_mix_columns(uint8_t *s)
{
uint8_t t[Nb*Nk];
mult_row_column(t, s);
mult_row_column(&t[Nb], s+Nb);
mult_row_column(&t[2*Nb], s+(2*Nb));
mult_row_column(&t[3*Nb], s+(3*Nb));
(void)_copy(s, sizeof(t), t, sizeof(t));
}
static inline void add_round_key(uint8_t *s, const unsigned int *k)
{
s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
}
static inline void inv_sub_bytes(uint8_t *s)
{
unsigned int i;
for (i = 0; i < (Nb*Nk); ++i) {
s[i] = inv_sbox[s[i]];
}
}
/*
* This inv_shift_rows also implements the matrix flip required for
* inv_mix_columns, but performs it here to reduce the number of memory
* operations.
*/
static inline void inv_shift_rows(uint8_t *s)
{
uint8_t t[Nb*Nk];
t[0] = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7];
t[4] = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11];
t[8] = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15];
t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3];
(void)_copy(s, sizeof(t), t, sizeof(t));
}
int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
{
uint8_t state[Nk*Nb];
unsigned int i;
if (out == (uint8_t *) 0) {
return TC_CRYPTO_FAIL;
} else if (in == (const uint8_t *) 0) {
return TC_CRYPTO_FAIL;
} else if (s == (TCAesKeySched_t) 0) {
return TC_CRYPTO_FAIL;
}
(void)_copy(state, sizeof(state), in, sizeof(state));
add_round_key(state, s->words + Nb*Nr);
for (i = Nr - 1; i > 0; --i) {
inv_shift_rows(state);
inv_sub_bytes(state);
add_round_key(state, s->words + Nb*i);
inv_mix_columns(state);
}
inv_shift_rows(state);
inv_sub_bytes(state);
add_round_key(state, s->words);
(void)_copy(out, sizeof(state), state, sizeof(state));
/*zeroing out the state buffer */
_set(state, TC_ZERO_BYTE, sizeof(state));
return TC_CRYPTO_SUCCESS;
}

View File

@@ -0,0 +1,191 @@
/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/aes.h>
#include <tinycrypt/utils.h>
#include <tinycrypt/constants.h>
static const uint8_t sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
0xb0, 0x54, 0xbb, 0x16
};
static inline unsigned int rotword(unsigned int a)
{
return (((a) >> 24)|((a) << 8));
}
#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o))
#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0))
int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k)
{
const unsigned int rconst[11] = {
0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
};
unsigned int i;
unsigned int t;
if (s == (TCAesKeySched_t) 0) {
return TC_CRYPTO_FAIL;
} else if (k == (const uint8_t *) 0) {
return TC_CRYPTO_FAIL;
}
for (i = 0; i < Nk; ++i) {
s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) |
(k[Nb*i+2]<<8) | (k[Nb*i+3]);
}
for (; i < (Nb * (Nr + 1)); ++i) {
t = s->words[i-1];
if ((i % Nk) == 0) {
t = subword(rotword(t)) ^ rconst[i/Nk];
}
s->words[i] = s->words[i-Nk] ^ t;
}
return TC_CRYPTO_SUCCESS;
}
static inline void add_round_key(uint8_t *s, const unsigned int *k)
{
s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
}
static inline void sub_bytes(uint8_t *s)
{
unsigned int i;
for (i = 0; i < (Nb * Nk); ++i) {
s[i] = sbox[s[i]];
}
}
#define triple(a)(_double_byte(a)^(a))
static inline void mult_row_column(uint8_t *out, const uint8_t *in)
{
out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3];
out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3];
out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]);
out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]);
}
static inline void mix_columns(uint8_t *s)
{
uint8_t t[Nb*Nk];
mult_row_column(t, s);
mult_row_column(&t[Nb], s+Nb);
mult_row_column(&t[2 * Nb], s + (2 * Nb));
mult_row_column(&t[3 * Nb], s + (3 * Nb));
(void) _copy(s, sizeof(t), t, sizeof(t));
}
/*
* This shift_rows also implements the matrix flip required for mix_columns, but
* performs it here to reduce the number of memory operations.
*/
static inline void shift_rows(uint8_t *s)
{
uint8_t t[Nb * Nk];
t[0] = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15];
t[4] = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3];
t[8] = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7];
t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11];
(void) _copy(s, sizeof(t), t, sizeof(t));
}
int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
{
uint8_t state[Nk*Nb];
unsigned int i;
if (out == (uint8_t *) 0) {
return TC_CRYPTO_FAIL;
} else if (in == (const uint8_t *) 0) {
return TC_CRYPTO_FAIL;
} else if (s == (TCAesKeySched_t) 0) {
return TC_CRYPTO_FAIL;
}
(void)_copy(state, sizeof(state), in, sizeof(state));
add_round_key(state, s->words);
for (i = 0; i < (Nr - 1); ++i) {
sub_bytes(state);
shift_rows(state);
mix_columns(state);
add_round_key(state, s->words + Nb*(i+1));
}
sub_bytes(state);
shift_rows(state);
add_round_key(state, s->words + Nb*(i+1));
(void)_copy(out, sizeof(state), state, sizeof(state));
/* zeroing out the state buffer */
_set(state, TC_ZERO_BYTE, sizeof(state));
return TC_CRYPTO_SUCCESS;
}

View File

@@ -0,0 +1,114 @@
/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/cbc_mode.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, const uint8_t *iv,
const TCAesKeySched_t sched)
{
uint8_t buffer[TC_AES_BLOCK_SIZE];
unsigned int n, m;
/* input sanity check: */
if (out == (uint8_t *) 0 ||
in == (const uint8_t *) 0 ||
sched == (TCAesKeySched_t) 0 ||
inlen == 0 ||
outlen == 0 ||
(inlen % TC_AES_BLOCK_SIZE) != 0 ||
(outlen % TC_AES_BLOCK_SIZE) != 0 ||
outlen != inlen + TC_AES_BLOCK_SIZE) {
return TC_CRYPTO_FAIL;
}
/* copy iv to the buffer */
(void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
/* copy iv to the output buffer */
(void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
out += TC_AES_BLOCK_SIZE;
for (n = m = 0; n < inlen; ++n) {
buffer[m++] ^= *in++;
if (m == TC_AES_BLOCK_SIZE) {
(void)tc_aes_encrypt(buffer, buffer, sched);
(void)_copy(out, TC_AES_BLOCK_SIZE,
buffer, TC_AES_BLOCK_SIZE);
out += TC_AES_BLOCK_SIZE;
m = 0;
}
}
return TC_CRYPTO_SUCCESS;
}
int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, const uint8_t *iv,
const TCAesKeySched_t sched)
{
uint8_t buffer[TC_AES_BLOCK_SIZE];
const uint8_t *p;
unsigned int n, m;
/* sanity check the inputs */
if (out == (uint8_t *) 0 ||
in == (const uint8_t *) 0 ||
sched == (TCAesKeySched_t) 0 ||
inlen == 0 ||
outlen == 0 ||
(inlen % TC_AES_BLOCK_SIZE) != 0 ||
(outlen % TC_AES_BLOCK_SIZE) != 0 ||
outlen != inlen - TC_AES_BLOCK_SIZE) {
return TC_CRYPTO_FAIL;
}
/*
* Note that in == iv + ciphertext, i.e. the iv and the ciphertext are
* contiguous. This allows for a very efficient decryption algorithm
* that would not otherwise be possible.
*/
p = iv;
for (n = m = 0; n < inlen; ++n) {
if ((n % TC_AES_BLOCK_SIZE) == 0) {
(void)tc_aes_decrypt(buffer, in, sched);
in += TC_AES_BLOCK_SIZE;
m = 0;
}
*out++ = buffer[m++] ^ *p++;
}
return TC_CRYPTO_SUCCESS;
}

View File

@@ -0,0 +1,266 @@
/* ccm_mode.c - TinyCrypt implementation of CCM mode */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/ccm_mode.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
#include <stdio.h>
int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
unsigned int nlen, unsigned int mlen)
{
/* input sanity check: */
if (c == (TCCcmMode_t) 0 ||
sched == (TCAesKeySched_t) 0 ||
nonce == (uint8_t *) 0) {
return TC_CRYPTO_FAIL;
} else if (nlen != 13) {
return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/
} else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
}
c->mlen = mlen;
c->sched = sched;
c->nonce = nonce;
return TC_CRYPTO_SUCCESS;
}
/**
* Variation of CBC-MAC mode used in CCM.
*/
static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen,
unsigned int flag, TCAesKeySched_t sched)
{
unsigned int i;
if (flag > 0) {
T[0] ^= (uint8_t)(dlen >> 8);
T[1] ^= (uint8_t)(dlen);
dlen += 2; i = 2;
} else {
i = 0;
}
while (i < dlen) {
T[i++ % (Nb * Nk)] ^= *data++;
if (((i % (Nb * Nk)) == 0) || dlen == i) {
(void) tc_aes_encrypt(T, T, sched);
}
}
}
/**
* Variation of CTR mode used in CCM.
* The CTR mode used by CCM is slightly different than the conventional CTR
* mode (the counter is increased before encryption, instead of after
* encryption). Besides, it is assumed that the counter is stored in the last
* 2 bytes of the nonce.
*/
static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
{
uint8_t buffer[TC_AES_BLOCK_SIZE];
uint8_t nonce[TC_AES_BLOCK_SIZE];
uint16_t block_num;
unsigned int i;
/* input sanity check: */
if (out == (uint8_t *) 0 ||
in == (uint8_t *) 0 ||
ctr == (uint8_t *) 0 ||
sched == (TCAesKeySched_t) 0 ||
inlen == 0 ||
outlen == 0 ||
outlen != inlen) {
return TC_CRYPTO_FAIL;
}
/* copy the counter to the nonce */
(void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
/* select the last 2 bytes of the nonce to be incremented */
block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
for (i = 0; i < inlen; ++i) {
if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
block_num++;
nonce[14] = (uint8_t)(block_num >> 8);
nonce[15] = (uint8_t)(block_num);
if (!tc_aes_encrypt(buffer, nonce, sched)) {
return TC_CRYPTO_FAIL;
}
}
/* update the output */
*out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
}
/* update the counter */
ctr[14] = nonce[14]; ctr[15] = nonce[15];
return TC_CRYPTO_SUCCESS;
}
int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
const uint8_t *associated_data,
unsigned int alen, const uint8_t *payload,
unsigned int plen, TCCcmMode_t c)
{
/* input sanity check: */
if ((out == (uint8_t *) 0) ||
(c == (TCCcmMode_t) 0) ||
((plen > 0) && (payload == (uint8_t *) 0)) ||
((alen > 0) && (associated_data == (uint8_t *) 0)) ||
(alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
(plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
(olen < (plen + c->mlen))) { /* invalid output buffer size */
return TC_CRYPTO_FAIL;
}
uint8_t b[Nb * Nk];
uint8_t tag[Nb * Nk];
unsigned int i;
/* GENERATING THE AUTHENTICATION TAG: */
/* formatting the sequence b for authentication: */
b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
for (i = 1; i <= 13; ++i) {
b[i] = c->nonce[i - 1];
}
b[14] = (uint8_t)(plen >> 8);
b[15] = (uint8_t)(plen);
/* computing the authentication tag using cbc-mac: */
(void) tc_aes_encrypt(tag, b, c->sched);
if (alen > 0) {
ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
}
if (plen > 0) {
ccm_cbc_mac(tag, payload, plen, 0, c->sched);
}
/* ENCRYPTION: */
/* formatting the sequence b for encryption: */
b[0] = 1; /* q - 1 = 2 - 1 = 1 */
b[14] = b[15] = TC_ZERO_BYTE;
/* encrypting payload using ctr mode: */
ccm_ctr_mode(out, plen, payload, plen, b, c->sched);
b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/
/* encrypting b and adding the tag to the output: */
(void) tc_aes_encrypt(b, b, c->sched);
out += plen;
for (i = 0; i < c->mlen; ++i) {
*out++ = tag[i] ^ b[i];
}
return TC_CRYPTO_SUCCESS;
}
int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
const uint8_t *associated_data,
unsigned int alen, const uint8_t *payload,
unsigned int plen, TCCcmMode_t c)
{
/* input sanity check: */
if ((out == (uint8_t *) 0) ||
(c == (TCCcmMode_t) 0) ||
((plen > 0) && (payload == (uint8_t *) 0)) ||
((alen > 0) && (associated_data == (uint8_t *) 0)) ||
(alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
(plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
(olen < plen - c->mlen)) { /* invalid output buffer size */
return TC_CRYPTO_FAIL;
}
uint8_t b[Nb * Nk];
uint8_t tag[Nb * Nk];
unsigned int i;
/* DECRYPTION: */
/* formatting the sequence b for decryption: */
b[0] = 1; /* q - 1 = 2 - 1 = 1 */
for (i = 1; i < 14; ++i) {
b[i] = c->nonce[i - 1];
}
b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */
/* decrypting payload using ctr mode: */
ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);
b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */
/* encrypting b and restoring the tag from input: */
(void) tc_aes_encrypt(b, b, c->sched);
for (i = 0; i < c->mlen; ++i) {
tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
}
/* VERIFYING THE AUTHENTICATION TAG: */
/* formatting the sequence b for authentication: */
b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
for (i = 1; i < 14; ++i) {
b[i] = c->nonce[i - 1];
}
b[14] = (uint8_t)((plen - c->mlen) >> 8);
b[15] = (uint8_t)(plen - c->mlen);
/* computing the authentication tag using cbc-mac: */
(void) tc_aes_encrypt(b, b, c->sched);
if (alen > 0) {
ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
}
if (plen > 0) {
ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
}
/* comparing the received tag and the computed one: */
if (_compare(b, tag, c->mlen) == 0) {
return TC_CRYPTO_SUCCESS;
} else {
/* erase the decrypted buffer in case of mac validation failure: */
_set(out, 0, plen - c->mlen);
return TC_CRYPTO_FAIL;
}
}

View File

@@ -0,0 +1,254 @@
/* cmac_mode.c - TinyCrypt CMAC mode implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/aes.h>
#include <tinycrypt/cmac_mode.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
/* max number of calls until change the key (2^48).*/
const static uint64_t MAX_CALLS = ((uint64_t)1 << 48);
/*
* gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte
* array with byte 0 the most significant and byte 15 the least significant.
* High bit carry reduction is based on the primitive polynomial
*
* X^128 + X^7 + X^2 + X + 1,
*
* which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed,
* since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since
* addition of polynomials with coefficients in Z/Z(2) is just XOR, we can
* add X^128 to both sides to get
*
* X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1)
*
* and the coefficients of the polynomial on the right hand side form the
* string 1000 0111 = 0x87, which is the value of gf_wrap.
*
* This gets used in the following way. Doubling in GF(2^128) is just a left
* shift by 1 bit, except when the most significant bit is 1. In the latter
* case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit
* that overflows beyond 128 bits can be replaced by addition of
* X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition
* in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87
* into the low order byte after a left shift when the starting high order
* bit is 1.
*/
const unsigned char gf_wrap = 0x87;
/*
* assumes: out != NULL and points to a GF(2^n) value to receive the
* doubled value;
* in != NULL and points to a 16 byte GF(2^n) value
* to double;
* the in and out buffers do not overlap.
* effects: doubles the GF(2^n) value pointed to by "in" and places
* the result in the GF(2^n) value pointed to by "out."
*/
void gf_double(uint8_t *out, uint8_t *in)
{
/* start with low order byte */
uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1);
/* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */
uint8_t carry = (in[0] >> 7) ? gf_wrap : 0;
out += (TC_AES_BLOCK_SIZE - 1);
for (;;) {
*out-- = (*x << 1) ^ carry;
if (x == in) {
break;
}
carry = *x-- >> 7;
}
}
int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched)
{
/* input sanity check: */
if (s == (TCCmacState_t) 0 ||
key == (const uint8_t *) 0) {
return TC_CRYPTO_FAIL;
}
/* put s into a known state */
_set(s, 0, sizeof(*s));
s->sched = sched;
/* configure the encryption key used by the underlying block cipher */
tc_aes128_set_encrypt_key(s->sched, key);
/* compute s->K1 and s->K2 from s->iv using s->keyid */
_set(s->iv, 0, TC_AES_BLOCK_SIZE);
tc_aes_encrypt(s->iv, s->iv, s->sched);
gf_double (s->K1, s->iv);
gf_double (s->K2, s->K1);
/* reset s->iv to 0 in case someone wants to compute now */
tc_cmac_init(s);
return TC_CRYPTO_SUCCESS;
}
int tc_cmac_erase(TCCmacState_t s)
{
if (s == (TCCmacState_t) 0) {
return TC_CRYPTO_FAIL;
}
/* destroy the current state */
_set(s, 0, sizeof(*s));
return TC_CRYPTO_SUCCESS;
}
int tc_cmac_init(TCCmacState_t s)
{
/* input sanity check: */
if (s == (TCCmacState_t) 0) {
return TC_CRYPTO_FAIL;
}
/* CMAC starts with an all zero initialization vector */
_set(s->iv, 0, TC_AES_BLOCK_SIZE);
/* and the leftover buffer is empty */
_set(s->leftover, 0, TC_AES_BLOCK_SIZE);
s->leftover_offset = 0;
/* Set countdown to max number of calls allowed before re-keying: */
s->countdown = MAX_CALLS;
return TC_CRYPTO_SUCCESS;
}
int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
{
unsigned int i;
/* input sanity check: */
if (s == (TCCmacState_t) 0) {
return TC_CRYPTO_FAIL;
}
if (data_length == 0) {
return TC_CRYPTO_SUCCESS;
}
if (data == (const uint8_t *) 0) {
return TC_CRYPTO_FAIL;
}
if (s->countdown == 0) {
return TC_CRYPTO_FAIL;
}
s->countdown--;
if (s->leftover_offset > 0) {
/* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */
size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset;
if (data_length < remaining_space) {
/* still not enough data to encrypt this time either */
_copy(&s->leftover[s->leftover_offset], data_length, data, data_length);
s->leftover_offset += data_length;
return TC_CRYPTO_SUCCESS;
}
/* leftover block is now full; encrypt it first */
_copy(&s->leftover[s->leftover_offset],
remaining_space,
data,
remaining_space);
data_length -= remaining_space;
data += remaining_space;
s->leftover_offset = 0;
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
s->iv[i] ^= s->leftover[i];
}
tc_aes_encrypt(s->iv, s->iv, s->sched);
}
/* CBC encrypt each (except the last) of the data blocks */
while (data_length > TC_AES_BLOCK_SIZE) {
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
s->iv[i] ^= data[i];
}
tc_aes_encrypt(s->iv, s->iv, s->sched);
data += TC_AES_BLOCK_SIZE;
data_length -= TC_AES_BLOCK_SIZE;
}
if (data_length > 0) {
/* save leftover data for next time */
_copy(s->leftover, data_length, data, data_length);
s->leftover_offset = data_length;
}
return TC_CRYPTO_SUCCESS;
}
int tc_cmac_final(uint8_t *tag, TCCmacState_t s)
{
uint8_t *k;
unsigned int i;
/* input sanity check: */
if (tag == (uint8_t *) 0 ||
s == (TCCmacState_t) 0) {
return TC_CRYPTO_FAIL;
}
if (s->leftover_offset == TC_AES_BLOCK_SIZE) {
/* the last message block is a full-sized block */
k = (uint8_t *) s->K1;
} else {
/* the final message block is not a full-sized block */
size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset;
_set(&s->leftover[s->leftover_offset], 0, remaining);
s->leftover[s->leftover_offset] = TC_CMAC_PADDING;
k = (uint8_t *) s->K2;
}
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
s->iv[i] ^= s->leftover[i] ^ k[i];
}
tc_aes_encrypt(tag, s->iv, s->sched);
/* erasing state: */
tc_cmac_erase(s);
return TC_CRYPTO_SUCCESS;
}

View File

@@ -0,0 +1,91 @@
/* ctr_mode.c - TinyCrypt CTR mode implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/constants.h>
#include <tinycrypt/ctr_mode.h>
#include <tinycrypt/utils.h>
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, uint8_t *ctr, uint32_t *blk_off,
const TCAesKeySched_t sched)
{
uint8_t buffer[TC_AES_BLOCK_SIZE];
uint8_t nonce[TC_AES_BLOCK_SIZE];
unsigned int block_num;
unsigned int i;
uint32_t n;
/* input sanity check: */
if (out == (uint8_t *) 0 ||
in == (uint8_t *) 0 ||
ctr == (uint8_t *) 0 ||
blk_off == (uint32_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]);
n = *blk_off;
for (i = 0; i < inlen; ++i) {
if (n == 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[n] ^ *in++;
n = (n + 1) % TC_AES_BLOCK_SIZE;
}
*blk_off = n;
/* update the counter */
ctr[12] = nonce[12]; ctr[13] = nonce[13];
ctr[14] = nonce[14]; ctr[15] = nonce[15];
return TC_CRYPTO_SUCCESS;
}

View File

@@ -0,0 +1,283 @@
/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */
/*
* Copyright (c) 2016, Chris Morrison
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/ctr_prng.h>
#include <tinycrypt/utils.h>
#include <tinycrypt/constants.h>
#include <string.h>
/*
* This PRNG is based on the CTR_DRBG described in Recommendation for Random
* Number Generation Using Deterministic Random Bit Generators,
* NIST SP 800-90A Rev. 1.
*
* Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps
* described in that document.
*
*/
/**
* @brief Array incrementer
* Treats the supplied array as one contiguous number (MSB in arr[0]), and
* increments it by one
* @return none
* @param arr IN/OUT -- array to be incremented
* @param len IN -- size of arr in bytes
*/
static void arrInc(uint8_t arr[], unsigned int len)
{
unsigned int i;
if (0 != arr) {
for (i = len; i > 0U; i--) {
if (++arr[i-1] != 0U) {
break;
}
}
}
}
/**
* @brief CTR PRNG update
* Updates the internal state of supplied the CTR PRNG context
* increments it by one
* @return none
* @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long
* @param ctx IN/OUT -- CTR PRNG state
* @param providedData IN -- data used when updating the internal state
*/
static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData)
{
if (0 != ctx) {
/* 10.2.1.2 step 1 */
uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
unsigned int len = 0U;
/* 10.2.1.2 step 2 */
while (len < sizeof temp) {
unsigned int blocklen = sizeof(temp) - len;
uint8_t output_block[TC_AES_BLOCK_SIZE];
/* 10.2.1.2 step 2.1 */
arrInc(ctx->V, sizeof ctx->V);
/* 10.2.1.2 step 2.2 */
if (blocklen > TC_AES_BLOCK_SIZE) {
blocklen = TC_AES_BLOCK_SIZE;
}
(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
/* 10.2.1.2 step 2.3/step 3 */
memcpy(&(temp[len]), output_block, blocklen);
len += blocklen;
}
/* 10.2.1.2 step 4 */
if (0 != providedData) {
unsigned int i;
for (i = 0U; i < sizeof temp; i++) {
temp[i] ^= providedData[i];
}
}
/* 10.2.1.2 step 5 */
(void)tc_aes128_set_encrypt_key(&ctx->key, temp);
/* 10.2.1.2 step 6 */
memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE);
}
}
int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
uint8_t const * const entropy,
unsigned int entropyLen,
uint8_t const * const personalization,
unsigned int pLen)
{
int result = TC_CRYPTO_FAIL;
unsigned int i;
uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U};
if (0 != personalization) {
/* 10.2.1.3.1 step 1 */
unsigned int len = pLen;
if (len > sizeof personalization_buf) {
len = sizeof personalization_buf;
}
/* 10.2.1.3.1 step 2 */
memcpy(personalization_buf, personalization, len);
}
if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) {
/* 10.2.1.3.1 step 3 */
memcpy(seed_material, entropy, sizeof seed_material);
for (i = 0U; i < sizeof seed_material; i++) {
seed_material[i] ^= personalization_buf[i];
}
/* 10.2.1.3.1 step 4 */
(void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr);
/* 10.2.1.3.1 step 5 */
memset(ctx->V, 0x00, sizeof ctx->V);
/* 10.2.1.3.1 step 6 */
tc_ctr_prng_update(ctx, seed_material);
/* 10.2.1.3.1 step 7 */
ctx->reseedCount = 1U;
result = TC_CRYPTO_SUCCESS;
}
return result;
}
int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
uint8_t const * const entropy,
unsigned int entropyLen,
uint8_t const * const additional_input,
unsigned int additionallen)
{
unsigned int i;
int result = TC_CRYPTO_FAIL;
uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
if (0 != additional_input) {
/* 10.2.1.4.1 step 1 */
unsigned int len = additionallen;
if (len > sizeof additional_input_buf) {
len = sizeof additional_input_buf;
}
/* 10.2.1.4.1 step 2 */
memcpy(additional_input_buf, additional_input, len);
}
unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE;
if ((0 != ctx) && (entropyLen >= seedlen)) {
/* 10.2.1.4.1 step 3 */
memcpy(seed_material, entropy, sizeof seed_material);
for (i = 0U; i < sizeof seed_material; i++) {
seed_material[i] ^= additional_input_buf[i];
}
/* 10.2.1.4.1 step 4 */
tc_ctr_prng_update(ctx, seed_material);
/* 10.2.1.4.1 step 5 */
ctx->reseedCount = 1U;
result = TC_CRYPTO_SUCCESS;
}
return result;
}
int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
uint8_t const * const additional_input,
unsigned int additionallen,
uint8_t * const out,
unsigned int outlen)
{
/* 2^48 - see section 10.2.1 */
static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL;
/* 2^19 bits - see section 10.2.1 */
static const unsigned int MAX_BYTES_PER_REQ = 65536U;
unsigned int result = TC_CRYPTO_FAIL;
if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) {
/* 10.2.1.5.1 step 1 */
if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) {
result = TC_CTR_PRNG_RESEED_REQ;
} else {
uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
if (0 != additional_input) {
/* 10.2.1.5.1 step 2 */
unsigned int len = additionallen;
if (len > sizeof additional_input_buf) {
len = sizeof additional_input_buf;
}
memcpy(additional_input_buf, additional_input, len);
tc_ctr_prng_update(ctx, additional_input_buf);
}
/* 10.2.1.5.1 step 3 - implicit */
/* 10.2.1.5.1 step 4 */
unsigned int len = 0U;
while (len < outlen) {
unsigned int blocklen = outlen - len;
uint8_t output_block[TC_AES_BLOCK_SIZE];
/* 10.2.1.5.1 step 4.1 */
arrInc(ctx->V, sizeof ctx->V);
/* 10.2.1.5.1 step 4.2 */
(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
/* 10.2.1.5.1 step 4.3/step 5 */
if (blocklen > TC_AES_BLOCK_SIZE) {
blocklen = TC_AES_BLOCK_SIZE;
}
memcpy(&(out[len]), output_block, blocklen);
len += blocklen;
}
/* 10.2.1.5.1 step 6 */
tc_ctr_prng_update(ctx, additional_input_buf);
/* 10.2.1.5.1 step 7 */
ctx->reseedCount++;
/* 10.2.1.5.1 step 8 */
result = TC_CRYPTO_SUCCESS;
}
}
return result;
}
void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx)
{
if (0 != ctx) {
memset(ctx->key.words, 0x00, sizeof ctx->key.words);
memset(ctx->V, 0x00, sizeof ctx->V);
ctx->reseedCount = 0U;
}
}

View File

@@ -0,0 +1,942 @@
/* ecc.c - TinyCrypt implementation of common ECC functions */
/*
* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_platform_specific.h>
#include <string.h>
/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
* has access to enough entropy in order to feed the PRNG regularly. */
#if default_RNG_defined
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
#else
static uECC_RNG_Function g_rng_function = 0;
#endif
void uECC_set_rng(uECC_RNG_Function rng_function)
{
g_rng_function = rng_function;
}
uECC_RNG_Function uECC_get_rng(void)
{
return g_rng_function;
}
int uECC_curve_private_key_size(uECC_Curve curve)
{
return BITS_TO_BYTES(curve->num_n_bits);
}
int uECC_curve_public_key_size(uECC_Curve curve)
{
return 2 * curve->num_bytes;
}
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words)
{
wordcount_t i;
for (i = 0; i < num_words; ++i) {
vli[i] = 0;
}
}
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words)
{
uECC_word_t bits = 0;
wordcount_t i;
for (i = 0; i < num_words; ++i) {
bits |= vli[i];
}
return (bits == 0);
}
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
{
return (vli[bit >> uECC_WORD_BITS_SHIFT] &
((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
}
/* Counts the number of words in vli. */
static wordcount_t vli_numDigits(const uECC_word_t *vli,
const wordcount_t max_words)
{
wordcount_t i;
/* Search from the end until we find a non-zero digit. We do it in reverse
* because we expect that most digits will be nonzero. */
for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
}
return (i + 1);
}
bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
const wordcount_t max_words)
{
uECC_word_t i;
uECC_word_t digit;
wordcount_t num_digits = vli_numDigits(vli, max_words);
if (num_digits == 0) {
return 0;
}
digit = vli[num_digits - 1];
for (i = 0; digit; ++i) {
digit >>= 1;
}
return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
}
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
wordcount_t num_words)
{
wordcount_t i;
for (i = 0; i < num_words; ++i) {
dest[i] = src[i];
}
}
cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
const uECC_word_t *right,
wordcount_t num_words)
{
wordcount_t i;
for (i = num_words - 1; i >= 0; --i) {
if (left[i] > right[i]) {
return 1;
} else if (left[i] < right[i]) {
return -1;
}
}
return 0;
}
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
wordcount_t num_words)
{
uECC_word_t diff = 0;
wordcount_t i;
for (i = num_words - 1; i >= 0; --i) {
diff |= (left[i] ^ right[i]);
}
return !(diff == 0);
}
uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
{
return (p_true*(cond)) | (p_false*(!cond));
}
/* Computes result = left - right, returning borrow, in constant time.
* Can modify in place. */
uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, wordcount_t num_words)
{
uECC_word_t borrow = 0;
wordcount_t i;
for (i = 0; i < num_words; ++i) {
uECC_word_t diff = left[i] - right[i] - borrow;
uECC_word_t val = (diff > left[i]);
borrow = cond_set(val, borrow, (diff != left[i]));
result[i] = diff;
}
return borrow;
}
/* Computes result = left + right, returning carry, in constant time.
* Can modify in place. */
static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, wordcount_t num_words)
{
uECC_word_t carry = 0;
wordcount_t i;
for (i = 0; i < num_words; ++i) {
uECC_word_t sum = left[i] + right[i] + carry;
uECC_word_t val = (sum < left[i]);
carry = cond_set(val, carry, (sum != left[i]));
result[i] = sum;
}
return carry;
}
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
wordcount_t num_words)
{
uECC_word_t tmp[NUM_ECC_WORDS];
uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
return (!equal - 2 * neg);
}
/* Computes vli = vli >> 1. */
static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words)
{
uECC_word_t *end = vli;
uECC_word_t carry = 0;
vli += num_words;
while (vli-- > end) {
uECC_word_t temp = *vli;
*vli = (temp >> 1) | carry;
carry = temp << (uECC_WORD_BITS - 1);
}
}
static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0,
uECC_word_t *r1, uECC_word_t *r2)
{
uECC_dword_t p = (uECC_dword_t)a * b;
uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
r01 += p;
*r2 += (r01 < p);
*r1 = r01 >> uECC_WORD_BITS;
*r0 = (uECC_word_t)r01;
}
/* Computes result = left * right. Result must be 2 * num_words long. */
static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, wordcount_t num_words)
{
uECC_word_t r0 = 0;
uECC_word_t r1 = 0;
uECC_word_t r2 = 0;
wordcount_t i, k;
/* Compute each digit of result in sequence, maintaining the carries. */
for (k = 0; k < num_words; ++k) {
for (i = 0; i <= k; ++i) {
muladd(left[i], right[k - i], &r0, &r1, &r2);
}
result[k] = r0;
r0 = r1;
r1 = r2;
r2 = 0;
}
for (k = num_words; k < num_words * 2 - 1; ++k) {
for (i = (k + 1) - num_words; i < num_words; ++i) {
muladd(left[i], right[k - i], &r0, &r1, &r2);
}
result[k] = r0;
r0 = r1;
r1 = r2;
r2 = 0;
}
result[num_words * 2 - 1] = r0;
}
void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words)
{
uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
/* result > mod (result = mod + remainder), so subtract mod to get
* remainder. */
uECC_vli_sub(result, result, mod, num_words);
}
}
void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words)
{
uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
if (l_borrow) {
/* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
* we can get the correct result from result + mod (with overflow). */
uECC_vli_add(result, result, mod, num_words);
}
}
/* Computes result = product % mod, where product is 2N words long. */
/* Currently only designed to work for curve_p or curve_n. */
void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
const uECC_word_t *mod, wordcount_t num_words)
{
uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
uECC_word_t tmp[2 * NUM_ECC_WORDS];
uECC_word_t *v[2] = {tmp, product};
uECC_word_t index;
/* Shift mod so its highest set bit is at the maximum position. */
bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
uECC_vli_numBits(mod, num_words);
wordcount_t word_shift = shift / uECC_WORD_BITS;
wordcount_t bit_shift = shift % uECC_WORD_BITS;
uECC_word_t carry = 0;
uECC_vli_clear(mod_multiple, word_shift);
if (bit_shift > 0) {
for(index = 0; index < (uECC_word_t)num_words; ++index) {
mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
}
} else {
uECC_vli_set(mod_multiple + word_shift, mod, num_words);
}
for (index = 1; shift >= 0; --shift) {
uECC_word_t borrow = 0;
wordcount_t i;
for (i = 0; i < num_words * 2; ++i) {
uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
if (diff != v[index][i]) {
borrow = (diff > v[index][i]);
}
v[1 - index][i] = diff;
}
/* Swap the index if there was no borrow */
index = !(index ^ borrow);
uECC_vli_rshift1(mod_multiple, num_words);
mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
(uECC_WORD_BITS - 1);
uECC_vli_rshift1(mod_multiple + num_words, num_words);
}
uECC_vli_set(result, v[index], num_words);
}
void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words)
{
uECC_word_t product[2 * NUM_ECC_WORDS];
uECC_vli_mult(product, left, right, num_words);
uECC_vli_mmod(result, product, mod, num_words);
}
void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, uECC_Curve curve)
{
uECC_word_t product[2 * NUM_ECC_WORDS];
uECC_vli_mult(product, left, right, curve->num_words);
curve->mmod_fast(result, product);
}
static void uECC_vli_modSquare_fast(uECC_word_t *result,
const uECC_word_t *left,
uECC_Curve curve)
{
uECC_vli_modMult_fast(result, left, left, curve);
}
#define EVEN(vli) (!(vli[0] & 1))
static void vli_modInv_update(uECC_word_t *uv,
const uECC_word_t *mod,
wordcount_t num_words)
{
uECC_word_t carry = 0;
if (!EVEN(uv)) {
carry = uECC_vli_add(uv, uv, mod, num_words);
}
uECC_vli_rshift1(uv, num_words);
if (carry) {
uv[num_words - 1] |= HIGH_BIT_SET;
}
}
void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
const uECC_word_t *mod, wordcount_t num_words)
{
uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
cmpresult_t cmpResult;
if (uECC_vli_isZero(input, num_words)) {
uECC_vli_clear(result, num_words);
return;
}
uECC_vli_set(a, input, num_words);
uECC_vli_set(b, mod, num_words);
uECC_vli_clear(u, num_words);
u[0] = 1;
uECC_vli_clear(v, num_words);
while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
if (EVEN(a)) {
uECC_vli_rshift1(a, num_words);
vli_modInv_update(u, mod, num_words);
} else if (EVEN(b)) {
uECC_vli_rshift1(b, num_words);
vli_modInv_update(v, mod, num_words);
} else if (cmpResult > 0) {
uECC_vli_sub(a, a, b, num_words);
uECC_vli_rshift1(a, num_words);
if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
uECC_vli_add(u, u, mod, num_words);
}
uECC_vli_sub(u, u, v, num_words);
vli_modInv_update(u, mod, num_words);
} else {
uECC_vli_sub(b, b, a, num_words);
uECC_vli_rshift1(b, num_words);
if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
uECC_vli_add(v, v, mod, num_words);
}
uECC_vli_sub(v, v, u, num_words);
vli_modInv_update(v, mod, num_words);
}
}
uECC_vli_set(result, u, num_words);
}
/* ------ Point operations ------ */
void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * Z1, uECC_Curve curve)
{
/* t1 = X, t2 = Y, t3 = Z */
uECC_word_t t4[NUM_ECC_WORDS];
uECC_word_t t5[NUM_ECC_WORDS];
wordcount_t num_words = curve->num_words;
if (uECC_vli_isZero(Z1, num_words)) {
return;
}
uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
if (uECC_vli_testBit(X1, 0)) {
uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
uECC_vli_rshift1(X1, num_words);
X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
} else {
uECC_vli_rshift1(X1, num_words);
}
/* t1 = 3/2*(x1^2 - z1^4) = B */
uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
/* t4 = B * (A - x3) - y1^4 = y3: */
uECC_vli_modSub(t4, X1, t4, curve->p, num_words);
uECC_vli_set(X1, Z1, num_words);
uECC_vli_set(Z1, Y1, num_words);
uECC_vli_set(Y1, t4, num_words);
}
void x_side_default(uECC_word_t *result,
const uECC_word_t *x,
uECC_Curve curve)
{
uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
wordcount_t num_words = curve->num_words;
uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
/* r = x^3 - 3x + b: */
uECC_vli_modAdd(result, result, curve->b, curve->p, num_words);
}
uECC_Curve uECC_secp256r1(void)
{
return &curve_secp256r1;
}
void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
{
unsigned int tmp[NUM_ECC_WORDS];
int carry;
/* t */
uECC_vli_set(result, product, NUM_ECC_WORDS);
/* s1 */
tmp[0] = tmp[1] = tmp[2] = 0;
tmp[3] = product[11];
tmp[4] = product[12];
tmp[5] = product[13];
tmp[6] = product[14];
tmp[7] = product[15];
carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
/* s2 */
tmp[3] = product[12];
tmp[4] = product[13];
tmp[5] = product[14];
tmp[6] = product[15];
tmp[7] = 0;
carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
/* s3 */
tmp[0] = product[8];
tmp[1] = product[9];
tmp[2] = product[10];
tmp[3] = tmp[4] = tmp[5] = 0;
tmp[6] = product[14];
tmp[7] = product[15];
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
/* s4 */
tmp[0] = product[9];
tmp[1] = product[10];
tmp[2] = product[11];
tmp[3] = product[13];
tmp[4] = product[14];
tmp[5] = product[15];
tmp[6] = product[13];
tmp[7] = product[8];
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
/* d1 */
tmp[0] = product[11];
tmp[1] = product[12];
tmp[2] = product[13];
tmp[3] = tmp[4] = tmp[5] = 0;
tmp[6] = product[8];
tmp[7] = product[10];
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
/* d2 */
tmp[0] = product[12];
tmp[1] = product[13];
tmp[2] = product[14];
tmp[3] = product[15];
tmp[4] = tmp[5] = 0;
tmp[6] = product[9];
tmp[7] = product[11];
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
/* d3 */
tmp[0] = product[13];
tmp[1] = product[14];
tmp[2] = product[15];
tmp[3] = product[8];
tmp[4] = product[9];
tmp[5] = product[10];
tmp[6] = 0;
tmp[7] = product[12];
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
/* d4 */
tmp[0] = product[14];
tmp[1] = product[15];
tmp[2] = 0;
tmp[3] = product[9];
tmp[4] = product[10];
tmp[5] = product[11];
tmp[6] = 0;
tmp[7] = product[13];
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
if (carry < 0) {
do {
carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
}
while (carry < 0);
} else {
while (carry ||
uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) {
carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
}
}
}
uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve)
{
return uECC_vli_isZero(point, curve->num_words * 2);
}
void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
uECC_Curve curve)
{
uECC_word_t t1[NUM_ECC_WORDS];
uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */
uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */
uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
}
/* P = (x1, y1) => 2P, (x2, y2) => P' */
static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * X2, uECC_word_t * Y2,
const uECC_word_t * const initial_Z,
uECC_Curve curve)
{
uECC_word_t z[NUM_ECC_WORDS];
wordcount_t num_words = curve->num_words;
if (initial_Z) {
uECC_vli_set(z, initial_Z, num_words);
} else {
uECC_vli_clear(z, num_words);
z[0] = 1;
}
uECC_vli_set(X2, X1, num_words);
uECC_vli_set(Y2, Y1, num_words);
apply_z(X1, Y1, z, curve);
curve->double_jacobian(X1, Y1, z, curve);
apply_z(X2, Y2, z, curve);
}
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * X2, uECC_word_t * Y2,
uECC_Curve curve)
{
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
uECC_word_t t5[NUM_ECC_WORDS];
wordcount_t num_words = curve->num_words;
uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
uECC_vli_set(X2, t5, num_words);
}
/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
or P => P - Q, Q => P + Q
*/
static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * X2, uECC_word_t * Y2,
uECC_Curve curve)
{
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
uECC_word_t t5[NUM_ECC_WORDS];
uECC_word_t t6[NUM_ECC_WORDS];
uECC_word_t t7[NUM_ECC_WORDS];
wordcount_t num_words = curve->num_words;
uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
/* t4 = (y2 - y1)*(B - x3) - E = y3: */
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words);
uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
/* t2 = (y2+y1)*(x3' - B) - E = y3': */
uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words);
uECC_vli_set(X1, t7, num_words);
}
void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
const uECC_word_t * scalar,
const uECC_word_t * initial_Z,
bitcount_t num_bits, uECC_Curve curve)
{
/* R0 and R1 */
uECC_word_t Rx[2][NUM_ECC_WORDS];
uECC_word_t Ry[2][NUM_ECC_WORDS];
uECC_word_t z[NUM_ECC_WORDS];
bitcount_t i;
uECC_word_t nb;
wordcount_t num_words = curve->num_words;
uECC_vli_set(Rx[1], point, num_words);
uECC_vli_set(Ry[1], point + num_words, num_words);
XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
for (i = num_bits - 2; i > 0; --i) {
nb = !uECC_vli_testBit(scalar, i);
XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
}
nb = !uECC_vli_testBit(scalar, 0);
XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
/* Find final 1/Z value. */
uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/
/* yP / (xP * Yb * (X1 - X0)) */
uECC_vli_modMult_fast(z, z, point + num_words, curve);
/* Xb * yP / (xP * Yb * (X1 - X0)) */
uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve);
/* End 1/Z calculation */
XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
apply_z(Rx[0], Ry[0], z, curve);
uECC_vli_set(result, Rx[0], num_words);
uECC_vli_set(result + num_words, Ry[0], num_words);
}
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
uECC_word_t *k1, uECC_Curve curve)
{
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
bitcount_t num_n_bits = curve->num_n_bits;
uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
(num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
uECC_vli_testBit(k0, num_n_bits));
uECC_vli_add(k1, k0, curve->n, num_n_words);
return carry;
}
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
uECC_word_t *private_key,
uECC_Curve curve)
{
uECC_word_t tmp1[NUM_ECC_WORDS];
uECC_word_t tmp2[NUM_ECC_WORDS];
uECC_word_t *p2[2] = {tmp1, tmp2};
uECC_word_t carry;
/* Regularize the bitcount for the private key so that attackers cannot
* use a side channel attack to learn the number of leading zeros. */
carry = regularize_k(private_key, tmp1, tmp2, curve);
EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
if (EccPoint_isZero(result, curve)) {
return 0;
}
return 1;
}
/* Converts an integer in uECC native format to big-endian bytes. */
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
const unsigned int *native)
{
wordcount_t i;
for (i = 0; i < num_bytes; ++i) {
unsigned b = num_bytes - 1 - i;
bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
}
}
/* Converts big-endian bytes to an integer in uECC native format. */
void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
int num_bytes)
{
wordcount_t i;
uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
for (i = 0; i < num_bytes; ++i) {
unsigned b = num_bytes - 1 - i;
native[b / uECC_WORD_SIZE] |=
(uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
}
}
int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
wordcount_t num_words)
{
uECC_word_t mask = (uECC_word_t)-1;
uECC_word_t tries;
bitcount_t num_bits = uECC_vli_numBits(top, num_words);
if (!g_rng_function) {
return 0;
}
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
return 0;
}
random[num_words - 1] &=
mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
if (!uECC_vli_isZero(random, num_words) &&
uECC_vli_cmp(top, random, num_words) == 1) {
return 1;
}
}
return 0;
}
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
{
uECC_word_t tmp1[NUM_ECC_WORDS];
uECC_word_t tmp2[NUM_ECC_WORDS];
wordcount_t num_words = curve->num_words;
/* The point at infinity is invalid. */
if (EccPoint_isZero(point, curve)) {
return -1;
}
/* x and y must be smaller than p. */
if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
return -2;
}
uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
/* Make sure that y^2 == x^3 + ax + b */
if (uECC_vli_equal(tmp1, tmp2, num_words) != 0)
return -3;
return 0;
}
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
{
uECC_word_t _public[NUM_ECC_WORDS * 2];
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
uECC_vli_bytesToNative(
_public + curve->num_words,
public_key + curve->num_bytes,
curve->num_bytes);
if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) {
return -4;
}
return uECC_valid_point(_public, curve);
}
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
uECC_Curve curve)
{
uECC_word_t _private[NUM_ECC_WORDS];
uECC_word_t _public[NUM_ECC_WORDS * 2];
uECC_vli_bytesToNative(
_private,
private_key,
BITS_TO_BYTES(curve->num_n_bits));
/* Make sure the private key is in the range [1, n-1]. */
if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
return 0;
}
if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
return 0;
}
/* Compute public key. */
if (!EccPoint_compute_public_key(_public, _private, curve)) {
return 0;
}
uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
uECC_vli_nativeToBytes(
public_key +
curve->num_bytes, curve->num_bytes, _public + curve->num_words);
return 1;
}

View File

@@ -0,0 +1,200 @@
/* ec_dh.c - TinyCrypt implementation of EC-DH */
/*
* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/constants.h>
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_dh.h>
#include <string.h>
#if default_RNG_defined
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
#else
static uECC_RNG_Function g_rng_function = 0;
#endif
int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
unsigned int *d, uECC_Curve curve)
{
uECC_word_t _private[NUM_ECC_WORDS];
uECC_word_t _public[NUM_ECC_WORDS * 2];
/* This function is designed for test purposes-only (such as validating NIST
* test vectors) as it uses a provided value for d instead of generating
* it uniformly at random. */
memcpy (_private, d, NUM_ECC_BYTES);
/* Computing public-key from private: */
if (EccPoint_compute_public_key(_public, _private, curve)) {
/* Converting buffers to correct bit order: */
uECC_vli_nativeToBytes(private_key,
BITS_TO_BYTES(curve->num_n_bits),
_private);
uECC_vli_nativeToBytes(public_key,
curve->num_bytes,
_public);
uECC_vli_nativeToBytes(public_key + curve->num_bytes,
curve->num_bytes,
_public + curve->num_words);
/* erasing temporary buffer used to store secret: */
memset(_private, 0, NUM_ECC_BYTES);
return 1;
}
return 0;
}
int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve)
{
uECC_word_t _random[NUM_ECC_WORDS * 2];
uECC_word_t _private[NUM_ECC_WORDS];
uECC_word_t _public[NUM_ECC_WORDS * 2];
uECC_word_t tries;
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
/* Generating _private uniformly at random: */
uECC_RNG_Function rng_function = uECC_get_rng();
if (!rng_function ||
!rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
return 0;
}
/* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
/* Computing public-key from private: */
if (EccPoint_compute_public_key(_public, _private, curve)) {
/* Converting buffers to correct bit order: */
uECC_vli_nativeToBytes(private_key,
BITS_TO_BYTES(curve->num_n_bits),
_private);
uECC_vli_nativeToBytes(public_key,
curve->num_bytes,
_public);
uECC_vli_nativeToBytes(public_key + curve->num_bytes,
curve->num_bytes,
_public + curve->num_words);
/* erasing temporary buffer that stored secret: */
memset(_private, 0, NUM_ECC_BYTES);
return 1;
}
}
return 0;
}
int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
uint8_t *secret, uECC_Curve curve)
{
uECC_word_t _public[NUM_ECC_WORDS * 2];
uECC_word_t _private[NUM_ECC_WORDS];
uECC_word_t tmp[NUM_ECC_WORDS];
uECC_word_t *p2[2] = {_private, tmp};
uECC_word_t *initial_Z = 0;
uECC_word_t carry;
wordcount_t num_words = curve->num_words;
wordcount_t num_bytes = curve->num_bytes;
int r;
/* Converting buffers to correct bit order: */
uECC_vli_bytesToNative(_private,
private_key,
BITS_TO_BYTES(curve->num_n_bits));
uECC_vli_bytesToNative(_public,
public_key,
num_bytes);
uECC_vli_bytesToNative(_public + num_words,
public_key + num_bytes,
num_bytes);
/* Regularize the bitcount for the private key so that attackers cannot use a
* side channel attack to learn the number of leading zeros. */
carry = regularize_k(_private, _private, tmp, curve);
/* If an RNG function was specified, try to get a random initial Z value to
* improve protection against side-channel attacks. */
if (g_rng_function) {
if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
r = 0;
goto clear_and_out;
}
initial_Z = p2[carry];
}
EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
curve);
uECC_vli_nativeToBytes(secret, num_bytes, _public);
r = !EccPoint_isZero(_public, curve);
clear_and_out:
/* erasing temporary buffer used to store secret: */
memset(p2, 0, sizeof(p2));
__asm__ __volatile__("" :: "g"(p2) : "memory");
memset(tmp, 0, sizeof(tmp));
__asm__ __volatile__("" :: "g"(tmp) : "memory");
memset(_private, 0, sizeof(_private));
__asm__ __volatile__("" :: "g"(_private) : "memory");
return r;
}

View File

@@ -0,0 +1,295 @@
/* ec_dsa.c - TinyCrypt implementation of EC-DSA */
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/constants.h>
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_dsa.h>
#if default_RNG_defined
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
#else
static uECC_RNG_Function g_rng_function = 0;
#endif
static void bits2int(uECC_word_t *native, const uint8_t *bits,
unsigned bits_size, uECC_Curve curve)
{
unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
int shift;
uECC_word_t carry;
uECC_word_t *ptr;
if (bits_size > num_n_bytes) {
bits_size = num_n_bytes;
}
uECC_vli_clear(native, num_n_words);
uECC_vli_bytesToNative(native, bits, bits_size);
if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
return;
}
shift = bits_size * 8 - curve->num_n_bits;
carry = 0;
ptr = native + num_n_words;
while (ptr-- > native) {
uECC_word_t temp = *ptr;
*ptr = (temp >> shift) | carry;
carry = temp << (uECC_WORD_BITS - shift);
}
/* Reduce mod curve_n */
if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
uECC_vli_sub(native, native, curve->n, num_n_words);
}
}
int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
unsigned hash_size, uECC_word_t *k, uint8_t *signature,
uECC_Curve curve)
{
uECC_word_t tmp[NUM_ECC_WORDS];
uECC_word_t s[NUM_ECC_WORDS];
uECC_word_t *k2[2] = {tmp, s};
uECC_word_t p[NUM_ECC_WORDS * 2];
uECC_word_t carry;
wordcount_t num_words = curve->num_words;
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
bitcount_t num_n_bits = curve->num_n_bits;
/* Make sure 0 < k < curve_n */
if (uECC_vli_isZero(k, num_words) ||
uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
return 0;
}
carry = regularize_k(k, tmp, s, curve);
EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
if (uECC_vli_isZero(p, num_words)) {
return 0;
}
/* If an RNG function was specified, get a random number
to prevent side channel analysis of k. */
if (!g_rng_function) {
uECC_vli_clear(tmp, num_n_words);
tmp[0] = 1;
}
else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
return 0;
}
/* Prevent side channel analysis of uECC_vli_modInv() to determine
bits of k / the private key by premultiplying by a random number */
uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */
uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
/* tmp = d: */
uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
s[num_n_words - 1] = 0;
uECC_vli_set(s, p, num_words);
uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
bits2int(tmp, message_hash, hash_size, curve);
uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
return 0;
}
uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
return 1;
}
int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
unsigned hash_size, uint8_t *signature, uECC_Curve curve)
{
uECC_word_t _random[2*NUM_ECC_WORDS];
uECC_word_t k[NUM_ECC_WORDS];
uECC_word_t tries;
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
/* Generating _random uniformly at random: */
uECC_RNG_Function rng_function = uECC_get_rng();
if (!rng_function ||
!rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
return 0;
}
// computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature,
curve)) {
return 1;
}
}
return 0;
}
static bitcount_t smax(bitcount_t a, bitcount_t b)
{
return (a > b ? a : b);
}
int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash,
unsigned hash_size, const uint8_t *signature,
uECC_Curve curve)
{
uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS];
uECC_word_t z[NUM_ECC_WORDS];
uECC_word_t sum[NUM_ECC_WORDS * 2];
uECC_word_t rx[NUM_ECC_WORDS];
uECC_word_t ry[NUM_ECC_WORDS];
uECC_word_t tx[NUM_ECC_WORDS];
uECC_word_t ty[NUM_ECC_WORDS];
uECC_word_t tz[NUM_ECC_WORDS];
const uECC_word_t *points[4];
const uECC_word_t *point;
bitcount_t num_bits;
bitcount_t i;
uECC_word_t _public[NUM_ECC_WORDS * 2];
uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS];
wordcount_t num_words = curve->num_words;
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
rx[num_n_words - 1] = 0;
r[num_n_words - 1] = 0;
s[num_n_words - 1] = 0;
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes,
curve->num_bytes);
uECC_vli_bytesToNative(r, signature, curve->num_bytes);
uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
/* r, s must not be 0. */
if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
return 0;
}
/* r, s must be < n. */
if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
return 0;
}
/* Calculate u1 and u2. */
uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
u1[num_n_words - 1] = 0;
bits2int(u1, message_hash, hash_size, curve);
uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
/* Calculate sum = G + Q. */
uECC_vli_set(sum, _public, num_words);
uECC_vli_set(sum + num_words, _public + num_words, num_words);
uECC_vli_set(tx, curve->G, num_words);
uECC_vli_set(ty, curve->G + num_words, num_words);
uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
XYcZ_add(tx, ty, sum, sum + num_words, curve);
uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
apply_z(sum, sum + num_words, z, curve);
/* Use Shamir's trick to calculate u1*G + u2*Q */
points[0] = 0;
points[1] = curve->G;
points[2] = _public;
points[3] = sum;
num_bits = smax(uECC_vli_numBits(u1, num_n_words),
uECC_vli_numBits(u2, num_n_words));
point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
uECC_vli_set(rx, point, num_words);
uECC_vli_set(ry, point + num_words, num_words);
uECC_vli_clear(z, num_words);
z[0] = 1;
for (i = num_bits - 2; i >= 0; --i) {
uECC_word_t index;
curve->double_jacobian(rx, ry, z, curve);
index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
point = points[index];
if (point) {
uECC_vli_set(tx, point, num_words);
uECC_vli_set(ty, point + num_words, num_words);
apply_z(tx, ty, z, curve);
uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
XYcZ_add(tx, ty, rx, ry, curve);
uECC_vli_modMult_fast(z, z, tz, curve);
}
}
uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
apply_z(rx, ry, z, curve);
/* v = x1 (mod n) */
if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
uECC_vli_sub(rx, rx, curve->n, num_n_words);
}
/* Accept only if v == r. */
return (int)(uECC_vli_equal(rx, r, num_words) == 0);
}

View File

@@ -0,0 +1,105 @@
/* uECC_platform_specific.c - Implementation of platform specific functions*/
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* uECC_platform_specific.c -- Implementation of platform specific functions
*/
#if defined(unix) || defined(__linux__) || defined(__unix__) || \
defined(__unix) | (defined(__APPLE__) && defined(__MACH__)) || \
defined(uECC_POSIX)
/* Some POSIX-like system with /dev/urandom or /dev/random. */
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
int default_CSPRNG(uint8_t *dest, unsigned int size) {
/* input sanity check: */
if (dest == (uint8_t *) 0 || (size <= 0))
return 0;
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
if (fd == -1) {
fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
if (fd == -1) {
return 0;
}
}
char *ptr = (char *)dest;
size_t left = (size_t) size;
while (left > 0) {
ssize_t bytes_read = read(fd, ptr, left);
if (bytes_read <= 0) { // read failed
close(fd);
return 0;
}
left -= bytes_read;
ptr += bytes_read;
}
close(fd);
return 1;
}
#endif /* platform */

View File

@@ -0,0 +1,148 @@
/* hmac.c - TinyCrypt implementation of the HMAC algorithm */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/hmac.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size)
{
const uint8_t inner_pad = (uint8_t) 0x36;
const uint8_t outer_pad = (uint8_t) 0x5c;
unsigned int i;
for (i = 0; i < key_size; ++i) {
key[i] = inner_pad ^ new_key[i];
key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i];
}
for (; i < TC_SHA256_BLOCK_SIZE; ++i) {
key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad;
}
}
int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
unsigned int key_size)
{
/* input sanity check: */
if (ctx == (TCHmacState_t) 0 ||
key == (const uint8_t *) 0 ||
key_size == 0) {
return TC_CRYPTO_FAIL;
}
const uint8_t dummy_key[key_size];
struct tc_hmac_state_struct dummy_state;
if (key_size <= TC_SHA256_BLOCK_SIZE) {
/*
* The next three lines consist of dummy calls just to avoid
* certain timing attacks. Without these dummy calls,
* adversaries would be able to learn whether the key_size is
* greater than TC_SHA256_BLOCK_SIZE by measuring the time
* consumed in this process.
*/
(void)tc_sha256_init(&dummy_state.hash_state);
(void)tc_sha256_update(&dummy_state.hash_state,
dummy_key,
key_size);
(void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE],
&dummy_state.hash_state);
/* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */
rekey(ctx->key, key, key_size);
} else {
(void)tc_sha256_init(&ctx->hash_state);
(void)tc_sha256_update(&ctx->hash_state, key, key_size);
(void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE],
&ctx->hash_state);
rekey(ctx->key,
&ctx->key[TC_SHA256_DIGEST_SIZE],
TC_SHA256_DIGEST_SIZE);
}
return TC_CRYPTO_SUCCESS;
}
int tc_hmac_init(TCHmacState_t ctx)
{
/* input sanity check: */
if (ctx == (TCHmacState_t) 0) {
return TC_CRYPTO_FAIL;
}
(void) tc_sha256_init(&ctx->hash_state);
(void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE);
return TC_CRYPTO_SUCCESS;
}
int tc_hmac_update(TCHmacState_t ctx,
const void *data,
unsigned int data_length)
{
/* input sanity check: */
if (ctx == (TCHmacState_t) 0) {
return TC_CRYPTO_FAIL;
}
(void)tc_sha256_update(&ctx->hash_state, data, data_length);
return TC_CRYPTO_SUCCESS;
}
int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx)
{
/* input sanity check: */
if (tag == (uint8_t *) 0 ||
taglen != TC_SHA256_DIGEST_SIZE ||
ctx == (TCHmacState_t) 0) {
return TC_CRYPTO_FAIL;
}
(void) tc_sha256_final(tag, &ctx->hash_state);
(void)tc_sha256_init(&ctx->hash_state);
(void)tc_sha256_update(&ctx->hash_state,
&ctx->key[TC_SHA256_BLOCK_SIZE],
TC_SHA256_BLOCK_SIZE);
(void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE);
(void)tc_sha256_final(tag, &ctx->hash_state);
/* destroy the current state */
_set(ctx, 0, sizeof(*ctx));
return TC_CRYPTO_SUCCESS;
}

View File

@@ -0,0 +1,212 @@
/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/hmac_prng.h>
#include <tinycrypt/hmac.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
/*
* min bytes in the seed string.
* MIN_SLEN*8 must be at least the expected security level.
*/
static const unsigned int MIN_SLEN = 32;
/*
* max bytes in the seed string;
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
*/
static const unsigned int MAX_SLEN = UINT32_MAX;
/*
* max bytes in the personalization string;
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
*/
static const unsigned int MAX_PLEN = UINT32_MAX;
/*
* max bytes in the additional_info string;
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
*/
static const unsigned int MAX_ALEN = UINT32_MAX;
/*
* max number of generates between re-seeds;
* TinyCrypt accepts up to (2^32 - 1) which is the maximal value of
* a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48.
*/
static const unsigned int MAX_GENS = UINT32_MAX;
/*
* maximum bytes per generate call;
* SP800-90A specifies a maximum up to 2^19.
*/
static const unsigned int MAX_OUT = (1 << 19);
/*
* Assumes: prng != NULL, e != NULL, len >= 0.
*/
static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
{
const uint8_t separator0 = 0x00;
const uint8_t separator1 = 0x01;
/* use current state, e and separator 0 to compute a new prng key: */
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
(void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0));
(void)tc_hmac_update(&prng->h, e, len);
(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
/* configure the new prng key into the prng's instance of hmac */
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
/* use the new key to compute a new state variable v */
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
/* use current state, e and separator 1 to compute a new prng key: */
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
(void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1));
(void)tc_hmac_update(&prng->h, e, len);
(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
/* configure the new prng key into the prng's instance of hmac */
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
/* use the new key to compute a new state variable v */
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
}
int tc_hmac_prng_init(TCHmacPrng_t prng,
const uint8_t *personalization,
unsigned int plen)
{
/* input sanity check: */
if (prng == (TCHmacPrng_t) 0 ||
personalization == (uint8_t *) 0 ||
plen > MAX_PLEN) {
return TC_CRYPTO_FAIL;
}
/* put the generator into a known state: */
_set(prng->key, 0x00, sizeof(prng->key));
_set(prng->v, 0x01, sizeof(prng->v));
tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
/* update assumes SOME key has been configured into HMAC */
update(prng, personalization, plen);
/* force a reseed before allowing tc_hmac_prng_generate to succeed: */
prng->countdown = 0;
return TC_CRYPTO_SUCCESS;
}
int tc_hmac_prng_reseed(TCHmacPrng_t prng,
const uint8_t *seed,
unsigned int seedlen,
const uint8_t *additional_input,
unsigned int additionallen)
{
/* input sanity check: */
if (prng == (TCHmacPrng_t) 0 ||
seed == (const uint8_t *) 0 ||
seedlen < MIN_SLEN ||
seedlen > MAX_SLEN) {
return TC_CRYPTO_FAIL;
}
if (additional_input != (const uint8_t *) 0) {
/*
* Abort if additional_input is provided but has inappropriate
* length
*/
if (additionallen == 0 ||
additionallen > MAX_ALEN) {
return TC_CRYPTO_FAIL;
} else {
/* call update for the seed and additional_input */
update(prng, seed, seedlen);
update(prng, additional_input, additionallen);
}
} else {
/* call update only for the seed */
update(prng, seed, seedlen);
}
/* ... and enable hmac_prng_generate */
prng->countdown = MAX_GENS;
return TC_CRYPTO_SUCCESS;
}
int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng)
{
unsigned int bufferlen;
/* input sanity check: */
if (out == (uint8_t *) 0 ||
prng == (TCHmacPrng_t) 0 ||
outlen == 0 ||
outlen > MAX_OUT) {
return TC_CRYPTO_FAIL;
} else if (prng->countdown == 0) {
return TC_HMAC_PRNG_RESEED_REQ;
}
prng->countdown--;
while (outlen != 0) {
/* operate HMAC in OFB mode to create "random" outputs */
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ?
outlen : TC_SHA256_DIGEST_SIZE;
(void)_copy(out, bufferlen, prng->v, bufferlen);
out += bufferlen;
outlen = (outlen > TC_SHA256_DIGEST_SIZE) ?
(outlen - TC_SHA256_DIGEST_SIZE) : 0;
}
/* block future PRNG compromises from revealing past state */
update(prng, prng->v, TC_SHA256_DIGEST_SIZE);
return TC_CRYPTO_SUCCESS;
}

View File

@@ -0,0 +1,217 @@
/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/sha256.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
static void compress(unsigned int *iv, const uint8_t *data);
int tc_sha256_init(TCSha256State_t s)
{
/* input sanity check: */
if (s == (TCSha256State_t) 0) {
return TC_CRYPTO_FAIL;
}
/*
* Setting the initial state values.
* These values correspond to the first 32 bits of the fractional parts
* of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17
* and 19.
*/
_set((uint8_t *) s, 0x00, sizeof(*s));
s->iv[0] = 0x6a09e667;
s->iv[1] = 0xbb67ae85;
s->iv[2] = 0x3c6ef372;
s->iv[3] = 0xa54ff53a;
s->iv[4] = 0x510e527f;
s->iv[5] = 0x9b05688c;
s->iv[6] = 0x1f83d9ab;
s->iv[7] = 0x5be0cd19;
return TC_CRYPTO_SUCCESS;
}
int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen)
{
/* input sanity check: */
if (s == (TCSha256State_t) 0 ||
data == (void *) 0) {
return TC_CRYPTO_FAIL;
} else if (datalen == 0) {
return TC_CRYPTO_SUCCESS;
}
while (datalen-- > 0) {
s->leftover[s->leftover_offset++] = *(data++);
if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) {
compress(s->iv, s->leftover);
s->leftover_offset = 0;
s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3);
}
}
return TC_CRYPTO_SUCCESS;
}
int tc_sha256_final(uint8_t *digest, TCSha256State_t s)
{
unsigned int i;
/* input sanity check: */
if (digest == (uint8_t *) 0 ||
s == (TCSha256State_t) 0) {
return TC_CRYPTO_FAIL;
}
s->bits_hashed += (s->leftover_offset << 3);
s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */
if (s->leftover_offset > (sizeof(s->leftover) - 8)) {
/* there is not room for all the padding in this block */
_set(s->leftover + s->leftover_offset, 0x00,
sizeof(s->leftover) - s->leftover_offset);
compress(s->iv, s->leftover);
s->leftover_offset = 0;
}
/* add the padding and the length in big-Endian format */
_set(s->leftover + s->leftover_offset, 0x00,
sizeof(s->leftover) - 8 - s->leftover_offset);
s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed);
s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8);
s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16);
s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24);
s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32);
s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40);
s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48);
s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56);
/* hash the padding and length */
compress(s->iv, s->leftover);
/* copy the iv out to digest */
for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) {
unsigned int t = *((unsigned int *) &s->iv[i]);
*digest++ = (uint8_t)(t >> 24);
*digest++ = (uint8_t)(t >> 16);
*digest++ = (uint8_t)(t >> 8);
*digest++ = (uint8_t)(t);
}
/* destroy the current state */
_set(s, 0, sizeof(*s));
return TC_CRYPTO_SUCCESS;
}
/*
* Initializing SHA-256 Hash constant words K.
* These values correspond to the first 32 bits of the fractional parts of the
* cube roots of the first 64 primes between 2 and 311.
*/
static const unsigned int k256[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
static inline unsigned int ROTR(unsigned int a, unsigned int n)
{
return (((a) >> n) | ((a) << (32 - n)));
}
#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22))
#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25))
#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3))
#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10))
#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c)))
#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
static inline unsigned int BigEndian(const uint8_t **c)
{
unsigned int n = 0;
n = (((unsigned int)(*((*c)++))) << 24);
n |= ((unsigned int)(*((*c)++)) << 16);
n |= ((unsigned int)(*((*c)++)) << 8);
n |= ((unsigned int)(*((*c)++)));
return n;
}
static void compress(unsigned int *iv, const uint8_t *data)
{
unsigned int a, b, c, d, e, f, g, h;
unsigned int s0, s1;
unsigned int t1, t2;
unsigned int work_space[16];
unsigned int n;
unsigned int i;
a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3];
e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7];
for (i = 0; i < 16; ++i) {
n = BigEndian(&data);
t1 = work_space[i] = n;
t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
t2 = Sigma0(a) + Maj(a, b, c);
h = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
for ( ; i < 64; ++i) {
s0 = work_space[(i+1)&0x0f];
s0 = sigma0(s0);
s1 = work_space[(i+14)&0x0f];
s1 = sigma1(s1);
t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf];
t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
t2 = Sigma0(a) + Maj(a, b, c);
h = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d;
iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h;
}

View File

@@ -0,0 +1,74 @@
/* utils.c - TinyCrypt platform-dependent run-time operations */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <tinycrypt/utils.h>
#include <tinycrypt/constants.h>
#include <string.h>
#define MASK_TWENTY_SEVEN 0x1b
unsigned int _copy(uint8_t *to, unsigned int to_len,
const uint8_t *from, unsigned int from_len)
{
if (from_len <= to_len) {
(void)memcpy(to, from, from_len);
return from_len;
} else {
return TC_CRYPTO_FAIL;
}
}
void _set(void *to, uint8_t val, unsigned int len)
{
(void)memset(to, val, len);
}
/*
* Doubles the value of a byte for values up to 127.
*/
uint8_t _double_byte(uint8_t a)
{
return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN));
}
int _compare(const uint8_t *a, const uint8_t *b, size_t size)
{
const uint8_t *tempa = a;
const uint8_t *tempb = b;
uint8_t result = 0;
for (unsigned int i = 0; i < size; i++) {
result |= tempa[i] ^ tempb[i];
}
return result;
}

View File

@@ -0,0 +1,67 @@
################################################################################
#
# Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
#
# Tests Makefile.
#
################################################################################
include ../config.mk
TEST_LIB_FILE:=test_ecc_utils.c
TEST_SOURCE:=$(filter-out $(TEST_LIB_FILE), $(wildcard test_*.c))
TEST_OBJECTS:=$(TEST_SOURCE:.c=.o)
TEST_DEPS:=$(TEST_SOURCE:.c=.d)
TEST_BINARY:=$(TEST_SOURCE:.c=$(DOTEXE))
# Edit the 'all' content to add/remove tests needed from TinyCrypt library:
all: $(TEST_BINARY)
clean:
-$(RM) $(TEST_BINARY) $(TEST_OBJECTS) $(TEST_DEPS)
-$(RM) *~ *.o *.d
# Dependencies
test_aes$(DOTEXE): test_aes.o aes_encrypt.o aes_decrypt.o utils.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_cbc_mode$(DOTEXE): test_cbc_mode.o cbc_mode.o \
aes_encrypt.o aes_decrypt.o utils.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_ctr_mode$(DOTEXE): test_ctr_mode.o ctr_mode.o \
aes_encrypt.o utils.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_ctr_prng$(DOTEXE): test_ctr_prng.o ctr_prng.o \
aes_encrypt.o utils.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_cmac_mode$(DOTEXE): test_cmac_mode.o aes_encrypt.o utils.o \
cmac_mode.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_ccm_mode$(DOTEXE): test_ccm_mode.o aes_encrypt.o \
utils.o ccm_mode.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_hmac$(DOTEXE): test_hmac.o hmac.o sha256.o utils.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_hmac_prng$(DOTEXE): test_hmac_prng.o hmac_prng.o hmac.o \
sha256.o utils.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_sha256$(DOTEXE): test_sha256.o sha256.o utils.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_ecc_dh$(DOTEXE): test_ecc_dh.o ecc.o ecc_dh.o test_ecc_utils.o ecc_platform_specific.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
test_ecc_dsa$(DOTEXE): test_ecc_dsa.o ecc.o utils.o ecc_dh.o \
ecc_dsa.o sha256.o test_ecc_utils.o ecc_platform_specific.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
-include $(TEST_DEPS)

View File

@@ -0,0 +1,100 @@
/* test_ecc_utils.h - TinyCrypt interface to common functions for ECC tests */
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* test_ecc_utils.h -- Interface to common functions for ECC tests.
*/
#ifndef __TEST_ECC_UTILS_H__
#define __TEST_ECC_UTILS_H__
#include <tinycrypt/ecc_dh.h>
#include <tinycrypt/ecc.h>
#include <test_utils.h>
int hex2int (char hex);
/*
* Convert hex string to byte string
* Return number of bytes written to buf, or 0 on error
*/
int hex2bin(uint8_t *buf, const size_t buflen, const char *hex,
const size_t hexlen);
/*
* Convert hex string to zero-padded nanoECC scalar
*/
void string2scalar(unsigned int * scalar, unsigned int num_word32, char *str);
void print_ecc_scalar(const char *label, const unsigned int * p_vli,
unsigned int num_word32);
int check_ecc_result(const int num, const char *name,
const unsigned int *expected,
const unsigned int *computed,
const unsigned int num_word32, const bool verbose);
/* Test ecc_make_keys, and also as keygen part of other tests */
int keygen_vectors(char **d_vec, char **qx_vec, char **qy_vec, int tests, bool verbose);
void vli_print_bytes(uint8_t *vli, unsigned int size);
int check_code(const int num, const char *name, const int expected,
const int computed, const int verbose);
#endif /* __TEST_ECC_UTILS_H__ */

View File

@@ -0,0 +1,125 @@
/* test_utils.h - TinyCrypt interface to common functions for tests */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* test_utils.h -- Interface to common functions for tests.
*/
#ifndef __TEST_UTILS_H__
#define __TEST_UTILS_H__
#include <tinycrypt/constants.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define PRINT_DATA(fmt, ...) printf(fmt, ##__VA_ARGS__)
#define PRINT_LINE \
PRINT_DATA( \
"============================================================" \
"=======\n")
#define FAIL "FAIL"
#define PASS "PASS"
#define FMT_ERROR "%s - %s@%d. "
/* TC_ here stands for 'Test Case' not 'TinyCrypt' */
#define TC_PASS 0
#define TC_FAIL 1
#define TC_ERROR(fmt, ...) \
do { \
PRINT_DATA(FMT_ERROR, FAIL, __func__, __LINE__); \
PRINT_DATA(fmt, ##__VA_ARGS__); \
} while (0)
#define TC_PRINT(fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
#define TC_START(name) PRINT_DATA("tc_start() - %s\n", name)
#define TC_END(result, fmt, ...) PRINT_DATA(fmt, ##__VA_ARGS__)
/* prints result and the function name */
#define TC_END_RESULT(result) \
do { \
PRINT_LINE; \
TC_END(result, "%s - %s.\n", \
result == TC_PASS ? PASS : FAIL, __func__); \
} while (0)
#define TC_END_REPORT(result) \
do { \
PRINT_LINE; \
TC_END(result, \
"PROJECT EXECUTION %s\n", \
result == TC_PASS ? "SUCCESSFUL" : "FAILED"); \
} while (0)
static inline void show_str(const char *label, const uint8_t *s, size_t len)
{
unsigned int i;
TC_PRINT("%s = ", label);
for (i = 0; i < (unsigned int) len; ++i) {
TC_PRINT("%02x", s[i]);
}
TC_PRINT("\n");
}
static inline void fatal(unsigned int testnum, const void *expected, size_t expectedlen,
const void *computed, size_t computedlen)
{
TC_ERROR("\tTest #%d Failed!\n", testnum);
show_str("\t\tExpected", expected, expectedlen);
show_str("\t\tComputed ", computed, computedlen);
TC_PRINT("\n");
}
static inline unsigned int check_result(unsigned int testnum, const void *expected, size_t expectedlen,
const void *computed, size_t computedlen)
{
unsigned int result = TC_PASS;
if (expectedlen != computedlen) {
TC_ERROR("The length of the computed buffer (%zu)", computedlen);
TC_ERROR("does not match the expected length (%zu).", expectedlen);
result = TC_FAIL;
} else if (memcmp(computed, expected, computedlen) != 0) {
fatal(testnum, expected, expectedlen, computed, computedlen);
result = TC_FAIL;
}
return result;
}
#endif /* __TEST_UTILS_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,177 @@
/* test_cbc_mode.c - TinyCrypt implementation of some AES-CBC tests */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* DESCRIPTION
* This module tests the following AES-CBC Mode routines:
*
* Scenarios tested include:
* - AES128 CBC mode encryption SP 800-38a tests
*/
#include <tinycrypt/cbc_mode.h>
#include <tinycrypt/constants.h>
#include <test_utils.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
* NIST test vectors from SP 800-38a:
*
* Block #1
* Plaintext 6bc1bee22e409f96e93d7e117393172a
* Input Block 6bc0bce12a459991e134741a7f9e1925
* Output Block 7649abac8119b246cee98e9b12e9197d
* Ciphertext 7649abac8119b246cee98e9b12e9197d
* Block #2
* Plaintext ae2d8a571e03ac9c9eb76fac45af8e51
* Input Block d86421fb9f1a1eda505ee1375746972c
* Output Block 5086cb9b507219ee95db113a917678b2
* Ciphertext 5086cb9b507219ee95db113a917678b2
* Block #3
* Plaintext 30c81c46a35ce411e5fbc1191a0a52ef
* Input Block 604ed7ddf32efdff7020d0238b7c2a5d
* Output Block 73bed6b8e3c1743b7116e69e22229516
* Ciphertext 73bed6b8e3c1743b7116e69e22229516
* Block #4
* Plaintext f69f2445df4f9b17ad2b417be66c3710
* Input Block 8521f2fd3c8eef2cdc3da7e5c44ea206
* Output Block 3ff1caa1681fac09120eca307586e1a7
* Ciphertext 3ff1caa1681fac09120eca307586e1a7
*/
const uint8_t key[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c
};
const uint8_t iv[16] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f
};
const uint8_t plaintext[64] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11,
0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46,
0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b,
0xe6, 0x6c, 0x37, 0x10
};
const uint8_t ciphertext[80] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46,
0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, 0x50, 0x86, 0xcb, 0x9b,
0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e,
0x22, 0x22, 0x95, 0x16, 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09,
0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7
};
/*
* NIST SP 800-38a CBC Test for encryption and decryption.
*/
int test_1_and_2(void)
{
struct tc_aes_key_sched_struct a;
uint8_t iv_buffer[16];
uint8_t encrypted[80];
uint8_t decrypted[64];
uint8_t *p;
unsigned int length;
int result = TC_PASS;
(void)tc_aes128_set_encrypt_key(&a, key);
(void)memcpy(iv_buffer, iv, TC_AES_BLOCK_SIZE);
TC_PRINT("CBC test #1 (encryption SP 800-38a tests):\n");
if (tc_cbc_mode_encrypt(encrypted, sizeof(plaintext) + TC_AES_BLOCK_SIZE,
plaintext, sizeof(plaintext), iv_buffer, &a) == 0) {
TC_ERROR("CBC test #1 (encryption SP 800-38a tests) failed in "
"%s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = check_result(1, ciphertext, sizeof(encrypted), encrypted,
sizeof(encrypted));
TC_END_RESULT(result);
TC_PRINT("CBC test #2 (decryption SP 800-38a tests):\n");
(void)tc_aes128_set_decrypt_key(&a, key);
p = &encrypted[TC_AES_BLOCK_SIZE];
length = ((unsigned int) sizeof(encrypted)) - TC_AES_BLOCK_SIZE;
if (tc_cbc_mode_decrypt(decrypted, length - TC_AES_BLOCK_SIZE, p, length,
encrypted, &a) == 0) {
TC_ERROR("CBC test #2 (decryption SP 800-38a tests) failed in. "
"%s\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = check_result(2, plaintext, sizeof(decrypted), decrypted,
sizeof(decrypted));
exitTest1:
TC_END_RESULT(result);
return result;
}
/*
* Main task to test AES
*/
int main(void)
{
int result = TC_PASS;
TC_START("Performing AES128 tests:");
TC_PRINT("Performing CBC tests:\n");
result = test_1_and_2();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("CBC test #1 failed.\n");
goto exitTest;
}
TC_PRINT("All CBC tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
return result;
}

View File

@@ -0,0 +1,545 @@
/* test_ccm_mode.c - TinyCrypt AES-CCM tests (RFC 3610 tests) */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* DESCRIPTION
* This module tests the following AES-CCM Mode routines:
*
* Scenarios tested include:
* - AES128 CCM mode encryption RFC 3610 test vector #1
* - AES128 CCM mode encryption RFC 3610 test vector #2
* - AES128 CCM mode encryption RFC 3610 test vector #3
* - AES128 CCM mode encryption RFC 3610 test vector #7
* - AES128 CCM mode encryption RFC 3610 test vector #8
* - AES128 CCM mode encryption RFC 3610 test vector #9
* - AES128 CCM mode encryption No associated data
* - AES128 CCM mode encryption No payload data
*/
#include <tinycrypt/ccm_mode.h>
#include <tinycrypt/constants.h>
#include <test_utils.h>
#include <string.h>
#define TC_CCM_MAX_CT_SIZE 50
#define TC_CCM_MAX_PT_SIZE 25
#define NUM_NIST_KEYS 16
#define NONCE_LEN 13
#define HEADER_LEN 8
#define M_LEN8 8
#define M_LEN10 10
#define DATA_BUF_LEN23 23
#define DATA_BUF_LEN24 24
#define DATA_BUF_LEN25 25
#define EXPECTED_BUF_LEN31 31
#define EXPECTED_BUF_LEN32 32
#define EXPECTED_BUF_LEN33 33
#define EXPECTED_BUF_LEN34 34
#define EXPECTED_BUF_LEN35 35
int do_test(const uint8_t *key, uint8_t *nonce,
size_t nlen, const uint8_t *hdr,
size_t hlen, const uint8_t *data,
size_t dlen, const uint8_t *expected,
size_t elen, const int mlen)
{
int result = TC_PASS;
uint8_t ciphertext[TC_CCM_MAX_CT_SIZE];
uint8_t decrypted[TC_CCM_MAX_PT_SIZE];
struct tc_ccm_mode_struct c;
struct tc_aes_key_sched_struct sched;
tc_aes128_set_encrypt_key(&sched, key);
result = tc_ccm_config(&c, &sched, nonce, nlen, mlen);
if (result == 0) {
TC_ERROR("CCM config failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = tc_ccm_generation_encryption(ciphertext, TC_CCM_MAX_CT_SIZE, hdr,
hlen, data, dlen, &c);
if (result == 0) {
TC_ERROR("ccm_encrypt failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
if (memcmp(expected, ciphertext, elen) != 0) {
TC_ERROR("ccm_encrypt produced wrong ciphertext in %s.\n",
__func__);
show_str("\t\tExpected", expected, elen);
show_str("\t\tComputed", ciphertext, elen);
result = TC_FAIL;
goto exitTest1;
}
result = tc_ccm_decryption_verification(decrypted, TC_CCM_MAX_PT_SIZE, hdr,
hlen, ciphertext, dlen+mlen, &c);
if (result == 0) {
TC_ERROR("ccm_decrypt failed in %s.\n", __func__);
show_str("\t\tExpected", data, dlen);
show_str("\t\tComputed", decrypted, sizeof(decrypted));
result = TC_FAIL;
goto exitTest1;
}
result = TC_PASS;
exitTest1:
TC_END_RESULT(result);
return result;
}
int test_vector_1(void)
{
int result = TC_PASS;
/* RFC 3610 test vector #1 */
const uint8_t key[NUM_NIST_KEYS] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
};
uint8_t nonce[NONCE_LEN] = {
0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0,
0xa1, 0xa2, 0xa3, 0xa4, 0xa5
};
const uint8_t hdr[HEADER_LEN] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
const uint8_t data[DATA_BUF_LEN23] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
};
const uint8_t expected[EXPECTED_BUF_LEN31] = {
0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0
};
uint16_t mlen = M_LEN8;
TC_PRINT("%s: Performing CCM test #1 (RFC 3610 test vector #1):\n",
__func__);
result = do_test(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
data, sizeof(data), expected, sizeof(expected), mlen);
return result;
}
int test_vector_2(void)
{
int result = TC_PASS;
/* RFC 3610 test vector #2 */
const uint8_t key[NUM_NIST_KEYS] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
};
uint8_t nonce[NONCE_LEN] = {
0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01, 0xa0,
0xa1, 0xa2, 0xa3, 0xa4, 0xa5
};
const uint8_t hdr[HEADER_LEN] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
const uint8_t data[DATA_BUF_LEN24] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
const uint8_t expected[EXPECTED_BUF_LEN32] = {
0x72, 0xc9, 0x1a, 0x36, 0xe1, 0x35, 0xf8, 0xcf,
0x29, 0x1c, 0xa8, 0x94, 0x08, 0x5c, 0x87, 0xe3,
0xcc, 0x15, 0xc4, 0x39, 0xc9, 0xe4, 0x3a, 0x3b,
0xa0, 0x91, 0xd5, 0x6e, 0x10, 0x40, 0x09, 0x16
};
uint16_t mlen = M_LEN8;
TC_PRINT("%s: Performing CCM test #2 (RFC 3610 test vector #2):\n",
__func__);
result = do_test(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
data, sizeof(data), expected, sizeof(expected), mlen);
return result;
}
int test_vector_3(void)
{
int result = TC_PASS;
/* RFC 3610 test vector #3 */
const uint8_t key[NUM_NIST_KEYS] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
};
uint8_t nonce[NONCE_LEN] = {
0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x02, 0xa0,
0xa1, 0xa2, 0xa3, 0xa4, 0xa5
};
const uint8_t hdr[HEADER_LEN] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
const uint8_t data[DATA_BUF_LEN25] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20
};
const uint8_t expected[EXPECTED_BUF_LEN33] = {
0x51, 0xb1, 0xe5, 0xf4, 0x4a, 0x19, 0x7d, 0x1d,
0xa4, 0x6b, 0x0f, 0x8e, 0x2d, 0x28, 0x2a, 0xe8,
0x71, 0xe8, 0x38, 0xbb, 0x64, 0xda, 0x85, 0x96,
0x57, 0x4a, 0xda, 0xa7, 0x6f, 0xbd, 0x9f, 0xb0,
0xc5
};
uint16_t mlen = M_LEN8;
TC_PRINT("%s: Performing CCM test #3 (RFC 3610 test vector #3):\n",
__func__);
result = do_test(key, nonce, sizeof(nonce), hdr, sizeof(hdr), data,
sizeof(data), expected, sizeof(expected), mlen);
return result;
}
int test_vector_4(void)
{
int result = TC_PASS;
/* RFC 3610 test vector #7 */
const uint8_t key[NUM_NIST_KEYS] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
};
uint8_t nonce[NONCE_LEN] = {
0x00, 0x00, 0x00, 0x09, 0x08, 0x07, 0x06, 0xa0,
0xa1, 0xa2, 0xa3, 0xa4, 0xa5
};
const uint8_t hdr[HEADER_LEN] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
const uint8_t data[DATA_BUF_LEN23] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
};
const uint8_t expected[EXPECTED_BUF_LEN33] = {
0x01, 0x35, 0xD1, 0xB2, 0xC9, 0x5F, 0x41, 0xD5,
0xD1, 0xD4, 0xFE, 0xC1, 0x85, 0xD1, 0x66, 0xB8,
0x09, 0x4E, 0x99, 0x9D, 0xFE, 0xD9, 0x6C, 0x04,
0x8C, 0x56, 0x60, 0x2C, 0x97, 0xAC, 0xBB, 0x74,
0x90
};
uint16_t mlen = M_LEN10;
TC_PRINT("%s: Performing CCM test #4 (RFC 3610 test vector #7):\n",
__func__);
result = do_test(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
data, sizeof(data), expected, sizeof(expected), mlen);
return result;
}
int test_vector_5(void)
{
int result = TC_PASS;
/* RFC 3610 test vector #8 */
const uint8_t key[NUM_NIST_KEYS] = {
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
};
uint8_t nonce[NONCE_LEN] = {
0x00, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x07, 0xA0,
0xA1, 0xA2, 0xA3, 0xA4, 0xA5
};
const uint8_t hdr[HEADER_LEN] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
const uint8_t data[DATA_BUF_LEN24] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
const uint8_t expected[EXPECTED_BUF_LEN34] = {
0x7B, 0x75, 0x39, 0x9A, 0xC0, 0x83, 0x1D, 0xD2,
0xF0, 0xBB, 0xD7, 0x58, 0x79, 0xA2, 0xFD, 0x8F,
0x6C, 0xAE, 0x6B, 0x6C, 0xD9, 0xB7, 0xDB, 0x24,
0xC1, 0x7B, 0x44, 0x33, 0xF4, 0x34, 0x96, 0x3F,
0x34, 0xB4
};
uint16_t mlen = M_LEN10;
TC_PRINT("%s: Performing CCM test #5 (RFC 3610 test vector #8):\n",
__func__);
result = do_test(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
data, sizeof(data), expected, sizeof(expected), mlen);
return result;
}
int test_vector_6(void)
{
int result = TC_PASS;
/* RFC 3610 test vector #9 */
const uint8_t key[NUM_NIST_KEYS] = {
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
};
uint8_t nonce[NONCE_LEN] = {
0x00, 0x00, 0x00, 0x0B, 0x0A, 0x09, 0x08, 0xA0,
0xA1, 0xA2, 0xA3, 0xA4, 0xA5
};
const uint8_t hdr[HEADER_LEN] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
const uint8_t data[DATA_BUF_LEN25] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20
};
const uint8_t expected[EXPECTED_BUF_LEN35] = {
0x82, 0x53, 0x1a, 0x60, 0xCC, 0x24, 0x94, 0x5a,
0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
0x7e, 0x5f, 0x4e
};
uint16_t mlen = M_LEN10;
TC_PRINT("%s: Performing CCM test #6 (RFC 3610 test vector #9):\n",
__func__);
result = do_test(key, nonce, sizeof(nonce), hdr, sizeof(hdr),
data, sizeof(data), expected, sizeof(expected), mlen);
return result;
}
int test_vector_7(void)
{
int result = TC_PASS;
/* Test based on RFC 3610 test vector #9 but with no associated data */
const uint8_t key[NUM_NIST_KEYS] = {
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
};
uint8_t nonce[NONCE_LEN] = {
0x00, 0x00, 0x00, 0x0B, 0x0A, 0x09, 0x08, 0xA0,
0xA1, 0xA2, 0xA3, 0xA4, 0xA5
};
uint8_t *hdr = NULL;
uint8_t data[DATA_BUF_LEN25] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20
};
struct tc_ccm_mode_struct c;
struct tc_aes_key_sched_struct sched;
uint8_t decrypted[TC_CCM_MAX_PT_SIZE];
uint8_t ciphertext[TC_CCM_MAX_CT_SIZE];
uint16_t mlen = M_LEN10;
TC_PRINT("%s: Performing CCM test #7 (no associated data):\n",
__func__);
tc_aes128_set_encrypt_key(&sched, key);
if (tc_ccm_config(&c, &sched, nonce, sizeof(nonce), mlen) == 0) {
TC_ERROR("ccm_config failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = tc_ccm_generation_encryption(ciphertext, TC_CCM_MAX_CT_SIZE, hdr,
0, data, sizeof(data), &c);
if (result == 0) {
TC_ERROR("ccm_encryption failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = tc_ccm_decryption_verification (decrypted, TC_CCM_MAX_PT_SIZE, hdr,
0, ciphertext, sizeof(data)+mlen, &c);
if (result == 0) {
TC_ERROR("ccm_decrypt failed in %s.\n", __func__);
show_str("\t\tExpected", data, sizeof(data));
show_str("\t\tComputed", decrypted, sizeof(decrypted));
result = TC_FAIL;
goto exitTest1;
}
result = TC_PASS;
exitTest1:
TC_END_RESULT(result);
return result;
}
int test_vector_8(void)
{
int result = TC_PASS;
/* Test based on RFC 3610 test vector #9 but with no payload data */
const uint8_t key[NUM_NIST_KEYS] = {
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF
};
uint8_t nonce[NONCE_LEN] = {
0x00, 0x00, 0x00, 0x0B, 0x0A, 0x09, 0x08, 0xA0,
0xA1, 0xA2, 0xA3, 0xA4, 0xA5
};
const uint8_t hdr[8] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
uint8_t *data = NULL;
struct tc_ccm_mode_struct c;
struct tc_aes_key_sched_struct sched;
uint8_t decrypted[TC_CCM_MAX_PT_SIZE];
uint8_t ciphertext[TC_CCM_MAX_CT_SIZE];
uint16_t mlen = M_LEN10;
TC_PRINT("%s: Performing CCM test #8 (no payload data):\n", __func__);
tc_aes128_set_encrypt_key(&sched, key);
if (tc_ccm_config(&c, &sched, nonce, sizeof(nonce), mlen) == 0) {
TC_ERROR("CCM config failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = tc_ccm_generation_encryption(ciphertext, TC_CCM_MAX_CT_SIZE, hdr,
sizeof(hdr), data, 0, &c);
if (result == 0) {
TC_ERROR("ccm_encrypt failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
result = tc_ccm_decryption_verification(decrypted, TC_CCM_MAX_PT_SIZE, hdr,
sizeof(hdr), ciphertext, mlen, &c);
if (result == 0) {
TC_ERROR("ccm_decrypt failed in %s.\n", __func__);
show_str("\t\tExpected", data, sizeof(data));
show_str("\t\tComputed", decrypted, sizeof(decrypted));
result = TC_FAIL;
goto exitTest1;
}
result = TC_PASS;
exitTest1:
TC_END_RESULT(result);
return result;
}
/*
* Main task to test CCM
*/
int main(void)
{
int result = TC_PASS;
TC_START("Performing CCM tests:");
result = test_vector_1();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CCM test #1 (RFC 3610 test vector #1) failed.\n");
goto exitTest;
}
result = test_vector_2();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CCM test #2 failed.\n");
goto exitTest;
}
result = test_vector_3();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CCM test #3 failed.\n");
goto exitTest;
}
result = test_vector_4();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CCM test #4 failed.\n");
goto exitTest;
}
result = test_vector_5();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CCM test #5 failed.\n");
goto exitTest;
}
result = test_vector_6();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CCM test #6 failed.\n");
goto exitTest;
}
result = test_vector_7();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CCM test #7 failed.\n");
goto exitTest;
}
result = test_vector_8();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CCM test #8 (no payload data) failed.\n");
goto exitTest;
}
TC_PRINT("All CCM tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
return result;
}

View File

@@ -0,0 +1,314 @@
/* test_cmac_mode.c - TinyCrypt AES-CMAC tests (including SP 800-38B tests) */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* DESCRIPTION
* This module tests the following AES-CMAC test (including SP 800-38B):
*
* Scenarios tested include:
* - CMAC test #1 (GF(2^128) double))
* - CMAC test #2 null msg (SP 800-38B test vector #1)
* - CMAC test #3 1 block msg (SP 800-38B test vector #2)
* - CMAC test #4 320 bit msg (SP 800-38B test vector #3)
* - CMAC test #5 512 bit msg (SP 800-38B test vector #4)
*/
#include <tinycrypt/cmac_mode.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/aes.h>
#include <test_utils.h>
#include <stdio.h>
#include <string.h>
#define BUF_LEN 16
static void show(const char *label, const uint8_t *s, size_t slen)
{
unsigned int i;
TC_PRINT("%s\t", label);
for (i = 0; i < slen; ++i) {
TC_PRINT("%02x", s[i]);
}
TC_PRINT("\n");
}
extern void gf_double(uint8_t *out, uint8_t *in);
static int verify_gf_2_128_double(uint8_t *K1, uint8_t *K2,
struct tc_cmac_struct s)
{
int result = TC_PASS;
TC_PRINT("Performing CMAC test #1 (GF(2^128) double):\n");
uint8_t zero[BUF_LEN];
uint8_t L[BUF_LEN];
const uint8_t l[BUF_LEN] = {
0x7d, 0xf7, 0x6b, 0x0c, 0x1a, 0xb8, 0x99, 0xb3,
0x3e, 0x42, 0xf0, 0x47, 0xb9, 0x1b, 0x54, 0x6f
};
const uint8_t k1[BUF_LEN] = {
0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
};
const uint8_t k2[BUF_LEN] = {
0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
};
(void) memset(zero, '\0', sizeof(zero));
tc_aes_encrypt(L, zero, s.sched);
if (memcmp(L, l, BUF_LEN) != 0) {
TC_ERROR("%s: AES encryption failed\n", __func__);
show("expected L =", l, sizeof(l));
show("computed L =", L, sizeof(L));
return TC_FAIL;
}
gf_double(K1, L);
if (memcmp(K1, k1, BUF_LEN) != 0) {
TC_ERROR("%s: gf_2_128_double failed when msb = 0\n", __func__);
show("expected K1 =", k1, sizeof(k1));
show("computed K1 =", K1, sizeof(k1));
return TC_FAIL;
}
gf_double(K2, K1);
if (memcmp(K2, k2, BUF_LEN) != 0) {
TC_ERROR("%s: gf_2_128_double failed when msb = 1\n", __func__);
show("expected K2 =", k2, sizeof(k2));
show("computed K2 =", K2, sizeof(k2));
return TC_FAIL;
}
TC_END_RESULT(result);
return result;
}
static int verify_cmac_null_msg(TCCmacState_t s)
{
int result = TC_PASS;
TC_PRINT("Performing CMAC test #2 (SP 800-38B test vector #1):\n");
const uint8_t tag[BUF_LEN] = {
0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
};
uint8_t Tag[BUF_LEN];
(void) tc_cmac_init(s);
(void) tc_cmac_update(s, (const uint8_t *) 0, 0);
(void) tc_cmac_final(Tag, s);
if (memcmp(Tag, tag, BUF_LEN) != 0) {
TC_ERROR("%s: aes_cmac failed with null msg = 1\n", __func__);
show("expected Tag =", tag, sizeof(tag));
show("computed Tag =", Tag, sizeof(Tag));
return TC_FAIL;
}
TC_END_RESULT(result);
return result;
}
static int verify_cmac_1_block_msg(TCCmacState_t s)
{
int result = TC_PASS;
TC_PRINT("Performing CMAC test #3 (SP 800-38B test vector #2):\n");
const uint8_t msg[BUF_LEN] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
};
const uint8_t tag[BUF_LEN] = {
0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
};
uint8_t Tag[BUF_LEN];
(void) tc_cmac_init(s);
(void) tc_cmac_update(s, msg, sizeof(msg));
(void) tc_cmac_final(Tag, s);
if (memcmp(Tag, tag, BUF_LEN) != 0) {
TC_ERROR("%s: aes_cmac failed with 1 block msg\n", __func__);
show("aes_cmac failed with 1 block msg =", msg, sizeof(msg));
show("expected Tag =", tag, sizeof(tag));
show("computed Tag =", Tag, sizeof(Tag));
return TC_FAIL;
}
TC_END_RESULT(result);
return result;
}
static int verify_cmac_320_bit_msg(TCCmacState_t s)
{
int result = TC_PASS;
TC_PRINT("Performing CMAC test #4 (SP 800-38B test vector #3):\n");
const uint8_t msg[40] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11
};
const uint8_t tag[BUF_LEN] = {
0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
};
uint8_t Tag[BUF_LEN];
(void) tc_cmac_init(s);
(void) tc_cmac_update(s, msg, sizeof(msg));
(void) tc_cmac_final(Tag, s);
if (memcmp(Tag, tag, BUF_LEN) != 0) {
TC_ERROR("%s: aes_cmac failed with 320 bit msg\n", __func__);
show("aes_cmac failed with 320 bit msg =", msg, sizeof(msg));
show("expected Tag =", tag, sizeof(tag));
show("computed Tag =", Tag, sizeof(Tag));
return TC_FAIL;
}
TC_END_RESULT(result);
return result;
}
static int verify_cmac_512_bit_msg(TCCmacState_t s)
{
int result = TC_PASS;
TC_PRINT("Performing CMAC test #5 (SP 800-38B test vector #4)\n");
const uint8_t msg[64] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
};
const uint8_t tag[BUF_LEN] = {
0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
};
uint8_t Tag[BUF_LEN];
(void)tc_cmac_init(s);
(void)tc_cmac_update(s, msg, sizeof(msg));
(void)tc_cmac_final(Tag, s);
if (memcmp(Tag, tag, BUF_LEN) != 0) {
TC_ERROR("%s: aes_cmac failed with 512 bit msg\n", __func__);
show("aes_cmac failed with 512 bit msg =", msg, sizeof(msg));
show("expected Tag =", tag, sizeof(tag));
show("computed Tag =", Tag, sizeof(Tag));
return TC_FAIL;
}
TC_END_RESULT(result);
return result;
}
/*
* Main task to test CMAC
* effects: returns 1 if all tests pass
* exceptions: returns a negative value if some test fails
*/
int main(void)
{
int result = TC_PASS;
struct tc_cmac_struct state;
struct tc_aes_key_sched_struct sched;
const uint8_t key[BUF_LEN] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
uint8_t K1[BUF_LEN], K2[BUF_LEN];
TC_START("Performing CMAC tests:");
(void) tc_cmac_setup(&state, key, &sched);
result = verify_gf_2_128_double(K1, K2, state);
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("CMAC test #1 (128 double) failed.\n");
goto exitTest;
}
(void) tc_cmac_setup(&state, key, &sched);
result = verify_cmac_null_msg(&state);
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("CMAC test #2 (null msg) failed.\n");
goto exitTest;
}
(void) tc_cmac_setup(&state, key, &sched);
result = verify_cmac_1_block_msg(&state);
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("CMAC test #3 (1 block msg)failed.\n");
goto exitTest;
}
(void) tc_cmac_setup(&state, key, &sched);
result = verify_cmac_320_bit_msg(&state);
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("CMAC test #4 (320 bit msg) failed.\n");
goto exitTest;
}
(void) tc_cmac_setup(&state, key, &sched);
result = verify_cmac_512_bit_msg(&state);
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("CMAC test #5 (512 bit msg)failed.\n");
goto exitTest;
}
TC_PRINT("All CMAC tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
return result;
}

View File

@@ -0,0 +1,150 @@
/* test_ctr_mode.c - TinyCrypt implementation of some AES-CTR tests */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
DESCRIPTION
This module tests the following AES-CTR Mode routines:
Scenarios tested include:
- AES128 CTR mode encryption SP 800-38a tests
*/
#include <tinycrypt/ctr_mode.h>
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include <test_utils.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* NIST SP 800-38a CTR Test for encryption and decryption.
*/
unsigned int test_1_and_2(void)
{
const uint8_t key[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c
};
uint8_t ctr[16] = {
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
0xfc, 0xfd, 0xfe, 0xff
};
const uint8_t plaintext[64] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11,
0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46,
0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b,
0xe6, 0x6c, 0x37, 0x10
};
const uint8_t ciphertext[80] = {
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
0xfc, 0xfd, 0xfe, 0xff, 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26,
0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x98, 0x06, 0xf6, 0x6b,
0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02,
0x0d, 0xb0, 0x3e, 0xab, 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1,
0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee
};
struct tc_aes_key_sched_struct sched;
uint8_t out[80];
uint8_t decrypted[64];
unsigned int result = TC_PASS;
uint32_t off = 0;
TC_PRINT("CTR test #1 (encryption SP 800-38a tests):\n");
(void)tc_aes128_set_encrypt_key(&sched, key);
(void)memcpy(out, ctr, sizeof(ctr));
if (tc_ctr_mode(&out[TC_AES_BLOCK_SIZE], sizeof(plaintext), plaintext,
sizeof(plaintext), ctr, &off, &sched) == 0) {
TC_ERROR("CTR test #1 (encryption SP 800-38a tests) failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
if (off != 0) {
TC_ERROR("CTR test #1 invalid block offset (%u).\n", off);
result = TC_FAIL;
goto exitTest1;
}
result = check_result(1, ciphertext, sizeof(out), out, sizeof(out));
TC_END_RESULT(result);
TC_PRINT("CTR test #2 (decryption SP 800-38a tests):\n");
(void) memcpy(ctr, out, sizeof(ctr));
off = 0;
if (tc_ctr_mode(decrypted, sizeof(decrypted), &out[TC_AES_BLOCK_SIZE],
sizeof(decrypted), ctr, &off, &sched) == 0) {
TC_ERROR("CTR test #2 (decryption SP 800-38a tests) failed in %s.\n", __func__);
result = TC_FAIL;
goto exitTest1;
}
if (off != 0) {
TC_ERROR("CTR test #2 invalid block offset (%u).\n", off);
result = TC_FAIL;
goto exitTest1;
}
result = check_result(2, plaintext, sizeof(plaintext),
decrypted, sizeof(plaintext));
exitTest1:
TC_END_RESULT(result);
return result;
}
/*
* Main task to test AES
*/
int main(void)
{
unsigned int result = TC_PASS;
TC_START("Performing AES128-CTR mode tests:");
TC_PRINT("Performing CTR tests:\n");
result = test_1_and_2();
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("CTR test #1 failed.\n");
goto exitTest;
}
TC_PRINT("All CTR tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
}

View File

@@ -0,0 +1,565 @@
/* test_ctr_prng.c - TinyCrypt implementation of some CTR-PRNG tests */
/*
* 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 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.
*/
/*
DESCRIPTION
This module tests the CTR-PRNG routines
*/
#include <tinycrypt/ctr_prng.h>
#include <tinycrypt/aes.h>
#include <tinycrypt/constants.h>
#include <test_utils.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* utility function to convert hex character representation to their nibble (4 bit) values */
static uint8_t nibbleFromChar(char c)
{
if(c >= '0' && c <= '9') return c - '0';
if(c >= 'a' && c <= 'f') return c - 'a' + 10U;
if(c >= 'A' && c <= 'F') return c - 'A' + 10U;
return 255U;
}
/*
* Convert a string of characters representing a hex buffer into a series of
* bytes of that real value
*/
uint8_t *hexStringToBytes(char *inhex)
{
uint8_t *retval;
uint8_t *p;
int len, i;
len = strlen(inhex) / 2;
retval = (uint8_t *)malloc(len+1);
for(i=0, p = (uint8_t *) inhex; i<len; i++) {
retval[i] = (nibbleFromChar(*p) << 4) | nibbleFromChar(*(p+1));
p += 2;
}
retval[len] = 0;
return retval;
}
typedef struct {
char * entropyString;
char * personalizationString; /* may be null */
char * additionalInputString1; /* may be null */
char * additionalInputString2; /* may be null */
char * expectedString;
} PRNG_Vector;
/* vectors taken from NIST CAVS 14.3 CTR_DRBG.rsp */
PRNG_Vector vectors[] = {
/*
* AES-128 no df, PredictionResistance = False, EntropyInputLen = 256,
* NonceLen = 0, PersonalizationStringLen = 0, AdditionalInputLen = 0,
* ReturnedBitsLen = 512
*/
{ /* Count 0 */
"ce50f33da5d4c1d3d4004eb35244b7f2cd7f2e5076fbf6780a7ff634b249a5fc",
0,
0,
0,
"6545c0529d372443b392ceb3ae3a99a30f963eaf313280f1d1a1e87f9db373d361e75d18018266499cccd64d9bbb8de0185f213383080faddec46bae1f784e5a",
},
{ /* Count 1 */
"a385f70a4d450321dfd18d8379ef8e7736fee5fbf0a0aea53b76696094e8aa93",
0,
0,
0,
"1a062553ab60457ed1f1c52f5aca5a3be564a27545358c112ed92c6eae2cb7597cfcc2e0a5dd81c5bfecc941da5e8152a9010d4845170734676c8c1b6b3073a5",
},
/*
* AES-128 no df, PredictionResistance = False, EntropyInputLen = 256,
* NonceLen = 0, PersonalizationStringLen = 0, AdditionalInputLen = 256,
* ReturnedBitsLen = 512
*/
{ /* Count 0 */
"6bd4f2ae649fc99350951ff0c5d460c1a9214154e7384975ee54b34b7cae0704",
0,
"ecd4893b979ac92db1894ae3724518a2f78cf2dbe2f6bbc6fda596df87c7a4ae",
"b23e9188687c88768b26738862c4791fa52f92502e1f94bf66af017c4228a0dc",
"5b2bf7a5c60d8ab6591110cbd61cd387b02de19784f496d1a109123d8b3562a5de2dd6d5d1aef957a6c4f371cecd93c15799d82e34d6a0dba7e915a27d8e65f3",
},
{ /* Count 1 */
"e2addbde2a76e769fc7aa3f45b31402f482b73bbe7067ad6254621f06d3ef68b",
0,
"ad11643b019e31245e4ea41f18f7680458310580fa6efad275c5833e7f800dae",
"b5d849616b3123c9725d188cd0005003220768d1200f9e7cc29ef6d88afb7b9a",
"132d0d50c8477a400bb8935be5928f916a85da9ffcf1a8f6e9f9a14cca861036cda14cf66d8953dab456b632cf687cd539b4b807926561d0b3562b9d3334fb61",
},
/*
* AES-128 no df, PredictionResistance = False, EntropyInputLen = 256,
* NonceLen = 0, PersonalizationStringLen = 256, AdditionalInputLen = 0,
* ReturnedBitsLen = 512
*/
{ /* Count 0 */
"cee23de86a69c7ef57f6e1e12bd16e35e51624226fa19597bf93ec476a44b0f2",
"a2ef16f226ea324f23abd59d5e3c660561c25e73638fe21c87566e86a9e04c3e",
0,
0,
"2a76d71b329f449c98dc08fff1d205a2fbd9e4ade120c7611c225c984eac8531288dd3049f3dc3bb3671501ab8fbf9ad49c86cce307653bd8caf29cb0cf07764",
},
{ /* Count 1 */
"b09eb4a82a39066ec945bb7c6aef6a0682a62c3e674bd900297d4271a5f25b49",
"a3b768adcfe76d61c972d900da8dffeeb2a42e740247aa719ed1c924d2d10bd4",
0,
0,
"5a1c26803f3ffd4daf32042fdcc32c3812bb5ef13bc208cef82ea047d2890a6f5dcecf32bcc32a2585775ac5e1ffaa8de00664c54fe00a7674b985619e953c3a",
},
/*
* AES-128 no df, PredictionResistance = False, EntropyInputLen = 256,
* NonceLen = 0, PersonalizationStringLen = 256, AdditionalInputLen = 256,
* ReturnedBitsLen = 512
*/
{ /* Count 0 */
"50b96542a1f2b8b05074051fe8fb0e45adbbd5560e3594e12d485fe1bfcb741f",
"820c3030f97b3ead81a93b88b871937278fd3d711d2085d9280cba394673b17e",
"1f1632058806d6d8e231288f3b15a3c324e90ccef4891bd595f09c3e80e27469",
"5cadc8bfd86d2a5d44f921f64c7d153001b9bdd7caa6618639b948ebfad5cb8a",
"02b76a66f103e98d450e25e09c35337747d987471d2b3d81e03be24c7e985417a32acd72bc0a6eddd9871410dacb921c659249b4e2b368c4ac8580fb5db559bc",
},
{ /* Count 1 */
"ff5f4b754e8b364f6df0c5effba5f1c036de49c4b38cd8d230ee1f14d7234ef5",
"994eb339f64034005d2e18352899e77df446e285c3430631d557498aac4f4280",
"e1824832d5fc2a6dea544cac2ab73306d6566bde98cc8f9425d064b860a9b218",
"c08b42433a78fd393a34ffc24724d479af08c36882799c134165d98b2866dc0a",
"1efa34aed07dd57bde9741b8d1907d28e8c1ac71601df37ef4295e6ffb67f6a1c4c13e5def65d505e2408aeb82948999ca1f9c9113b99a6b59ff7f0cc3dc6e92",
},
/*
* AES-128 no df, PredictionResistance = False, EntropyInputLen = 256,
* NonceLen = 0, PersonalizationStringLen = 0, AdditionalInputLen = 0,
* ReturnedBitsLen = 512
*/
{ /* Count 0 */
"69a09f6bf5dda15cd4af29e14cf5e0cddd7d07ac39bba587f8bc331104f9c448",
0,
0,
0,
"f78a4919a6ec899f7b6c69381febbbe083315f3d289e70346db0e4ec4360473ae0b3d916e9b6b964309f753ed66ae59de48da316cc1944bc8dfd0e2575d0ff6d",
},
{ /* Count 1 */
"80bfbd340d79888f34f043ed6807a9f28b72b6644d9d9e9d777109482b80788a",
0,
0,
0,
"80db048d2f130d864b19bfc547c92503e580cb1a8e1f74f3d97fdda6501fb1aa81fcedac0dd18b6ccfdc183ca28a44fc9f3a08834ba8751a2f4495367c54a185",
},
/*
* AES-128 no df, PredictionResistance = False, EntropyInputLen = 256,
* NonceLen = 0, PersonalizationStringLen = 0, AdditionalInputLen = 256,
* ReturnedBitsLen = 512
*/
{ /* Count 0 */
"7f40804693552e317523fda6935a5bc814353b1fbb7d334964ac4d1d12ddccce",
0,
"95c04259f64fcd1fe00c183aa3fb76b8a73b4d1243b800d770e38515bc41143c",
"5523102dbd7fe1228436b91a765b165ae6405eb0236e237afad4759cf0888941",
"1abf6bccb4c2d64e5187b1e2e34e493eca204ee4eef0d964267e38228f5f20efba376430a266f3832916d0a45b2703f46401dfd145e447a0a1667ebd8b6ee748",
},
{ /* Count 1 */
"350df677409a1dc297d01d3716a2abdfa6272cd030ab75f76839648582b47113",
0,
"ba5709a12ae6634a5436b7ea06838b48f7b847a237f6654a0e27c776ebee9511",
"f1b2c717c5e3a934127e10471d67accc65f4a45010ca53b35f54c88833dbd8e7",
"1ef1ea279812e8abe54f7ffd12d04c80ae40741f4ccfe232a5fba3a78dfd3e2ed419b88ee9188df724160cbb3aea0f276e84a3c0ff01e3b89fe30ebcfa64cb86",
},
/*
* AES-128 no df, PredictionResistance = False, EntropyInputLen = 256,
* NonceLen = 0, PersonalizationStringLen = 256, AdditionalInputLen = 0,
* ReturnedBitsLen = 512
*/
{ /* Count 0 */
"3fef762f0aa0677f61c65d749eeb10b013ff68ccc6314f150cfee752dcd8f987",
"f56db099240c7590dac396372b8737404d418b2864a3df96a8a397967245735f",
0,
0,
"af0afe0837442136fbb1959a1c91a9291c1d8188ede07c67d0e4dd6541303415e7a67999c302ba0df555324c26077514592a9b6db6be2f153fad2250161164e4",
},
{ /* Count 1 */
"3eebe77db4631862e3eb7e39370515b8baa1cdd71a5b1b0cda79c14d0b5f48ea",
"4be56a9b9c21242739c985ef12aa4d98e8c7da07c4c1dc6829f2e06833cfa148",
0,
0,
"be9e18a753df261927473c8bb5fb7c3ea6e821df5ab49adc566a4ebf44f75fa825b1f9d8c154bcd469134c0bb688e07e3c3e45407ca350d540e1528cc2e64068",
},
/*
* AES-128 no df, PredictionResistance = False, EntropyInputLen = 256,
* NonceLen = 0, PersonalizationStringLen = 256, AdditionalInputLen = 256,
* ReturnedBitsLen = 512
*/
{ /* Count 0 */
"c129c2732003bbf1d1dec244a933cd04cb47199bbce98fe080a1be880afb2155",
"64e2b9ac5c20642e3e3ee454b7463861a7e93e0dd1bbf8c4a0c28a6cb3d811ba",
"f94f0975760d52f47bd490d1623a9907e4df701f601cf2d573aba803a29d2b51",
"6f99720b186e2028a5fcc586b3ea518458e437ff449c7c5a318e6d13f75b5db7",
"7b8b3378b9031ab3101cec8af5b8ba5a9ca2a9af41432cd5f2e5e19716140bb219ed7f4ba88fc37b2d7e146037d2cac1128ffe14131c8691e581067a29cacf80",
},
{ /* Count 1 */
"7667643670254b3530e80a17b16b22406e84efa6a4b5ceef3ebc877495fc6048",
"40b92969953acde756747005117e46eff6893d7132a8311ffb1062280367326b",
"797a02ffbe8ff2c94ed0e5d39ebdc7847adaa762a88238242ed8f71f5635b194",
"d617f0f0e609e90d814192ba2e5214293d485402cdf9f789cc78b05e8c374f18",
"e8d6f89dca9825aed8927b43187492a98ca8648db30f0ac709556d401a8ac2b959c81350fc64332c4c0deb559a286a72e65dbb462bd872f9b28c0728f353dc10",
}
};
static unsigned int executePRNG_TestVector(PRNG_Vector vector, unsigned int idx)
{
unsigned int result = TC_PASS;
uint8_t * entropy = hexStringToBytes(vector.entropyString);
unsigned int entropylen = strlen(vector.entropyString) / 2U;
uint8_t * expected = hexStringToBytes(vector.expectedString);
unsigned int expectedlen = strlen(vector.expectedString) / 2U;
uint8_t * personalization = 0;
unsigned int plen = 0U;
uint8_t * additional_input1 = 0;
unsigned int additionallen1 = 0U;
uint8_t * additional_input2 = 0;
unsigned int additionallen2 = 0U;
uint8_t * output = (uint8_t *)malloc(expectedlen);
unsigned int i;
TCCtrPrng_t ctx;
if (0 != vector.personalizationString) {
personalization = hexStringToBytes(vector.personalizationString);
plen = strlen(vector.personalizationString) / 2U;
}
if (0 != vector.additionalInputString1) {
additional_input1 = hexStringToBytes(vector.additionalInputString1);
additionallen1 = strlen(vector.additionalInputString1) / 2U;
}
if (0 != vector.additionalInputString2) {
additional_input2 = hexStringToBytes(vector.additionalInputString2);
additionallen2 = strlen(vector.additionalInputString2) / 2U;
}
(void)tc_ctr_prng_init(&ctx, entropy, entropylen, personalization, plen);
(void)tc_ctr_prng_generate(&ctx, additional_input1, additionallen1, output, expectedlen);
(void)tc_ctr_prng_generate(&ctx, additional_input2, additionallen2, output, expectedlen);
for (i = 0U; i < expectedlen; i++) {
if (output[i] != expected[i]) {
TC_ERROR("CTR PRNG test #%d failed\n", idx);
result = TC_FAIL;
break;
}
}
free(entropy);
free(expected);
free(personalization);
free(additional_input1);
free(additional_input2);
free(output);
return result;
}
static int test_reseed(void)
{
int result = TC_PASS;
uint8_t entropy[32U] = {0U}; /* value not important */
uint8_t additional_input[32] = {0U};
uint8_t output[32];
TCCtrPrng_t ctx;
int ret;
unsigned int i;
(void)tc_ctr_prng_init(&ctx, entropy, sizeof entropy, 0, 0U);
/* force internal state to max allowed count */
ctx.reseedCount = 0x1000000000000ULL;
ret = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof output);
if (1 != ret) {
result = TC_FAIL;
goto exitTest;
}
/* expect further attempts to fail due to reaching reseed threshold */
ret = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof output);
if (-1 != ret) {
result = TC_FAIL;
goto exitTest;
}
/* reseed and confirm generate works again */
/* make entropy different from original value - not really important for the purpose of this test */
memset(entropy, 0xFF, sizeof entropy);
ret = tc_ctr_prng_reseed(&ctx, entropy, sizeof entropy, additional_input, sizeof additional_input);
if (1 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_generate(&ctx, 0, 0, output, sizeof output);
if (1 != ret) {
result = TC_FAIL;
goto exitTest;
}
/* confirm entropy and additional_input are being used correctly */
/* first, entropy only */
memset(&ctx, 0x0, sizeof ctx);
for (i = 0U; i < sizeof entropy; i++) {
entropy[i] = i;
}
ret = tc_ctr_prng_reseed(&ctx, entropy, sizeof entropy, 0, 0U);
if (1 != ret) {
result = TC_FAIL;
goto exitTest;
}
{
uint8_t expectedV[] =
{0x7EU, 0xE3U, 0xA0U, 0xCBU, 0x6DU, 0x5CU, 0x4BU, 0xC2U,
0x4BU, 0x7EU, 0x3CU, 0x48U, 0x88U, 0xC3U, 0x69U, 0x70U};
for (i = 0U; i < sizeof expectedV; i++) {
if (ctx.V[i] != expectedV[i]) {
result = TC_FAIL;
goto exitTest;
}
}
}
/* now, entropy and additional_input */
memset(&ctx, 0x0, sizeof ctx);
for (i = 0U; i < sizeof additional_input; i++) {
additional_input[i] = i * 2U;
}
ret = tc_ctr_prng_reseed(&ctx, entropy, sizeof entropy, additional_input, sizeof additional_input);
if (1 != ret) {
result = TC_FAIL;
goto exitTest;
}
{
uint8_t expectedV[] =
{0x5EU, 0xC1U, 0x84U, 0xEDU, 0x45U, 0x76U, 0x67U, 0xECU,
0x7BU, 0x4CU, 0x08U, 0x7EU, 0xB0U, 0xF9U, 0x55U, 0x4EU};
for (i = 0U; i < sizeof expectedV; i++) {
if (ctx.V[i] != expectedV[i]) {
result = TC_FAIL;
goto exitTest;
}
}
}
exitTest:
if (TC_FAIL == result) {
TC_ERROR("CTR PRNG reseed tests failed\n");
}
return result;
}
static int test_uninstantiate(void)
{
unsigned int i;
int result = TC_PASS;
uint8_t entropy[32U] = {0U}; /* value not important */
TCCtrPrng_t ctx;
(void)tc_ctr_prng_init(&ctx, entropy, sizeof entropy, 0, 0U);
tc_ctr_prng_uninstantiate(&ctx);
/* show that state has been zeroised */
for (i = 0U; i < sizeof ctx.V; i++) {
if (0U != ctx.V[i]) {
TC_ERROR("CTR PRNG uninstantiate tests failed\n");
result = TC_FAIL;
break;
}
}
for (i = 0U; i < sizeof ctx.key.words / sizeof ctx.key.words[0]; i++) {
if (0U != ctx.key.words[i]) {
TC_ERROR("CTR PRNG uninstantiate tests failed\n");
result = TC_FAIL;
break;
}
}
if (0U != ctx.reseedCount) {
TC_ERROR("CTR PRNG uninstantiate tests failed\n");
result = TC_FAIL;
}
return result;
}
static int test_robustness(void)
{
int result = TC_PASS;
int ret;
uint8_t entropy[32U] = {0U}; /* value not important */
uint8_t output[32];
TCCtrPrng_t ctx;
/* show that the CTR PRNG is robust to invalid inputs */
tc_ctr_prng_uninstantiate(0);
ret = tc_ctr_prng_generate(&ctx, 0, 0, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_generate(0, 0, 0, output, sizeof output);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_generate(0, 0, 0, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_reseed(&ctx, 0, 0, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
/* too little entropy */
ret = tc_ctr_prng_reseed(&ctx, entropy, (sizeof entropy) - 1U, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_reseed(0, entropy, sizeof entropy, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_reseed(0, 0, 0, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_init(&ctx, 0, 0, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
/* too little entropy */
ret = tc_ctr_prng_init(&ctx, entropy, (sizeof entropy) - 1U, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_init(0, entropy, sizeof entropy, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
ret = tc_ctr_prng_init(0, 0, 0, 0, 0);
if (0 != ret) {
result = TC_FAIL;
goto exitTest;
}
exitTest:
if (TC_FAIL == result) {
TC_ERROR("CTR PRNG reseed tests failed\n");
}
return result;
}
/*
* Main task to test CTR PRNG
*/
int main(void)
{
int result = TC_PASS;
unsigned int i;
TC_START("Performing CTR-PRNG tests:");
for (i = 0U; i < sizeof vectors / sizeof vectors[0]; i++) {
result = executePRNG_TestVector(vectors[i], i);
if (TC_PASS != result) {
goto exitTest;
}
}
if (TC_PASS != test_reseed()) {
goto exitTest;
}
if (TC_PASS != test_uninstantiate()) {
goto exitTest;
}
if (TC_PASS != test_robustness()) {
goto exitTest;
}
TC_PRINT("All CTR PRNG tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
}

View File

@@ -0,0 +1,521 @@
/* test_ecc_dh.c - TinyCrypt implementation of some EC-DH tests */
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* test_ecc_ecdh.c -- Implementation of some EC-DH tests
*
*/
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_dh.h>
#include <tinycrypt/ecc_platform_specific.h>
#include <test_ecc_utils.h>
#include <test_utils.h>
#include <tinycrypt/constants.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int ecdh_vectors(char **qx_vec, char **qy_vec, char **d_vec, char **z_vec,
int tests, int verbose)
{
unsigned int pub[2*NUM_ECC_WORDS];
unsigned int prv[NUM_ECC_WORDS];
unsigned int z[NUM_ECC_WORDS];
unsigned int result = TC_PASS;
int rc;
unsigned int exp_z[NUM_ECC_WORDS];
const struct uECC_Curve_t * curve = uECC_secp256r1();
for (int i = 0; i < tests; i++) {
string2scalar(pub + NUM_ECC_WORDS, NUM_ECC_WORDS, qx_vec[i]);
string2scalar(pub, NUM_ECC_WORDS, qy_vec[i]);
string2scalar(exp_z, NUM_ECC_WORDS, z_vec[i]);
string2scalar(prv, NUM_ECC_WORDS, d_vec[i]);
uint8_t pub_bytes[2*NUM_ECC_BYTES];
uECC_vli_nativeToBytes(pub_bytes, 2*NUM_ECC_BYTES, pub);
uint8_t private_bytes[NUM_ECC_BYTES];
uECC_vli_nativeToBytes(private_bytes, NUM_ECC_BYTES, prv);
uint8_t z_bytes[NUM_ECC_BYTES];
uECC_vli_nativeToBytes(z_bytes, NUM_ECC_BYTES, exp_z);
rc = uECC_shared_secret(pub_bytes, private_bytes, z_bytes, curve);
if (rc == TC_CRYPTO_FAIL) {
TC_ERROR("ECDH failure, exit.\n");
result = TC_FAIL;
return result;;
}
uECC_vli_bytesToNative(z, z_bytes, NUM_ECC_BYTES);
result = check_ecc_result(i, "Z", exp_z, z, NUM_ECC_WORDS, verbose);
if (result == TC_FAIL) {
return result;
}
}
return result;
}
int cavp_ecdh(bool verbose)
{
unsigned int result = TC_PASS;
/*
* P-256
*/
char *d[] = {
"7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
"38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
"1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8",
"207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d",
"59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf",
"f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef",
"3b589af7db03459c23068b64f63f28d3c3c6bc25b5bf76ac05f35482888b5190",
"d8bf929a20ea7436b2461b541a11c80e61d826c0a4c9d322b31dd54e7f58b9c8",
"0f9883ba0ef32ee75ded0d8bda39a5146a29f1f2507b3bd458dbea0b2bb05b4d",
"2beedb04b05c6988f6a67500bb813faf2cae0d580c9253b6339e4a3337bb6c08",
"77c15dcf44610e41696bab758943eff1409333e4d5a11bbe72c8f6c395e9f848",
"42a83b985011d12303db1a800f2610f74aa71cdf19c67d54ce6c9ed951e9093e",
"ceed35507b5c93ead5989119b9ba342cfe38e6e638ba6eea343a55475de2800b",
"43e0e9d95af4dc36483cdd1968d2b7eeb8611fcce77f3a4e7d059ae43e509604",
"b2f3600df3368ef8a0bb85ab22f41fc0e5f4fdd54be8167a5c3cd4b08db04903",
"4002534307f8b62a9bf67ff641ddc60fef593b17c3341239e95bdb3e579bfdc8",
"4dfa12defc60319021b681b3ff84a10a511958c850939ed45635934ba4979147",
"1331f6d874a4ed3bc4a2c6e9c74331d3039796314beee3b7152fcdba5556304e",
"dd5e9f70ae740073ca0204df60763fb6036c45709bf4a7bb4e671412fad65da3",
"5ae026cfc060d55600717e55b8a12e116d1d0df34af831979057607c2d9c2f76",
"b601ac425d5dbf9e1735c5e2d5bdb79ca98b3d5be4a2cfd6f2273f150e064d9d",
"fefb1dda1845312b5fce6b81b2be205af2f3a274f5a212f66c0d9fc33d7ae535",
"334ae0c4693d23935a7e8e043ebbde21e168a7cba3fa507c9be41d7681e049ce",
"2c4bde40214fcc3bfc47d4cf434b629acbe9157f8fd0282540331de7942cf09d",
"85a268f9d7772f990c36b42b0a331adc92b5941de0b862d5d89a347cbf8faab0",
};
char *x[] = {
"700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287",
"809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7ae",
"a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3",
"df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed",
"41192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb922",
"33e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792",
"6a9e0c3f916e4e315c91147be571686d90464e8bf981d34a90b6353bca6eeba7",
"a9c0acade55c2a73ead1a86fb0a9713223c82475791cd0e210b046412ce224bb",
"94e94f16a98255fff2b9ac0c9598aac35487b3232d3231bd93b7db7df36f9eb9",
"e099bf2a4d557460b5544430bbf6da11004d127cb5d67f64ab07c94fcdf5274f",
"f75a5fe56bda34f3c1396296626ef012dc07e4825838778a645c8248cff01658",
"2db4540d50230756158abf61d9835712b6486c74312183ccefcaef2797b7674d",
"cd94fc9497e8990750309e9a8534fd114b0a6e54da89c4796101897041d14ecb",
"15b9e467af4d290c417402e040426fe4cf236bae72baa392ed89780dfccdb471",
"49c503ba6c4fa605182e186b5e81113f075bc11dcfd51c932fb21e951eee2fa1",
"19b38de39fdd2f70f7091631a4f75d1993740ba9429162c2a45312401636b29c",
"2c91c61f33adfe9311c942fdbff6ba47020feff416b7bb63cec13faf9b099954",
"a28a2edf58025668f724aaf83a50956b7ac1cfbbff79b08c3bf87dfd2828d767",
"a2ef857a081f9d6eb206a81c4cf78a802bdf598ae380c8886ecd85fdc1ed7644",
"ccd8a2d86bc92f2e01bce4d6922cf7fe1626aed044685e95e2eebd464505f01f",
"c188ffc8947f7301fb7b53e36746097c2134bf9cc981ba74b4e9c4361f595e4e",
"317e1020ff53fccef18bf47bb7f2dd7707fb7b7a7578e04f35b3beed222a0eb6",
"45fb02b2ceb9d7c79d9c2fa93e9c7967c2fa4df5789f9640b24264b1e524fcb1",
"a19ef7bff98ada781842fbfc51a47aff39b5935a1c7d9625c8d323d511c92de6",
"356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b",
};
char *y[] = {
"db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
"b29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
"ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536",
"422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
"1af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328",
"f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f",
"40f9bead39c2f2bcc2602f75b8a73ec7bdffcbcead159d0174c6c4d3c5357f05",
"f6de0afa20e93e078467c053d241903edad734c6b403ba758c2b5ff04c9d4229",
"d8049a43579cfa90b8093a94416cbefbf93386f15b3f6e190b6e3455fedfe69a",
"d9c50dbe70d714edb5e221f4e020610eeb6270517e688ca64fb0e98c7ef8c1c5",
"33bbdf1b1772d8059df568b061f3f1122f28a8d819167c97be448e3dc3fb0c3c",
"62f57f314e3f3495dc4e099012f5e0ba71770f9660a1eada54104cdfde77243e",
"c3def4b5fe04faee0a11932229fff563637bfdee0e79c6deeaf449f85401c5c4",
"cdf4e9170fb904302b8fd93a820ba8cc7ed4efd3a6f2d6b05b80b2ff2aee4e77",
"8af706ff0922d87b3f0c5e4e31d8b259aeb260a9269643ed520a13bb25da5924",
"09aed7232b28e060941741b6828bcdfa2bc49cc844f3773611504f82a390a5ae",
"6cab31b06419e5221fca014fb84ec870622a1b12bab5ae43682aa7ea73ea08d0",
"dfa7bfffd4c766b86abeaf5c99b6e50cb9ccc9d9d00b7ffc7804b0491b67bc03",
"563c4c20419f07bc17d0539fade1855e34839515b892c0f5d26561f97fa04d1a",
"e9ddd583a9635a667777d5b8a8f31b0f79eba12c75023410b54b8567dddc0f38",
"bf7d2f2056e72421ef393f0c0f2b0e00130e3cac4abbcc00286168e85ec55051",
"09420ce5a19d77c6fe1ee587e6a49fbaf8f280e8df033d75403302e5a27db2ae",
"5c6e8ecf1f7d3023893b7b1ca1e4d178972ee2a230757ddc564ffe37f5c5a321",
"e9c184df75c955e02e02e400ffe45f78f339e1afe6d056fb3245f4700ce606ef",
"57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92",
};
char *Z[] = {
"46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
"057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
"2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec",
"96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
"19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62",
"664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3",
"ca342daa50dc09d61be7c196c85e60a80c5cb04931746820be548cdde055679d",
"35aa9b52536a461bfde4e85fc756be928c7de97923f0416c7a3ac8f88b3d4489",
"605c16178a9bc875dcbff54d63fe00df699c03e8a888e9e94dfbab90b25f39b4",
"f96e40a1b72840854bb62bc13c40cc2795e373d4e715980b261476835a092e0b",
"8388fa79c4babdca02a8e8a34f9e43554976e420a4ad273c81b26e4228e9d3a3",
"72877cea33ccc4715038d4bcbdfe0e43f42a9e2c0c3b017fc2370f4b9acbda4a",
"e4e7408d85ff0e0e9c838003f28cdbd5247cdce31f32f62494b70e5f1bc36307",
"ed56bcf695b734142c24ecb1fc1bb64d08f175eb243a31f37b3d9bb4407f3b96",
"bc5c7055089fc9d6c89f83c1ea1ada879d9934b2ea28fcf4e4a7e984b28ad2cf",
"9a4e8e657f6b0e097f47954a63c75d74fcba71a30d83651e3e5a91aa7ccd8343",
"3ca1fc7ad858fb1a6aba232542f3e2a749ffc7203a2374a3f3d3267f1fc97b78",
"1aaabe7ee6e4a6fa732291202433a237df1b49bc53866bfbe00db96a0f58224f",
"430e6a4fba4449d700d2733e557f66a3bf3d50517c1271b1ddae1161b7ac798c",
"1ce9e6740529499f98d1f1d71329147a33df1d05e4765b539b11cf615d6974d3",
"4690e3743c07d643f1bc183636ab2a9cb936a60a802113c49bb1b3f2d0661660",
"30c2261bd0004e61feda2c16aa5e21ffa8d7e7f7dbf6ec379a43b48e4b36aeb0",
"2adae4a138a239dcd93c243a3803c3e4cf96e37fe14e6a9b717be9599959b11c",
"2e277ec30f5ea07d6ce513149b9479b96e07f4b6913b1b5c11305c1444a1bc0b",
"1e51373bd2c6044c129c436e742a55be2a668a85ae08441b6756445df5493857",
};
TC_PRINT("Test #1: ECDH");
TC_PRINT("NIST-p256\n");
result = ecdh_vectors(x, y, d, Z, 25, verbose);
if(result == TC_FAIL) {
goto exitTest1;
}
exitTest1:
TC_END_RESULT(result);
return result;
}
int cavp_keygen(bool verbose)
{
unsigned int result = TC_PASS;
/*
* [P-256, B.4.2 Key Pair Generation by Testing Candidates]
*/
char *d[] = {
"c9806898a0334916c860748880a541f093b579a9b1f32934d86c363c39800357",
"710735c8388f48c684a97bd66751cc5f5a122d6b9a96a2dbe73662f78217446d",
"78d5d8b7b3e2c16b3e37e7e63becd8ceff61e2ce618757f514620ada8a11f6e4",
"2a61a0703860585fe17420c244e1de5a6ac8c25146b208ef88ad51ae34c8cb8c",
"01b965b45ff386f28c121c077f1d7b2710acc6b0cb58d8662d549391dcf5a883",
"fac92c13d374c53a085376fe4101618e1e181b5a63816a84a0648f3bdc24e519",
"f257a192dde44227b3568008ff73bcf599a5c45b32ab523b5b21ca582fef5a0a",
"add67e57c42a3d28708f0235eb86885a4ea68e0d8cfd76eb46134c596522abfd",
"4494860fd2c805c5c0d277e58f802cff6d731f76314eb1554142a637a9bc5538",
"d40b07b1ea7b86d4709ef9dc634c61229feb71abd63dc7fc85ef46711a87b210",
};
char *x[] = {
"d0720dc691aa80096ba32fed1cb97c2b620690d06de0317b8618d5ce65eb728f",
"f6836a8add91cb182d8d258dda6680690eb724a66dc3bb60d2322565c39e4ab9",
"76711126cbb2af4f6a5fe5665dad4c88d27b6cb018879e03e54f779f203a854e",
"e1aa7196ceeac088aaddeeba037abb18f67e1b55c0a5c4e71ec70ad666fcddc8",
"1f038c5422e88eec9e88b815e8f6b3e50852333fc423134348fc7d79ef8e8a10",
"7258f2ab96fc84ef6ccb33e308cd392d8b568ea635730ceb4ebd72fa870583b9",
"d2e01411817b5512b79bbbe14d606040a4c90deb09e827d25b9f2fc068997872",
"55bed2d9c029b7f230bde934c7124ed52b1330856f13cbac65a746f9175f85d7",
"5190277a0c14d8a3d289292f8a544ce6ea9183200e51aec08440e0c1a463a4e4",
"fbcea7c2827e0e8085d7707b23a3728823ea6f4878b24747fb4fd2842d406c73",
};
char *y[] = {
"9681b517b1cda17d0d83d335d9c4a8a9a9b0b1b3c7106d8f3c72bc5093dc275f",
"1f837aa32864870cb8e8d0ac2ff31f824e7beddc4bb7ad72c173ad974b289dc2",
"a26df39960ab5248fd3620fd018398e788bd89a3cea509b352452b69811e6856",
"d7d35bdce6dedc5de98a7ecb27a9cd066a08f586a733b59f5a2cdb54f971d5c8",
"43a047cb20e94b4ffb361ef68952b004c0700b2962e0c0635a70269bc789b849",
"489807ca55bdc29ca5c8fe69b94f227b0345cccdbe89975e75d385cc2f6bb1e2",
"503f138f8bab1df2c4507ff663a1fdf7f710e7adb8e7841eaa902703e314e793",
"32805e311d583b4e007c40668185e85323948e21912b6b0d2cda8557389ae7b0",
"ecd98514821bd5aaf3419ab79b71780569470e4fed3da3c1353b28fe137f36eb",
"2393c85f1f710c5afc115a39ba7e18abe03f19c9d4bb3d47d19468b818efa535",
};
TC_PRINT("Test #2: ECC KeyGen ");
TC_PRINT("NIST-p256\n");
result = keygen_vectors(d, x, y, 10, verbose);
if(result == TC_FAIL) {
goto exitTest1;
}
exitTest1:
TC_END_RESULT(result);
return result;
}
/* Test ecc_make_keys, and also as keygen part of other tests */
int pkv_vectors(char **qx_vec, char **qy_vec, char **res_vec, int tests,
bool verbose)
{
unsigned int pub[2 * NUM_ECC_WORDS];
uint8_t _public[2 * NUM_ECC_BYTES];
int rc;
int exp_rc;
char tmp;
unsigned int result = TC_PASS;
const struct uECC_Curve_t * curve = uECC_secp256r1();
for (int i = 0; i < tests; i++) {
if (2 != sscanf(res_vec[i], "%c (%d ", &tmp, &exp_rc)) {
TC_ERROR("Error: failed to parse CAVP response.\n");
result = TC_FAIL;
goto exitTest1;
}
if (strlen(qx_vec[i]) > 2 * NUM_ECC_BYTES ||
strlen(qy_vec[i]) > 2 * NUM_ECC_BYTES) {
/* invalid input to ECC digit conversion (string2native()) */
rc = -2;
} else {
string2scalar(pub, NUM_ECC_WORDS, qx_vec[i]);
string2scalar(pub + NUM_ECC_WORDS, NUM_ECC_WORDS, qy_vec[i]);
uECC_vli_nativeToBytes(_public, NUM_ECC_BYTES, pub);
uECC_vli_nativeToBytes(_public + NUM_ECC_BYTES, NUM_ECC_BYTES, pub+NUM_ECC_WORDS);
rc = uECC_valid_public_key(_public, curve);
}
/*
* map to CAVP error codes
* 0 => 0 - success
* -1 => ? - (x,y) = (0,0) (not covered)
* -2 => 1 - out of bounds (pubverify or ecc import)
* -3 => 2 - not on curve
* -4 => ? - public key is the group generator
*/
if (rc == -3) rc = 2;
if (rc == -2) rc = 1;
result = check_code(i, res_vec[i], exp_rc, rc, verbose);
if(result == TC_FAIL) {
goto exitTest1;
}
}
exitTest1:
TC_END_RESULT(result);
return result;
}
int cavp_pkv(bool verbose)
{
/*
* [P-256]
*/
char *x[] = {
"e0f7449c5588f24492c338f2bc8f7865f755b958d48edb0f2d0056e50c3fd5b7",
"d17c446237d9df87266ba3a91ff27f45abfdcb77bfd83536e92903efb861a9a9",
"17875397ae87369365656d490e8ce956911bd97607f2aff41b56f6f3a61989826",
"f2d1c0dc0852c3d8a2a2500a23a44813ccce1ac4e58444175b440469ffc12273",
"10b0ca230fff7c04768f4b3d5c75fa9f6c539bea644dffbec5dc796a213061b58",
"2c1052f25360a15062d204a056274e93cbe8fc4c4e9b9561134ad5c15ce525da",
"a40d077a87dae157d93dcccf3fe3aca9c6479a75aa2669509d2ef05c7de6782f",
"2633d398a3807b1895548adbb0ea2495ef4b930f91054891030817df87d4ac0a",
"14bf57f76c260b51ec6bbc72dbd49f02a56eaed070b774dc4bad75a54653c3d56",
"2fa74931ae816b426f484180e517f5050c92decfc8daf756cd91f54d51b302f1",
"f8c6dd3181a76aa0e36c2790bba47041acbe7b1e473ff71eee39a824dc595ff0",
"7a81a7e0b015252928d8b36e4ca37e92fdc328eb25c774b4f872693028c4be38",
};
char *y[] = {
"86d7e9255d0f4b6f44fa2cd6f8ba3c0aa828321d6d8cc430ca6284ce1d5b43a0",
"1eabb6a349ce2cd447d777b6739c5fc066add2002d2029052c408d0701066231c",
"980a3c4f61b9692633fbba5ef04c9cb546dd05cdec9fa8428b8849670e2fba92",
"32bfe992831b305d8c37b9672df5d29fcb5c29b4a40534683e3ace23d24647dd",
"f5edf37c11052b75f771b7f9fa050e353e464221fec916684ed45b6fead38205",
"ced9783713a8a2a09eff366987639c625753295d9a85d0f5325e32dedbcada0b",
"503d86b87d743ba20804fd7e7884aa017414a7b5b5963e0d46e3a9611419ddf3",
"d6b2f738e3873cc8364a2d364038ce7d0798bb092e3dd77cbdae7c263ba618d2",
"7a231a23bf8b3aa31d9600d888a0678677a30e573decd3dc56b33f365cc11236",
"5b994346137988c58c14ae2152ac2f6ad96d97decb33099bd8a0210114cd1141",
"9c965f227f281b3072b95b8daf29e88b35284f3574462e268e529bbdc50e9e52",
"08862f7335147261e7b1c3d055f9a316e4cab7daf99cc09d1c647f5dd6e7d5bb",
};
char *Result[] = {
"P (0 )", "F (1 - Q_x or Q_y out of range)",
"F (1 - Q_x or Q_y out of range)", "F (2 - Point not on curve)",
"F (1 - Q_x or Q_y out of range)", "P (0 )",
"F (2 - Point not on curve)", "P (0 )",
"F (1 - Q_x or Q_y out of range)", "P (0 )",
"F (2 - Point not on curve)", "F (2 - Point not on curve)",
};
TC_PRINT("Test #3: PubKeyVerify ");
TC_PRINT("NIST-p256-SHA2-256\n");
return pkv_vectors(x, y, Result, 12, verbose);
}
int montecarlo_ecdh(int num_tests, bool verbose)
{
int i;
uint8_t private1[NUM_ECC_BYTES] = {0};
uint8_t private2[NUM_ECC_BYTES] = {0};
uint8_t public1[2*NUM_ECC_BYTES] = {0};
uint8_t public2[2*NUM_ECC_BYTES] = {0};
uint8_t secret1[NUM_ECC_BYTES] = {0};
uint8_t secret2[NUM_ECC_BYTES] = {0};
unsigned int result = TC_PASS;
const struct uECC_Curve_t * curve = uECC_secp256r1();
TC_PRINT("Test #4: Monte Carlo (%d Randomized EC-DH key-exchange) ", num_tests);
TC_PRINT("NIST-p256\n ");
for (i = 0; i < num_tests; ++i) {
if (verbose) {
TC_PRINT(".");
fflush(stdout);
}
if (!uECC_make_key(public1, private1, curve) ||
!uECC_make_key(public2, private2, curve)) {
TC_ERROR("uECC_make_key() failed\n");
result = TC_FAIL;
goto exitTest1;
}
if (!uECC_shared_secret(public2, private1, secret1, curve)) {
TC_ERROR("shared_secret() failed (1)\n");
result = TC_FAIL;
goto exitTest1;;
}
if (!uECC_shared_secret(public1, private2, secret2, curve)) {
TC_ERROR("shared_secret() failed (2)\n");
result = TC_FAIL;
goto exitTest1;
}
if (memcmp(secret1, secret2, sizeof(secret1)) != 0) {
TC_PRINT("Shared secrets are not identical!\n");
TC_PRINT("Private key 1 = ");
vli_print_bytes(private1, 32);
TC_PRINT("\nPrivate key 2 = ");
vli_print_bytes(private2, 32);
TC_PRINT("\nPublic key 1 = ");
vli_print_bytes(public1, 64);
TC_PRINT("\nPublic key 2 = ");
vli_print_bytes(public2, 64);
TC_PRINT("\nShared secret 1 = ");
vli_print_bytes(secret1, 32);
TC_PRINT("\nShared secret 2 = ");
vli_print_bytes(secret2, 32);
TC_PRINT("\n");
}
}
TC_PRINT("\n");
exitTest1:
TC_END_RESULT(result);
return result;
}
int main()
{
unsigned int result = TC_PASS;
TC_START("Performing ECC-DH tests:");
/* Setup of the Cryptographically Secure PRNG. */
uECC_set_rng(&default_CSPRNG);
bool verbose = true;
TC_PRINT("Performing cavp_ecdh test:\n");
result = cavp_ecdh(verbose);
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("cavp_ecdh test failed.\n");
goto exitTest;
}
TC_PRINT("Performing cavp_keygen test:\n");
result = cavp_keygen(verbose);
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("cavp_keygen test failed.\n");
goto exitTest;
}
TC_PRINT("Performing cavp_pkv test:\n");
result = cavp_pkv(verbose);
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("cavp_pkv failed.\n");
goto exitTest;
}
TC_PRINT("Performing montecarlo_ecdh test:\n");
result = montecarlo_ecdh(10, verbose);
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("montecarlo_ecdh test failed.\n");
goto exitTest;
}
TC_PRINT("All EC-DH tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
}

View File

@@ -0,0 +1,669 @@
/* test_ecc_ecdsa.c - TinyCrypt implementation of some EC-DSA tests */
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* test_ecc_ecdsa.c -- Implementation of some EC-DSA tests
*
*/
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_platform_specific.h>
#include <tinycrypt/ecc_dsa.h>
#include <tinycrypt/ecc_dh.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/sha256.h>
#include <test_utils.h>
#include <test_ecc_utils.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
/* Maximum size of message to be signed. */
#define BUF_SIZE 256
int sign_vectors(TCSha256State_t hash, char **d_vec, char **k_vec,
char **msg_vec, char **qx_vec, char **qy_vec, char **r_vec,
char **s_vec, int tests, bool verbose)
{
unsigned int k[NUM_ECC_WORDS];
unsigned int private[NUM_ECC_WORDS];
uint8_t private_bytes[NUM_ECC_BYTES];
unsigned int sig[2 * NUM_ECC_WORDS];
uint8_t sig_bytes[2 * NUM_ECC_BYTES];
unsigned int digest[TC_SHA256_DIGEST_SIZE / 4];
uint8_t digest_bytes[TC_SHA256_DIGEST_SIZE];
unsigned int result = TC_PASS;
/* expected outputs (converted input vectors) */
unsigned int exp_r[NUM_ECC_WORDS];
unsigned int exp_s[NUM_ECC_WORDS];
uint8_t msg[BUF_SIZE];
size_t msglen;
for (int i = 0; i < tests; i++) {
/* use keygen test to generate and validate pubkey */
keygen_vectors(d_vec+i, qx_vec+i, qy_vec+i, 1, false);
string2scalar(private, NUM_ECC_WORDS, d_vec[i]);
uECC_vli_nativeToBytes(private_bytes, NUM_ECC_BYTES, private);
/* validate ECDSA: hash message, sign digest, check r+s */
memset(k, 0, NUM_ECC_BYTES);
string2scalar(k, NUM_ECC_WORDS, k_vec[i]);
string2scalar(exp_r, NUM_ECC_WORDS, r_vec[i]);
string2scalar(exp_s, NUM_ECC_WORDS, s_vec[i]);
msglen = hex2bin(msg, BUF_SIZE, msg_vec[i], strlen(msg_vec[i]));
if (msglen == false) {
TC_ERROR("failed to import message!\n");
result = TC_FAIL;
goto exitTest1;
}
tc_sha256_init(hash);
tc_sha256_update(hash, msg, msglen);
tc_sha256_final(digest_bytes, hash);
/* if digest larger than ECC scalar, drop the end
* if digest smaller than ECC scalar, zero-pad front */
int hash_dwords = TC_SHA256_DIGEST_SIZE / 4;
if (NUM_ECC_WORDS < hash_dwords) {
hash_dwords = NUM_ECC_WORDS;
}
memset(digest, 0, NUM_ECC_BYTES - 4 * hash_dwords);
uECC_vli_bytesToNative(digest + (NUM_ECC_WORDS-hash_dwords),
digest_bytes, TC_SHA256_DIGEST_SIZE);
if (uECC_sign_with_k(private_bytes, digest_bytes,
sizeof(digest_bytes), k, sig_bytes, uECC_secp256r1()) == 0) {
TC_ERROR("ECDSA_sign failed!\n");
result = TC_FAIL;
goto exitTest1;
}
uECC_vli_bytesToNative(sig, sig_bytes, NUM_ECC_BYTES);
uECC_vli_bytesToNative(sig + NUM_ECC_WORDS, sig_bytes+NUM_ECC_BYTES, NUM_ECC_BYTES);
result = check_ecc_result(i, "sig.r", exp_r, sig, NUM_ECC_WORDS, verbose);
if(result == TC_FAIL) {
goto exitTest1;
}
result = check_ecc_result(i, "sig.s", exp_s, sig + NUM_ECC_WORDS, NUM_ECC_WORDS, verbose);
if(result == TC_FAIL) {
goto exitTest1;
}
}
exitTest1:
TC_END_RESULT(result);
return result;
}
int cavp_sign(bool verbose)
{
/*
* [P-256,SHA-256]
*/
char *d[] = {
"519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464",
"0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813",
"e283871239837e13b95f789e6e1af63bf61c918c992e62bca040d64cad1fc2ef",
"a3d2d3b7596f6592ce98b4bfe10d41837f10027a90d7bb75349490018cf72d07",
"53a0e8a8fe93db01e7ae94e1a9882a102ebd079b3a535827d583626c272d280d",
"4af107e8e2194c830ffb712a65511bc9186a133007855b49ab4b3833aefc4a1d",
"78dfaa09f1076850b3e206e477494cddcfb822aaa0128475053592c48ebaf4ab",
"80e692e3eb9fcd8c7d44e7de9f7a5952686407f90025a1d87e52c7096a62618a",
"5e666c0db0214c3b627a8e48541cc84a8b6fd15f300da4dff5d18aec6c55b881",
"f73f455271c877c4d5334627e37c278f68d143014b0a05aa62f308b2101c5308",
"b20d705d9bd7c2b8dc60393a5357f632990e599a0975573ac67fd89b49187906",
"d4234bebfbc821050341a37e1240efe5e33763cbbb2ef76a1c79e24724e5a5e7",
"b58f5211dff440626bb56d0ad483193d606cf21f36d9830543327292f4d25d8c",
"54c066711cdb061eda07e5275f7e95a9962c6764b84f6f1f3ab5a588e0a2afb1",
"34fa4682bf6cb5b16783adcd18f0e6879b92185f76d7c920409f904f522db4b1",
};
char *k[] = {
"94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de",
"6d3e71882c3b83b156bb14e0ab184aa9fb728068d3ae9fac421187ae0b2f34c6",
"ad5e887eb2b380b8d8280ad6e5ff8a60f4d26243e0124c2f31a297b5d0835de2",
"24fc90e1da13f17ef9fe84cc96b9471ed1aaac17e3a4bae33a115df4e5834f18",
"5d833e8d24cc7a402d7ee7ec852a3587cddeb48358cea71b0bedb8fabe84e0c4",
"e18f96f84dfa2fd3cdfaec9159d4c338cd54ad314134f0b31e20591fc238d0ab",
"295544dbb2da3da170741c9b2c6551d40af7ed4e891445f11a02b66a5c258a77",
"7c80fd66d62cc076cef2d030c17c0a69c99611549cb32c4ff662475adbe84b22",
"2e7625a48874d86c9e467f890aaa7cd6ebdf71c0102bfdcfa24565d6af3fdce9",
"62f8665fd6e26b3fa069e85281777a9b1f0dfd2c0b9f54a086d0c109ff9fd615",
"72b656f6b35b9ccbc712c9f1f3b1a14cbbebaec41c4bca8da18f492a062d6f6f",
"d926fe10f1bfd9855610f4f5a3d666b1a149344057e35537373372ead8b1a778",
"e158bf4a2d19a99149d9cdb879294ccb7aaeae03d75ddd616ef8ae51a6dc1071",
"646fe933e96c3b8f9f507498e907fdd201f08478d0202c752a7c2cfebf4d061a",
"a6f463ee72c9492bc792fe98163112837aebd07bab7a84aaed05be64db3086f4",
};
char *Msg[] = {
"5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf416983fe16"
"5b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5473e253605fb1ddfd280"
"65b53cb5858a8ad28175bf9bd386a5e471ea7a65c17cc934a9d791e91491eb3754d0379979"
"0fe2d308d16146d5c9b0d0debd97d79ce8",
"c35e2f092553c55772926bdbe87c9796827d17024dbb9233a545366e2e5987dd344deb72df"
"987144b8c6c43bc41b654b94cc856e16b96d7a821c8ec039b503e3d86728c494a967d83011"
"a0e090b5d54cd47f4e366c0912bc808fbb2ea96efac88fb3ebec9342738e225f7c7c2b011c"
"e375b56621a20642b4d36e060db4524af1",
"3c054e333a94259c36af09ab5b4ff9beb3492f8d5b4282d16801daccb29f70fe61a0b37ffe"
"f5c04cd1b70e85b1f549a1c4dc672985e50f43ea037efa9964f096b5f62f7ffdf8d6bfb2cc"
"859558f5a393cb949dbd48f269343b5263dcdb9c556eca074f2e98e6d94c2c29a677afaf80"
"6edf79b15a3fcd46e7067b7669f83188ee",
"0989122410d522af64ceb07da2c865219046b4c3d9d99b01278c07ff63eaf1039cb787ae9e"
"2dd46436cc0415f280c562bebb83a23e639e476a02ec8cff7ea06cd12c86dcc3adefbf1a9e"
"9a9b6646c7599ec631b0da9a60debeb9b3e19324977f3b4f36892c8a38671c8e1cc8e50fcd"
"50f9e51deaf98272f9266fc702e4e57c30",
"dc66e39f9bbfd9865318531ffe9207f934fa615a5b285708a5e9c46b7775150e818d7f24d2"
"a123df3672fff2094e3fd3df6fbe259e3989dd5edfcccbe7d45e26a775a5c4329a084f057c"
"42c13f3248e3fd6f0c76678f890f513c32292dd306eaa84a59abe34b16cb5e38d0e885525d"
"10336ca443e1682aa04a7af832b0eee4e7",
"600974e7d8c5508e2c1aab0783ad0d7c4494ab2b4da265c2fe496421c4df238b0be25f2565"
"9157c8a225fb03953607f7df996acfd402f147e37aee2f1693e3bf1c35eab3ae360a2bd91d"
"04622ea47f83d863d2dfecb618e8b8bdc39e17d15d672eee03bb4ce2cc5cf6b217e5faf3f3"
"36fdd87d972d3a8b8a593ba85955cc9d71",
"dfa6cb9b39adda6c74cc8b2a8b53a12c499ab9dee01b4123642b4f11af336a91a5c9ce0520"
"eb2395a6190ecbf6169c4cba81941de8e76c9c908eb843b98ce95e0da29c5d4388040264e0"
"5e07030a577cc5d176387154eabae2af52a83e85c61c7c61da930c9b19e45d7e34c8516dc3"
"c238fddd6e450a77455d534c48a152010b",
"51d2547cbff92431174aa7fc7302139519d98071c755ff1c92e4694b58587ea560f72f32fc"
"6dd4dee7d22bb7387381d0256e2862d0644cdf2c277c5d740fa089830eb52bf79d1e75b859"
"6ecf0ea58a0b9df61e0c9754bfcd62efab6ea1bd216bf181c5593da79f10135a9bc6e164f1"
"854bc8859734341aad237ba29a81a3fc8b",
"558c2ac13026402bad4a0a83ebc9468e50f7ffab06d6f981e5db1d082098065bcff6f21a7a"
"74558b1e8612914b8b5a0aa28ed5b574c36ac4ea5868432a62bb8ef0695d27c1e3ceaf75c7"
"b251c65ddb268696f07c16d2767973d85beb443f211e6445e7fe5d46f0dce70d58a4cd9fe7"
"0688c035688ea8c6baec65a5fc7e2c93e8",
"4d55c99ef6bd54621662c3d110c3cb627c03d6311393b264ab97b90a4b15214a5593ba2510"
"a53d63fb34be251facb697c973e11b665cb7920f1684b0031b4dd370cb927ca7168b0bf8ad"
"285e05e9e31e34bc24024739fdc10b78586f29eff94412034e3b606ed850ec2c1900e8e681"
"51fc4aee5adebb066eb6da4eaa5681378e",
"f8248ad47d97c18c984f1f5c10950dc1404713c56b6ea397e01e6dd925e903b4fadfe2c9e8"
"77169e71ce3c7fe5ce70ee4255d9cdc26f6943bf48687874de64f6cf30a012512e787b8805"
"9bbf561162bdcc23a3742c835ac144cc14167b1bd6727e940540a9c99f3cbb41fb1dcb00d7"
"6dda04995847c657f4c19d303eb09eb48a",
"3b6ee2425940b3d240d35b97b6dcd61ed3423d8e71a0ada35d47b322d17b35ea0472f35edd"
"1d252f87b8b65ef4b716669fc9ac28b00d34a9d66ad118c9d94e7f46d0b4f6c2b2d339fd6b"
"cd351241a387cc82609057048c12c4ec3d85c661975c45b300cb96930d89370a327c98b67d"
"efaa89497aa8ef994c77f1130f752f94a4",
"c5204b81ec0a4df5b7e9fda3dc245f98082ae7f4efe81998dcaa286bd4507ca840a53d21b0"
"1e904f55e38f78c3757d5a5a4a44b1d5d4e480be3afb5b394a5d2840af42b1b4083d40afbf"
"e22d702f370d32dbfd392e128ea4724d66a3701da41ae2f03bb4d91bb946c7969404cb544f"
"71eb7a49eb4c4ec55799bda1eb545143a7",
"72e81fe221fb402148d8b7ab03549f1180bcc03d41ca59d7653801f0ba853add1f6d29edd7"
"f9abc621b2d548f8dbf8979bd16608d2d8fc3260b4ebc0dd42482481d548c7075711b57596"
"49c41f439fad69954956c9326841ea6492956829f9e0dc789f73633b40f6ac77bcae6dfc79"
"30cfe89e526d1684365c5b0be2437fdb01",
"21188c3edd5de088dacc1076b9e1bcecd79de1003c2414c3866173054dc82dde85169baa77"
"993adb20c269f60a5226111828578bcc7c29e6e8d2dae81806152c8ba0c6ada1986a1983eb"
"eec1473a73a04795b6319d48662d40881c1723a706f516fe75300f92408aa1dc6ae4288d20"
"46f23c1aa2e54b7fb6448a0da922bd7f34",
};
char *Qx[] = {
"1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83",
"e266ddfdc12668db30d4ca3e8f7749432c416044f2d2b8c10bf3d4012aeffa8a",
"74ccd8a62fba0e667c50929a53f78c21b8ff0c3c737b0b40b1750b2302b0bde8",
"322f80371bf6e044bc49391d97c1714ab87f990b949bc178cb7c43b7c22d89e1",
"1bcec4570e1ec2436596b8ded58f60c3b1ebc6a403bc5543040ba82963057244",
"a32e50be3dae2c8ba3f5e4bdae14cf7645420d425ead94036c22dd6c4fc59e00",
"8bcfe2a721ca6d753968f564ec4315be4857e28bef1908f61a366b1f03c97479",
"a88bc8430279c8c0400a77d751f26c0abc93e5de4ad9a4166357952fe041e767",
"1bc487570f040dc94196c9befe8ab2b6de77208b1f38bdaae28f9645c4d2bc3a",
"b8188bd68701fc396dab53125d4d28ea33a91daf6d21485f4770f6ea8c565dde",
"51f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce",
"8fb287f0202ad57ae841aea35f29b2e1d53e196d0ddd9aec24813d64c0922fb7",
"68229b48c2fe19d3db034e4c15077eb7471a66031f28a980821873915298ba76",
"0a7dbb8bf50cb605eb2268b081f26d6b08e012f952c4b70a5a1e6e7d46af98bb",
"105d22d9c626520faca13e7ced382dcbe93498315f00cc0ac39c4821d0d73737",
};
char *Qy[] = {
"ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9",
"bfa86404a2e9ffe67d47c587ef7a97a7f456b863b4d02cfc6928973ab5b1cb39",
"29074e21f3a0ef88b9efdf10d06aa4c295cc1671f758ca0e4cd108803d0f2614",
"3c15d54a5cc6b9f09de8457e873eb3deb1fceb54b0b295da6050294fae7fd999",
"8af62a4c683f096b28558320737bf83b9959a46ad2521004ef74cf85e67494e1",
"d623bf641160c289d6742c6257ae6ba574446dd1d0e74db3aaa80900b78d4ae9",
"0f67576a30b8e20d4232d8530b52fb4c89cbc589ede291e499ddd15fe870ab96",
"2d365a1eef25ead579cc9a069b6abc1b16b81c35f18785ce26a10ba6d1381185",
"ec81602abd8345e71867c8210313737865b8aa186851e1b48eaca140320f5d8f",
"423f058810f277f8fe076f6db56e9285a1bf2c2a1dae145095edd9c04970bc4a",
"4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1",
"1f6daff1aa2dd2d6d3741623eecb5e7b612997a1039aab2e5cf2de969cfea573",
"303e8ee3742a893f78b810991da697083dd8f11128c47651c27a56740a80c24c",
"f26dd7d799930062480849962ccf5004edcfd307c044f4e8f667c9baa834eeae",
"6c47f3cbbfa97dfcebe16270b8c7d5d3a5900b888c42520d751e8faf3b401ef4",
};
char *R[] = {
"f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac",
"976d3a4e9d23326dc0baa9fa560b7c4e53f42864f508483a6473b6a11079b2db",
"35fb60f5ca0f3ca08542fb3cc641c8263a2cab7a90ee6a5e1583fac2bb6f6bd1",
"d7c562370af617b581c84a2468cc8bd50bb1cbf322de41b7887ce07c0e5884ca",
"18caaf7b663507a8bcd992b836dec9dc5703c080af5e51dfa3a9a7c387182604",
"8524c5024e2d9a73bde8c72d9129f57873bbad0ed05215a372a84fdbc78f2e68",
"c5a186d72df452015480f7f338970bfe825087f05c0088d95305f87aacc9b254",
"9d0c6afb6df3bced455b459cc21387e14929392664bb8741a3693a1795ca6902",
"2f9e2b4e9f747c657f705bffd124ee178bbc5391c86d056717b140c153570fd9",
"1cc628533d0004b2b20e7f4baad0b8bb5e0673db159bbccf92491aef61fc9620",
"9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c42",
"490efd106be11fc365c7467eb89b8d39e15d65175356775deab211163c2504cb",
"e67a9717ccf96841489d6541f4f6adb12d17b59a6bef847b6183b8fcf16a32eb",
"b53ce4da1aa7c0dc77a1896ab716b921499aed78df725b1504aba1597ba0c64b",
"542c40a18140a6266d6f0286e24e9a7bad7650e72ef0e2131e629c076d962663",
};
char *S[] = {
"8bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903",
"1b766e9ceb71ba6c01dcd46e0af462cd4cfa652ae5017d4555b8eeefe36e1932",
"ee59d81bc9db1055cc0ed97b159d8784af04e98511d0a9a407b99bb292572e96",
"b46d9f2d8c4bf83546ff178f1d78937c008d64e8ecc5cbb825cb21d94d670d89",
"77c68928ac3b88d985fb43fb615fb7ff45c18ba5c81af796c613dfa98352d29c",
"d18c2caf3b1072f87064ec5e8953f51301cada03469c640244760328eb5a05cb",
"84a58f9e9d9e735344b316b1aa1ab5185665b85147dc82d92e969d7bee31ca30",
"d7f9ddd191f1f412869429209ee3814c75c72fa46a9cccf804a2f5cc0b7e739f",
"f5413bfd85949da8d83de83ab0d19b2986613e224d1901d76919de23ccd03199",
"880e0bbf82a8cf818ed46ba03cf0fc6c898e36fca36cc7fdb1d2db7503634430",
"2bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c",
"644300fc0da4d40fb8c6ead510d14f0bd4e1321a469e9c0a581464c7186b7aa7",
"9ae6ba6d637706849a6a9fc388cf0232d85c26ea0d1fe7437adb48de58364333",
"d7c246dc7ad0e67700c373edcfdd1c0a0495fc954549ad579df6ed1438840851",
"4f7f65305e24a6bbb5cff714ba8f5a2cee5bdc89ba8d75dcbf21966ce38eb66f",
};
struct tc_sha256_state_struct sha256_ctx;
TC_PRINT("Test #1: ECDSAsign ");
TC_PRINT("NIST-p256, SHA2-256\n");
return sign_vectors(&sha256_ctx, d, k, Msg, Qx, Qy, R, S, 15, verbose);
}
int vrfy_vectors(TCSha256State_t hash, char **msg_vec, char **qx_vec, char **qy_vec,
char **r_vec, char **s_vec, char **res_vec, int tests, bool verbose)
{
const struct uECC_Curve_t * curve = uECC_secp256r1();
unsigned int pub[2 * NUM_ECC_WORDS];
uint8_t pub_bytes[2 * NUM_ECC_BYTES];
unsigned int sig[2 * NUM_ECC_WORDS];
uint8_t sig_bytes[2 * NUM_ECC_BYTES];
uint8_t digest_bytes[TC_SHA256_DIGEST_SIZE];
unsigned int digest[TC_SHA256_DIGEST_SIZE / 4];
unsigned int result = TC_PASS;
int rc;
int exp_rc;
char tmp;
uint8_t msg[BUF_SIZE];
size_t msglen;
for (int i = 0; i < tests; i++) {
string2scalar(pub, NUM_ECC_WORDS, qx_vec[i]);
string2scalar(pub + NUM_ECC_WORDS, NUM_ECC_WORDS, qy_vec[i]);
string2scalar(sig, NUM_ECC_WORDS, r_vec[i]);
string2scalar(sig + NUM_ECC_WORDS, NUM_ECC_WORDS, s_vec[i]);
if (2 != sscanf(res_vec[i], "%c (%d ", &tmp, &exp_rc)) {
TC_ERROR("Error: failed to parse CAVP response.\n");
result = TC_FAIL;
goto exitTest1;
}
/* validate ECDSA: hash message, verify r+s */
msglen = hex2bin(msg, BUF_SIZE, msg_vec[i], strlen(msg_vec[i]));
if (msglen == false) {
TC_ERROR("failed to import message!\n");
result = TC_FAIL;
goto exitTest1;
}
tc_sha256_init(hash);
tc_sha256_update(hash, msg, msglen);
tc_sha256_final(digest_bytes, hash);
/* if digest larger than ECC scalar, drop the end
* if digest smaller than ECC scalar, zero-pad front */
int hash_dwords = TC_SHA256_DIGEST_SIZE / 4;
if (NUM_ECC_WORDS < hash_dwords) {
hash_dwords = NUM_ECC_WORDS;
}
memset(digest, 0, NUM_ECC_BYTES - 4 * hash_dwords);
uECC_vli_bytesToNative(digest + (NUM_ECC_WORDS-hash_dwords), digest_bytes,
TC_SHA256_DIGEST_SIZE);
uECC_vli_nativeToBytes(pub_bytes, NUM_ECC_BYTES, pub);
uECC_vli_nativeToBytes(pub_bytes + NUM_ECC_BYTES, NUM_ECC_BYTES,
pub + NUM_ECC_WORDS);
/* adapt return codes to match CAVP error: */
if (0 != uECC_valid_public_key(pub_bytes, curve)) {
/* error 4 - Q changed */
rc = 4;
} else {
uECC_vli_nativeToBytes(sig_bytes, NUM_ECC_BYTES, sig);
uECC_vli_nativeToBytes(sig_bytes + NUM_ECC_BYTES, NUM_ECC_BYTES,
sig + NUM_ECC_WORDS);
rc = uECC_verify(pub_bytes, digest_bytes, sizeof(digest_bytes), sig_bytes,
uECC_secp256r1());
/* CAVP expects 0 for success, others for fail */
rc = !rc;
if (exp_rc != 0 && rc != 0) {
/* mimic CAVP code on errors. */
rc = exp_rc;
}
}
result = check_code(i, res_vec[i], exp_rc, rc, verbose);
if(result == TC_FAIL) {
goto exitTest1;
}
}
exitTest1:
TC_END_RESULT(result);
return result;
}
int cavp_verify(bool verbose)
{
/*
* [P-256,SHA-256]
*/
char *Msg[] = {
"e4796db5f785f207aa30d311693b3702821dff1168fd2e04c0836825aefd850d9aa60326d8"
"8cde1a23c7745351392ca2288d632c264f197d05cd424a30336c19fd09bb229654f0222fcb"
"881a4b35c290a093ac159ce13409111ff0358411133c24f5b8e2090d6db6558afc36f06ca1"
"f6ef779785adba68db27a409859fc4c4a0",
"069a6e6b93dfee6df6ef6997cd80dd2182c36653cef10c655d524585655462d683877f95ec"
"c6d6c81623d8fac4e900ed0019964094e7de91f1481989ae1873004565789cbf5dc56c62ae"
"dc63f62f3b894c9c6f7788c8ecaadc9bd0e81ad91b2b3569ea12260e93924fdddd3972af52"
"73198f5efda0746219475017557616170e",
"df04a346cf4d0e331a6db78cca2d456d31b0a000aa51441defdb97bbeb20b94d8d746429a3"
"93ba88840d661615e07def615a342abedfa4ce912e562af714959896858af817317a840dcf"
"f85a057bb91a3c2bf90105500362754a6dd321cdd86128cfc5f04667b57aa78c112411e42d"
"a304f1012d48cd6a7052d7de44ebcc01de",
"e1130af6a38ccb412a9c8d13e15dbfc9e69a16385af3c3f1e5da954fd5e7c45fd75e2b8c36"
"699228e92840c0562fbf3772f07e17f1add56588dd45f7450e1217ad239922dd9c32695dc7"
"1ff2424ca0dec1321aa47064a044b7fe3c2b97d03ce470a592304c5ef21eed9f93da56bb23"
"2d1eeb0035f9bf0dfafdcc4606272b20a3",
"73c5f6a67456ae48209b5f85d1e7de7758bf235300c6ae2bdceb1dcb27a7730fb68c950b7f"
"cada0ecc4661d3578230f225a875e69aaa17f1e71c6be5c831f22663bac63d0c7a9635edb0"
"043ff8c6f26470f02a7bc56556f1437f06dfa27b487a6c4290d8bad38d4879b334e341ba09"
"2dde4e4ae694a9c09302e2dbf443581c08",
"666036d9b4a2426ed6585a4e0fd931a8761451d29ab04bd7dc6d0c5b9e38e6c2b263ff6cb8"
"37bd04399de3d757c6c7005f6d7a987063cf6d7e8cb38a4bf0d74a282572bd01d0f41e3fd0"
"66e3021575f0fa04f27b700d5b7ddddf50965993c3f9c7118ed78888da7cb221849b326059"
"2b8e632d7c51e935a0ceae15207bedd548",
"7e80436bce57339ce8da1b5660149a20240b146d108deef3ec5da4ae256f8f894edcbbc57b"
"34ce37089c0daa17f0c46cd82b5a1599314fd79d2fd2f446bd5a25b8e32fcf05b76d644573"
"a6df4ad1dfea707b479d97237a346f1ec632ea5660efb57e8717a8628d7f82af50a4e84b11"
"f21bdff6839196a880ae20b2a0918d58cd",
"1669bfb657fdc62c3ddd63269787fc1c969f1850fb04c933dda063ef74a56ce13e3a649700"
"820f0061efabf849a85d474326c8a541d99830eea8131eaea584f22d88c353965dabcdc4bf"
"6b55949fd529507dfb803ab6b480cd73ca0ba00ca19c438849e2cea262a1c57d8f81cd257f"
"b58e19dec7904da97d8386e87b84948169",
"3fe60dd9ad6caccf5a6f583b3ae65953563446c4510b70da115ffaa0ba04c076115c7043ab"
"8733403cd69c7d14c212c655c07b43a7c71b9a4cffe22c2684788ec6870dc2013f269172c8"
"22256f9e7cc674791bf2d8486c0f5684283e1649576efc982ede17c7b74b214754d70402fb"
"4bb45ad086cf2cf76b3d63f7fce39ac970",
"983a71b9994d95e876d84d28946a041f8f0a3f544cfcc055496580f1dfd4e312a2ad418fe6"
"9dbc61db230cc0c0ed97e360abab7d6ff4b81ee970a7e97466acfd9644f828ffec538abc38"
"3d0e92326d1c88c55e1f46a668a039beaa1be631a89129938c00a81a3ae46d4aecbf9707f7"
"64dbaccea3ef7665e4c4307fa0b0a3075c",
"4a8c071ac4fd0d52faa407b0fe5dab759f7394a5832127f2a3498f34aac287339e043b4ffa"
"79528faf199dc917f7b066ad65505dab0e11e6948515052ce20cfdb892ffb8aa9bf3f1aa5b"
"e30a5bbe85823bddf70b39fd7ebd4a93a2f75472c1d4f606247a9821f1a8c45a6cb80545de"
"2e0c6c0174e2392088c754e9c8443eb5af",
"0a3a12c3084c865daf1d302c78215d39bfe0b8bf28272b3c0b74beb4b7409db0718239de70"
"0785581514321c6440a4bbaea4c76fa47401e151e68cb6c29017f0bce4631290af5ea5e2bf"
"3ed742ae110b04ade83a5dbd7358f29a85938e23d87ac8233072b79c94670ff0959f9c7f45"
"17862ff829452096c78f5f2e9a7e4e9216",
"785d07a3c54f63dca11f5d1a5f496ee2c2f9288e55007e666c78b007d95cc28581dce51f49"
"0b30fa73dc9e2d45d075d7e3a95fb8a9e1465ad191904124160b7c60fa720ef4ef1c5d2998"
"f40570ae2a870ef3e894c2bc617d8a1dc85c3c55774928c38789b4e661349d3f84d2441a3b"
"856a76949b9f1f80bc161648a1cad5588e",
"76f987ec5448dd72219bd30bf6b66b0775c80b394851a43ff1f537f140a6e7229ef8cd72ad"
"58b1d2d20298539d6347dd5598812bc65323aceaf05228f738b5ad3e8d9fe4100fd767c2f0"
"98c77cb99c2992843ba3eed91d32444f3b6db6cd212dd4e5609548f4bb62812a920f6e2bf1"
"581be1ebeebdd06ec4e971862cc42055ca",
"60cd64b2cd2be6c33859b94875120361a24085f3765cb8b2bf11e026fa9d8855dbe435acf7"
"882e84f3c7857f96e2baab4d9afe4588e4a82e17a78827bfdb5ddbd1c211fbc2e6d884cddd"
"7cb9d90d5bf4a7311b83f352508033812c776a0e00c003c7e0d628e50736c7512df0acfa9f"
"2320bd102229f46495ae6d0857cc452a84",
};
char *Qx[] = {
"87f8f2b218f49845f6f10eec3877136269f5c1a54736dbdf69f89940cad41555",
"5cf02a00d205bdfee2016f7421807fc38ae69e6b7ccd064ee689fc1a94a9f7d2",
"2ddfd145767883ffbb0ac003ab4a44346d08fa2570b3120dcce94562422244cb",
"e424dc61d4bb3cb7ef4344a7f8957a0c5134e16f7a67c074f82e6e12f49abf3c",
"e0fc6a6f50e1c57475673ee54e3a57f9a49f3328e743bf52f335e3eeaa3d2864",
"a849bef575cac3c6920fbce675c3b787136209f855de19ffe2e8d29b31a5ad86",
"3dfb6f40f2471b29b77fdccba72d37c21bba019efa40c1c8f91ec405d7dcc5df",
"69b7667056e1e11d6caf6e45643f8b21e7a4bebda463c7fdbc13bc98efbd0214",
"bf02cbcf6d8cc26e91766d8af0b164fc5968535e84c158eb3bc4e2d79c3cc682",
"224a4d65b958f6d6afb2904863efd2a734b31798884801fcab5a590f4d6da9de",
"43691c7795a57ead8c5c68536fe934538d46f12889680a9cb6d055a066228369",
"9157dbfcf8cf385f5bb1568ad5c6e2a8652ba6dfc63bc1753edf5268cb7eb596",
"072b10c081a4c1713a294f248aef850e297991aca47fa96a7470abe3b8acfdda",
"09308ea5bfad6e5adf408634b3d5ce9240d35442f7fe116452aaec0d25be8c24",
"2d98ea01f754d34bbc3003df5050200abf445ec728556d7ed7d5c54c55552b6d",
};
char *Qy[] = {
"e15f369036f49842fac7a86c8a2b0557609776814448b8f5e84aa9f4395205e9",
"ec530ce3cc5c9d1af463f264d685afe2b4db4b5828d7e61b748930f3ce622a85",
"5f70c7d11ac2b7a435ccfbbae02c3df1ea6b532cc0e9db74f93fffca7c6f9a64",
"970eed7aa2bc48651545949de1dddaf0127e5965ac85d1243d6f60e7dfaee927",
"7f59d689c91e463607d9194d99faf316e25432870816dde63f5d4b373f12f22a",
"bf5fe4f7858f9b805bd8dcc05ad5e7fb889de2f822f3d8b41694e6c55c16b471",
"f22f953f1e395a52ead7f3ae3fc47451b438117b1e04d613bc8555b7d6e6d1bb",
"d3f9b12eb46c7c6fda0da3fc85bc1fd831557f9abc902a3be3cb3e8be7d1aa2f",
"069ba6cb06b49d60812066afa16ecf7b51352f2c03bd93ec220822b1f3dfba03",
"178d51fddada62806f097aa615d33b8f2404e6b1479f5fd4859d595734d6d2b9",
"f8790110b3c3b281aa1eae037d4f1234aff587d903d93ba3af225c27ddc9ccac",
"972570f4313d47fc96f7c02d5594d77d46f91e949808825b3d31f029e8296405",
"9581145cca04a0fb94cedce752c8f0370861916d2a94e7c647c5373ce6a4c8f5",
"f40c93e023ef494b1c3079b2d10ef67f3170740495ce2cc57f8ee4b0618b8ee5",
"9b52672742d637a32add056dfd6d8792f2a33c2e69dafabea09b960bc61e230a",
};
char *R[] = {
"d19ff48b324915576416097d2544f7cbdf8768b1454ad20e0baac50e211f23b0",
"dc23d130c6117fb5751201455e99f36f59aba1a6a21cf2d0e7481a97451d6693",
"9913111cff6f20c5bf453a99cd2c2019a4e749a49724a08774d14e4c113edda8",
"bf96b99aa49c705c910be33142017c642ff540c76349b9dab72f981fd9347f4f",
"1d75830cd36f4c9aa181b2c4221e87f176b7f05b7c87824e82e396c88315c407",
"25acc3aa9d9e84c7abf08f73fa4195acc506491d6fc37cb9074528a7db87b9d6",
"548886278e5ec26bed811dbb72db1e154b6f17be70deb1b210107decb1ec2a5a",
"288f7a1cd391842cce21f00e6f15471c04dc182fe4b14d92dc18910879799790",
"f5acb06c59c2b4927fb852faa07faf4b1852bbb5d06840935e849c4d293d1bad",
"87b93ee2fecfda54deb8dff8e426f3c72c8864991f8ec2b3205bb3b416de93d2",
"8acd62e8c262fa50dd9840480969f4ef70f218ebf8ef9584f199031132c6b1ce",
"dfaea6f297fa320b707866125c2a7d5d515b51a503bee817de9faa343cc48eeb",
"09f5483eccec80f9d104815a1be9cc1a8e5b12b6eb482a65c6907b7480cf4f19",
"5cc8aa7c35743ec0c23dde88dabd5e4fcd0192d2116f6926fef788cddb754e73",
"06108e525f845d0155bf60193222b3219c98e3d49424c2fb2a0987f825c17959",
};
char *Result[] = {
"F (3 - S changed)", "F (2 - R changed)", "F (4 - Q changed)",
"P (0 )", "P (0 )", "F (2 - R changed)",
"F (4 - Q changed)", "F (1 - Message changed)", "F (3 - S changed)",
"F (2 - R changed)", "F (3 - S changed)", "F (1 - Message changed)",
"F (4 - Q changed)", "F (1 - Message changed)", "P (0 )",
};
char *S[] = {
"a3e81e59311cdfff2d4784949f7a2cb50ba6c3a91fa54710568e61aca3e847c6",
"d6ce7708c18dbf35d4f8aa7240922dc6823f2e7058cbc1484fcad1599db5018c",
"9467cd4cd21ecb56b0cab0a9a453b43386845459127a952421f5c6382866c5cc",
"17c55095819089c2e03b9cd415abdf12444e323075d98f31920b9e0f57ec871c",
"cb2acb01dac96efc53a32d4a0d85d0c2e48955214783ecf50a4f0414a319c05a",
"9b21d5b5259ed3f2ef07dfec6cc90d3a37855d1ce122a85ba6a333f307d31537",
"e93bfebd2f14f3d827ca32b464be6e69187f5edbd52def4f96599c37d58eee75",
"247b3c4e89a3bcadfea73c7bfd361def43715fa382b8c3edf4ae15d6e55e9979",
"049dab79c89cc02f1484c437f523e080a75f134917fda752f2d5ca397addfe5d",
"4044a24df85be0cc76f21a4430b75b8e77b932a87f51e4eccbc45c263ebf8f66",
"cfca7ed3d4347fb2a29e526b43c348ae1ce6c60d44f3191b6d8ea3a2d9c92154",
"8f780ad713f9c3e5a4f7fa4c519833dfefc6a7432389b1e4af463961f09764f2",
"a4f90e560c5e4eb8696cb276e5165b6a9d486345dedfb094a76e8442d026378d",
"9c9c045ebaa1b828c32f82ace0d18daebf5e156eb7cbfdc1eff4399a8a900ae7",
"62b5cdd591e5b507e560167ba8f6f7cda74673eb315680cb89ccbc4eec477dce",
};
struct tc_sha256_state_struct sha256_ctx;
printf("Test #2: ECDSAvrfy ");
printf("NIST-p256, SHA2-256\n");
return vrfy_vectors(&sha256_ctx, Msg, Qx, Qy, R, S, Result, 15, verbose);
}
int montecarlo_signverify(int num_tests, bool verbose)
{
printf("Test #3: Monte Carlo (%d Randomized EC-DSA signatures) ", num_tests);
printf("NIST-p256, SHA2-256\n ");
int i;
uint8_t private[NUM_ECC_BYTES];
uint8_t public[2*NUM_ECC_BYTES];
uint8_t hash[NUM_ECC_BYTES];
unsigned int hash_words[NUM_ECC_WORDS];
uint8_t sig[2*NUM_ECC_BYTES];
const struct uECC_Curve_t * curve = uECC_secp256r1();
for (i = 0; i < num_tests; ++i) {
if (verbose) {
TC_PRINT(".");
fflush(stdout);
}
uECC_generate_random_int(hash_words, curve->n, BITS_TO_WORDS(curve->num_n_bits));
uECC_vli_nativeToBytes(hash, NUM_ECC_BYTES, hash_words);
if (!uECC_make_key(public, private, curve)) {
TC_ERROR("uECC_make_key() failed\n");
return TC_FAIL;
}
if (!uECC_sign(private, hash, sizeof(hash), sig, curve)) {
TC_ERROR("uECC_sign() failed\n");
return TC_FAIL;
}
if (!uECC_verify(public, hash, sizeof(hash), sig, curve)) {
TC_ERROR("uECC_verify() failed\n");
return TC_FAIL;
}
if (verbose) {
fflush(stdout);
printf(".");
}
}
TC_PRINT("\n");
return TC_PASS;
}
int main()
{
unsigned int result = TC_PASS;
TC_START("Performing ECC-DSA tests:");
/* Setup of the Cryptographically Secure PRNG. */
uECC_set_rng(&default_CSPRNG);
bool verbose = true;
TC_PRINT("Performing cavp_sign test:\n");
result = cavp_sign(verbose);
if (result == TC_FAIL) { /* terminate test */
TC_ERROR("cavp_sign test failed.\n");
goto exitTest;
}
TC_PRINT("Performing cavp_verify test:\n");
result = cavp_verify(verbose);
if (result == TC_FAIL) {
TC_ERROR("cavp_verify test failed.\n");
goto exitTest;
}
TC_PRINT("Performing montecarlo_signverify test:\n");
result = montecarlo_signverify(10, verbose);
if (result == TC_FAIL) {
TC_ERROR("montecarlo_signverify test failed.\n");
goto exitTest;
}
TC_PRINT("\nAll ECC-DSA tests succeeded.\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
}

View File

@@ -0,0 +1,271 @@
/* test_ecc_utils.c - TinyCrypt common functions for ECC tests */
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* test_ecc_utils.c -- Implementation of some common functions for ECC tests.
*
*/
#include <test_ecc_utils.h>
#include <tinycrypt/constants.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>
#include <unistd.h>
int hex2int (char hex)
{
uint8_t dec;
if ('0' <= hex && hex <= '9') dec = hex - '0';
else if ('a' <= hex && hex <= 'f') dec = hex - 'a' + 10;
else if ('A' <= hex && hex <= 'F') dec = hex - 'A' + 10;
else return -1;
return dec;
}
/*
* Convert hex string to byte string
* Return number of bytes written to buf, or 0 on error
*/
int hex2bin(uint8_t *buf, const size_t buflen, const char *hex,
const size_t hexlen)
{
int dec;
if (buflen < hexlen / 2 + hexlen % 2)
{
return false;
}
/* if hexlen is uneven, insert leading zero nibble */
if (hexlen % 2)
{
dec = hex2int(hex[0]);
if (dec == -1)
return false;
buf[0] = dec;
buf++;
hex++;
}
/* regular hex conversion */
for (size_t i = 0; i < hexlen / 2; i++)
{
dec = hex2int(hex[2 * i]);
if (dec == -1)
{
return false;
}
buf[i] = dec << 4;
dec = hex2int(hex[ 2 * i + 1]);
if (dec == -1)
{
return false;
}
buf[i] += dec;
}
return hexlen / 2 + hexlen % 2;
}
/*
* Convert hex string to zero-padded nanoECC scalar
*/
void string2scalar(unsigned int *scalar, unsigned int num_word32, char *str)
{
unsigned int num_bytes = 4 * num_word32;
uint8_t tmp[num_bytes];
size_t hexlen = strlen(str);
int padding;
if (0 > (padding = 2 * num_bytes - strlen(str)))
{
printf("Error: 2 * num_bytes(%d) < strlen(hex) (%zu)\n",
2 * num_bytes, strlen(str));
exit(-1);
}
memset(tmp, 0, padding / 2);
if (false == hex2bin(tmp + padding / 2, num_bytes, str, hexlen))
{
exit(-1);
}
uECC_vli_bytesToNative(scalar, tmp, num_bytes);
}
void vli_print_bytes(uint8_t *vli, unsigned int size)
{
for(unsigned i = 0; i < size; ++i)
{
printf("%02X ", (unsigned)vli[i]);
}
}
void print_ecc_scalar(const char *label, const unsigned int * p_vli,
unsigned int num_word32)
{
unsigned int i;
if (label) {
printf("%s = { ", label);
}
for(i = 0; i < num_word32 - 1; ++i) {
printf("0x%08lX, ", (unsigned long)p_vli[i]);
}
printf("0x%08lX", (unsigned long)p_vli[i]);
if (label) {
printf(" };\n");
}
}
int check_ecc_result(const int num, const char *name,
const unsigned int *expected,
const unsigned int *computed,
const unsigned int num_word32, const bool verbose)
{
uint32_t num_bytes = 4 * num_word32;
if (memcmp(computed, expected, num_bytes)) {
TC_PRINT("\n Vector #%02d check %s - FAILURE:\n\n", num, name);
print_ecc_scalar("Expected", expected, num_word32);
print_ecc_scalar("Computed", computed, num_word32);
TC_PRINT("\n");
return TC_FAIL;
}
if (verbose) {
TC_PRINT(" Vector #%02d check %s - success\n", num, name);
}
return TC_PASS;
}
int check_code(const int num, const char *name, const int expected,
const int computed, const int verbose)
{
if (expected != computed) {
TC_ERROR("\n Vector #%02d check %s - FAILURE:\n", num, name);
TC_ERROR("\n Expected: %d, computed: %d\n\n", expected, computed);
return TC_FAIL;
}
if (verbose) {
TC_PRINT(" Vector #%02d check %s - success (%d=%d)\n", num, name,
expected, computed);
}
return TC_PASS;
}
/* Test ecc_make_keys, and also as keygen part of other tests */
int keygen_vectors(char **d_vec, char **qx_vec, char **qy_vec, int tests,
bool verbose)
{
unsigned int pub[2 * NUM_ECC_WORDS];
unsigned int d[NUM_ECC_WORDS];
unsigned int prv[NUM_ECC_WORDS];
unsigned int result = TC_PASS;
/* expected outputs (converted input vectors) */
unsigned int exp_pub[2 * NUM_ECC_WORDS];
unsigned int exp_prv[NUM_ECC_WORDS];
for (int i = 0; i < tests; i++) {
string2scalar(exp_prv, NUM_ECC_WORDS, d_vec[i]);
string2scalar(exp_pub, NUM_ECC_WORDS, qx_vec[i]);
string2scalar(exp_pub + NUM_ECC_WORDS, NUM_ECC_WORDS, qy_vec[i]);
/*
* Feed prvkey vector as padded random seed into ecc_make_key.
* Internal mod-reduction will be zero-op and generate correct prv/pub
*/
memset(d, 0, NUM_ECC_WORDS);
string2scalar(d, NUM_ECC_WORDS, d_vec[i]);
uint8_t pub_bytes[2*NUM_ECC_BYTES];
uint8_t prv_bytes[NUM_ECC_BYTES];
uECC_make_key_with_d(pub_bytes, prv_bytes, d, uECC_secp256r1());
uECC_vli_bytesToNative(prv, prv_bytes, NUM_ECC_BYTES);
uECC_vli_bytesToNative(pub, pub_bytes, NUM_ECC_BYTES);
uECC_vli_bytesToNative(pub + NUM_ECC_WORDS, pub_bytes + NUM_ECC_BYTES, NUM_ECC_BYTES);
/* validate correctness of vector conversion and make_key() */
result = check_ecc_result(i, "prv ", exp_prv, prv, NUM_ECC_WORDS, verbose);
if (result == TC_FAIL) {
return result;
}
result = check_ecc_result(i, "pub.x", exp_pub, pub, NUM_ECC_WORDS, verbose);
if (result == TC_FAIL) {
return result;
}
result = check_ecc_result(i, "pub.y", exp_pub + NUM_ECC_WORDS, pub + NUM_ECC_WORDS, NUM_ECC_WORDS, verbose);
if (result == TC_FAIL) {
return result;
}
}
return result;
}

View File

@@ -0,0 +1,362 @@
/* test_hmac.c - TinyCrypt implementation of some HMAC tests */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
DESCRIPTION
This module tests the following HMAC routines:
Scenarios tested include:
- HMAC tests (RFC 4231 test vectors)
*/
#include <tinycrypt/hmac.h>
#include <tinycrypt/sha256.h>
#include <tinycrypt/constants.h>
#include <test_utils.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
unsigned int do_hmac_test(TCHmacState_t h, unsigned int testnum, const uint8_t *data,
size_t datalen, const uint8_t *expected,
size_t expectedlen)
{
uint8_t digest[32];
unsigned int result = TC_PASS;
(void)tc_hmac_init(h);
(void)tc_hmac_update(h, data, datalen);
(void)tc_hmac_final(digest, TC_SHA256_DIGEST_SIZE, h);
result = check_result(testnum, expected, expectedlen,
digest, sizeof(digest));
return result;
}
/*
* NIST test vectors for encryption.
*/
unsigned int test_1(void)
{
unsigned int result = TC_PASS;
TC_PRINT("HMAC %s:\n", __func__);
const uint8_t key[20] = {
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
};
const uint8_t data[8] = {
0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65
};
const uint8_t expected[32] = {
0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce,
0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7
};
struct tc_hmac_state_struct h;
(void)memset(&h, 0x00, sizeof(h));
(void)tc_hmac_set_key(&h, key, sizeof(key));
result = do_hmac_test(&h, 1, data, sizeof(data),expected,
sizeof(expected));
TC_END_RESULT(result);
return result;
}
unsigned int test_2(void)
{
unsigned int result = TC_PASS;
TC_PRINT("HMAC %s:\n", __func__);
const uint8_t key[4] = {
0x4a, 0x65, 0x66, 0x65
};
const uint8_t data[28] = {
0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77,
0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
0x69, 0x6e, 0x67, 0x3f
};
const uint8_t expected[32] = {
0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26,
0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43
};
struct tc_hmac_state_struct h;
(void)memset(&h, 0x00, sizeof(h));
(void)tc_hmac_set_key(&h, key, sizeof(key));
result = do_hmac_test(&h, 2, data, sizeof(data), expected,
sizeof(expected));
TC_END_RESULT(result);
return result;
}
unsigned int test_3(void)
{
unsigned int result = TC_PASS;
TC_PRINT("HMAC %s:\n", __func__);
const uint8_t key[20] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
};
const uint8_t data[50] = {
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd
};
const uint8_t expected[32] = {
0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb,
0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe
};
struct tc_hmac_state_struct h;
(void)memset(&h, 0x00, sizeof(h));
(void)tc_hmac_set_key(&h, key, sizeof(key));
result = do_hmac_test(&h, 3, data, sizeof(data), expected,
sizeof(expected));
TC_END_RESULT(result);
return result;
}
unsigned int test_4(void)
{
unsigned int result = TC_PASS;
TC_PRINT("HMAC %s:\n", __func__);
const uint8_t key[25] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19
};
const uint8_t data[50] = {
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd
};
const uint8_t expected[32] = {
0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98,
0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b
};
struct tc_hmac_state_struct h;
(void)memset(&h, 0x00, sizeof(h));
(void)tc_hmac_set_key(&h, key, sizeof(key));
result = do_hmac_test(&h, 4, data, sizeof(data), expected,
sizeof(expected));
TC_END_RESULT(result);
return result;
}
unsigned int test_5(void)
{
unsigned int result = TC_PASS;
TC_PRINT("HMAC %s:\n", __func__);
const uint8_t key[20] = {
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c
};
const uint8_t data[20] = {
0x54, 0x65, 0x73, 0x74, 0x20, 0x57, 0x69, 0x74, 0x68, 0x20, 0x54, 0x72,
0x75, 0x6e, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e
};
const uint8_t expected[32] = {
0xa3, 0xb6, 0x16, 0x74, 0x73, 0x10, 0x0e, 0xe0, 0x6e, 0x0c, 0x79, 0x6c,
0x29, 0x55, 0x55, 0x2b, 0xfa, 0x6f, 0x7c, 0x0a, 0x6a, 0x8a, 0xef, 0x8b,
0x93, 0xf8, 0x60, 0xaa, 0xb0, 0xcd, 0x20, 0xc5
};
struct tc_hmac_state_struct h;
(void)memset(&h, 0x00, sizeof(h));
(void)tc_hmac_set_key(&h, key, sizeof(key));
result = do_hmac_test(&h, 5, data, sizeof(data), expected,
sizeof(expected));
TC_END_RESULT(result);
return result;
}
unsigned int test_6(void)
{
unsigned int result = TC_PASS;
TC_PRINT("HMAC %s:\n", __func__);
const uint8_t key[131] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
};
const uint8_t data[54] = {
0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c,
0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x4b, 0x65,
0x79, 0x20, 0x2d, 0x20, 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
0x20, 0x46, 0x69, 0x72, 0x73, 0x74
};
const uint8_t expected[32] = {
0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa,
0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54
};
struct tc_hmac_state_struct h;
(void)memset(&h, 0x00, sizeof(h));
(void)tc_hmac_set_key(&h, key, sizeof(key));
result = do_hmac_test(&h, 6, data, sizeof(data), expected,
sizeof(expected));
TC_END_RESULT(result);
return result;
}
unsigned int test_7(void)
{
unsigned int result = TC_PASS;
TC_PRINT("HMAC %s:\n", __func__);
const uint8_t key[131] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
};
const uint8_t data[152] = {
0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65,
0x73, 0x74, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x72, 0x67,
0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e,
0x20, 0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x68, 0x61, 0x73,
0x68, 0x65, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79,
0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e
};
const uint8_t expected[32] = {
0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc,
0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2
};
struct tc_hmac_state_struct h;
(void)memset(&h, 0x00, sizeof(h));
(void)tc_hmac_set_key(&h, key, sizeof(key));
result = do_hmac_test(&h, 7, data, sizeof(data), expected,
sizeof(expected));
TC_END_RESULT(result);
return result;
}
/*
* Main task to test AES
*/
int main(void)
{
unsigned int result = TC_PASS;
TC_START("Performing HMAC tests (RFC4231 test vectors):");
result = test_1();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("HMAC test #1 failed.\n");
goto exitTest;
}
result = test_2();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("HMAC test #2 failed.\n");
goto exitTest;
}
result = test_3();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("HMAC test #3 failed.\n");
goto exitTest;
}
result = test_4();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("HMAC test #4 failed.\n");
goto exitTest;
}
result = test_5();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("HMAC test #5 failed.\n");
goto exitTest;
}
result = test_6();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("HMAC #6 test failed.\n");
goto exitTest;
}
result = test_7();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("HMAC test #7 failed.\n");
goto exitTest;
}
TC_PRINT("All HMAC tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
}

View File

@@ -0,0 +1,135 @@
/* test_hmac_prng.c - TinyCrypt implementation of some HMAC-PRNG tests */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
DESCRIPTION
This module tests the following PRNG routines:
Scenarios tested include:
- HMAC-PRNG init
- HMAC-PRNG reseed
- HMAC-PRNG generate)
*/
#include <tinycrypt/hmac_prng.h>
#include <tinycrypt/constants.h>
#include <test_utils.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TC_DEBUG_MODE 0
#ifdef TC_DEBUG_MODE
void show(const char *label, const uint8_t *s, size_t len)
{
unsigned int i;
printf ("%s = ", label);
for (i = 0; i < (unsigned int) len; ++i) {
printf ("%02x", s[i]);
}
printf ("\n");
}
void printBinaryFile(const uint8_t *s, unsigned int slen)
{
FILE *write_ptr;
write_ptr = fopen("pseudo-random-data.bin","wb");
fwrite(s, slen, 1, write_ptr);
}
#endif
/*
* Main task to test AES
*/
int main(void)
{
uint8_t seed[128];
struct tc_hmac_prng_struct h;
unsigned int size = (1 << 19);
uint8_t random[size];
unsigned int i;
unsigned int result = TC_PASS;
TC_START("Performing HMAC-PRNG tests:");
TC_PRINT("HMAC-PRNG test#1 (init, reseed, generate):\n");
/* Fake seed (replace by a a truly random seed): */
for (i = 0; i < (unsigned int) sizeof(seed); ++i) {
seed[i] = i;
}
/* Fake personalization and additional_input (replace by appropriate
* values): *
* e.g.: hostname+timestamp */
uint8_t *personalization = (uint8_t *) "HOSTNAME";
uint8_t *additional_input = (uint8_t *) "additional input";
TC_PRINT("HMAC-PRNG test#1 (init):\n");
if (tc_hmac_prng_init(&h, personalization,
sizeof(personalization)) == 0) {
TC_ERROR("HMAC-PRNG initialization failed.\n");
result = TC_FAIL;
goto exitTest;
}
TC_END_RESULT(result);
TC_PRINT("HMAC-PRNG test#1 (reseed):\n");
if (tc_hmac_prng_reseed(&h, seed, sizeof(seed), additional_input,
sizeof(additional_input)) == 0) {
TC_ERROR("HMAC-PRNG reseed failed.\n");
result = TC_FAIL;
goto exitTest;
}
TC_END_RESULT(result);
TC_PRINT("HMAC-PRNG test#1 (generate):\n");
if (tc_hmac_prng_generate(random, size, &h) < 1) {
TC_ERROR("HMAC-PRNG generate failed.\n");
result = TC_FAIL;
goto exitTest;
}
TC_END_RESULT(result);
#ifdef TC_DEBUG_MODE
printBinaryFile(random, size);
show ("Pseudo-random data", random, size);
#endif
TC_PRINT("All HMAC tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
}

View File

@@ -0,0 +1,511 @@
/* test_sha256.c - TinyCrypt implementation of some SHA-256 tests */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
DESCRIPTION
This module tests the following SHA256 routines:
Scenarios tested include:
- NIST SHA256 test vectors
*/
#include <tinycrypt/sha256.h>
#include <tinycrypt/constants.h>
#include <test_utils.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/*
* NIST SHA256 test vector 1.
*/
unsigned int test_1(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #1:\n");
const uint8_t expected[32] = {
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
};
const char *m = "abc";
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)tc_sha256_init(&s);
tc_sha256_update(&s, (const uint8_t *) m, strlen(m));
(void)tc_sha256_final(digest, &s);
result = check_result(1, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
/*
* NIST SHA256 test vector 2.
*/
unsigned int test_2(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #2:\n");
const uint8_t expected[32] = {
0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93,
0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
};
const char *m = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)tc_sha256_init(&s);
tc_sha256_update(&s, (const uint8_t *) m, strlen(m));
(void) tc_sha256_final(digest, &s);
result = check_result(2, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_3(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #3:\n");
const uint8_t expected[32] = {
0x68, 0x32, 0x57, 0x20, 0xaa, 0xbd, 0x7c, 0x82, 0xf3, 0x0f, 0x55, 0x4b,
0x31, 0x3d, 0x05, 0x70, 0xc9, 0x5a, 0xcc, 0xbb, 0x7d, 0xc4, 0xb5, 0xaa,
0xe1, 0x12, 0x04, 0xc0, 0x8f, 0xfe, 0x73, 0x2b
};
const uint8_t m[1] = { 0xbd };
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(3, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_4(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #4:\n");
const uint8_t expected[32] = {
0x7a, 0xbc, 0x22, 0xc0, 0xae, 0x5a, 0xf2, 0x6c, 0xe9, 0x3d, 0xbb, 0x94,
0x43, 0x3a, 0x0e, 0x0b, 0x2e, 0x11, 0x9d, 0x01, 0x4f, 0x8e, 0x7f, 0x65,
0xbd, 0x56, 0xc6, 0x1c, 0xcc, 0xcd, 0x95, 0x04
};
const uint8_t m[4] = { 0xc9, 0x8c, 0x8e, 0x55 };
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(4, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_5(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #5:\n");
const uint8_t expected[32] = {
0x02, 0x77, 0x94, 0x66, 0xcd, 0xec, 0x16, 0x38, 0x11, 0xd0, 0x78, 0x81,
0x5c, 0x63, 0x3f, 0x21, 0x90, 0x14, 0x13, 0x08, 0x14, 0x49, 0x00, 0x2f,
0x24, 0xaa, 0x3e, 0x80, 0xf0, 0xb8, 0x8e, 0xf7
};
uint8_t m[55];
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)memset(m, 0x00, sizeof(m));
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(5, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_6(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #6:\n");
const uint8_t expected[32] = {
0xd4, 0x81, 0x7a, 0xa5, 0x49, 0x76, 0x28, 0xe7, 0xc7, 0x7e, 0x6b, 0x60,
0x61, 0x07, 0x04, 0x2b, 0xbb, 0xa3, 0x13, 0x08, 0x88, 0xc5, 0xf4, 0x7a,
0x37, 0x5e, 0x61, 0x79, 0xbe, 0x78, 0x9f, 0xbb
};
uint8_t m[56];
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)memset(m, 0x00, sizeof(m));
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(6, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_7(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #7:\n");
const uint8_t expected[32] = {
0x65, 0xa1, 0x6c, 0xb7, 0x86, 0x13, 0x35, 0xd5, 0xac, 0xe3, 0xc6, 0x07,
0x18, 0xb5, 0x05, 0x2e, 0x44, 0x66, 0x07, 0x26, 0xda, 0x4c, 0xd1, 0x3b,
0xb7, 0x45, 0x38, 0x1b, 0x23, 0x5a, 0x17, 0x85
};
uint8_t m[57];
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)memset(m, 0x00, sizeof(m));
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(7, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_8(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #8:\n");
const uint8_t expected[32] = {
0xf5, 0xa5, 0xfd, 0x42, 0xd1, 0x6a, 0x20, 0x30, 0x27, 0x98, 0xef, 0x6e,
0xd3, 0x09, 0x97, 0x9b, 0x43, 0x00, 0x3d, 0x23, 0x20, 0xd9, 0xf0, 0xe8,
0xea, 0x98, 0x31, 0xa9, 0x27, 0x59, 0xfb, 0x4b
};
uint8_t m[64];
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)memset(m, 0x00, sizeof(m));
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(8, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_9(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #9:\n");
const uint8_t expected[32] = {
0x54, 0x1b, 0x3e, 0x9d, 0xaa, 0x09, 0xb2, 0x0b, 0xf8, 0x5f, 0xa2, 0x73,
0xe5, 0xcb, 0xd3, 0xe8, 0x01, 0x85, 0xaa, 0x4e, 0xc2, 0x98, 0xe7, 0x65,
0xdb, 0x87, 0x74, 0x2b, 0x70, 0x13, 0x8a, 0x53
};
uint8_t m[1000];
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)memset(m, 0x00, sizeof(m));
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(9, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_10(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #10:\n");
const uint8_t expected[32] = {
0xc2, 0xe6, 0x86, 0x82, 0x34, 0x89, 0xce, 0xd2, 0x01, 0x7f, 0x60, 0x59,
0xb8, 0xb2, 0x39, 0x31, 0x8b, 0x63, 0x64, 0xf6, 0xdc, 0xd8, 0x35, 0xd0,
0xa5, 0x19, 0x10, 0x5a, 0x1e, 0xad, 0xd6, 0xe4
};
uint8_t m[1000];
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)memset(m, 0x41, sizeof(m));
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(10, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_11(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #11:\n");
const uint8_t expected[32] = {
0xf4, 0xd6, 0x2d, 0xde, 0xc0, 0xf3, 0xdd, 0x90, 0xea, 0x13, 0x80, 0xfa,
0x16, 0xa5, 0xff, 0x8d, 0xc4, 0xc5, 0x4b, 0x21, 0x74, 0x06, 0x50, 0xf2,
0x4a, 0xfc, 0x41, 0x20, 0x90, 0x35, 0x52, 0xb0
};
uint8_t m[1005];
uint8_t digest[32];
struct tc_sha256_state_struct s;
(void)memset(m, 0x55, sizeof(m));
(void)tc_sha256_init(&s);
tc_sha256_update(&s, m, sizeof(m));
(void)tc_sha256_final(digest, &s);
result = check_result(11, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_12(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #12:\n");
const uint8_t expected[32] = {
0xd2, 0x97, 0x51, 0xf2, 0x64, 0x9b, 0x32, 0xff, 0x57, 0x2b, 0x5e, 0x0a,
0x9f, 0x54, 0x1e, 0xa6, 0x60, 0xa5, 0x0f, 0x94, 0xff, 0x0b, 0xee, 0xdf,
0xb0, 0xb6, 0x92, 0xb9, 0x24, 0xcc, 0x80, 0x25
};
uint8_t m[1000];
uint8_t digest[32];
struct tc_sha256_state_struct s;
unsigned int i;
(void)memset(m, 0x00, sizeof(m));
(void)tc_sha256_init(&s);
for (i = 0; i < 1000; ++i) {
tc_sha256_update(&s, m, sizeof(m));
}
(void)tc_sha256_final(digest, &s);
result = check_result(12, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_13(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #13:\n");
const uint8_t expected[32] = {
0x15, 0xa1, 0x86, 0x8c, 0x12, 0xcc, 0x53, 0x95, 0x1e, 0x18, 0x23, 0x44,
0x27, 0x74, 0x47, 0xcd, 0x09, 0x79, 0x53, 0x6b, 0xad, 0xcc, 0x51, 0x2a,
0xd2, 0x4c, 0x67, 0xe9, 0xb2, 0xd4, 0xf3, 0xdd
};
uint8_t m[32768];
uint8_t digest[32];
struct tc_sha256_state_struct s;
unsigned int i;
(void)memset(m, 0x5a, sizeof(m));
(void)tc_sha256_init(&s);
for (i = 0; i < 16384; ++i) {
tc_sha256_update(&s, m, sizeof(m));
}
(void)tc_sha256_final(digest, &s);
result = check_result(13, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
unsigned int test_14(void)
{
unsigned int result = TC_PASS;
TC_PRINT("SHA256 test #14:\n");
const uint8_t expected[32] = {
0x46, 0x1c, 0x19, 0xa9, 0x3b, 0xd4, 0x34, 0x4f, 0x92, 0x15, 0xf5, 0xec,
0x64, 0x35, 0x70, 0x90, 0x34, 0x2b, 0xc6, 0x6b, 0x15, 0xa1, 0x48, 0x31,
0x7d, 0x27, 0x6e, 0x31, 0xcb, 0xc2, 0x0b, 0x53
};
uint8_t m[32768];
uint8_t digest[32];
struct tc_sha256_state_struct s;
unsigned int i;
(void)memset(m, 0x00, sizeof(m));
(void) tc_sha256_init(&s);
for (i = 0; i < 33280; ++i) {
tc_sha256_update(&s, m, sizeof(m));
}
(void) tc_sha256_final(digest, &s);
result = check_result(14, expected, sizeof(expected),
digest, sizeof(digest));
TC_END_RESULT(result);
return result;
}
/*
* Main task to test AES
*/
int main(void)
{
unsigned int result = TC_PASS;
TC_START("Performing SHA256 tests (NIST tests vectors):");
result = test_1();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #1 failed.\n");
goto exitTest;
}
result = test_2();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #2 failed.\n");
goto exitTest;
}
result = test_3();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #3 failed.\n");
goto exitTest;
}
result = test_4();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #4 failed.\n");
goto exitTest;
}
result = test_5();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #5 failed.\n");
goto exitTest;
}
result = test_6();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #6 failed.\n");
goto exitTest;
}
result = test_7();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #7 failed.\n");
goto exitTest;
}
result = test_8();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #8 failed.\n");
goto exitTest;
}
result = test_9();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #9 failed.\n");
goto exitTest;
}
result = test_10();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #10 failed.\n");
goto exitTest;
}
result = test_11();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #11 failed.\n");
goto exitTest;
}
result = test_12();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #12 failed.\n");
goto exitTest;
}
/* memory and computation intensive test cases: */
result = test_13();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #13 failed.\n");
goto exitTest;
}
result = test_14();
if (result == TC_FAIL) {
/* terminate test */
TC_ERROR("SHA256 test #14 failed.\n");
goto exitTest;
}
TC_PRINT("All SHA256 tests succeeded!\n");
exitTest:
TC_END_RESULT(result);
TC_END_REPORT(result);
}