Commit 5fb8efe7 authored by Paul Bakker's avatar Paul Bakker
Browse files

Merged HMAC-DRBG code

parents ffd94cce 725afd8b
PolarSSL ChangeLog (Sorted per branch, date)
= PolarSSL 1.3 branch
Features
* HMAC-DRBG as a separate module
Bugfix
* ecp_gen_keypair() does more tries to prevent failure because of
statistics
......
......@@ -290,7 +290,7 @@
* may result in a compromise of the long-term signing key. This is avoided by
* the deterministic variant.
*
* Requires: POLARSSL_MD_C
* Requires: POLARSSL_HMAC_DRBG_C
*
* Comment this macro to disable deterministic ECDSA.
*/
......@@ -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
*
......@@ -1902,6 +1916,13 @@
#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
// HMAC_DRBG options
//
#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
// ECP options
//
#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
......@@ -1962,7 +1983,7 @@
#error "POLARSSL_ECDSA_C defined, but not all prerequisites"
#endif
#if defined(POLARSSL_ECDSA_DETERMINISTIC) && !defined(POLARSSL_MD_C)
#if defined(POLARSSL_ECDSA_DETERMINISTIC) && !defined(POLARSSL_HMAC_DRBG_C)
#error "POLARSSL_ECDSA_DETERMINISTIC defined, but not all prerequisites"
#endif
......@@ -2004,6 +2025,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"
......
......@@ -41,15 +41,17 @@
*
* 16 bit error code bit-segmentation
*
* 1 bit - Intentionally not used
* 1 bit - Sign bit
* 3 bits - High level module ID
* 5 bits - Module-dependent error code
* 6 bits - Low level module errors
* 1 bit - Intentionally not used
* 7 bits - Low level module errors
*
* Low-level module errors (0x007E-0x0002)
* For historical reasons, low-level error codes are divided in even and odd,
* and even codes were assigned first.
*
* Module Nr Codes assigned
* Low-level module errors (0x0001-0x00FF)
*
* Module Nr Codes assigned
* MPI 7 0x0002-0x0010
* GCM 2 0x0012-0x0014
* BLOWFISH 2 0x0016-0x0018
......@@ -61,7 +63,7 @@
* OID 1 0x002E-0x002E
* PADLOCK 1 0x0030-0x0030
* DES 1 0x0032-0x0032
* CTR_DBRG 3 0x0034-0x003A
* CTR_DBRG 4 0x0034-0x003A
* ENTROPY 3 0x003C-0x0040
* NET 11 0x0042-0x0056
* ASN1 7 0x0060-0x006C
......@@ -72,6 +74,8 @@
* SHA256 1 0x0078-0x0078
* SHA512 1 0x007A-0x007A
* PBKDF2 1 0x007C-0x007C
* RIPEMD160 1 0x007E-0x007E
* HMAC_DRBG 4 0x0001-0x0007
*
* High-level module nr (3 bits - 0x1...-0x8...)
* Name ID Nr of Errors
......@@ -88,7 +92,7 @@
* SSL 6 8 (Started from top)
* SSL 7 31
*
* Module dependent error code (5 bits 0x.08.-0x.F8.)
* Module dependent error code (5 bits 0x.00.-0x.F8.)
*/
#ifdef __cplusplus
......
/**
* \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 <polarssl_maintainer at polarssl.org>
*
* 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"
/*
* ! Same values as ctr_drbg.h !
*/
#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0001 /**< The entropy source failed. */
#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */
#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */
#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */
#if !defined(POLARSSL_CONFIG_OPTIONS)
#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
#endif /* !POLARSSL_CONFIG_OPTIONS */
#define POLARSSL_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */
#define POLARSSL_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */
#ifdef __cplusplus
extern "C" {
#endif
/**
* HMAC_DRBG context.
*/
typedef struct
{
/* Working state: the key K is not stored explicitely,
* but is implied by the HMAC context */
md_context_t md_ctx; /*!< HMAC context (inc. K) */
unsigned char V[POLARSSL_MD_MAX_SIZE]; /*!< V in the spec */
int reseed_counter; /*!< reseed counter */
/* Administrative state */
size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */
int prediction_resistance; /*!< enable prediction resistance (Automatic
reseed before every random generation) */
int reseed_interval; /*!< reseed interval */
/* Callbacks */
int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */
void *p_entropy; /*!< context for the entropy function */
} 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 f_entropy Entropy callback (p_entropy, buffer to fill, buffer
* length)
* \param p_entropy Entropy context
* \param custom Personalization data (Device specific identifiers)
* (Can be NULL)
* \param len Length of personalization data
*
* \note The "security strength" as defined by NIST is set to:
* 128 bits if md_alg is SHA-1,
* 192 bits if md_alg is SHA-224,
* 256 bits if md_alg is SHA-256 or higher.
* Note that SHA-256 is just as efficient as SHA-224.
*
* \return 0 if successful, or
* POLARSSL_ERR_MD_BAD_INPUT_DATA, or
* POLARSSL_ERR_MD_ALLOC_FAILED, or
* POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED.
*/
int hmac_drbg_init( hmac_drbg_context *ctx,
const md_info_t * md_info,
int (*f_entropy)(void *, unsigned char *, size_t),
void *p_entropy,
const unsigned char *custom,
size_t len );
/**
* \brief Initilisation of simpified HMAC_DRBG (never reseeds).
* (For use with deterministic ECDSA.)
*
* \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
*
* \return 0 if successful, or
* POLARSSL_ERR_MD_BAD_INPUT_DATA, or
* POLARSSL_ERR_MD_ALLOC_FAILED.
*/
int hmac_drbg_init_buf( hmac_drbg_context *ctx,
const md_info_t * md_info,
const unsigned char *data, size_t data_len );
/**
* \brief Enable / disable prediction resistance (Default: Off)
*
* Note: If enabled, entropy is used for ctx->entropy_len before each call!
* Only use this if you have ample supply of good entropy!
*
* \param ctx HMAC_DRBG context
* \param resistance POLARSSL_HMAC_DRBG_PR_ON or POLARSSL_HMAC_DRBG_PR_OFF
*/
void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
int resistance );
/**
* \brief Set the amount of entropy grabbed on each reseed
* (Default: given by the security strength, which
* depends on the hash used, see \c hmac_drbg_init() )
*
* \param ctx HMAC_DRBG context
* \param len Amount of entropy to grab, in bytes
*/
void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx,
size_t len );
/**
* \brief Set the reseed interval
* (Default: POLARSSL_HMAC_DRBG_RESEED_INTERVAL)
*
* \param ctx HMAC_DRBG context
* \param interval Reseed interval
*/
void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx,
int interval );
/**
* \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 reseeding (extracts data from entropy source)
*
* \param ctx HMAC_DRBG context
* \param additional Additional data to add to state (Can be NULL)
* \param len Length of additional data
*
* \return 0 if successful, or
* POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
*/
int hmac_drbg_reseed( hmac_drbg_context *ctx,
const unsigned char *additional, size_t len );
/**
* \brief HMAC_DRBG generate random with additional update input
*
* Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
*
* \param p_rng HMAC_DRBG context
* \param output Buffer to fill
* \param output_len Length of the buffer
* \param additional Additional data to update with (can be NULL)
* \param add_len Length of additional data (can be 0)
*
* \return 0 if successful, or
* POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
* POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
* POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG.
*/
int hmac_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t output_len,
const unsigned char *additional,
size_t add_len );
/**
* \brief HMAC_DRBG generate random
*
* Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
*
* \param p_rng HMAC_DRBG context
* \param output Buffer to fill
* \param out_len Length of the buffer
*
* \return 0 if successful, or
* POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
* POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG
*/
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_FS_IO)
/**
* \brief Write a seed file
*
* \param ctx HMAC_DRBG context
* \param path Name of the file
*
* \return 0 if successful, 1 on file error, or
* POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
*/
int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path );
/**
* \brief Read and update a seed file. Seed is added to this
* instance
*
* \param ctx HMAC_DRBG context
* \param path Name of the file
*
* \return 0 if successful, 1 on file error,
* POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
* POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG
*/
int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path );
#endif
#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 */
......@@ -38,7 +38,7 @@ typedef UINT32 uint32_t;
#include <inttypes.h>
#endif
#define POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR -0x0074 /**< Read/write error in file. */
#define POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR -0x007E /**< Read/write error in file. */
#if !defined(POLARSSL_RIPEMD160_ALT)
// Regular implementation
......
......@@ -26,6 +26,7 @@ set(src
error.c
gcm.c
havege.c
hmac_drbg.c
md.c
md_wrap.c
md2.c
......
......@@ -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 \
......
......@@ -362,8 +362,8 @@ int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path )
if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
{
ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
goto exit;
ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; /* LCOV_EXCL_LINE */
goto exit; /* LCOV_EXCL_LINE */
}
ret = 0;
......@@ -394,8 +394,8 @@ int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
if( fread( buf, 1, n, f ) != n )
{
fclose( f );
return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
fclose( f ); /* LCOV_EXCL_LINE */
return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); /* LCOV_EXCL_LINE */
}
fclose( f );
......@@ -410,7 +410,7 @@ int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
#include <stdio.h>
unsigned char entropy_source_pr[96] =
static unsigned char entropy_source_pr[96] =
{ 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
......@@ -424,7 +424,7 @@ unsigned char entropy_source_pr[96] =
0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
unsigned char entropy_source_nopr[64] =
static unsigned char entropy_source_nopr[64] =
{ 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
......@@ -434,32 +434,39 @@ unsigned char entropy_source_nopr[64] =
0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
unsigned char nonce_pers_pr[16] =
static const unsigned char nonce_pers_pr[16] =
{ 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
unsigned char nonce_pers_nopr[16] =
static const unsigned char nonce_pers_nopr[16] =
{ 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
unsigned char result_pr[16] =
static const unsigned char result_pr[16] =
{ 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
unsigned char result_nopr[16] =
static const unsigned char result_nopr[16] =
{ 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
int test_offset;
static int test_offset;
static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
size_t len )
{
unsigned char *p = data;
const unsigned char *p = data;
memcpy( buf, p + test_offset, len );
test_offset += 32;
test_offset += len;
return( 0 );
}
#define CHK( c ) if( (c) != 0 ) \
{ \
if( verbose != 0 ) \
printf( "failed\n" ); \
return( 1 ); \
}
/*
* Checkup routine
*/
......@@ -475,39 +482,13 @@ int ctr_drbg_self_test( int verbose )
printf( " CTR_DRBG (PR = TRUE) : " );
test_offset = 0;
if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
entropy_source_pr, nonce_pers_pr, 16, 32 ) );
ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );
if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
......@@ -518,46 +499,13 @@ int ctr_drbg_self_test( int verbose )
printf( " CTR_DRBG (PR = FALSE): " );
test_offset = 0;
if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
CHK( ctr_drbg_random( &ctx, buf, 16 ) );
CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
CHK( ctr_drbg_random( &ctx, buf, 16 ) );
CHK( memcmp( buf, result_nopr, 16 ) );
return( 1 );
}
if( ctr_drbg_reseed( &ctx, NULL, 0 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( ctr_drbg_random( &ctx, buf, 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( memcmp( buf, result_nopr, 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
printf( "passed\n" );
......
......@@ -37,101 +37,10 @@
#include "polarssl/asn1write.h"
#if defined(POLARSSL_ECDSA_DETERMINISTIC)
/*
* 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;
/*
* Simplified HMAC_DRBG update, using optional additional data
*/
static void hmac_drbg_update( hmac_drbg_context *ctx,
const unsigned char *data, size_t data_len )
{
size_t md_len = ctx->md_ctx.md_info->size;
unsigned char rounds = ( data != NULL && data_len != 0 ) ? 2 : 1;
unsigned char sep[1];