From 490bdf392823de3b673481f32fccb18cfaf12630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 27 Jan 2014 14:03:10 +0100 Subject: [PATCH] Add minimalistic HMAC_DRBG implementation (copied from ECDSA) --- include/polarssl/config.h | 18 ++++ include/polarssl/hmac_drbg.h | 112 +++++++++++++++++++++++++ library/CMakeLists.txt | 1 + library/Makefile | 1 + library/hmac_drbg.c | 143 ++++++++++++++++++++++++++++++++ visualc/VS2010/PolarSSL.vcxproj | 2 + visualc/VS6/polarssl.dsp | 8 ++ 7 files changed, 285 insertions(+) create mode 100644 include/polarssl/hmac_drbg.h create mode 100644 library/hmac_drbg.c diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 83f9dac580..a124720b74 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -1311,6 +1311,20 @@ */ //#define POLARSSL_HAVEGE_C +/** + * \def POLARSSL_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: POLARSSL_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define POLARSSL_HMAC_DRBG_C + /** * \def POLARSSL_MD_C * @@ -2000,6 +2014,10 @@ #error "POLARSSL_HAVEGE_C defined, but not all prerequisites" #endif +#if defined(POLARSSL_HMAC_DRBG) && !defined(POLARSSL_MD_C) +#error "POLARSSL_HMAC_DRBG_C defined, but not all prerequisites" +#endif + #if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ) #error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" diff --git a/include/polarssl/hmac_drbg.h b/include/polarssl/hmac_drbg.h new file mode 100644 index 0000000000..f86c13665b --- /dev/null +++ b/include/polarssl/hmac_drbg.h @@ -0,0 +1,112 @@ +/** + * \file hmac_drbg.h + * + * \brief HMAC_DRBG (NIST SP 800-90A) + * + * Copyright (C) 2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef POLARSSL_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_H + +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Simplified HMAC_DRBG context. + * No reseed counter, no prediction resistance flag. + */ +typedef struct +{ + md_context_t md_ctx; + unsigned char V[POLARSSL_MD_MAX_SIZE]; + unsigned char K[POLARSSL_MD_MAX_SIZE]; +} hmac_drbg_context; + +/** + * \brief HMAC_DRBG initialisation + * + * \param ctx HMAC_DRBG context to be initialised + * \param md_info MD algorithm to use for HMAC_DRBG + * \param data Concatenation of entropy string and additional data + * \param data_len Length of data in bytes + * + * \todo Use entropy callback rather than buffer. + * + * \return 0 if successful, or + * POLARSSL_ERR_MD_BAD_INPUT_DATA, or + * POLARSSL_ERR_MD_ALLOC_FAILED + */ +int hmac_drbg_init( hmac_drbg_context *ctx, + const md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief HMAC_DRBG update state + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +void hmac_drbg_update( hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached. (TODO) + * + * \param p_rng HMAC_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * + * \return 0 if successful. + */ +int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx HMAC_DRBG context to free. + */ +void hmac_drbg_free( hmac_drbg_context *ctx ); + + +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index dd6bbd3f1f..77aac2042e 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -26,6 +26,7 @@ set(src error.c gcm.c havege.c + hmac_drbg.c md.c md_wrap.c md2.c diff --git a/library/Makefile b/library/Makefile index a4126f0e1c..311e31637f 100644 --- a/library/Makefile +++ b/library/Makefile @@ -44,6 +44,7 @@ OBJS= aes.o aesni.o arc4.o \ ecp.o ecp_curves.o \ entropy.o entropy_poll.o \ error.o gcm.o havege.o \ + hmac_drbg.o \ md.o md_wrap.o md2.o \ md4.o md5.o memory.o \ memory_buffer_alloc.o net.o \ diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c new file mode 100644 index 0000000000..6aa1ba565b --- /dev/null +++ b/library/hmac_drbg.c @@ -0,0 +1,143 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright (C) 2014, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * The NIST SP 800-90 DRBGs are described in the following publication. + * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + */ + +#include "polarssl/config.h" + +#if defined(POLARSSL_HMAC_DRBG_C) + +#include "polarssl/hmac_drbg.h" + +/* + * HMAC_DRBG update, using optional additional data + */ +void hmac_drbg_update( hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + size_t md_len = ctx->md_ctx.md_info->size; + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + md_hmac_starts( &ctx->md_ctx, ctx->K, md_len ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_update( &ctx->md_ctx, sep, 1 ); + if( rounds == 2 ) + md_hmac_update( &ctx->md_ctx, additional, add_len ); + md_hmac_finish( &ctx->md_ctx, ctx->K ); + + md_hmac_starts( &ctx->md_ctx, ctx->K, md_len ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_finish( &ctx->md_ctx, ctx->V ); + } +} + +/* + * Simplified HMAC_DRBG initialisation. + */ +int hmac_drbg_init( hmac_drbg_context *ctx, + const md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret; + + memset( ctx, 0, sizeof( hmac_drbg_context ) ); + + if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 ) + return( ret ); + + memset( ctx->V, 0x01, md_info->size ); + /* ctx->K is already 0 */ + + hmac_drbg_update( ctx, data, data_len ); + + return( 0 ); +} + +/* + * Simplified HMAC_DRBG random function + */ +int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng; + size_t md_len = ctx->md_ctx.md_info->size; + size_t left = out_len; + unsigned char *out = output; + + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + md_hmac_starts( &ctx->md_ctx, ctx->K, md_len ); + md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); + md_hmac_finish( &ctx->md_ctx, ctx->V ); + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + hmac_drbg_update( ctx, NULL, 0 ); + + return( 0 ); +} + +/* + * Free an HMAC_DRBG context + */ +void hmac_drbg_free( hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + + md_free_ctx( &ctx->md_ctx ); + + memset( ctx, 0, sizeof( hmac_drbg_context ) ); +} + + +#if defined(POLARSSL_SELF_TEST) + +#include + +/* + * Checkup routine + */ +int hmac_drbg_self_test( int verbose ) +{ + + if( verbose != 0 ) + printf( "\n" ); + + return( 0 ); +} +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_HMAC_DRBG_C */ diff --git a/visualc/VS2010/PolarSSL.vcxproj b/visualc/VS2010/PolarSSL.vcxproj index 127d106a6f..84beb62de9 100644 --- a/visualc/VS2010/PolarSSL.vcxproj +++ b/visualc/VS2010/PolarSSL.vcxproj @@ -168,6 +168,7 @@ + @@ -227,6 +228,7 @@ + diff --git a/visualc/VS6/polarssl.dsp b/visualc/VS6/polarssl.dsp index 645b29c68f..f763caaeb6 100644 --- a/visualc/VS6/polarssl.dsp +++ b/visualc/VS6/polarssl.dsp @@ -185,6 +185,10 @@ SOURCE=..\..\library\havege.c # End Source File # Begin Source File +SOURCE=..\..\library\hmac_drbg.c +# End Source File +# Begin Source File + SOURCE=..\..\library\md2.c # End Source File # Begin Source File @@ -457,6 +461,10 @@ SOURCE=..\..\include\polarssl\havege.h # End Source File # Begin Source File +SOURCE=..\..\include\polarssl\hmac_drbg.h +# End Source File +# Begin Source File + SOURCE=..\..\include\polarssl\md2.h # End Source File # Begin Source File