Merge branch fixing date validity in X.509
diff --git a/ChangeLog b/ChangeLog
index a63957c..9f82b69 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,21 @@
      a contribution from Tobias Tangemann. #541
    * Fixed cert_app sample program for debug output and for use when no root
      certificates are provided.
+   * Fix conditional statement that would cause a 1 byte overread in
+     mbedtls_asn1_get_int(). Found and fixed by Guido Vranken. #599
+   * Fixed pthread implementation to avoid unintended double initialisations
+     and double frees. (found by Niklas Amnebratt)
+   * 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.
+   * Fix mbedtls_x509_get_sig() to update the ASN1 type in the mbedtls_x509_buf
+     data structure until after error checks are successful. Found by
+     subramanyam-c. #622
+   * Fix documentation and implementation missmatch for function arguments of
+     mbedtls_gcm_finish(). Found by cmiatpaar. #602
+   * Guarantee that P>Q at RSA key generation. Found by inestlerode. #558
+   * Fix potential byte overread when verifying malformed SERVER_HELLO in
+     ssl_parse_hello_verify_request() for DTLS. Found by Guido Vranken.
    * Fix check for validity of date when parsing in mbedtls_x509_get_time().
      Found by subramanyam-c.
 
@@ -46,6 +63,8 @@
      naming collision in projects which also have files with the common name
      net.c. For consistency, the corresponding header file, net.h, is marked as
      deprecated, and its contents moved to net_sockets.h.
+   * Changed the strategy for X.509 certificate parsing and validation, to no
+     longer disregard certificates with unrecognised fields.
 
 = mbed TLS 2.3.0 branch released 2016-06-28
 
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..75e0b97
--- /dev/null
+++ b/include/mbedtls/cmac.h
@@ -0,0 +1,166 @@
+/**
+ * \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;
+};
+
+/**
+ * \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/gcm.h b/include/mbedtls/gcm.h
index 6743ac9..1b77aae 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -190,8 +190,8 @@
  *                  16 bytes.
  *
  * \param ctx       GCM context
- * \param tag       buffer for holding the tag (may be NULL if tag_len is 0)
- * \param tag_len   length of the tag to generate
+ * \param tag       buffer for holding the tag
+ * \param tag_len   length of the tag to generate (must be at least 4)
  *
  * \return          0 if successful or MBEDTLS_ERR_GCM_BAD_INPUT
  */
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/include/mbedtls/x509_csr.h b/include/mbedtls/x509_csr.h
index 7a9c2e0..fe9843c 100644
--- a/include/mbedtls/x509_csr.h
+++ b/include/mbedtls/x509_csr.h
@@ -282,7 +282,7 @@
  *
  * \note            f_rng may be NULL if RSA is used for signature and the
  *                  signature is made offline (otherwise f_rng is desirable
- *                  for couermeasures against timing attacks).
+ *                  for countermeasures against timing attacks).
  *                  ECDSA signatures always require a non-NULL f_rng.
  */
 int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
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/asn1parse.c b/library/asn1parse.c
index ffa2f52..4dd65c0 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -153,7 +153,7 @@
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
         return( ret );
 
-    if( len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+    if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 )
         return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
 
     *val = 0;
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..ee2fe05
--- /dev/null
+++ b/library/cmac.c
@@ -0,0 +1,1033 @@
+/*
+ * \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 ) );
+
+    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 there data still to process from the last call, that's greater in
+     * size 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;
+        }
+
+        input += block_size - cmac_ctx->unprocessed_len;
+        ilen -= block_size - 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;
+    }
+
+    /* If there is data left over that wasn't aligned to a block */
+    if( ilen > 0 )
+    {
+        memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
+                input,
+                ilen );
+        cmac_ctx->unprocessed_len += ilen;
+    }
+
+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->unprocessed_len < block_size )
+    {
+        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->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 ) );
+
+    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 );
+    }
+
+    for( i = 0; i < num_tests; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  %s CMAC subkey #%u: ", testname, i + 1 );
+
+        mbedtls_cipher_init( &ctx );
+
+        if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "test execution failed\n" );
+
+            goto cleanup;
+        }
+
+        if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
+                                       MBEDTLS_ENCRYPT ) ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "test execution failed\n" );
+
+            goto cleanup;
+        }
+
+        ret = cmac_generate_subkeys( &ctx, K1, K2 );
+        if( ret != 0 )
+        {
+           if( verbose != 0 )
+                mbedtls_printf( "failed\n" );
+
+            goto cleanup;
+        }
+
+        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 cleanup;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+
+        mbedtls_cipher_free( &ctx );
+    }
+
+    goto exit;
+
+cleanup:
+    mbedtls_cipher_free( &ctx );
+
+exit:
+    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/gcm.c b/library/gcm.c
index aaacf97..f1210c5 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -415,8 +415,7 @@
     if( tag_len > 16 || tag_len < 4 )
         return( MBEDTLS_ERR_GCM_BAD_INPUT );
 
