Merged HMAC-DRBG code

This commit is contained in:
Paul Bakker 2014-02-05 15:54:34 +01:00
commit 5fb8efe71e
28 changed files with 5054 additions and 200 deletions

View File

@ -1,6 +1,9 @@
PolarSSL ChangeLog (Sorted per branch, date) PolarSSL ChangeLog (Sorted per branch, date)
= PolarSSL 1.3 branch = PolarSSL 1.3 branch
Features
* HMAC-DRBG as a separate module
Bugfix Bugfix
* ecp_gen_keypair() does more tries to prevent failure because of * ecp_gen_keypair() does more tries to prevent failure because of
statistics statistics

View File

@ -290,7 +290,7 @@
* may result in a compromise of the long-term signing key. This is avoided by * may result in a compromise of the long-term signing key. This is avoided by
* the deterministic variant. * the deterministic variant.
* *
* Requires: POLARSSL_MD_C * Requires: POLARSSL_HMAC_DRBG_C
* *
* Comment this macro to disable deterministic ECDSA. * Comment this macro to disable deterministic ECDSA.
*/ */
@ -1311,6 +1311,20 @@
*/ */
//#define POLARSSL_HAVEGE_C //#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 * \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_REQUEST 1024 /**< Maximum number of requested bytes per call */
#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ #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 // ECP options
// //
#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ #define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
@ -1962,7 +1983,7 @@
#error "POLARSSL_ECDSA_C defined, but not all prerequisites" #error "POLARSSL_ECDSA_C defined, but not all prerequisites"
#endif #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" #error "POLARSSL_ECDSA_DETERMINISTIC defined, but not all prerequisites"
#endif #endif
@ -2004,6 +2025,10 @@
#error "POLARSSL_HAVEGE_C defined, but not all prerequisites" #error "POLARSSL_HAVEGE_C defined, but not all prerequisites"
#endif #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) && \ #if defined(POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \
( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) ) ( !defined(POLARSSL_ECDH_C) || !defined(POLARSSL_X509_CRT_PARSE_C) )
#error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" #error "POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"

View File

@ -41,15 +41,17 @@
* *
* 16 bit error code bit-segmentation * 16 bit error code bit-segmentation
* *
* 1 bit - Intentionally not used * 1 bit - Sign bit
* 3 bits - High level module ID * 3 bits - High level module ID
* 5 bits - Module-dependent error code * 5 bits - Module-dependent error code
* 6 bits - Low level module errors * 7 bits - Low level module errors
* 1 bit - Intentionally not used
* *
* 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 * MPI 7 0x0002-0x0010
* GCM 2 0x0012-0x0014 * GCM 2 0x0012-0x0014
* BLOWFISH 2 0x0016-0x0018 * BLOWFISH 2 0x0016-0x0018
@ -61,7 +63,7 @@
* OID 1 0x002E-0x002E * OID 1 0x002E-0x002E
* PADLOCK 1 0x0030-0x0030 * PADLOCK 1 0x0030-0x0030
* DES 1 0x0032-0x0032 * DES 1 0x0032-0x0032
* CTR_DBRG 3 0x0034-0x003A * CTR_DBRG 4 0x0034-0x003A
* ENTROPY 3 0x003C-0x0040 * ENTROPY 3 0x003C-0x0040
* NET 11 0x0042-0x0056 * NET 11 0x0042-0x0056
* ASN1 7 0x0060-0x006C * ASN1 7 0x0060-0x006C
@ -72,6 +74,8 @@
* SHA256 1 0x0078-0x0078 * SHA256 1 0x0078-0x0078
* SHA512 1 0x007A-0x007A * SHA512 1 0x007A-0x007A
* PBKDF2 1 0x007C-0x007C * PBKDF2 1 0x007C-0x007C
* RIPEMD160 1 0x007E-0x007E
* HMAC_DRBG 4 0x0001-0x0007
* *
* High-level module nr (3 bits - 0x1...-0x8...) * High-level module nr (3 bits - 0x1...-0x8...)
* Name ID Nr of Errors * Name ID Nr of Errors
@ -88,7 +92,7 @@
* SSL 6 8 (Started from top) * SSL 6 8 (Started from top)
* SSL 7 31 * 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 #ifdef __cplusplus

View File

@ -0,0 +1,265 @@
/**
* \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 */

View File

@ -38,7 +38,7 @@ typedef UINT32 uint32_t;
#include <inttypes.h> #include <inttypes.h>
#endif #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) #if !defined(POLARSSL_RIPEMD160_ALT)
// Regular implementation // Regular implementation

View File

@ -26,6 +26,7 @@ set(src
error.c error.c
gcm.c gcm.c
havege.c havege.c
hmac_drbg.c
md.c md.c
md_wrap.c md_wrap.c
md2.c md2.c

View File

@ -44,6 +44,7 @@ OBJS= aes.o aesni.o arc4.o \
ecp.o ecp_curves.o \ ecp.o ecp_curves.o \
entropy.o entropy_poll.o \ entropy.o entropy_poll.o \
error.o gcm.o havege.o \ error.o gcm.o havege.o \
hmac_drbg.o \
md.o md_wrap.o md2.o \ md.o md_wrap.o md2.o \
md4.o md5.o memory.o \ md4.o md5.o memory.o \
memory_buffer_alloc.o net.o \ memory_buffer_alloc.o net.o \

View File

@ -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 ) if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
{ {
ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; /* LCOV_EXCL_LINE */
goto exit; goto exit; /* LCOV_EXCL_LINE */
} }
ret = 0; 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 ) if( fread( buf, 1, n, f ) != n )
{ {
fclose( f ); fclose( f ); /* LCOV_EXCL_LINE */
return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); /* LCOV_EXCL_LINE */
} }
fclose( f ); fclose( f );
@ -410,7 +410,7 @@ int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
#include <stdio.h> #include <stdio.h>
unsigned char entropy_source_pr[96] = static unsigned char entropy_source_pr[96] =
{ 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, 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, 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; 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, { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, 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, 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; 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, { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; 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, { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; 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, { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; 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, { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; 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, static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
size_t len ) size_t len )
{ {
unsigned char *p = data; const unsigned char *p = data;
memcpy( buf, p + test_offset, len ); memcpy( buf, p + test_offset, len );
test_offset += 32; test_offset += len;
return( 0 ); return( 0 );
} }
#define CHK( c ) if( (c) != 0 ) \
{ \
if( verbose != 0 ) \
printf( "failed\n" ); \
return( 1 ); \
}
/* /*
* Checkup routine * Checkup routine
*/ */
@ -475,39 +482,13 @@ int ctr_drbg_self_test( int verbose )
printf( " CTR_DRBG (PR = TRUE) : " ); printf( " CTR_DRBG (PR = TRUE) : " );
test_offset = 0; test_offset = 0;
if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_pr, nonce_pers_pr, 16, 32 ) != 0 ) CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
{ entropy_source_pr, nonce_pers_pr, 16, 32 ) );
if( verbose != 0 )
printf( "failed\n" );
return( 1 );
}
ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON ); 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 ) if( verbose != 0 )
printf( "passed\n" ); printf( "passed\n" );
@ -518,46 +499,13 @@ int ctr_drbg_self_test( int verbose )
printf( " CTR_DRBG (PR = FALSE): " ); printf( " CTR_DRBG (PR = FALSE): " );
test_offset = 0; test_offset = 0;
if( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy, entropy_source_nopr, nonce_pers_nopr, 16, 32 ) != 0 ) CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
{ entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
if( verbose != 0 ) CHK( ctr_drbg_random( &ctx, buf, 16 ) );
printf( "failed\n" ); 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_random( &ctx, buf, 16 ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );
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 ) if( verbose != 0 )
printf( "passed\n" ); printf( "passed\n" );

