Merge branch 'iotssl-825-double-free-quickfix'
Conflicts:
ChangeLog
diff --git a/ChangeLog b/ChangeLog
index 8090a70..9f94210 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,8 @@
= mbed TLS 2.3.x branch released 2016-xx-xx
Features
+ * Added support for CMAC for AES and 3DES and AES-CMAC-PRF-128, as defined by
+ NIST SP 800-38B, RFC-4493 and RFC-4615.
* Added hardware entropy selftest to verify that the hardware entropy source
is functioning correctly.
* Added a script to print build environment info for diagnostic use in test
@@ -29,6 +31,9 @@
a contribution from Tobias Tangemann. #541
* Fixed cert_app sample program for debug output and for use when no root
certificates are provided.
+ * Fixed the sample applications gen_key.c, cert_req.c and cert_write.c for
+ builds where the configuration MBEDTLS_PEM_WRITE_C is not defined. Found
+ by inestlerode. #559.
* Fixed default threading implementation to avoid accidental double
initialisations and double frees.
diff --git a/configs/config-thread.h b/configs/config-thread.h
index 3193a04..990fe08 100644
--- a/configs/config-thread.h
+++ b/configs/config-thread.h
@@ -57,6 +57,7 @@
#define MBEDTLS_CCM_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_CMAC_C
#define MBEDTLS_ECJPAKE_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ENTROPY_C
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 75cdcbc..fe86c1e 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -77,6 +77,11 @@
#error "MBEDTLS_DHM_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_CMAC_C) && \
+ !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C)
+#error "MBEDTLS_CMAC_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C)
#error "MBEDTLS_ECDH_C defined, but not all prerequisites"
#endif
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index c967554..b12e388 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -177,6 +177,11 @@
typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t;
/**
+ * CMAC context (opaque struct).
+ */
+typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
+
+/**
* Cipher information. Allows cipher functions to be called in a generic way.
*/
typedef struct {
@@ -241,6 +246,11 @@
/** Cipher-specific context */
void *cipher_ctx;
+
+#if defined(MBEDTLS_CMAC_C)
+ /** CMAC Specific context */
+ mbedtls_cmac_context_t *cmac_ctx;
+#endif
} mbedtls_cipher_context_t;
/**
diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h
new file mode 100644
index 0000000..f64ae69
--- /dev/null
+++ b/include/mbedtls/cmac.h
@@ -0,0 +1,170 @@
+/**
+ * \file cmac.h
+ *
+ * \brief Cipher-based Message Authentication Code (CMAC) Mode for
+ * Authentication
+ *
+ * Copyright (C) 2015-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_CMAC_H
+#define MBEDTLS_CMAC_H
+
+#include "mbedtls/cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MBEDTLS_AES_BLOCK_SIZE 16
+#define MBEDTLS_DES3_BLOCK_SIZE 8
+
+#if defined(MBEDTLS_AES_C)
+#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /* longest used by CMAC is AES */
+#else
+#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */
+#endif
+
+/**
+ * CMAC context structure - Contains internal state information only
+ */
+struct mbedtls_cmac_context_t
+{
+
+ /** Internal state of the CMAC algorithm */
+ unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+ /** Unprocessed data - either data that was not block aligned and is still
+ * pending to be processed, or the final block */
+ unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+ /** Length of data pending to be processed */
+ size_t unprocessed_len;
+
+ /** Flag to indicate if the last block needs padding */
+ int padding_flag;
+};
+
+/**
+ * \brief Set the CMAC key and prepare to authenticate the input
+ * data.
+ * Should be called with an initialised cipher context.
+ *
+ * \param ctx Cipher context
+ * \param key CMAC key
+ * \param keybits length of the CMAC key in bits
+ * (must be acceptable by the cipher)
+ *
+ * \return 0 if successful, or a cipher specific error code
+ */
+int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
+ const unsigned char *key, size_t keybits );
+
+/**
+ * \brief Generic CMAC process buffer.
+ * Called between mbedtls_cipher_cmac_starts() or
+ * mbedtls_cipher_cmac_reset() and
+ * mbedtls_cipher_cmac_finish().
+ * May be called repeatedly.
+ *
+ * \param ctx CMAC context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
+ const unsigned char *input, size_t ilen );
+
+/**
+ * \brief Output CMAC.
+ * Called after mbedtls_cipher_cmac_update().
+ * Usually followed by mbedtls_cipher_cmac_reset(), then
+ * mbedtls_cipher_cmac_starts(), or mbedtls_cipher_free().
+ *
+ * \param ctx CMAC context
+ * \param output Generic CMAC checksum result
+ *
+ * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
+ unsigned char *output );
+
+/**
+ * \brief Prepare to authenticate a new message with the same key.
+ * Called after mbedtls_cipher_cmac_finish() and before
+ * mbedtls_cipher_cmac_update().
+ *
+ * \param ctx CMAC context to be reset
+ *
+ * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx );
+
+/**
+ * \brief Output = Generic_CMAC( hmac key, input buffer )
+ *
+ * \param cipher_info message digest info
+ * \param key CMAC key
+ * \param keylen length of the CMAC key in bits
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output Generic CMAC-result
+ *
+ * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter
+ * verification fails.
+ */
+int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output );
+
+#if defined(MBEDTLS_AES_C)
+/**
+ * \brief AES-CMAC-128-PRF
+ * Implementation of (AES-CMAC-PRF-128), as defined in RFC 4615
+ *
+ * \param key PRF key
+ * \param key_len PRF key length in bytes
+ * \param input buffer holding the input data
+ * \param in_len length of the input data in bytes
+ * \param output buffer holding the generated pseudorandom output (16 bytes)
+ *
+ * \return 0 if successful
+ */
+int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len,
+ const unsigned char *input, size_t in_len,
+ unsigned char output[16] );
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedtls_cmac_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CMAC_H */
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index a58519b..498e5b5 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1672,6 +1672,19 @@
#define MBEDTLS_CIPHER_C
/**
+ * \def MBEDTLS_CMAC_C
+ *
+ * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
+ * ciphers.
+ *
+ * Module: library/cmac.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
+ *
+ */
+//#define MBEDTLS_CMAC_C
+
+/**
* \def MBEDTLS_CTR_DRBG_C
*
* Enable the CTR_DRBG AES-256-based random generator.
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index b902355..9b996a9 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -304,8 +304,8 @@
/**
* \brief Output HMAC.
* Called after mbedtls_md_hmac_update().
- * Usually followed my mbedtls_md_hmac_reset(), mbedtls_md_hmac_starts(),
- * or mbedtls_md_free().
+ * Usually followed by mbedtls_md_hmac_reset(),
+ * mbedtls_md_hmac_starts(), or mbedtls_md_free().
*
* \param ctx HMAC context
* \param output Generic HMAC checksum result
@@ -317,7 +317,8 @@
/**
* \brief Prepare to authenticate a new message with the same key.
- * Called after mbedtls_md_hmac_finish() and before mbedtls_md_hmac_update().
+ * Called after mbedtls_md_hmac_finish() and before
+ * mbedtls_md_hmac_update().
*
* \param ctx HMAC context to be reset
*
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 98fe8c9..eeb8e84 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -15,6 +15,7 @@
ccm.c
cipher.c
cipher_wrap.c
+ cmac.c
ctr_drbg.c
des.c
dhm.c
diff --git a/library/Makefile b/library/Makefile
index 4b29628..28f9231 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -48,9 +48,9 @@
asn1parse.o asn1write.o base64.o \
bignum.o blowfish.o camellia.o \
ccm.o cipher.o cipher_wrap.o \
- ctr_drbg.o des.o dhm.o \
- ecdh.o ecdsa.o ecjpake.o \
- ecp.o \
+ cmac.o ctr_drbg.o des.o \
+ dhm.o ecdh.o ecdsa.o \
+ ecjpake.o ecp.o \
ecp_curves.o entropy.o entropy_poll.o \
error.o gcm.o havege.o \
hmac_drbg.o md.o md2.o \
diff --git a/library/cipher.c b/library/cipher.c
index bbe40eb..a883438 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -45,6 +45,17 @@
#include "mbedtls/ccm.h"
#endif
+#if defined(MBEDTLS_CMAC_C)
+#include "mbedtls/cmac.h"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#define mbedtls_calloc calloc
+#define mbedtls_free free
+#endif
+
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
#define MBEDTLS_CIPHER_MODE_STREAM
#endif
@@ -127,6 +138,14 @@
if( ctx == NULL )
return;
+#if defined(MBEDTLS_CMAC_C)
+ if( ctx->cmac_ctx )
+ {
+ mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) );
+ mbedtls_free( ctx->cmac_ctx );
+ }
+#endif
+
if( ctx->cipher_ctx )
ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
diff --git a/library/cmac.c b/library/cmac.c
new file mode 100644
index 0000000..f755d40
--- /dev/null
+++ b/library/cmac.c
@@ -0,0 +1,1035 @@
+/*
+ * \file cmac.c
+ *
+ * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES
+ *
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+/*
+ * References:
+ *
+ * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The
+ * CMAC Mode for Authentication
+ * http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38b.pdf
+ *
+ * - RFC 4493 - The AES-CMAC Algorithm
+ * https://tools.ietf.org/html/rfc4493
+ *
+ * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message
+ * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)
+ * Algorithm for the Internet Key Exchange Protocol (IKE)
+ * https://tools.ietf.org/html/rfc4615
+ *
+ * Additional test vectors: ISO/IEC 9797-1
+ *
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CMAC_C)
+
+#include "mbedtls/cmac.h"
+
+#include <string.h>
+
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_calloc calloc
+#define mbedtls_free free
+#if defined(MBEDTLS_SELF_TEST)
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C || MBEDTLS_DES_C */
+#endif /* MBEDTLS_PLATFORM_C */
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+ volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * Multiplication by u in the Galois field of GF(2^n)
+ *
+ * As explained in NIST SP 800-38B, this can be computed:
+ *
+ * If MSB(p) = 0, then p = (p << 1)
+ * If MSB(p) = 1, then p = (p << 1) ^ R_n
+ * with R_64 = 0x1B and R_128 = 0x87
+ *
+ * Input and output MUST NOT point to the same buffer
+ * Block size must be 8 byes or 16 bytes - the block sizes for DES and AES.
+ */
+static int cmac_multiply_by_u( unsigned char *output,
+ const unsigned char *input,
+ size_t blocksize )
+{
+ const unsigned char R_128 = 0x87;
+ const unsigned char R_64 = 0x1B;
+ unsigned char R_n, mask;
+ unsigned char overflow = 0x00;
+ int i;
+
+ if( blocksize == MBEDTLS_AES_BLOCK_SIZE )
+ {
+ R_n = R_128;
+ }
+ else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE )
+ {
+ R_n = R_64;
+ }
+ else
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ for( i = blocksize - 1; i >= 0; i-- )
+ {
+ output[i] = input[i] << 1 | overflow;
+ overflow = input[i] >> 7;
+ }
+
+ /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
+ * using bit operations to avoid branches */
+
+ /* MSVC has a warning about unary minus on unsigned, but this is
+ * well-defined and precisely what we want to do here */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+ mask = - ( input[0] >> 7 );
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+ output[ blocksize - 1 ] ^= R_n & mask;
+
+ return( 0 );
+}
+
+/*
+ * Generate subkeys
+ *
+ * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
+ */
+static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
+ unsigned char* K1, unsigned char* K2 )
+{
+ int ret;
+ unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
+ size_t olen, block_size;
+
+ mbedtls_zeroize( L, sizeof( L ) );
+
+ block_size = ctx->cipher_info->block_size;
+
+ /* Calculate Ek(0) */
+ if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 )
+ goto exit;
+
+ /*
+ * Generate K1 and K2
+ */
+ if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
+ goto exit;
+
+ if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 )
+ goto exit;
+
+exit:
+ mbedtls_zeroize( L, sizeof( L ) );
+
+ return( ret );
+}
+
+static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
+ const unsigned char *input2,
+ const size_t block_size )
+{
+ size_t index;
+
+ for( index = 0; index < block_size; index++ )
+ output[ index ] = input1[ index ] ^ input2[ index ];
+}
+
+/*
+ * Create padded last block from (partial) last block.
+ *
+ * We can't use the padding option from the cipher layer, as it only works for
+ * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
+ */
+static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
+ size_t padded_block_len,
+ const unsigned char *last_block,
+ size_t last_block_len )
+{
+ size_t j;
+
+ for( j = 0; j < padded_block_len; j++ )
+ {
+ if( j < last_block_len )
+ padded_block[j] = last_block[j];
+ else if( j == last_block_len )
+ padded_block[j] = 0x80;
+ else
+ padded_block[j] = 0x00;
+ }
+}
+
+int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
+ const unsigned char *key, size_t keybits )
+{
+ mbedtls_cipher_type_t type;
+ mbedtls_cmac_context_t *cmac_ctx;
+ int retval;
+
+ if( ctx == NULL || ctx->cipher_info == NULL || key == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if( ( retval = mbedtls_cipher_setkey( ctx, key, keybits,
+ MBEDTLS_ENCRYPT ) ) != 0 )
+ return( retval );
+
+ type = ctx->cipher_info->type;
+
+ switch( type )
+ {
+ case MBEDTLS_CIPHER_AES_128_ECB:
+ case MBEDTLS_CIPHER_AES_192_ECB:
+ case MBEDTLS_CIPHER_AES_256_ECB:
+ case MBEDTLS_CIPHER_DES_EDE3_ECB:
+ break;
+ default:
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ /* Allocated and initialise in the cipher context memory for the CMAC
+ * context */
+ cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) );
+ if( cmac_ctx == NULL )
+ return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
+
+ ctx->cmac_ctx = cmac_ctx;
+
+ mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
+ cmac_ctx->padding_flag = 1;
+
+ return 0;
+}
+
+int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
+ const unsigned char *input, size_t ilen )
+{
+ mbedtls_cmac_context_t* cmac_ctx;
+ unsigned char *state;
+ int n, j, ret = 0;
+ size_t olen, block_size;
+
+ if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
+ ctx->cmac_ctx == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ cmac_ctx = ctx->cmac_ctx;
+ block_size = ctx->cipher_info->block_size;
+ state = ctx->cmac_ctx->state;
+
+ /* Is their data still to process from the last call, that's equal to
+ * or greater than a block? */
+ if( cmac_ctx->unprocessed_len > 0 &&
+ ilen > block_size - cmac_ctx->unprocessed_len )
+ {
+ memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
+ input,
+ block_size - cmac_ctx->unprocessed_len );
+
+ cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
+
+ if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
+ &olen ) ) != 0 )
+ {
+ goto exit;
+ }
+
+ ilen -= block_size;
+ input += cmac_ctx->unprocessed_len;
+
+ cmac_ctx->unprocessed_len = 0;
+ }
+
+ /* n is the number of blocks including any final partial block */
+ n = ( ilen + block_size - 1 ) / block_size;
+
+ /* Iterate across the input data in block sized chunks */
+ for( j = 0; j < n - 1; j++ )
+ {
+ cmac_xor_block( state, input, state, block_size );
+
+ if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
+ &olen ) ) != 0 )
+ goto exit;
+
+ ilen -= block_size;
+ input += block_size;
+
+ cmac_ctx->padding_flag = 0;
+ }
+
+ /* If there is data left over that wasn't aligned to a block */
+ if( ilen > 0 )
+ {
+ memcpy( &cmac_ctx->unprocessed_block, input, ilen );
+ cmac_ctx->unprocessed_len = ilen;
+
+ if( ilen % block_size > 0 )
+ cmac_ctx->padding_flag = 1;
+ else
+ cmac_ctx->padding_flag = 0;
+ }
+
+exit:
+ return( ret );
+}
+
+int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
+ unsigned char *output )
+{
+ mbedtls_cmac_context_t* cmac_ctx;
+ unsigned char *state, *last_block;
+ unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
+ unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
+ unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
+ int ret;
+ size_t olen, block_size;
+
+ if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
+ output == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ cmac_ctx = ctx->cmac_ctx;
+ block_size = ctx->cipher_info->block_size;
+ state = cmac_ctx->state;
+
+ mbedtls_zeroize( K1, sizeof( K1 ) );
+ mbedtls_zeroize( K2, sizeof( K2 ) );
+ cmac_generate_subkeys( ctx, K1, K2 );
+
+ last_block = cmac_ctx->unprocessed_block;
+
+ /* Calculate last block */
+ if( cmac_ctx->padding_flag )
+ {
+ cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
+ cmac_xor_block( M_last, M_last, K2, block_size );
+ }
+ else
+ {
+ /* Last block is complete block */
+ cmac_xor_block( M_last, last_block, K1, block_size );
+ }
+
+
+ cmac_xor_block( state, M_last, state, block_size );
+ if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
+ &olen ) ) != 0 )
+ {
+ goto exit;
+ }
+
+ memcpy( output, state, block_size );
+
+exit:
+ /* Wipe the generated keys on the stack, and any other transients to avoid
+ * side channel leakage */
+ mbedtls_zeroize( K1, sizeof( K1 ) );
+ mbedtls_zeroize( K2, sizeof( K2 ) );
+
+ cmac_ctx->padding_flag = 1;
+ cmac_ctx->unprocessed_len = 0;
+ mbedtls_zeroize( cmac_ctx->unprocessed_block,
+ sizeof( cmac_ctx->unprocessed_block ) );
+
+ mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
+ return( ret );
+}
+
+int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
+{
+ mbedtls_cmac_context_t* cmac_ctx;
+
+ if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ cmac_ctx = ctx->cmac_ctx;
+
+ /* Reset the internal state */
+ cmac_ctx->unprocessed_len = 0;
+ mbedtls_zeroize( cmac_ctx->unprocessed_block,
+ sizeof( cmac_ctx->unprocessed_block ) );
+ mbedtls_zeroize( cmac_ctx->state,
+ sizeof( cmac_ctx->state ) );
+ cmac_ctx->padding_flag = 1;
+
+ return( 0 );
+}
+
+int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *input, size_t ilen,
+ unsigned char *output )
+{
+ mbedtls_cipher_context_t ctx;
+ int ret;
+
+ if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ mbedtls_cipher_init( &ctx );
+
+ if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
+ goto exit;
+
+ ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
+ if( ret != 0 )
+ goto exit;
+
+ ret = mbedtls_cipher_cmac_finish( &ctx, output );
+
+exit:
+ mbedtls_cipher_free( &ctx );
+
+ return( ret );
+}
+
+#if defined(MBEDTLS_AES_C)
+/*
+ * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
+ */
+int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
+ const unsigned char *input, size_t in_len,
+ unsigned char *output )
+{
+ int ret;
+ const mbedtls_cipher_info_t *cipher_info;
+ unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
+ unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
+
+ if( key == NULL || input == NULL || output == NULL )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
+ if( cipher_info == NULL )
+ {
+ /* Failing at this point must be due to a build issue */
+ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ goto exit;
+ }
+
+ if( key_length == MBEDTLS_AES_BLOCK_SIZE )
+ {
+ /* Use key as is */
+ memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE );
+ }
+ else
+ {
+ memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE );
+
+ ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
+ key_length, int_key );
+ if( ret != 0 )
+ goto exit;
+ }
+
+ ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
+ output );
+
+exit:
+ mbedtls_zeroize( int_key, sizeof( int_key ) );
+
+ return( ret );
+}
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_SELF_TEST)
+/*
+ * CMAC test data from SP800-38B Appendix D.1 (corrected)
+ * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
+ *
+ * AES-CMAC-PRF-128 test data from RFC 4615
+ * https://tools.ietf.org/html/rfc4615#page-4
+ */
+
+#define NB_CMAC_TESTS_PER_KEY 4
+#define NB_PRF_TESTS 3
+
+#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
+/* All CMAC test inputs are truncated from the same 64 byte buffer. */
+static const unsigned char test_message[] = {
+ 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
+};
+#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_AES_C)
+/* Truncation point of message for AES CMAC tests */
+static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
+ 0,
+ 16,
+ 40,
+ 64
+};
+
+/* AES 128 CMAC Test Data */
+static const unsigned char aes_128_key[16] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+};
+static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
+ {
+ 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
+ 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
+ },
+ {
+ 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
+ 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
+ }
+};
+static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
+ {
+ 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+ 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
+ },
+ {
+ 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+ 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+ },
+ {
+ 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+ 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
+ },
+ {
+ 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+ 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+ }
+};
+
+/* AES 192 CMAC Test Data */
+static const unsigned char aes_192_key[24] = {
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
+ 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
+};
+static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
+ {
+ 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
+ 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
+ },
+ {
+ 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
+ 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
+ }
+};
+static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
+ {
+ 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
+ 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
+ },
+ {
+ 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
+ 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
+ },
+ {
+ 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
+ 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
+ },
+ {
+ 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
+ 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
+ }
+};
+
+/* AES 256 CMAC Test Data */
+static const unsigned char aes_256_key[32] = {
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
+ 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+ 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+};
+static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
+ {
+ 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
+ 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
+ },
+ {
+ 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
+ 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
+ }
+};
+static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
+ {
+ 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
+ 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
+ },
+ {
+ 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
+ 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
+ },
+ {
+ 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
+ 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
+ },
+ {
+ 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
+ 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
+ }
+};
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_DES_C)
+/* Truncation point of message for 3DES CMAC tests */
+static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
+ 0,
+ 8,
+ 20,
+ 32
+};
+
+/* 3DES 2 Key CMAC Test Data */
+static const unsigned char des3_2key_key[24] = {
+ 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
+ 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
+ 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
+};
+static const unsigned char des3_2key_subkeys[2][8] = {
+ {
+ 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
+ },
+ {
+ 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
+ }
+};
+static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
+ {
+ 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
+ },
+ {
+ 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
+ },
+ {
+ 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
+ },
+ {
+ 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
+ }
+};
+
+/* 3DES 3 Key CMAC Test Data */
+static const unsigned char des3_3key_key[24] = {
+ 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
+ 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
+ 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
+};
+static const unsigned char des3_3key_subkeys[2][8] = {
+ {
+ 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
+ },
+ {
+ 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
+ }
+};
+static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
+ {
+ 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
+ },
+ {
+ 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
+ },
+ {
+ 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
+ },
+ {
+ 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
+ }
+};
+
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_AES_C)
+/* AES AES-CMAC-PRF-128 Test Data */
+static const unsigned char PRFK[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0xed, 0xcb
+};
+
+/* Sizes in bytes */
+static const size_t PRFKlen[NB_PRF_TESTS] = {
+ 18,
+ 16,
+ 10
+};
+
+/* PRF M */
+static const unsigned char PRFM[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13
+};
+
+static const unsigned char PRFT[NB_PRF_TESTS][16] = {
+ {
+ 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
+ 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
+ },
+ {
+ 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
+ 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
+ },
+ {
+ 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
+ 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
+ }
+};
+#endif /* MBEDTLS_AES_C */
+
+static int cmac_test_subkeys( int verbose,
+ const char* testname,
+ const unsigned char* key,
+ int keybits,
+ const unsigned char* subkeys,
+ mbedtls_cipher_type_t cipher_type,
+ int block_size,
+ int num_tests )
+{
+ int i, ret;
+ mbedtls_cipher_context_t ctx;
+ const mbedtls_cipher_info_t *cipher_info;
+ unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
+ unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+ cipher_info = mbedtls_cipher_info_from_type( cipher_type );
+ if( cipher_info == NULL )
+ {
+ /* Failing at this point must be due to a build issue */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+
+ mbedtls_cipher_init( &ctx );
+
+ for( i = 0; i < num_tests; i++ )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
+
+ if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "test execution failed\n" );
+
+ goto exit;
+ }
+
+ if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
+ MBEDTLS_ENCRYPT ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "test execution failed\n" );
+
+ goto exit;
+ }
+
+ ret = cmac_generate_subkeys( &ctx, K1, K2 );
+ if( ret != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed\n" );
+ goto exit;
+ }
+
+ if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
+ ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed\n" );
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+exit:
+ mbedtls_cipher_free( &ctx );
+
+ return( ret );
+}
+
+static int cmac_test_wth_cipher( int verbose,
+ const char* testname,
+ const unsigned char* key,
+ int keybits,
+ const unsigned char* messages,
+ const unsigned int message_lengths[4],
+ const unsigned char* expected_result,
+ mbedtls_cipher_type_t cipher_type,
+ int block_size,
+ int num_tests )
+{
+ const mbedtls_cipher_info_t *cipher_info;
+ int i, ret;
+ unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+ cipher_info = mbedtls_cipher_info_from_type( cipher_type );
+ if( cipher_info == NULL )
+ {
+ /* Failing at this point must be due to a build issue */
+ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+ goto exit;
+ }
+
+ for( i = 0; i < num_tests; i++ )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 );
+
+ if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
+ message_lengths[i], output ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed\n" );
+ goto exit;
+ }
+
+ if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed\n" );
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+exit:
+ return( ret );
+}
+
+#if defined(MBEDTLS_AES_C)
+static int test_aes128_cmac_prf( int verbose )
+{
+ int i;
+ int ret;
+ unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
+
+ for( i = 0; i < NB_PRF_TESTS; i++ )
+ {
+ mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
+ ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
+ if( ret != 0 ||
+ memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
+ {
+
+ if( verbose != 0 )
+ mbedtls_printf( "failed\n" );
+
+ return( ret );
+ }
+ else if( verbose != 0 )
+ {
+ mbedtls_printf( "passed\n" );
+ }
+ }
+ return( ret );
+}
+#endif /* MBEDTLS_AES_C */
+
+int mbedtls_cmac_self_test( int verbose )
+{
+ int ret;
+
+#if defined(MBEDTLS_AES_C)
+ /* AES-128 */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "AES 128",
+ aes_128_key,
+ 128,
+ (const unsigned char*)aes_128_subkeys,
+ MBEDTLS_CIPHER_AES_128_ECB,
+ MBEDTLS_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher( verbose,
+ "AES 128",
+ aes_128_key,
+ 128,
+ test_message,
+ aes_message_lengths,
+ (const unsigned char*)aes_128_expected_result,
+ MBEDTLS_CIPHER_AES_128_ECB,
+ MBEDTLS_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* AES-192 */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "AES 192",
+ aes_192_key,
+ 192,
+ (const unsigned char*)aes_192_subkeys,
+ MBEDTLS_CIPHER_AES_192_ECB,
+ MBEDTLS_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher( verbose,
+ "AES 192",
+ aes_192_key,
+ 192,
+ test_message,
+ aes_message_lengths,
+ (const unsigned char*)aes_192_expected_result,
+ MBEDTLS_CIPHER_AES_192_ECB,
+ MBEDTLS_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* AES-256 */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "AES 256",
+ aes_256_key,
+ 256,
+ (const unsigned char*)aes_256_subkeys,
+ MBEDTLS_CIPHER_AES_256_ECB,
+ MBEDTLS_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher ( verbose,
+ "AES 256",
+ aes_256_key,
+ 256,
+ test_message,
+ aes_message_lengths,
+ (const unsigned char*)aes_256_expected_result,
+ MBEDTLS_CIPHER_AES_256_ECB,
+ MBEDTLS_AES_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_DES_C)
+ /* 3DES 2 key */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "3DES 2 key",
+ des3_2key_key,
+ 192,
+ (const unsigned char*)des3_2key_subkeys,
+ MBEDTLS_CIPHER_DES_EDE3_ECB,
+ MBEDTLS_DES3_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher( verbose,
+ "3DES 2 key",
+ des3_2key_key,
+ 192,
+ test_message,
+ des3_message_lengths,
+ (const unsigned char*)des3_2key_expected_result,
+ MBEDTLS_CIPHER_DES_EDE3_ECB,
+ MBEDTLS_DES3_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* 3DES 3 key */
+ if( ( ret = cmac_test_subkeys( verbose,
+ "3DES 3 key",
+ des3_3key_key,
+ 192,
+ (const unsigned char*)des3_3key_subkeys,
+ MBEDTLS_CIPHER_DES_EDE3_ECB,
+ MBEDTLS_DES3_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( ( ret = cmac_test_wth_cipher( verbose,
+ "3DES 3 key",
+ des3_3key_key,
+ 192,
+ test_message,
+ des3_message_lengths,
+ (const unsigned char*)des3_3key_expected_result,
+ MBEDTLS_CIPHER_DES_EDE3_ECB,
+ MBEDTLS_DES3_BLOCK_SIZE,
+ NB_CMAC_TESTS_PER_KEY ) ) != 0 )
+ {
+ return( ret );
+ }
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_AES_C)
+ if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
+ return( ret );
+#endif /* MBEDTLS_AES_C */
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_CMAC_C */
diff --git a/library/version_features.c b/library/version_features.c
index 5d20ba0..0a2f065 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -465,6 +465,9 @@
#if defined(MBEDTLS_CIPHER_C)
"MBEDTLS_CIPHER_C",
#endif /* MBEDTLS_CIPHER_C */
+#if defined(MBEDTLS_CMAC_C)
+ "MBEDTLS_CMAC_C",
+#endif /* MBEDTLS_CMAC_C */
#if defined(MBEDTLS_CTR_DRBG_C)
"MBEDTLS_CTR_DRBG_C",
#endif /* MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c
index 63a3aeb..4812694 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -120,12 +120,14 @@
USAGE_DEV_RANDOM \
"\n"
-#if !defined(MBEDTLS_PK_WRITE_C) || !defined(MBEDTLS_FS_IO) || \
- !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
+#if !defined(MBEDTLS_PK_WRITE_C) || !defined(MBEDTLS_PEM_WRITE_C) || \
+ !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_ENTROPY_C) || \
+ !defined(MBEDTLS_CTR_DRBG_C)
int main( void )
{
mbedtls_printf( "MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO and/or "
- "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
+ "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
+ "MBEDTLS_PEM_WRITE_C"
"not defined.\n" );
return( 0 );
}
@@ -418,4 +420,6 @@
return( ret );
}
-#endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_FS_IO */
+#endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_PEM_WRITE_C && MBEDTLS_FS_IO &&
+ * MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
+
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 8ab32f6..eb578e7 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -1,7 +1,7 @@
/*
* Benchmark demonstration program
*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -61,6 +61,7 @@
#include "mbedtls/camellia.h"
#include "mbedtls/gcm.h"
#include "mbedtls/ccm.h"
+#include "mbedtls/cmac.h"
#include "mbedtls/havege.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/hmac_drbg.h"
@@ -92,13 +93,14 @@
#define OPTIONS \
"md4, md5, ripemd160, sha1, sha256, sha512,\n" \
- "arc4, des3, des, aes_cbc, aes_gcm, aes_ccm, camellia, blowfish,\n" \
+ "arc4, des3, des, camellia, blowfish,\n" \
+ "aes_cbc, aes_gcm, aes_ccm, aes_cmac, des3_cmac,\n" \
"havege, ctr_drbg, hmac_drbg\n" \
"rsa, dhm, ecdsa, ecdh.\n"
#if defined(MBEDTLS_ERROR_C)
#define PRINT_ERROR \
- mbedtls_strerror( ret, ( char * )tmp, sizeof( tmp ) ); \
+ mbedtls_strerror( ret, ( char * )tmp, sizeof( tmp ) ); \
mbedtls_printf( "FAILED: %s\n", tmp );
#else
#define PRINT_ERROR \
@@ -234,7 +236,9 @@
typedef struct {
char md4, md5, ripemd160, sha1, sha256, sha512,
- arc4, des3, des, aes_cbc, aes_gcm, aes_ccm, camellia, blowfish,
+ arc4, des3, des,
+ aes_cbc, aes_gcm, aes_ccm, aes_cmac, des3_cmac,
+ camellia, blowfish,
havege, ctr_drbg, hmac_drbg,
rsa, dhm, ecdsa, ecdh;
} todo_list;
@@ -283,6 +287,10 @@
todo.aes_gcm = 1;
else if( strcmp( argv[i], "aes_ccm" ) == 0 )
todo.aes_ccm = 1;
+ else if( strcmp( argv[i], "aes_cmac" ) == 0 )
+ todo.aes_cmac = 1;
+ else if( strcmp( argv[i], "des3_cmac" ) == 0 )
+ todo.des3_cmac = 1;
else if( strcmp( argv[i], "camellia" ) == 0 )
todo.camellia = 1;
else if( strcmp( argv[i], "blowfish" ) == 0 )
@@ -358,7 +366,8 @@
}
#endif
-#if defined(MBEDTLS_DES_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_DES_C)
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
if( todo.des3 )
{
mbedtls_des3_context des3;
@@ -378,7 +387,25 @@
mbedtls_des_crypt_cbc( &des, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
mbedtls_des_free( &des );
}
-#endif
+
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#if defined(MBEDTLS_CMAC_C)
+ if( todo.des3_cmac )
+ {
+ unsigned char output[8];
+ const mbedtls_cipher_info_t *cipher_info;
+
+ memset( buf, 0, sizeof( buf ) );
+ memset( tmp, 0, sizeof( tmp ) );
+
+ cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_DES_EDE3_ECB );
+
+ TIME_AND_TSC( "3DES-CMAC",
+ mbedtls_cipher_cmac( cipher_info, tmp, 192, buf,
+ BUFSIZE, output ) );
+ }
+#endif /* MBEDTLS_CMAC_C */
+#endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -447,7 +474,38 @@
}
}
#endif
-#endif
+#if defined(MBEDTLS_CMAC_C)
+ if( todo.aes_cmac )
+ {
+ unsigned char output[16];
+ const mbedtls_cipher_info_t *cipher_info;
+ mbedtls_cipher_type_t cipher_type;
+ int keysize;
+
+ for( keysize = 128, cipher_type = MBEDTLS_CIPHER_AES_128_ECB;
+ keysize <= 256;
+ keysize += 64, cipher_type++ )
+ {
+ mbedtls_snprintf( title, sizeof( title ), "AES-CMAC-%d", keysize );
+
+ memset( buf, 0, sizeof( buf ) );
+ memset( tmp, 0, sizeof( tmp ) );
+
+ cipher_info = mbedtls_cipher_info_from_type( cipher_type );
+
+ TIME_AND_TSC( title,
+ mbedtls_cipher_cmac( cipher_info, tmp, keysize,
+ buf, BUFSIZE, output ) );
+ }
+
+ memset( buf, 0, sizeof( buf ) );
+ memset( tmp, 0, sizeof( tmp ) );
+ TIME_AND_TSC( "AES-CMAC-PRF-128",
+ mbedtls_aes_cmac_prf_128( tmp, 16, buf, BUFSIZE,
+ output ) );
+ }
+#endif /* MBEDTLS_CMAC_C */
+#endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_CAMELLIA_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
if( todo.camellia )
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 89c6616..1941ad0 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -32,6 +32,7 @@
#include "mbedtls/dhm.h"
#include "mbedtls/gcm.h"
#include "mbedtls/ccm.h"
+#include "mbedtls/cmac.h"
#include "mbedtls/md2.h"
#include "mbedtls/md4.h"
#include "mbedtls/md5.h"
@@ -277,6 +278,14 @@
suites_tested++;
#endif
+#if defined(MBEDTLS_CMAC_C)
+ if( ( mbedtls_cmac_self_test( v ) ) != 0 )
+ {
+ suites_failed++;
+ }
+ suites_tested++;
+#endif
+
#if defined(MBEDTLS_BASE64_C)
if( mbedtls_base64_self_test( v ) != 0 )
{
diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c
index 5cafb80..30df216 100644
--- a/programs/x509/cert_req.c
+++ b/programs/x509/cert_req.c
@@ -34,7 +34,8 @@
#if !defined(MBEDTLS_X509_CSR_WRITE_C) || !defined(MBEDTLS_FS_IO) || \
!defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_SHA256_C) || \
- !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
+ !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
+ !defined(MBEDTLS_PEM_WRITE_C)
int main( void )
{
mbedtls_printf( "MBEDTLS_X509_CSR_WRITE_C and/or MBEDTLS_FS_IO and/or "
@@ -341,4 +342,4 @@
return( ret );
}
#endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
- MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
+ MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_WRITE_C */
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 7907d82..66e5f1d 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -32,10 +32,11 @@
#define mbedtls_printf printf
#endif
-#if !defined(MBEDTLS_X509_CRT_WRITE_C) || \
- !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
- !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
- !defined(MBEDTLS_ERROR_C) || !defined(MBEDTLS_SHA256_C)
+#if !defined(MBEDTLS_X509_CRT_WRITE_C) || \
+ !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
+ !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
+ !defined(MBEDTLS_ERROR_C) || !defined(MBEDTLS_SHA256_C) || \
+ !defined(MBEDTLS_PEM_WRITE_C)
int main( void )
{
mbedtls_printf( "MBEDTLS_X509_CRT_WRITE_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
@@ -664,4 +665,4 @@
}
#endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
- MBEDTLS_ERROR_C */
+ MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */
diff --git a/tests/Makefile b/tests/Makefile
index b86702c..4787f25 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -50,6 +50,7 @@
test_suite_arc4$(EXEXT) test_suite_asn1write$(EXEXT) \
test_suite_base64$(EXEXT) test_suite_blowfish$(EXEXT) \
test_suite_camellia$(EXEXT) test_suite_ccm$(EXEXT) \
+ test_suite_cmac$(EXEXT) \
test_suite_cipher.aes$(EXEXT) \
test_suite_cipher.arc4$(EXEXT) test_suite_cipher.ccm$(EXEXT) \
test_suite_cipher.gcm$(EXEXT) \
@@ -236,6 +237,10 @@
echo " CC $<"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+test_suite_cmac$(EXEXT): test_suite_cmac.c $(DEP)
+ echo " CC $<"
+ $(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
test_suite_cipher.aes$(EXEXT): test_suite_cipher.aes.c $(DEP)
echo " CC $<"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index afbcaff..ee0df0c 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -181,6 +181,12 @@
echo "GNUTLS_LEGACY_CLI: $GNUTLS_LEGACY_CLI"
echo "GNUTLS_LEGACY_SERV: $GNUTLS_LEGACY_SERV"
+# To avoid setting OpenSSL and GnuTLS for each call to compat.sh and ssl-opt.sh
+# we just export the variables they require
+export OPENSSL_CMD="$OPENSSL"
+export GNUTLS_CLI="$GNUTLS_CLI"
+export GNUTLS_SERV="$GNUTLS_SERV"
+
# Make sure the tools we need are available.
check_tools "$OPENSSL" "$OPENSSL_LEGACY" "$GNUTLS_CLI" "$GNUTLS_SERV" \
"$GNUTLS_LEGACY_CLI" "$GNUTLS_LEGACY_SERV" "doxygen" "dot" \
diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh
index e8b6164..b405871 100755
--- a/tests/scripts/basic-build-test.sh
+++ b/tests/scripts/basic-build-test.sh
@@ -36,11 +36,30 @@
exit 1
fi
+: ${OPENSSL:="openssl"}
+: ${OPENSSL_LEGACY:="$OPENSSL"}
+: ${GNUTLS_CLI:="gnutls-cli"}
+: ${GNUTLS_SERV:="gnutls-serv"}
+: ${GNUTLS_LEGACY_CLI:="$GNUTLS_CLI"}
+: ${GNUTLS_LEGACY_SERV:="$GNUTLS_SERV"}
+
+# To avoid setting OpenSSL and GnuTLS for each call to compat.sh and ssl-opt.sh
+# we just export the variables they require
+export OPENSSL_CMD="$OPENSSL"
+export GNUTLS_CLI="$GNUTLS_CLI"
+export GNUTLS_SERV="$GNUTLS_SERV"
+
CONFIG_H='include/mbedtls/config.h'
CONFIG_BAK="$CONFIG_H.bak"
# Step 0 - print build environment info
-scripts/output_env.sh
+OPENSSL="$OPENSSL" \
+ OPENSSL_LEGACY="$OPENSSL_LEGACY" \
+ GNUTLS_CLI="$GNUTLS_CLI" \
+ GNUTLS_SERV="$GNUTLS_SERV" \
+ GNUTLS_LEGACY_CLI="$GNUTLS_LEGACY_CLI" \
+ GNUTLS_LEGACY_SERV="$GNUTLS_LEGACY_SERV" \
+ scripts/output_env.sh
echo
# Step 1 - Make and instrumented build for code coverage
@@ -65,7 +84,15 @@
echo
# Step 2c - Compatibility tests
-sh compat.sh |tee compat-test-$TEST_OUTPUT
+sh compat.sh -m 'tls1 tls1_1 tls1_2 dtls1 dtls1_2' | \
+ tee compat-test-$TEST_OUTPUT
+OPENSSL_CMD="$OPENSSL_LEGACY" \
+ sh compat.sh -m 'ssl3' |tee -a compat-test-$TEST_OUTPUT
+OPENSSL_CMD="$OPENSSL_LEGACY" \
+ GNUTLS_CLI="$GNUTLS_LEGACY_CLI" \
+ GNUTLS_SERV="$GNUTLS_LEGACY_SERV" \
+ sh compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES\|RC4\|ARCFOUR' | \
+ tee -a compat-test-$TEST_OUTPUT
echo
# Step 3 - Process the coverage report
@@ -128,9 +155,9 @@
# Step 4c - System Compatibility tests
echo "System/Compatibility tests - tests/compat.sh"
-PASSED_TESTS=$(tail -n5 compat-test-$TEST_OUTPUT|sed -n -e 's/.* (\([0-9]*\) \/ [0-9]* tests ([0-9]* skipped))$/\1/p')
-SKIPPED_TESTS=$(tail -n5 compat-test-$TEST_OUTPUT|sed -n -e 's/.* ([0-9]* \/ [0-9]* tests (\([0-9]*\) skipped))$/\1/p')
-EXED_TESTS=$(tail -n5 compat-test-$TEST_OUTPUT|sed -n -e 's/.* ([0-9]* \/ \([0-9]*\) tests ([0-9]* skipped))$/\1/p')
+PASSED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* (\([0-9]*\) \/ [0-9]* tests ([0-9]* skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
+SKIPPED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* ([0-9]* \/ [0-9]* tests (\([0-9]*\) skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
+EXED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* ([0-9]* \/ \([0-9]*\) tests ([0-9]* skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
FAILED_TESTS=$(($EXED_TESTS - $PASSED_TESTS))
echo "Passed : $PASSED_TESTS"
diff --git a/tests/scripts/yotta-build.sh b/tests/scripts/yotta-build.sh
index 19cc576..4bae34a 100755
--- a/tests/scripts/yotta-build.sh
+++ b/tests/scripts/yotta-build.sh
@@ -1,12 +1,26 @@
#!/bin/sh
-# Do test builds of the yotta module for all supported targets
+# yotta-build.sh
+#
+# This file is part of mbed TLS (https://tls.mbed.org)
+#
+# Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
+#
+# Purpose
+#
+# To run test builds of the yotta module for all supported targets.
set -eu
-yotta/create-module.sh
-cd yotta/module
-yt update || true # needs network
+check_tools()
+{
+ for TOOL in "$@"; do
+ if ! `hash "$TOOL" >/dev/null 2>&1`; then
+ echo "$TOOL not found!" >&2
+ exit 1
+ fi
+ done
+}
yotta_build()
{
@@ -19,22 +33,29 @@
yt -t $TARGET build -d
}
+# Make sure the tools we need are available.
+check_tools "arm-none-eabi-gcc" "armcc" "yotta"
+
+yotta/create-module.sh
+cd yotta/module
+yt update || true # needs network
+
if uname -a | grep 'Linux.*x86' >/dev/null; then
yotta_build x86-linux-native
fi
if uname -a | grep 'Darwin.*x86' >/dev/null; then
yotta_build x86-osx-native
fi
-if which armcc >/dev/null && armcc --help >/dev/null 2>&1; then
- yotta_build frdm-k64f-armcc
- #yotta_build nordic-nrf51822-16k-armcc
-fi
-if which arm-none-eabi-gcc >/dev/null; then
- yotta_build frdm-k64f-gcc
- #yotta_build st-nucleo-f401re-gcc # dirent
- #yotta_build stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4
- #yotta_build nordic-nrf51822-16k-gcc # fails in minar-platform
- #yotta_build bbc-microbit-classic-gcc # fails in minar-platform
- #yotta_build st-stm32f439zi-gcc # fails in mbed-hal-st-stm32f4
- #yotta_build st-stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4
-fi
+
+# armcc build tests.
+yotta_build frdm-k64f-armcc
+#yotta_build nordic-nrf51822-16k-armcc
+
+# arm-none-eabi-gcc build tests.
+yotta_build frdm-k64f-gcc
+#yotta_build st-nucleo-f401re-gcc # dirent
+#yotta_build stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4
+#yotta_build nordic-nrf51822-16k-gcc # fails in minar-platform
+#yotta_build bbc-microbit-classic-gcc # fails in minar-platform
+#yotta_build st-stm32f439zi-gcc # fails in mbed-hal-st-stm32f4
+#yotta_build st-stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4
diff --git a/tests/suites/test_suite_aes.function b/tests/suites/test_suite_aes.function
index 97bf51b..c5f0eaa 100644
--- a/tests/suites/test_suite_aes.function
+++ b/tests/suites/test_suite_aes.function
@@ -292,6 +292,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void aes_selftest()
{
- TEST_ASSERT( mbedtls_aes_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_aes_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_arc4.function b/tests/suites/test_suite_arc4.function
index 3da7d88..a4b401b 100644
--- a/tests/suites/test_suite_arc4.function
+++ b/tests/suites/test_suite_arc4.function
@@ -41,6 +41,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void arc4_selftest()
{
- TEST_ASSERT( mbedtls_arc4_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_arc4_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_base64.function b/tests/suites/test_suite_base64.function
index ab6d88c..77fa7fd 100644
--- a/tests/suites/test_suite_base64.function
+++ b/tests/suites/test_suite_base64.function
@@ -119,6 +119,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void base64_selftest()
{
- TEST_ASSERT( mbedtls_base64_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_base64_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_camellia.function b/tests/suites/test_suite_camellia.function
index 8c69a96..9df6482 100644
--- a/tests/suites/test_suite_camellia.function
+++ b/tests/suites/test_suite_camellia.function
@@ -224,6 +224,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void camellia_selftest()
{
- TEST_ASSERT( mbedtls_camellia_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_camellia_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_ccm.function b/tests/suites/test_suite_ccm.function
index 13371eb..2f5c77c 100644
--- a/tests/suites/test_suite_ccm.function
+++ b/tests/suites/test_suite_ccm.function
@@ -10,7 +10,7 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST:MBEDTLS_AES_C */
void mbedtls_ccm_self_test( )
{
- TEST_ASSERT( mbedtls_ccm_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_ccm_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_cmac.data b/tests/suites/test_suite_cmac.data
new file mode 100644
index 0000000..a913ffd
--- /dev/null
+++ b/tests/suites/test_suite_cmac.data
@@ -0,0 +1,27 @@
+CMAC self test
+mbedtls_cmac_self_test:
+
+CMAC init #1 AES-128: OK
+depends_on:MBEDTLS_AES_C
+mbedtls_cmac_setkey:MBEDTLS_CIPHER_AES_128_ECB:128:0
+
+CMAC init #2 AES-192: OK
+depends_on:MBEDTLS_AES_C
+mbedtls_cmac_setkey:MBEDTLS_CIPHER_AES_192_ECB:192:0
+
+CMAC init #3 AES-256: OK
+depends_on:MBEDTLS_AES_C
+mbedtls_cmac_setkey:MBEDTLS_CIPHER_AES_256_ECB:256:0
+
+CMAC init #4 3DES : OK
+depends_on:MBEDTLS_DES_C
+mbedtls_cmac_setkey:MBEDTLS_CIPHER_DES_EDE3_ECB:192:0
+
+CMAC init #5 AES-224: bad key size
+depends_on:MBEDTLS_AES_C
+mbedtls_cmac_setkey:MBEDTLS_CIPHER_ID_AES:224:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+CMAC init #6 Camellia: wrong cipher
+depends_on:MBEDTLS_CAMELLIA_C
+mbedtls_cmac_setkey:MBEDTLS_CIPHER_ID_CAMELLIA:128:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
diff --git a/tests/suites/test_suite_cmac.function b/tests/suites/test_suite_cmac.function
new file mode 100644
index 0000000..3b23b52
--- /dev/null
+++ b/tests/suites/test_suite_cmac.function
@@ -0,0 +1,37 @@
+/* BEGIN_HEADER */
+#include "mbedtls/cipher.h"
+#include "mbedtls/cmac.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_CMAC_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
+void mbedtls_cmac_self_test( )
+{
+ TEST_ASSERT( mbedtls_cmac_self_test( 1 ) == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_cmac_setkey( int cipher_type, int key_size,
+ int result )
+{
+ const mbedtls_cipher_info_t *cipher_info;
+ unsigned char key[32];
+ unsigned char buf[16];
+ unsigned char tmp[16];
+
+ memset( key, 0x2A, sizeof( key ) );
+ TEST_ASSERT( (unsigned) key_size <= 8 * sizeof( key ) );
+
+ TEST_ASSERT( ( cipher_info = mbedtls_cipher_info_from_type( cipher_type ) )
+ != NULL );
+
+ TEST_ASSERT( result == mbedtls_cipher_cmac( cipher_info, key, key_size,
+ buf, 16, tmp ) );
+}
+/* END_CASE */
+
diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function
index 3c7873b..3acfb8b 100644
--- a/tests/suites/test_suite_ctr_drbg.function
+++ b/tests/suites/test_suite_ctr_drbg.function
@@ -216,6 +216,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void ctr_drbg_selftest( )
{
- TEST_ASSERT( mbedtls_ctr_drbg_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_ctr_drbg_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_des.function b/tests/suites/test_suite_des.function
index aecd419..2e73a77 100644
--- a/tests/suites/test_suite_des.function
+++ b/tests/suites/test_suite_des.function
@@ -362,6 +362,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void des_selftest()
{
- TEST_ASSERT( mbedtls_des_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_des_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index 002c20b..b9b8e19 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -123,6 +123,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void dhm_selftest()
{
- TEST_ASSERT( mbedtls_dhm_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_dhm_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_ecjpake.function b/tests/suites/test_suite_ecjpake.function
index 8d867b7..11cf8dc 100644
--- a/tests/suites/test_suite_ecjpake.function
+++ b/tests/suites/test_suite_ecjpake.function
@@ -101,7 +101,7 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void ecjpake_selftest()
{
- TEST_ASSERT( mbedtls_ecjpake_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_ecjpake_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index eee6486..afe61ec 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -507,6 +507,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void ecp_selftest()
{
- TEST_ASSERT( mbedtls_ecp_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_ecp_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index 5b97cad..97a21bc 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -380,6 +380,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void entropy_selftest( int result )
{
- TEST_ASSERT( mbedtls_entropy_self_test( 0 ) == result );
+ TEST_ASSERT( mbedtls_entropy_self_test( 1 ) == result );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function
index 9d841dc..56c7e18 100644
--- a/tests/suites/test_suite_gcm.function
+++ b/tests/suites/test_suite_gcm.function
@@ -119,6 +119,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void gcm_selftest()
{
- TEST_ASSERT( mbedtls_gcm_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_gcm_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_hmac_drbg.function b/tests/suites/test_suite_hmac_drbg.function
index 3cc9642..5209470 100644
--- a/tests/suites/test_suite_hmac_drbg.function
+++ b/tests/suites/test_suite_hmac_drbg.function
@@ -314,6 +314,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void hmac_drbg_selftest( )
{
- TEST_ASSERT( mbedtls_hmac_drbg_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_hmac_drbg_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_mdx.function b/tests/suites/test_suite_mdx.function
index 3d23363..9d0ee47 100644
--- a/tests/suites/test_suite_mdx.function
+++ b/tests/suites/test_suite_mdx.function
@@ -88,27 +88,27 @@
/* BEGIN_CASE depends_on:MBEDTLS_MD2_C:MBEDTLS_SELF_TEST */
void md2_selftest()
{
- TEST_ASSERT( mbedtls_md2_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_md2_self_test( 1 ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_MD4_C:MBEDTLS_SELF_TEST */
void md4_selftest()
{
- TEST_ASSERT( mbedtls_md4_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_md4_self_test( 1 ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_MD5_C:MBEDTLS_SELF_TEST */
void md5_selftest()
{
- TEST_ASSERT( mbedtls_md5_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_md5_self_test( 1 ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_RIPEMD160_C:MBEDTLS_SELF_TEST */
void ripemd160_selftest()
{
- TEST_ASSERT( mbedtls_ripemd160_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_ripemd160_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_memory_buffer_alloc.function b/tests/suites/test_suite_memory_buffer_alloc.function
index 04dd68b..a0c70d8 100644
--- a/tests/suites/test_suite_memory_buffer_alloc.function
+++ b/tests/suites/test_suite_memory_buffer_alloc.function
@@ -25,7 +25,7 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void mbedtls_memory_buffer_alloc_self_test( )
{
- TEST_ASSERT( mbedtls_memory_buffer_alloc_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_memory_buffer_alloc_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index e5d0850..b94c889 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -877,6 +877,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void mpi_selftest()
{
- TEST_ASSERT( mbedtls_mpi_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_mpi_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_pkcs5.function b/tests/suites/test_suite_pkcs5.function
index b1f796e..8fabec0 100644
--- a/tests/suites/test_suite_pkcs5.function
+++ b/tests/suites/test_suite_pkcs5.function
@@ -82,6 +82,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void pkcs5_selftest( )
{
- TEST_ASSERT( mbedtls_pkcs5_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_pkcs5_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_rsa.function b/tests/suites/test_suite_rsa.function
index 59cbb5c..8837e3a 100644
--- a/tests/suites/test_suite_rsa.function
+++ b/tests/suites/test_suite_rsa.function
@@ -690,6 +690,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void rsa_selftest()
{
- TEST_ASSERT( mbedtls_rsa_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_rsa_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_shax.function b/tests/suites/test_suite_shax.function
index ec326fc..6b3ee9c 100644
--- a/tests/suites/test_suite_shax.function
+++ b/tests/suites/test_suite_shax.function
@@ -112,20 +112,20 @@
/* BEGIN_CASE depends_on:MBEDTLS_SHA1_C:MBEDTLS_SELF_TEST */
void sha1_selftest()
{
- TEST_ASSERT( mbedtls_sha1_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_sha1_self_test( 1 ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C:MBEDTLS_SELF_TEST */
void sha256_selftest()
{
- TEST_ASSERT( mbedtls_sha256_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_sha256_self_test( 1 ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SHA512_C:MBEDTLS_SELF_TEST */
void sha512_selftest()
{
- TEST_ASSERT( mbedtls_sha512_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_sha512_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_timing.function b/tests/suites/test_suite_timing.function
index 74f711c..5882f85 100644
--- a/tests/suites/test_suite_timing.function
+++ b/tests/suites/test_suite_timing.function
@@ -10,6 +10,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void timing_selftest()
{
- TEST_ASSERT( mbedtls_timing_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_timing_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index c476ec5..2affab7 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -623,6 +623,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_SELF_TEST */
void x509_selftest()
{
- TEST_ASSERT( mbedtls_x509_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_x509_self_test( 1 ) == 0 );
}
/* END_CASE */
diff --git a/tests/suites/test_suite_xtea.function b/tests/suites/test_suite_xtea.function
index e294a9b..cbc714a 100644
--- a/tests/suites/test_suite_xtea.function
+++ b/tests/suites/test_suite_xtea.function
@@ -124,6 +124,6 @@
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void xtea_selftest()
{
- TEST_ASSERT( mbedtls_xtea_self_test( 0 ) == 0 );
+ TEST_ASSERT( mbedtls_xtea_self_test( 1 ) == 0 );
}
/* END_CASE */