-    if( tag_len != 0 )
-        memcpy( tag, ctx->base_ectr, tag_len );
+    memcpy( tag, ctx->base_ectr, tag_len );
 
     if( orig_len || orig_add_len )
     {
diff --git a/library/rsa.c b/library/rsa.c
index 7a33689..40ef2a9 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -102,7 +102,10 @@
     if( f_rng == NULL || nbits < 128 || exponent < 3 )
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
-    mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); 
+    if( nbits % 2 )
+        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+
+    mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 );
     mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G );
 
     /*
@@ -116,16 +119,8 @@
         MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0,
                                 f_rng, p_rng ) );
 
-        if( nbits % 2 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, ( nbits >> 1 ) + 1, 0,
+        MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0,
                                 f_rng, p_rng ) );
-        }
-        else
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0,
-                                f_rng, p_rng ) );
-        }
 
         if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
             continue;
@@ -134,6 +129,9 @@
         if( mbedtls_mpi_bitlen( &ctx->N ) != nbits )
             continue;
 
+        if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
+                                mbedtls_mpi_swap( &ctx->P, &ctx->Q );
+
         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) );
diff --git a/library/sha256.c b/library/sha256.c
index 4e82c0b..ad25d38 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -41,7 +41,10 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
+#include <stdlib.h>
 #define mbedtls_printf printf
+#define mbedtls_calloc    calloc
+#define mbedtls_free       free
 #endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST */
 
@@ -389,10 +392,19 @@
 int mbedtls_sha256_self_test( int verbose )
 {
     int i, j, k, buflen, ret = 0;
-    unsigned char buf[1024];
+    unsigned char *buf;
     unsigned char sha256sum[32];
     mbedtls_sha256_context ctx;
 
+    buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
+    if( NULL == buf )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "Buffer allocation failed\n" );
+
+        return( 1 );
+    }
+
     mbedtls_sha256_init( &ctx );
 
     for( i = 0; i < 6; i++ )
@@ -436,6 +448,7 @@
 
 exit:
     mbedtls_sha256_free( &ctx );
+    mbedtls_free( buf );
 
     return( ret );
 }
diff --git a/library/sha512.c b/library/sha512.c
index 0f9e1e5..724522a 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -47,7 +47,10 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
+#include <stdlib.h>
 #define mbedtls_printf printf
+#define mbedtls_calloc    calloc
+#define mbedtls_free       free
 #endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST */
 
@@ -445,10 +448,19 @@
 int mbedtls_sha512_self_test( int verbose )
 {
     int i, j, k, buflen, ret = 0;
-    unsigned char buf[1024];
+    unsigned char *buf;
     unsigned char sha512sum[64];
     mbedtls_sha512_context ctx;
 
+    buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
+    if( NULL == buf )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "Buffer allocation failed\n" );
+
+        return( 1 );
+    }
+
     mbedtls_sha512_init( &ctx );
 
     for( i = 0; i < 6; i++ )
@@ -492,6 +504,7 @@
 
 exit:
     mbedtls_sha512_free( &ctx );
+    mbedtls_free( buf );
 
     return( ret );
 }
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 29a3943..39fcd6c 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -1355,6 +1355,15 @@
     cookie_len = *p++;
     MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len );
 
+    if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "cookie length does not match incoming message size" ) );
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                    MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
     mbedtls_free( ssl->handshake->verify_cookie );
 
     ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 505bb6c..df7b734 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -49,8 +49,7 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
-    defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
 #include "mbedtls/oid.h"
 #endif
 
@@ -4347,7 +4346,7 @@
 
         ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert,
                                   ssl->in_msg + i, n );
-        if( ret != 0 )
+        if( 0 != ret && ( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND ) != ret )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
             return( ret );