View File

@ -37,101 +37,10 @@
#include "polarssl/asn1write.h" #include "polarssl/asn1write.h"
#if defined(POLARSSL_ECDSA_DETERMINISTIC) #if defined(POLARSSL_ECDSA_DETERMINISTIC)
/* #include "polarssl/hmac_drbg.h"
* Simplified HMAC_DRBG context. #endif
* 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];
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, data, data_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.
*
* Uses an entropy buffer rather than callback,
* assume personalisation string is included in entropy buffer,
* assumes md_info is not NULL and valid.
*/
static void hmac_drbg_init( hmac_drbg_context *ctx,
const md_info_t * md_info,
const unsigned char *data, size_t data_len )
{
memset( ctx, 0, sizeof( hmac_drbg_context ) );
md_init_ctx( &ctx->md_ctx, md_info );
memset( ctx->V, 0x01, md_info->size );
/* ctx->K is already 0 */
hmac_drbg_update( ctx, data, data_len );
}
/*
* Simplified HMAC_DRBG random function
*/
static int hmac_drbg_random( void *state,
unsigned char *output, size_t out_len )
{
hmac_drbg_context *ctx = (hmac_drbg_context *) state;
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 );
}
static 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_ECDSA_DETERMINISTIC)
/* /*
* This a hopefully temporary compatibility function. * This a hopefully temporary compatibility function.
* *
@ -284,7 +193,7 @@ int ecdsa_sign_det( ecp_group *grp, mpi *r, mpi *s,
MPI_CHK( mpi_write_binary( d, data, grp_len ) ); MPI_CHK( mpi_write_binary( d, data, grp_len ) );
MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
MPI_CHK( mpi_write_binary( &h, data + grp_len, grp_len ) ); MPI_CHK( mpi_write_binary( &h, data + grp_len, grp_len ) );
hmac_drbg_init( &rng_ctx, md_info, data, 2 * grp_len ); hmac_drbg_init_buf( &rng_ctx, md_info, data, 2 * grp_len );
ret = ecdsa_sign( grp, r, s, d, buf, blen, ret = ecdsa_sign( grp, r, s, d, buf, blen,
hmac_drbg_random, &rng_ctx ); hmac_drbg_random, &rng_ctx );

View File

@ -77,6 +77,10 @@
#include "polarssl/gcm.h" #include "polarssl/gcm.h"
#endif #endif
#if defined(POLARSSL_HMAC_DRBG_C)
#include "polarssl/hmac_drbg.h"
#endif
#if defined(POLARSSL_MD_C) #if defined(POLARSSL_MD_C)
#include "polarssl/md.h" #include "polarssl/md.h"
#endif #endif
@ -125,6 +129,10 @@
#include "polarssl/pkcs5.h" #include "polarssl/pkcs5.h"
#endif #endif
#if defined(POLARSSL_RIPEMD160_C)
#include "polarssl/ripemd160.h"
#endif
#if defined(POLARSSL_RSA_C) #if defined(POLARSSL_RSA_C)
#include "polarssl/rsa.h" #include "polarssl/rsa.h"
#endif #endif
@ -589,6 +597,17 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
snprintf( buf, buflen, "GCM - Bad input parameters to function" ); snprintf( buf, buflen, "GCM - Bad input parameters to function" );
#endif /* POLARSSL_GCM_C */ #endif /* POLARSSL_GCM_C */
#if defined(POLARSSL_HMAC_DRBG_C)
if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) )
snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" );
if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG) )
snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG) )
snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" );
if( use_ret == -(POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR) )
snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" );
#endif /* POLARSSL_HMAC_DRBG_C */
#if defined(POLARSSL_MD2_C) #if defined(POLARSSL_MD2_C)
if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) ) if( use_ret == -(POLARSSL_ERR_MD2_FILE_IO_ERROR) )
snprintf( buf, buflen, "MD2 - Read/write error in file" ); snprintf( buf, buflen, "MD2 - Read/write error in file" );
@ -644,6 +663,11 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
snprintf( buf, buflen, "PBKDF2 - Bad input parameters to function" ); snprintf( buf, buflen, "PBKDF2 - Bad input parameters to function" );
#endif /* POLARSSL_PBKDF2_C */ #endif /* POLARSSL_PBKDF2_C */
#if defined(POLARSSL_RIPEMD160_C)
if( use_ret == -(POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR) )
snprintf( buf, buflen, "RIPEMD160 - Read/write error in file" );
#endif /* POLARSSL_RIPEMD160_C */
#if defined(POLARSSL_SHA1_C) #if defined(POLARSSL_SHA1_C)
if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) ) if( use_ret == -(POLARSSL_ERR_SHA1_FILE_IO_ERROR) )
snprintf( buf, buflen, "SHA1 - Read/write error in file" ); snprintf( buf, buflen, "SHA1 - Read/write error in file" );

483
library/hmac_drbg.c Normal file
View File

