Added --prng option to control PRNG (pseudo-random

number generator) parameters.  In previous OpenVPN
versions, the PRNG was hardcoded to use the SHA1
hash.  Now any OpenSSL hash may be used.  This is
part of an effort to remove hardcoded references to
a specific cipher or cryptographic hash algorithm.


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3503 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
james 2008-11-18 01:25:05 +00:00
parent f158465dad
commit 03bfb228ff
9 changed files with 137 additions and 22 deletions

View File

@ -1640,6 +1640,7 @@ void uninit_crypto_lib ()
engine_initialized = false;
}
#endif
prng_uninit ();
}
/*
@ -1649,33 +1650,73 @@ void uninit_crypto_lib ()
* IV values and a number of other miscellaneous tasks.
*/
#define NONCE_SECRET_LEN 16
static uint8_t nonce_data [SHA_DIGEST_LENGTH + NONCE_SECRET_LEN]; /* GLOBAL */
static uint8_t *nonce_data; /* GLOBAL */
static const EVP_MD *nonce_md = NULL; /* GLOBAL */
static int nonce_secret_len; /* GLOBAL */
void
prng_init (void)
prng_init (const char *md_name, const int nonce_secret_len_parm)
{
if (!RAND_bytes (nonce_data, sizeof(nonce_data)))
msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for PRNG");
prng_uninit ();
nonce_md = md_name ? get_md (md_name) : NULL;
if (nonce_md)
{
ASSERT (nonce_secret_len_parm >= NONCE_SECRET_LEN_MIN && nonce_secret_len_parm <= NONCE_SECRET_LEN_MAX);
nonce_secret_len = nonce_secret_len_parm;
{
const int size = EVP_MD_size (nonce_md) + nonce_secret_len;
dmsg (D_CRYPTO_DEBUG, "PRNG init md=%s size=%d", EVP_MD_name (nonce_md), size);
nonce_data = (uint8_t*) malloc (size);
check_malloc_return (nonce_data);
#if 1 /* Must be 1 for real usage */
if (!RAND_bytes (nonce_data, size))
msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for PRNG");
#else
/* Only for testing -- will cause a predictable PRNG sequence */
{
int i;
for (i = 0; i < size; ++i)
nonce_data[i] = (uint8_t) i;
}
#endif
}
}
}
void
prng_uninit (void)
{
free (nonce_data);
nonce_data = NULL;
nonce_md = NULL;
nonce_secret_len = 0;
}
void
prng_bytes (uint8_t *output, int len)
{
SHA_CTX ctx;
mutex_lock_static (L_PRNG);
while (len > 0)
if (nonce_md)
{
const int blen = min_int (len, SHA_DIGEST_LENGTH);
SHA1_Init (&ctx);
SHA1_Update (&ctx, nonce_data, sizeof (nonce_data));
SHA1_Final (nonce_data, &ctx);
memcpy (output, nonce_data, blen);
output += blen;
len -= blen;
EVP_MD_CTX ctx;
const int md_size = EVP_MD_size (nonce_md);
mutex_lock_static (L_PRNG);
while (len > 0)
{
unsigned int outlen = 0;
const int blen = min_int (len, md_size);
EVP_DigestInit (&ctx, nonce_md);
EVP_DigestUpdate (&ctx, nonce_data, md_size + nonce_secret_len);
EVP_DigestFinal (&ctx, nonce_data, &outlen);
ASSERT (outlen == md_size);
EVP_MD_CTX_cleanup (&ctx);
memcpy (output, nonce_data, blen);
output += blen;
len -= blen;
}
mutex_unlock_static (L_PRNG);
}
mutex_unlock_static (L_PRNG);
else
RAND_bytes (output, len);
}
/* an analogue to the random() function, but use prng_bytes */

View File

@ -329,8 +329,11 @@ void crypto_adjust_frame_parameters(struct frame *frame,
bool packet_id,
bool packet_id_long_form);
void prng_init (void);
#define NONCE_SECRET_LEN_MIN 16
#define NONCE_SECRET_LEN_MAX 64
void prng_init (const char *md_name, const int nonce_secret_len_parm);
void prng_bytes (uint8_t *output, int len);
void prng_uninit ();
void test_crypto (const struct crypto_options *co, struct frame* f);

View File

@ -140,6 +140,7 @@
#define D_AUTO_USERID LOGLEV(7, 70, M_DEBUG) /* AUTO_USERID debugging */
#define D_TLS_KEYSELECT LOGLEV(7, 70, M_DEBUG) /* show information on key selection for data channel */
#define D_ARGV_PARSE_CMD LOGLEV(7, 70, M_DEBUG) /* show parse_line() errors in argv_printf %sc */
#define D_CRYPTO_DEBUG LOGLEV(7, 70, M_DEBUG) /* show detailed info from crypto.c routines */
#define D_PF_DROPPED_BCAST LOGLEV(7, 71, M_DEBUG) /* packet filter dropped a broadcast packet */
#define D_PF_DEBUG LOGLEV(7, 72, M_DEBUG) /* packet filter debugging, must also define PF_DEBUG in pf.h */
@ -153,7 +154,6 @@
#define D_MULTI_TCP LOGLEV(8, 70, M_DEBUG) /* show debug info from mtcp.c */
#define D_TLS_DEBUG LOGLEV(9, 70, M_DEBUG) /* show detailed info from TLS routines */
#define D_CRYPTO_DEBUG LOGLEV(9, 70, M_DEBUG) /* show detailed info from crypto.c routines */
#define D_COMP LOGLEV(9, 70, M_DEBUG) /* show compression info */
#define D_READ_WRITE LOGLEV(9, 70, M_DEBUG) /* show all tun/tcp/udp reads/writes/opens */
#define D_PACKET_CONTENT LOGLEV(9, 70, M_DEBUG) /* show before/after encryption packet content */