diff --git a/library/threading.c b/library/threading.c
index 1b6d9cd..83ec01a 100644
--- a/library/threading.c
+++ b/library/threading.c
@@ -32,7 +32,7 @@
 #if defined(MBEDTLS_THREADING_PTHREAD)
 static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
 {
-    if( mutex == NULL )
+    if( mutex == NULL || mutex->is_valid )
         return;
 
     mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0;
@@ -40,10 +40,11 @@
 
 static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex )
 {
-    if( mutex == NULL )
+    if( mutex == NULL || !mutex->is_valid )
         return;
 
     (void) pthread_mutex_destroy( &mutex->mutex );
+    mutex->is_valid = 0;
 }
 
 static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex )
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/library/x509.c b/library/x509.c
index a79562b..fad390d 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -591,16 +591,18 @@
 {
     int ret;
     size_t len;
+    int tag_type;
 
     if( ( end - *p ) < 1 )
         return( MBEDTLS_ERR_X509_INVALID_SIGNATURE +
                 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
 
-    sig->tag = **p;
+    tag_type = **p;
 
     if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
         return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret );
 
+    sig->tag = tag_type;
     sig->len = len;
     sig->p = *p;
 
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index 48b97ce..875d0b08 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -36,7 +36,8 @@
 #if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
     defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) && \
-    defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C)
+    defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C) && \
+    defined(MBEDTLS_SHA1_C)
 #include "mbedtls/net_sockets.h"
 #include "mbedtls/aes.h"
 #include "mbedtls/dhm.h"
@@ -55,7 +56,8 @@
 #if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) ||     \
     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) ||  \
     !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) ||    \
-    !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C)
+    !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \
+    !defined(MBEDTLS_SHA1_C)
 int main( void )
 {
     mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_C "
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index 173a29d..8bf2b1b 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -36,7 +36,8 @@
 #if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
     defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) && \
-    defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C)
+    defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C) && \
+    defined(MBEDTLS_SHA1_C)
 #include "mbedtls/net_sockets.h"
 #include "mbedtls/aes.h"
 #include "mbedtls/dhm.h"
@@ -55,7 +56,8 @@
 #if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) ||     \
     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) ||  \
     !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) ||    \
-    !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C)
+    !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \
+    !defined(MBEDTLS_SHA1_C)
 int main( void )
 {
     mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_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/CMakeLists.txt b/tests/CMakeLists.txt
index 13659de..21583c4 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -61,6 +61,7 @@
 add_test_suite(cipher cipher.gcm)
 add_test_suite(cipher cipher.null)
 add_test_suite(cipher cipher.padding)
+add_test_suite(cmac)
 add_test_suite(ctr_drbg)
 add_test_suite(debug)
 add_test_suite(des)
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 ee0df0c..6b33960 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -32,6 +32,7 @@
 
 MEMORY=0
 FORCE=0
+RELEASE=0
 
 # Default commands, can be overriden by the environment
 : ${OPENSSL:="openssl"}
@@ -48,6 +49,8 @@
     printf "  -h|--help\t\tPrint this help.\n"
     printf "  -m|--memory\t\tAdditional optional memory tests.\n"
     printf "  -f|--force\t\tForce the tests to overwrite any modified files.\n"
+    printf "  -s|--seed\t\tInteger seed value to use for this test run.\n"
+    printf "  -r|--release-test\t\tRun this script in release mode. This fixes the seed value to 1.\n"
     printf "     --out-of-source-dir=<path>\t\tDirectory used for CMake out-of-source build tests."
     printf "     --openssl=<OpenSSL_path>\t\tPath to OpenSSL executable to use for most tests.\n"
     printf "     --openssl-legacy=<OpenSSL_path>\t\tPath to OpenSSL executable to use for legacy tests e.g. SSLv3.\n"
@@ -106,6 +109,13 @@
         --force|-f)
             FORCE=1
             ;;
+        --seed|-s)
+            shift
+            SEED="$1"
+            ;;
+        --release-test|-r)
+            RELEASE=1
+            ;;
         --out-of-source-dir)
             shift
             OUT_OF_SOURCE_DIR="$1"
@@ -171,9 +181,15 @@
     fi
 fi
 
+if [ $RELEASE -eq 1 ]; then
+    # Fix the seed value to 1 to ensure that the tests are deterministic.
+    SEED=1
+fi
+
 msg "info: $0 configuration"
 echo "MEMORY: $MEMORY"
 echo "FORCE: $FORCE"
+echo "SEED: ${SEED-"UNSET"}"
 echo "OPENSSL: $OPENSSL"
 echo "OPENSSL_LEGACY: $OPENSSL_LEGACY"
 echo "GNUTLS_CLI: $GNUTLS_CLI"
