From f2b92bb25ba3e3fbf27f930dc2d4a8de3cb5d6c3 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Thu, 11 Aug 2016 10:45:14 +0100 Subject: [PATCH 01/83] Actually apply debug_level settings in cert_app --- programs/x509/cert_app.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c index 3f50a7a14..c6434fe1f 100644 --- a/programs/x509/cert_app.c +++ b/programs/x509/cert_app.c @@ -57,6 +57,7 @@ int main( void ) #include "mbedtls/net.h" #include "mbedtls/ssl.h" #include "mbedtls/x509.h" +#include "mbedtls/debug.h" #include #include @@ -380,6 +381,10 @@ int main( int argc, char *argv[] ) mbedtls_printf( " ok\n" ); +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( opt.debug_level ); +#endif + /* * 2. Start the connection */ From 5e8c62f53d0632febbd208f9eb17adc287123ebb Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Thu, 11 Aug 2016 10:45:33 +0100 Subject: [PATCH 02/83] Do not add empty cert / key in cert_app --- programs/x509/cert_app.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c index c6434fe1f..73e853e97 100644 --- a/programs/x509/cert_app.c +++ b/programs/x509/cert_app.c @@ -153,9 +153,7 @@ int main( int argc, char *argv[] ) mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; mbedtls_x509_crl cacrl; - mbedtls_pk_context pkey; int i, j; uint32_t flags; int verify = 0; @@ -170,7 +168,6 @@ int main( int argc, char *argv[] ) mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); mbedtls_x509_crt_init( &cacert ); - mbedtls_x509_crt_init( &clicert ); #if defined(MBEDTLS_X509_CRL_PARSE_C) mbedtls_x509_crl_init( &cacrl ); #else @@ -178,7 +175,6 @@ int main( int argc, char *argv[] ) it to the verify function */ memset( &cacrl, 0, sizeof(mbedtls_x509_crl) ); #endif - mbedtls_pk_init( &pkey ); if( argc == 0 ) { @@ -423,12 +419,6 @@ int main( int argc, char *argv[] ) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); - if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); - goto ssl_exit; - } - if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); @@ -484,11 +474,9 @@ exit: mbedtls_net_free( &server_fd ); mbedtls_x509_crt_free( &cacert ); - mbedtls_x509_crt_free( &clicert ); #if defined(MBEDTLS_X509_CRL_PARSE_C) mbedtls_x509_crl_free( &cacrl ); #endif - mbedtls_pk_free( &pkey ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); From d43fb9598a7ffd662b17bfa06d67fb796cf25249 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Mon, 26 Sep 2016 20:48:56 +0100 Subject: [PATCH 03/83] Update for ChangeLog for fixes for cert_app --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index a4f98ceb5..4b66c758c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,8 @@ Bugfix enabled unless others were also present. Found by David Fernandez. #428 * Fix for out-of-tree builds using CMake. Found by jwurzer, and fix based on a contribution from Tobias Tangemann. #541 + * Fixed cert_app sample program for debug output and for use when no root + certificates are provided. Changes * Extended test coverage of special cases, and added new timing test suite. From 788aa4a81214fa1d13b723e63a1e5b728b614771 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Wed, 14 Sep 2016 14:32:09 +0100 Subject: [PATCH 04/83] Rename net.{c,h} to net_sockets.{c,h} The library/net.c and its corresponding include/mbedtls/net.h file are renamed to library/net_sockets.c and include/mbedtls/net_sockets.h respectively. This is to avoid naming collisions in projects which also have files with the common name 'net'. --- ChangeLog | 4 + include/mbedtls/config.h | 2 +- include/mbedtls/net.h | 214 ++-------------------------- include/mbedtls/net_sockets.h | 225 ++++++++++++++++++++++++++++++ include/mbedtls/ssl.h | 7 +- library/CMakeLists.txt | 2 +- library/Makefile | 7 +- library/error.c | 2 +- library/{net.c => net_sockets.c} | 2 +- programs/pkey/dh_client.c | 2 +- programs/pkey/dh_server.c | 2 +- programs/ssl/dtls_client.c | 2 +- programs/ssl/dtls_server.c | 2 +- programs/ssl/mini_client.c | 2 +- programs/ssl/ssl_client1.c | 2 +- programs/ssl/ssl_client2.c | 2 +- programs/ssl/ssl_fork_server.c | 2 +- programs/ssl/ssl_mail_client.c | 2 +- programs/ssl/ssl_pthread_server.c | 2 +- programs/ssl/ssl_server.c | 2 +- programs/ssl/ssl_server2.c | 2 +- programs/test/udp_proxy.c | 2 +- programs/x509/cert_app.c | 2 +- scripts/footprint.sh | 2 +- scripts/generate_errors.pl | 3 + tests/scripts/all.sh | 2 +- visualc/VS2010/mbedTLS.vcxproj | 4 +- yotta/data/README.md | 2 +- 28 files changed, 273 insertions(+), 233 deletions(-) create mode 100644 include/mbedtls/net_sockets.h rename library/{net.c => net_sockets.c} (99%) diff --git a/ChangeLog b/ChangeLog index 4b66c758c..ca3dd1a79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -35,6 +35,10 @@ Changes through the symbol YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE. * Added optimization for code space for X.509/OID based on configured features. (contributed by Aviv Palivoda) + * Renamed source file library/net.c to library/net_sockets.c to avoid + 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. = mbed TLS 2.3.0 branch released 2016-06-28 diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 8d7d63110..8a892d74c 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1960,7 +1960,7 @@ * environment: * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS * - * Module: library/net.c + * Module: library/net_sockets.c * * This module provides networking routines. */ diff --git a/include/mbedtls/net.h b/include/mbedtls/net.h index 8c6534cfb..774559b3c 100644 --- a/include/mbedtls/net.h +++ b/include/mbedtls/net.h @@ -1,9 +1,9 @@ /** * \file net.h * - * \brief Network communication functions + * \brief Deprecated header file that includes mbedtls/net_sockets.h * - * 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 @@ -19,207 +19,13 @@ * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) + * + * \deprecated Superseded by mbedtls/net_sockets.h */ -#ifndef MBEDTLS_NET_H -#define MBEDTLS_NET_H -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "ssl.h" - -#include -#include - -#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ -#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ -#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ -#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ -#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ -#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ -#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ -#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ -#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ -#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ -#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ - -#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ - -#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ -#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Wrapper type for sockets. - * - * Currently backed by just a file descriptor, but might be more in the future - * (eg two file descriptors for combined IPv4 + IPv6 support, or additional - * structures for hand-made UDP demultiplexing). - */ -typedef struct -{ - int fd; /**< The underlying file descriptor */ -} -mbedtls_net_context; - -/** - * \brief Initialize a context - * Just makes the context ready to be used or freed safely. - * - * \param ctx Context to initialize - */ -void mbedtls_net_init( mbedtls_net_context *ctx ); - -/** - * \brief Initiate a connection with host:port in the given protocol - * - * \param ctx Socket to use - * \param host Host to connect to - * \param port Port to connect to - * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP - * - * \return 0 if successful, or one of: - * MBEDTLS_ERR_NET_SOCKET_FAILED, - * MBEDTLS_ERR_NET_UNKNOWN_HOST, - * MBEDTLS_ERR_NET_CONNECT_FAILED - * - * \note Sets the socket in connected mode even with UDP. - */ -int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); - -/** - * \brief Create a receiving socket on bind_ip:port in the chosen - * protocol. If bind_ip == NULL, all interfaces are bound. - * - * \param ctx Socket to use - * \param bind_ip IP to bind to, can be NULL - * \param port Port number to use - * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP - * - * \return 0 if successful, or one of: - * MBEDTLS_ERR_NET_SOCKET_FAILED, - * MBEDTLS_ERR_NET_BIND_FAILED, - * MBEDTLS_ERR_NET_LISTEN_FAILED - * - * \note Regardless of the protocol, opens the sockets and binds it. - * In addition, make the socket listening if protocol is TCP. - */ -int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); - -/** - * \brief Accept a connection from a remote client - * - * \param bind_ctx Relevant socket - * \param client_ctx Will contain the connected client socket - * \param client_ip Will contain the client IP address - * \param buf_size Size of the client_ip buffer - * \param ip_len Will receive the size of the client IP written - * - * \return 0 if successful, or - * MBEDTLS_ERR_NET_ACCEPT_FAILED, or - * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, - * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to - * non-blocking and accept() would block. - */ -int mbedtls_net_accept( mbedtls_net_context *bind_ctx, - mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len ); - -/** - * \brief Set the socket blocking - * - * \param ctx Socket to set - * - * \return 0 if successful, or a non-zero error code - */ -int mbedtls_net_set_block( mbedtls_net_context *ctx ); - -/** - * \brief Set the socket non-blocking - * - * \param ctx Socket to set - * - * \return 0 if successful, or a non-zero error code - */ -int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); - -/** - * \brief Portable usleep helper - * - * \param usec Amount of microseconds to sleep - * - * \note Real amount of time slept will not be less than - * select()'s timeout granularity (typically, 10ms). - */ -void mbedtls_net_usleep( unsigned long usec ); - -/** - * \brief Read at most 'len' characters. If no error occurs, - * the actual amount read is returned. - * - * \param ctx Socket - * \param buf The buffer to write to - * \param len Maximum length of the buffer - * - * \return the number of bytes received, - * or a non-zero error code; with a non-blocking socket, - * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. - */ -int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); - -/** - * \brief Write at most 'len' characters. If no error occurs, - * the actual amount read is returned. - * - * \param ctx Socket - * \param buf The buffer to read from - * \param len The length of the buffer - * - * \return the number of bytes sent, - * or a non-zero error code; with a non-blocking socket, - * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. - */ -int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); - -/** - * \brief Read at most 'len' characters, blocking for at most - * 'timeout' seconds. If no error occurs, the actual amount - * read is returned. - * - * \param ctx Socket - * \param buf The buffer to write to - * \param len Maximum length of the buffer - * \param timeout Maximum number of milliseconds to wait for data - * 0 means no timeout (wait forever) - * - * \return the number of bytes received, - * or a non-zero error code: - * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, - * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. - * - * \note This function will block (until data becomes available or - * timeout is reached) even if the socket is set to - * non-blocking. Handling timeouts with non-blocking reads - * requires a different strategy. - */ -int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ); - -/** - * \brief Gracefully shutdown the connection and free associated data - * - * \param ctx The context to free - */ -void mbedtls_net_free( mbedtls_net_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* net.h */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#include "mbedtls/net_sockets.h" +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/include/mbedtls/net_sockets.h b/include/mbedtls/net_sockets.h new file mode 100644 index 000000000..de335526f --- /dev/null +++ b/include/mbedtls/net_sockets.h @@ -0,0 +1,225 @@ +/** + * \file net_sockets.h + * + * \brief Network communication functions + * + * Copyright (C) 2006-2015, 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_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#include +#include + +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct +{ + int fd; /**< The underlying file descriptor */ +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init( mbedtls_net_context *ctx ); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \note Sets the socket in connected mode even with UDP. + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \note Regardless of the protocol, opens the sockets and binds it. + * In addition, make the socket listening if protocol is TCP. + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to + * non-blocking and accept() would block. + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return the number of bytes received, + * or a non-zero error code: + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free( mbedtls_net_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index c0bfd3e07..1c0513da7 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1105,9 +1105,10 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for * the conventions those callbacks must follow. * - * \note On some platforms, net.c provides \c mbedtls_net_send(), - * \c mbedtls_net_recv() and \c mbedtls_net_recv_timeout() - * that are suitable to be used here. + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \c mbedtls_net_recv_timeout() that are suitable to be used + * here. */ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, void *p_bio, diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 6aeb38525..98fe8c9c5 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -71,7 +71,7 @@ set(src_x509 set(src_tls debug.c - net.c + net_sockets.c ssl_cache.c ssl_ciphersuites.c ssl_cli.c diff --git a/library/Makefile b/library/Makefile index 00528b3c8..4b296282b 100644 --- a/library/Makefile +++ b/library/Makefile @@ -68,9 +68,10 @@ OBJS_X509= certs.o pkcs11.o x509.o \ x509_create.o x509_crl.o x509_crt.o \ x509_csr.o x509write_crt.o x509write_csr.o -OBJS_TLS= debug.o net.o ssl_cache.o \ - ssl_ciphersuites.o ssl_cli.o \ - ssl_cookie.o ssl_srv.o ssl_ticket.o \ +OBJS_TLS= debug.o net_sockets.o \ + ssl_cache.o ssl_ciphersuites.o \ + ssl_cli.o ssl_cookie.o \ + ssl_srv.o ssl_ticket.o \ ssl_tls.o .SILENT: diff --git a/library/error.c b/library/error.c index 4bd15bfee..71d4faa70 100644 --- a/library/error.c +++ b/library/error.c @@ -102,7 +102,7 @@ #endif #if defined(MBEDTLS_NET_C) -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #endif #if defined(MBEDTLS_OID_C) diff --git a/library/net.c b/library/net_sockets.c similarity index 99% rename from library/net.c rename to library/net_sockets.c index 8b96321bc..cc06cbfad 100644 --- a/library/net.c +++ b/library/net_sockets.c @@ -38,7 +38,7 @@ #include #endif -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c index 8ebf34a77..48b97cee9 100644 --- a/programs/pkey/dh_client.c +++ b/programs/pkey/dh_client.c @@ -37,7 +37,7 @@ 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) -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/aes.h" #include "mbedtls/dhm.h" #include "mbedtls/rsa.h" diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c index 7eef845df..173a29d35 100644 --- a/programs/pkey/dh_server.c +++ b/programs/pkey/dh_server.c @@ -37,7 +37,7 @@ 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) -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/aes.h" #include "mbedtls/dhm.h" #include "mbedtls/rsa.h" diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c index b37eb838c..442a3fb7c 100644 --- a/programs/ssl/dtls_client.c +++ b/programs/ssl/dtls_client.c @@ -51,7 +51,7 @@ int main( void ) #include -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/debug.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c index 1d6eb3bea..9d0dda4d1 100644 --- a/programs/ssl/dtls_server.c +++ b/programs/ssl/dtls_server.c @@ -67,7 +67,7 @@ int main( void ) #include "mbedtls/x509.h" #include "mbedtls/ssl.h" #include "mbedtls/ssl_cookie.h" -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/error.h" #include "mbedtls/debug.h" #include "mbedtls/timing.h" diff --git a/programs/ssl/mini_client.c b/programs/ssl/mini_client.c index 1d787313e..290455e9a 100644 --- a/programs/ssl/mini_client.c +++ b/programs/ssl/mini_client.c @@ -68,7 +68,7 @@ int main( void ) #include -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c index 3516e15c9..591f737ae 100644 --- a/programs/ssl/ssl_client1.c +++ b/programs/ssl/ssl_client1.c @@ -52,7 +52,7 @@ int main( void ) } #else -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/debug.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 78f9e00f5..a1d71e1b3 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -49,7 +49,7 @@ int main( void ) } #else -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c index 363f38f73..7624896a3 100644 --- a/programs/ssl/ssl_fork_server.c +++ b/programs/ssl/ssl_fork_server.c @@ -66,7 +66,7 @@ int main( void ) #include "mbedtls/certs.h" #include "mbedtls/x509.h" #include "mbedtls/ssl.h" -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/timing.h" #include diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c index c807eb569..4a22771d7 100644 --- a/programs/ssl/ssl_mail_client.c +++ b/programs/ssl/ssl_mail_client.c @@ -54,7 +54,7 @@ int main( void ) #include "mbedtls/base64.h" #include "mbedtls/error.h" -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" diff --git a/programs/ssl/ssl_pthread_server.c b/programs/ssl/ssl_pthread_server.c index c4b02ac54..9a05ad8fd 100644 --- a/programs/ssl/ssl_pthread_server.c +++ b/programs/ssl/ssl_pthread_server.c @@ -66,7 +66,7 @@ int main( void ) #include "mbedtls/certs.h" #include "mbedtls/x509.h" #include "mbedtls/ssl.h" -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/error.h" #if defined(MBEDTLS_SSL_CACHE_C) diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c index c7f526795..fd54f1726 100644 --- a/programs/ssl/ssl_server.c +++ b/programs/ssl/ssl_server.c @@ -65,7 +65,7 @@ int main( void ) #include "mbedtls/certs.h" #include "mbedtls/x509.h" #include "mbedtls/ssl.h" -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/error.h" #include "mbedtls/debug.h" diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 6d4e9165b..18bda599f 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -50,7 +50,7 @@ int main( void ) } #else -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c index b698c78f0..20624d227 100644 --- a/programs/test/udp_proxy.c +++ b/programs/test/udp_proxy.c @@ -50,7 +50,7 @@ int main( void ) } #else -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/error.h" #include "mbedtls/ssl.h" diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c index 73e853e97..c893ca8de 100644 --- a/programs/x509/cert_app.c +++ b/programs/x509/cert_app.c @@ -54,7 +54,7 @@ int main( void ) #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" -#include "mbedtls/net.h" +#include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" #include "mbedtls/x509.h" #include "mbedtls/debug.h" diff --git a/scripts/footprint.sh b/scripts/footprint.sh index 9d3c6294f..d38e50af2 100755 --- a/scripts/footprint.sh +++ b/scripts/footprint.sh @@ -85,7 +85,7 @@ doit() echo "(generated by $0)" > "$OUTFILE" echo "" >> "$OUTFILE" -log "Footprint of standard configurations (minus net.c, timing.c, fs_io)" +log "Footprint of standard configurations (minus net_sockets.c, timing.c, fs_io)" log "for bare-metal ARM Cortex-M3/M4 microcontrollers." VERSION_H="include/mbedtls/version.h" diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index 9605d6802..cfcf07c8f 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -90,6 +90,9 @@ while (my $line = ) $include_name =~ tr/A-Z/a-z/; $include_name = "" if ($include_name eq "asn1"); + # Fix faulty ones + $include_name = "net_sockets" if ($module_name eq "NET"); + my $found_ll = grep $_ eq $module_name, @low_level_modules; my $found_hl = grep $_ eq $module_name, @high_level_modules; if (!$found_ll && !$found_hl) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index f40d52f4d..afbcaffc5 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -332,7 +332,7 @@ scripts/config.pl full scripts/config.pl unset MBEDTLS_SSL_CLI_C CC=gcc CFLAGS='-Werror -O0' make -msg "build: full config except net.c, make, gcc -std=c99 -pedantic" # ~ 30s +msg "build: full config except net_sockets.c, make, gcc -std=c99 -pedantic" # ~ 30s cleanup cp "$CONFIG_H" "$CONFIG_BAK" scripts/config.pl full diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index 04b7377bb..a92e581e0 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -179,7 +179,7 @@ - + @@ -244,7 +244,7 @@ - + diff --git a/yotta/data/README.md b/yotta/data/README.md index 7ec7cef4c..b748aac32 100644 --- a/yotta/data/README.md +++ b/yotta/data/README.md @@ -72,7 +72,7 @@ While the two editions share the same code base, there are still a number of dif * The mbed OS edition has a smaller set of features enabled by default in `config.h`, in order to reduce footprint. While the default configuration of the standalone edition puts more emphasize on maintaining interoperability with old peers, the mbed OS edition only enables the most modern ciphers and the latest version of (D)TLS. -* The following components of mbed TLS are disabled in the mbed OS edition: `net.c` and `timing.c`. This is because mbed OS includes their equivalents. +* The following components of mbed TLS are disabled in the mbed OS edition: `net_sockets.c` and `timing.c`. This is because mbed OS include their equivalents. * The mbed OS edition comes with a fully integrated API for (D)TLS connections in a companion module: [mbed-tls-sockets](https://github.com/ARMmbed/mbed-tls-sockets). See "Performing TLS and DTLS connections" above. From f84f8926a70cb3f7fd78e68c5f6b7e9569a49ab3 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Mon, 19 Sep 2016 15:33:30 +0100 Subject: [PATCH 05/83] Add new config.h that does not need entropy source --- ChangeLog | 2 + configs/config-no-entropy.h | 84 +++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 configs/config-no-entropy.h diff --git a/ChangeLog b/ChangeLog index ca3dd1a79..2725f383e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,8 @@ Features * Added the macro MBEDTLS_X509_MAX_FILE_PATH_LEN that enables the user to configure the maximum length of a file path that can be buffered when calling mbedtls_x509_crt_parse_path(). + * Added a configuration file config-no-entropy.h that enables a subset of + library features that do not require an entropy source. Bugfix * Fix for platform time abstraction to avoid dependency issues where a build diff --git a/configs/config-no-entropy.h b/configs/config-no-entropy.h new file mode 100644 index 000000000..91e4a0264 --- /dev/null +++ b/configs/config-no-entropy.h @@ -0,0 +1,84 @@ +/** + * Minimal configuration of features that do not require an entropy source + * + * Copyright (C) 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) + */ +/* + * Minimal configuration of features that do not require an entropy source + * Distinguishing reatures: + * - no entropy module + * - no TLS protocol implementation available due missing entropy source + * + * See README.txt for usage instructions. + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME + +/* mbed TLS feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_NIST_OPTIM +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_PK_RSA_ALT_SUPPORT +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_PKCS1_V21 +#define MBEDTLS_SELF_TEST +#define MBEDTLS_VERSION_FEATURES +#define MBEDTLS_X509_CHECK_KEY_USAGE +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/* mbed TLS modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_GCM_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#define MBEDTLS_OID_C +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_VERSION_C +#define MBEDTLS_X509_USE_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_CRL_PARSE_C + +#include "check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ From 7abc974ec40b43001f6d8bc69859d41ec834c05a Mon Sep 17 00:00:00 2001 From: Andres AG Date: Fri, 23 Sep 2016 17:58:49 +0100 Subject: [PATCH 06/83] Add config macro for min bytes hw entropy --- ChangeLog | 3 +++ configs/config-no-entropy.h | 3 ++- include/mbedtls/config.h | 1 + include/mbedtls/entropy_poll.h | 2 ++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2725f383e..60383a97b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,9 @@ Features calling mbedtls_x509_crt_parse_path(). * Added a configuration file config-no-entropy.h that enables a subset of library features that do not require an entropy source. + * Added the macro MBEDTLS_ENTROPY_MIN_HARDWARE in config.h. This allows users + to configure the minimum number of bytes for entropy sources using the + mbedtls_hardware_poll() function. Bugfix * Fix for platform time abstraction to avoid dependency issues where a build diff --git a/configs/config-no-entropy.h b/configs/config-no-entropy.h index 91e4a0264..95f17d456 100644 --- a/configs/config-no-entropy.h +++ b/configs/config-no-entropy.h @@ -22,7 +22,8 @@ * Minimal configuration of features that do not require an entropy source * Distinguishing reatures: * - no entropy module - * - no TLS protocol implementation available due missing entropy source + * - no TLS protocol implementation available due to absence of an entropy + * source * * See README.txt for usage instructions. */ diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 8a892d74c..a58519bd5 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -2509,6 +2509,7 @@ /* Entropy options */ //#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ //#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ /* Memory buffer allocator options */ //#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ diff --git a/include/mbedtls/entropy_poll.h b/include/mbedtls/entropy_poll.h index 430e8651c..81258d5f3 100644 --- a/include/mbedtls/entropy_poll.h +++ b/include/mbedtls/entropy_poll.h @@ -41,7 +41,9 @@ extern "C" { #define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ #define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ #define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) #define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif /** * \brief Entropy poll callback that provides 0 entropy. From b2fdd04f6aa79b3111d2e1bda871791e0c4c0003 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Thu, 22 Sep 2016 14:17:46 +0100 Subject: [PATCH 07/83] Fix scripts to support multiple openssl and gnutls --- tests/scripts/all.sh | 6 ++++ tests/scripts/basic-build-test.sh | 37 ++++++++++++++++++--- tests/scripts/yotta-build.sh | 55 +++++++++++++++++++++---------- 3 files changed, 76 insertions(+), 22 deletions(-) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index afbcaffc5..ee0df0cc4 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -181,6 +181,12 @@ echo "GNUTLS_SERV: $GNUTLS_SERV" echo "GNUTLS_LEGACY_CLI: $GNUTLS_LEGACY_CLI" echo "GNUTLS_LEGACY_SERV: $GNUTLS_LEGACY_SERV" +# To avoid setting OpenSSL and GnuTLS for each call to compat.sh and ssl-opt.sh +# we just export the variables they require +export OPENSSL_CMD="$OPENSSL" +export GNUTLS_CLI="$GNUTLS_CLI" +export GNUTLS_SERV="$GNUTLS_SERV" + # Make sure the tools we need are available. check_tools "$OPENSSL" "$OPENSSL_LEGACY" "$GNUTLS_CLI" "$GNUTLS_SERV" \ "$GNUTLS_LEGACY_CLI" "$GNUTLS_LEGACY_SERV" "doxygen" "dot" \ diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh index e8b616492..b4058718a 100755 --- a/tests/scripts/basic-build-test.sh +++ b/tests/scripts/basic-build-test.sh @@ -36,11 +36,30 @@ if [ -d library -a -d include -a -d tests ]; then :; else exit 1 fi +: ${OPENSSL:="openssl"} +: ${OPENSSL_LEGACY:="$OPENSSL"} +: ${GNUTLS_CLI:="gnutls-cli"} +: ${GNUTLS_SERV:="gnutls-serv"} +: ${GNUTLS_LEGACY_CLI:="$GNUTLS_CLI"} +: ${GNUTLS_LEGACY_SERV:="$GNUTLS_SERV"} + +# To avoid setting OpenSSL and GnuTLS for each call to compat.sh and ssl-opt.sh +# we just export the variables they require +export OPENSSL_CMD="$OPENSSL" +export GNUTLS_CLI="$GNUTLS_CLI" +export GNUTLS_SERV="$GNUTLS_SERV" + CONFIG_H='include/mbedtls/config.h' CONFIG_BAK="$CONFIG_H.bak" # Step 0 - print build environment info -scripts/output_env.sh +OPENSSL="$OPENSSL" \ + OPENSSL_LEGACY="$OPENSSL_LEGACY" \ + GNUTLS_CLI="$GNUTLS_CLI" \ + GNUTLS_SERV="$GNUTLS_SERV" \ + GNUTLS_LEGACY_CLI="$GNUTLS_LEGACY_CLI" \ + GNUTLS_LEGACY_SERV="$GNUTLS_LEGACY_SERV" \ + scripts/output_env.sh echo # Step 1 - Make and instrumented build for code coverage @@ -65,7 +84,15 @@ sh ssl-opt.sh |tee sys-test-$TEST_OUTPUT echo # Step 2c - Compatibility tests -sh compat.sh |tee compat-test-$TEST_OUTPUT +sh compat.sh -m 'tls1 tls1_1 tls1_2 dtls1 dtls1_2' | \ + tee compat-test-$TEST_OUTPUT +OPENSSL_CMD="$OPENSSL_LEGACY" \ + sh compat.sh -m 'ssl3' |tee -a compat-test-$TEST_OUTPUT +OPENSSL_CMD="$OPENSSL_LEGACY" \ + GNUTLS_CLI="$GNUTLS_LEGACY_CLI" \ + GNUTLS_SERV="$GNUTLS_LEGACY_SERV" \ + sh compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES\|RC4\|ARCFOUR' | \ + tee -a compat-test-$TEST_OUTPUT echo # Step 3 - Process the coverage report @@ -128,9 +155,9 @@ TOTAL_EXED=$(($TOTAL_EXED + $TOTAL_TESTS)) # Step 4c - System Compatibility tests echo "System/Compatibility tests - tests/compat.sh" -PASSED_TESTS=$(tail -n5 compat-test-$TEST_OUTPUT|sed -n -e 's/.* (\([0-9]*\) \/ [0-9]* tests ([0-9]* skipped))$/\1/p') -SKIPPED_TESTS=$(tail -n5 compat-test-$TEST_OUTPUT|sed -n -e 's/.* ([0-9]* \/ [0-9]* tests (\([0-9]*\) skipped))$/\1/p') -EXED_TESTS=$(tail -n5 compat-test-$TEST_OUTPUT|sed -n -e 's/.* ([0-9]* \/ \([0-9]*\) tests ([0-9]* skipped))$/\1/p') +PASSED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* (\([0-9]*\) \/ [0-9]* tests ([0-9]* skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }') +SKIPPED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* ([0-9]* \/ [0-9]* tests (\([0-9]*\) skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }') +EXED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* ([0-9]* \/ \([0-9]*\) tests ([0-9]* skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }') FAILED_TESTS=$(($EXED_TESTS - $PASSED_TESTS)) echo "Passed : $PASSED_TESTS" diff --git a/tests/scripts/yotta-build.sh b/tests/scripts/yotta-build.sh index 19cc57664..4bae34aa3 100755 --- a/tests/scripts/yotta-build.sh +++ b/tests/scripts/yotta-build.sh @@ -1,12 +1,26 @@ #!/bin/sh -# Do test builds of the yotta module for all supported targets +# yotta-build.sh +# +# This file is part of mbed TLS (https://tls.mbed.org) +# +# Copyright (c) 2015-2016, ARM Limited, All Rights Reserved +# +# Purpose +# +# To run test builds of the yotta module for all supported targets. set -eu -yotta/create-module.sh -cd yotta/module -yt update || true # needs network +check_tools() +{ + for TOOL in "$@"; do + if ! `hash "$TOOL" >/dev/null 2>&1`; then + echo "$TOOL not found!" >&2 + exit 1 + fi + done +} yotta_build() { @@ -19,22 +33,29 @@ yotta_build() yt -t $TARGET build -d } +# Make sure the tools we need are available. +check_tools "arm-none-eabi-gcc" "armcc" "yotta" + +yotta/create-module.sh +cd yotta/module +yt update || true # needs network + if uname -a | grep 'Linux.*x86' >/dev/null; then yotta_build x86-linux-native fi if uname -a | grep 'Darwin.*x86' >/dev/null; then yotta_build x86-osx-native fi -if which armcc >/dev/null && armcc --help >/dev/null 2>&1; then - yotta_build frdm-k64f-armcc - #yotta_build nordic-nrf51822-16k-armcc -fi -if which arm-none-eabi-gcc >/dev/null; then - yotta_build frdm-k64f-gcc - #yotta_build st-nucleo-f401re-gcc # dirent - #yotta_build stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4 - #yotta_build nordic-nrf51822-16k-gcc # fails in minar-platform - #yotta_build bbc-microbit-classic-gcc # fails in minar-platform - #yotta_build st-stm32f439zi-gcc # fails in mbed-hal-st-stm32f4 - #yotta_build st-stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4 -fi + +# armcc build tests. +yotta_build frdm-k64f-armcc +#yotta_build nordic-nrf51822-16k-armcc + +# arm-none-eabi-gcc build tests. +yotta_build frdm-k64f-gcc +#yotta_build st-nucleo-f401re-gcc # dirent +#yotta_build stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4 +#yotta_build nordic-nrf51822-16k-gcc # fails in minar-platform +#yotta_build bbc-microbit-classic-gcc # fails in minar-platform +#yotta_build st-stm32f439zi-gcc # fails in mbed-hal-st-stm32f4 +#yotta_build st-stm32f429i-disco-gcc # fails in mbed-hal-st-stm32f4 From 93012e8bce9788244238ab8f93b2544d1d030b89 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Fri, 9 Sep 2016 09:10:28 +0100 Subject: [PATCH 08/83] Set selftest verbose flag to boost coverage --- tests/suites/test_suite_aes.function | 2 +- tests/suites/test_suite_arc4.function | 2 +- tests/suites/test_suite_base64.function | 2 +- tests/suites/test_suite_camellia.function | 2 +- tests/suites/test_suite_ccm.function | 2 +- tests/suites/test_suite_ctr_drbg.function | 2 +- tests/suites/test_suite_des.function | 2 +- tests/suites/test_suite_dhm.function | 2 +- tests/suites/test_suite_ecjpake.function | 2 +- tests/suites/test_suite_ecp.function | 2 +- tests/suites/test_suite_entropy.function | 2 +- tests/suites/test_suite_gcm.function | 2 +- tests/suites/test_suite_hmac_drbg.function | 2 +- tests/suites/test_suite_mdx.function | 8 ++++---- tests/suites/test_suite_memory_buffer_alloc.function | 2 +- tests/suites/test_suite_mpi.function | 2 +- tests/suites/test_suite_pkcs5.function | 2 +- tests/suites/test_suite_rsa.function | 2 +- tests/suites/test_suite_shax.function | 6 +++--- tests/suites/test_suite_timing.function | 2 +- tests/suites/test_suite_x509parse.function | 2 +- tests/suites/test_suite_xtea.function | 2 +- 22 files changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/suites/test_suite_aes.function b/tests/suites/test_suite_aes.function index 97bf51b88..c5f0eaac9 100644 --- a/tests/suites/test_suite_aes.function +++ b/tests/suites/test_suite_aes.function @@ -292,6 +292,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void aes_selftest() { - TEST_ASSERT( mbedtls_aes_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_aes_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_arc4.function b/tests/suites/test_suite_arc4.function index 3da7d8830..a4b401b62 100644 --- a/tests/suites/test_suite_arc4.function +++ b/tests/suites/test_suite_arc4.function @@ -41,6 +41,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void arc4_selftest() { - TEST_ASSERT( mbedtls_arc4_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_arc4_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_base64.function b/tests/suites/test_suite_base64.function index ab6d88ca7..77fa7fded 100644 --- a/tests/suites/test_suite_base64.function +++ b/tests/suites/test_suite_base64.function @@ -119,6 +119,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void base64_selftest() { - TEST_ASSERT( mbedtls_base64_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_base64_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_camellia.function b/tests/suites/test_suite_camellia.function index 8c69a96ee..9df6482a8 100644 --- a/tests/suites/test_suite_camellia.function +++ b/tests/suites/test_suite_camellia.function @@ -224,6 +224,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void camellia_selftest() { - TEST_ASSERT( mbedtls_camellia_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_camellia_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_ccm.function b/tests/suites/test_suite_ccm.function index 13371eb9e..2f5c77c2c 100644 --- a/tests/suites/test_suite_ccm.function +++ b/tests/suites/test_suite_ccm.function @@ -10,7 +10,7 @@ /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST:MBEDTLS_AES_C */ void mbedtls_ccm_self_test( ) { - TEST_ASSERT( mbedtls_ccm_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_ccm_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function index 3c7873b31..3acfb8bae 100644 --- a/tests/suites/test_suite_ctr_drbg.function +++ b/tests/suites/test_suite_ctr_drbg.function @@ -216,6 +216,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void ctr_drbg_selftest( ) { - TEST_ASSERT( mbedtls_ctr_drbg_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_ctr_drbg_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_des.function b/tests/suites/test_suite_des.function index aecd419e5..2e73a7768 100644 --- a/tests/suites/test_suite_des.function +++ b/tests/suites/test_suite_des.function @@ -362,6 +362,6 @@ void des_key_parity_run() /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void des_selftest() { - TEST_ASSERT( mbedtls_des_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_des_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function index 002c20bf4..b9b8e1956 100644 --- a/tests/suites/test_suite_dhm.function +++ b/tests/suites/test_suite_dhm.function @@ -123,6 +123,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void dhm_selftest() { - TEST_ASSERT( mbedtls_dhm_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_dhm_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_ecjpake.function b/tests/suites/test_suite_ecjpake.function index 8d867b736..11cf8dc94 100644 --- a/tests/suites/test_suite_ecjpake.function +++ b/tests/suites/test_suite_ecjpake.function @@ -101,7 +101,7 @@ cleanup: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void ecjpake_selftest() { - TEST_ASSERT( mbedtls_ecjpake_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_ecjpake_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index eee648693..afe61ec61 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -507,6 +507,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void ecp_selftest() { - TEST_ASSERT( mbedtls_ecp_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_ecp_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function index 5b97cad3d..97a21bc18 100644 --- a/tests/suites/test_suite_entropy.function +++ b/tests/suites/test_suite_entropy.function @@ -380,6 +380,6 @@ void entropy_nv_seed( char *read_seed_str ) /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void entropy_selftest( int result ) { - TEST_ASSERT( mbedtls_entropy_self_test( 0 ) == result ); + TEST_ASSERT( mbedtls_entropy_self_test( 1 ) == result ); } /* END_CASE */ diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function index 9d841dc12..56c7e1899 100644 --- a/tests/suites/test_suite_gcm.function +++ b/tests/suites/test_suite_gcm.function @@ -119,6 +119,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void gcm_selftest() { - TEST_ASSERT( mbedtls_gcm_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_gcm_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_hmac_drbg.function b/tests/suites/test_suite_hmac_drbg.function index 3cc96421e..52094700b 100644 --- a/tests/suites/test_suite_hmac_drbg.function +++ b/tests/suites/test_suite_hmac_drbg.function @@ -314,6 +314,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void hmac_drbg_selftest( ) { - TEST_ASSERT( mbedtls_hmac_drbg_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_hmac_drbg_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_mdx.function b/tests/suites/test_suite_mdx.function index 3d233638b..9d0ee471f 100644 --- a/tests/suites/test_suite_mdx.function +++ b/tests/suites/test_suite_mdx.function @@ -88,27 +88,27 @@ void ripemd160_text( char *text_src_string, char *hex_hash_string ) /* BEGIN_CASE depends_on:MBEDTLS_MD2_C:MBEDTLS_SELF_TEST */ void md2_selftest() { - TEST_ASSERT( mbedtls_md2_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_md2_self_test( 1 ) == 0 ); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_MD4_C:MBEDTLS_SELF_TEST */ void md4_selftest() { - TEST_ASSERT( mbedtls_md4_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_md4_self_test( 1 ) == 0 ); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_MD5_C:MBEDTLS_SELF_TEST */ void md5_selftest() { - TEST_ASSERT( mbedtls_md5_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_md5_self_test( 1 ) == 0 ); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_RIPEMD160_C:MBEDTLS_SELF_TEST */ void ripemd160_selftest() { - TEST_ASSERT( mbedtls_ripemd160_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_ripemd160_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_memory_buffer_alloc.function b/tests/suites/test_suite_memory_buffer_alloc.function index 04dd68bec..a0c70d8a2 100644 --- a/tests/suites/test_suite_memory_buffer_alloc.function +++ b/tests/suites/test_suite_memory_buffer_alloc.function @@ -25,7 +25,7 @@ static int check_pointer( void *p ) /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void mbedtls_memory_buffer_alloc_self_test( ) { - TEST_ASSERT( mbedtls_memory_buffer_alloc_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_memory_buffer_alloc_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function index e5d0850f1..b94c88980 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -877,6 +877,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void mpi_selftest() { - TEST_ASSERT( mbedtls_mpi_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_mpi_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_pkcs5.function b/tests/suites/test_suite_pkcs5.function index b1f796e09..8fabec085 100644 --- a/tests/suites/test_suite_pkcs5.function +++ b/tests/suites/test_suite_pkcs5.function @@ -82,6 +82,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void pkcs5_selftest( ) { - TEST_ASSERT( mbedtls_pkcs5_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_pkcs5_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_rsa.function b/tests/suites/test_suite_rsa.function index 59cbb5c97..8837e3a83 100644 --- a/tests/suites/test_suite_rsa.function +++ b/tests/suites/test_suite_rsa.function @@ -690,6 +690,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void rsa_selftest() { - TEST_ASSERT( mbedtls_rsa_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_rsa_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_shax.function b/tests/suites/test_suite_shax.function index ec326fcc9..6b3ee9c54 100644 --- a/tests/suites/test_suite_shax.function +++ b/tests/suites/test_suite_shax.function @@ -112,20 +112,20 @@ void mbedtls_sha512(char *hex_src_string, char *hex_hash_string ) /* BEGIN_CASE depends_on:MBEDTLS_SHA1_C:MBEDTLS_SELF_TEST */ void sha1_selftest() { - TEST_ASSERT( mbedtls_sha1_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_sha1_self_test( 1 ) == 0 ); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_SHA256_C:MBEDTLS_SELF_TEST */ void sha256_selftest() { - TEST_ASSERT( mbedtls_sha256_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_sha256_self_test( 1 ) == 0 ); } /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_SHA512_C:MBEDTLS_SELF_TEST */ void sha512_selftest() { - TEST_ASSERT( mbedtls_sha512_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_sha512_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_timing.function b/tests/suites/test_suite_timing.function index 74f711c7d..5882f85d7 100644 --- a/tests/suites/test_suite_timing.function +++ b/tests/suites/test_suite_timing.function @@ -10,6 +10,6 @@ /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void timing_selftest() { - TEST_ASSERT( mbedtls_timing_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_timing_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index c476ec507..2affab79b 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -623,6 +623,6 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_SELF_TEST */ void x509_selftest() { - TEST_ASSERT( mbedtls_x509_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_x509_self_test( 1 ) == 0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_xtea.function b/tests/suites/test_suite_xtea.function index e294a9bd2..cbc714a12 100644 --- a/tests/suites/test_suite_xtea.function +++ b/tests/suites/test_suite_xtea.function @@ -124,6 +124,6 @@ void xtea_decrypt_cbc( char *hex_key_string, char *hex_iv_string, /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ void xtea_selftest() { - TEST_ASSERT( mbedtls_xtea_self_test( 0 ) == 0 ); + TEST_ASSERT( mbedtls_xtea_self_test( 1 ) == 0 ); } /* END_CASE */ From 5437a75b155f57a30920c4ba75f4d90d460a9902 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 26 Sep 2016 09:15:44 +0100 Subject: [PATCH 09/83] Add safety check to sample mutex implementation Due to inconsistent freeing strategy in pkparse.c the sample mutex implementation in threading.c could lead to undefined behaviour by destroying the same mutex several times. This fix prevents mutexes from being destroyed several times in the sample threading implementation. --- ChangeLog | 2 ++ library/threading.c | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 60383a97b..8090a70ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,8 @@ Bugfix a contribution from Tobias Tangemann. #541 * Fixed cert_app sample program for debug output and for use when no root certificates are provided. + * Fixed default threading implementation to avoid accidental double + initialisations and double frees. Changes * Extended test coverage of special cases, and added new timing test suite. diff --git a/library/threading.c b/library/threading.c index 1b6d9cd44..83ec01a45 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_init_pthread( mbedtls_threading_mutex_t *mutex ) 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 ) From dc5c7b98ac3bffb3b94fa5feece658365758a733 Mon Sep 17 00:00:00 2001 From: Robert Cragie Date: Fri, 11 Dec 2015 15:49:45 +0000 Subject: [PATCH 10/83] Add support for AES-128-CMAC and AES-CMAC-PRF-128 --- include/mbedtls/cmac.h | 139 +++++++++++ include/mbedtls/config.h | 12 + library/CMakeLists.txt | 1 + library/cmac.c | 527 +++++++++++++++++++++++++++++++++++++++ programs/test/selftest.c | 6 + 5 files changed, 685 insertions(+) create mode 100644 include/mbedtls/cmac.h create mode 100644 library/cmac.c diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h new file mode 100644 index 000000000..08483f685 --- /dev/null +++ b/include/mbedtls/cmac.h @@ -0,0 +1,139 @@ +/** + * \file cmac.h + * + * \brief The CMAC Mode for Authentication + * + * Copyright (C) 2006-2015, 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 "cipher.h" + +#define MBEDTLS_ERR_CMAC_BAD_INPUT -0x000D /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_CMAC_VERIFY_FAILED -0x000F /**< Verification failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CCM context structure + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ + unsigned char K1[16]; + unsigned char K2[16]; +} +mbedtls_cmac_context; + +/** + * \brief Initialize CMAC context (just makes references valid) + * Makes the context ready for mbedtls_cmac_setkey() or + * mbedtls_cmac_free(). + * + * \param ctx CMAC context to initialize + */ +void mbedtls_cmac_init( mbedtls_cmac_context *ctx ); + +/** + * \brief CMAC initialization + * + * \param ctx CMAC context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) + * \param key encryption key + * \param keybits key size in bits (must be acceptable by the cipher) + * + * \return 0 if successful, or a cipher specific error code + */ +int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Free a CMAC context and underlying cipher sub-context + * + * \param ctx CMAC context to free + */ +void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); + +/** + * \brief CMAC generate + * + * \param ctx CMAC context + * \param length length of the input data in bytes + * \param input buffer holding the input data + * \param tag buffer for holding the generated tag + * \param tag_len length of the tag to generate in bytes + * must be between 4, 6, 8, 10, 14 or 16 + * + * \return 0 if successful + */ +int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + unsigned char *tag, size_t tag_len ); + +/** + * \brief CMAC verify + * + * \param ctx CMAC context + * \param length length of the input data in bytes + * \param input buffer holding the input data + * \param tag buffer holding the tag to verify + * \param tag_len length of the tag to verify in bytes + * must be 4, 6, 8, 10, 14 or 16 + * + * \return 0 if successful and authenticated, + * MBEDTLS_ERR_CMAC_AUTH_FAILED if tag does not match + */ +int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + const unsigned char *tag, size_t tag_len ); + +/** + * \brief AES-CMAC-128-PRF + * + * \param ctx CMAC context + * \param length length of the input data in bytes + * \param key PRF key + * \param key_len PRF key length + * \param input buffer holding the input data + * \param tag buffer holding the tag to verify (16 bytes) + * + * \return 0 if successful + */ +int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *key, size_t key_len, + const unsigned char *input, + unsigned char *tag ); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_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 */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index a58519bd5..6e0313629 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1671,6 +1671,18 @@ */ #define MBEDTLS_CIPHER_C +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC mode for 128-bit block cipher. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + */ +#define MBEDTLS_CMAC_C + /** * \def MBEDTLS_CTR_DRBG_C * diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 98fe8c9c5..eeb8e84ca 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -15,6 +15,7 @@ set(src_crypto ccm.c cipher.c cipher_wrap.c + cmac.c ctr_drbg.c des.c dhm.c diff --git a/library/cmac.c b/library/cmac.c new file mode 100644 index 000000000..73ee6d049 --- /dev/null +++ b/library/cmac.c @@ -0,0 +1,527 @@ +/* + * NIST SP800-38B compliant CMAC implementation + * + * Copyright (C) 2006-2015, 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) + */ + +/* + * Definition of CMAC: + * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf + * RFC 4493 "The AES-CMAC Algorithm" + */ + +#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 + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * XOR 128-bit + */ +#define XOR_128(i1, i2, o) \ + for( i = 0; i < 16; i++ ) \ + ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; + +/* + * Update the CMAC state in Mn using an input block x + * TODO: Compiler optimisation + */ +#define UPDATE_CMAC( x ) \ + XOR_128( Mn, ( x ), Mn ); \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, Mn, 16, Mn, &olen ) ) != 0 ) \ + return( ret ); + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Initialize context + */ +void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_cmac_context ) ); +} + +/* + * Leftshift a 16-byte block by 1 bit + * \note output can be same as input + */ +static void leftshift_onebit(unsigned char *input, unsigned char *output) +{ + int i; + unsigned char temp; + unsigned char overflow = 0; + + for( i = 15; i >= 0; i-- ) + { + temp = input[i]; + output[i] = temp << 1; + output[i] |= overflow; + overflow = temp >> 7; + } + return; +} + +/* + * Generate subkeys + */ +static int generate_subkeys(mbedtls_cmac_context *ctx) +{ + static const unsigned char Rb[2] = {0x00, 0x87}; /* Note - block size 16 only */ + int ret; + unsigned char L[16]; + size_t olen; + + /* Calculate Ek(0) */ + memset( L, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, L, 16, L, &olen ) ) != 0 ) + { + return( ret ); + } + + /* + * Generate K1 + * If MSB(L) = 0, then K1 = (L << 1) + * If MSB(L) = 1, then K1 = (L << 1) ^ Rb + */ + leftshift_onebit( L, ctx->K1 ); + ctx->K1[15] ^= Rb[L[0] >> 7]; /* "Constant-time" operation */ + + /* + * Generate K2 + * If MSB(K1) == 0, then K2 = (K1 << 1) + * If MSB(K1) == 1, then K2 = (K1 << 1) ^ Rb + */ + leftshift_onebit( ctx->K1, ctx->K2 ); + ctx->K2[15] ^= Rb[ctx->K1[0] >> 7]; /* "Constant-time" operation */ + + return( 0 ); +} + +int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( generate_subkeys(ctx) ); +} + +/* + * Free context + */ +void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) ); +} + +/* TODO: Use cipher padding function? */ +static void padding(const unsigned char *lastb, unsigned char *pad, const size_t length) +{ + size_t j; + + /* original last block */ + for( j = 0; j < 16; j++ ) + { + if( j < length ) + { + pad[j] = lastb[j]; + } + else if( j == length ) + { + pad[j] = 0x80; + } + else + { + pad[j] = 0x00; + } + } +} + +/* + * Generate tag on complete message + */ +static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + unsigned char *tag, size_t tag_len ) +{ + unsigned char Mn[16]; + unsigned char M_last[16]; + unsigned char padded[16]; + int n, i, j, ret, flag; + size_t olen; + + /* + * Check length requirements: SP800-38B A + * 4 is a worst case bottom limit + */ + if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + + /* TODO: Use cipher padding function? */ + // mbedtls_cipher_set_padding_mode( ctx->cipher, MBEDTLS_PADDING_ONE_AND_ZEROS ); + + n = ( length + 15 ) / 16; /* n is number of rounds */ + + if( n == 0 ) + { + n = 1; + flag = 0; + } + else + { + flag = ( ( length % 16 ) == 0); + } + + /* Calculate last block */ + if( flag ) + { + /* Last block is complete block */ + XOR_128( &input[16 * (n - 1)], ctx->K1, M_last ); + } + else + { + /* TODO: Use cipher padding function? */ + padding( &input[16 * (n - 1)], padded, length % 16 ); + XOR_128( padded, ctx->K2, M_last ); + } + + memset( Mn, 0, 16 ); + + for( j = 0; j < n - 1; j++ ) + { + UPDATE_CMAC(&input[16 * j]); + } + + UPDATE_CMAC(M_last); + + memcpy( tag, Mn, 16 ); + + return( 0 ); +} + +int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + unsigned char *tag, size_t tag_len ) +{ + return( cmac_generate( ctx, length, input, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + if( ( ret = cmac_generate( ctx, length, input, check_tag, tag_len) ) != 0 ) + { + return ret; + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + { + diff |= tag[i] ^ check_tag[i]; + } + + if( diff != 0 ) + { + return( MBEDTLS_ERR_CMAC_VERIFY_FAILED ); + } + + return( 0 ); +} + +int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *key, size_t key_length, + const unsigned char *input, + unsigned char *tag ) +{ + int ret; + unsigned char zero_key[16]; + unsigned char int_key[16]; + + if( key_length == 16 ) + { + /* Use key as is */ + memcpy(int_key, key, 16); + } + else + { + mbedtls_cmac_context zero_ctx; + + /* Key is AES_CMAC(0, key) */ + mbedtls_cmac_init( &zero_ctx ); + memset(zero_key, 0, 16); + ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, zero_key, 8 * sizeof zero_key ); + if( ret != 0 ) + { + return( ret ); + } + ret = mbedtls_cmac_generate( &zero_ctx, key_length, key, int_key, 16 ); + if( ret != 0 ) + { + return( ret ); + } + } + + ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES, int_key, 8 * sizeof int_key ); + if( ret != 0 ) + { + return( ret ); + } + return( mbedtls_cmac_generate( ctx, length, input, tag, 16 ) ); +} + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * Examples 1 to 4 from SP800-3B corrected Appendix D.1 + * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf + */ + +#define NB_CMAC_TESTS 4 +#define NB_PRF_TESTS 3 + +/* Key */ +static const unsigned char key[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; + +/* Assume we don't need to test Ek0 as this is a function of the cipher */ + +/* Subkey K1 */ +static const unsigned char K1[] = { + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde +}; + +/* Subkey K2 */ +static const unsigned char K2[] = { + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b +}; + +/* All Messages */ +static const unsigned char M[] = { + 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 +}; + +static const unsigned char T[NB_CMAC_TESTS][16] = { + { + 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 + } +}; + +/* Sizes in bytes */ +static const size_t Mlen[NB_CMAC_TESTS] = { + 0, + 16, + 40, + 64 +}; + +/* PRF K */ +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 + } +}; + + +int mbedtls_cmac_self_test( int verbose ) +{ + mbedtls_cmac_context ctx; + unsigned char tag[16]; + int i; + int ret; + + mbedtls_cmac_init( &ctx ); + + if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: setup failed" ); + + return( 1 ); + } + + if( ( memcmp( ctx.K1, K1, 16 ) != 0 ) || + ( memcmp( ctx.K2, K2, 16 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: subkey generation failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_CMAC_TESTS; i++ ) + { + mbedtls_printf( " AES-128-CMAC #%u: ", i ); + + ret = mbedtls_cmac_generate( &ctx, Mlen[i], M, tag, 16 ); + if( ret != 0 || + memcmp( tag, T[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + ret = mbedtls_cmac_verify( &ctx, Mlen[i], M, T[i], 16 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i ); + + mbedtls_aes_cmac_prf_128( &ctx, 20, PRFK, PRFKlen[i], PRFM, tag); + + if( ret != 0 || + memcmp( tag, PRFT[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + mbedtls_cmac_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_CMAC_C */ diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 89c66169e..17fdb2128 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,11 @@ int main( int argc, char *argv[] ) suites_tested++; #endif +#if defined(MBEDTLS_CMAC_C) && defined(MBEDTLS_AES_C) + if( ( ret = mbedtls_cmac_self_test( v ) ) != 0 ) + return( ret ); +#endif + #if defined(MBEDTLS_BASE64_C) if( mbedtls_base64_self_test( v ) != 0 ) { From 8324818e0a273872e3bbaec72e772412e7ba80e6 Mon Sep 17 00:00:00 2001 From: Robert Cragie Date: Mon, 14 Dec 2015 15:18:33 +0000 Subject: [PATCH 11/83] Added MBEDTLS_CMAC_C --- library/version_features.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/version_features.c b/library/version_features.c index 5d20ba019..23b5620ef 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -462,6 +462,9 @@ static const char *features[] = { #if defined(MBEDTLS_CERTS_C) "MBEDTLS_CERTS_C", #endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CMAC_C) + "MBEDTLS_CMAC_C", +#endif /* MBEDTLS_CMAC_C */ #if defined(MBEDTLS_CIPHER_C) "MBEDTLS_CIPHER_C", #endif /* MBEDTLS_CIPHER_C */ From 84a4c677412054dff4b8dd4ffc6e20641f86a287 Mon Sep 17 00:00:00 2001 From: Robert Cragie Date: Mon, 14 Dec 2015 17:13:29 +0000 Subject: [PATCH 12/83] Added CMAC as proper low-level module and changed error returns --- include/mbedtls/cmac.h | 4 ++-- include/mbedtls/error.h | 1 + library/error.c | 11 +++++++++++ scripts/generate_errors.pl | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 08483f685..65017ef5c 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -25,8 +25,8 @@ #include "cipher.h" -#define MBEDTLS_ERR_CMAC_BAD_INPUT -0x000D /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_CMAC_VERIFY_FAILED -0x000F /**< Verification failed. */ +#define MBEDTLS_ERR_CMAC_BAD_INPUT -0x0011 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_CMAC_VERIFY_FAILED -0x0013 /**< Verification failed. */ #ifdef __cplusplus extern "C" { diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 5e549f6b6..703233ae9 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -66,6 +66,7 @@ * PBKDF2 1 0x007C-0x007C * HMAC_DRBG 4 0x0003-0x0009 * CCM 2 0x000D-0x000F + * CMAC 2 0x0011-0x0013 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors diff --git a/library/error.c b/library/error.c index 71d4faa70..8c38cf294 100644 --- a/library/error.c +++ b/library/error.c @@ -69,6 +69,10 @@ #include "mbedtls/cipher.h" #endif +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #endif @@ -578,6 +582,13 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CMAC_C) + if( use_ret == -(MBEDTLS_ERR_CMAC_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "CMAC - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_CMAC_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "CMAC - Verification failed" ); +#endif /* MBEDTLS_CMAC_C */ + #if defined(MBEDTLS_CTR_DRBG_C) if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index cfcf07c8f..dd91151d6 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -33,7 +33,7 @@ my @low_level_modules = ( "AES", "ASN1", "BLOWFISH", "CAMELLIA", "BIGNUM", "BASE64", "XTEA", "PBKDF2", "OID", "PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY", "HMAC_DRBG", "MD2", "MD4", "MD5", "RIPEMD160", - "SHA1", "SHA256", "SHA512", "GCM", "THREADING", "CCM" ); + "SHA1", "SHA256", "SHA512", "GCM", "THREADING", "CCM", "CMAC" ); my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL", "PK", "PKCS12", "PKCS5" ); From 48f2ff9dbe11c39351bfd0fc595b5c967194af25 Mon Sep 17 00:00:00 2001 From: Robert Cragie Date: Mon, 14 Dec 2015 17:34:33 +0000 Subject: [PATCH 13/83] Use autogenerated version_features.c --- library/version_features.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/version_features.c b/library/version_features.c index 23b5620ef..0a2f06575 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -462,12 +462,12 @@ static const char *features[] = { #if defined(MBEDTLS_CERTS_C) "MBEDTLS_CERTS_C", #endif /* MBEDTLS_CERTS_C */ -#if defined(MBEDTLS_CMAC_C) - "MBEDTLS_CMAC_C", -#endif /* MBEDTLS_CMAC_C */ #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 */ From f261ef07ee87d0268e22814920a58a851906ebbb Mon Sep 17 00:00:00 2001 From: Robert Cragie Date: Mon, 14 Dec 2015 17:52:55 +0000 Subject: [PATCH 14/83] Bad code in function documentation --- include/mbedtls/cmac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 65017ef5c..c01fdc963 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -100,7 +100,7 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, * must be 4, 6, 8, 10, 14 or 16 * * \return 0 if successful and authenticated, - * MBEDTLS_ERR_CMAC_AUTH_FAILED if tag does not match + * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match */ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, const unsigned char *input, From 3d23b1d5ede08b01154305624200d9b6a918b8c2 Mon Sep 17 00:00:00 2001 From: Robert Cragie Date: Tue, 15 Dec 2015 07:38:11 +0000 Subject: [PATCH 15/83] Line endings wrong --- include/mbedtls/cmac.h | 278 +++++------ library/cmac.c | 1054 ++++++++++++++++++++-------------------- 2 files changed, 666 insertions(+), 666 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index c01fdc963..282d549a4 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -1,139 +1,139 @@ -/** - * \file cmac.h - * - * \brief The CMAC Mode for Authentication - * - * Copyright (C) 2006-2015, 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 "cipher.h" - -#define MBEDTLS_ERR_CMAC_BAD_INPUT -0x0011 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_CMAC_VERIFY_FAILED -0x0013 /**< Verification failed. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief CCM context structure - */ -typedef struct { - mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ - unsigned char K1[16]; - unsigned char K2[16]; -} -mbedtls_cmac_context; - -/** - * \brief Initialize CMAC context (just makes references valid) - * Makes the context ready for mbedtls_cmac_setkey() or - * mbedtls_cmac_free(). - * - * \param ctx CMAC context to initialize - */ -void mbedtls_cmac_init( mbedtls_cmac_context *ctx ); - -/** - * \brief CMAC initialization - * - * \param ctx CMAC context to be initialized - * \param cipher cipher to use (a 128-bit block cipher) - * \param key encryption key - * \param keybits key size in bits (must be acceptable by the cipher) - * - * \return 0 if successful, or a cipher specific error code - */ -int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ); - -/** - * \brief Free a CMAC context and underlying cipher sub-context - * - * \param ctx CMAC context to free - */ -void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); - -/** - * \brief CMAC generate - * - * \param ctx CMAC context - * \param length length of the input data in bytes - * \param input buffer holding the input data - * \param tag buffer for holding the generated tag - * \param tag_len length of the tag to generate in bytes - * must be between 4, 6, 8, 10, 14 or 16 - * - * \return 0 if successful - */ -int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, - unsigned char *tag, size_t tag_len ); - -/** - * \brief CMAC verify - * - * \param ctx CMAC context - * \param length length of the input data in bytes - * \param input buffer holding the input data - * \param tag buffer holding the tag to verify - * \param tag_len length of the tag to verify in bytes - * must be 4, 6, 8, 10, 14 or 16 - * - * \return 0 if successful and authenticated, - * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match - */ -int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, - const unsigned char *tag, size_t tag_len ); - -/** - * \brief AES-CMAC-128-PRF - * - * \param ctx CMAC context - * \param length length of the input data in bytes - * \param key PRF key - * \param key_len PRF key length - * \param input buffer holding the input data - * \param tag buffer holding the tag to verify (16 bytes) - * - * \return 0 if successful - */ -int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *key, size_t key_len, - const unsigned char *input, - unsigned char *tag ); - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_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 */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_CMAC_H */ +/** + * \file cmac.h + * + * \brief The CMAC Mode for Authentication + * + * Copyright (C) 2006-2015, 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 "cipher.h" + +#define MBEDTLS_ERR_CMAC_BAD_INPUT -0x0011 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_CMAC_VERIFY_FAILED -0x0013 /**< Verification failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CCM context structure + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ + unsigned char K1[16]; + unsigned char K2[16]; +} +mbedtls_cmac_context; + +/** + * \brief Initialize CMAC context (just makes references valid) + * Makes the context ready for mbedtls_cmac_setkey() or + * mbedtls_cmac_free(). + * + * \param ctx CMAC context to initialize + */ +void mbedtls_cmac_init( mbedtls_cmac_context *ctx ); + +/** + * \brief CMAC initialization + * + * \param ctx CMAC context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) + * \param key encryption key + * \param keybits key size in bits (must be acceptable by the cipher) + * + * \return 0 if successful, or a cipher specific error code + */ +int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Free a CMAC context and underlying cipher sub-context + * + * \param ctx CMAC context to free + */ +void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); + +/** + * \brief CMAC generate + * + * \param ctx CMAC context + * \param length length of the input data in bytes + * \param input buffer holding the input data + * \param tag buffer for holding the generated tag + * \param tag_len length of the tag to generate in bytes + * must be between 4, 6, 8, 10, 14 or 16 + * + * \return 0 if successful + */ +int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + unsigned char *tag, size_t tag_len ); + +/** + * \brief CMAC verify + * + * \param ctx CMAC context + * \param length length of the input data in bytes + * \param input buffer holding the input data + * \param tag buffer holding the tag to verify + * \param tag_len length of the tag to verify in bytes + * must be 4, 6, 8, 10, 14 or 16 + * + * \return 0 if successful and authenticated, + * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match + */ +int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + const unsigned char *tag, size_t tag_len ); + +/** + * \brief AES-CMAC-128-PRF + * + * \param ctx CMAC context + * \param length length of the input data in bytes + * \param key PRF key + * \param key_len PRF key length + * \param input buffer holding the input data + * \param tag buffer holding the tag to verify (16 bytes) + * + * \return 0 if successful + */ +int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *key, size_t key_len, + const unsigned char *input, + unsigned char *tag ); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_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 */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/library/cmac.c b/library/cmac.c index 73ee6d049..2ba58b6fa 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -1,527 +1,527 @@ -/* - * NIST SP800-38B compliant CMAC implementation - * - * Copyright (C) 2006-2015, 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) - */ - -/* - * Definition of CMAC: - * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf - * RFC 4493 "The AES-CMAC Algorithm" - */ - -#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 - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -/* - * Macros for common operations. - * Results in smaller compiled code than static inline functions. - */ - -/* - * XOR 128-bit - */ -#define XOR_128(i1, i2, o) \ - for( i = 0; i < 16; i++ ) \ - ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; - -/* - * Update the CMAC state in Mn using an input block x - * TODO: Compiler optimisation - */ -#define UPDATE_CMAC( x ) \ - XOR_128( Mn, ( x ), Mn ); \ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, Mn, 16, Mn, &olen ) ) != 0 ) \ - return( ret ); - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Initialize context - */ -void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_cmac_context ) ); -} - -/* - * Leftshift a 16-byte block by 1 bit - * \note output can be same as input - */ -static void leftshift_onebit(unsigned char *input, unsigned char *output) -{ - int i; - unsigned char temp; - unsigned char overflow = 0; - - for( i = 15; i >= 0; i-- ) - { - temp = input[i]; - output[i] = temp << 1; - output[i] |= overflow; - overflow = temp >> 7; - } - return; -} - -/* - * Generate subkeys - */ -static int generate_subkeys(mbedtls_cmac_context *ctx) -{ - static const unsigned char Rb[2] = {0x00, 0x87}; /* Note - block size 16 only */ - int ret; - unsigned char L[16]; - size_t olen; - - /* Calculate Ek(0) */ - memset( L, 0, 16 ); - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, L, 16, L, &olen ) ) != 0 ) - { - return( ret ); - } - - /* - * Generate K1 - * If MSB(L) = 0, then K1 = (L << 1) - * If MSB(L) = 1, then K1 = (L << 1) ^ Rb - */ - leftshift_onebit( L, ctx->K1 ); - ctx->K1[15] ^= Rb[L[0] >> 7]; /* "Constant-time" operation */ - - /* - * Generate K2 - * If MSB(K1) == 0, then K2 = (K1 << 1) - * If MSB(K1) == 1, then K2 = (K1 << 1) ^ Rb - */ - leftshift_onebit( ctx->K1, ctx->K2 ); - ctx->K2[15] ^= Rb[ctx->K1[0] >> 7]; /* "Constant-time" operation */ - - return( 0 ); -} - -int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - - cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_CMAC_BAD_INPUT ); - - if( cipher_info->block_size != 16 ) - return( MBEDTLS_ERR_CMAC_BAD_INPUT ); - - mbedtls_cipher_free( &ctx->cipher_ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - - return( generate_subkeys(ctx) ); -} - -/* - * Free context - */ -void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) -{ - mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) ); -} - -/* TODO: Use cipher padding function? */ -static void padding(const unsigned char *lastb, unsigned char *pad, const size_t length) -{ - size_t j; - - /* original last block */ - for( j = 0; j < 16; j++ ) - { - if( j < length ) - { - pad[j] = lastb[j]; - } - else if( j == length ) - { - pad[j] = 0x80; - } - else - { - pad[j] = 0x00; - } - } -} - -/* - * Generate tag on complete message - */ -static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, - unsigned char *tag, size_t tag_len ) -{ - unsigned char Mn[16]; - unsigned char M_last[16]; - unsigned char padded[16]; - int n, i, j, ret, flag; - size_t olen; - - /* - * Check length requirements: SP800-38B A - * 4 is a worst case bottom limit - */ - if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) - return( MBEDTLS_ERR_CMAC_BAD_INPUT ); - - /* TODO: Use cipher padding function? */ - // mbedtls_cipher_set_padding_mode( ctx->cipher, MBEDTLS_PADDING_ONE_AND_ZEROS ); - - n = ( length + 15 ) / 16; /* n is number of rounds */ - - if( n == 0 ) - { - n = 1; - flag = 0; - } - else - { - flag = ( ( length % 16 ) == 0); - } - - /* Calculate last block */ - if( flag ) - { - /* Last block is complete block */ - XOR_128( &input[16 * (n - 1)], ctx->K1, M_last ); - } - else - { - /* TODO: Use cipher padding function? */ - padding( &input[16 * (n - 1)], padded, length % 16 ); - XOR_128( padded, ctx->K2, M_last ); - } - - memset( Mn, 0, 16 ); - - for( j = 0; j < n - 1; j++ ) - { - UPDATE_CMAC(&input[16 * j]); - } - - UPDATE_CMAC(M_last); - - memcpy( tag, Mn, 16 ); - - return( 0 ); -} - -int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, - unsigned char *tag, size_t tag_len ) -{ - return( cmac_generate( ctx, length, input, tag, tag_len ) ); -} - -/* - * Authenticated decryption - */ -int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, - const unsigned char *tag, size_t tag_len ) -{ - int ret; - unsigned char check_tag[16]; - unsigned char i; - int diff; - - if( ( ret = cmac_generate( ctx, length, input, check_tag, tag_len) ) != 0 ) - { - return ret; - } - - /* Check tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - { - diff |= tag[i] ^ check_tag[i]; - } - - if( diff != 0 ) - { - return( MBEDTLS_ERR_CMAC_VERIFY_FAILED ); - } - - return( 0 ); -} - -int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *key, size_t key_length, - const unsigned char *input, - unsigned char *tag ) -{ - int ret; - unsigned char zero_key[16]; - unsigned char int_key[16]; - - if( key_length == 16 ) - { - /* Use key as is */ - memcpy(int_key, key, 16); - } - else - { - mbedtls_cmac_context zero_ctx; - - /* Key is AES_CMAC(0, key) */ - mbedtls_cmac_init( &zero_ctx ); - memset(zero_key, 0, 16); - ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, zero_key, 8 * sizeof zero_key ); - if( ret != 0 ) - { - return( ret ); - } - ret = mbedtls_cmac_generate( &zero_ctx, key_length, key, int_key, 16 ); - if( ret != 0 ) - { - return( ret ); - } - } - - ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES, int_key, 8 * sizeof int_key ); - if( ret != 0 ) - { - return( ret ); - } - return( mbedtls_cmac_generate( ctx, length, input, tag, 16 ) ); -} - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -/* - * Examples 1 to 4 from SP800-3B corrected Appendix D.1 - * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf - */ - -#define NB_CMAC_TESTS 4 -#define NB_PRF_TESTS 3 - -/* Key */ -static const unsigned char key[] = { - 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c -}; - -/* Assume we don't need to test Ek0 as this is a function of the cipher */ - -/* Subkey K1 */ -static const unsigned char K1[] = { - 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, - 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde -}; - -/* Subkey K2 */ -static const unsigned char K2[] = { - 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, - 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b -}; - -/* All Messages */ -static const unsigned char M[] = { - 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 -}; - -static const unsigned char T[NB_CMAC_TESTS][16] = { - { - 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 - } -}; - -/* Sizes in bytes */ -static const size_t Mlen[NB_CMAC_TESTS] = { - 0, - 16, - 40, - 64 -}; - -/* PRF K */ -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 - } -}; - - -int mbedtls_cmac_self_test( int verbose ) -{ - mbedtls_cmac_context ctx; - unsigned char tag[16]; - int i; - int ret; - - mbedtls_cmac_init( &ctx ); - - if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: setup failed" ); - - return( 1 ); - } - - if( ( memcmp( ctx.K1, K1, 16 ) != 0 ) || - ( memcmp( ctx.K2, K2, 16 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: subkey generation failed" ); - - return( 1 ); - } - - for( i = 0; i < NB_CMAC_TESTS; i++ ) - { - mbedtls_printf( " AES-128-CMAC #%u: ", i ); - - ret = mbedtls_cmac_generate( &ctx, Mlen[i], M, tag, 16 ); - if( ret != 0 || - memcmp( tag, T[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - ret = mbedtls_cmac_verify( &ctx, Mlen[i], M, T[i], 16 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - for( i = 0; i < NB_PRF_TESTS; i++ ) - { - mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i ); - - mbedtls_aes_cmac_prf_128( &ctx, 20, PRFK, PRFKlen[i], PRFM, tag); - - if( ret != 0 || - memcmp( tag, PRFT[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - mbedtls_cmac_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -#endif /* MBEDTLS_CMAC_C */ +/* + * NIST SP800-38B compliant CMAC implementation + * + * Copyright (C) 2006-2015, 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) + */ + +/* + * Definition of CMAC: + * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf + * RFC 4493 "The AES-CMAC Algorithm" + */ + +#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 + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * XOR 128-bit + */ +#define XOR_128(i1, i2, o) \ + for( i = 0; i < 16; i++ ) \ + ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; + +/* + * Update the CMAC state in Mn using an input block x + * TODO: Compiler optimisation + */ +#define UPDATE_CMAC( x ) \ + XOR_128( Mn, ( x ), Mn ); \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, Mn, 16, Mn, &olen ) ) != 0 ) \ + return( ret ); + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Initialize context + */ +void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_cmac_context ) ); +} + +/* + * Leftshift a 16-byte block by 1 bit + * \note output can be same as input + */ +static void leftshift_onebit(unsigned char *input, unsigned char *output) +{ + int i; + unsigned char temp; + unsigned char overflow = 0; + + for( i = 15; i >= 0; i-- ) + { + temp = input[i]; + output[i] = temp << 1; + output[i] |= overflow; + overflow = temp >> 7; + } + return; +} + +/* + * Generate subkeys + */ +static int generate_subkeys(mbedtls_cmac_context *ctx) +{ + static const unsigned char Rb[2] = {0x00, 0x87}; /* Note - block size 16 only */ + int ret; + unsigned char L[16]; + size_t olen; + + /* Calculate Ek(0) */ + memset( L, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, L, 16, L, &olen ) ) != 0 ) + { + return( ret ); + } + + /* + * Generate K1 + * If MSB(L) = 0, then K1 = (L << 1) + * If MSB(L) = 1, then K1 = (L << 1) ^ Rb + */ + leftshift_onebit( L, ctx->K1 ); + ctx->K1[15] ^= Rb[L[0] >> 7]; /* "Constant-time" operation */ + + /* + * Generate K2 + * If MSB(K1) == 0, then K2 = (K1 << 1) + * If MSB(K1) == 1, then K2 = (K1 << 1) ^ Rb + */ + leftshift_onebit( ctx->K1, ctx->K2 ); + ctx->K2[15] ^= Rb[ctx->K1[0] >> 7]; /* "Constant-time" operation */ + + return( 0 ); +} + +int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( generate_subkeys(ctx) ); +} + +/* + * Free context + */ +void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) ); +} + +/* TODO: Use cipher padding function? */ +static void padding(const unsigned char *lastb, unsigned char *pad, const size_t length) +{ + size_t j; + + /* original last block */ + for( j = 0; j < 16; j++ ) + { + if( j < length ) + { + pad[j] = lastb[j]; + } + else if( j == length ) + { + pad[j] = 0x80; + } + else + { + pad[j] = 0x00; + } + } +} + +/* + * Generate tag on complete message + */ +static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + unsigned char *tag, size_t tag_len ) +{ + unsigned char Mn[16]; + unsigned char M_last[16]; + unsigned char padded[16]; + int n, i, j, ret, flag; + size_t olen; + + /* + * Check length requirements: SP800-38B A + * 4 is a worst case bottom limit + */ + if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + + /* TODO: Use cipher padding function? */ + // mbedtls_cipher_set_padding_mode( ctx->cipher, MBEDTLS_PADDING_ONE_AND_ZEROS ); + + n = ( length + 15 ) / 16; /* n is number of rounds */ + + if( n == 0 ) + { + n = 1; + flag = 0; + } + else + { + flag = ( ( length % 16 ) == 0); + } + + /* Calculate last block */ + if( flag ) + { + /* Last block is complete block */ + XOR_128( &input[16 * (n - 1)], ctx->K1, M_last ); + } + else + { + /* TODO: Use cipher padding function? */ + padding( &input[16 * (n - 1)], padded, length % 16 ); + XOR_128( padded, ctx->K2, M_last ); + } + + memset( Mn, 0, 16 ); + + for( j = 0; j < n - 1; j++ ) + { + UPDATE_CMAC(&input[16 * j]); + } + + UPDATE_CMAC(M_last); + + memcpy( tag, Mn, 16 ); + + return( 0 ); +} + +int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + unsigned char *tag, size_t tag_len ) +{ + return( cmac_generate( ctx, length, input, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *input, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + if( ( ret = cmac_generate( ctx, length, input, check_tag, tag_len) ) != 0 ) + { + return ret; + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + { + diff |= tag[i] ^ check_tag[i]; + } + + if( diff != 0 ) + { + return( MBEDTLS_ERR_CMAC_VERIFY_FAILED ); + } + + return( 0 ); +} + +int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, + const unsigned char *key, size_t key_length, + const unsigned char *input, + unsigned char *tag ) +{ + int ret; + unsigned char zero_key[16]; + unsigned char int_key[16]; + + if( key_length == 16 ) + { + /* Use key as is */ + memcpy(int_key, key, 16); + } + else + { + mbedtls_cmac_context zero_ctx; + + /* Key is AES_CMAC(0, key) */ + mbedtls_cmac_init( &zero_ctx ); + memset(zero_key, 0, 16); + ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, zero_key, 8 * sizeof zero_key ); + if( ret != 0 ) + { + return( ret ); + } + ret = mbedtls_cmac_generate( &zero_ctx, key_length, key, int_key, 16 ); + if( ret != 0 ) + { + return( ret ); + } + } + + ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES, int_key, 8 * sizeof int_key ); + if( ret != 0 ) + { + return( ret ); + } + return( mbedtls_cmac_generate( ctx, length, input, tag, 16 ) ); +} + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * Examples 1 to 4 from SP800-3B corrected Appendix D.1 + * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf + */ + +#define NB_CMAC_TESTS 4 +#define NB_PRF_TESTS 3 + +/* Key */ +static const unsigned char key[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; + +/* Assume we don't need to test Ek0 as this is a function of the cipher */ + +/* Subkey K1 */ +static const unsigned char K1[] = { + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde +}; + +/* Subkey K2 */ +static const unsigned char K2[] = { + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b +}; + +/* All Messages */ +static const unsigned char M[] = { + 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 +}; + +static const unsigned char T[NB_CMAC_TESTS][16] = { + { + 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 + } +}; + +/* Sizes in bytes */ +static const size_t Mlen[NB_CMAC_TESTS] = { + 0, + 16, + 40, + 64 +}; + +/* PRF K */ +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 + } +}; + + +int mbedtls_cmac_self_test( int verbose ) +{ + mbedtls_cmac_context ctx; + unsigned char tag[16]; + int i; + int ret; + + mbedtls_cmac_init( &ctx ); + + if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: setup failed" ); + + return( 1 ); + } + + if( ( memcmp( ctx.K1, K1, 16 ) != 0 ) || + ( memcmp( ctx.K2, K2, 16 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: subkey generation failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_CMAC_TESTS; i++ ) + { + mbedtls_printf( " AES-128-CMAC #%u: ", i ); + + ret = mbedtls_cmac_generate( &ctx, Mlen[i], M, tag, 16 ); + if( ret != 0 || + memcmp( tag, T[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + ret = mbedtls_cmac_verify( &ctx, Mlen[i], M, T[i], 16 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i ); + + mbedtls_aes_cmac_prf_128( &ctx, 20, PRFK, PRFKlen[i], PRFM, tag); + + if( ret != 0 || + memcmp( tag, PRFT[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + mbedtls_cmac_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_CMAC_C */ From 690083c21d7254d4d1026779d8fa32e5a844bc1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 10:48:02 +0000 Subject: [PATCH 16/83] cmac: improve argument order and naming - always use the pattern "buffer, length" - avoid using unqualified "length" as a name when there are more than one --- include/mbedtls/cmac.h | 18 +++++++++--------- library/cmac.c | 38 +++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 282d549a4..3b5c13e99 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -77,24 +77,24 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); * \brief CMAC generate * * \param ctx CMAC context - * \param length length of the input data in bytes * \param input buffer holding the input data + * \param in_len length of the input data in bytes * \param tag buffer for holding the generated tag * \param tag_len length of the tag to generate in bytes * must be between 4, 6, 8, 10, 14 or 16 * * \return 0 if successful */ -int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, +int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, + const unsigned char *input, size_t in_len, unsigned char *tag, size_t tag_len ); /** * \brief CMAC verify * * \param ctx CMAC context - * \param length length of the input data in bytes * \param input buffer holding the input data + * \param in_len length of the input data in bytes * \param tag buffer holding the tag to verify * \param tag_len length of the tag to verify in bytes * must be 4, 6, 8, 10, 14 or 16 @@ -102,25 +102,25 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, * \return 0 if successful and authenticated, * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match */ -int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, +int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, + const unsigned char *input, size_t in_len, const unsigned char *tag, size_t tag_len ); /** * \brief AES-CMAC-128-PRF * * \param ctx CMAC context - * \param length length of the input data in bytes * \param key PRF key * \param key_len PRF key length * \param input buffer holding the input data + * \param in_len length of the input data in bytes * \param tag buffer holding the tag to verify (16 bytes) * * \return 0 if successful */ -int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, +int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, const unsigned char *key, size_t key_len, - const unsigned char *input, + const unsigned char *input, size_t in_len, unsigned char *tag ); #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) diff --git a/library/cmac.c b/library/cmac.c index 2ba58b6fa..0d93c9736 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -200,8 +200,8 @@ static void padding(const unsigned char *lastb, unsigned char *pad, const size_t /* * Generate tag on complete message */ -static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, +static int cmac_generate( mbedtls_cmac_context *ctx, + const unsigned char *input, size_t in_len, unsigned char *tag, size_t tag_len ) { unsigned char Mn[16]; @@ -211,7 +211,7 @@ static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, size_t olen; /* - * Check length requirements: SP800-38B A + * Check in_len requirements: SP800-38B A * 4 is a worst case bottom limit */ if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) @@ -220,7 +220,7 @@ static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, /* TODO: Use cipher padding function? */ // mbedtls_cipher_set_padding_mode( ctx->cipher, MBEDTLS_PADDING_ONE_AND_ZEROS ); - n = ( length + 15 ) / 16; /* n is number of rounds */ + n = ( in_len + 15 ) / 16; /* n is number of rounds */ if( n == 0 ) { @@ -229,7 +229,7 @@ static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, } else { - flag = ( ( length % 16 ) == 0); + flag = ( ( in_len % 16 ) == 0); } /* Calculate last block */ @@ -241,7 +241,7 @@ static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, else { /* TODO: Use cipher padding function? */ - padding( &input[16 * (n - 1)], padded, length % 16 ); + padding( &input[16 * (n - 1)], padded, in_len % 16 ); XOR_128( padded, ctx->K2, M_last ); } @@ -259,18 +259,18 @@ static int cmac_generate( mbedtls_cmac_context *ctx, size_t length, return( 0 ); } -int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, +int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, + const unsigned char *input, size_t in_len, unsigned char *tag, size_t tag_len ) { - return( cmac_generate( ctx, length, input, tag, tag_len ) ); + return( cmac_generate( ctx, input, in_len, tag, tag_len ) ); } /* * Authenticated decryption */ -int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, - const unsigned char *input, +int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, + const unsigned char *input, size_t in_len, const unsigned char *tag, size_t tag_len ) { int ret; @@ -278,7 +278,7 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, unsigned char i; int diff; - if( ( ret = cmac_generate( ctx, length, input, check_tag, tag_len) ) != 0 ) + if( ( ret = cmac_generate( ctx, input, in_len, check_tag, tag_len) ) != 0 ) { return ret; } @@ -297,9 +297,9 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, size_t length, return( 0 ); } -int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, +int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, const unsigned char *key, size_t key_length, - const unsigned char *input, + const unsigned char *input, size_t in_len, unsigned char *tag ) { int ret; @@ -323,7 +323,7 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, { return( ret ); } - ret = mbedtls_cmac_generate( &zero_ctx, key_length, key, int_key, 16 ); + ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 ); if( ret != 0 ) { return( ret ); @@ -335,7 +335,7 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, size_t length, { return( ret ); } - return( mbedtls_cmac_generate( ctx, length, input, tag, 16 ) ); + return( mbedtls_cmac_generate( ctx, input, in_len, tag, 16 ) ); } #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) @@ -473,7 +473,7 @@ int mbedtls_cmac_self_test( int verbose ) { mbedtls_printf( " AES-128-CMAC #%u: ", i ); - ret = mbedtls_cmac_generate( &ctx, Mlen[i], M, tag, 16 ); + ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 ); if( ret != 0 || memcmp( tag, T[i], 16 ) != 0 ) { @@ -482,7 +482,7 @@ int mbedtls_cmac_self_test( int verbose ) return( 1 ); } - ret = mbedtls_cmac_verify( &ctx, Mlen[i], M, T[i], 16 ); + ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T[i], 16 ); if( ret != 0 ) { if( verbose != 0 ) @@ -499,7 +499,7 @@ int mbedtls_cmac_self_test( int verbose ) { mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i ); - mbedtls_aes_cmac_prf_128( &ctx, 20, PRFK, PRFKlen[i], PRFM, tag); + mbedtls_aes_cmac_prf_128( &ctx, PRFK, PRFKlen[i], PRFM, 20, tag); if( ret != 0 || memcmp( tag, PRFT[i], 16 ) != 0 ) From 3da5402a89d7cadea3d316faca11116adf66d19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 11:00:47 +0000 Subject: [PATCH 17/83] cmac: fix whitespace/codingstyle issues --- library/cmac.c | 61 +++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 0d93c9736..fa32212eb 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -54,7 +54,7 @@ /* * XOR 128-bit */ -#define XOR_128(i1, i2, o) \ +#define XOR_128( i1, i2, o ) \ for( i = 0; i < 16; i++ ) \ ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; @@ -64,7 +64,8 @@ */ #define UPDATE_CMAC( x ) \ XOR_128( Mn, ( x ), Mn ); \ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, Mn, 16, Mn, &olen ) ) != 0 ) \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \ + Mn, 16, Mn, &olen ) ) != 0 ) \ return( ret ); /* Implementation that should never be optimized out by the compiler */ @@ -84,7 +85,7 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) * Leftshift a 16-byte block by 1 bit * \note output can be same as input */ -static void leftshift_onebit(unsigned char *input, unsigned char *output) +static void leftshift_onebit( unsigned char *input, unsigned char *output ) { int i; unsigned char temp; @@ -97,27 +98,29 @@ static void leftshift_onebit(unsigned char *input, unsigned char *output) output[i] |= overflow; overflow = temp >> 7; } + return; } /* * Generate subkeys */ -static int generate_subkeys(mbedtls_cmac_context *ctx) +static int generate_subkeys( mbedtls_cmac_context *ctx ) { - static const unsigned char Rb[2] = {0x00, 0x87}; /* Note - block size 16 only */ + static const unsigned char Rb[2] = { 0x00, 0x87 }; /* block size 16 only */ int ret; unsigned char L[16]; size_t olen; /* Calculate Ek(0) */ memset( L, 0, 16 ); - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, L, 16, L, &olen ) ) != 0 ) + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, + L, 16, L, &olen ) ) != 0 ) { return( ret ); } - /* + /* * Generate K1 * If MSB(L) = 0, then K1 = (L << 1) * If MSB(L) = 1, then K1 = (L << 1) ^ Rb @@ -132,7 +135,7 @@ static int generate_subkeys(mbedtls_cmac_context *ctx) */ leftshift_onebit( ctx->K1, ctx->K2 ); ctx->K2[15] ^= Rb[ctx->K1[0] >> 7]; /* "Constant-time" operation */ - + return( 0 ); } @@ -144,7 +147,8 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, int ret; const mbedtls_cipher_info_t *cipher_info; - cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, + MBEDTLS_MODE_ECB ); if( cipher_info == NULL ) return( MBEDTLS_ERR_CMAC_BAD_INPUT ); @@ -157,12 +161,12 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, return( ret ); if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) + MBEDTLS_ENCRYPT ) ) != 0 ) { return( ret ); } - return( generate_subkeys(ctx) ); + return( generate_subkeys( ctx ) ); } /* @@ -175,7 +179,9 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) } /* TODO: Use cipher padding function? */ -static void padding(const unsigned char *lastb, unsigned char *pad, const size_t length) +static void padding( const unsigned char *lastb, + unsigned char *pad, + const size_t length ) { size_t j; @@ -236,12 +242,12 @@ static int cmac_generate( mbedtls_cmac_context *ctx, if( flag ) { /* Last block is complete block */ - XOR_128( &input[16 * (n - 1)], ctx->K1, M_last ); + XOR_128( &input[16 * ( n - 1 )], ctx->K1, M_last ); } else { /* TODO: Use cipher padding function? */ - padding( &input[16 * (n - 1)], padded, in_len % 16 ); + padding( &input[16 * ( n - 1 )], padded, in_len % 16 ); XOR_128( padded, ctx->K2, M_last ); } @@ -249,10 +255,10 @@ static int cmac_generate( mbedtls_cmac_context *ctx, for( j = 0; j < n - 1; j++ ) { - UPDATE_CMAC(&input[16 * j]); + UPDATE_CMAC( &input[16 * j] ); } - UPDATE_CMAC(M_last); + UPDATE_CMAC( M_last ); memcpy( tag, Mn, 16 ); @@ -277,8 +283,8 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, unsigned char check_tag[16]; unsigned char i; int diff; - - if( ( ret = cmac_generate( ctx, input, in_len, check_tag, tag_len) ) != 0 ) + + if( ( ret = cmac_generate( ctx, input, in_len, check_tag, tag_len ) ) != 0 ) { return ret; } @@ -309,7 +315,7 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, if( key_length == 16 ) { /* Use key as is */ - memcpy(int_key, key, 16); + memcpy( int_key, key, 16 ); } else { @@ -317,8 +323,9 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, /* Key is AES_CMAC(0, key) */ mbedtls_cmac_init( &zero_ctx ); - memset(zero_key, 0, 16); - ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, zero_key, 8 * sizeof zero_key ); + memset( zero_key, 0, 16 ); + ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, + zero_key, 8 * sizeof zero_key ); if( ret != 0 ) { return( ret ); @@ -330,7 +337,8 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, } } - ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES, int_key, 8 * sizeof int_key ); + ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES, + int_key, 8 * sizeof int_key ); if( ret != 0 ) { return( ret ); @@ -424,7 +432,7 @@ static const size_t PRFKlen[NB_PRF_TESTS] = { 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 + 0x10, 0x11, 0x12, 0x13 }; static const unsigned char PRFT[NB_PRF_TESTS][16] = { @@ -472,7 +480,7 @@ int mbedtls_cmac_self_test( int verbose ) for( i = 0; i < NB_CMAC_TESTS; i++ ) { mbedtls_printf( " AES-128-CMAC #%u: ", i ); - + ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 ); if( ret != 0 || memcmp( tag, T[i], 16 ) != 0 ) @@ -482,6 +490,7 @@ int mbedtls_cmac_self_test( int verbose ) return( 1 ); } + ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T[i], 16 ); if( ret != 0 ) { @@ -499,8 +508,8 @@ int mbedtls_cmac_self_test( int verbose ) { mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i ); - mbedtls_aes_cmac_prf_128( &ctx, PRFK, PRFKlen[i], PRFM, 20, tag); - + mbedtls_aes_cmac_prf_128( &ctx, PRFK, PRFKlen[i], PRFM, 20, tag ); + if( ret != 0 || memcmp( tag, PRFT[i], 16 ) != 0 ) { From a610b4c04beb60734a8bec3f0eb228be31d20afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 11:28:16 +0000 Subject: [PATCH 18/83] cmac: factor multiply by u to its own function We're doing exactly the same operation for K1 and K2. --- library/cmac.c | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index fa32212eb..8f6574a20 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -82,24 +82,28 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) } /* - * Leftshift a 16-byte block by 1 bit - * \note output can be same as input + * Multiply by u in GF(2^128) + * + * As explained in the paper, this can be achieved as + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ Rb + * with Rb = 0x87 + * + * Input and output MUST not point to the same buffer */ -static void leftshift_onebit( unsigned char *input, unsigned char *output ) +static void multiply_by_u( unsigned char *output, const unsigned char *input ) { - int i; - unsigned char temp; + static const unsigned char Rb[2] = { 0x00, 0x87 }; /* block size 16 only */ unsigned char overflow = 0; + int i; for( i = 15; i >= 0; i-- ) { - temp = input[i]; - output[i] = temp << 1; - output[i] |= overflow; - overflow = temp >> 7; + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; } - return; + output[15] ^= Rb[input[0] >> 7]; /* "Constant-time" operation */ } /* @@ -107,7 +111,6 @@ static void leftshift_onebit( unsigned char *input, unsigned char *output ) */ static int generate_subkeys( mbedtls_cmac_context *ctx ) { - static const unsigned char Rb[2] = { 0x00, 0x87 }; /* block size 16 only */ int ret; unsigned char L[16]; size_t olen; @@ -121,20 +124,10 @@ static int generate_subkeys( mbedtls_cmac_context *ctx ) } /* - * Generate K1 - * If MSB(L) = 0, then K1 = (L << 1) - * If MSB(L) = 1, then K1 = (L << 1) ^ Rb + * Generate K1 and K2 */ - leftshift_onebit( L, ctx->K1 ); - ctx->K1[15] ^= Rb[L[0] >> 7]; /* "Constant-time" operation */ - - /* - * Generate K2 - * If MSB(K1) == 0, then K2 = (K1 << 1) - * If MSB(K1) == 1, then K2 = (K1 << 1) ^ Rb - */ - leftshift_onebit( ctx->K1, ctx->K2 ); - ctx->K2[15] ^= Rb[ctx->K1[0] >> 7]; /* "Constant-time" operation */ + multiply_by_u( ctx->K1, L ); + multiply_by_u( ctx->K2, ctx->K1 ); return( 0 ); } From d6cf75474bc7432e1d203c2a47db60ae6bf2bd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 11:30:00 +0000 Subject: [PATCH 19/83] cmac: zeroize sensitive intermediate values --- library/cmac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/cmac.c b/library/cmac.c index 8f6574a20..87846a617 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -129,6 +129,8 @@ static int generate_subkeys( mbedtls_cmac_context *ctx ) multiply_by_u( ctx->K1, L ); multiply_by_u( ctx->K2, ctx->K1 ); + mbedtls_zeroize( L, sizeof( L ) ); + return( 0 ); } @@ -336,6 +338,9 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, { return( ret ); } + + mbedtls_zeroize( int_key, sizeof( int_key ) ); + return( mbedtls_cmac_generate( ctx, input, in_len, tag, 16 ) ); } From 475f06f60980a99fd9618827dfb91ad895158fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 13:05:03 +0000 Subject: [PATCH 20/83] cmac: make subkey gen more constant-time The previous version had secret-dependent memory accesses. While it was probably not an issue in practice cause the two bytes of the array are probably on the same cache line anyway, as a matter of principle this should be avoided. --- library/cmac.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 87846a617..af0439a43 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -93,7 +93,8 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) */ static void multiply_by_u( unsigned char *output, const unsigned char *input ) { - static const unsigned char Rb[2] = { 0x00, 0x87 }; /* block size 16 only */ + const unsigned char Rb = 0x87; /* block size 16 only */ + unsigned char mask; unsigned char overflow = 0; int i; @@ -103,7 +104,20 @@ static void multiply_by_u( unsigned char *output, const unsigned char *input ) overflow = input[i] >> 7; } - output[15] ^= Rb[input[0] >> 7]; /* "Constant-time" operation */ + /* 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[15] ^= Rb & mask; } /* From d2c3d3eddb7d55e7547f04ae8fbc780b5e5b473f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 13:14:04 +0000 Subject: [PATCH 21/83] cmac: clean up padding function and comments --- library/cmac.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index af0439a43..1287c820a 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -187,28 +187,26 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) ); } -/* TODO: Use cipher padding function? */ -static void padding( const unsigned char *lastb, - unsigned char *pad, - const size_t length ) +/* + * 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 padding( unsigned char padded_block[16], + const unsigned char *last_block, + size_t length ) { size_t j; - /* original last block */ for( j = 0; j < 16; j++ ) { if( j < length ) - { - pad[j] = lastb[j]; - } + padded_block[j] = last_block[j]; else if( j == length ) - { - pad[j] = 0x80; - } + padded_block[j] = 0x80; else - { - pad[j] = 0x00; - } + padded_block[j] = 0x00; } } @@ -232,9 +230,6 @@ static int cmac_generate( mbedtls_cmac_context *ctx, if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) return( MBEDTLS_ERR_CMAC_BAD_INPUT ); - /* TODO: Use cipher padding function? */ - // mbedtls_cipher_set_padding_mode( ctx->cipher, MBEDTLS_PADDING_ONE_AND_ZEROS ); - n = ( in_len + 15 ) / 16; /* n is number of rounds */ if( n == 0 ) @@ -255,8 +250,7 @@ static int cmac_generate( mbedtls_cmac_context *ctx, } else { - /* TODO: Use cipher padding function? */ - padding( &input[16 * ( n - 1 )], padded, in_len % 16 ); + padding( padded, &input[16 * ( n - 1 )], in_len % 16 ); XOR_128( padded, ctx->K2, M_last ); } From 2c0630636409b88f05c3e0010370a7b48699f1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 14:27:55 +0000 Subject: [PATCH 22/83] cmac: some more padding-related tune-ups - use one less temporary buffer - pedantic: in_len + 15 was a potential overflow - use a more explicit name instead of 'flag' - Mn was a bit misleading --- library/cmac.c | 51 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 1287c820a..d9e94a6fc 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -54,19 +54,20 @@ /* * XOR 128-bit */ -#define XOR_128( i1, i2, o ) \ +#define XOR_128( o, i1, i2 ) \ for( i = 0; i < 16; i++ ) \ ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; /* - * Update the CMAC state in Mn using an input block x - * TODO: Compiler optimisation + * Update the CMAC state using an input block x */ #define UPDATE_CMAC( x ) \ - XOR_128( Mn, ( x ), Mn ); \ +do { \ + XOR_128( state, ( x ), state ); \ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \ - Mn, 16, Mn, &olen ) ) != 0 ) \ - return( ret ); + state, 16, state, &olen ) ) != 0 ) \ + return( ret ); \ +} while( 0 ) /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { @@ -217,10 +218,9 @@ static int cmac_generate( mbedtls_cmac_context *ctx, const unsigned char *input, size_t in_len, unsigned char *tag, size_t tag_len ) { - unsigned char Mn[16]; + unsigned char state[16]; unsigned char M_last[16]; - unsigned char padded[16]; - int n, i, j, ret, flag; + int n, i, j, ret, needs_padding; size_t olen; /* @@ -230,40 +230,33 @@ static int cmac_generate( mbedtls_cmac_context *ctx, if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) return( MBEDTLS_ERR_CMAC_BAD_INPUT ); - n = ( in_len + 15 ) / 16; /* n is number of rounds */ - - if( n == 0 ) - { - n = 1; - flag = 0; - } + if( in_len == 0 ) + needs_padding = 1; else - { - flag = ( ( in_len % 16 ) == 0); - } + needs_padding = in_len % 16 != 0; + + n = in_len / 16 + needs_padding; /* Calculate last block */ - if( flag ) + if( needs_padding ) { - /* Last block is complete block */ - XOR_128( &input[16 * ( n - 1 )], ctx->K1, M_last ); + padding( M_last, input + 16 * ( n - 1 ), in_len % 16 ); + XOR_128( M_last, M_last, ctx->K2 ); } else { - padding( padded, &input[16 * ( n - 1 )], in_len % 16 ); - XOR_128( padded, ctx->K2, M_last ); + /* Last block is complete block */ + XOR_128( M_last, input + 16 * ( n - 1 ), ctx->K1 ); } - memset( Mn, 0, 16 ); + memset( state, 0, 16 ); for( j = 0; j < n - 1; j++ ) - { - UPDATE_CMAC( &input[16 * j] ); - } + UPDATE_CMAC( input + 16 * j ); UPDATE_CMAC( M_last ); - memcpy( tag, Mn, 16 ); + memcpy( tag, state, 16 ); return( 0 ); } From d18c70708e716da885cd2021c58ab5fd3e7d6d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 15:03:05 +0000 Subject: [PATCH 23/83] cmac: reduce visibility of macros The #undef is usefull for people who want to to amalgamated releases --- library/cmac.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index d9e94a6fc..35c32f3a5 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -46,29 +46,6 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ -/* - * Macros for common operations. - * Results in smaller compiled code than static inline functions. - */ - -/* - * XOR 128-bit - */ -#define XOR_128( o, i1, i2 ) \ - for( i = 0; i < 16; i++ ) \ - ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; - -/* - * Update the CMAC state using an input block x - */ -#define UPDATE_CMAC( x ) \ -do { \ - XOR_128( state, ( x ), state ); \ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \ - state, 16, state, &olen ) ) != 0 ) \ - return( ret ); \ -} while( 0 ) - /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; @@ -211,6 +188,25 @@ static void padding( unsigned char padded_block[16], } } +/* + * XOR 128-bit + * Here, macro results in smaller compiled code than static inline function + */ +#define XOR_128( o, i1, i2 ) \ + for( i = 0; i < 16; i++ ) \ + ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; + +/* + * Update the CMAC state using an input block x + */ +#define UPDATE_CMAC( x ) \ +do { \ + XOR_128( state, ( x ), state ); \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \ + state, 16, state, &olen ) ) != 0 ) \ + return( ret ); \ +} while( 0 ) + /* * Generate tag on complete message */ @@ -261,6 +257,9 @@ static int cmac_generate( mbedtls_cmac_context *ctx, return( 0 ); } +#undef XOR_128 +#undef UPDATE_CMAC + int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, const unsigned char *input, size_t in_len, unsigned char *tag, size_t tag_len ) From ab9c5fd9b3eb2f5afbc941b09dfd9d69388ab69c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 15:05:57 +0000 Subject: [PATCH 24/83] cmac: avoid useless wrapping of function probably a leftover from an earlier stage --- library/cmac.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 35c32f3a5..ff7cb2109 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -210,9 +210,10 @@ do { \ /* * Generate tag on complete message */ -static int cmac_generate( mbedtls_cmac_context *ctx, - const unsigned char *input, size_t in_len, - unsigned char *tag, size_t tag_len ) +int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, + const unsigned char *input, size_t in_len, + unsigned char *tag, size_t tag_len ) + { unsigned char state[16]; unsigned char M_last[16]; @@ -260,13 +261,6 @@ static int cmac_generate( mbedtls_cmac_context *ctx, #undef XOR_128 #undef UPDATE_CMAC -int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, - const unsigned char *input, size_t in_len, - unsigned char *tag, size_t tag_len ) -{ - return( cmac_generate( ctx, input, in_len, tag, tag_len ) ); -} - /* * Authenticated decryption */ @@ -279,7 +273,8 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, unsigned char i; int diff; - if( ( ret = cmac_generate( ctx, input, in_len, check_tag, tag_len ) ) != 0 ) + if( ( ret = mbedtls_cmac_generate( ctx, input, in_len, + check_tag, tag_len ) ) != 0 ) { return ret; } From 7b555f292873e7e87ea90a9bc34054797bf035f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jan 2016 15:09:09 +0000 Subject: [PATCH 25/83] cmac: more cosmetic changes --- include/mbedtls/cmac.h | 2 ++ library/cmac.c | 46 +++++++++++++++++++++--------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 3b5c13e99..c2ae83be1 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -108,6 +108,7 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, /** * \brief AES-CMAC-128-PRF + * TODO: add reference to the standard * * \param ctx CMAC context * \param key PRF key @@ -115,6 +116,7 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, * \param input buffer holding the input data * \param in_len length of the input data in bytes * \param tag buffer holding the tag to verify (16 bytes) + * TODO: update description of tag * * \return 0 if successful */ diff --git a/library/cmac.c b/library/cmac.c index ff7cb2109..23b8044ff 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -69,7 +69,8 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) * * Input and output MUST not point to the same buffer */ -static void multiply_by_u( unsigned char *output, const unsigned char *input ) +static void cmac_multiply_by_u( unsigned char *output, + const unsigned char *input ) { const unsigned char Rb = 0x87; /* block size 16 only */ unsigned char mask; @@ -101,7 +102,7 @@ static void multiply_by_u( unsigned char *output, const unsigned char *input ) /* * Generate subkeys */ -static int generate_subkeys( mbedtls_cmac_context *ctx ) +static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) { int ret; unsigned char L[16]; @@ -118,14 +119,17 @@ static int generate_subkeys( mbedtls_cmac_context *ctx ) /* * Generate K1 and K2 */ - multiply_by_u( ctx->K1, L ); - multiply_by_u( ctx->K2, ctx->K1 ); + cmac_multiply_by_u( ctx->K1, L ); + cmac_multiply_by_u( ctx->K2, ctx->K1 ); mbedtls_zeroize( L, sizeof( L ) ); return( 0 ); } +/* + * Set key and prepare context for use + */ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, @@ -153,7 +157,7 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, return( ret ); } - return( generate_subkeys( ctx ) ); + return( cmac_generate_subkeys( ctx ) ); } /* @@ -171,9 +175,9 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) * 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 padding( unsigned char padded_block[16], - const unsigned char *last_block, - size_t length ) +static void cmac_pad( unsigned char padded_block[16], + const unsigned char *last_block, + size_t length ) { size_t j; @@ -237,7 +241,7 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, /* Calculate last block */ if( needs_padding ) { - padding( M_last, input + 16 * ( n - 1 ), in_len % 16 ); + cmac_pad( M_last, input + 16 * ( n - 1 ), in_len % 16 ); XOR_128( M_last, M_last, ctx->K2 ); } else @@ -262,7 +266,7 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, #undef UPDATE_CMAC /* - * Authenticated decryption + * Verify tag on complete message */ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, const unsigned char *input, size_t in_len, @@ -281,18 +285,19 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, /* Check tag in "constant-time" */ for( diff = 0, i = 0; i < tag_len; i++ ) - { diff |= tag[i] ^ check_tag[i]; - } if( diff != 0 ) - { return( MBEDTLS_ERR_CMAC_VERIFY_FAILED ); - } return( 0 ); } +/* + * PRF based on CMAC with AES-128 + * TODO: add reference to the standard + * TODO: do we need to take a cmac_context as an argument here? + */ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, const unsigned char *key, size_t key_length, const unsigned char *input, size_t in_len, @@ -317,22 +322,17 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, zero_key, 8 * sizeof zero_key ); if( ret != 0 ) - { return( ret ); - } + ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 ); if( ret != 0 ) - { return( ret ); - } } ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES, int_key, 8 * sizeof int_key ); if( ret != 0 ) - { return( ret ); - } mbedtls_zeroize( int_key, sizeof( int_key ) ); @@ -341,7 +341,7 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /* - * Examples 1 to 4 from SP800-3B corrected Appendix D.1 + * Examples 1 to 4 from SP800-38B corrected Appendix D.1 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf */ @@ -456,7 +456,7 @@ int mbedtls_cmac_self_test( int verbose ) if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) { if( verbose != 0 ) - mbedtls_printf( " CMAC: setup failed" ); + mbedtls_printf( " CMAC: setup failed\n" ); return( 1 ); } @@ -465,7 +465,7 @@ int mbedtls_cmac_self_test( int verbose ) ( memcmp( ctx.K2, K2, 16 ) != 0 ) ) { if( verbose != 0 ) - mbedtls_printf( " CMAC: subkey generation failed" ); + mbedtls_printf( " CMAC: subkey generation failed\n" ); return( 1 ); } From 8262ac3b545f17c0cc8937dad21c25bc26f77f31 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Tue, 17 May 2016 10:17:31 -0700 Subject: [PATCH 26/83] Added cmac.o to libary/Makefile --- library/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/Makefile b/library/Makefile index 4b296282b..28f92315a 100644 --- a/library/Makefile +++ b/library/Makefile @@ -48,9 +48,9 @@ OBJS_CRYPTO= aes.o aesni.o arc4.o \ 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 \ From b0c3c43dec60dd9442ee757d4b2fdbc44057de3a Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Wed, 18 May 2016 14:29:51 -0700 Subject: [PATCH 27/83] CMAC support for cipher with 64bit blocks (DES/3DES) --- include/mbedtls/cmac.h | 10 +- library/cmac.c | 519 ++++++++++++++++++++++++++++++++++------- 2 files changed, 442 insertions(+), 87 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index c2ae83be1..3e02f912e 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -37,8 +37,8 @@ extern "C" { */ typedef struct { mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ - unsigned char K1[16]; - unsigned char K2[16]; + unsigned char* K1; + unsigned char* K2; } mbedtls_cmac_context; @@ -108,9 +108,8 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, /** * \brief AES-CMAC-128-PRF - * TODO: add reference to the standard + * See RFC * - * \param ctx CMAC context * \param key PRF key * \param key_len PRF key length * \param input buffer holding the input data @@ -120,8 +119,7 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, * * \return 0 if successful */ -int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, - const unsigned char *key, size_t key_len, +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, const unsigned char *input, size_t in_len, unsigned char *tag ); diff --git a/library/cmac.c b/library/cmac.c index 23b8044ff..ab4a82ddf 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -60,24 +60,39 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) } /* - * Multiply by u in GF(2^128) + * Multiplication by u in the Galois field of GF(2^n) * - * As explained in the paper, this can be achieved as + * As explained in the paper, this can computed: * If MSB(p) = 0, then p = (p << 1) - * If MSB(p) = 1, then p = (p << 1) ^ Rb - * with Rb = 0x87 + * 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. */ -static void cmac_multiply_by_u( unsigned char *output, - const unsigned char *input ) +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize) { - const unsigned char Rb = 0x87; /* block size 16 only */ - unsigned char mask; - unsigned char overflow = 0; - int i; - for( i = 15; i >= 0; i-- ) + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i, starting_index; + + starting_index = blocksize -1; + + if(blocksize == 16){ + R_n = R_128; + } else if(blocksize == 8) { + R_n = R_64; + } else { + return MBEDTLS_ERR_CMAC_BAD_INPUT; + } + + + for( i = starting_index; i >= 0; i-- ) { output[i] = input[i] << 1 | overflow; overflow = input[i] >> 7; @@ -96,7 +111,8 @@ static void cmac_multiply_by_u( unsigned char *output, #pragma warning( pop ) #endif - output[15] ^= Rb & mask; + output[starting_index] ^= R_n & mask; + return 0; } /* @@ -104,27 +120,35 @@ static void cmac_multiply_by_u( unsigned char *output, */ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) { - int ret; - unsigned char L[16]; - size_t olen; + int ret, keybytes; + unsigned char *L; + size_t olen, block_size; + + ret = 0; + block_size = ctx->cipher_ctx.cipher_info->block_size; + + L = mbedtls_calloc(block_size, sizeof(unsigned char)); /* Calculate Ek(0) */ - memset( L, 0, 16 ); + memset( L, 0, block_size ); if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, - L, 16, L, &olen ) ) != 0 ) + L, block_size, L, &olen ) ) != 0 ) { - return( ret ); + goto exit; } /* * Generate K1 and K2 */ - cmac_multiply_by_u( ctx->K1, L ); - cmac_multiply_by_u( ctx->K2, ctx->K1 ); + if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size) ) != 0 ) + goto exit; + if( ( cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size) ) != 0 ) + goto exit; - mbedtls_zeroize( L, sizeof( L ) ); - - return( 0 ); + exit: + mbedtls_zeroize( L, sizeof( L ) ); + free(L); + return ret; } /* @@ -135,7 +159,7 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, const unsigned char *key, unsigned int keybits ) { - int ret; + int ret, blocksize; const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, @@ -143,8 +167,8 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, if( cipher_info == NULL ) return( MBEDTLS_ERR_CMAC_BAD_INPUT ); - if( cipher_info->block_size != 16 ) - return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); + ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); mbedtls_cipher_free( &ctx->cipher_ctx ); @@ -165,8 +189,15 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, */ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) { + int block_size; + block_size = ctx->cipher_ctx.cipher_info->block_size; + mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) ); + + mbedtls_zeroize(ctx->K1, block_size * sizeof( unsigned char ) ); + mbedtls_zeroize(ctx->K2, block_size * sizeof( unsigned char ) ); + mbedtls_free( ctx->K1 ); + mbedtls_free( ctx->K2 ); } /* @@ -176,16 +207,17 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) * 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[16], + size_t padded_block_len, const unsigned char *last_block, - size_t length ) + size_t last_block_len ) { size_t j; - for( j = 0; j < 16; j++ ) + for( j = 0; j < padded_block_len; j++ ) { - if( j < length ) + if( j < last_block_len ) padded_block[j] = last_block[j]; - else if( j == length ) + else if( j == last_block_len ) padded_block[j] = 0x80; else padded_block[j] = 0x00; @@ -193,11 +225,11 @@ static void cmac_pad( unsigned char padded_block[16], } /* - * XOR 128-bit + * XOR Block * Here, macro results in smaller compiled code than static inline function */ -#define XOR_128( o, i1, i2 ) \ - for( i = 0; i < 16; i++ ) \ +#define XOR_BLOCK( o, i1, i2 ) \ + for( i = 0; i < block_size; i++ ) \ ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; /* @@ -205,9 +237,10 @@ static void cmac_pad( unsigned char padded_block[16], */ #define UPDATE_CMAC( x ) \ do { \ - XOR_128( state, ( x ), state ); \ + XOR_BLOCK( state, ( x ), state ); \ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \ - state, 16, state, &olen ) ) != 0 ) \ + state, block_size, \ + state, &olen ) ) != 0 ) \ return( ret ); \ } while( 0 ) @@ -219,50 +252,61 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, unsigned char *tag, size_t tag_len ) { - unsigned char state[16]; - unsigned char M_last[16]; + + unsigned char *state; + unsigned char *M_last; int n, i, j, ret, needs_padding; - size_t olen; + size_t olen, block_size; + + + ret = 0; + block_size = ctx->cipher_ctx.cipher_info->block_size; + + state = mbedtls_calloc(block_size, sizeof(unsigned char) ); + M_last = mbedtls_calloc(block_size, sizeof(unsigned char) ); /* * Check in_len requirements: SP800-38B A * 4 is a worst case bottom limit */ - if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + if( tag_len < 4 || tag_len > block_size || tag_len % 2 != 0 ) return( MBEDTLS_ERR_CMAC_BAD_INPUT ); if( in_len == 0 ) needs_padding = 1; else - needs_padding = in_len % 16 != 0; + needs_padding = in_len % block_size != 0; - n = in_len / 16 + needs_padding; + n = in_len / block_size + needs_padding; /* Calculate last block */ if( needs_padding ) { - cmac_pad( M_last, input + 16 * ( n - 1 ), in_len % 16 ); - XOR_128( M_last, M_last, ctx->K2 ); + cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size ); + XOR_BLOCK( M_last, M_last, ctx->K2 ); } else { /* Last block is complete block */ - XOR_128( M_last, input + 16 * ( n - 1 ), ctx->K1 ); + XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 ); } - memset( state, 0, 16 ); + memset( state, 0, block_size ); for( j = 0; j < n - 1; j++ ) - UPDATE_CMAC( input + 16 * j ); + UPDATE_CMAC( input + block_size * j ); UPDATE_CMAC( M_last ); - memcpy( tag, state, 16 ); + memcpy( tag, state, block_size ); - return( 0 ); + exit: + free(state); + free(M_last); + return( ret ); } -#undef XOR_128 +#undef XOR_BLOCK #undef UPDATE_CMAC /* @@ -273,14 +317,17 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, const unsigned char *tag, size_t tag_len ) { int ret; - unsigned char check_tag[16]; + unsigned char *check_tag; unsigned char i; int diff; + check_tag = mbedtls_calloc(ctx->cipher_ctx.cipher_info->block_size, + sizeof(unsigned char) ); + if( ( ret = mbedtls_cmac_generate( ctx, input, in_len, check_tag, tag_len ) ) != 0 ) { - return ret; + goto exit; } /* Check tag in "constant-time" */ @@ -288,25 +335,29 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, diff |= tag[i] ^ check_tag[i]; if( diff != 0 ) - return( MBEDTLS_ERR_CMAC_VERIFY_FAILED ); + ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED; + goto exit; - return( 0 ); + exit: + free(check_tag); + return ret; } /* * PRF based on CMAC with AES-128 - * TODO: add reference to the standard - * TODO: do we need to take a cmac_context as an argument here? + * See RFC 4615 */ -int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, - const unsigned char *key, size_t key_length, +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, const unsigned char *input, size_t in_len, unsigned char *tag ) { int ret; + mbedtls_cmac_context ctx; unsigned char zero_key[16]; unsigned char int_key[16]; + mbedtls_cmac_init(&ctx); + if( key_length == 16 ) { /* Use key as is */ @@ -322,21 +373,27 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, zero_key, 8 * sizeof zero_key ); if( ret != 0 ) - return( ret ); + goto exit; ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 ); if( ret != 0 ) - return( ret ); + goto exit; } - ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES, + ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, int_key, 8 * sizeof int_key ); if( ret != 0 ) - return( ret ); + goto exit; mbedtls_zeroize( int_key, sizeof( int_key ) ); - return( mbedtls_cmac_generate( ctx, input, in_len, tag, 16 ) ); + ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 ); + + exit: + mbedtls_cmac_free(&ctx); + return( ret ); + + } #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) @@ -345,30 +402,116 @@ int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx, * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf */ -#define NB_CMAC_TESTS 4 +#define NB_CMAC_TESTS_AES_128 4 +#define NB_CMAC_TESTS_AES_192 4 +#define NB_CMAC_TESTS_AES_256 4 +#define NB_CMAC_TESTS_3DES 4 + #define NB_PRF_TESTS 3 -/* Key */ -static const unsigned char key[] = { +/* AES 128 Key */ +static const unsigned char aes_128_key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; +/* AES 192 Key */ +static const unsigned char aes_192_key[] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; + +/* AES 256 Key */ +static const unsigned char aes_256_key[] = { + 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 +}; + +/* 3DES 112 bit key */ +static const unsigned char des3_2key_key[] = { + 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5, + 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38, + 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5 +}; + +/* 3DES 168 bit key */ +static const unsigned char des3_3key_key[] = { + 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62, + 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58, + 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5 +}; + + + /* Assume we don't need to test Ek0 as this is a function of the cipher */ /* Subkey K1 */ -static const unsigned char K1[] = { +static const unsigned char aes_128_k1[] = { 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde }; /* Subkey K2 */ -static const unsigned char K2[] = { +static const unsigned char aes_128_k2[] = { 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b }; -/* All Messages */ + + +/* Subkey K1 */ +static const unsigned char aes_192_k1[] = { + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 +}; + +/* Subkey K2 */ +static const unsigned char aes_192_k2[] = { + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c +}; + +/* Subkey K1 */ +static const unsigned char aes_256_k1[] = { + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f +}; + +/* Subkey K2 */ +static const unsigned char aes_256_k2[] = { + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 +}; + + +/* Subkey K1 */ +static const unsigned char des3_2key_k1[] = { + 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef +}; + +/* Subkey K2 */ +static const unsigned char des3_2key_k2[] = { + 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5 +}; + +/* Subkey K1 */ +static const unsigned char des3_3key_k1[] = { + 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f +}; + +/* Subkey K2 */ +static const unsigned char des3_3key_k2[] = { + 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5 +}; + +/* Assume we don't need to test Ek0 as this is a function of the cipher */ + + + +/* All Messages are the same. The difference is the length */ static const unsigned char M[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, @@ -380,7 +523,7 @@ static const unsigned char M[] = { 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; -static const unsigned char T[NB_CMAC_TESTS][16] = { +static const unsigned char T_128[NB_CMAC_TESTS_3DES][16] = { { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 @@ -400,13 +543,91 @@ static const unsigned char T[NB_CMAC_TESTS][16] = { }; /* Sizes in bytes */ -static const size_t Mlen[NB_CMAC_TESTS] = { +static const size_t Mlen[NB_CMAC_TESTS_AES_192] = { 0, 16, 40, 64 }; +static const size_t Mlen_3des[NB_CMAC_TESTS_AES_192] = { + 0, + 8, + 20, + 32 +}; + + + +static const unsigned char T_256[NB_CMAC_TESTS_AES_192][16] = { + { + 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 + } +}; + +static const unsigned char T_192[NB_CMAC_TESTS_AES_192][16] = { + { + 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 + } +}; + +static const unsigned char T_3des_2key[NB_CMAC_TESTS_AES_192][16] = { + { + 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 + } +}; + +static const unsigned char T_3des_3key[NB_CMAC_TESTS_AES_192][16] = { + { + 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 + } +}; + + /* PRF K */ static const unsigned char PRFK[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -453,7 +674,8 @@ int mbedtls_cmac_self_test( int verbose ) mbedtls_cmac_init( &ctx ); - if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) + // AES 128 bit key + if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, aes_128_key, 8 * sizeof(aes_128_key) ) != 0 ) { if( verbose != 0 ) mbedtls_printf( " CMAC: setup failed\n" ); @@ -461,8 +683,8 @@ int mbedtls_cmac_self_test( int verbose ) return( 1 ); } - if( ( memcmp( ctx.K1, K1, 16 ) != 0 ) || - ( memcmp( ctx.K2, K2, 16 ) != 0 ) ) + if( ( memcmp( ctx.K1, aes_128_k1, 16 ) != 0 ) || + ( memcmp( ctx.K2, aes_128_k2, 16 ) != 0 ) ) { if( verbose != 0 ) mbedtls_printf( " CMAC: subkey generation failed\n" ); @@ -470,13 +692,13 @@ int mbedtls_cmac_self_test( int verbose ) return( 1 ); } - for( i = 0; i < NB_CMAC_TESTS; i++ ) + for( i = 0; i < NB_CMAC_TESTS_AES_128; i++ ) { mbedtls_printf( " AES-128-CMAC #%u: ", i ); ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 ); if( ret != 0 || - memcmp( tag, T[i], 16 ) != 0 ) + memcmp( tag, T_128[i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); @@ -484,7 +706,7 @@ int mbedtls_cmac_self_test( int verbose ) return( 1 ); } - ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T[i], 16 ); + ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T_128[i], 16 ); if( ret != 0 ) { if( verbose != 0 ) @@ -497,14 +719,130 @@ int mbedtls_cmac_self_test( int verbose ) mbedtls_printf( "passed\n" ); } - for( i = 0; i < NB_PRF_TESTS; i++ ) + // AES 192 bit key + if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, aes_192_key, 8 * sizeof(aes_192_key) ) != 0 ) { - mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i ); + if( verbose != 0 ) + mbedtls_printf( " CMAC: setup failed\n" ); - mbedtls_aes_cmac_prf_128( &ctx, PRFK, PRFKlen[i], PRFM, 20, tag ); + return( 1 ); + } + if( ( memcmp( ctx.K1, aes_192_k1, 16 ) != 0 ) || + ( memcmp( ctx.K2, aes_192_k2, 16 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: subkey generation failed\n" ); + + return( 1 ); + } + + for( i = 0; i < NB_CMAC_TESTS_AES_192; i++ ) + { + mbedtls_printf( " AES-192-CMAC #%u: ", i ); + + ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 ); if( ret != 0 || - memcmp( tag, PRFT[i], 16 ) != 0 ) + memcmp( tag, T_192[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T_192[i], 16 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + // 3DES 2 key bit key + if( (ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_3DES, des3_2key_key, 8 * sizeof(des3_2key_key) )) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: setup failed %i\n", ret); + + return( 1 ); + } + + if( ( memcmp( ctx.K1, des3_2key_k1, 8 ) != 0 ) || + ( memcmp( ctx.K2, des3_2key_k2, 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: subkey generation failed\n" ); + + return( 1 ); + } + + for( i = 0; i < NB_CMAC_TESTS_3DES; i++ ) + { + mbedtls_printf( " DES-112-CMAC #%u: ", i ); + + ret = mbedtls_cmac_generate( &ctx, M, Mlen_3des[i], tag, 8 ); + if( ret != 0 || + memcmp( tag, T_3des_2key[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + ret = mbedtls_cmac_verify( &ctx, M, Mlen_3des[i], T_3des_2key[i], 8 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + // 3DES 3 key + if( (ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_3DES, des3_3key_key, 8 * sizeof(des3_3key_key) )) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: setup failed %i\n", ret); + + return( 1 ); + } + + if( ( memcmp( ctx.K1, des3_3key_k1, 8 ) != 0 ) || + ( memcmp( ctx.K2, des3_3key_k2, 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: subkey generation failed\n" ); + + return( 1 ); + } + + for( i = 0; i < NB_CMAC_TESTS_3DES; i++ ) + { + mbedtls_printf( " DES-168-CMAC #%u: ", i ); + + ret = mbedtls_cmac_generate( &ctx, M, Mlen_3des[i], tag, 8 ); + if( ret != 0 || + memcmp( tag, T_3des_3key[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + ret = mbedtls_cmac_verify( &ctx, M, Mlen_3des[i], T_3des_3key[i], 8 ); + if( ret != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); @@ -518,6 +856,25 @@ int mbedtls_cmac_self_test( int verbose ) mbedtls_cmac_free( &ctx ); + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i ); + + mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag ); + + if( ret != 0 || + memcmp( tag, PRFT[i], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + if( verbose != 0 ) mbedtls_printf( "\n" ); From f13d3db373cdc652e8dc37b8158a34be8807024b Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Wed, 18 May 2016 16:05:18 -0700 Subject: [PATCH 28/83] Updated comments for CMAC in config.h --- include/mbedtls/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 6e0313629..f6f431bfb 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1674,11 +1674,11 @@ /** * \def MBEDTLS_CMAC_C * - * Enable the CMAC mode for 128-bit block cipher. + * Enable the CMAC mode for block ciphers. * * Module: library/cmac.c * - * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_DES_C * */ #define MBEDTLS_CMAC_C From 00dc5f0fc8e3629db0e8c55f28cb544c429ae609 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Thu, 19 May 2016 14:23:50 -0700 Subject: [PATCH 29/83] Fixed CMAC tag length --- library/cmac.c | 413 ++++++++++++++++++++----------------------------- 1 file changed, 168 insertions(+), 245 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index ab4a82ddf..8348939f1 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -59,6 +59,7 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) memset( ctx, 0, sizeof( mbedtls_cmac_context ) ); } + /* * Multiplication by u in the Galois field of GF(2^n) * @@ -298,7 +299,7 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, UPDATE_CMAC( M_last ); - memcpy( tag, state, block_size ); + memcpy( tag, state, tag_len ); exit: free(state); @@ -444,74 +445,59 @@ static const unsigned char des3_3key_key[] = { 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5 }; - - -/* Assume we don't need to test Ek0 as this is a function of the cipher */ - -/* Subkey K1 */ -static const unsigned char aes_128_k1[] = { - 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, - 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde +static const unsigned char aes_128_subkeys[2][16] = { + { + 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 + } }; -/* Subkey K2 */ -static const unsigned char aes_128_k2[] = { - 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, - 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b +static const unsigned char aes_192_subkeys[2][16] = { + { + 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_256_subkeys[2][16] = { + { + 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 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_3key_subkeys[2][8] = { + { + 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f + }, + { + 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5 + } }; - -/* Subkey K1 */ -static const unsigned char aes_192_k1[] = { - 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, - 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 -}; - -/* Subkey K2 */ -static const unsigned char aes_192_k2[] = { - 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, - 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c -}; - -/* Subkey K1 */ -static const unsigned char aes_256_k1[] = { - 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, - 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f -}; - -/* Subkey K2 */ -static const unsigned char aes_256_k2[] = { - 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, - 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 -}; - - -/* Subkey K1 */ -static const unsigned char des3_2key_k1[] = { - 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef -}; - -/* Subkey K2 */ -static const unsigned char des3_2key_k2[] = { - 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5 -}; - -/* Subkey K1 */ -static const unsigned char des3_3key_k1[] = { - 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f -}; - -/* Subkey K2 */ -static const unsigned char des3_3key_k2[] = { - 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5 -}; - -/* Assume we don't need to test Ek0 as this is a function of the cipher */ - - - -/* All Messages are the same. The difference is the length */ +/* All Messages are truncated from the same 64 byte buffer. */ static const unsigned char M[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, @@ -597,7 +583,7 @@ static const unsigned char T_192[NB_CMAC_TESTS_AES_192][16] = { } }; -static const unsigned char T_3des_2key[NB_CMAC_TESTS_AES_192][16] = { +static const unsigned char T_3des_2key[4][8] = { { 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61 }, @@ -612,7 +598,7 @@ static const unsigned char T_3des_2key[NB_CMAC_TESTS_AES_192][16] = { } }; -static const unsigned char T_3des_3key[NB_CMAC_TESTS_AES_192][16] = { +static const unsigned char T_3des_3key[4][8] = { { 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95 }, @@ -664,6 +650,71 @@ static const unsigned char PRFT[NB_PRF_TESTS][16] = { } }; +int test_cmac_with_cipher(int verbose, + const unsigned char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + size_t message_lengths[4], + const unsigned char* subkeys, + const unsigned char* expected_result, + mbedtls_cipher_id_t cipher_id, + int block_size) +{ + const int num_tests = 4; + mbedtls_cmac_context ctx; + int i, ret; + unsigned char* tag; + + tag = mbedtls_calloc( block_size, sizeof( unsigned char ) ); + mbedtls_cmac_init( &ctx ); + + if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: setup failed\n" ); + goto exit; + } + + if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) || + ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( " CMAC: subkey generation failed\n" ); + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%u: ", testname, i +1 ); + + if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + mbedtls_printf( "passed\n" ); + } + exit: + free( tag ); + mbedtls_cmac_free( &ctx ); + return( ret ); +} int mbedtls_cmac_self_test( int verbose ) { @@ -672,189 +723,61 @@ int mbedtls_cmac_self_test( int verbose ) int i; int ret; - mbedtls_cmac_init( &ctx ); + test_cmac_with_cipher(verbose, + "AES 128", + aes_128_key, + 128, + M, + Mlen, + aes_128_subkeys, + T_128, + MBEDTLS_CIPHER_ID_AES, + 16 ); - // AES 128 bit key - if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, aes_128_key, 8 * sizeof(aes_128_key) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: setup failed\n" ); + test_cmac_with_cipher(verbose, + "AES 192", + aes_192_key, + 192, + M, + Mlen, + aes_192_subkeys, + T_192, + MBEDTLS_CIPHER_ID_AES, + 16 ); - return( 1 ); - } + test_cmac_with_cipher(verbose, + "AES 256", + aes_256_key, + 256, + M, + Mlen, + aes_256_subkeys, + T_256, + MBEDTLS_CIPHER_ID_AES, + 16 ); - if( ( memcmp( ctx.K1, aes_128_k1, 16 ) != 0 ) || - ( memcmp( ctx.K2, aes_128_k2, 16 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: subkey generation failed\n" ); + test_cmac_with_cipher(verbose, + "3DES 2 key", + des3_2key_key, + 192, + M, + Mlen_3des, + des3_2key_subkeys, + T_3des_2key, + MBEDTLS_CIPHER_ID_3DES, + 8 ); - return( 1 ); - } + test_cmac_with_cipher(verbose, + "3DES 3 key", + des3_3key_key, + 192, + M, + Mlen_3des, + des3_3key_subkeys, + T_3des_3key, + MBEDTLS_CIPHER_ID_3DES, + 8 ); - for( i = 0; i < NB_CMAC_TESTS_AES_128; i++ ) - { - mbedtls_printf( " AES-128-CMAC #%u: ", i ); - - ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 ); - if( ret != 0 || - memcmp( tag, T_128[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T_128[i], 16 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - // AES 192 bit key - if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, aes_192_key, 8 * sizeof(aes_192_key) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: setup failed\n" ); - - return( 1 ); - } - - if( ( memcmp( ctx.K1, aes_192_k1, 16 ) != 0 ) || - ( memcmp( ctx.K2, aes_192_k2, 16 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: subkey generation failed\n" ); - - return( 1 ); - } - - for( i = 0; i < NB_CMAC_TESTS_AES_192; i++ ) - { - mbedtls_printf( " AES-192-CMAC #%u: ", i ); - - ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 ); - if( ret != 0 || - memcmp( tag, T_192[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T_192[i], 16 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - // 3DES 2 key bit key - if( (ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_3DES, des3_2key_key, 8 * sizeof(des3_2key_key) )) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: setup failed %i\n", ret); - - return( 1 ); - } - - if( ( memcmp( ctx.K1, des3_2key_k1, 8 ) != 0 ) || - ( memcmp( ctx.K2, des3_2key_k2, 8 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: subkey generation failed\n" ); - - return( 1 ); - } - - for( i = 0; i < NB_CMAC_TESTS_3DES; i++ ) - { - mbedtls_printf( " DES-112-CMAC #%u: ", i ); - - ret = mbedtls_cmac_generate( &ctx, M, Mlen_3des[i], tag, 8 ); - if( ret != 0 || - memcmp( tag, T_3des_2key[i], 8 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_cmac_verify( &ctx, M, Mlen_3des[i], T_3des_2key[i], 8 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - // 3DES 3 key - if( (ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_3DES, des3_3key_key, 8 * sizeof(des3_3key_key) )) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: setup failed %i\n", ret); - - return( 1 ); - } - - if( ( memcmp( ctx.K1, des3_3key_k1, 8 ) != 0 ) || - ( memcmp( ctx.K2, des3_3key_k2, 8 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: subkey generation failed\n" ); - - return( 1 ); - } - - for( i = 0; i < NB_CMAC_TESTS_3DES; i++ ) - { - mbedtls_printf( " DES-168-CMAC #%u: ", i ); - - ret = mbedtls_cmac_generate( &ctx, M, Mlen_3des[i], tag, 8 ); - if( ret != 0 || - memcmp( tag, T_3des_3key[i], 8 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_cmac_verify( &ctx, M, Mlen_3des[i], T_3des_3key[i], 8 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - mbedtls_cmac_free( &ctx ); for( i = 0; i < NB_PRF_TESTS; i++ ) { @@ -877,7 +800,7 @@ int mbedtls_cmac_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "\n" ); - +*/ return( 0 ); } From 0f6af73599154c142077a369e668fb5e8a964f89 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Thu, 19 May 2016 15:59:23 -0700 Subject: [PATCH 30/83] More cleanup of CMAC selftests --- library/cmac.c | 405 +++++++++++++++++++++++++------------------------ 1 file changed, 206 insertions(+), 199 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 8348939f1..0de85bcc5 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -397,108 +397,23 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, } -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#ifdef MBEDTLS_SELF_TEST /* - * Examples 1 to 4 from SP800-38B corrected Appendix D.1 + * 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_AES_128 4 -#define NB_CMAC_TESTS_AES_192 4 -#define NB_CMAC_TESTS_AES_256 4 -#define NB_CMAC_TESTS_3DES 4 - +#define NB_CMAC_TESTS_PER_KEY 4 #define NB_PRF_TESTS 3 +#define AES_BLOCK_SIZE 16 +#define DES3_BLOCK_SIZE 8 -/* AES 128 Key */ -static const unsigned char aes_128_key[] = { - 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c -}; - -/* AES 192 Key */ -static const unsigned char aes_192_key[] = { - 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, - 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, - 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b -}; - -/* AES 256 Key */ -static const unsigned char aes_256_key[] = { - 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 -}; - -/* 3DES 112 bit key */ -static const unsigned char des3_2key_key[] = { - 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5, - 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38, - 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5 -}; - -/* 3DES 168 bit key */ -static const unsigned char des3_3key_key[] = { - 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 aes_128_subkeys[2][16] = { - { - 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_192_subkeys[2][16] = { - { - 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_256_subkeys[2][16] = { - { - 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 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_3key_subkeys[2][8] = { - { - 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f - }, - { - 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5 - } -}; - - -/* All Messages are truncated from the same 64 byte buffer. */ -static const unsigned char M[] = { +#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, @@ -508,8 +423,33 @@ static const unsigned char M[] = { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; +#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */ -static const unsigned char T_128[NB_CMAC_TESTS_3DES][16] = { +#ifdef MBEDTLS_AES_C +/* Truncation point of message for AES CMAC tests */ +static const size_t aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 40, + 64 +}; + +/* AES 128 CMAC Test Data */ +static const unsigned char aes_128_key[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][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][AES_BLOCK_SIZE] = { { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 @@ -528,43 +468,23 @@ static const unsigned char T_128[NB_CMAC_TESTS_3DES][16] = { } }; -/* Sizes in bytes */ -static const size_t Mlen[NB_CMAC_TESTS_AES_192] = { - 0, - 16, - 40, - 64 +/* AES 192 CMAC Test Data */ +static const unsigned char aes_192_key[] = { + 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 size_t Mlen_3des[NB_CMAC_TESTS_AES_192] = { - 0, - 8, - 20, - 32 -}; - - - -static const unsigned char T_256[NB_CMAC_TESTS_AES_192][16] = { +static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = { { - 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, - 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 }, { - 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 + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c } }; - -static const unsigned char T_192[NB_CMAC_TESTS_AES_192][16] = { +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = { { 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 @@ -583,7 +503,67 @@ static const unsigned char T_192[NB_CMAC_TESTS_AES_192][16] = { } }; -static const unsigned char T_3des_2key[4][8] = { +/* AES 256 CMAC Test Data */ +static const unsigned char aes_256_key[] = { + 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][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][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 */ + +#ifdef MBEDTLS_DES_C +/* Truncation point of message for 3DES CMAC tests */ +static const size_t 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[] = { + 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 T_3des_2key[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = { { 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61 }, @@ -598,7 +578,21 @@ static const unsigned char T_3des_2key[4][8] = { } }; -static const unsigned char T_3des_3key[4][8] = { +/* 3DES 3 Key CMAC Test Data */ +static const unsigned char des3_3key_key[] = { + 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 T_3des_3key[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = { { 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95 }, @@ -613,8 +607,10 @@ static const unsigned char T_3des_3key[4][8] = { } }; +#endif /* MBEDTLS_DES_C */ -/* PRF K */ +#ifdef 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, @@ -649,6 +645,7 @@ static const unsigned char PRFT[NB_PRF_TESTS][16] = { 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d } }; +#endif /* MBEDTLS_AES_C */ int test_cmac_with_cipher(int verbose, const unsigned char* testname, @@ -716,94 +713,104 @@ int test_cmac_with_cipher(int verbose, return( ret ); } -int mbedtls_cmac_self_test( int verbose ) -{ - mbedtls_cmac_context ctx; - unsigned char tag[16]; +#ifdef MBEDTLS_AES_C +int test_aes128_cmac_prf( verbose ) { int i; int ret; - - test_cmac_with_cipher(verbose, - "AES 128", - aes_128_key, - 128, - M, - Mlen, - aes_128_subkeys, - T_128, - MBEDTLS_CIPHER_ID_AES, - 16 ); - - test_cmac_with_cipher(verbose, - "AES 192", - aes_192_key, - 192, - M, - Mlen, - aes_192_subkeys, - T_192, - MBEDTLS_CIPHER_ID_AES, - 16 ); - - test_cmac_with_cipher(verbose, - "AES 256", - aes_256_key, - 256, - M, - Mlen, - aes_256_subkeys, - T_256, - MBEDTLS_CIPHER_ID_AES, - 16 ); - - test_cmac_with_cipher(verbose, - "3DES 2 key", - des3_2key_key, - 192, - M, - Mlen_3des, - des3_2key_subkeys, - T_3des_2key, - MBEDTLS_CIPHER_ID_3DES, - 8 ); - - test_cmac_with_cipher(verbose, - "3DES 3 key", - des3_3key_key, - 192, - M, - Mlen_3des, - des3_3key_subkeys, - T_3des_3key, - MBEDTLS_CIPHER_ID_3DES, - 8 ); - - + unsigned char tag[16]; for( i = 0; i < NB_PRF_TESTS; i++ ) { - mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i ); - - mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag ); - + mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag ); if( ret != 0 || memcmp( tag, PRFT[i], 16 ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); - return( 1 ); + 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; + +#ifdef MBEDTLS_AES_C + test_cmac_with_cipher(verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + aes_128_subkeys, + aes_128_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ); + + test_cmac_with_cipher(verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + aes_192_subkeys, + aes_192_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ); + + test_cmac_with_cipher(verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + aes_256_subkeys, + aes_256_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ); +#endif /* MBEDTLS_AES_C */ + +#ifdef MBEDTLS_DES_C + test_cmac_with_cipher(verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + des3_2key_subkeys, + T_3des_2key, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ); + + test_cmac_with_cipher(verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + des3_3key_subkeys, + T_3des_3key, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ); +#endif /* MBEDTLS_DES_C */ + +#ifdef MBEDTLS_AES_C + test_aes128_cmac_prf( verbose ); +#endif /* MBEDTLS_AES_C */ if( verbose != 0 ) mbedtls_printf( "\n" ); -*/ + return( 0 ); } -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ +#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CMAC_C */ From b439d4556df1a522deeb5acc864525b35a1da19a Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Thu, 19 May 2016 16:02:42 -0700 Subject: [PATCH 31/83] Only compile AES CMAC PRF support if MBEDTLS_AES_C is defined and other cleanups --- include/mbedtls/cmac.h | 37 ++++++++++++----------- library/cmac.c | 66 +++++++++++++++++++++--------------------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 3e02f912e..fed337d5c 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -33,12 +33,12 @@ extern "C" { #endif /** - * \brief CCM context structure + * \brief CMAC context structure */ typedef struct { mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ - unsigned char* K1; - unsigned char* K2; + unsigned char* K1; /*!< CMAC Subkey 1 */ + unsigned char* K2; /*!< CMAC Subkey 2 */ } mbedtls_cmac_context; @@ -52,12 +52,12 @@ mbedtls_cmac_context; void mbedtls_cmac_init( mbedtls_cmac_context *ctx ); /** - * \brief CMAC initialization + * \brief Initialize the CMAC context * * \param ctx CMAC context to be initialized - * \param cipher cipher to use (a 128-bit block cipher) + * \param cipher cipher to use * \param key encryption key - * \param keybits key size in bits (must be acceptable by the cipher) + * \param keybits encryption key size in bits (must be acceptable by the cipher) * * \return 0 if successful, or a cipher specific error code */ @@ -68,20 +68,22 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, /** * \brief Free a CMAC context and underlying cipher sub-context + * Securely wipes sub keys and other sensitive data. * * \param ctx CMAC context to free */ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); /** - * \brief CMAC generate + * \brief Generate a CMAC tag. * * \param ctx CMAC context * \param input buffer holding the input data * \param in_len length of the input data in bytes * \param tag buffer for holding the generated tag * \param tag_len length of the tag to generate in bytes - * must be between 4, 6, 8, 10, 14 or 16 + * Must be 4, 6, 8 if cipher block size is 64 + * Must be 4, 6, 8 0, 14 or 16 if cipher block size is 128 * * \return 0 if successful */ @@ -90,47 +92,48 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, unsigned char *tag, size_t tag_len ); /** - * \brief CMAC verify + * \brief Verify a CMAC tag. * * \param ctx CMAC context * \param input buffer holding the input data * \param in_len length of the input data in bytes * \param tag buffer holding the tag to verify * \param tag_len length of the tag to verify in bytes - * must be 4, 6, 8, 10, 14 or 16 - * - * \return 0 if successful and authenticated, + * Must be 4, 6, 8 if cipher block size is 64 + * Must be 4, 6, 8 0, 14 or 16 if cipher block size is 128 + * \return 0 if successful and authenticated * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match */ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, const unsigned char *input, size_t in_len, const unsigned char *tag, size_t tag_len ); +#ifdef MBEDTLS_AES_C /** * \brief AES-CMAC-128-PRF - * See RFC + * See RFC 4615 for details * * \param key PRF key * \param key_len PRF key length * \param input buffer holding the input data * \param in_len length of the input data in bytes * \param tag buffer holding the tag to verify (16 bytes) - * TODO: update description of tag * * \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 *tag ); + unsigned char tag[16] ); +#endif /* MBEDTLS_AES_C */ -#if defined(MBEDTLS_SELF_TEST) && defined(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 */ +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ #ifdef __cplusplus } diff --git a/library/cmac.c b/library/cmac.c index 0de85bcc5..3d223194b 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -73,7 +73,7 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) */ static int cmac_multiply_by_u( unsigned char *output, const unsigned char *input, - size_t blocksize) + size_t blocksize ) { const unsigned char R_128 = 0x87; @@ -84,12 +84,12 @@ static int cmac_multiply_by_u( unsigned char *output, starting_index = blocksize -1; - if(blocksize == 16){ + if( blocksize == 16 ){ R_n = R_128; - } else if(blocksize == 8) { + } else if( blocksize == 8 ) { R_n = R_64; } else { - return MBEDTLS_ERR_CMAC_BAD_INPUT; + return( MBEDTLS_ERR_CMAC_BAD_INPUT ); } @@ -113,7 +113,7 @@ static int cmac_multiply_by_u( unsigned char *output, #endif output[starting_index] ^= R_n & mask; - return 0; + return( 0 ); } /* @@ -128,7 +128,7 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) ret = 0; block_size = ctx->cipher_ctx.cipher_info->block_size; - L = mbedtls_calloc(block_size, sizeof(unsigned char)); + L = mbedtls_calloc( block_size, sizeof( unsigned char ) ); /* Calculate Ek(0) */ memset( L, 0, block_size ); @@ -141,15 +141,15 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) /* * Generate K1 and K2 */ - if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size) ) != 0 ) + if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size ) ) != 0 ) goto exit; - if( ( cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size) ) != 0 ) + if( ( cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 ) goto exit; exit: mbedtls_zeroize( L, sizeof( L ) ); - free(L); - return ret; + free( L ); + return( ret ); } /* @@ -195,8 +195,8 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize(ctx->K1, block_size * sizeof( unsigned char ) ); - mbedtls_zeroize(ctx->K2, block_size * sizeof( unsigned char ) ); + mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) ); + mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) ); mbedtls_free( ctx->K1 ); mbedtls_free( ctx->K2 ); } @@ -263,8 +263,8 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, ret = 0; block_size = ctx->cipher_ctx.cipher_info->block_size; - state = mbedtls_calloc(block_size, sizeof(unsigned char) ); - M_last = mbedtls_calloc(block_size, sizeof(unsigned char) ); + state = mbedtls_calloc( block_size, sizeof( unsigned char ) ); + M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) ); /* * Check in_len requirements: SP800-38B A @@ -302,8 +302,8 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, memcpy( tag, state, tag_len ); exit: - free(state); - free(M_last); + free( state ); + free( M_last ); return( ret ); } @@ -322,8 +322,8 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, unsigned char i; int diff; - check_tag = mbedtls_calloc(ctx->cipher_ctx.cipher_info->block_size, - sizeof(unsigned char) ); + check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size, + sizeof( unsigned char ) ); if( ( ret = mbedtls_cmac_generate( ctx, input, in_len, check_tag, tag_len ) ) != 0 ) @@ -340,24 +340,25 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, goto exit; exit: - free(check_tag); - return ret; + free( check_tag ); + return( ret ); } +#ifdef MBEDTLS_AES_C /* * PRF based on CMAC with AES-128 * See 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 *tag ) + unsigned char tag[16] ) { int ret; mbedtls_cmac_context ctx; unsigned char zero_key[16]; unsigned char int_key[16]; - mbedtls_cmac_init(&ctx); + mbedtls_cmac_init(&ctx ); if( key_length == 16 ) { @@ -368,7 +369,7 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, { mbedtls_cmac_context zero_ctx; - /* Key is AES_CMAC(0, key) */ + /* Key is AES_CMAC( 0, key ) */ mbedtls_cmac_init( &zero_ctx ); memset( zero_key, 0, 16 ); ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, @@ -391,11 +392,10 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 ); exit: - mbedtls_cmac_free(&ctx); + mbedtls_cmac_free( &ctx ); return( ret ); - - } +#endif /* MBEDTLS_AES_C */ #ifdef MBEDTLS_SELF_TEST /* @@ -647,7 +647,7 @@ static const unsigned char PRFT[NB_PRF_TESTS][16] = { }; #endif /* MBEDTLS_AES_C */ -int test_cmac_with_cipher(int verbose, +int test_cmac_with_cipher( int verbose, const unsigned char* testname, const unsigned char* key, int keybits, @@ -656,7 +656,7 @@ int test_cmac_with_cipher(int verbose, const unsigned char* subkeys, const unsigned char* expected_result, mbedtls_cipher_id_t cipher_id, - int block_size) + int block_size ) { const int num_tests = 4; mbedtls_cmac_context ctx; @@ -743,7 +743,7 @@ int mbedtls_cmac_self_test( int verbose ) int ret; #ifdef MBEDTLS_AES_C - test_cmac_with_cipher(verbose, + test_cmac_with_cipher( verbose, "AES 128", aes_128_key, 128, @@ -754,7 +754,7 @@ int mbedtls_cmac_self_test( int verbose ) MBEDTLS_CIPHER_ID_AES, AES_BLOCK_SIZE ); - test_cmac_with_cipher(verbose, + test_cmac_with_cipher( verbose, "AES 192", aes_192_key, 192, @@ -765,7 +765,7 @@ int mbedtls_cmac_self_test( int verbose ) MBEDTLS_CIPHER_ID_AES, AES_BLOCK_SIZE ); - test_cmac_with_cipher(verbose, + test_cmac_with_cipher ( verbose, "AES 256", aes_256_key, 256, @@ -778,7 +778,7 @@ int mbedtls_cmac_self_test( int verbose ) #endif /* MBEDTLS_AES_C */ #ifdef MBEDTLS_DES_C - test_cmac_with_cipher(verbose, + test_cmac_with_cipher( verbose, "3DES 2 key", des3_2key_key, 192, @@ -789,7 +789,7 @@ int mbedtls_cmac_self_test( int verbose ) MBEDTLS_CIPHER_ID_3DES, DES3_BLOCK_SIZE ); - test_cmac_with_cipher(verbose, + test_cmac_with_cipher( verbose, "3DES 3 key", des3_3key_key, 192, From 9044b0295ca3fb76b7e35d3b56835a86162f4551 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Thu, 19 May 2016 16:36:56 -0700 Subject: [PATCH 32/83] More cleanup of CMAC self tests --- library/cmac.c | 119 ++++++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 51 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 3d223194b..477e35f98 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -743,66 +743,83 @@ int mbedtls_cmac_self_test( int verbose ) int ret; #ifdef MBEDTLS_AES_C - test_cmac_with_cipher( verbose, - "AES 128", - aes_128_key, - 128, - test_message, - aes_message_lengths, - aes_128_subkeys, - aes_128_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ); + if( ( ret = test_cmac_with_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + aes_128_subkeys, + aes_128_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) + { + return( ret ); + } - test_cmac_with_cipher( verbose, - "AES 192", - aes_192_key, - 192, - test_message, - aes_message_lengths, - aes_192_subkeys, - aes_192_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ); + if( ( ret = test_cmac_with_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + aes_192_subkeys, + aes_192_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) + { + return( ret ); + } - test_cmac_with_cipher ( verbose, - "AES 256", - aes_256_key, - 256, - test_message, - aes_message_lengths, - aes_256_subkeys, - aes_256_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ); + if( ( ret = test_cmac_with_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + aes_256_subkeys, + aes_256_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) + { + return( ret ); + } #endif /* MBEDTLS_AES_C */ #ifdef MBEDTLS_DES_C - test_cmac_with_cipher( verbose, - "3DES 2 key", - des3_2key_key, - 192, - test_message, - des3_message_lengths, - des3_2key_subkeys, - T_3des_2key, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ); + if( ( ret = test_cmac_with_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + des3_2key_subkeys, + T_3des_2key, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ) !=0 ) ) + { + return( ret ); + } - test_cmac_with_cipher( verbose, - "3DES 3 key", - des3_3key_key, - 192, - test_message, - des3_message_lengths, - des3_3key_subkeys, - T_3des_3key, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ); + if( ( ret = test_cmac_with_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + des3_3key_subkeys, + T_3des_3key, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ) !=0 ) ) + { + return( ret ); + } #endif /* MBEDTLS_DES_C */ #ifdef MBEDTLS_AES_C - test_aes128_cmac_prf( verbose ); + if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) ) + return( ret ); + #endif /* MBEDTLS_AES_C */ if( verbose != 0 ) From 57863ad7edafcbb137ee37a8d09243e7b734462d Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Thu, 19 May 2016 16:38:36 -0700 Subject: [PATCH 33/83] selftest supports cmac if only MBEDTLS_DES_C is defined Other minor typo fixes --- include/mbedtls/cmac.h | 6 +- include/mbedtls/error.h | 2 +- library/cmac.c | 145 +++++++++++++++++++++++---------------- library/error.c | 2 + programs/test/selftest.c | 2 +- 5 files changed, 95 insertions(+), 62 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index fed337d5c..b94b6edcc 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -27,6 +27,8 @@ #define MBEDTLS_ERR_CMAC_BAD_INPUT -0x0011 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_CMAC_VERIFY_FAILED -0x0013 /**< Verification failed. */ +#define MBEDTLS_ERR_CMAC_ALLOC_FAILED -0x0015 /**< Memory Allocation failed. */ + #ifdef __cplusplus extern "C" { @@ -83,7 +85,7 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); * \param tag buffer for holding the generated tag * \param tag_len length of the tag to generate in bytes * Must be 4, 6, 8 if cipher block size is 64 - * Must be 4, 6, 8 0, 14 or 16 if cipher block size is 128 + * Must be 4, 6, 8 , 10, 12, 14 or 16 if cipher block size is 128 * * \return 0 if successful */ @@ -100,7 +102,7 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, * \param tag buffer holding the tag to verify * \param tag_len length of the tag to verify in bytes * Must be 4, 6, 8 if cipher block size is 64 - * Must be 4, 6, 8 0, 14 or 16 if cipher block size is 128 + * Must be 4, 6, 8 , 10, 12, 14 or 16 if cipher block size is 128 * \return 0 if successful and authenticated * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match */ diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 703233ae9..6e3905d86 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -66,7 +66,7 @@ * PBKDF2 1 0x007C-0x007C * HMAC_DRBG 4 0x0003-0x0009 * CCM 2 0x000D-0x000F - * CMAC 2 0x0011-0x0013 + * CMAC 3 0x0011-0x0015 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors diff --git a/library/cmac.c b/library/cmac.c index 477e35f98..39ebb8709 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -121,7 +121,7 @@ static int cmac_multiply_by_u( unsigned char *output, */ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) { - int ret, keybytes; + int ret; unsigned char *L; size_t olen, block_size; @@ -129,7 +129,11 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) block_size = ctx->cipher_ctx.cipher_info->block_size; L = mbedtls_calloc( block_size, sizeof( unsigned char ) ); - + if( L == NULL) + { + ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; + goto exit; + } /* Calculate Ek(0) */ memset( L, 0, block_size ); if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, @@ -147,7 +151,8 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) goto exit; exit: - mbedtls_zeroize( L, sizeof( L ) ); + if( L != NULL ) + mbedtls_zeroize( L, sizeof( L ) ); free( L ); return( ret ); } @@ -160,7 +165,7 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, const unsigned char *key, unsigned int keybits ) { - int ret, blocksize; + int ret; const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, @@ -171,6 +176,9 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); + if(ctx->K1 == NULL || ctx->K2 == NULL ) + return MBEDTLS_ERR_CMAC_ALLOC_FAILED; + mbedtls_cipher_free( &ctx->cipher_ctx ); if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) @@ -242,7 +250,9 @@ do { \ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \ state, block_size, \ state, &olen ) ) != 0 ) \ - return( ret ); \ + { \ + goto exit; \ + } \ } while( 0 ) /* @@ -256,8 +266,8 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, unsigned char *state; unsigned char *M_last; - int n, i, j, ret, needs_padding; - size_t olen, block_size; + int n, j, ret, needs_padding; + size_t olen, block_size, i; ret = 0; @@ -266,12 +276,21 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, state = mbedtls_calloc( block_size, sizeof( unsigned char ) ); M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) ); + if( state == NULL || M_last == NULL ) + { + ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; + goto exit; + } + /* * Check in_len requirements: SP800-38B A * 4 is a worst case bottom limit */ if( tag_len < 4 || tag_len > block_size || tag_len % 2 != 0 ) - return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + { + ret = MBEDTLS_ERR_CMAC_BAD_INPUT; + goto exit; + } if( in_len == 0 ) needs_padding = 1; @@ -324,6 +343,11 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size, sizeof( unsigned char ) ); + if(check_tag == NULL) + { + ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; + goto exit; + } if( ( ret = mbedtls_cmac_generate( ctx, input, in_len, check_tag, tag_len ) ) != 0 ) @@ -427,7 +451,7 @@ static const unsigned char test_message[] = { #ifdef MBEDTLS_AES_C /* Truncation point of message for AES CMAC tests */ -static const size_t aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { 0, 16, 40, @@ -435,7 +459,7 @@ static const size_t aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { }; /* AES 128 CMAC Test Data */ -static const unsigned char aes_128_key[] = { +static const unsigned char aes_128_key[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; @@ -469,7 +493,7 @@ static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BL }; /* AES 192 CMAC Test Data */ -static const unsigned char aes_192_key[] = { +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 @@ -504,7 +528,7 @@ static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BL }; /* AES 256 CMAC Test Data */ -static const unsigned char aes_256_key[] = { +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, @@ -542,7 +566,7 @@ static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BL #ifdef MBEDTLS_DES_C /* Truncation point of message for 3DES CMAC tests */ -static const size_t des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { 0, 8, 20, @@ -550,7 +574,7 @@ static const size_t des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { }; /* 3DES 2 Key CMAC Test Data */ -static const unsigned char des3_2key_key[] = { +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 @@ -563,7 +587,7 @@ static const unsigned char des3_2key_subkeys[2][8] = { 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5 } }; -static const unsigned char T_3des_2key[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = { +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = { { 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61 }, @@ -579,7 +603,7 @@ static const unsigned char T_3des_2key[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = }; /* 3DES 3 Key CMAC Test Data */ -static const unsigned char des3_3key_key[] = { +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 @@ -592,7 +616,7 @@ static const unsigned char des3_3key_subkeys[2][8] = { 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5 } }; -static const unsigned char T_3des_3key[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = { +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = { { 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95 }, @@ -648,11 +672,11 @@ static const unsigned char PRFT[NB_PRF_TESTS][16] = { #endif /* MBEDTLS_AES_C */ int test_cmac_with_cipher( int verbose, - const unsigned char* testname, + char* testname, const unsigned char* key, int keybits, const unsigned char* messages, - size_t message_lengths[4], + const unsigned int message_lengths[4], const unsigned char* subkeys, const unsigned char* expected_result, mbedtls_cipher_id_t cipher_id, @@ -664,6 +688,11 @@ int test_cmac_with_cipher( int verbose, unsigned char* tag; tag = mbedtls_calloc( block_size, sizeof( unsigned char ) ); + if( tag == NULL ){ + ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; + goto exit; + } + mbedtls_cmac_init( &ctx ); if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 ) @@ -714,7 +743,7 @@ int test_cmac_with_cipher( int verbose, } #ifdef MBEDTLS_AES_C -int test_aes128_cmac_prf( verbose ) { +int test_aes128_cmac_prf( int verbose ) { int i; int ret; unsigned char tag[16]; @@ -749,8 +778,8 @@ int mbedtls_cmac_self_test( int verbose ) 128, test_message, aes_message_lengths, - aes_128_subkeys, - aes_128_expected_result, + (const unsigned char*) aes_128_subkeys, + (const unsigned char*) aes_128_expected_result, MBEDTLS_CIPHER_ID_AES, AES_BLOCK_SIZE ) !=0 ) ) { @@ -758,29 +787,29 @@ int mbedtls_cmac_self_test( int verbose ) } if( ( ret = test_cmac_with_cipher( verbose, - "AES 192", - aes_192_key, - 192, - test_message, - aes_message_lengths, - aes_192_subkeys, - aes_192_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*) aes_192_subkeys, + (const unsigned char*) aes_192_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) { return( ret ); } if( ( ret = test_cmac_with_cipher ( verbose, - "AES 256", - aes_256_key, - 256, - test_message, - aes_message_lengths, - aes_256_subkeys, - aes_256_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*) aes_256_subkeys, + (const unsigned char*) aes_256_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) { return( ret ); } @@ -788,29 +817,29 @@ int mbedtls_cmac_self_test( int verbose ) #ifdef MBEDTLS_DES_C if( ( ret = test_cmac_with_cipher( verbose, - "3DES 2 key", - des3_2key_key, - 192, - test_message, - des3_message_lengths, - des3_2key_subkeys, - T_3des_2key, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ) !=0 ) ) + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*) des3_2key_subkeys, + (const unsigned char*) des3_2key_expected_result, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ) !=0 ) ) { return( ret ); } if( ( ret = test_cmac_with_cipher( verbose, - "3DES 3 key", - des3_3key_key, - 192, - test_message, - des3_message_lengths, - des3_3key_subkeys, - T_3des_3key, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ) !=0 ) ) + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*) des3_3key_subkeys, + (const unsigned char*) des3_3key_expected_result, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ) !=0 ) ) { return( ret ); } diff --git a/library/error.c b/library/error.c index 8c38cf294..7ec8420e9 100644 --- a/library/error.c +++ b/library/error.c @@ -587,6 +587,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "CMAC - Bad input parameters to function" ); if( use_ret == -(MBEDTLS_ERR_CMAC_VERIFY_FAILED) ) mbedtls_snprintf( buf, buflen, "CMAC - Verification failed" ); + if( use_ret == -(MBEDTLS_ERR_CMAC_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "CMAC - Failed to allocate memory" ); #endif /* MBEDTLS_CMAC_C */ #if defined(MBEDTLS_CTR_DRBG_C) diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 17fdb2128..74eed598e 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -278,7 +278,7 @@ int main( int argc, char *argv[] ) suites_tested++; #endif -#if defined(MBEDTLS_CMAC_C) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CMAC_C) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) if( ( ret = mbedtls_cmac_self_test( v ) ) != 0 ) return( ret ); #endif From 2cfa5072ed4a00ed1e64fed5f3a00b63ca62ebc3 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Mon, 23 May 2016 20:17:04 -0700 Subject: [PATCH 34/83] better handling of failed calloc --- library/cmac.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 39ebb8709..4c25a67d0 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -173,12 +173,6 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, if( cipher_info == NULL ) return( MBEDTLS_ERR_CMAC_BAD_INPUT ); - ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); - ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); - - if(ctx->K1 == NULL || ctx->K2 == NULL ) - return MBEDTLS_ERR_CMAC_ALLOC_FAILED; - mbedtls_cipher_free( &ctx->cipher_ctx ); if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) @@ -190,6 +184,16 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, return( ret ); } + ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); + ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); + + if( ctx->K1 == NULL || ctx->K2 == NULL ) + { + mbedtls_free(ctx->K1); + mbedtls_free(ctx->K2); + return( MBEDTLS_ERR_CMAC_ALLOC_FAILED ); + } + return( cmac_generate_subkeys( ctx ) ); } From 617634e6565c81808d6fb2fed38f59f582caa965 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Thu, 19 May 2016 19:02:53 -0700 Subject: [PATCH 35/83] cmac.c whitespace cleanup --- library/cmac.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 4c25a67d0..09a705d65 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -59,7 +59,6 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) memset( ctx, 0, sizeof( mbedtls_cmac_context ) ); } - /* * Multiplication by u in the Galois field of GF(2^n) * @@ -267,13 +266,11 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, unsigned char *tag, size_t tag_len ) { - unsigned char *state; unsigned char *M_last; int n, j, ret, needs_padding; size_t olen, block_size, i; - ret = 0; block_size = ctx->cipher_ctx.cipher_info->block_size; From 87e4040bb9b3d752f62b11944bf8c63087ded6e7 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Thu, 19 May 2016 19:05:57 -0700 Subject: [PATCH 36/83] No CMAC minimum tag length is specified by NIST SP800-38B A Minor Typo Changes --- include/mbedtls/cmac.h | 8 +++--- library/cmac.c | 58 ++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index b94b6edcc..5a59f90d6 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -84,8 +84,8 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); * \param in_len length of the input data in bytes * \param tag buffer for holding the generated tag * \param tag_len length of the tag to generate in bytes - * Must be 4, 6, 8 if cipher block size is 64 - * Must be 4, 6, 8 , 10, 12, 14 or 16 if cipher block size is 128 + * Must be 2, 4, 6, 8 if cipher block size is 64 + * Must be 2, 4, 6, 8, 10, 12, 14 or 16 if cipher block size is 128 * * \return 0 if successful */ @@ -101,8 +101,8 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, * \param in_len length of the input data in bytes * \param tag buffer holding the tag to verify * \param tag_len length of the tag to verify in bytes - * Must be 4, 6, 8 if cipher block size is 64 - * Must be 4, 6, 8 , 10, 12, 14 or 16 if cipher block size is 128 + * Must be 2, 4, 6, 8 if cipher block size is 64 + * Must be 2, 4, 6, 8, 10, 12, 14 or 16 if cipher block size is 128 * \return 0 if successful and authenticated * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match */ diff --git a/library/cmac.c b/library/cmac.c index 09a705d65..063a9d1c3 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -62,7 +62,7 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) /* * Multiplication by u in the Galois field of GF(2^n) * - * As explained in the paper, this can computed: + * As explained in the paper, 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 @@ -245,7 +245,7 @@ static void cmac_pad( unsigned char padded_block[16], ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; /* - * Update the CMAC state using an input block x + * Update the CMAC state using an input block */ #define UPDATE_CMAC( x ) \ do { \ @@ -283,11 +283,7 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, goto exit; } - /* - * Check in_len requirements: SP800-38B A - * 4 is a worst case bottom limit - */ - if( tag_len < 4 || tag_len > block_size || tag_len % 2 != 0 ) + if( tag_len < 2 || tag_len > block_size || tag_len % 2 != 0 ) { ret = MBEDTLS_ERR_CMAC_BAD_INPUT; goto exit; @@ -495,9 +491,9 @@ static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BL /* 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 + 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][AES_BLOCK_SIZE] = { { @@ -530,10 +526,10 @@ static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BL /* 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 + 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][AES_BLOCK_SIZE] = { { @@ -576,9 +572,9 @@ static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { /* 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 + 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] = { { @@ -605,9 +601,9 @@ static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3 /* 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 + 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] = { { @@ -673,18 +669,18 @@ static const unsigned char PRFT[NB_PRF_TESTS][16] = { #endif /* MBEDTLS_AES_C */ int test_cmac_with_cipher( int verbose, - char* testname, - const unsigned char* key, - int keybits, - const unsigned char* messages, - const unsigned int message_lengths[4], - const unsigned char* subkeys, - const unsigned char* expected_result, - mbedtls_cipher_id_t cipher_id, - int block_size ) + char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* subkeys, + const unsigned char* expected_result, + mbedtls_cipher_id_t cipher_id, + int block_size ) { - const int num_tests = 4; - mbedtls_cmac_context ctx; + const int num_tests = 4; + mbedtls_cmac_context ctx; int i, ret; unsigned char* tag; From 4b64ab6664595332845fac7a54c6eaf417471d95 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Fri, 20 May 2016 06:33:01 -0700 Subject: [PATCH 37/83] Removed unneed memsets and fixed spacing --- library/cmac.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 063a9d1c3..d32d1c7e7 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -74,7 +74,6 @@ 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; @@ -91,7 +90,6 @@ static int cmac_multiply_by_u( unsigned char *output, return( MBEDTLS_ERR_CMAC_BAD_INPUT ); } - for( i = starting_index; i >= 0; i-- ) { output[i] = input[i] << 1 | overflow; @@ -128,13 +126,12 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) block_size = ctx->cipher_ctx.cipher_info->block_size; L = mbedtls_calloc( block_size, sizeof( unsigned char ) ); - if( L == NULL) + if( L == NULL ) { ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; goto exit; } /* Calculate Ek(0) */ - memset( L, 0, block_size ); if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, L, block_size, L, &olen ) ) != 0 ) { @@ -152,7 +149,7 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) exit: if( L != NULL ) mbedtls_zeroize( L, sizeof( L ) ); - free( L ); + mbedtls_free( L ); return( ret ); } @@ -308,8 +305,6 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 ); } - memset( state, 0, block_size ); - for( j = 0; j < n - 1; j++ ) UPDATE_CMAC( input + block_size * j ); @@ -318,8 +313,8 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, memcpy( tag, state, tag_len ); exit: - free( state ); - free( M_last ); + mbedtls_free( state ); + mbedtls_free( M_last ); return( ret ); } @@ -340,7 +335,7 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size, sizeof( unsigned char ) ); - if(check_tag == NULL) + if( check_tag == NULL ) { ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; goto exit; @@ -361,7 +356,7 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, goto exit; exit: - free( check_tag ); + mbedtls_free( check_tag ); return( ret ); } @@ -727,14 +722,14 @@ int test_cmac_with_cipher( int verbose, if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - goto exit; + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; } mbedtls_printf( "passed\n" ); } exit: - free( tag ); + mbedtls_free( tag ); mbedtls_cmac_free( &ctx ); return( ret ); } From 6a3c0d2d678ee2ee43ed1b834129495c4bd4efbb Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Fri, 20 May 2016 18:25:43 -0700 Subject: [PATCH 38/83] Do not zeroize null pointer --- library/cmac.c | 85 ++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index d32d1c7e7..1a6f31376 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -82,11 +82,14 @@ static int cmac_multiply_by_u( unsigned char *output, starting_index = blocksize -1; - if( blocksize == 16 ){ + if( blocksize == 16 ) + { R_n = R_128; - } else if( blocksize == 8 ) { + } else if( blocksize == 8 ) + { R_n = R_64; - } else { + } else + { return( MBEDTLS_ERR_CMAC_BAD_INPUT ); } @@ -122,7 +125,6 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) unsigned char *L; size_t olen, block_size; - ret = 0; block_size = ctx->cipher_ctx.cipher_info->block_size; L = mbedtls_calloc( block_size, sizeof( unsigned char ) ); @@ -143,7 +145,7 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) */ if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size ) ) != 0 ) goto exit; - if( ( cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 ) + if( ( ret = cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 ) goto exit; exit: @@ -203,8 +205,10 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) ); - mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) ); + if( ctx->K1 != NULL ) + mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) ); + if( ctx->K2 != NULL ) + mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) ); mbedtls_free( ctx->K1 ); mbedtls_free( ctx->K2 ); } @@ -261,7 +265,6 @@ do { \ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, const unsigned char *input, size_t in_len, unsigned char *tag, size_t tag_len ) - { unsigned char *state; unsigned char *M_last; @@ -389,7 +392,7 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, mbedtls_cmac_init( &zero_ctx ); memset( zero_key, 0, 16 ); ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, - zero_key, 8 * sizeof zero_key ); + zero_key, 8 * sizeof( zero_key ) ); if( ret != 0 ) goto exit; @@ -399,17 +402,16 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, } ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, - int_key, 8 * sizeof int_key ); + int_key, 8 * sizeof( int_key ) ); if( ret != 0 ) goto exit; - mbedtls_zeroize( int_key, sizeof( int_key ) ); - ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 ); exit: - mbedtls_cmac_free( &ctx ); - return( ret ); + mbedtls_zeroize( int_key, sizeof( int_key ) ); + mbedtls_cmac_free( &ctx ); + return( ret ); } #endif /* MBEDTLS_AES_C */ @@ -680,7 +682,8 @@ int test_cmac_with_cipher( int verbose, unsigned char* tag; tag = mbedtls_calloc( block_size, sizeof( unsigned char ) ); - if( tag == NULL ){ + if( tag == NULL ) + { ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; goto exit; } @@ -735,7 +738,8 @@ int test_cmac_with_cipher( int verbose, } #ifdef MBEDTLS_AES_C -int test_aes128_cmac_prf( int verbose ) { +int test_aes128_cmac_prf( int verbose ) +{ int i; int ret; unsigned char tag[16]; @@ -794,14 +798,14 @@ int mbedtls_cmac_self_test( int verbose ) if( ( ret = test_cmac_with_cipher ( verbose, "AES 256", - aes_256_key, - 256, - test_message, - aes_message_lengths, - (const unsigned char*) aes_256_subkeys, - (const unsigned char*) aes_256_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*) aes_256_subkeys, + (const unsigned char*) aes_256_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) { return( ret ); } @@ -810,28 +814,28 @@ int mbedtls_cmac_self_test( int verbose ) #ifdef MBEDTLS_DES_C if( ( ret = test_cmac_with_cipher( verbose, "3DES 2 key", - des3_2key_key, - 192, - test_message, - des3_message_lengths, - (const unsigned char*) des3_2key_subkeys, - (const unsigned char*) des3_2key_expected_result, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ) !=0 ) ) + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*) des3_2key_subkeys, + (const unsigned char*) des3_2key_expected_result, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ) !=0 ) ) { return( ret ); } if( ( ret = test_cmac_with_cipher( verbose, "3DES 3 key", - des3_3key_key, - 192, - test_message, - des3_message_lengths, - (const unsigned char*) des3_3key_subkeys, - (const unsigned char*) des3_3key_expected_result, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ) !=0 ) ) + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*) des3_3key_subkeys, + (const unsigned char*) des3_3key_expected_result, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ) !=0 ) ) { return( ret ); } @@ -840,7 +844,6 @@ int mbedtls_cmac_self_test( int verbose ) #ifdef MBEDTLS_AES_C if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) ) return( ret ); - #endif /* MBEDTLS_AES_C */ if( verbose != 0 ) From 0cf14c10d40ad14a7371ec9ef92a5375f5cad43e Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Mon, 23 May 2016 12:49:50 -0700 Subject: [PATCH 39/83] Fixed some build warnings --- library/cmac.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/library/cmac.c b/library/cmac.c index 1a6f31376..3c584049c 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -441,6 +441,14 @@ static const unsigned char test_message[] = { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; +/* Function Prototype */ +int test_cmac_with_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* subkeys, + const unsigned char* expected_result, mbedtls_cipher_id_t cipher_id, + int block_size ); + + #endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */ #ifdef MBEDTLS_AES_C @@ -666,7 +674,7 @@ static const unsigned char PRFT[NB_PRF_TESTS][16] = { #endif /* MBEDTLS_AES_C */ int test_cmac_with_cipher( int verbose, - char* testname, + const char* testname, const unsigned char* key, int keybits, const unsigned char* messages, @@ -738,6 +746,9 @@ int test_cmac_with_cipher( int verbose, } #ifdef MBEDTLS_AES_C +/* Function Prototype */ +int test_aes128_cmac_prf( int verbose ); + int test_aes128_cmac_prf( int verbose ) { int i; From ae1cb12d824f9deaa2d797e46a16c1e9c1a0d1d6 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Mon, 23 May 2016 15:01:59 -0700 Subject: [PATCH 40/83] Changed test function to inline to pass tests/scripts/check-names.sh --- library/cmac.c | 131 +++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 70 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 3c584049c..d51983418 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -441,12 +441,6 @@ static const unsigned char test_message[] = { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; -/* Function Prototype */ -int test_cmac_with_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* subkeys, - const unsigned char* expected_result, mbedtls_cipher_id_t cipher_id, - int block_size ); #endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */ @@ -673,16 +667,16 @@ static const unsigned char PRFT[NB_PRF_TESTS][16] = { }; #endif /* MBEDTLS_AES_C */ -int test_cmac_with_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* subkeys, - const unsigned char* expected_result, - mbedtls_cipher_id_t cipher_id, - int block_size ) +static inline 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* subkeys, + const unsigned char* expected_result, + mbedtls_cipher_id_t cipher_id, + int block_size ) { const int num_tests = 4; mbedtls_cmac_context ctx; @@ -746,10 +740,7 @@ int test_cmac_with_cipher( int verbose, } #ifdef MBEDTLS_AES_C -/* Function Prototype */ -int test_aes128_cmac_prf( int verbose ); - -int test_aes128_cmac_prf( int verbose ) +static inline int test_aes128_cmac_prf( int verbose ) { int i; int ret; @@ -779,74 +770,74 @@ int mbedtls_cmac_self_test( int verbose ) int ret; #ifdef MBEDTLS_AES_C - if( ( ret = test_cmac_with_cipher( verbose, - "AES 128", - aes_128_key, - 128, - test_message, - aes_message_lengths, - (const unsigned char*) aes_128_subkeys, - (const unsigned char*) aes_128_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*) aes_128_subkeys, + (const unsigned char*) aes_128_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) { return( ret ); } - if( ( ret = test_cmac_with_cipher( verbose, - "AES 192", - aes_192_key, - 192, - test_message, - aes_message_lengths, - (const unsigned char*) aes_192_subkeys, - (const unsigned char*) aes_192_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*) aes_192_subkeys, + (const unsigned char*) aes_192_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) { return( ret ); } - if( ( ret = test_cmac_with_cipher ( verbose, - "AES 256", - aes_256_key, - 256, - test_message, - aes_message_lengths, - (const unsigned char*) aes_256_subkeys, - (const unsigned char*) aes_256_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*) aes_256_subkeys, + (const unsigned char*) aes_256_expected_result, + MBEDTLS_CIPHER_ID_AES, + AES_BLOCK_SIZE ) !=0 ) ) { return( ret ); } #endif /* MBEDTLS_AES_C */ #ifdef MBEDTLS_DES_C - if( ( ret = test_cmac_with_cipher( verbose, - "3DES 2 key", - des3_2key_key, - 192, - test_message, - des3_message_lengths, - (const unsigned char*) des3_2key_subkeys, - (const unsigned char*) des3_2key_expected_result, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ) !=0 ) ) + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*) des3_2key_subkeys, + (const unsigned char*) des3_2key_expected_result, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ) !=0 ) ) { return( ret ); } - if( ( ret = test_cmac_with_cipher( verbose, - "3DES 3 key", - des3_3key_key, - 192, - test_message, - des3_message_lengths, - (const unsigned char*) des3_3key_subkeys, - (const unsigned char*) des3_3key_expected_result, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ) !=0 ) ) + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*) des3_3key_subkeys, + (const unsigned char*) des3_3key_expected_result, + MBEDTLS_CIPHER_ID_3DES, + DES3_BLOCK_SIZE ) !=0 ) ) { return( ret ); } From 06acc18f4492908c1ce7a10f84147950a82055ca Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Tue, 24 May 2016 15:53:52 -0700 Subject: [PATCH 41/83] Minor change to pass build tests --- include/mbedtls/cmac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 5a59f90d6..5a09761c2 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -27,7 +27,7 @@ #define MBEDTLS_ERR_CMAC_BAD_INPUT -0x0011 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_CMAC_VERIFY_FAILED -0x0013 /**< Verification failed. */ -#define MBEDTLS_ERR_CMAC_ALLOC_FAILED -0x0015 /**< Memory Allocation failed. */ +#define MBEDTLS_ERR_CMAC_ALLOC_FAILED -0x0015 /**< Failed to allocate memory */ #ifdef __cplusplus From 9ce2e091de5df992b6cc51566dc324e027b8716c Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Tue, 24 May 2016 22:46:43 -0700 Subject: [PATCH 42/83] cleaned up indentation and braket issues in mbedtls_cmac_verify --- library/cmac.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library/cmac.c b/library/cmac.c index d51983418..d8c809b41 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -355,8 +355,15 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, diff |= tag[i] ^ check_tag[i]; if( diff != 0 ) + { ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED; goto exit; + } + else + { + ret = 0; + goto exit; + } exit: mbedtls_free( check_tag ); @@ -718,6 +725,7 @@ static inline int cmac_test_wth_cipher( int verbose, mbedtls_printf( "failed\n" ); goto exit; } + if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 ) { if( verbose != 0 ) @@ -731,7 +739,9 @@ static inline int cmac_test_wth_cipher( int verbose, mbedtls_printf( "failed\n" ); goto exit; } - mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); } exit: mbedtls_free( tag ); From 53e23b684f63676cb80b7f925243de05771e30c9 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Tue, 13 Sep 2016 14:00:15 -0700 Subject: [PATCH 43/83] Minor CMAC fixes for merge --- configs/config-thread.h | 1 + include/mbedtls/check_config.h | 5 +++++ include/mbedtls/cmac.h | 2 +- include/mbedtls/config.h | 2 +- library/cmac.c | 25 +++++++++++++------------ 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/configs/config-thread.h b/configs/config-thread.h index 3193a0404..fdfa64aa4 100644 --- a/configs/config-thread.h +++ b/configs/config-thread.h @@ -39,6 +39,7 @@ /* mbed TLS feature support */ #define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_CMAC_C #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_ECP_NIST_OPTIM #define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 75cdcbc2f..8ebe438c0 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_CAMELLIA_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/cmac.h b/include/mbedtls/cmac.h index 5a09761c2..10c8633c9 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -3,7 +3,7 @@ * * \brief The CMAC Mode for Authentication * - * 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 diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index f6f431bfb..2a4964281 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1681,7 +1681,7 @@ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_DES_C * */ -#define MBEDTLS_CMAC_C +//#define MBEDTLS_CMAC_C /** * \def MBEDTLS_CTR_DRBG_C diff --git a/library/cmac.c b/library/cmac.c index d8c809b41..e57e024bb 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -1,7 +1,8 @@ /* - * NIST SP800-38B compliant CMAC implementation + * \file cmac.c + * \brief NIST SP800-38B compliant CMAC implementation * - * 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 @@ -20,9 +21,10 @@ */ /* - * Definition of CMAC: - * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf - * RFC 4493 "The AES-CMAC Algorithm" + * References: + * - CMAC: NIST SP 800-38B + * - CMAC PRF: RFC 4493 + * - Additional test vectors: ISO/IEC 9797-1 */ #if !defined(MBEDTLS_CONFIG_FILE) @@ -72,7 +74,7 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) */ static int cmac_multiply_by_u( unsigned char *output, const unsigned char *input, - size_t blocksize ) + size_t blocksize ) { const unsigned char R_128 = 0x87; const unsigned char R_64 = 0x1B; @@ -151,7 +153,7 @@ static int cmac_generate_subkeys( mbedtls_cmac_context *ctx ) exit: if( L != NULL ) mbedtls_zeroize( L, sizeof( L ) ); - mbedtls_free( L ); + mbedtls_free( L ); return( ret ); } @@ -200,9 +202,8 @@ int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, */ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) { - int block_size; - block_size = ctx->cipher_ctx.cipher_info->block_size; - + int block_size; + block_size = ctx->cipher_ctx.cipher_info->block_size; mbedtls_cipher_free( &ctx->cipher_ctx ); if( ctx->K1 != NULL ) @@ -220,7 +221,7 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) * 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[16], - size_t padded_block_len, + size_t padded_block_len, const unsigned char *last_block, size_t last_block_len ) { @@ -418,7 +419,7 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, exit: mbedtls_zeroize( int_key, sizeof( int_key ) ); mbedtls_cmac_free( &ctx ); - return( ret ); + return( ret ); } #endif /* MBEDTLS_AES_C */ From 72b69e380857075c3463ab9ec767e39c201b66ac Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Tue, 13 Sep 2016 14:21:01 -0700 Subject: [PATCH 44/83] Minor fixes to comments --- include/mbedtls/cmac.h | 13 +++++++------ library/cmac.c | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 10c8633c9..325d22d51 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -57,7 +57,8 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ); * \brief Initialize the CMAC context * * \param ctx CMAC context to be initialized - * \param cipher cipher to use + * \param cipher cipher to use. + Cipher block size must be 8 bytes or 16 bytes. * \param key encryption key * \param keybits encryption key size in bits (must be acceptable by the cipher) * @@ -84,8 +85,8 @@ void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); * \param in_len length of the input data in bytes * \param tag buffer for holding the generated tag * \param tag_len length of the tag to generate in bytes - * Must be 2, 4, 6, 8 if cipher block size is 64 - * Must be 2, 4, 6, 8, 10, 12, 14 or 16 if cipher block size is 128 + * Must be 2, 4, 6, 8 if cipher block size is 8 + * Must be 2, 4, 6, 8, 10, 12, 14 or 16 if cipher block size is 16 * * \return 0 if successful */ @@ -101,8 +102,8 @@ int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, * \param in_len length of the input data in bytes * \param tag buffer holding the tag to verify * \param tag_len length of the tag to verify in bytes - * Must be 2, 4, 6, 8 if cipher block size is 64 - * Must be 2, 4, 6, 8, 10, 12, 14 or 16 if cipher block size is 128 + * Must be 2, 4, 6, 8 if cipher block size is 8 + * Must be 2, 4, 6, 8, 10, 12, 14 or 16 if cipher block size is 16 * \return 0 if successful and authenticated * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match */ @@ -119,7 +120,7 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, * \param key_len PRF key length * \param input buffer holding the input data * \param in_len length of the input data in bytes - * \param tag buffer holding the tag to verify (16 bytes) + * \param tag buffer holding the generated pseudorandom output * * \return 0 if successful */ diff --git a/library/cmac.c b/library/cmac.c index e57e024bb..920c23d6a 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -64,7 +64,7 @@ void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) /* * Multiplication by u in the Galois field of GF(2^n) * - * As explained in the paper, this can be computed: + * 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 From 8b4111c51688bab133eb505a966733cde09b01ec Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Tue, 13 Sep 2016 15:58:46 -0700 Subject: [PATCH 45/83] Fix build failure for thread config --- configs/config-thread.h | 2 +- library/cmac.c | 11 ++++++++--- programs/test/selftest.c | 7 +++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/configs/config-thread.h b/configs/config-thread.h index fdfa64aa4..990fe08c6 100644 --- a/configs/config-thread.h +++ b/configs/config-thread.h @@ -39,7 +39,6 @@ /* mbed TLS feature support */ #define MBEDTLS_AES_ROM_TABLES -#define MBEDTLS_CMAC_C #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_ECP_NIST_OPTIM #define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED @@ -58,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/library/cmac.c b/library/cmac.c index 920c23d6a..f86e4c5aa 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -39,14 +39,19 @@ #include -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) #include -#define mbedtls_printf printf +#define mbedtls_printf printf +#endif /* defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )*/ #endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 74eed598e..33f96ea13 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -279,8 +279,11 @@ int main( int argc, char *argv[] ) #endif #if defined(MBEDTLS_CMAC_C) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) - if( ( ret = mbedtls_cmac_self_test( v ) ) != 0 ) - return( ret ); + if( ( mbedtls_cmac_self_test( v ) ) != 0 ) + { + suites_failed++; + } + suites_tested++; #endif #if defined(MBEDTLS_BASE64_C) From 2898f79795bf94964babc3e4a01bf67e7e89c176 Mon Sep 17 00:00:00 2001 From: Brian Murray Date: Tue, 13 Sep 2016 16:17:36 -0700 Subject: [PATCH 46/83] Specify AES-CMAC-PRF buffer output size in comment --- include/mbedtls/cmac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 325d22d51..ddacb2177 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -120,7 +120,7 @@ int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, * \param key_len PRF key length * \param input buffer holding the input data * \param in_len length of the input data in bytes - * \param tag buffer holding the generated pseudorandom output + * \param tag buffer holding the generated pseudorandom output (16 bytes) * * \return 0 if successful */ From 327398ad3afd5f629d8bae408c9bc2a9b7c5bb27 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 14:09:11 +0100 Subject: [PATCH 47/83] Refactor and change CMAC interface Change the CMAC interface to match the mbedtls_md_hmac_xxxx() interface. This changes the overall design of the CMAC interface to make it more consistent with the existing HMAC interface, and will allow incremental updates of input data rather than requiring all data to be presented at once, which is what the current interface requires. --- include/mbedtls/cipher.h | 10 + include/mbedtls/cmac.h | 146 ++++---- include/mbedtls/config.h | 3 +- library/cipher.c | 19 + library/cmac.c | 739 ++++++++++++++++++++++++--------------- library/error.c | 9 - 6 files changed, 578 insertions(+), 348 deletions(-) diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index c9675544a..b12e38843 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -176,6 +176,11 @@ enum { */ 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. */ @@ -241,6 +246,11 @@ typedef struct { /** 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 index ddacb2177..ceeb20add 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -1,9 +1,10 @@ /** * \file cmac.h * - * \brief The CMAC Mode for Authentication + * \brief Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * 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 @@ -23,110 +24,131 @@ #ifndef MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H -#include "cipher.h" - -#define MBEDTLS_ERR_CMAC_BAD_INPUT -0x0011 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_CMAC_VERIFY_FAILED -0x0013 /**< Verification failed. */ -#define MBEDTLS_ERR_CMAC_ALLOC_FAILED -0x0015 /**< Failed to allocate memory */ - +#include "mbedtls/cipher.h" #ifdef __cplusplus extern "C" { #endif +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE 16 /* longest known is AES */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE 8 /* longest known is 3DES */ +#endif + /** * \brief CMAC context structure */ -typedef struct { - mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ - unsigned char* K1; /*!< CMAC Subkey 1 */ - unsigned char* K2; /*!< CMAC Subkey 2 */ +typedef struct mbedtls_cmac_context_t { + + /** Internal state of the CMAC algorithm */ + unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; + + /** 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_SIZE]; + + /** Length of data pending to be processed */ + size_t unprocessed_len; + + /** Flag to indicate if the last block needs padding */ + int padding_flag; } -mbedtls_cmac_context; +mbedtls_cmac_context_t; /** - * \brief Initialize CMAC context (just makes references valid) - * Makes the context ready for mbedtls_cmac_setkey() or - * mbedtls_cmac_free(). + * \brief Set the CMAC key and prepare to authenticate the input + * data. + * Should be called with an initialised cipher context. * - * \param ctx CMAC context to initialize + * \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 */ -void mbedtls_cmac_init( mbedtls_cmac_context *ctx ); +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keylen ); /** - * \brief Initialize the CMAC context + * \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 to be initialized - * \param cipher cipher to use. - Cipher block size must be 8 bytes or 16 bytes. - * \param key encryption key - * \param keybits encryption key size in bits (must be acceptable by the cipher) + * \param ctx CMAC context + * \param input buffer holding the data + * \param ilen length of the input data * - * \return 0 if successful, or a cipher specific error code + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. */ -int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ); +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); /** - * \brief Free a CMAC context and underlying cipher sub-context - * Securely wipes sub keys and other sensitive data. + * \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 to 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. */ -void mbedtls_cmac_free( mbedtls_cmac_context *ctx ); +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); /** - * \brief Generate a CMAC tag. + * \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 - * \param input buffer holding the input data - * \param in_len length of the input data in bytes - * \param tag buffer for holding the generated tag - * \param tag_len length of the tag to generate in bytes - * Must be 2, 4, 6, 8 if cipher block size is 8 - * Must be 2, 4, 6, 8, 10, 12, 14 or 16 if cipher block size is 16 + * \param ctx CMAC context to be reset * - * \return 0 if successful + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. */ -int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, - const unsigned char *input, size_t in_len, - unsigned char *tag, size_t tag_len ); +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); /** - * \brief Verify a CMAC tag. + * \brief Output = Generic_CMAC( hmac key, input buffer ) * - * \param ctx CMAC context - * \param input buffer holding the input data - * \param in_len length of the input data in bytes - * \param tag buffer holding the tag to verify - * \param tag_len length of the tag to verify in bytes - * Must be 2, 4, 6, 8 if cipher block size is 8 - * Must be 2, 4, 6, 8, 10, 12, 14 or 16 if cipher block size is 16 - * \return 0 if successful and authenticated - * MBEDTLS_ERR_CMAC_VERIFY_FAILED if tag does not match + * \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_cmac_verify( mbedtls_cmac_context *ctx, - const unsigned char *input, size_t in_len, - const unsigned char *tag, size_t tag_len ); +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 ); #ifdef MBEDTLS_AES_C /** * \brief AES-CMAC-128-PRF - * See RFC 4615 for details + * Implementation of (AES-CMAC-PRF-128), as defined in RFC 4615 * * \param key PRF key - * \param key_len PRF key length + * \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 tag buffer holding the generated pseudorandom output (16 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 tag[16] ); + unsigned char output[16] ); #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 2a4964281..4546d596a 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1674,7 +1674,8 @@ /** * \def MBEDTLS_CMAC_C * - * Enable the CMAC mode for block ciphers. + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. * * Module: library/cmac.c * diff --git a/library/cipher.c b/library/cipher.c index bbe40eb39..a88343869 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 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) 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 index f86e4c5aa..1eb1c1074 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -1,5 +1,6 @@ /* * \file cmac.c + * * \brief NIST SP800-38B compliant CMAC implementation * * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved @@ -22,9 +23,21 @@ /* * References: - * - CMAC: NIST SP 800-38B - * - CMAC PRF: RFC 4493 - * - Additional test vectors: ISO/IEC 9797-1 + * + * - 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) @@ -46,35 +59,29 @@ #include #define mbedtls_calloc calloc #define mbedtls_free free -#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || \ + defined(MBEDTLS_DES_C) ) #include #define mbedtls_printf printf -#endif /* defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )*/ +#endif /* defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || + * defined(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 = v; while( n-- ) *p++ = 0; -} - -/* - * Initialize context - */ -void mbedtls_cmac_init( mbedtls_cmac_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_cmac_context ) ); + 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 + * 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. */ static int cmac_multiply_by_u( unsigned char *output, @@ -85,22 +92,22 @@ static int cmac_multiply_by_u( unsigned char *output, const unsigned char R_64 = 0x1B; unsigned char R_n, mask; unsigned char overflow = 0x00; - int i, starting_index; - - starting_index = blocksize -1; + int i; if( blocksize == 16 ) { R_n = R_128; - } else if( blocksize == 8 ) + } + else if( blocksize == 8 ) { R_n = R_64; - } else + } + else { - return( MBEDTLS_ERR_CMAC_BAD_INPUT ); + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } - for( i = starting_index; i >= 0; i-- ) + for( i = blocksize - 1; i >= 0; i-- ) { output[i] = input[i] << 1 | overflow; overflow = input[i] >> 7; @@ -108,6 +115,7 @@ static int cmac_multiply_by_u( unsigned char *output, /* 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) @@ -119,104 +127,53 @@ static int cmac_multiply_by_u( unsigned char *output, #pragma warning( pop ) #endif - output[starting_index] ^= R_n & mask; + 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_cmac_context *ctx ) +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) { int ret; - unsigned char *L; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; size_t olen, block_size; - block_size = ctx->cipher_ctx.cipher_info->block_size; + mbedtls_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; - L = mbedtls_calloc( block_size, sizeof( unsigned char ) ); - if( L == NULL ) - { - ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; - goto exit; - } /* Calculate Ek(0) */ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, - L, block_size, L, &olen ) ) != 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( ctx->K1, L , block_size ) ) != 0 ) - goto exit; - if( ( ret = cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 ) + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) goto exit; - exit: - if( L != NULL ) - mbedtls_zeroize( L, sizeof( L ) ); - mbedtls_free( L ); - return( ret ); + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_zeroize( L, sizeof( L ) ); + + return( ret ); } -/* - * Set key and prepare context for use - */ -int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ) +static void cmac_xor_block(unsigned char *output, const unsigned char *input1, + const unsigned char *input2, const size_t block_size ) { - int ret; - const mbedtls_cipher_info_t *cipher_info; + size_t index; - cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, - MBEDTLS_MODE_ECB ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_CMAC_BAD_INPUT ); - - mbedtls_cipher_free( &ctx->cipher_ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - - ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); - ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) ); - - if( ctx->K1 == NULL || ctx->K2 == NULL ) - { - mbedtls_free(ctx->K1); - mbedtls_free(ctx->K2); - return( MBEDTLS_ERR_CMAC_ALLOC_FAILED ); - } - - return( cmac_generate_subkeys( ctx ) ); -} - -/* - * Free context - */ -void mbedtls_cmac_free( mbedtls_cmac_context *ctx ) -{ - int block_size; - block_size = ctx->cipher_ctx.cipher_info->block_size; - mbedtls_cipher_free( &ctx->cipher_ctx ); - - if( ctx->K1 != NULL ) - mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) ); - if( ctx->K2 != NULL ) - mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) ); - mbedtls_free( ctx->K1 ); - mbedtls_free( ctx->K2 ); + for( index = 0; index < block_size; index++ ) + output[ index ] = input1[ index ] ^ input2[ index ]; } /* @@ -243,154 +200,266 @@ static void cmac_pad( unsigned char padded_block[16], } } -/* - * XOR Block - * Here, macro results in smaller compiled code than static inline function - */ -#define XOR_BLOCK( o, i1, i2 ) \ - for( i = 0; i < block_size; i++ ) \ - ( o )[i] = ( i1 )[i] ^ ( i2 )[i]; - -/* - * Update the CMAC state using an input block - */ -#define UPDATE_CMAC( x ) \ -do { \ - XOR_BLOCK( state, ( x ), state ); \ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \ - state, block_size, \ - state, &olen ) ) != 0 ) \ - { \ - goto exit; \ - } \ -} while( 0 ) - -/* - * Generate tag on complete message - */ -int mbedtls_cmac_generate( mbedtls_cmac_context *ctx, - const unsigned char *input, size_t in_len, - unsigned char *tag, size_t tag_len ) +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keylen ) { + mbedtls_cipher_type_t type; + mbedtls_cmac_context_t *cmac_ctx; + unsigned int block_size; + 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, keylen, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + block_size = ctx->cipher_info->block_size; + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + cmac_ctx->padding_flag = 1; + + return 0; +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; unsigned char *state; - unsigned char *M_last; - int n, j, ret, needs_padding; - size_t olen, block_size, i; + int n, j, ret = 0; + size_t olen, block_size; - ret = 0; - block_size = ctx->cipher_ctx.cipher_info->block_size; + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - state = mbedtls_calloc( block_size, sizeof( unsigned char ) ); - M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) ); + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; - if( state == NULL || M_last == NULL ) + /* Is their data still to process from the last call, that's equal to + * or greater than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen + cmac_ctx->unprocessed_len > block_size ) { - ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; - goto exit; + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + ilen -= block_size; + input += cmac_ctx->unprocessed_len; + + cmac_ctx->unprocessed_len = 0; } - if( tag_len < 2 || tag_len > block_size || tag_len % 2 != 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++ ) { - ret = MBEDTLS_ERR_CMAC_BAD_INPUT; - goto exit; + //char *ptr = input + block_size * j ; + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + + cmac_ctx->padding_flag = 0; } - if( in_len == 0 ) - needs_padding = 1; - else - needs_padding = in_len % block_size != 0; + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block, input, ilen ); + cmac_ctx->unprocessed_len = ilen; - n = in_len / block_size + needs_padding; + if( ilen % block_size > 0 ) + cmac_ctx->padding_flag = 1; + else + cmac_ctx->padding_flag = 0; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; + 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 ); + +// mbedtls_zeroize( M_last, sizeof(M_last) ); +// if( cmac_ctx->unprocessed_len > 0 ) +// needs_padding = 1; + + unsigned char *last_block = cmac_ctx->unprocessed_block; + //unsigned char *M_last = cmac_ctx->unprocessed_block; /* Calculate last block */ - if( needs_padding ) + if( cmac_ctx->padding_flag ) { - cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size ); - XOR_BLOCK( M_last, M_last, ctx->K2 ); + 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 */ - XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 ); + cmac_xor_block( M_last, last_block, K1, block_size ); } - for( j = 0; j < n - 1; j++ ) - UPDATE_CMAC( input + block_size * j ); - UPDATE_CMAC( M_last ); + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } - memcpy( tag, state, tag_len ); - exit: - mbedtls_free( state ); - mbedtls_free( M_last ); - return( ret ); + + 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_len ) ); + + mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE ); + return( ret ); } -#undef XOR_BLOCK -#undef UPDATE_CMAC - -/* - * Verify tag on complete message - */ -int mbedtls_cmac_verify( mbedtls_cmac_context *ctx, - const unsigned char *input, size_t in_len, - const unsigned char *tag, size_t tag_len ) +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) { - int ret; - unsigned char *check_tag; - unsigned char i; - int diff; + mbedtls_cmac_context_t* cmac_ctx; - check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size, - sizeof( unsigned char ) ); - if( check_tag == NULL ) - { - ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; - goto exit; - } + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - if( ( ret = mbedtls_cmac_generate( ctx, input, in_len, - check_tag, tag_len ) ) != 0 ) - { - goto exit; - } + cmac_ctx = ctx->cmac_ctx; - /* Check tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_len ) ); - if( diff != 0 ) - { - ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED; - goto exit; - } - else - { - ret = 0; - goto exit; - } + cmac_ctx->padding_flag = 1; - exit: - mbedtls_free( check_tag ); - return( ret ); + 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; + // Are we leaking here? Should we reset or free? + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + mbedtls_cipher_cmac_finish( &ctx, output ); + if( ret != 0 ) + goto exit; + +exit: + return( ret ); +} #ifdef MBEDTLS_AES_C + /* +// TODO - clean up comments * PRF based on CMAC with AES-128 * See 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 tag[16] ) + unsigned char *output ) { int ret; - mbedtls_cmac_context ctx; + const mbedtls_cipher_info_t *cipher_info; unsigned char zero_key[16]; unsigned char int_key[16]; - mbedtls_cmac_init(&ctx ); + 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 == 16 ) { @@ -399,32 +468,21 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, } else { - mbedtls_cmac_context zero_ctx; - - /* Key is AES_CMAC( 0, key ) */ - mbedtls_cmac_init( &zero_ctx ); memset( zero_key, 0, 16 ); - ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES, - zero_key, 8 * sizeof( zero_key ) ); - if( ret != 0 ) - goto exit; - ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 ); + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); if( ret != 0 ) goto exit; } - ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, - int_key, 8 * sizeof( int_key ) ); - if( ret != 0 ) - goto exit; + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); - ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 ); +exit: + mbedtls_zeroize( int_key, sizeof( int_key ) ); - exit: - mbedtls_zeroize( int_key, sizeof( int_key ) ); - mbedtls_cmac_free( &ctx ); - return( ret ); + return( ret ); } #endif /* MBEDTLS_AES_C */ @@ -439,6 +497,8 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, #define NB_CMAC_TESTS_PER_KEY 4 #define NB_PRF_TESTS 3 + +// TODO - should use a value somewhere else #define AES_BLOCK_SIZE 16 #define DES3_BLOCK_SIZE 8 @@ -680,43 +740,104 @@ static const unsigned char PRFT[NB_PRF_TESTS][16] = { }; #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_SIZE]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; + + 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 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 exit; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto exit; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) != 0 ) || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + +exit: + return( ret ); +} + static inline 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* subkeys, const unsigned char* expected_result, - mbedtls_cipher_id_t cipher_id, - int block_size ) + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) { - const int num_tests = 4; - mbedtls_cmac_context ctx; + const mbedtls_cipher_info_t *cipher_info; int i, ret; - unsigned char* tag; + unsigned char* output; - tag = mbedtls_calloc( block_size, sizeof( unsigned char ) ); - if( tag == NULL ) + output = mbedtls_calloc( block_size, sizeof( unsigned char ) ); + if( output == NULL ) { - ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED; + ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED; goto exit; } - mbedtls_cmac_init( &ctx ); - - if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 ) + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) { - if( verbose != 0 ) - mbedtls_printf( " CMAC: setup failed\n" ); - goto exit; - } - - if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) || - ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( " CMAC: subkey generation failed\n" ); + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; goto exit; } @@ -725,34 +846,28 @@ static inline int cmac_test_wth_cipher( int verbose, if( verbose != 0 ) mbedtls_printf( " %s CMAC #%u: ", testname, i +1 ); - if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 ) + 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( tag, &expected_result[i * block_size], block_size ) ) != 0 ) + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); goto exit; } - if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &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: - mbedtls_free( tag ); - mbedtls_cmac_free( &ctx ); - return( ret ); +exit: + mbedtls_free( output ); + + return( ret ); } #ifdef MBEDTLS_AES_C @@ -760,14 +875,16 @@ static inline int test_aes128_cmac_prf( int verbose ) { int i; int ret; - unsigned char tag[16]; + unsigned char output[16]; + 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, tag ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); if( ret != 0 || - memcmp( tag, PRFT[i], 16 ) != 0 ) + memcmp( output, PRFT[i], 16 ) != 0 ) { + if( verbose != 0 ) mbedtls_printf( "failed\n" ); @@ -784,18 +901,45 @@ static inline int test_aes128_cmac_prf( int verbose ) int mbedtls_cmac_self_test( int verbose ) { int ret; - + #ifdef 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, + 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_subkeys, (const unsigned char*) aes_128_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + MBEDTLS_CIPHER_AES_128_ECB, + 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, + AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) !=0 ) ) { return( ret ); } @@ -806,54 +950,97 @@ int mbedtls_cmac_self_test( int verbose ) 192, test_message, aes_message_lengths, - (const unsigned char*) aes_192_subkeys, (const unsigned char*) aes_192_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + MBEDTLS_CIPHER_AES_192_ECB, + AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + { +mbedtls_printf("ret = %x\n", ret); + 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, + AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) !=0 ) ) { return( ret ); } - if( ( ret = cmac_test_wth_cipher ( verbose, + if( ( ret = cmac_test_wth_cipher ( verbose, "AES 256", aes_256_key, 256, test_message, aes_message_lengths, - (const unsigned char*) aes_256_subkeys, (const unsigned char*) aes_256_expected_result, - MBEDTLS_CIPHER_ID_AES, - AES_BLOCK_SIZE ) !=0 ) ) + MBEDTLS_CIPHER_AES_256_ECB, + AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) !=0 ) ) { return( ret ); } #endif /* MBEDTLS_AES_C */ #ifdef 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, + 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_subkeys, (const unsigned char*) des3_2key_expected_result, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ) !=0 ) ) + MBEDTLS_CIPHER_DES_EDE3_ECB, + 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, + 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_subkeys, (const unsigned char*) des3_3key_expected_result, - MBEDTLS_CIPHER_ID_3DES, - DES3_BLOCK_SIZE ) !=0 ) ) + MBEDTLS_CIPHER_DES_EDE3_ECB, + DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) !=0 ) ) { return( ret ); } diff --git a/library/error.c b/library/error.c index 7ec8420e9..e7b521bc7 100644 --- a/library/error.c +++ b/library/error.c @@ -582,15 +582,6 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); #endif /* MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CMAC_C) - if( use_ret == -(MBEDTLS_ERR_CMAC_BAD_INPUT) ) - mbedtls_snprintf( buf, buflen, "CMAC - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_CMAC_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "CMAC - Verification failed" ); - if( use_ret == -(MBEDTLS_ERR_CMAC_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "CMAC - Failed to allocate memory" ); -#endif /* MBEDTLS_CMAC_C */ - #if defined(MBEDTLS_CTR_DRBG_C) if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); From d812fa69d9a0997659f44e8698202855cdb08d0b Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 14:13:31 +0100 Subject: [PATCH 48/83] Introduce a CMAC specific test suite --- tests/Makefile | 5 ++++ tests/suites/test_suite_cmac.data | 27 +++++++++++++++++++ tests/suites/test_suite_cmac.function | 37 +++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 tests/suites/test_suite_cmac.data create mode 100644 tests/suites/test_suite_cmac.function diff --git a/tests/Makefile b/tests/Makefile index b86702c34..23c68ec86 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -50,6 +50,7 @@ APPS = test_suite_aes.ecb$(EXEXT) test_suite_aes.cbc$(EXEXT) \ 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 @@ test_suite_ccm$(EXEXT): test_suite_ccm.c $(DEP) 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/suites/test_suite_cmac.data b/tests/suites/test_suite_cmac.data new file mode 100644 index 000000000..a913ffdd8 --- /dev/null +++ b/tests/suites/test_suite_cmac.data @@ -0,0 +1,27 @@ +CMAC self test +mbedtls_cmac_self_test: + +CMAC init #1 AES-128: OK +depends_on:MBEDTLS_AES_C +mbedtls_cmac_setkey:MBEDTLS_CIPHER_AES_128_ECB:128:0 + +CMAC init #2 AES-192: OK +depends_on:MBEDTLS_AES_C +mbedtls_cmac_setkey:MBEDTLS_CIPHER_AES_192_ECB:192:0 + +CMAC init #3 AES-256: OK +depends_on:MBEDTLS_AES_C +mbedtls_cmac_setkey:MBEDTLS_CIPHER_AES_256_ECB:256:0 + +CMAC init #4 3DES : OK +depends_on:MBEDTLS_DES_C +mbedtls_cmac_setkey:MBEDTLS_CIPHER_DES_EDE3_ECB:192:0 + +CMAC init #5 AES-224: bad key size +depends_on:MBEDTLS_AES_C +mbedtls_cmac_setkey:MBEDTLS_CIPHER_ID_AES:224:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + +CMAC init #6 Camellia: wrong cipher +depends_on:MBEDTLS_CAMELLIA_C +mbedtls_cmac_setkey:MBEDTLS_CIPHER_ID_CAMELLIA:128:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + diff --git a/tests/suites/test_suite_cmac.function b/tests/suites/test_suite_cmac.function new file mode 100644 index 000000000..81a5a0aaa --- /dev/null +++ b/tests/suites/test_suite_cmac.function @@ -0,0 +1,37 @@ +/* BEGIN_HEADER */ +#include "mbedtls/cipher.h" +#include "mbedtls/cmac.h" +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES + * depends_on:MBEDTLS_CMAC_C + * END_DEPENDENCIES + */ + +/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ +void mbedtls_cmac_self_test( ) +{ + TEST_ASSERT( mbedtls_cmac_self_test( 1 ) == 0 ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void mbedtls_cmac_setkey( int cipher_type, int key_size, + int result ) +{ + const mbedtls_cipher_info_t *cipher_info; + unsigned char key[32]; + unsigned char buf[16]; + unsigned char tmp[16]; + + memset( key, 0x2A, sizeof( key ) ); + TEST_ASSERT( (unsigned) key_size <= 8 * sizeof( key ) ); + + TEST_ASSERT( ( cipher_info = mbedtls_cipher_info_from_type( cipher_type ) ) + != NULL ); + + TEST_ASSERT( result == mbedtls_cipher_cmac( cipher_info, key, key_size, + buf, 16, tmp ) != 0 ); +} +/* END_CASE */ + From 549dc3d75e1cf034ccf59e482e6c77cef03b5eac Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 14:14:19 +0100 Subject: [PATCH 49/83] Add CMAC functions to the benchmark sample application --- programs/test/benchmark.c | 69 +++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c index 8ab32f677..86b84250a 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 @@ int main( void ) #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,7 +93,8 @@ int main( void ) #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" @@ -234,7 +236,9 @@ unsigned char buf[BUFSIZE]; 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 @@ int main( int argc, char *argv[] ) 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 @@ int main( int argc, char *argv[] ) } #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 @@ int main( int argc, char *argv[] ) 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,37 @@ int main( int argc, char *argv[] ) } } #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 ) From 37a064af7693a32084631db5069f8e5b2c110e1b Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 14:15:58 +0100 Subject: [PATCH 50/83] Remove CMAC as a separate and independent error group --- include/mbedtls/error.h | 1 - scripts/generate_errors.pl | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 6e3905d86..5e549f6b6 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -66,7 +66,6 @@ * PBKDF2 1 0x007C-0x007C * HMAC_DRBG 4 0x0003-0x0009 * CCM 2 0x000D-0x000F - * CMAC 3 0x0011-0x0015 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index dd91151d6..cfcf07c8f 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -33,7 +33,7 @@ my @low_level_modules = ( "AES", "ASN1", "BLOWFISH", "CAMELLIA", "BIGNUM", "BASE64", "XTEA", "PBKDF2", "OID", "PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY", "HMAC_DRBG", "MD2", "MD4", "MD5", "RIPEMD160", - "SHA1", "SHA256", "SHA512", "GCM", "THREADING", "CCM", "CMAC" ); + "SHA1", "SHA256", "SHA512", "GCM", "THREADING", "CCM" ); my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL", "PK", "PKCS12", "PKCS5" ); From 01ba45b1392ab6c21b65786920ae594a9e3dc844 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 14:17:01 +0100 Subject: [PATCH 51/83] Clean up comment formatting in md.h --- include/mbedtls/md.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h index b90235533..9b996a951 100644 --- a/include/mbedtls/md.h +++ b/include/mbedtls/md.h @@ -304,8 +304,8 @@ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *inpu /** * \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 @@ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); /** * \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 * From 21c54816f5744dcbbb992459cda8a2e1a83f901d Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 14:17:37 +0100 Subject: [PATCH 52/83] Add CMAC to ChangeLog --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 60383a97b..489c4bf48 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ mbed TLS ChangeLog (Sorted per branch, date) = 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 From 7ca3109614bfc1c8c1b3ffdfbf009b88bac5afbf Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 14:39:15 +0100 Subject: [PATCH 53/83] Regenerate error.c file to remove CMAC --- library/error.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/error.c b/library/error.c index e7b521bc7..71d4faa70 100644 --- a/library/error.c +++ b/library/error.c @@ -69,10 +69,6 @@ #include "mbedtls/cipher.h" #endif -#if defined(MBEDTLS_CMAC_C) -#include "mbedtls/cmac.h" -#endif - #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #endif From 8308a445d88864fb76996a7999baa23e35ca6886 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 15:12:59 +0100 Subject: [PATCH 54/83] Fix naming in cmac.h to comply with check-names.sh --- include/mbedtls/cmac.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index ceeb20add..6d531dddb 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -37,9 +37,10 @@ extern "C" { #endif /** - * \brief CMAC context structure + * CMAC context structure - Contains internal state information only */ -typedef struct mbedtls_cmac_context_t { +struct mbedtls_cmac_context_t +{ /** Internal state of the CMAC algorithm */ unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; @@ -53,8 +54,7 @@ typedef struct mbedtls_cmac_context_t { /** Flag to indicate if the last block needs padding */ int padding_flag; -} -mbedtls_cmac_context_t; +}; /** * \brief Set the CMAC key and prepare to authenticate the input From 94ffde7b0ae4c297947ec15ae766c3f76e2ebbc0 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 5 Oct 2016 15:33:53 +0100 Subject: [PATCH 55/83] Fix CMAC interface for doxygen Parameters didn't match the function definition. --- include/mbedtls/cmac.h | 2 +- library/cmac.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 6d531dddb..71f7ab43a 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -69,7 +69,7 @@ struct mbedtls_cmac_context_t * \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 keylen ); + const unsigned char *key, size_t keybits ); /** * \brief Generic CMAC process buffer. diff --git a/library/cmac.c b/library/cmac.c index 1eb1c1074..5a6206ea9 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -201,7 +201,7 @@ static void cmac_pad( unsigned char padded_block[16], } int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, - const unsigned char *key, size_t keylen ) + const unsigned char *key, size_t keybits ) { mbedtls_cipher_type_t type; mbedtls_cmac_context_t *cmac_ctx; @@ -211,7 +211,7 @@ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - if( ( retval = mbedtls_cipher_setkey( ctx, key, keylen, + if( ( retval = mbedtls_cipher_setkey( ctx, key, keybits, MBEDTLS_ENCRYPT ) ) != 0 ) return( retval ); From 69283e51d54e5eb7fbea4ad4d182e9778647608d Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Thu, 6 Oct 2016 12:49:58 +0100 Subject: [PATCH 56/83] Clean up and minor fixes following review Minor fixes following review including: * formatting changes including indentation and code style * corrections * removal of debug code * clarification of code through variable renaming * memory leak * compiler warnings --- include/mbedtls/check_config.h | 2 +- include/mbedtls/cmac.h | 13 +- include/mbedtls/config.h | 2 +- library/cmac.c | 285 ++++++++++++-------------- tests/suites/test_suite_cmac.function | 2 +- 5 files changed, 140 insertions(+), 164 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 8ebe438c0..fe86c1e8d 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -78,7 +78,7 @@ #endif #if defined(MBEDTLS_CMAC_C) && \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_DES_C) + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) #error "MBEDTLS_CMAC_C defined, but not all prerequisites" #endif diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index 71f7ab43a..d94c015e0 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -30,10 +30,13 @@ 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_SIZE 16 /* longest known is AES */ +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /* longest used by CMAC is AES */ #else -#define MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE 8 /* longest known is 3DES */ +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */ #endif /** @@ -43,11 +46,11 @@ struct mbedtls_cmac_context_t { /** Internal state of the CMAC algorithm */ - unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; + 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_SIZE]; + unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; /** Length of data pending to be processed */ size_t unprocessed_len; @@ -133,7 +136,7 @@ int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, const unsigned char *input, size_t ilen, unsigned char *output ); -#ifdef MBEDTLS_AES_C +#if defined(MBEDTLS_AES_C) /** * \brief AES-CMAC-128-PRF * Implementation of (AES-CMAC-PRF-128), as defined in RFC 4615 diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 4546d596a..498e5b598 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1679,7 +1679,7 @@ * * Module: library/cmac.c * - * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_DES_C + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C * */ //#define MBEDTLS_CMAC_C diff --git a/library/cmac.c b/library/cmac.c index 5a6206ea9..7fc513a45 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -1,7 +1,7 @@ /* * \file cmac.c * - * \brief NIST SP800-38B compliant CMAC implementation + * \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 @@ -63,8 +63,7 @@ defined(MBEDTLS_DES_C) ) #include #define mbedtls_printf printf -#endif /* defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || - * defined(MBEDTLS_DES_C) )*/ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C || MBEDTLS_DES_C */ #endif /* MBEDTLS_PLATFORM_C */ /* Implementation that should never be optimized out by the compiler */ @@ -82,7 +81,7 @@ static void mbedtls_zeroize( void *v, size_t 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. + * 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, @@ -94,11 +93,11 @@ static int cmac_multiply_by_u( unsigned char *output, unsigned char overflow = 0x00; int i; - if( blocksize == 16 ) + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) { R_n = R_128; } - else if( blocksize == 8 ) + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) { R_n = R_64; } @@ -141,7 +140,7 @@ 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]; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; size_t olen, block_size; mbedtls_zeroize( L, sizeof( L ) ); @@ -167,8 +166,9 @@ exit: return( ret ); } -static void cmac_xor_block(unsigned char *output, const unsigned char *input1, - const unsigned char *input2, const size_t block_size ) +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) { size_t index; @@ -182,7 +182,7 @@ static void cmac_xor_block(unsigned char *output, const unsigned char *input1, * 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[16], +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 ) @@ -205,7 +205,6 @@ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, { mbedtls_cipher_type_t type; mbedtls_cmac_context_t *cmac_ctx; - unsigned int block_size; int retval; if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) @@ -215,7 +214,6 @@ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, MBEDTLS_ENCRYPT ) ) != 0 ) return( retval ); - block_size = ctx->cipher_info->block_size; type = ctx->cipher_info->type; switch( type ) @@ -288,7 +286,6 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, /* Iterate across the input data in block sized chunks */ for( j = 0; j < n - 1; j++ ) { - //char *ptr = input + block_size * j ; cmac_xor_block( state, input, state, block_size ); if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, @@ -321,10 +318,10 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, unsigned char *output ) { mbedtls_cmac_context_t* cmac_ctx; - unsigned char *state; - unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; - unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; - unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; + 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; @@ -336,16 +333,11 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, block_size = ctx->cipher_info->block_size; state = cmac_ctx->state; - mbedtls_zeroize( K1, sizeof(K1) ); - mbedtls_zeroize( K2, sizeof(K2) ); + mbedtls_zeroize( K1, sizeof( K1 ) ); + mbedtls_zeroize( K2, sizeof( K2 ) ); cmac_generate_subkeys( ctx, K1, K2 ); -// mbedtls_zeroize( M_last, sizeof(M_last) ); -// if( cmac_ctx->unprocessed_len > 0 ) -// needs_padding = 1; - - unsigned char *last_block = cmac_ctx->unprocessed_block; - //unsigned char *M_last = cmac_ctx->unprocessed_block; + last_block = cmac_ctx->unprocessed_block; /* Calculate last block */ if( cmac_ctx->padding_flag ) @@ -367,21 +359,20 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, 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) ); + mbedtls_zeroize( K1, sizeof( K1 ) ); + mbedtls_zeroize( K2, sizeof( K2 ) ); + cmac_ctx->padding_flag = 1; cmac_ctx->unprocessed_len = 0; mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_len ) ); + sizeof( cmac_ctx->unprocessed_block ) ); - mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE ); + mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); return( ret ); } @@ -398,7 +389,7 @@ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) cmac_ctx->unprocessed_len = 0; mbedtls_zeroize( cmac_ctx->unprocessed_block, sizeof( cmac_ctx->unprocessed_len ) ); - + mbedtls_zeroize( cmac_ctx->state, MBEDTLS_CIPHER_BLKSIZE_MAX ); cmac_ctx->padding_flag = 1; return( 0 ); @@ -421,28 +412,24 @@ int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, goto exit; ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); - if( ret != 0 ) goto exit; - // Are we leaking here? Should we reset or free? ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); if( ret != 0 ) goto exit; - mbedtls_cipher_cmac_finish( &ctx, output ); - if( ret != 0 ) - goto exit; + ret = mbedtls_cipher_cmac_finish( &ctx, output ); exit: + mbedtls_cipher_free( &ctx ); + return( ret ); } -#ifdef MBEDTLS_AES_C +#if defined(MBEDTLS_AES_C) /* -// TODO - clean up comments - * PRF based on CMAC with AES-128 - * See RFC 4615 + * 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, @@ -450,8 +437,11 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, { int ret; const mbedtls_cipher_info_t *cipher_info; - unsigned char zero_key[16]; - unsigned char int_key[16]; + 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 ) @@ -461,14 +451,14 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, goto exit; } - if( key_length == 16 ) + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) { /* Use key as is */ - memcpy( int_key, key, 16 ); + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); } else { - memset( zero_key, 0, 16 ); + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, key_length, int_key ); @@ -486,7 +476,7 @@ exit: } #endif /* MBEDTLS_AES_C */ -#ifdef MBEDTLS_SELF_TEST +#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 @@ -498,10 +488,6 @@ exit: #define NB_CMAC_TESTS_PER_KEY 4 #define NB_PRF_TESTS 3 -// TODO - should use a value somewhere else -#define AES_BLOCK_SIZE 16 -#define DES3_BLOCK_SIZE 8 - #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[] = { @@ -514,11 +500,9 @@ static const unsigned char test_message[] = { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ - -#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */ - -#ifdef MBEDTLS_AES_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, @@ -532,7 +516,7 @@ 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][AES_BLOCK_SIZE] = { +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 @@ -542,7 +526,7 @@ static const unsigned char aes_128_subkeys[2][AES_BLOCK_SIZE] = { 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b } }; -static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = { +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 @@ -567,7 +551,7 @@ static const unsigned char aes_192_key[24] = { 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b }; -static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = { +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 @@ -577,7 +561,7 @@ static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = { 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c } }; -static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = { +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 @@ -603,7 +587,7 @@ static const unsigned char aes_256_key[32] = { 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 }; -static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = { +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 @@ -613,7 +597,7 @@ static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = { 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 } }; -static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = { +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 @@ -633,7 +617,7 @@ static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BL }; #endif /* MBEDTLS_AES_C */ -#ifdef MBEDTLS_DES_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, @@ -656,7 +640,7 @@ static const unsigned char des3_2key_subkeys[2][8] = { 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5 } }; -static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = { +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 }, @@ -685,7 +669,7 @@ static const unsigned char des3_3key_subkeys[2][8] = { 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5 } }; -static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = { +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 }, @@ -702,7 +686,7 @@ static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3 #endif /* MBEDTLS_DES_C */ -#ifdef MBEDTLS_AES_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, @@ -752,23 +736,22 @@ static int cmac_test_subkeys( int verbose, int i, ret; mbedtls_cipher_context_t ctx; const mbedtls_cipher_info_t *cipher_info; - unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; - unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE]; + 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 */ - ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; - goto exit; + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } + mbedtls_cipher_init( &ctx ); + for( i = 0; i < num_tests; i++ ) { if( verbose != 0 ) - mbedtls_printf( " %s CMAC subkey #%u: ", testname, i +1 ); - - mbedtls_cipher_init( &ctx ); + mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) { @@ -808,30 +791,25 @@ static int cmac_test_subkeys( int verbose, } exit: + mbedtls_cipher_free( &ctx ); + return( ret ); } -static inline 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 ) +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; - - output = mbedtls_calloc( block_size, sizeof( unsigned char ) ); - if( output == NULL ) - { - ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED; - goto exit; - } + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; cipher_info = mbedtls_cipher_info_from_type( cipher_type ); if( cipher_info == NULL ) @@ -864,32 +842,32 @@ static inline int cmac_test_wth_cipher( int verbose, if( verbose != 0 ) mbedtls_printf( "passed\n" ); } -exit: - mbedtls_free( output ); +exit: return( ret ); } -#ifdef MBEDTLS_AES_C -static inline int test_aes128_cmac_prf( int verbose ) +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) { int i; int ret; - unsigned char output[16]; + 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], 16 ) != 0 ) + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( ret ); - } else if( verbose != 0 ) + } + else if( verbose != 0 ) { mbedtls_printf( "passed\n" ); } @@ -902,17 +880,16 @@ int mbedtls_cmac_self_test( int verbose ) { int ret; -#ifdef MBEDTLS_AES_C - +#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, - AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + "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 ); } @@ -923,23 +900,23 @@ int mbedtls_cmac_self_test( int verbose ) 128, test_message, aes_message_lengths, - (const unsigned char*) aes_128_expected_result, + (const unsigned char*)aes_128_expected_result, MBEDTLS_CIPHER_AES_128_ECB, - AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + 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, - AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + "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 ); } @@ -950,103 +927,99 @@ int mbedtls_cmac_self_test( int verbose ) 192, test_message, aes_message_lengths, - (const unsigned char*) aes_192_expected_result, + (const unsigned char*)aes_192_expected_result, MBEDTLS_CIPHER_AES_192_ECB, - AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) != 0 ) ) { -mbedtls_printf("ret = %x\n", ret); 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, - AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + "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, + 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, + (const unsigned char*)aes_256_expected_result, MBEDTLS_CIPHER_AES_256_ECB, - AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) != 0 ) ) { return( ret ); } #endif /* MBEDTLS_AES_C */ -#ifdef MBEDTLS_DES_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, - DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + "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, + (const unsigned char*)des3_2key_expected_result, MBEDTLS_CIPHER_DES_EDE3_ECB, - DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + 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, - DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + "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, + (const unsigned char*)des3_3key_expected_result, MBEDTLS_CIPHER_DES_EDE3_ECB, - DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) !=0 ) ) + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) != 0 ) ) { return( ret ); } #endif /* MBEDTLS_DES_C */ -#ifdef MBEDTLS_AES_C +#if defined(MBEDTLS_AES_C) if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) ) return( ret ); #endif /* MBEDTLS_AES_C */ diff --git a/tests/suites/test_suite_cmac.function b/tests/suites/test_suite_cmac.function index 81a5a0aaa..3b23b521e 100644 --- a/tests/suites/test_suite_cmac.function +++ b/tests/suites/test_suite_cmac.function @@ -31,7 +31,7 @@ void mbedtls_cmac_setkey( int cipher_type, int key_size, != NULL ); TEST_ASSERT( result == mbedtls_cipher_cmac( cipher_info, key, key_size, - buf, 16, tmp ) != 0 ); + buf, 16, tmp ) ); } /* END_CASE */ From b981b16379f3896422b5d8c9e9ad1ecae583c370 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Thu, 6 Oct 2016 10:27:22 +0100 Subject: [PATCH 57/83] Minor fixes to formatting and compilation conditions --- programs/test/benchmark.c | 11 ++++++----- programs/test/selftest.c | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c index 86b84250a..22a878db5 100644 --- a/programs/test/benchmark.c +++ b/programs/test/benchmark.c @@ -93,14 +93,14 @@ int main( void ) #define OPTIONS \ "md4, md5, ripemd160, sha1, sha256, sha512,\n" \ - "arc4, des3, des, 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 \ @@ -401,8 +401,8 @@ int main( int argc, char *argv[] ) 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 ) ); + mbedtls_cipher_cmac( cipher_info, tmp, 192, buf, + BUFSIZE, output ) ); } #endif /* MBEDTLS_CMAC_C */ #endif /* MBEDTLS_DES_C */ @@ -501,7 +501,8 @@ int main( int argc, char *argv[] ) 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 ) ); + mbedtls_aes_cmac_prf_128( tmp, 16, buf, BUFSIZE, + output ) ); } #endif /* MBEDTLS_CMAC_C */ #endif /* MBEDTLS_AES_C */ diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 33f96ea13..1941ad051 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -278,7 +278,7 @@ int main( int argc, char *argv[] ) suites_tested++; #endif -#if defined(MBEDTLS_CMAC_C) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +#if defined(MBEDTLS_CMAC_C) if( ( mbedtls_cmac_self_test( v ) ) != 0 ) { suites_failed++; From d241f1cf17a10b56aa6c70c83e468014d1869db6 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Thu, 6 Oct 2016 10:39:49 +0100 Subject: [PATCH 58/83] Fixes following review Fixes issue of not zeroing entire block on reset and conditional compilation. --- library/cmac.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 7fc513a45..9e4dc892a 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -59,8 +59,7 @@ #include #define mbedtls_calloc calloc #define mbedtls_free free -#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || \ - defined(MBEDTLS_DES_C) ) +#if defined(MBEDTLS_SELF_TEST) #include #define mbedtls_printf printf #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C || MBEDTLS_DES_C */ @@ -388,8 +387,9 @@ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) /* Reset the internal state */ cmac_ctx->unprocessed_len = 0; mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_len ) ); - mbedtls_zeroize( cmac_ctx->state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + sizeof( cmac_ctx->unprocessed_block )); + mbedtls_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); cmac_ctx->padding_flag = 1; return( 0 ); From a592dcc1c6277bb191269e709cdd3d5593e593ed Mon Sep 17 00:00:00 2001 From: Andres AG Date: Thu, 6 Oct 2016 15:23:39 +0100 Subject: [PATCH 59/83] Clean up of formatting, and potential integer overflow fix --- include/mbedtls/cmac.h | 2 +- library/cmac.c | 8 ++++---- programs/test/benchmark.c | 4 ++-- tests/Makefile | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index d94c015e0..f64ae69b4 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -48,7 +48,7 @@ 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 + /** 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]; diff --git a/library/cmac.c b/library/cmac.c index 9e4dc892a..03d939278 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -245,7 +245,7 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, { mbedtls_cmac_context_t* cmac_ctx; unsigned char *state; - int n, j, ret = 0; + int n, j, ret = 0; size_t olen, block_size; if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || @@ -259,7 +259,7 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, /* Is their data still to process from the last call, that's equal to * or greater than a block? */ if( cmac_ctx->unprocessed_len > 0 && - ilen + cmac_ctx->unprocessed_len > block_size ) + ilen > block_size - cmac_ctx->unprocessed_len ) { memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], input, @@ -387,7 +387,7 @@ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) /* Reset the internal state */ cmac_ctx->unprocessed_len = 0; mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block )); + sizeof( cmac_ctx->unprocessed_block ) ); mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); cmac_ctx->padding_flag = 1; @@ -822,7 +822,7 @@ static int cmac_test_wth_cipher( int verbose, for( i = 0; i < num_tests; i++ ) { if( verbose != 0 ) - mbedtls_printf( " %s CMAC #%u: ", testname, i +1 ); + mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, message_lengths[i], output ) ) != 0 ) diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c index 22a878db5..eb578e730 100644 --- a/programs/test/benchmark.c +++ b/programs/test/benchmark.c @@ -494,8 +494,8 @@ int main( int argc, char *argv[] ) cipher_info = mbedtls_cipher_info_from_type( cipher_type ); TIME_AND_TSC( title, - mbedtls_cipher_cmac( cipher_info, tmp, keysize, - buf, BUFSIZE, output ) ); + mbedtls_cipher_cmac( cipher_info, tmp, keysize, + buf, BUFSIZE, output ) ); } memset( buf, 0, sizeof( buf ) ); diff --git a/tests/Makefile b/tests/Makefile index 23c68ec86..4787f2508 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -50,7 +50,7 @@ APPS = test_suite_aes.ecb$(EXEXT) test_suite_aes.cbc$(EXEXT) \ 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_cmac$(EXEXT) \ test_suite_cipher.aes$(EXEXT) \ test_suite_cipher.arc4$(EXEXT) test_suite_cipher.ccm$(EXEXT) \ test_suite_cipher.gcm$(EXEXT) \ From 604d399a5ca3a725f367e44a65cf55ce8fba7003 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Thu, 6 Oct 2016 19:02:49 +0100 Subject: [PATCH 60/83] Add extra compilation conditions to gen_key.c #559 The sample application programs/pkey/gen_key.c uses the library function mbedtls_pk_write_key_pem() which is dependent on the configuration option MBEDTLS_PEM_WRITE_C. If the option isn't defined the build breaks. This change adds the compilation condition MBEDTLS_PEM_WRITE_C to the gen_key.c sample application. --- programs/pkey/gen_key.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c index 63a3aeb98..48126948d 100644 --- a/programs/pkey/gen_key.c +++ b/programs/pkey/gen_key.c @@ -120,12 +120,14 @@ int dev_random_entropy_poll( void *data, unsigned char *output, 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 @@ exit: 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 */ + From f73fd701c07a8637b2570eb4f34416e946ef78bf Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Fri, 7 Oct 2016 11:17:44 +0100 Subject: [PATCH 61/83] Update Changelog for fix #559 --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index 489c4bf48..8e255260f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,9 @@ Bugfix a contribution from Tobias Tangemann. #541 * Fixed cert_app sample program for debug output and for use when no root certificates are provided. + * Fixed sample application 'programs/pkey/gen_key.c' for builds where the + configuration MBEDTLS_PEM_WRITE_C is not defined. Found by inestlerode. + #559. Changes * Extended test coverage of special cases, and added new timing test suite. From 420be4ea0461795cf8d35981a2c7e7c01ba9d810 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Fri, 7 Oct 2016 12:55:43 +0100 Subject: [PATCH 62/83] Fix bracketing in cmac.c The bracketing in some expressions where an assignment was being made in an if statement in cmac.c had been accidentally broken and was causing compiler warnings with armcc. --- library/cmac.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 03d939278..f755d409f 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -778,8 +778,8 @@ static int cmac_test_subkeys( int verbose, goto exit; } - if( ( ret = memcmp( K1, subkeys, block_size ) != 0 ) || - ( ret = memcmp( K2, &subkeys[block_size], block_size ) != 0 ) ) + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); @@ -889,7 +889,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)aes_128_subkeys, MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -903,7 +903,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)aes_128_expected_result, MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -916,7 +916,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)aes_192_subkeys, MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -930,7 +930,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)aes_192_expected_result, MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -943,7 +943,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)aes_256_subkeys, MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -957,7 +957,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)aes_256_expected_result, MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -972,7 +972,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)des3_2key_subkeys, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -986,7 +986,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)des3_2key_expected_result, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -999,7 +999,7 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)des3_3key_subkeys, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) { return( ret ); } @@ -1013,14 +1013,14 @@ int mbedtls_cmac_self_test( int verbose ) (const unsigned char*)des3_3key_expected_result, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) != 0 ) ) + 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 ) ) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) return( ret ); #endif /* MBEDTLS_AES_C */ From 203a6934e718af4849eadb4021b7688d3d191a26 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Fri, 7 Oct 2016 15:00:17 +0100 Subject: [PATCH 63/83] Add extra compilation conditions to X.509 samples The sample applications programs/pkey/cert_req.c and programs/pkey/cert_write.c use the library functions mbedtls_pk_write_csr_pem() and mbedtls_pk_write_crt_pem() respectively which are dependent on the configuration option MBEDTLS_PEM_WRITE_C. If the option isn't defined the build breaks. This change adds the compilation condition MBEDTLS_PEM_WRITE_C to these sample application. --- programs/x509/cert_req.c | 5 +++-- programs/x509/cert_write.c | 11 ++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index 5cafb80cd..30df2162a 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 @@ exit: 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 7907d8221..66e5f1dab 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 @@ exit: } #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 */ From f77309cb3591af98d5a87672ac4ec87d6bcc5df5 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Fri, 7 Oct 2016 15:56:07 +0100 Subject: [PATCH 64/83] Update Changelog for fixes to X.509 sample apps --- ChangeLog | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8e255260f..911f28017 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,9 +31,9 @@ Bugfix a contribution from Tobias Tangemann. #541 * Fixed cert_app sample program for debug output and for use when no root certificates are provided. - * Fixed sample application 'programs/pkey/gen_key.c' for builds where the - configuration MBEDTLS_PEM_WRITE_C is not defined. Found by inestlerode. - #559. + * 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. Changes * Extended test coverage of special cases, and added new timing test suite. From b98eaff408749196c13d6bd46b4941e0c98783de Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Tue, 11 Oct 2016 10:13:52 +0100 Subject: [PATCH 65/83] Revise Changelog to clarify and add credit --- ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f9421062..defebd031 100644 --- a/ChangeLog +++ b/ChangeLog @@ -34,8 +34,8 @@ Bugfix * Fixed the sample applications gen_key.c, cert_req.c and cert_write.c for builds where the configuration MBEDTLS_PEM_WRITE_C is not defined. Found by inestlerode. #559. - * Fixed default threading implementation to avoid accidental double - initialisations and double frees. + * Fixed pthread implementation to avoid unintended double initialisations + and double frees. (found by Niklas Amnebratt) Changes * Extended test coverage of special cases, and added new timing test suite. From 6b0774ab1a716e303a2ebd0ece70cffca56bcbb1 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Mon, 10 Oct 2016 21:37:42 +0100 Subject: [PATCH 66/83] Fix issues in CMAC in repeated updates Successive calls to mbedtls_cipher_cmac_update() which weren't block aligned were failing, which is fixed by this commit. --- library/cmac.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index f755d409f..8ea0685b7 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -256,8 +256,8 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, block_size = ctx->cipher_info->block_size; state = ctx->cmac_ctx->state; - /* Is their data still to process from the last call, that's equal to - * or greater than a block? */ + /* 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 ) { @@ -273,9 +273,8 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, goto exit; } - ilen -= block_size; - input += cmac_ctx->unprocessed_len; - + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; cmac_ctx->unprocessed_len = 0; } @@ -300,8 +299,10 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, /* If there is data left over that wasn't aligned to a block */ if( ilen > 0 ) { - memcpy( &cmac_ctx->unprocessed_block, input, ilen ); - cmac_ctx->unprocessed_len = ilen; + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; if( ilen % block_size > 0 ) cmac_ctx->padding_flag = 1; @@ -339,7 +340,7 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, last_block = cmac_ctx->unprocessed_block; /* Calculate last block */ - if( cmac_ctx->padding_flag ) + if( cmac_ctx->padding_flag && 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 ); From 33183fd408f538c7b84ef1982c6e2a89e9c1c922 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Mon, 10 Oct 2016 21:41:03 +0100 Subject: [PATCH 67/83] Extend test coverage of CMAC Expands tests to include NULL tests and successive calls to mbedtls_cipher_cmac_update() and mbedtls_cipher_cmac_reset(). --- tests/suites/test_suite_cmac.data | 39 +++- tests/suites/test_suite_cmac.function | 273 +++++++++++++++++++++++++- 2 files changed, 309 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_cmac.data b/tests/suites/test_suite_cmac.data index a913ffdd8..70b7609e4 100644 --- a/tests/suites/test_suite_cmac.data +++ b/tests/suites/test_suite_cmac.data @@ -1,6 +1,9 @@ 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 @@ -21,7 +24,41 @@ CMAC init #5 AES-224: bad key size depends_on:MBEDTLS_AES_C mbedtls_cmac_setkey:MBEDTLS_CIPHER_ID_AES:224:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -CMAC init #6 Camellia: wrong cipher +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 index 3b23b521e..f452afef4 100644 --- a/tests/suites/test_suite_cmac.function +++ b/tests/suites/test_suite_cmac.function @@ -15,6 +15,87 @@ void mbedtls_cmac_self_test( ) } /* 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 ); + +} +/* END_CASE */ + /* BEGIN_CASE */ void mbedtls_cmac_setkey( int cipher_type, int key_size, int result ) @@ -30,8 +111,196 @@ void mbedtls_cmac_setkey( int cipher_type, int key_size, TEST_ASSERT( ( cipher_info = mbedtls_cipher_info_from_type( cipher_type ) ) != NULL ); - TEST_ASSERT( result == mbedtls_cipher_cmac( cipher_info, key, key_size, - buf, 16, tmp ) ); + 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 ); + + /* 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 ); + + mbedtls_cipher_init( &ctx ); + + 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 ); + + 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 ); + + /* 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 ); + + mbedtls_cipher_init( &ctx ); + + 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 ); + + + mbedtls_cipher_free( &ctx ); } /* END_CASE */ From 53da6ae842610aa3fc2d3e413d6667646aa4d2ef Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Mon, 10 Oct 2016 22:03:39 +0100 Subject: [PATCH 68/83] Add CMAC test suite to CMakeLists.txt --- tests/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 13659de0f..21583c40a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -61,6 +61,7 @@ add_test_suite(cipher cipher.des) 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) From bd8d22192012bc51c62b566540ff4c576516cbae Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Tue, 11 Oct 2016 12:05:51 +0100 Subject: [PATCH 69/83] Fix exit and formatting in CMAC test suite Minor fixes following review. --- tests/suites/test_suite_cmac.function | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_cmac.function b/tests/suites/test_suite_cmac.function index f452afef4..1f88ddcfe 100644 --- a/tests/suites/test_suite_cmac.function +++ b/tests/suites/test_suite_cmac.function @@ -79,9 +79,9 @@ void mbedtls_cmac_null_args( ) 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_data, 16, + test_output ) == + MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); TEST_ASSERT( mbedtls_aes_cmac_prf_128( test_key, 16, NULL, 16, @@ -188,6 +188,7 @@ void mbedtls_cmac_multiple_blocks( int cipher_type, TEST_ASSERT( memcmp( output, expected_result, block_size ) == 0 ); +exit: mbedtls_cipher_free( &ctx ); } /* END_CASE */ @@ -255,7 +256,7 @@ void mbedtls_cmac_multiple_operations_same_key( int cipher_type, /* Multiple partial and complete blocks. A negative length means skip the * update operation */ - if( block_a1_len >= 0) + if( block_a1_len >= 0 ) TEST_ASSERT( mbedtls_cipher_cmac_update( &ctx, (unsigned char*)block_a1, block_a1_len ) == 0); @@ -299,7 +300,7 @@ void mbedtls_cmac_multiple_operations_same_key( int cipher_type, TEST_ASSERT( memcmp( output, expected_result_b, block_size ) == 0 ); - +exit: mbedtls_cipher_free( &ctx ); } /* END_CASE */ From 2573136fa8147abeddcdc8c49b7a3d3a284f7170 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Fri, 30 Sep 2016 13:11:29 +0100 Subject: [PATCH 70/83] Fix to test output in test suites Fixes the test suites to consistently use mbedtls_fprintf to output to stdout or stderr. Also redirects output from the tests to /dev/null to avoid confusing output if the test suite code or library outputs anything to stdout. --- tests/suites/helpers.function | 12 +++---- tests/suites/main_test.function | 61 ++++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index d12be75ce..2475a3cc6 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -8,16 +8,13 @@ #include "mbedtls/platform.h" #else #include -#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 @@ -355,7 +352,8 @@ static void test_fail( const char *test, int line_no, const char* filename ) { 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 ac5322e45..ed5d4146c 100644 --- a/tests/suites/main_test.function +++ b/tests/suites/main_test.function @@ -7,7 +7,8 @@ int verify_string( char **str ) 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 @@ int verify_int( char *str, int *value ) 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 ); } @@ -77,6 +79,12 @@ SUITE_POST_DEP /*----------------------------------------------------------------------------*/ /* Test dispatch code */ +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#include +#endif +#include + + int dep_check( char *str ) { if( str == NULL ) @@ -249,6 +257,7 @@ int main(int argc, const char *argv[]) const char **test_files = NULL; int testfile_count = 0; int option_verbose = 0; + int tests_stdout; /* Other Local variables */ int arg_index = 1; @@ -343,7 +352,8 @@ int main(int argc, const char *argv[]) { 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 +389,7 @@ int main(int argc, const char *argv[]) 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 +405,50 @@ int main(int argc, const char *argv[]) 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 ) + { + /* Redirect all stdout output to /dev/null */ + tests_stdout = dup( fileno(stdout) ); + if( tests_stdout == -1 ) + { + /* Redirection has failed with no stdout so exit */ + exit(1); + } + + fflush( stdout ); + fclose( stdout ); + stdout = fopen("/dev/null", "w" ); + if( stdout == NULL ) + { + /* 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 stdout */ + fflush( stdout ); + fclose( stdout ); + + stdout = fdopen ( tests_stdout, "w"); + if( stdout == NULL ) + { + /* Redirection has failed with no stdout so exit */ + exit(1); + } + } +#endif /* __unix__ || __APPLE__ __MACH__ */ + } if( unmet_dep_count > 0 || ret == DISPATCH_UNSUPPORTED_SUITE ) From 8ca53b51c52982686262015fa84d7ec30ebb61ea Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 5 Oct 2016 10:57:49 +0100 Subject: [PATCH 71/83] Fix minor style issues in test framework --- tests/suites/helpers.function | 40 +++++++++++++++++++++++++++++++++ tests/suites/main_test.function | 40 +++++++-------------------------- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index 2475a3cc6..5938447af 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -34,6 +34,9 @@ typedef UINT32 uint32_t; #include +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#include +#endif /*----------------------------------------------------------------------------*/ /* Constants */ @@ -102,6 +105,43 @@ static int test_errors = 0; /*----------------------------------------------------------------------------*/ /* 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; +} +#endif /* __unix__ || __APPLE__ __MACH__ */ + static int unhexify( unsigned char *obuf, const char *ibuf ) { unsigned char c, c2; diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function index ed5d4146c..14209a576 100644 --- a/tests/suites/main_test.function +++ b/tests/suites/main_test.function @@ -79,12 +79,6 @@ SUITE_POST_DEP /*----------------------------------------------------------------------------*/ /* Test dispatch code */ -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -#include -#endif -#include - - int dep_check( char *str ) { if( str == NULL ) @@ -257,7 +251,6 @@ int main(int argc, const char *argv[]) const char **test_files = NULL; int testfile_count = 0; int option_verbose = 0; - int tests_stdout; /* Other Local variables */ int arg_index = 1; @@ -268,6 +261,7 @@ int main(int argc, const char *argv[]) char buf[5000]; char *params[50]; void *pointer; + int stdout_fd = 0; #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC) @@ -353,7 +347,7 @@ int main(int argc, const char *argv[]) if( unmet_dep_count > 0 ) { mbedtls_fprintf( stderr, - "FATAL: Dep count larger than zero at start of loop\n"); + "FATAL: Dep count larger than zero at start of loop\n" ); mbedtls_exit( MBEDTLS_EXIT_FAILURE ); } unmet_dep_count = 0; @@ -389,7 +383,7 @@ int main(int argc, const char *argv[]) unmet_dependencies[ unmet_dep_count ] = strdup(params[i]); if( unmet_dependencies[ unmet_dep_count ] == NULL ) { - mbedtls_fprintf( stderr, "FATAL: Out of memory\n"); + mbedtls_fprintf( stderr, "FATAL: Out of memory\n" ); mbedtls_exit( MBEDTLS_EXIT_FAILURE ); } unmet_dep_count++; @@ -412,21 +406,11 @@ int main(int argc, const char *argv[]) */ if( !option_verbose ) { - /* Redirect all stdout output to /dev/null */ - tests_stdout = dup( fileno(stdout) ); - if( tests_stdout == -1 ) + stdout_fd = redirect_output( &stdout, "/dev/null" ); + if( stdout_fd == -1 ) { /* Redirection has failed with no stdout so exit */ - exit(1); - } - - fflush( stdout ); - fclose( stdout ); - stdout = fopen("/dev/null", "w" ); - if( stdout == NULL ) - { - /* Redirection has failed with no stdout so exit */ - exit(1); + exit( 1 ); } } #endif /* __unix__ || __APPLE__ __MACH__ */ @@ -434,18 +418,10 @@ int main(int argc, const char *argv[]) ret = dispatch_test( cnt, params ); #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - if( !option_verbose ) + if( !option_verbose && restore_output( &stdout, stdout_fd ) ) { - /* Restore stdout */ - fflush( stdout ); - fclose( stdout ); - - stdout = fdopen ( tests_stdout, "w"); - if( stdout == NULL ) - { /* Redirection has failed with no stdout so exit */ - exit(1); - } + exit( 1 ); } #endif /* __unix__ || __APPLE__ __MACH__ */ From 851ae29a5d5b409cac0357da6e0a2b8c22e32887 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Tue, 11 Oct 2016 10:13:52 +0100 Subject: [PATCH 72/83] Revise Changelog to clarify and add credit --- ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index defebd031..f8890dc70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,11 +31,11 @@ Bugfix a contribution from Tobias Tangemann. #541 * Fixed cert_app sample program for debug output and for use when no root certificates are provided. + * 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. - * Fixed pthread implementation to avoid unintended double initialisations - and double frees. (found by Niklas Amnebratt) Changes * Extended test coverage of special cases, and added new timing test suite. From e3d882ad4ab271bbfe9183371637f76591c1fea6 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 11 Oct 2016 10:49:26 +0100 Subject: [PATCH 73/83] Remove unnecessary flag from CMAC context --- include/mbedtls/cmac.h | 4 ---- library/cmac.c | 12 +----------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h index f64ae69b4..75e0b97c4 100644 --- a/include/mbedtls/cmac.h +++ b/include/mbedtls/cmac.h @@ -44,7 +44,6 @@ extern "C" { */ struct mbedtls_cmac_context_t { - /** Internal state of the CMAC algorithm */ unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; @@ -54,9 +53,6 @@ struct mbedtls_cmac_context_t /** Length of data pending to be processed */ size_t unprocessed_len; - - /** Flag to indicate if the last block needs padding */ - int padding_flag; }; /** diff --git a/library/cmac.c b/library/cmac.c index 8ea0685b7..62f2a6abb 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -235,7 +235,6 @@ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, ctx->cmac_ctx = cmac_ctx; mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); - cmac_ctx->padding_flag = 1; return 0; } @@ -292,8 +291,6 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, ilen -= block_size; input += block_size; - - cmac_ctx->padding_flag = 0; } /* If there is data left over that wasn't aligned to a block */ @@ -303,11 +300,6 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, input, ilen ); cmac_ctx->unprocessed_len += ilen; - - if( ilen % block_size > 0 ) - cmac_ctx->padding_flag = 1; - else - cmac_ctx->padding_flag = 0; } exit: @@ -340,7 +332,7 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, last_block = cmac_ctx->unprocessed_block; /* Calculate last block */ - if( cmac_ctx->padding_flag && cmac_ctx->unprocessed_len < block_size ) + 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 ); @@ -367,7 +359,6 @@ exit: mbedtls_zeroize( K1, sizeof( K1 ) ); mbedtls_zeroize( K2, sizeof( K2 ) ); - cmac_ctx->padding_flag = 1; cmac_ctx->unprocessed_len = 0; mbedtls_zeroize( cmac_ctx->unprocessed_block, sizeof( cmac_ctx->unprocessed_block ) ); @@ -391,7 +382,6 @@ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) sizeof( cmac_ctx->unprocessed_block ) ); mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); - cmac_ctx->padding_flag = 1; return( 0 ); } From 7770ea82d5772612f6ae9afc2a1b931079bd4eb0 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Mon, 10 Oct 2016 15:46:20 +0100 Subject: [PATCH 74/83] Add seed cmdline arg to test scripts --- tests/scripts/all.sh | 19 +++++++++++++++++++ tests/ssl-opt.sh | 6 +++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index ee0df0cc4..6b3396059 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -32,6 +32,7 @@ CONFIG_BAK="$CONFIG_H.bak" MEMORY=0 FORCE=0 +RELEASE=0 # Default commands, can be overriden by the environment : ${OPENSSL:="openssl"} @@ -48,6 +49,8 @@ usage() 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=\t\tDirectory used for CMake out-of-source build tests." printf " --openssl=\t\tPath to OpenSSL executable to use for most tests.\n" printf " --openssl-legacy=\t\tPath to OpenSSL executable to use for legacy tests e.g. SSLv3.\n" @@ -106,6 +109,13 @@ while [ $# -gt 0 ]; do --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 @@ else 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 OPENSSL_CMD="$OPENSSL" 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 d9c45cd7a..429d9cd19 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -58,6 +58,7 @@ print_usage() { 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 @@ get_options() { -p|--preserve-logs) PRESERVE_LOGS=1 ;; + --seed) + shift; SEED="$1" + ;; -h|--help) print_usage exit 0 @@ -595,7 +599,7 @@ unset PORT_BASE # +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" From 1aae658d76d7cc98e698777b2bbe4a075dfe38ec Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 26 Sep 2016 09:15:44 +0100 Subject: [PATCH 75/83] Add safety check to sample mutex implementation Due to inconsistent freeing strategy in pkparse.c the sample mutex implementation in threading.c could lead to undefined behaviour by destroying the same mutex several times. This fix prevents mutexes from being destroyed several times in the sample threading implementation. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index f8890dc70..e6a4dbc76 100644 --- a/ChangeLog +++ b/ChangeLog @@ -36,6 +36,8 @@ Bugfix * Fixed the sample applications gen_key.c, cert_req.c and cert_write.c for builds where the configuration MBEDTLS_PEM_WRITE_C is not defined. Found by inestlerode. #559. + * Fixed default threading implementation to avoid accidental double + initialisations and double frees. Changes * Extended test coverage of special cases, and added new timing test suite. From 8abc6b86f98cdfa6bf6788e512a73b1806a442c0 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Tue, 11 Oct 2016 15:41:40 +0100 Subject: [PATCH 76/83] Fix memory leak in test_suite_cmac.function --- tests/suites/test_suite_cmac.function | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_cmac.function b/tests/suites/test_suite_cmac.function index 1f88ddcfe..0cb437b67 100644 --- a/tests/suites/test_suite_cmac.function +++ b/tests/suites/test_suite_cmac.function @@ -93,6 +93,9 @@ void mbedtls_cmac_null_args( ) NULL ) == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +exit: + mbedtls_cipher_free( &ctx ); } /* END_CASE */ @@ -144,6 +147,8 @@ void mbedtls_cmac_multiple_blocks( int cipher_type, 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 ); @@ -154,8 +159,6 @@ void mbedtls_cmac_multiple_blocks( int cipher_type, TEST_ASSERT( ( cipher_info = mbedtls_cipher_info_from_type( cipher_type ) ) != NULL ); - mbedtls_cipher_init( &ctx ); - TEST_ASSERT( mbedtls_cipher_setup( &ctx, cipher_info ) == 0 ); TEST_ASSERT( mbedtls_cipher_cmac_starts( &ctx, @@ -231,6 +234,8 @@ void mbedtls_cmac_multiple_operations_same_key( int cipher_type, 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 ); @@ -244,8 +249,6 @@ void mbedtls_cmac_multiple_operations_same_key( int cipher_type, TEST_ASSERT( ( cipher_info = mbedtls_cipher_info_from_type( cipher_type ) ) != NULL ); - mbedtls_cipher_init( &ctx ); - TEST_ASSERT( mbedtls_cipher_setup( &ctx, cipher_info ) == 0 ); TEST_ASSERT( mbedtls_cipher_cmac_starts( &ctx, From d4443582479d3ffcf16b3e376db73de9f3f7e25f Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 12 Oct 2016 10:00:42 +0100 Subject: [PATCH 77/83] Fix memory leaks in CMAC tests --- library/cmac.c | 21 ++++++++++++++------- tests/suites/test_suite_cmac.function | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/library/cmac.c b/library/cmac.c index 62f2a6abb..ee2fe056c 100644 --- a/library/cmac.c +++ b/library/cmac.c @@ -737,19 +737,19 @@ static int cmac_test_subkeys( int verbose, return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } - mbedtls_cipher_init( &ctx ); - for( i = 0; i < num_tests; i++ ) { if( verbose != 0 ) mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); + mbedtls_cipher_init( &ctx ); + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "test execution failed\n" ); - goto exit; + goto cleanup; } if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, @@ -758,7 +758,7 @@ static int cmac_test_subkeys( int verbose, if( verbose != 0 ) mbedtls_printf( "test execution failed\n" ); - goto exit; + goto cleanup; } ret = cmac_generate_subkeys( &ctx, K1, K2 ); @@ -766,7 +766,8 @@ static int cmac_test_subkeys( int verbose, { if( verbose != 0 ) mbedtls_printf( "failed\n" ); - goto exit; + + goto cleanup; } if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || @@ -774,16 +775,22 @@ static int cmac_test_subkeys( int verbose, { if( verbose != 0 ) mbedtls_printf( "failed\n" ); - goto exit; + + goto cleanup; } if( verbose != 0 ) mbedtls_printf( "passed\n" ); + + mbedtls_cipher_free( &ctx ); } -exit: + goto exit; + +cleanup: mbedtls_cipher_free( &ctx ); +exit: return( ret ); } diff --git a/tests/suites/test_suite_cmac.function b/tests/suites/test_suite_cmac.function index 0cb437b67..4b31ab2ff 100644 --- a/tests/suites/test_suite_cmac.function +++ b/tests/suites/test_suite_cmac.function @@ -93,7 +93,6 @@ void mbedtls_cmac_null_args( ) NULL ) == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - exit: mbedtls_cipher_free( &ctx ); } @@ -114,6 +113,7 @@ void mbedtls_cmac_setkey( int cipher_type, int key_size, 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 ); } From cd153278eb616e2c877d320a3a6bdd0658399676 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Tue, 4 Oct 2016 12:06:50 +0100 Subject: [PATCH 78/83] Fix typo in docs for mbedtls_x509write_csr_der() --- include/mbedtls/x509_csr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/x509_csr.h b/include/mbedtls/x509_csr.h index 7a9c2e055..fe9843cb5 100644 --- a/include/mbedtls/x509_csr.h +++ b/include/mbedtls/x509_csr.h @@ -282,7 +282,7 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s * * \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, From 776a6fcd1a55818f70a843e249649a390545f48f Mon Sep 17 00:00:00 2001 From: Andres AG Date: Mon, 26 Sep 2016 09:52:41 +0100 Subject: [PATCH 79/83] Fix 1 byte overread in mbedtls_asn1_get_int() --- ChangeLog | 4 ++-- library/asn1parse.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e6a4dbc76..8d76eb93c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,13 +31,13 @@ Bugfix 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. * 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. - * Fixed default threading implementation to avoid accidental double - initialisations and double frees. Changes * Extended test coverage of special cases, and added new timing test suite. diff --git a/library/asn1parse.c b/library/asn1parse.c index ffa2f5299..4dd65c03c 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -153,7 +153,7 @@ int mbedtls_asn1_get_int( unsigned char **p, 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; From 3a5e0709828a6550bfe16261b9ff946bbfacc3d0 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 12 Oct 2016 16:37:59 +0100 Subject: [PATCH 80/83] Updated Changelog for fix #599 --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8d76eb93c..c77c58fe6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -32,7 +32,7 @@ Bugfix * 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. + 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 From 821da84ff9894060e615e51c50306c361c3411b8 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Mon, 26 Sep 2016 10:09:30 +0100 Subject: [PATCH 81/83] Fix documentation for mbedtls_gcm_finish() Fix implementation and documentation missmatch for the function arguments to mbedtls_gcm_finish(). Also, removed redundant if condition that always evaluates to true. --- ChangeLog | 2 ++ include/mbedtls/gcm.h | 4 ++-- library/gcm.c | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index c77c58fe6..fc08e896c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -38,6 +38,8 @@ Bugfix * 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 documentation and implementation missmatch for function arguments of + mbedtls_gcm_finish(). Found by cmiatpaar. Changes * Extended test coverage of special cases, and added new timing test suite. diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h index 6743ac9a5..1b77aaedd 100644 --- a/include/mbedtls/gcm.h +++ b/include/mbedtls/gcm.h @@ -190,8 +190,8 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx, * 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/library/gcm.c b/library/gcm.c index aaacf97d6..f1210c52c 100644 --- a/library/gcm.c +++ b/library/gcm.c @@ -415,8 +415,7 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, 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 ) { From f6e3b9e8b21110e61c06837ed582ab4211289199 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 12 Oct 2016 19:47:29 +0100 Subject: [PATCH 82/83] Clarified Changelog for fix #602 --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fc08e896c..2e89c6afe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -39,7 +39,7 @@ Bugfix builds where the configuration MBEDTLS_PEM_WRITE_C is not defined. Found by inestlerode. #559. * Fix documentation and implementation missmatch for function arguments of - mbedtls_gcm_finish(). Found by cmiatpaar. + mbedtls_gcm_finish(). Found by cmiatpaar. #602 Changes * Extended test coverage of special cases, and added new timing test suite. From edf2a3fba79d24e33a00e33c4d959c66e824e2d0 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Wed, 12 Oct 2016 23:07:30 +0100 Subject: [PATCH 83/83] Fix stdio redirection memory leak in test suites --- tests/suites/helpers.function | 5 +++++ tests/suites/main_test.function | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index 5938447af..ff3ab99e4 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -140,6 +140,11 @@ static int restore_output( FILE** out_stream, int old_fd ) return 0; } + +static void close_output( FILE* stdout ) +{ + fclose( stdout ); +} #endif /* __unix__ || __APPLE__ __MACH__ */ static int unhexify( unsigned char *obuf, const char *ibuf ) diff --git a/tests/suites/main_test.function b/tests/suites/main_test.function index 14209a576..afff5a482 100644 --- a/tests/suites/main_test.function +++ b/tests/suites/main_test.function @@ -261,7 +261,7 @@ int main(int argc, const char *argv[]) char buf[5000]; char *params[50]; void *pointer; - int stdout_fd = 0; + int stdout_fd = -1; #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC) @@ -499,6 +499,11 @@ int main(int argc, const char *argv[]) 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 ); }