28
init.c
View File

@ -401,7 +401,7 @@ init_static (void)
/* init PRNG used for IV generation */
/* When forking, copy this to more places in the code to avoid fork
random-state predictability */
prng_init ();
prng_init (NULL, 0);
#endif
#ifdef PID_TEST
@ -473,6 +473,29 @@ init_static (void)
}
#endif
#ifdef PRNG_TEST
{
struct gc_arena gc = gc_new ();
uint8_t rndbuf[8];
int i;
prng_init ("sha1", 16);
//prng_init (NULL, 0);
const int factor = 1;
for (i = 0; i < factor * 8; ++i)
{
#if 1
prng_bytes (rndbuf, sizeof (rndbuf));
#else
ASSERT(RAND_bytes (rndbuf, sizeof (rndbuf)));
#endif
printf ("[%d] %s\n", i, format_hex (rndbuf, sizeof (rndbuf), 0, &gc));
}
gc_free (&gc);
prng_uninit ();
return false;
}
#endif
return true;
}
@ -1634,6 +1657,9 @@ do_init_crypto_tls_c1 (struct context *c)
options->ciphername_defined, options->authname,
options->authname_defined, options->keysize, true, true);
/* Initialize PRNG with config-specified digest */
prng_init (options->prng_hash, options->prng_nonce_secret_len);
/* TLS handshake authentication (--tls-auth) */
if (options->tls_auth_file)
{

View File

@ -3616,6 +3616,21 @@ larger key may offer no real guarantee of greater
security, or may even reduce security.
.\"*********************************************************
.TP
.B --prng alg [nsl]
(Advanced) For PRNG (Pseudo-random number generator),
use digest algorithm
.B alg
(default=sha1), and set
.B nsl
(default=16)
to the size in bytes of the nonce secret length (between 16 and 64).
Set
.B alg=none
to disable the PRNG and use the OpenSSL RAND_bytes function
instead for all of OpenVPN's pseudo-random number needs.
.\"*********************************************************
.TP
.B --engine [engine-name]
Enable OpenSSL hardware-based crypto engine functionality.

View File

@ -442,6 +442,8 @@ static const char usage_message[] =
"--cipher alg : Encrypt packets with cipher algorithm alg\n"
" (default=%s).\n"
" Set alg=none to disable encryption.\n"
"--prng alg [nsl] : For PRNG, use digest algorithm alg, and\n"
" nonce_secret_len=nsl. Set alg=none to disable PRNG.\n"
#ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH
"--keysize n : Size of cipher key in bits (optional).\n"
" If unspecified, defaults to cipher-specific default.\n"
@ -717,6 +719,8 @@ init_options (struct options *o, const bool init_gc)
o->ciphername_defined = true;
o->authname = "SHA1";
o->authname_defined = true;
o->prng_hash = "SHA1";
o->prng_nonce_secret_len = 16;
o->replay = true;
o->replay_window = DEFAULT_SEQ_BACKTRACK;
o->replay_time = DEFAULT_TIME_BACKTRACK;
@ -1272,6 +1276,8 @@ show_settings (const struct options *o)
SHOW_STR (ciphername);
SHOW_BOOL (authname_defined);
SHOW_STR (authname);
SHOW_STR (prng_hash);
SHOW_INT (prng_nonce_secret_len);
SHOW_INT (keysize);
SHOW_BOOL (engine);
SHOW_BOOL (replay);
@ -5158,6 +5164,28 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_CRYPTO);
options->ciphername_defined = true;
}
else if (streq (p[0], "prng") && p[1])
{
VERIFY_PERMISSION (OPT_P_CRYPTO);
if (streq (p[1], "none"))
options->prng_hash = NULL;
else
options->prng_hash = p[1];
if (p[2])
{
const int sl = atoi (p[2]);
if (sl >= NONCE_SECRET_LEN_MIN && sl <= NONCE_SECRET_LEN_MAX)
{
options->prng_nonce_secret_len = sl;
}
else
{
msg (msglevel, "prng parameter nonce_secret_len must be between %d and %d",
NONCE_SECRET_LEN_MIN, NONCE_SECRET_LEN_MAX);
goto err;
}
}
}
else if (streq (p[0], "no-replay"))
{
VERIFY_PERMISSION (OPT_P_CRYPTO);

View File

@ -418,6 +418,8 @@ struct options
bool authname_defined;
const char *authname;
int keysize;
const char *prng_hash;
int prng_nonce_secret_len;
const char *engine;
bool replay;
bool mute_replay_warnings;

2
ps.c
View File

@ -793,7 +793,7 @@ port_share_open (const char *host, const int port)
set_nonblock (fd[1]);
/* initialize prng */
prng_init ();
prng_init (NULL, 0);
/* execute the event loop */
port_share_proxy (hostaddr, port, fd[1]);

View File

@ -1,5 +1,5 @@
dnl define the OpenVPN version
define(PRODUCT_VERSION,[2.1_rc14])
define(PRODUCT_VERSION,[2.1_rc14a])
dnl define the TAP version
define(PRODUCT_TAP_ID,[tap0901])
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])