diff options
author | james <james@e7ae566f-a301-0410-adde-c780ea21d3b5> | 2008-11-18 01:25:05 +0000 |
---|---|---|
committer | james <james@e7ae566f-a301-0410-adde-c780ea21d3b5> | 2008-11-18 01:25:05 +0000 |
commit | 03bfb228ffd95c37e135bb9a5a37160c247e28a9 (patch) | |
tree | 62fe17de8cce142be0749cf4a07509246b02f48b /crypto.c | |
parent | Version 2.1_rc14 (diff) | |
download | openvpn-03bfb228ffd95c37e135bb9a5a37160c247e28a9.tar.xz |
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
Diffstat (limited to 'crypto.c')
-rw-r--r-- | crypto.c | 73 |
1 files changed, 57 insertions, 16 deletions
@@ -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; /* GLOBAL */ +static const EVP_MD *nonce_md = NULL; /* GLOBAL */ +static int nonce_secret_len; /* GLOBAL */ -static uint8_t nonce_data [SHA_DIGEST_LENGTH + NONCE_SECRET_LEN]; /* GLOBAL */ +void +prng_init (const char *md_name, const int nonce_secret_len_parm) +{ + 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_init (void) +prng_uninit (void) { - if (!RAND_bytes (nonce_data, sizeof(nonce_data))) - msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for PRNG"); + 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 */ |