git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3503 e7ae566f-a301-0410-adde-c780ea21d3b5
| ... | ... |
@@ -1640,6 +1640,7 @@ void uninit_crypto_lib () |
| 1640 | 1640 |
engine_initialized = false; |
| 1641 | 1641 |
} |
| 1642 | 1642 |
#endif |
| 1643 |
+ prng_uninit (); |
|
| 1643 | 1644 |
} |
| 1644 | 1645 |
|
| 1645 | 1646 |
/* |
| ... | ... |
@@ -1649,33 +1650,73 @@ void uninit_crypto_lib () |
| 1649 | 1649 |
* IV values and a number of other miscellaneous tasks. |
| 1650 | 1650 |
*/ |
| 1651 | 1651 |
|
| 1652 |
-#define NONCE_SECRET_LEN 16 |
|
| 1652 |
+static uint8_t *nonce_data; /* GLOBAL */ |
|
| 1653 |
+static const EVP_MD *nonce_md = NULL; /* GLOBAL */ |
|
| 1654 |
+static int nonce_secret_len; /* GLOBAL */ |
|
| 1653 | 1655 |
|
| 1654 |
-static uint8_t nonce_data [SHA_DIGEST_LENGTH + NONCE_SECRET_LEN]; /* GLOBAL */ |
|
| 1656 |
+void |
|
| 1657 |
+prng_init (const char *md_name, const int nonce_secret_len_parm) |
|
| 1658 |
+{
|
|
| 1659 |
+ prng_uninit (); |
|
| 1660 |
+ nonce_md = md_name ? get_md (md_name) : NULL; |
|
| 1661 |
+ if (nonce_md) |
|
| 1662 |
+ {
|
|
| 1663 |
+ ASSERT (nonce_secret_len_parm >= NONCE_SECRET_LEN_MIN && nonce_secret_len_parm <= NONCE_SECRET_LEN_MAX); |
|
| 1664 |
+ nonce_secret_len = nonce_secret_len_parm; |
|
| 1665 |
+ {
|
|
| 1666 |
+ const int size = EVP_MD_size (nonce_md) + nonce_secret_len; |
|
| 1667 |
+ dmsg (D_CRYPTO_DEBUG, "PRNG init md=%s size=%d", EVP_MD_name (nonce_md), size); |
|
| 1668 |
+ nonce_data = (uint8_t*) malloc (size); |
|
| 1669 |
+ check_malloc_return (nonce_data); |
|
| 1670 |
+#if 1 /* Must be 1 for real usage */ |
|
| 1671 |
+ if (!RAND_bytes (nonce_data, size)) |
|
| 1672 |
+ msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for PRNG"); |
|
| 1673 |
+#else |
|
| 1674 |
+ /* Only for testing -- will cause a predictable PRNG sequence */ |
|
| 1675 |
+ {
|
|
| 1676 |
+ int i; |
|
| 1677 |
+ for (i = 0; i < size; ++i) |
|
| 1678 |
+ nonce_data[i] = (uint8_t) i; |
|
| 1679 |
+ } |
|
| 1680 |
+#endif |
|
| 1681 |
+ } |
|
| 1682 |
+ } |
|
| 1683 |
+} |
|
| 1655 | 1684 |
|
| 1656 | 1685 |
void |
| 1657 |
-prng_init (void) |
|
| 1686 |
+prng_uninit (void) |
|
| 1658 | 1687 |
{
|
| 1659 |
- if (!RAND_bytes (nonce_data, sizeof(nonce_data))) |
|
| 1660 |
- msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for PRNG"); |
|
| 1688 |
+ free (nonce_data); |
|
| 1689 |
+ nonce_data = NULL; |
|
| 1690 |
+ nonce_md = NULL; |
|
| 1691 |
+ nonce_secret_len = 0; |
|
| 1661 | 1692 |
} |
| 1662 | 1693 |
|
| 1663 | 1694 |
void |
| 1664 | 1695 |
prng_bytes (uint8_t *output, int len) |
| 1665 | 1696 |
{
|
| 1666 |
- SHA_CTX ctx; |
|
| 1667 |
- mutex_lock_static (L_PRNG); |
|
| 1668 |
- while (len > 0) |
|
| 1697 |
+ if (nonce_md) |
|
| 1669 | 1698 |
{
|
| 1670 |
- const int blen = min_int (len, SHA_DIGEST_LENGTH); |
|
| 1671 |
- SHA1_Init (&ctx); |
|
| 1672 |
- SHA1_Update (&ctx, nonce_data, sizeof (nonce_data)); |
|
| 1673 |
- SHA1_Final (nonce_data, &ctx); |
|
| 1674 |
- memcpy (output, nonce_data, blen); |
|
| 1675 |
- output += blen; |
|
| 1676 |
- len -= blen; |
|
| 1699 |
+ EVP_MD_CTX ctx; |
|
| 1700 |
+ const int md_size = EVP_MD_size (nonce_md); |
|
| 1701 |
+ mutex_lock_static (L_PRNG); |
|
| 1702 |
+ while (len > 0) |
|
| 1703 |
+ {
|
|
| 1704 |
+ unsigned int outlen = 0; |
|
| 1705 |
+ const int blen = min_int (len, md_size); |
|
| 1706 |
+ EVP_DigestInit (&ctx, nonce_md); |
|
| 1707 |
+ EVP_DigestUpdate (&ctx, nonce_data, md_size + nonce_secret_len); |
|
| 1708 |
+ EVP_DigestFinal (&ctx, nonce_data, &outlen); |
|
| 1709 |
+ ASSERT (outlen == md_size); |
|
| 1710 |
+ EVP_MD_CTX_cleanup (&ctx); |
|
| 1711 |
+ memcpy (output, nonce_data, blen); |
|
| 1712 |
+ output += blen; |
|
| 1713 |
+ len -= blen; |
|
| 1714 |
+ } |
|
| 1715 |
+ mutex_unlock_static (L_PRNG); |
|
| 1677 | 1716 |
} |
| 1678 |
- mutex_unlock_static (L_PRNG); |
|
| 1717 |
+ else |
|
| 1718 |
+ RAND_bytes (output, len); |
|
| 1679 | 1719 |
} |
| 1680 | 1720 |
|
| 1681 | 1721 |
/* an analogue to the random() function, but use prng_bytes */ |
| ... | ... |
@@ -329,8 +329,11 @@ void crypto_adjust_frame_parameters(struct frame *frame, |
| 329 | 329 |
bool packet_id, |
| 330 | 330 |
bool packet_id_long_form); |
| 331 | 331 |
|
| 332 |
-void prng_init (void); |
|
| 332 |
+#define NONCE_SECRET_LEN_MIN 16 |
|
| 333 |
+#define NONCE_SECRET_LEN_MAX 64 |
|
| 334 |
+void prng_init (const char *md_name, const int nonce_secret_len_parm); |
|
| 333 | 335 |
void prng_bytes (uint8_t *output, int len); |
| 336 |
+void prng_uninit (); |
|
| 334 | 337 |
|
| 335 | 338 |
void test_crypto (const struct crypto_options *co, struct frame* f); |
| 336 | 339 |
|
| ... | ... |
@@ -140,6 +140,7 @@ |
| 140 | 140 |
#define D_AUTO_USERID LOGLEV(7, 70, M_DEBUG) /* AUTO_USERID debugging */ |
| 141 | 141 |
#define D_TLS_KEYSELECT LOGLEV(7, 70, M_DEBUG) /* show information on key selection for data channel */ |
| 142 | 142 |
#define D_ARGV_PARSE_CMD LOGLEV(7, 70, M_DEBUG) /* show parse_line() errors in argv_printf %sc */ |
| 143 |
+#define D_CRYPTO_DEBUG LOGLEV(7, 70, M_DEBUG) /* show detailed info from crypto.c routines */ |
|
| 143 | 144 |
#define D_PF_DROPPED_BCAST LOGLEV(7, 71, M_DEBUG) /* packet filter dropped a broadcast packet */ |
| 144 | 145 |
#define D_PF_DEBUG LOGLEV(7, 72, M_DEBUG) /* packet filter debugging, must also define PF_DEBUG in pf.h */ |
| 145 | 146 |
|
| ... | ... |
@@ -153,7 +154,6 @@ |
| 153 | 153 |
#define D_MULTI_TCP LOGLEV(8, 70, M_DEBUG) /* show debug info from mtcp.c */ |
| 154 | 154 |
|
| 155 | 155 |
#define D_TLS_DEBUG LOGLEV(9, 70, M_DEBUG) /* show detailed info from TLS routines */ |
| 156 |
-#define D_CRYPTO_DEBUG LOGLEV(9, 70, M_DEBUG) /* show detailed info from crypto.c routines */ |
|
| 157 | 156 |
#define D_COMP LOGLEV(9, 70, M_DEBUG) /* show compression info */ |
| 158 | 157 |
#define D_READ_WRITE LOGLEV(9, 70, M_DEBUG) /* show all tun/tcp/udp reads/writes/opens */ |
| 159 | 158 |
#define D_PACKET_CONTENT LOGLEV(9, 70, M_DEBUG) /* show before/after encryption packet content */ |
| ... | ... |
@@ -401,7 +401,7 @@ init_static (void) |
| 401 | 401 |
/* init PRNG used for IV generation */ |
| 402 | 402 |
/* When forking, copy this to more places in the code to avoid fork |
| 403 | 403 |
random-state predictability */ |
| 404 |
- prng_init (); |
|
| 404 |
+ prng_init (NULL, 0); |
|
| 405 | 405 |
#endif |
| 406 | 406 |
|
| 407 | 407 |
#ifdef PID_TEST |
| ... | ... |
@@ -473,6 +473,29 @@ init_static (void) |
| 473 | 473 |
} |
| 474 | 474 |
#endif |
| 475 | 475 |
|
| 476 |
+#ifdef PRNG_TEST |
|
| 477 |
+ {
|
|
| 478 |
+ struct gc_arena gc = gc_new (); |
|
| 479 |
+ uint8_t rndbuf[8]; |
|
| 480 |
+ int i; |
|
| 481 |
+ prng_init ("sha1", 16);
|
|
| 482 |
+ //prng_init (NULL, 0); |
|
| 483 |
+ const int factor = 1; |
|
| 484 |
+ for (i = 0; i < factor * 8; ++i) |
|
| 485 |
+ {
|
|
| 486 |
+#if 1 |
|
| 487 |
+ prng_bytes (rndbuf, sizeof (rndbuf)); |
|
| 488 |
+#else |
|
| 489 |
+ ASSERT(RAND_bytes (rndbuf, sizeof (rndbuf))); |
|
| 490 |
+#endif |
|
| 491 |
+ printf ("[%d] %s\n", i, format_hex (rndbuf, sizeof (rndbuf), 0, &gc));
|
|
| 492 |
+ } |
|
| 493 |
+ gc_free (&gc); |
|
| 494 |
+ prng_uninit (); |
|
| 495 |
+ return false; |
|
| 496 |
+ } |
|
| 497 |
+#endif |
|
| 498 |
+ |
|
| 476 | 499 |
return true; |
| 477 | 500 |
} |
| 478 | 501 |
|
| ... | ... |
@@ -1634,6 +1657,9 @@ do_init_crypto_tls_c1 (struct context *c) |
| 1634 | 1634 |
options->ciphername_defined, options->authname, |
| 1635 | 1635 |
options->authname_defined, options->keysize, true, true); |
| 1636 | 1636 |
|
| 1637 |
+ /* Initialize PRNG with config-specified digest */ |
|
| 1638 |
+ prng_init (options->prng_hash, options->prng_nonce_secret_len); |
|
| 1639 |
+ |
|
| 1637 | 1640 |
/* TLS handshake authentication (--tls-auth) */ |
| 1638 | 1641 |
if (options->tls_auth_file) |
| 1639 | 1642 |
{
|
| ... | ... |
@@ -3616,6 +3616,21 @@ larger key may offer no real guarantee of greater |
| 3616 | 3616 |
security, or may even reduce security. |
| 3617 | 3617 |
.\"********************************************************* |
| 3618 | 3618 |
.TP |
| 3619 |
+.B --prng alg [nsl] |
|
| 3620 |
+(Advanced) For PRNG (Pseudo-random number generator), |
|
| 3621 |
+use digest algorithm |
|
| 3622 |
+.B alg |
|
| 3623 |
+(default=sha1), and set |
|
| 3624 |
+.B nsl |
|
| 3625 |
+(default=16) |
|
| 3626 |
+to the size in bytes of the nonce secret length (between 16 and 64). |
|
| 3627 |
+ |
|
| 3628 |
+Set |
|
| 3629 |
+.B alg=none |
|
| 3630 |
+to disable the PRNG and use the OpenSSL RAND_bytes function |
|
| 3631 |
+instead for all of OpenVPN's pseudo-random number needs. |
|
| 3632 |
+.\"********************************************************* |
|
| 3633 |
+.TP |
|
| 3619 | 3634 |
.B --engine [engine-name] |
| 3620 | 3635 |
Enable OpenSSL hardware-based crypto engine functionality. |
| 3621 | 3636 |
|
| ... | ... |
@@ -442,6 +442,8 @@ static const char usage_message[] = |
| 442 | 442 |
"--cipher alg : Encrypt packets with cipher algorithm alg\n" |
| 443 | 443 |
" (default=%s).\n" |
| 444 | 444 |
" Set alg=none to disable encryption.\n" |
| 445 |
+ "--prng alg [nsl] : For PRNG, use digest algorithm alg, and\n" |
|
| 446 |
+ " nonce_secret_len=nsl. Set alg=none to disable PRNG.\n" |
|
| 445 | 447 |
#ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH |
| 446 | 448 |
"--keysize n : Size of cipher key in bits (optional).\n" |
| 447 | 449 |
" If unspecified, defaults to cipher-specific default.\n" |
| ... | ... |
@@ -717,6 +719,8 @@ init_options (struct options *o, const bool init_gc) |
| 717 | 717 |
o->ciphername_defined = true; |
| 718 | 718 |
o->authname = "SHA1"; |
| 719 | 719 |
o->authname_defined = true; |
| 720 |
+ o->prng_hash = "SHA1"; |
|
| 721 |
+ o->prng_nonce_secret_len = 16; |
|
| 720 | 722 |
o->replay = true; |
| 721 | 723 |
o->replay_window = DEFAULT_SEQ_BACKTRACK; |
| 722 | 724 |
o->replay_time = DEFAULT_TIME_BACKTRACK; |
| ... | ... |
@@ -1272,6 +1276,8 @@ show_settings (const struct options *o) |
| 1272 | 1272 |
SHOW_STR (ciphername); |
| 1273 | 1273 |
SHOW_BOOL (authname_defined); |
| 1274 | 1274 |
SHOW_STR (authname); |
| 1275 |
+ SHOW_STR (prng_hash); |
|
| 1276 |
+ SHOW_INT (prng_nonce_secret_len); |
|
| 1275 | 1277 |
SHOW_INT (keysize); |
| 1276 | 1278 |
SHOW_BOOL (engine); |
| 1277 | 1279 |
SHOW_BOOL (replay); |
| ... | ... |
@@ -5158,6 +5164,28 @@ add_option (struct options *options, |
| 5158 | 5158 |
VERIFY_PERMISSION (OPT_P_CRYPTO); |
| 5159 | 5159 |
options->ciphername_defined = true; |
| 5160 | 5160 |
} |
| 5161 |
+ else if (streq (p[0], "prng") && p[1]) |
|
| 5162 |
+ {
|
|
| 5163 |
+ VERIFY_PERMISSION (OPT_P_CRYPTO); |
|
| 5164 |
+ if (streq (p[1], "none")) |
|
| 5165 |
+ options->prng_hash = NULL; |
|
| 5166 |
+ else |
|
| 5167 |
+ options->prng_hash = p[1]; |
|
| 5168 |
+ if (p[2]) |
|
| 5169 |
+ {
|
|
| 5170 |
+ const int sl = atoi (p[2]); |
|
| 5171 |
+ if (sl >= NONCE_SECRET_LEN_MIN && sl <= NONCE_SECRET_LEN_MAX) |
|
| 5172 |
+ {
|
|
| 5173 |
+ options->prng_nonce_secret_len = sl; |
|
| 5174 |
+ } |
|
| 5175 |
+ else |
|
| 5176 |
+ {
|
|
| 5177 |
+ msg (msglevel, "prng parameter nonce_secret_len must be between %d and %d", |
|
| 5178 |
+ NONCE_SECRET_LEN_MIN, NONCE_SECRET_LEN_MAX); |
|
| 5179 |
+ goto err; |
|
| 5180 |
+ } |
|
| 5181 |
+ } |
|
| 5182 |
+ } |
|
| 5161 | 5183 |
else if (streq (p[0], "no-replay")) |
| 5162 | 5184 |
{
|
| 5163 | 5185 |
VERIFY_PERMISSION (OPT_P_CRYPTO); |