@@ -187,6 +203,9 @@
 export GNUTLS_CLI="$GNUTLS_CLI"
 export GNUTLS_SERV="$GNUTLS_SERV"
 
+# Avoid passing --seed flag in every call to ssl-opt.sh
+[ ! -z ${SEED+set} ] && export SEED
+
 # 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/ssl-opt.sh b/tests/ssl-opt.sh
index d9c45cd..429d9cd 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -58,6 +58,7 @@
     printf "  -n|--number\tExecute only numbered test (comma-separated, e.g. '245,256')\n"
     printf "  -s|--show-numbers\tShow test numbers in front of test names\n"
     printf "  -p|--preserve-logs\tPreserve logs of successful tests as well\n"
+    printf "     --seed\tInteger seed value to use for this test run\n"
 }
 
 get_options() {
@@ -81,6 +82,9 @@
             -p|--preserve-logs)
                 PRESERVE_LOGS=1
                 ;;
+            --seed)
+                shift; SEED="$1"
+                ;;
             -h|--help)
                 print_usage
                 exit 0
@@ -595,7 +599,7 @@
 # +SRV_PORT will be replaced by either $SRV_PORT or $PXY_PORT later
 P_SRV="$P_SRV server_addr=127.0.0.1 server_port=$SRV_PORT"
 P_CLI="$P_CLI server_addr=127.0.0.1 server_port=+SRV_PORT"
-P_PXY="$P_PXY server_addr=127.0.0.1 server_port=$SRV_PORT listen_addr=127.0.0.1 listen_port=$PXY_PORT"
+P_PXY="$P_PXY server_addr=127.0.0.1 server_port=$SRV_PORT listen_addr=127.0.0.1 listen_port=$PXY_PORT ${SEED:+"seed=$SEED"}"
 O_SRV="$O_SRV -accept $SRV_PORT -dhparam data_files/dhparams.pem"
 O_CLI="$O_CLI -connect localhost:+SRV_PORT"
 G_SRV="$G_SRV -p $SRV_PORT"
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index d12be75..63815df 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -8,16 +8,13 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
 #define mbedtls_fprintf    fprintf
-#define mbedtls_calloc    calloc
+#define mbedtls_snprintf   snprintf
+#define mbedtls_calloc     calloc
 #define mbedtls_free       free
 #define mbedtls_exit       exit
 #define mbedtls_time       time
 #define mbedtls_time_t     time_t
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#define mbedtls_snprintf   snprintf
 #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
 #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
 #endif
@@ -37,6 +34,9 @@
 
 #include <string.h>
 
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+#include <unistd.h>
+#endif
 
 /*----------------------------------------------------------------------------*/
 /* Constants */
@@ -105,6 +105,48 @@
 /*----------------------------------------------------------------------------*/
 /* Helper Functions */
 
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+static int redirect_output( FILE** out_stream, const char* path )
+{
+    int stdout_fd = dup( fileno( *out_stream ) );
+
+    if( stdout_fd == -1 )
+    {
+        return -1;
+    }
+
+    fflush( *out_stream );
+    fclose( *out_stream );
+    *out_stream = fopen( path, "w" );
+
+    if( *out_stream == NULL )
+    {
+        return -1;
+    }
+
+    return stdout_fd;
+}
+
+static int restore_output( FILE** out_stream, int old_fd )
+{
+    fflush( *out_stream );
+    fclose( *out_stream );
+
+    *out_stream = fdopen( old_fd, "w" );
+    if( *out_stream == NULL )
+    {
+        return -1;
+    }
+
+    return 0;
+}
+
+static void close_output( FILE* out_stream )
+{
+    fclose( out_stream );
+}
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
 static int unhexify( unsigned char *obuf, const char *ibuf )
 {
     unsigned char c, c2;
@@ -355,7 +397,8 @@
 {
     test_errors++;
     if( test_errors == 1 )
-        mbedtls_printf( "FAILED\n" );
-    mbedtls_printf( "  %s\n  at line %d, %s\n", test, line_no, filename );
+        mbedtls_fprintf( stdout, "FAILED\n" );
+    mbedtls_fprintf( stdout, "  %s\n  at line %d, %s\n", test, line_no,
+                        filename );
 }
 
diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function
index ac5322e..afff5a4 100644
--- a/tests/suites/main_test.function
+++ b/tests/suites/main_test.function
@@ -7,7 +7,8 @@
     if( (*str)[0] != '"' ||
         (*str)[strlen( *str ) - 1] != '"' )
     {
-        mbedtls_printf( "Expected string (with \"\") for parameter and got: %s\n", *str );
+        mbedtls_fprintf( stderr,
+            "Expected string (with \"\") for parameter and got: %s\n", *str );
         return( -1 );
     }
 
@@ -60,7 +61,8 @@
 
 MAPPING_CODE
 
-    mbedtls_printf( "Expected integer for parameter and got: %s\n", str );
+    mbedtls_fprintf( stderr,
+                    "Expected integer for parameter and got: %s\n", str );
     return( KEY_VALUE_MAPPING_NOT_FOUND );
 }
 
