aboutsummaryrefslogtreecommitdiff
path: root/crypto.c
diff options
context:
space:
mode:
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2008-11-18 01:25:05 +0000
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2008-11-18 01:25:05 +0000
commit03bfb228ffd95c37e135bb9a5a37160c247e28a9 (patch)
tree62fe17de8cce142be0749cf4a07509246b02f48b /crypto.c
parentVersion 2.1_rc14 (diff)
downloadopenvpn-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.c73
1 files changed, 57 insertions, 16 deletions
diff --git a/crypto.c b/crypto.c
index 7c2a9bb..d813f03 100644
--- a/crypto.c
+++ b/crypto.c
@@ -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 */