Browse code

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

james authored on 2008/11/18 10:25:05
Showing 9 changed files
... ...
@@ -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);
... ...
@@ -418,6 +418,8 @@ struct options
418 418
   bool authname_defined;
419 419
   const char *authname;
420 420
   int keysize;
421
+  const char *prng_hash;
422
+  int prng_nonce_secret_len;
421 423
   const char *engine;
422 424
   bool replay;
423 425
   bool mute_replay_warnings;
... ...
@@ -793,7 +793,7 @@ port_share_open (const char *host, const int port)
793 793
       set_nonblock (fd[1]);
794 794
 
795 795
       /* initialize prng */
796
-      prng_init ();
796
+      prng_init (NULL, 0);
797 797
 
798 798
       /* execute the event loop */
799 799
       port_share_proxy (hostaddr, port, fd[1]);
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1_rc14])
2
+define(PRODUCT_VERSION,[2.1_rc14a])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])