Commit 5cbb60bf authored by Manuel Pégourié-Gonnard's avatar Manuel Pégourié-Gonnard
Browse files

Merge branch 'md_hmac' into development

* md_hmac: (21 commits)
  Add more tests for MD utility functions
  Rework documentation of MD layer
  Check return value of the TLS PRF
  Make tls1_prf and tls12_prf more efficient
  Factor tls_prf_sha{256,384} together
  Reintroduce md_init_ctx compatibility wrapper
  Rename md_init_ctx() to md_setup()
  Update doxygen documentation on HMAC
  Clean up unneeded things
  Make hmac_ctx optional
  Make ipad/opad dynamic and more opaque
  Remove ipad and opad from specific md contexts
  Remove specific xxx_hmac functions
  Remove use of xxx_hmac() in program
  Remove calls to xxx_hmac() from SSL modules
  Remove references to xxx_hmac() from MD layer
  Remove tests for xxx_hmac()
  Implement hmac in the MD layer
  Add generic HMAC tests from mdx.data
  Fix tests and programs to use md_get_xxx()
  ...
parents 9325b26b 19d644b7
......@@ -6,6 +6,11 @@ Features
* Support for DTLS 1.0 and 1.2 (RFC 6347).
API Changes
* md_init_ctx() is deprecated in favour of md_setup(), that adds a third
argument (allowing memory savings if HMAC is not used)
* Removed individual mdX_hmac and shaX_hmac functions (use generic
md_hmac functions from md.h)
* Change md_info_t into an opaque structure (use md_get_xxx() accessors).
* Some constness fixes
* Signature of mpi_mul_mpi() changed to make the last argument unsigned
* Remove the PBKDF2 module (use PKCS5).
......
......@@ -12,13 +12,12 @@
* for authentication, which is a message integrity control.
*
* All hash algorithms can be accessed via the generic MD layer (see
* \c md_init_ctx())
* \c md_setup())
*
* The following hashing-algorithms are provided:
* - MD2, MD4, MD5 128-bit one-way hash functions by Ron Rivest (see
* \c md2_hmac(), \c md4_hmac() and \c md5_hmac()).
* - MD2, MD4, MD5 128-bit one-way hash functions by Ron Rivest.
* - SHA-1, SHA-256, SHA-384/512 160-bit or more one-way hash functions by
* NIST and NSA (see\c sha1_hmac(), \c sha256_hmac() and \c sha512_hmac()).
* NIST and NSA.
*
* This module provides one-way hashing which can be used for authentication.
*/
......@@ -5,7 +5,7 @@
*
* \author Adriaan de Jong <dejong@fox-it.com>
*
* Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
*
* This file is part of mbed TLS (https://tls.mbed.org)
*
......@@ -65,63 +65,9 @@ typedef enum {
#endif
/**
* Message digest information. Allows message digest functions to be called
* in a generic way.
* Opaque struct defined in md_wrap.h
*/
typedef struct {
/** Digest identifier */
md_type_t type;
/** Name of the message digest */
const char * name;
/** Output length of the digest function */
int size;
/** Digest initialisation function */
void (*starts_func)( void *ctx );
/** Digest update function */
void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
/** Digest finalisation function */
void (*finish_func)( void *ctx, unsigned char *output );
/** Generic digest function */
void (*digest_func)( const unsigned char *input, size_t ilen,
unsigned char *output );
/** Generic file digest function */
int (*file_func)( const char *path, unsigned char *output );
/** HMAC Initialisation function */
void (*hmac_starts_func)( void *ctx, const unsigned char *key,
size_t keylen );
/** HMAC update function */
void (*hmac_update_func)( void *ctx, const unsigned char *input,
size_t ilen );
/** HMAC finalisation function */
void (*hmac_finish_func)( void *ctx, unsigned char *output);
/** HMAC context reset function */
void (*hmac_reset_func)( void *ctx );
/** Generic HMAC function */
void (*hmac_func)( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char *output );
/** Allocate a new context */
void * (*ctx_alloc_func)( void );
/** Free the given context */
void (*ctx_free_func)( void *ctx );
/** Internal use only */
void (*process_func)( void *ctx, const unsigned char *input );
} md_info_t;
typedef struct _md_info_t md_info_t;
/**
* Generic message digest context.
......@@ -132,12 +78,10 @@ typedef struct {
/** Digest-specific context */
void *md_ctx;
} md_context_t;
#define MD_CONTEXT_T_INIT { \
NULL, /* md_info */ \
NULL, /* md_ctx */ \
}
/** HMAC part of the context */
void *hmac_ctx;
} md_context_t;
/**
* \brief Returns the list of digests supported by the generic digest module.
......@@ -170,35 +114,58 @@ const md_info_t *md_info_from_string( const char *md_name );
const md_info_t *md_info_from_type( md_type_t md_type );
/**
* \brief Initialize a md_context (as NONE)
* \brief Initialize a md_context (as NONE)
* This should always be called first.
* Prepares the context for md_setup() or md_free().
*/
void md_init( md_context_t *ctx );
/**
* \brief Free and clear the message-specific context of ctx.
* Freeing ctx itself remains the responsibility of the
* caller.
* \brief Free and clear the internal structures of ctx.
* Can be called at any time after md_init().
* Mandatory once md_setup() has been called.
*/
void md_free( md_context_t *ctx );
#if ! defined(POLARSSL_DEPRECATED_REMOVED)
#if defined(POLARSSL_DEPRECATED_WARNING)
#define DEPRECATED __attribute__((deprecated))
#else
#define DEPRECATED
#endif
/**
* \brief Initialises and fills the message digest context structure
* with the appropriate values.
* \brief Select MD to use and allocate internal structures.
* Should be called after md_init() or md_free().
* Makes it necessary to call md_free() later.
*
* \note Currently also clears structure. In future versions you
* will be required to call md_init() on the structure
* first.
* \deprecated Superseded by md_setup() in 2.0.0
*
* \param ctx context to initialise. May not be NULL. The
* digest-specific context (ctx->md_ctx) must be NULL. It will
* be allocated, and must be freed using md_free_ctx() later.
* \param md_info message digest to use.
* \param ctx Context to set up.
* \param md_info Message digest to use.
*
* \returns \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on
* parameter failure, \c POLARSSL_ERR_MD_ALLOC_FAILED if
* allocation of the digest-specific context failed.
* \returns \c 0 on success,
* \c POLARSSL_ERR_MD_BAD_INPUT_DATA on parameter failure,
* \c POLARSSL_ERR_MD_ALLOC_FAILED memory allocation failure.
*/
int md_init_ctx( md_context_t *ctx, const md_info_t *md_info ) DEPRECATED;
#undef DEPRECATED
#endif /* POLARSSL_DEPRECATED_REMOVED */
/**
* \brief Select MD to use and allocate internal structures.
* Should be called after md_init() or md_free().
* Makes it necessary to call md_free() later.
*
* \param ctx Context to set up.
* \param md_info Message digest to use.
* \param hmac 0 to save some meory is HMAC will not be use,
* non-zero is HMAC is going to be used with this context.
*
* \returns \c 0 on success,
* \c POLARSSL_ERR_MD_BAD_INPUT_DATA on parameter failure,
* \c POLARSSL_ERR_MD_ALLOC_FAILED memory allocation failure.
*/
int md_init_ctx( md_context_t *ctx, const md_info_t *md_info );
int md_setup( md_context_t *ctx, const md_info_t *md_info, int hmac );
/**
* \brief Returns the size of the message digest output.
......@@ -207,13 +174,7 @@ int md_init_ctx( md_context_t *ctx, const md_info_t *md_info );
*
* \return size of the message digest output.
*/
static inline unsigned char md_get_size( const md_info_t *md_info )
{
if( md_info == NULL )
return( 0 );
return md_info->size;
}
unsigned char md_get_size( const md_info_t *md_info );
/**
* \brief Returns the type of the message digest output.
......@@ -222,13 +183,7 @@ static inline unsigned char md_get_size( const md_info_t *md_info )
*
* \return type of the message digest output.
*/
static inline md_type_t md_get_type( const md_info_t *md_info )
{
if( md_info == NULL )
return( POLARSSL_MD_NONE );
return md_info->type;
}
md_type_t md_get_type( const md_info_t *md_info );
/**
* \brief Returns the name of the message digest output.
......@@ -237,44 +192,44 @@ static inline md_type_t md_get_type( const md_info_t *md_info )
*
* \return name of the message digest output.
*/
static inline const char *md_get_name( const md_info_t *md_info )
{
if( md_info == NULL )
return( NULL );
return md_info->name;
}
const char *md_get_name( const md_info_t *md_info );
/**
* \brief Set-up the given context for a new message digest
* \brief Prepare the context to digest a new message.
* Generally called after md_setup() or md_finish().
* Followed by md_update().
*
* \param ctx generic message digest context.
* \param ctx generic message digest context.
*
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
*/
int md_starts( md_context_t *ctx );
/**
* \brief Generic message digest process buffer
* \brief Generic message digest process buffer
* Called between md_starts() and md_finish().
* May be called repeatedly.
*
* \param ctx Generic message digest context
* \param input buffer holding the datal
* \param ilen length of the input data
* \param ctx Generic message digest context
* \param input buffer holding the datal
* \param ilen length of the input data
*
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
*/
int md_update( md_context_t *ctx, const unsigned char *input, size_t ilen );
/**
* \brief Generic message digest final digest
* \brief Generic message digest final digest
* Called after md_update().
* Usually followed by md_free() or md_starts().
*
* \param ctx Generic message digest context
* \param output Generic message digest checksum result
* \param ctx Generic message digest context
* \param output Generic message digest checksum result
*
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
*/
int md_finish( md_context_t *ctx, unsigned char *output );
......@@ -307,49 +262,57 @@ int md_file( const md_info_t *md_info, const char *path,
unsigned char *output );
/**
* \brief Generic HMAC context setup
* \brief Set HMAC key and prepare to authenticate a new message.
* Usually called after md_setup() or md_hmac_finish().
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param ctx HMAC context
* \param key HMAC secret key
* \param keylen length of the HMAC key
*
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
*/
int md_hmac_starts( md_context_t *ctx, const unsigned char *key,
size_t keylen );
/**
* \brief Generic HMAC process buffer
* \brief Generic HMAC process buffer.
* Called between md_hmac_starts() or md_hmac_reset()
* and md_hmac_finish().
* May be called repeatedly.
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
*/
int md_hmac_update( md_context_t *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief Generic HMAC final digest
* \brief Output HMAC.
* Called after md_hmac_update().
* Usually followed my md_hmac_reset(), md_hmac_starts(),
* or md_free().
*
* \param ctx HMAC context
* \param output Generic HMAC checksum result
* \param ctx HMAC context
* \param output Generic HMAC checksum result
*
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
*/
int md_hmac_finish( md_context_t *ctx, unsigned char *output);
/**
* \brief Generic HMAC context reset
* \brief Prepare to authenticate a new message with the same key.
* Called after md_hmac_finish() and before md_hmac_update().
*
* \param ctx HMAC context to be reset
* \param ctx HMAC context to be reset
*
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
* \returns 0 on success, POLARSSL_ERR_MD_BAD_INPUT_DATA if parameter
* verification fails.
*/
int md_hmac_reset( md_context_t *ctx );
......
......@@ -50,9 +50,6 @@ typedef struct
unsigned char cksum[16]; /*!< checksum of the data block */
unsigned char state[48]; /*!< intermediate digest state */
unsigned char buffer[16]; /*!< data block being processed */
unsigned char ipad[16]; /*!< HMAC: inner padding */
unsigned char opad[16]; /*!< HMAC: outer padding */
size_t left; /*!< amount of data in buffer */
}
md2_context;
......@@ -126,54 +123,6 @@ void md2( const unsigned char *input, size_t ilen, unsigned char output[16] );
*/
int md2_file( const char *path, unsigned char output[16] );
/**
* \brief MD2 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void md2_hmac_starts( md2_context *ctx, const unsigned char *key,
size_t keylen );
/**
* \brief MD2 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md2_hmac_update( md2_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief MD2 HMAC final digest
*
* \param ctx HMAC context
* \param output MD2 HMAC checksum result
*/
void md2_hmac_finish( md2_context *ctx, unsigned char output[16] );
/**
* \brief MD2 HMAC context reset
*
* \param ctx HMAC context to be reset
*/
void md2_hmac_reset( md2_context *ctx );
/**
* \brief Output = HMAC-MD2( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-MD2 result
*/
void md2_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[16] );
/**
* \brief Checkup routine
*
......
......@@ -57,9 +57,6 @@ typedef struct
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
md4_context;
......@@ -132,54 +129,6 @@ void md4( const unsigned char *input, size_t ilen, unsigned char output[16] );
*/
int md4_file( const char *path, unsigned char output[16] );
/**
* \brief MD4 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void md4_hmac_starts( md4_context *ctx, const unsigned char *key,
size_t keylen );
/**
* \brief MD4 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md4_hmac_update( md4_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief MD4 HMAC final digest
*
* \param ctx HMAC context
* \param output MD4 HMAC checksum result
*/
void md4_hmac_finish( md4_context *ctx, unsigned char output[16] );
/**
* \brief MD4 HMAC context reset
*
* \param ctx HMAC context to be reset
*/
void md4_hmac_reset( md4_context *ctx );
/**
* \brief Output = HMAC-MD4( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-MD4 result
*/
void md4_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[16] );
/**
* \brief Checkup routine
*
......
......@@ -57,9 +57,6 @@ typedef struct
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
md5_context;
......@@ -135,54 +132,6 @@ void md5( const unsigned char *input, size_t ilen, unsigned char output[16] );
*/
int md5_file( const char *path, unsigned char output[16] );
/**
* \brief MD5 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void md5_hmac_starts( md5_context *ctx,
const unsigned char *key, size_t keylen );
/**
* \brief MD5 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md5_hmac_update( md5_context *ctx,
const unsigned char *input, size_t ilen );
/**
* \brief MD5 HMAC final digest
*
* \param ctx HMAC context
* \param output MD5 HMAC checksum result
*/
void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
/**
* \brief MD5 HMAC context reset
*
* \param ctx HMAC context to be reset
*/
void md5_hmac_reset( md5_context *ctx );
/**
* \brief Output = HMAC-MD5( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-MD5 result
*/
void md5_hmac( const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char output[16] );
/**
* \brief Checkup routine
*
......
......@@ -3,9 +3,11 @@
*
* \brief Message digest wrappers.
*
* \warning This in an internal header. Do not include directly.
*
* \author Adriaan de Jong <dejong@fox-it.com>
*
* Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
*
* This file is part of mbed TLS (https://tls.mbed.org)
*
......@@ -38,6 +40,49 @@
extern "C" {
#endif
/**
* Message digest information.
* Allows message digest functions to be called in a generic way.
*/
struct _md_info_t {
/** Digest identifier */
md_type_t type;
/** Name of the message digest */
const char * name;
/** Output length of the digest function */
int size;
/** Block length of the digest function */
int block_size;
/** Digest initialisation function */
void (*starts_func)( void *ctx );
/** Digest update function */
void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
/** Digest finalisation function */
void (*finish_func)( void *ctx, unsigned char *output );
/** Generic digest function */
void (*digest_func)( const unsigned char *input, size_t ilen,
unsigned char *output );
/** Generic file digest function */
int (*file_func)( const char *path, unsigned char *output );
/** Allocate a new context */
void * (*ctx_alloc_func)( void );
/** Free the given context */
void (*ctx_free_func)( void *ctx );