@@ -259,6 +261,7 @@
     char buf[5000];
     char *params[50];
     void *pointer;
+    int stdout_fd = -1;
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
     !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
@@ -343,7 +346,8 @@
         {
             if( unmet_dep_count > 0 )
             {
-                mbedtls_printf("FATAL: Dep count larger than zero at start of loop\n");
+                mbedtls_fprintf( stderr,
+                    "FATAL: Dep count larger than zero at start of loop\n" );
                 mbedtls_exit( MBEDTLS_EXIT_FAILURE );
             }
             unmet_dep_count = 0;
@@ -379,7 +383,7 @@
                         unmet_dependencies[ unmet_dep_count ] = strdup(params[i]);
                         if(  unmet_dependencies[ unmet_dep_count ] == NULL )
                         {
-                            mbedtls_printf("FATAL: Out of memory\n");
+                            mbedtls_fprintf( stderr, "FATAL: Out of memory\n" );
                             mbedtls_exit( MBEDTLS_EXIT_FAILURE );
                         }
                         unmet_dep_count++;
@@ -395,7 +399,32 @@
             if( unmet_dep_count == 0 )
             {
                 test_errors = 0;
+
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+                /* Suppress all output from the library unless we're verbose
+                 * mode
+                 */
+                if( !option_verbose )
+                {
+                    stdout_fd = redirect_output( &stdout, "/dev/null" );
+                    if( stdout_fd == -1 )
+                    {
+                        /* Redirection has failed with no stdout so exit */
+                        exit( 1 );
+                    }
+                }
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
                 ret = dispatch_test( cnt, params );
+
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+                if( !option_verbose && restore_output( &stdout, stdout_fd ) )
+                {
+                        /* Redirection has failed with no stdout so exit */
+                        exit( 1 );
+                }
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
             }
 
             if( unmet_dep_count > 0 || ret == DISPATCH_UNSUPPORTED_SUITE )
@@ -470,6 +499,11 @@
     mbedtls_memory_buffer_alloc_free();
 #endif
 
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+    if( stdout_fd != -1 )
+        close_output( stdout );
+#endif /* __unix__ || __APPLE__ __MACH__ */
+
     return( total_errors != 0 );
 }
 