@ -0,0 +1,483 @@
/*
* 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 <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.
*/
/*
* The NIST SP 800-90A DRBGs are described in the following publication.
* http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
* References below are based on rev. 1 (January 2012).
*/
#include "polarssl/config.h"
#if defined(POLARSSL_HMAC_DRBG_C)
#include "polarssl/hmac_drbg.h"
#if defined(POLARSSL_FS_IO)
#include <stdio.h>
#endif
/*
* HMAC_DRBG update, using optional additional data (10.1.2.2)
*/
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];
unsigned char K[POLARSSL_MD_MAX_SIZE];
for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
{
/* Step 1 or 4 */
md_hmac_reset( &ctx->md_ctx );
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, K );
/* Step 2 or 5 */
md_hmac_starts( &ctx->md_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 (for use with deterministic ECDSA)
*/
int hmac_drbg_init_buf( 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 );
/*
* Set initial working state.
* Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value.
*/
md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
memset( ctx->V, 0x01, md_info->size );
hmac_drbg_update( ctx, data, data_len );
return( 0 );
}
/*
* HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
*/
int hmac_drbg_reseed( hmac_drbg_context *ctx,
const unsigned char *additional, size_t len )
{
unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen;
/* III. Check input length */
if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
{
return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
}
memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
/* IV. Gather entropy_len bytes of entropy for the seed */
if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
seedlen = ctx->entropy_len;
/* 1. Concatenate entropy and additional data if any */
if( additional != NULL && len != 0 )
{
memcpy( seed + seedlen, additional, len );
seedlen += len;
}
/* 2. Update state */
hmac_drbg_update( ctx, seed, seedlen );
/* 3. Reset reseed_counter */
ctx->reseed_counter = 1;
/* 4. Done */
return( 0 );
}
/*
* HMAC_DRBG initialisation (10.1.2.3 + 9.1)
*/
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 )
{
int ret;
size_t entropy_len;
memset( ctx, 0, sizeof( hmac_drbg_context ) );
if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
return( ret );
/*
* Set initial working state.
* Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value.
*/
md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
memset( ctx->V, 0x01, md_info->size );
ctx->f_entropy = f_entropy;
ctx->p_entropy = p_entropy;
ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
/*
* See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
* each hash function, then according to SP800-90A rev1 10.1 table 2,
* min_entropy_len (in bits) is security_strength.
*
* (This also matches the sizes used in the NIST test vectors.)
*/
entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
32; /* better (256+) -> 256 bits */
/*
* For initialisation, use more entropy to emulate a nonce
* (Again, matches test vectors.)
*/
ctx->entropy_len = entropy_len * 3 / 2;
if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
return( ret );
ctx->entropy_len = entropy_len;
return( 0 );
}
/*
* Set prediction resistance
*/
void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
int resistance )
{
ctx->prediction_resistance = resistance;
}
/*
* Set entropy length grabbed for reseeds
*/
void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
{
ctx->entropy_len = len;
}
/*
* Set reseed interval
*/
void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
{
ctx->reseed_interval = interval;
}
/*
* HMAC_DRBG random function with optional additional data:
* 10.1.2.5 (arabic) + 9.3 (Roman)
*/
int hmac_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t out_len,
const unsigned char *additional, size_t add_len )
{
int ret;
hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
size_t md_len = md_get_size( ctx->md_ctx.md_info );
size_t left = out_len;
unsigned char *out = output;
/* II. Check request length */
if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
/* III. Check input length */
if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
/* 1. (aka VII and IX) Check reseed counter and PR */
if( ctx->f_entropy != NULL && /* For no-reseeding instances */
( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
ctx->reseed_counter > ctx->reseed_interval ) )
{
if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
return( ret );
add_len = 0; /* VII.4 */
}
/* 2. Use additional data if any */
if( additional != NULL && add_len != 0 )
hmac_drbg_update( ctx, additional, add_len );
/* 3, 4, 5. Generate bytes */
while( left != 0 )
{
size_t use_len = left > md_len ? md_len : left;
md_hmac_reset( &ctx->md_ctx );
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;
}
/* 6. Update */
hmac_drbg_update( ctx, additional, add_len );
/* 7. Update reseed counter */
ctx->reseed_counter++;
/* 8. Done */
return( 0 );
}
/*
* HMAC_DRBG random function
*/
int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
{
return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 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_FS_IO)
int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
{
int ret;
FILE *f;
unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
if( ( f = fopen( path, "wb" ) ) == NULL )
return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
goto exit;
if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
{
ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR; /* LCOV_EXCL_LINE */
goto exit; /* LCOV_EXCL_LINE */
}
ret = 0;
exit:
fclose( f );
return( ret );
}
int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
{
FILE *f;
size_t n;
unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
if( ( f = fopen( path, "rb" ) ) == NULL )
return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
fseek( f, 0, SEEK_END );
n = (size_t) ftell( f );
fseek( f, 0, SEEK_SET );
if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
{
fclose( f );
return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
}
if( fread( buf, 1, n, f ) != n )
{
fclose( f ); /* LCOV_EXCL_LINE */
return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); /* LCOV_EXCL_LINE */
}
fclose( f );
hmac_drbg_update( ctx, buf, n );
return( hmac_drbg_write_seed_file( ctx, path ) );
}
#endif /* POLARSSL_FS_IO */
#if defined(POLARSSL_SELF_TEST)
#include <stdio.h>
#if !defined(POLARSSL_SHA1_C)
/* Dummy checkup routine */
int hmac_drbg_self_test( int verbose )
{
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#else
#define OUTPUT_LEN 80
/* From a NIST PR=true test vector */
static unsigned char entropy_pr[] = {
0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
static const unsigned char result_pr[OUTPUT_LEN] = {
0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
/* From a NIST PR=false test vector */
static unsigned char entropy_nopr[] = {
0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
0xe9, 0x9d, 0xfe, 0xdf };
static const unsigned char result_nopr[OUTPUT_LEN] = {
0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
/* "Entropy" from buffer */
static int test_offset;
static int hmac_drbg_self_test_entropy( void *data,
unsigned char *buf, size_t len )
{
const unsigned char *p = data;
memcpy( buf, p + test_offset, len );
test_offset += len;
return( 0 );
}
#define CHK( c ) if( (c) != 0 ) \
{ \
if( verbose != 0 ) \
printf( "failed\n" ); \
return( 1 ); \
}
/*
* Checkup routine for HMAC_DRBG with SHA-1
*/
int hmac_drbg_self_test( int verbose )
{
hmac_drbg_context ctx;
unsigned char buf[OUTPUT_LEN];
const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 );
/*
* PR = True
*/
if( verbose != 0 )
printf( " HMAC_DRBG (PR = True) : " );
test_offset = 0;
CHK( hmac_drbg_init( &ctx, md_info,
hmac_drbg_self_test_entropy, entropy_pr,
NULL, 0 ) );
hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
hmac_drbg_free( &ctx );
if( verbose != 0 )
printf( "passed\n" );
/*
* PR = False
*/
if( verbose != 0 )
printf( " HMAC_DRBG (PR = False) : " );
test_offset = 0;
CHK( hmac_drbg_init( &ctx, md_info,
hmac_drbg_self_test_entropy, entropy_nopr,
NULL, 0 ) );
CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) );
CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
hmac_drbg_free( &ctx );
if( verbose != 0 )
printf( "passed\n" );
if( verbose != 0 )
printf( "\n" );
return( 0 );
}
#endif /* POLARSSL_SHA1_C */
#endif /* POLARSSL_SELF_TEST */
#endif /* POLARSSL_HMAC_DRBG_C */

View File

@ -45,6 +45,7 @@
#include "polarssl/gcm.h" #include "polarssl/gcm.h"
#include "polarssl/havege.h" #include "polarssl/havege.h"
#include "polarssl/ctr_drbg.h" #include "polarssl/ctr_drbg.h"
#include "polarssl/hmac_drbg.h"
#include "polarssl/rsa.h" #include "polarssl/rsa.h"
#include "polarssl/dhm.h" #include "polarssl/dhm.h"
#include "polarssl/ecdsa.h" #include "polarssl/ecdsa.h"
@ -55,8 +56,8 @@
#endif #endif
#define BUFSIZE 1024 #define BUFSIZE 1024
#define HEADER_FORMAT " %-18s : " #define HEADER_FORMAT " %-24s : "
#define TITLE_LEN 19 #define TITLE_LEN 15
#if !defined(POLARSSL_TIMING_C) #if !defined(POLARSSL_TIMING_C)
int main( int argc, char *argv[] ) int main( int argc, char *argv[] )
@ -141,14 +142,14 @@ unsigned char buf[BUFSIZE];
typedef struct { typedef struct {
char md4, md5, ripemd160, sha1, sha256, sha512, char md4, md5, ripemd160, sha1, sha256, sha512,
arc4, des3, des, aes_cbc, aes_gcm, camellia, blowfish, arc4, des3, des, aes_cbc, aes_gcm, camellia, blowfish,
havege, ctr_drbg, havege, ctr_drbg, hmac_drbg,
rsa, dhm, ecdsa, ecdh; rsa, dhm, ecdsa, ecdh;
} todo_list; } todo_list;
#define OPTIONS \ #define OPTIONS \
"md4, md5, ripemd160, sha1, sha256, sha512,\n" \ "md4, md5, ripemd160, sha1, sha256, sha512,\n" \
"arc4, des3, des, aes_cbc, aes_gcm, camellia, blowfish,\n" \ "arc4, des3, des, aes_cbc, aes_gcm, camellia, blowfish,\n" \
"havege, ctr_drbg,\n" \ "havege, ctr_drbg, hmac_drbg\n" \
"rsa, dhm, ecdsa, ecdh.\n" "rsa, dhm, ecdsa, ecdh.\n"
int main( int argc, char *argv[] ) int main( int argc, char *argv[] )
@ -196,6 +197,8 @@ int main( int argc, char *argv[] )
todo.havege = 1; todo.havege = 1;
else if( strcmp( argv[i], "ctr_drbg" ) == 0 ) else if( strcmp( argv[i], "ctr_drbg" ) == 0 )
todo.ctr_drbg = 1; todo.ctr_drbg = 1;
else if( strcmp( argv[i], "hmac_drbg" ) == 0 )
todo.hmac_drbg = 1;
else if( strcmp( argv[i], "rsa" ) == 0 ) else if( strcmp( argv[i], "rsa" ) == 0 )
todo.rsa = 1; todo.rsa = 1;
else if( strcmp( argv[i], "dhm" ) == 0 ) else if( strcmp( argv[i], "dhm" ) == 0 )
@ -380,6 +383,56 @@ int main( int argc, char *argv[] )
} }
#endif #endif
#if defined(POLARSSL_HMAC_DRBG_C)
if( todo.hmac_drbg )
{
hmac_drbg_context hmac_drbg;
const md_info_t *md_info;
#if defined(POLARSSL_SHA1_C)
if( ( md_info = md_info_from_type( POLARSSL_MD_SHA1 ) ) == NULL )
exit(1);
if( hmac_drbg_init( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
exit(1);
TIME_AND_TSC( "HMAC_DRBG SHA-1 (NOPR)",
if( hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
exit(1) );
hmac_drbg_free( &hmac_drbg );
if( hmac_drbg_init( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
exit(1);
hmac_drbg_set_prediction_resistance( &hmac_drbg,
POLARSSL_HMAC_DRBG_PR_ON );
TIME_AND_TSC( "HMAC_DRBG SHA-1 (PR)",
if( hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
exit(1) );
hmac_drbg_free( &hmac_drbg );
#endif
#if defined(POLARSSL_SHA256_C)
if( ( md_info = md_info_from_type( POLARSSL_MD_SHA256 ) ) == NULL )
exit(1);
if( hmac_drbg_init( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
exit(1);
TIME_AND_TSC( "HMAC_DRBG SHA-256 (NOPR)",
if( hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
exit(1) );
hmac_drbg_free( &hmac_drbg );
if( hmac_drbg_init( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
exit(1);
hmac_drbg_set_prediction_resistance( &hmac_drbg,
POLARSSL_HMAC_DRBG_PR_ON );
TIME_AND_TSC( "HMAC_DRBG SHA-256 (PR)",
if( hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
exit(1) );
hmac_drbg_free( &hmac_drbg );
#endif
}
#endif
#if defined(POLARSSL_RSA_C) && defined(POLARSSL_GENPRIME) #if defined(POLARSSL_RSA_C) && defined(POLARSSL_GENPRIME)
if( todo.rsa ) if( todo.rsa )
{ {

View File

@ -28,6 +28,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "polarssl/hmac_drbg.h"
#include "polarssl/ctr_drbg.h" #include "polarssl/ctr_drbg.h"
#include "polarssl/dhm.h" #include "polarssl/dhm.h"
#include "polarssl/gcm.h" #include "polarssl/gcm.h"
@ -140,7 +141,7 @@ int main( int argc, char *argv[] )
return( ret ); return( ret );
#endif #endif
#if defined(POLARSSL_RSA_C) && defined(POLARSSL_BIGNUM_C) #if defined(POLARSSL_RSA_C)
if( ( ret = rsa_self_test( v ) ) != 0 ) if( ( ret = rsa_self_test( v ) ) != 0 )
return( ret ); return( ret );
#endif #endif
@ -165,6 +166,11 @@ int main( int argc, char *argv[] )
return( ret ); return( ret );
#endif #endif
#if defined(POLARSSL_HMAC_DRBG_C)
if( ( ret = hmac_drbg_self_test( v ) ) != 0 )
return( ret );
#endif
#if defined(POLARSSL_PBKDF2_C) #if defined(POLARSSL_PBKDF2_C)
if( ( ret = pbkdf2_self_test( v ) ) != 0 ) if( ( ret = pbkdf2_self_test( v ) ) != 0 )
return( ret ); return( ret );

View File

@ -11,8 +11,8 @@ my $error_format_file = $data_dir.'/error.fmt';
my @low_level_modules = ( "AES", "ASN1", "BLOWFISH", "CAMELLIA", "BIGNUM", my @low_level_modules = ( "AES", "ASN1", "BLOWFISH", "CAMELLIA", "BIGNUM",
"BASE64", "XTEA", "PBKDF2", "OID", "BASE64", "XTEA", "PBKDF2", "OID",
"PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY", "PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY",
"MD2", "MD4", "MD5", "SHA1", "SHA256", "SHA512", "HMAC_DRBG", "MD2", "MD4", "MD5", "RIPEMD160",
"GCM", "THREADING" ); "SHA1", "SHA256", "SHA512", "GCM", "THREADING" );
my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL", my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL",
"PK", "PKCS12", "PKCS5" ); "PK", "PKCS12", "PKCS5" );
@ -48,6 +48,7 @@ while (my $line = <GREP>)
# Fix faulty ones # Fix faulty ones
$module_name = "BIGNUM" if ($module_name eq "MPI"); $module_name = "BIGNUM" if ($module_name eq "MPI");
$module_name = "CTR_DRBG" if ($module_name eq "CTR"); $module_name = "CTR_DRBG" if ($module_name eq "CTR");
$module_name = "HMAC_DRBG" if ($module_name eq "HMAC");
my $define_name = $module_name; my $define_name = $module_name;
$define_name = "X509_USE,X509_CREATE" if ($define_name eq "X509"); $define_name = "X509_USE,X509_CREATE" if ($define_name eq "X509");

2
tests/.gitignore vendored
View File

@ -1,2 +1,4 @@
/test_suite* /test_suite*
data_files/mpi_write data_files/mpi_write
data_files/hmac_drbg_seed
data_files/ctr_drbg_seed

View File

@ -63,6 +63,10 @@ add_test_suite(gcm gcm.aes128_de)
add_test_suite(gcm gcm.aes192_de) add_test_suite(gcm gcm.aes192_de)
add_test_suite(gcm gcm.aes256_de) add_test_suite(gcm gcm.aes256_de)
add_test_suite(gcm gcm.camellia) add_test_suite(gcm gcm.camellia)
add_test_suite(hmac_drbg hmac_drbg.misc)
add_test_suite(hmac_drbg hmac_drbg.no_reseed)
add_test_suite(hmac_drbg hmac_drbg.nopr)
add_test_suite(hmac_drbg hmac_drbg.pr)
add_test_suite(hmac_shax) add_test_suite(hmac_shax)
add_test_suite(md) add_test_suite(md)
add_test_suite(mdx) add_test_suite(mdx)

View File

@ -44,6 +44,10 @@ APPS = test_suite_aes.ecb test_suite_aes.cbc \
test_suite_gcm.aes192_en \ test_suite_gcm.aes192_en \
test_suite_gcm.aes256_en \ test_suite_gcm.aes256_en \
test_suite_gcm.camellia test_suite_hmac_shax \ test_suite_gcm.camellia test_suite_hmac_shax \
test_suite_hmac_drbg.misc \
test_suite_hmac_drbg.no_reseed \
test_suite_hmac_drbg.nopr \
test_suite_hmac_drbg.pr \
test_suite_md test_suite_mdx \ test_suite_md test_suite_mdx \
test_suite_mpi test_suite_pbkdf2 \ test_suite_mpi test_suite_pbkdf2 \
test_suite_pkcs1_v21 test_suite_pkcs5 \ test_suite_pkcs1_v21 test_suite_pkcs5 \
@ -133,6 +137,22 @@ test_suite_gcm.camellia.c : suites/test_suite_gcm.function suites/test_suite_gcm
echo " Generate $@" echo " Generate $@"
scripts/generate_code.pl suites test_suite_gcm test_suite_gcm.camellia scripts/generate_code.pl suites test_suite_gcm test_suite_gcm.camellia
test_suite_hmac_drbg.misc.c : suites/test_suite_hmac_drbg.function suites/test_suite_hmac_drbg.misc.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
echo " Generate $@"
scripts/generate_code.pl suites test_suite_hmac_drbg test_suite_hmac_drbg.misc
test_suite_hmac_drbg.no_reseed.c : suites/test_suite_hmac_drbg.function suites/test_suite_hmac_drbg.no_reseed.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
echo " Generate $@"
scripts/generate_code.pl suites test_suite_hmac_drbg test_suite_hmac_drbg.no_reseed
test_suite_hmac_drbg.nopr.c : suites/test_suite_hmac_drbg.function suites/test_suite_hmac_drbg.nopr.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
echo " Generate $@"
scripts/generate_code.pl suites test_suite_hmac_drbg test_suite_hmac_drbg.nopr
test_suite_hmac_drbg.pr.c : suites/test_suite_hmac_drbg.function suites/test_suite_hmac_drbg.pr.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
echo " Generate $@"
scripts/generate_code.pl suites test_suite_hmac_drbg test_suite_hmac_drbg.pr
%.c : suites/%.function suites/%.data scripts/generate_code.pl suites/helpers.function suites/main_test.function %.c : suites/%.function suites/%.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
echo " Generate $@" echo " Generate $@"
scripts/generate_code.pl suites $* $* scripts/generate_code.pl suites $* $*
@ -257,6 +277,22 @@ test_suite_gcm.camellia: test_suite_gcm.camellia.c ../library/libpolarssl.a
echo " CC $@.c" echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
test_suite_hmac_drbg.misc: test_suite_hmac_drbg.misc.c ../library/libpolarssl.a
echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
test_suite_hmac_drbg.no_reseed: test_suite_hmac_drbg.no_reseed.c ../library/libpolarssl.a
echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
test_suite_hmac_drbg.nopr: test_suite_hmac_drbg.nopr.c ../library/libpolarssl.a
echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
test_suite_hmac_drbg.pr: test_suite_hmac_drbg.pr.c ../library/libpolarssl.a
echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@
test_suite_hmac_shax: test_suite_hmac_shax.c ../library/libpolarssl.a test_suite_hmac_shax: test_suite_hmac_shax.c ../library/libpolarssl.a
echo " CC $@.c" echo " CC $@.c"
$(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@

View File

@ -61,7 +61,9 @@ int verify_int( char *str, int *value )
continue; continue;
} }
if( str[i] < '0' || str[i] > '9' ) if( ! ( ( str[i] >= '0' && str[i] <= '9' ) ||
( hex && ( ( str[i] >= 'a' && str[i] <= 'f' ) ||
( str[i] >= 'A' && str[i] <= 'F' ) ) ) ) )
{ {
digits = 0; digits = 0;
break; break;

View File

@ -718,3 +718,15 @@ ctr_drbg_validate_nopr:"898064243e44ff67151736ce8bb6f1c759cab4aaca9b87543a1ac984
CTR_DRBG NIST Validation (AES-256 use df,False,256,128,256,256) #14 CTR_DRBG NIST Validation (AES-256 use df,False,256,128,256,256) #14
ctr_drbg_validate_nopr:"50de72903b9d99764123ffaa0c721e14ad1ab5c46a34c040f25324ba1d937b8ef10467161fcf2978c2a680ac5570c6d2":"5c9954fd0143e62c3bf2d5734052e3c9370f7b9d75c70f58fe33b12e3997ee2c8db84f8467affd7cfd9a9e7ec60da6f31bf9bf32aedf644e4934bd1fc916bc8d":"d5dc4c9fc7171fcbfdaead558a565ffd55d245a58b22ad1666ee05131e33f49e":"ea3114e92e6a19f53b207a0a54cd363a6d053fed0a827f92556f0a8580f7a342":"53686f069b455af4692888d11fac15cf7b4bd38e198de4e62b7098f875198a75":"9fb0df053e0345e5640aa97fedef50a6" ctr_drbg_validate_nopr:"50de72903b9d99764123ffaa0c721e14ad1ab5c46a34c040f25324ba1d937b8ef10467161fcf2978c2a680ac5570c6d2":"5c9954fd0143e62c3bf2d5734052e3c9370f7b9d75c70f58fe33b12e3997ee2c8db84f8467affd7cfd9a9e7ec60da6f31bf9bf32aedf644e4934bd1fc916bc8d":"d5dc4c9fc7171fcbfdaead558a565ffd55d245a58b22ad1666ee05131e33f49e":"ea3114e92e6a19f53b207a0a54cd363a6d053fed0a827f92556f0a8580f7a342":"53686f069b455af4692888d11fac15cf7b4bd38e198de4e62b7098f875198a75":"9fb0df053e0345e5640aa97fedef50a6"
CTR_DRBG entropy usage
ctr_drbg_entropy_usage:
CTR_DRBG write/update seed file
ctr_drbg_seed_file:"data_files/ctr_drbg_seed":0
CTR_DRBG write/update seed file
ctr_drbg_seed_file:"no_such_dir/file":POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR
CTR_DRBG self test
ctr_drbg_selftest:

View File

@ -4,9 +4,9 @@
int test_offset_idx; int test_offset_idx;
int entropy_func( void *data, unsigned char *buf, size_t len ) int entropy_func( void *data, unsigned char *buf, size_t len )
{ {
unsigned char *p = (unsigned char *) data; const unsigned char *p = (unsigned char *) data;
memcpy( buf, p + test_offset_idx, len ); memcpy( buf, p + test_offset_idx, len );
test_offset_idx += 32; test_offset_idx += len;
return( 0 ); return( 0 );
} }
/* END_HEADER */ /* END_HEADER */
@ -81,3 +81,92 @@ void ctr_drbg_validate_nopr( char *add_init_string, char *entropy_string,
TEST_ASSERT( strcmp( (char *) output_str, result_str ) == 0 ); TEST_ASSERT( strcmp( (char *) output_str, result_str ) == 0 );
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE */
void ctr_drbg_entropy_usage( )
{
unsigned char out[16];
unsigned char add[16];
unsigned char entropy[1024];
ctr_drbg_context ctx;
size_t i, reps = 10;
int last_idx;
test_offset_idx = 0;
memset( entropy, 0, sizeof( entropy ) );
memset( out, 0, sizeof( out ) );
memset( add, 0, sizeof( add ) );
/* Init must use entropy */
last_idx = test_offset_idx;
TEST_ASSERT( ctr_drbg_init( &ctx, entropy_func, entropy, NULL, 0 ) == 0 );
TEST_ASSERT( last_idx < test_offset_idx );
/* By default, PR is off and reseed_interval is large,
* so the next few calls should not use entropy */
last_idx = test_offset_idx;
for( i = 0; i < reps; i++ )
{
TEST_ASSERT( ctr_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
TEST_ASSERT( ctr_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
add, sizeof( add ) ) == 0 );
}
TEST_ASSERT( last_idx == test_offset_idx );
/* While at it, make sure we didn't write past the requested length */
TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
TEST_ASSERT( out[sizeof( out ) - 3] == 0 );
TEST_ASSERT( out[sizeof( out ) - 2] == 0 );
TEST_ASSERT( out[sizeof( out ) - 1] == 0 );
/* Set reseed_interval to the number of calls done,
* so the next call should reseed */
ctr_drbg_set_reseed_interval( &ctx, 2 * reps );
TEST_ASSERT( ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( last_idx < test_offset_idx );
/* The new few calls should not reseed */
last_idx = test_offset_idx;
for( i = 0; i < reps / 2; i++ )
{
TEST_ASSERT( ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( ctr_drbg_random_with_add( &ctx, out, sizeof( out ) ,
add, sizeof( add ) ) == 0 );
}
TEST_ASSERT( last_idx == test_offset_idx );
/* Now enable PR, so the next few calls should all reseed */
ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
TEST_ASSERT( ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( last_idx < test_offset_idx );
/* Finally, check setting entropy_len */
ctr_drbg_set_entropy_len( &ctx, 42 );
last_idx = test_offset_idx;
TEST_ASSERT( ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( test_offset_idx - last_idx == 42 );
ctr_drbg_set_entropy_len( &ctx, 13 );
last_idx = test_offset_idx;
TEST_ASSERT( ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( test_offset_idx - last_idx == 13 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
void ctr_drbg_seed_file( char *path, int ret )
{
ctr_drbg_context ctx;
TEST_ASSERT( ctr_drbg_init( &ctx, rnd_std_rand, NULL, NULL, 0 ) == 0 );
TEST_ASSERT( ctr_drbg_write_seed_file( &ctx, path ) == ret );
TEST_ASSERT( ctr_drbg_update_seed_file( &ctx, path ) == ret );
}
/* END_CASE */
/* BEGIN_CASE depends_on:POLARSSL_SELF_TEST */
void ctr_drbg_selftest( )
{
TEST_ASSERT( ctr_drbg_self_test( 0 ) == 0 );
}
/* END_CASE */

View File

@ -14,8 +14,8 @@ Non existing high error
error_strerror:-0x8880:"UNKNOWN ERROR CODE (8880)" error_strerror:-0x8880:"UNKNOWN ERROR CODE (8880)"
Non existing low error Non existing low error
error_strerror:-0x0001:"UNKNOWN ERROR CODE (0001)" error_strerror:-0x007F:"UNKNOWN ERROR CODE (007F)"
Non existing low and high error Non existing low and high error
error_strerror:-0x8881:"UNKNOWN ERROR CODE (8880) \: UNKNOWN ERROR CODE (0001)" error_strerror:-0x88FF:"UNKNOWN ERROR CODE (8880) \: UNKNOWN ERROR CODE (007F)"

View File

@ -0,0 +1,294 @@
/* BEGIN_HEADER */
#include <polarssl/hmac_drbg.h>
typedef struct
{
unsigned char *p;
size_t len;
} entropy_ctx;
int entropy_func( void *data, unsigned char *buf, size_t len )
{
entropy_ctx *ctx = (entropy_ctx *) data;
if( len > ctx->len )
return( -1 );
memcpy( buf, ctx->p, len );
ctx->p += len;
ctx->len -= len;
return( 0 );
}
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:POLARSSL_HMAC_DRBG_C
* END_DEPENDENCIES
*/
/* BEGIN_CASE */
void hmac_drbg_entropy_usage( int md_alg )
{
unsigned char out[16];
unsigned char buf[1024];
const md_info_t *md_info;
hmac_drbg_context ctx;
entropy_ctx entropy;
size_t last_len, i, reps = 10;
memset( buf, 0, sizeof( buf ) );
memset( out, 0, sizeof( out ) );
entropy.len = sizeof( buf );
entropy.p = buf;
TEST_ASSERT( ( md_info = md_info_from_type( md_alg ) ) != NULL );
/* Init must use entropy */
last_len = entropy.len;
TEST_ASSERT( hmac_drbg_init( &ctx, md_info, entropy_func, &entropy,
NULL, 0 ) == 0 );
TEST_ASSERT( entropy.len < last_len );
/* By default, PR is off and reseed_interval is large,
* so the next few calls should not use entropy */
last_len = entropy.len;
for( i = 0; i < reps; i++ )
{
TEST_ASSERT( hmac_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
buf, 16 ) == 0 );
}
TEST_ASSERT( entropy.len == last_len );
/* While at it, make sure we didn't write past the requested length */
TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
TEST_ASSERT( out[sizeof( out ) - 3] == 0 );
TEST_ASSERT( out[sizeof( out ) - 2] == 0 );
TEST_ASSERT( out[sizeof( out ) - 1] == 0 );
/* Set reseed_interval to the number of calls done,
* so the next call should reseed */
hmac_drbg_set_reseed_interval( &ctx, 2 * reps );
TEST_ASSERT( hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( entropy.len < last_len );
/* The new few calls should not reseed */
last_len = entropy.len;
for( i = 0; i < reps / 2; i++ )
{
TEST_ASSERT( hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, out, sizeof( out ) ,
buf, 16 ) == 0 );
}
TEST_ASSERT( entropy.len == last_len );
/* Now enable PR, so the next few calls should all reseed */
hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
TEST_ASSERT( hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( entropy.len < last_len );
/* Finally, check setting entropy_len */
hmac_drbg_set_entropy_len( &ctx, 42 );
last_len = entropy.len;
TEST_ASSERT( hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( (int) last_len - entropy.len == 42 );
hmac_drbg_set_entropy_len( &ctx, 13 );
last_len = entropy.len;
TEST_ASSERT( hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
TEST_ASSERT( (int) last_len - entropy.len == 13 );
hmac_drbg_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE depends_on:POLARSSL_FS_IO */
void hmac_drbg_seed_file( int md_alg, char *path, int ret )
{
const md_info_t *md_info;
hmac_drbg_context ctx;
TEST_ASSERT( ( md_info = md_info_from_type( md_alg ) ) != NULL );
TEST_ASSERT( hmac_drbg_init( &ctx, md_info, rnd_std_rand, NULL,
NULL, 0 ) == 0 );
TEST_ASSERT( hmac_drbg_write_seed_file( &ctx, path ) == ret );
TEST_ASSERT( hmac_drbg_update_seed_file( &ctx, path ) == ret );
hmac_drbg_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void hmac_drbg_buf( int md_alg )
{
unsigned char out[16];
unsigned char buf[100];
const md_info_t *md_info;
hmac_drbg_context ctx;
size_t i;
memset( buf, 0, sizeof( buf ) );
memset( out, 0, sizeof( out ) );
TEST_ASSERT( ( md_info = md_info_from_type( md_alg ) ) != NULL );
TEST_ASSERT( hmac_drbg_init_buf( &ctx, md_info, buf, sizeof( buf ) ) == 0 );
/* Make sure it never tries to reseed (would segfault otherwise) */
hmac_drbg_set_reseed_interval( &ctx, 3 );
hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
for( i = 0; i < 30; i++ )
TEST_ASSERT( hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
hmac_drbg_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void hmac_drbg_no_reseed( int md_alg,
char *entropy_hex, char *custom_hex,
char *add1_hex, char *add2_hex,
char *output_hex )
{
unsigned char data[1024];
unsigned char entropy[512];
unsigned char custom[512];
unsigned char add1[512];
unsigned char add2[512];
unsigned char output[512];
unsigned char my_output[512];
size_t custom_len, add1_len, add2_len, out_len;
entropy_ctx p_entropy;
const md_info_t *md_info;
hmac_drbg_context ctx;
memset( my_output, 0, sizeof my_output );
custom_len = unhexify( custom, custom_hex );
add1_len = unhexify( add1, add1_hex );
add2_len = unhexify( add2, add2_hex );
out_len = unhexify( output, output_hex );
p_entropy.len = unhexify( entropy, entropy_hex );
p_entropy.p = entropy;
TEST_ASSERT( ( md_info = md_info_from_type( md_alg ) ) != NULL );
/* Test the simplified buffer-based variant */
memcpy( data, entropy, p_entropy.len );
memcpy( data + p_entropy.len, custom, custom_len );
TEST_ASSERT( hmac_drbg_init_buf( &ctx, md_info,
data, p_entropy.len + custom_len ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, my_output, out_len,
add1, add1_len ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, my_output, out_len,
add2, add2_len ) == 0 );
hmac_drbg_free( &ctx );
TEST_ASSERT( memcmp( my_output, output, out_len ) == 0 );
/* And now the normal entropy-based variant */
TEST_ASSERT( hmac_drbg_init( &ctx, md_info, entropy_func, &p_entropy,
custom, custom_len ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, my_output, out_len,
add1, add1_len ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, my_output, out_len,
add2, add2_len ) == 0 );
hmac_drbg_free( &ctx );
TEST_ASSERT( memcmp( my_output, output, out_len ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE */
void hmac_drbg_nopr( int md_alg,
char *entropy_hex, char *custom_hex,
char *add1_hex, char *add2_hex, char *add3_hex,
char *output_hex )
{
unsigned char entropy[512];
unsigned char custom[512];
unsigned char add1[512];
unsigned char add2[512];
unsigned char add3[512];
unsigned char output[512];
unsigned char my_output[512];
size_t custom_len, add1_len, add2_len, add3_len, out_len;
entropy_ctx p_entropy;
const md_info_t *md_info;
hmac_drbg_context ctx;
memset( my_output, 0, sizeof my_output );
custom_len = unhexify( custom, custom_hex );
add1_len = unhexify( add1, add1_hex );
add2_len = unhexify( add2, add2_hex );
add3_len = unhexify( add3, add3_hex );
out_len = unhexify( output, output_hex );
p_entropy.len = unhexify( entropy, entropy_hex );
p_entropy.p = entropy;
TEST_ASSERT( ( md_info = md_info_from_type( md_alg ) ) != NULL );
TEST_ASSERT( hmac_drbg_init( &ctx, md_info, entropy_func, &p_entropy,
custom, custom_len ) == 0 );
TEST_ASSERT( hmac_drbg_reseed( &ctx, add1, add1_len ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, my_output, out_len,
add2, add2_len ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, my_output, out_len,
add3, add3_len ) == 0 );
hmac_drbg_free( &ctx );
TEST_ASSERT( memcmp( my_output, output, out_len ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE */
void hmac_drbg_pr( int md_alg,
char *entropy_hex, char *custom_hex,
char *add1_hex, char *add2_hex,
char *output_hex )
{
unsigned char entropy[512];
unsigned char custom[512];
unsigned char add1[512];
unsigned char add2[512];
unsigned char output[512];
unsigned char my_output[512];
size_t custom_len, add1_len, add2_len, out_len;
entropy_ctx p_entropy;
const md_info_t *md_info;
hmac_drbg_context ctx;
memset( my_output, 0, sizeof my_output );
custom_len = unhexify( custom, custom_hex );
add1_len = unhexify( add1, add1_hex );
add2_len = unhexify( add2, add2_hex );
out_len = unhexify( output, output_hex );
p_entropy.len = unhexify( entropy, entropy_hex );
p_entropy.p = entropy;
TEST_ASSERT( ( md_info = md_info_from_type( md_alg ) ) != NULL );
TEST_ASSERT( hmac_drbg_init( &ctx, md_info, entropy_func, &p_entropy,
custom, custom_len ) == 0 );
hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, my_output, out_len,
add1, add1_len ) == 0 );
TEST_ASSERT( hmac_drbg_random_with_add( &ctx, my_output, out_len,
add2, add2_len ) == 0 );
hmac_drbg_free( &ctx );
TEST_ASSERT( memcmp( my_output, output, out_len ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:POLARSSL_SELF_TEST */
void hmac_drbg_selftest( )
{
TEST_ASSERT( hmac_drbg_self_test( 0 ) == 0 );
}
/* END_CASE */

View File

@ -0,0 +1,82 @@
HMAC_DRBG entropy usage SHA-1
depends_on:POLARSSL_SHA1_C
hmac_drbg_entropy_usage:POLARSSL_MD_SHA1
HMAC_DRBG entropy usage SHA-224
depends_on:POLARSSL_SHA256_C
hmac_drbg_entropy_usage:POLARSSL_MD_SHA224
HMAC_DRBG entropy usage SHA-256
depends_on:POLARSSL_SHA256_C
hmac_drbg_entropy_usage:POLARSSL_MD_SHA256
HMAC_DRBG entropy usage SHA-384
depends_on:POLARSSL_SHA512_C
hmac_drbg_entropy_usage:POLARSSL_MD_SHA384
HMAC_DRBG entropy usage SHA-512
depends_on:POLARSSL_SHA512_C
hmac_drbg_entropy_usage:POLARSSL_MD_SHA512
HMAC_DRBG write/update seed file SHA-1
depends_on:POLARSSL_SHA1_C
hmac_drbg_seed_file:POLARSSL_MD_SHA1:"data_files/hmac_drbg_seed":0
HMAC_DRBG write/update seed file SHA-1
depends_on:POLARSSL_SHA1_C
hmac_drbg_seed_file:POLARSSL_MD_SHA1:"no_such_dir/file":POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR
HMAC_DRBG write/update seed file SHA-224
depends_on:POLARSSL_SHA256_C
hmac_drbg_seed_file:POLARSSL_MD_SHA224:"data_files/hmac_drbg_seed":0
HMAC_DRBG write/update seed file SHA-224
depends_on:POLARSSL_SHA256_C
hmac_drbg_seed_file:POLARSSL_MD_SHA224:"no_such_dir/file":POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR
HMAC_DRBG write/update seed file SHA-256
depends_on:POLARSSL_SHA256_C
hmac_drbg_seed_file:POLARSSL_MD_SHA256:"data_files/hmac_drbg_seed":0
HMAC_DRBG write/update seed file SHA-256
depends_on:POLARSSL_SHA256_C
hmac_drbg_seed_file:POLARSSL_MD_SHA256:"no_such_dir/file":POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR
HMAC_DRBG write/update seed file SHA-384
depends_on:POLARSSL_SHA512_C
hmac_drbg_seed_file:POLARSSL_MD_SHA384:"data_files/hmac_drbg_seed":0
HMAC_DRBG write/update seed file SHA-384
depends_on:POLARSSL_SHA512_C
hmac_drbg_seed_file:POLARSSL_MD_SHA384:"no_such_dir/file":POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR
HMAC_DRBG write/update seed file SHA-512
depends_on:POLARSSL_SHA512_C
hmac_drbg_seed_file:POLARSSL_MD_SHA512:"data_files/hmac_drbg_seed":0
HMAC_DRBG write/update seed file SHA-512
depends_on:POLARSSL_SHA512_C
hmac_drbg_seed_file:POLARSSL_MD_SHA512:"no_such_dir/file":POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR
HMAC_DRBG from buffer SHA-1
depends_on:POLARSSL_SHA1_C
hmac_drbg_buf:POLARSSL_MD_SHA1
HMAC_DRBG from buffer SHA-224
depends_on:POLARSSL_SHA256_C
hmac_drbg_buf:POLARSSL_MD_SHA224
HMAC_DRBG from buffer SHA-256
depends_on:POLARSSL_SHA256_C
hmac_drbg_buf:POLARSSL_MD_SHA256
HMAC_DRBG from buffer SHA-384
depends_on:POLARSSL_SHA512_C
hmac_drbg_buf:POLARSSL_MD_SHA384
HMAC_DRBG from buffer SHA-512
depends_on:POLARSSL_SHA512_C
hmac_drbg_buf:POLARSSL_MD_SHA512
HMAC_DRBG self test
hmac_drbg_selftest:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -168,6 +168,7 @@
<ClInclude Include="..\..\include\polarssl\error.h" /> <ClInclude Include="..\..\include\polarssl\error.h" />
<ClInclude Include="..\..\include\polarssl\gcm.h" /> <ClInclude Include="..\..\include\polarssl\gcm.h" />
<ClInclude Include="..\..\include\polarssl\havege.h" /> <ClInclude Include="..\..\include\polarssl\havege.h" />
<ClInclude Include="..\..\include\polarssl\hmac_drbg.h" />
<ClInclude Include="..\..\include\polarssl\md2.h" /> <ClInclude Include="..\..\include\polarssl\md2.h" />
<ClInclude Include="..\..\include\polarssl\md4.h" /> <ClInclude Include="..\..\include\polarssl\md4.h" />
<ClInclude Include="..\..\include\polarssl\md5.h" /> <ClInclude Include="..\..\include\polarssl\md5.h" />
@ -227,6 +228,7 @@
<ClCompile Include="..\..\library\error.c" /> <ClCompile Include="..\..\library\error.c" />
<ClCompile Include="..\..\library\gcm.c" /> <ClCompile Include="..\..\library\gcm.c" />
<ClCompile Include="..\..\library\havege.c" /> <ClCompile Include="..\..\library\havege.c" />
<ClCompile Include="..\..\library\hmac_drbg.c" />
<ClCompile Include="..\..\library\md2.c" /> <ClCompile Include="..\..\library\md2.c" />
<ClCompile Include="..\..\library\md4.c" /> <ClCompile Include="..\..\library\md4.c" />
<ClCompile Include="..\..\library\md5.c" /> <ClCompile Include="..\..\library\md5.c" />

View File

@ -185,6 +185,10 @@ SOURCE=..\..\library\havege.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\library\hmac_drbg.c
# End Source File
# Begin Source File
SOURCE=..\..\library\md2.c SOURCE=..\..\library\md2.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@ -457,6 +461,10 @@ SOURCE=..\..\include\polarssl\havege.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\include\polarssl\hmac_drbg.h
# End Source File
# Begin Source File
SOURCE=..\..\include\polarssl\md2.h SOURCE=..\..\include\polarssl\md2.h
# End Source File # End Source File
# Begin Source File # Begin Source File