diff --git a/tests/suites/test_suite_cmac.data b/tests/suites/test_suite_cmac.data
new file mode 100644
index 0000000..70b7609
--- /dev/null
+++ b/tests/suites/test_suite_cmac.data
@@ -0,0 +1,64 @@
+CMAC self test
+mbedtls_cmac_self_test:
+
+CMAC null arguments
+mbedtls_cmac_null_args:
+
+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 AES-0: bad key size
+depends_on:MBEDTLS_AES_C
+mbedtls_cmac_setkey:MBEDTLS_CIPHER_ID_AES:0:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+CMAC init #7 Camellia: wrong cipher
+depends_on:MBEDTLS_CAMELLIA_C
+mbedtls_cmac_setkey:MBEDTLS_CIPHER_ID_CAMELLIA:128:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+CMAC Single Blocks #1 - Empty block, no updates
+mbedtls_cmac_multiple_blocks:MBEDTLS_CIPHER_AES_128_ECB:"2b7e151628aed2a6abf7158809cf4f3c":128:16:"":-1:"":-1:"":-1:"":-1:"bb1d6929e95937287fa37d129b756746"
+
+CMAC Single Blocks #2 - Single 16 byte block
+mbedtls_cmac_multiple_blocks:MBEDTLS_CIPHER_AES_128_ECB:"2b7e151628aed2a6abf7158809cf4f3c":128:16:"6bc1bee22e409f96e93d7e117393172a":16:"":-1:"":-1:"":-1:"070a16b46b4d4144f79bdd9dd04a287c"
+
+CMAC Single Blocks #3 - Single 64 byte block
+mbedtls_cmac_multiple_blocks:MBEDTLS_CIPHER_AES_128_ECB:"2b7e151628aed2a6abf7158809cf4f3c":128:16:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":64:"":-1:"":-1:"":-1:"51f0bebf7e3b9d92fc49741779363cfe"
+
+CMAC Multiple Blocks #1 - Multiple 8 byte blocks
+mbedtls_cmac_multiple_blocks:MBEDTLS_CIPHER_AES_128_ECB:"2b7e151628aed2a6abf7158809cf4f3c":128:16:"6bc1bee22e409f96":8:"e93d7e117393172a":8:"":-1:"":-1:"070a16b46b4d4144f79bdd9dd04a287c"
+
+CMAC Multiple Blocks #2 - Multiple 16 byte blocks
+mbedtls_cmac_multiple_blocks:MBEDTLS_CIPHER_AES_128_ECB:"2b7e151628aed2a6abf7158809cf4f3c":128:16:"6bc1bee22e409f96e93d7e117393172a":16:"ae2d8a571e03ac9c9eb76fac45af8e51":16:"30c81c46a35ce411e5fbc1191a0a52ef":16:"f69f2445df4f9b17ad2b417be66c3710":16:"51f0bebf7e3b9d92fc49741779363cfe"
+
+CMAC Multiple Blocks #3 - Multiple variable sized blocks
+mbedtls_cmac_multiple_blocks:MBEDTLS_CIPHER_AES_128_ECB:"2b7e151628aed2a6abf7158809cf4f3c":128:16:"6bc1bee22e409f96":8:"e93d7e117393172aae2d8a571e03ac9c":16:"9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef":24:"f69f2445df4f9b17ad2b417be66c3710":16:"51f0bebf7e3b9d92fc49741779363cfe"
+
+CMAC Multiple Blocks #4 - Multiple 8 byte blocks with gaps
+mbedtls_cmac_multiple_blocks:MBEDTLS_CIPHER_AES_128_ECB:"2b7e151628aed2a6abf7158809cf4f3c":128:16:"":0:"6bc1bee22e409f96":8:"":0:"e93d7e117393172a":8:"070a16b46b4d4144f79bdd9dd04a287c"
+
+CMAC Multiple Operations, same key #1 - Empty, empty
+mbedtls_cmac_multiple_operations_same_key:MBEDTLS_CIPHER_AES_192_ECB:"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b":192:16:"":-1:"":-1:"":-1:"d17ddf46adaacde531cac483de7a9367":"":-1:"":-1:"":-1:"d17ddf46adaacde531cac483de7a9367"
+
+CMAC Multiple Operations, same key #2 - Empty, 64 byte block
+mbedtls_cmac_multiple_operations_same_key:MBEDTLS_CIPHER_AES_192_ECB:"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b":192:16:"":-1:"":-1:"":-1:"d17ddf46adaacde531cac483de7a9367":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":64:"":-1:"":-1:"a1d5df0eed790f794d77589659f39a11"
+
+CMAC Multiple Operations, same key #3 - variable byte blocks
+mbedtls_cmac_multiple_operations_same_key:MBEDTLS_CIPHER_AES_192_ECB:"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b":192:16:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51":32:"30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":32:"":-1:"a1d5df0eed790f794d77589659f39a11":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51":32:"30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":32:"":-1:"a1d5df0eed790f794d77589659f39a11"
+
diff --git a/tests/suites/test_suite_cmac.function b/tests/suites/test_suite_cmac.function
new file mode 100644
index 0000000..4b31ab2
--- /dev/null
+++ b/tests/suites/test_suite_cmac.function
@@ -0,0 +1,310 @@
+/* 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_null_args( )
+{
+    mbedtls_cipher_context_t ctx;
+    const mbedtls_cipher_info_t *cipher_info;
+    unsigned char test_key[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    unsigned char test_data[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    unsigned char test_output[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+    mbedtls_cipher_init( &ctx );
+
+    /* Test NULL cipher info */
+    TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx, test_data, 16 ) ==
+                                         MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
+    TEST_ASSERT( mbedtls_cipher_setup( &ctx, cipher_info ) == 0 );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_starts( NULL, test_key, 128 ) ==
+                                         MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_starts( &ctx, NULL, 128 ) ==
+                                         MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_update( NULL, test_data, 16 ) ==
+                                         MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx, NULL, 16 ) ==
+                                         MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_finish( NULL, test_output ) ==
+                                         MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_finish( &ctx, NULL ) ==
+                                         MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_reset( NULL ) ==
+                                         MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac( NULL,
+                                      test_key, 128,
+                                      test_data, 16,
+                                      test_output ) ==
+                                            MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac( cipher_info,
+                                      NULL, 128,
+                                      test_data, 16,
+                                      test_output ) ==
+                                            MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac( cipher_info,
+                                      test_key, 128,
+                                      NULL, 16,
+                                      test_output ) ==
+                                            MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_cipher_cmac( cipher_info,
+                                      test_key, 128,
+                                      test_data, 16,
+                                      NULL ) ==
+                                            MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_aes_cmac_prf_128( NULL, 16,
+                                           test_data, 16,
+                                           test_output ) ==
+                                           MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_aes_cmac_prf_128( test_key, 16,
+                                           NULL, 16,
+                                           test_output ) ==
+                                              MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_aes_cmac_prf_128( test_key, 16,
+                                           test_data, 16,
+                                           NULL ) ==
+                                              MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+exit:
+    mbedtls_cipher_free( &ctx );
+}
+/* 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 );
+
+    memset( buf, 0x2A, sizeof( buf ) );
+    TEST_ASSERT( ( result == mbedtls_cipher_cmac( cipher_info, key, key_size,
+                                                buf, 16, tmp ) ) != 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_cmac_multiple_blocks( int cipher_type,
+                                   char *key_string, int keybits,
+                                   int block_size,
+                                   char *block1_string, int block1_len,
+                                   char *block2_string, int block2_len,
+                                   char *block3_string, int block3_len,
+                                   char *block4_string, int block4_len,
+                                   char *expected_result_string )
+{
+    unsigned char key[100];
+    unsigned char block1[100];
+    unsigned char block2[100];
+    unsigned char block3[100];
+    unsigned char block4[100];
+    unsigned char expected_result[100];
+    const mbedtls_cipher_info_t *cipher_info;
+    mbedtls_cipher_context_t ctx;
+    unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+    /* Convert the test parameters to binary data */
+    unhexify( key, key_string );
+    unhexify( block1, block1_string );
+    unhexify( block2, block2_string );
+    unhexify( block3, block3_string );
+    unhexify( block4, block4_string );
+    unhexify( expected_result, expected_result_string );
+
+    mbedtls_cipher_init( &ctx );
+
+    /* Validate the test inputs */
+    TEST_ASSERT( block1_len <= 100 );
+    TEST_ASSERT( block2_len <= 100 );
+    TEST_ASSERT( block3_len <= 100 );
+    TEST_ASSERT( block4_len <= 100 );
+
+    /* Set up */
+    TEST_ASSERT( ( cipher_info = mbedtls_cipher_info_from_type( cipher_type ) )
+                    != NULL );
+
+    TEST_ASSERT( mbedtls_cipher_setup( &ctx, cipher_info ) == 0 );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_starts( &ctx,
+                                             (const unsigned char*)key,
+                                             keybits ) == 0 );
+
+    /* Multiple partial and complete blocks. A negative length means skip the
+     * update operation */
+    if( block1_len >= 0)
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block1,
+                                                 block1_len ) == 0);
+
+    if( block2_len >= 0 )
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block2,
+                                                 block2_len ) == 0);
+
+    if( block3_len >= 0 )
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block3,
+                                                 block3_len ) == 0);
+
+    if( block4_len >= 0 )
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block4,
+                                                 block4_len ) == 0);
+
+    TEST_ASSERT( mbedtls_cipher_cmac_finish( &ctx, output ) == 0 );
+
+    TEST_ASSERT( memcmp( output, expected_result, block_size )  == 0 );
+
+exit:
+    mbedtls_cipher_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_cmac_multiple_operations_same_key( int cipher_type,
+                                   char *key_string, int keybits,
+                                   int block_size,
+                                   char *block_a1_string, int block_a1_len,
+                                   char *block_a2_string, int block_a2_len,
+                                   char *block_a3_string, int block_a3_len,
+                                   char *expected_result_a_string,
+                                   char *block_b1_string, int block_b1_len,
+                                   char *block_b2_string, int block_b2_len,
+                                   char *block_b3_string, int block_b3_len,
+                                   char *expected_result_b_string )
+{
+    unsigned char key[100];
+    unsigned char block_a1[100];
+    unsigned char block_a2[100];
+    unsigned char block_a3[100];
+    unsigned char block_b1[100];
+    unsigned char block_b2[100];
+    unsigned char block_b3[100];
+    unsigned char expected_result_a[100], expected_result_b[100];
+    const mbedtls_cipher_info_t *cipher_info;
+    mbedtls_cipher_context_t ctx;
+    unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+    /* Convert the test parameters to binary data */
+    unhexify( key, key_string );
+    unhexify( block_a1, block_a1_string );
+    unhexify( block_a2, block_a2_string );
+    unhexify( block_a3, block_a3_string );
+
+    unhexify( block_b1, block_b1_string );
+    unhexify( block_b2, block_b2_string );
+    unhexify( block_b3, block_b3_string );
+
+    unhexify( expected_result_a, expected_result_a_string );
+    unhexify( expected_result_b, expected_result_b_string );
+
+    mbedtls_cipher_init( &ctx );
+
+    /* Validate the test inputs */
+    TEST_ASSERT( block_a1_len <= 100 );
+    TEST_ASSERT( block_a2_len <= 100 );
+    TEST_ASSERT( block_a3_len <= 100 );
+
+    TEST_ASSERT( block_b1_len <= 100 );
+    TEST_ASSERT( block_b2_len <= 100 );
+    TEST_ASSERT( block_b3_len <= 100 );
+
+    /* Set up */
+    TEST_ASSERT( ( cipher_info = mbedtls_cipher_info_from_type( cipher_type ) )
+                    != NULL );
+
+    TEST_ASSERT( mbedtls_cipher_setup( &ctx, cipher_info ) == 0 );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_starts( &ctx,
+                                             (const unsigned char*)key,
+                                             keybits ) == 0 );
+
+    /* Sequence A */
+
+    /* Multiple partial and complete blocks. A negative length means skip the
+     * update operation */
+    if( block_a1_len >= 0 )
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block_a1,
+                                                 block_a1_len ) == 0);
+
+    if( block_a2_len >= 0 )
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block_a2,
+                                                 block_a2_len ) == 0);
+
+    if( block_a3_len >= 0 )
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block_a3,
+                                                  block_a3_len ) == 0);
+
+    TEST_ASSERT( mbedtls_cipher_cmac_finish( &ctx, output ) == 0 );
+
+    TEST_ASSERT( memcmp( output, expected_result_a, block_size )  == 0 );
+
+    TEST_ASSERT( mbedtls_cipher_cmac_reset( &ctx ) == 0 );
+
+    /* Sequence B */
+
+    /* Multiple partial and complete blocks. A negative length means skip the
+     * update operation */
+    if( block_b1_len >= 0)
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block_b1,
+                                                 block_b1_len ) == 0);
+
+    if( block_b2_len >= 0 )
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block_b2,
+                                                 block_b2_len ) == 0);
+
+    if( block_b3_len >= 0 )
+        TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx,
+                                                 (unsigned char*)block_b3,
+                                                 block_b3_len ) == 0);
+
+    TEST_ASSERT( mbedtls_cipher_cmac_finish( &ctx, output ) == 0 );
+
+    TEST_ASSERT( memcmp( output, expected_result_b, block_size )  == 0 );
+
+exit:
+    mbedtls_cipher_free( &ctx );
+}
+/* END_CASE */
+
diff --git a/tests/suites/test_suite_rsa.data b/tests/suites/test_suite_rsa.data
index d522332..af16880 100644
--- a/tests/suites/test_suite_rsa.data
+++ b/tests/suites/test_suite_rsa.data
@@ -361,7 +361,7 @@
 mbedtls_rsa_gen_key:2048:3:0
 
 RSA Generate Key - 1025 bit key
-mbedtls_rsa_gen_key:1025:3:0
+mbedtls_rsa_gen_key:1025:3:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSA PKCS1 Encrypt Bad RNG
 depends_on:MBEDTLS_PKCS1_V15
diff --git a/tests/suites/test_suite_rsa.function b/tests/suites/test_suite_rsa.function
index 8837e3a..d48bc85 100644
--- a/tests/suites/test_suite_rsa.function
+++ b/tests/suites/test_suite_rsa.function
@@ -678,6 +678,7 @@
     if( result == 0 )
     {
         TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
+        TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx.P, &ctx.Q ) > 0 );
     }
 
 exit: