File openvpn-fips140-2.3.2.patch of Package openvpn

diff -urNp openvpn-2.3.2.orig/src/openvpn/crypto_backend.h openvpn-2.3.2/src/openvpn/crypto_backend.h
--- openvpn-2.3.2.orig/src/openvpn/crypto_backend.h	2013-08-13 03:24:16.465313821 +0200
+++ openvpn-2.3.2/src/openvpn/crypto_backend.h	2013-08-13 05:55:40.914256287 +0200
@@ -452,10 +452,11 @@ void md_ctx_final (md_ctx_t *ctx, uint8_
  * @param key		The key to use for the HMAC
  * @param key_len	The key length to use
  * @param kt 		Static message digest parameters
+ * @param prf_use	Intended use for PRF in TLS protocol
  *
  */
 void hmac_ctx_init (hmac_ctx_t *ctx, const uint8_t *key, int key_length,
-    const md_kt_t *kt);
+    const md_kt_t *kt, bool prf_use);
 
 /*
  * Free the given HMAC context.
diff -urNp openvpn-2.3.2.orig/src/openvpn/crypto.c openvpn-2.3.2/src/openvpn/crypto.c
--- openvpn-2.3.2.orig/src/openvpn/crypto.c	2013-08-13 03:24:16.466313824 +0200
+++ openvpn-2.3.2/src/openvpn/crypto.c	2013-08-13 05:54:09.655008218 +0200
@@ -486,7 +486,7 @@ init_key_ctx (struct key_ctx *ctx, struc
   if (kt->digest && kt->hmac_length > 0)
     {
       ALLOC_OBJ(ctx->hmac, hmac_ctx_t);
-      hmac_ctx_init (ctx->hmac, key->hmac, kt->hmac_length, kt->digest);
+      hmac_ctx_init (ctx->hmac, key->hmac, kt->hmac_length, kt->digest, 0);
 
       msg (D_HANDSHAKE,
       "%s: Using %d bit message hash '%s' for HMAC authentication",
@@ -1409,61 +1409,61 @@ free_ssl_lib (void)
 #endif /* ENABLE_SSL */
 
 /*
- * md5 functions
+ * sha1 functions
  */
 
 const char *
-md5sum (uint8_t *buf, int len, int n_print_chars, struct gc_arena *gc)
+sha1sum (uint8_t *buf, int len, int n_print_chars, struct gc_arena *gc)
 {
-  uint8_t digest[MD5_DIGEST_LENGTH];
-  const md_kt_t *md5_kt = md_kt_get("MD5");
+  uint8_t digest[SHA_DIGEST_LENGTH];
+  const md_kt_t *sha1_kt = md_kt_get("SHA1");
 
-  md_full(md5_kt, buf, len, digest);
+  md_full(sha1_kt, buf, len, digest);
 
-  return format_hex (digest, MD5_DIGEST_LENGTH, n_print_chars, gc);
+  return format_hex (digest, SHA_DIGEST_LENGTH, n_print_chars, gc);
 }
 
 void
-md5_state_init (struct md5_state *s)
+sha1_state_init (struct sha1_state *s)
 {
-  const md_kt_t *md5_kt = md_kt_get("MD5");
+  const md_kt_t *sha1_kt = md_kt_get("SHA1");
 
-  md_ctx_init(&s->ctx, md5_kt);
+  md_ctx_init(&s->ctx, sha1_kt);
 }
 
 void
-md5_state_update (struct md5_state *s, void *data, size_t len)
+sha1_state_update (struct sha1_state *s, void *data, size_t len)
 {
   md_ctx_update(&s->ctx, data, len);
 }
 
 void
-md5_state_final (struct md5_state *s, struct md5_digest *out)
+sha1_state_final (struct sha1_state *s, struct sha1_digest *out)
 {
   md_ctx_final(&s->ctx, out->digest);
   md_ctx_cleanup(&s->ctx);
 }
 
 void
-md5_digest_clear (struct md5_digest *digest)
+sha1_digest_clear (struct sha1_digest *digest)
 {
   CLEAR (*digest);
 }
 
 bool
-md5_digest_defined (const struct md5_digest *digest)
+sha1_digest_defined (const struct sha1_digest *digest)
 {
   int i;
-  for (i = 0; i < MD5_DIGEST_LENGTH; ++i)
+  for (i = 0; i < SHA_DIGEST_LENGTH; ++i)
     if (digest->digest[i])
       return true;
   return false;
 }
 
 bool
-md5_digest_equal (const struct md5_digest *d1, const struct md5_digest *d2)
+sha1_digest_equal (const struct sha1_digest *d1, const struct sha1_digest *d2)
 {
-  return memcmp(d1->digest, d2->digest, MD5_DIGEST_LENGTH) == 0;
+  return memcmp(d1->digest, d2->digest, SHA_DIGEST_LENGTH) == 0;
 }
 
 #endif /* ENABLE_CRYPTO */
diff -urNp openvpn-2.3.2.orig/src/openvpn/crypto.h openvpn-2.3.2/src/openvpn/crypto.h
--- openvpn-2.3.2.orig/src/openvpn/crypto.h	2013-08-13 03:24:16.459313788 +0200
+++ openvpn-2.3.2/src/openvpn/crypto.h	2013-08-13 05:54:09.656008193 +0200
@@ -364,24 +364,24 @@ void free_ssl_lib (void);
 #endif /* ENABLE_SSL */
 
 /*
- * md5 functions
+ * sha1 functions
  */
 
-struct md5_state {
+struct sha1_state {
   md_ctx_t ctx;
 };
 
-struct md5_digest {
+struct sha1_digest {
   uint8_t digest [MD5_DIGEST_LENGTH];
 };
 
-const char *md5sum(uint8_t *buf, int len, int n_print_chars, struct gc_arena *gc);
-void md5_state_init (struct md5_state *s);
-void md5_state_update (struct md5_state *s, void *data, size_t len);
-void md5_state_final (struct md5_state *s, struct md5_digest *out);
-void md5_digest_clear (struct md5_digest *digest);
-bool md5_digest_defined (const struct md5_digest *digest);
-bool md5_digest_equal (const struct md5_digest *d1, const struct md5_digest *d2);
+const char *sha1sum(uint8_t *buf, int len, int n_print_chars, struct gc_arena *gc);
+void sha1_state_init (struct sha1_state *s);
+void sha1_state_update (struct sha1_state *s, void *data, size_t len);
+void sha1_state_final (struct sha1_state *s, struct sha1_digest *out);
+void sha1_digest_clear (struct sha1_digest *digest);
+bool sha1_digest_defined (const struct sha1_digest *digest);
+bool sha1_digest_equal (const struct sha1_digest *d1, const struct sha1_digest *d2);
 
 /*
  * Inline functions
diff -urNp openvpn-2.3.2.orig/src/openvpn/crypto_openssl.c openvpn-2.3.2/src/openvpn/crypto_openssl.c
--- openvpn-2.3.2.orig/src/openvpn/crypto_openssl.c	2013-08-13 03:24:16.462313808 +0200
+++ openvpn-2.3.2/src/openvpn/crypto_openssl.c	2013-08-13 05:56:06.930326789 +0200
@@ -719,13 +719,17 @@ md_ctx_final (EVP_MD_CTX *ctx, uint8_t *
 
 void
 hmac_ctx_init (HMAC_CTX *ctx, const uint8_t *key, int key_len,
-    const EVP_MD *kt)
+    const EVP_MD *kt, bool prf_use)
 {
   ASSERT(NULL != kt && NULL != ctx);
 
   CLEAR(*ctx);
 
   HMAC_CTX_init (ctx);
+  /* FIPS 140-2 explicitly allows MD5 for the use in PRF although it is not
+   * to be used anywhere else */
+  if(kt == EVP_md5() && prf_use)
+    HMAC_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   HMAC_Init_ex (ctx, key, key_len, kt, NULL);
 
   /* make sure we used a big enough key */
diff -urNp openvpn-2.3.2.orig/src/openvpn/crypto_openssl.h openvpn-2.3.2/src/openvpn/crypto_openssl.h
--- openvpn-2.3.2.orig/src/openvpn/crypto_openssl.h	2013-08-13 03:24:16.465313821 +0200
+++ openvpn-2.3.2/src/openvpn/crypto_openssl.h	2013-08-13 05:54:09.656008193 +0200
@@ -33,6 +33,7 @@
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
+#include <openssl/sha.h>
 
 /** Generic cipher key type %context. */
 typedef EVP_CIPHER cipher_kt_t;
diff -urNp openvpn-2.3.2.orig/src/openvpn/crypto_polarssl.c openvpn-2.3.2/src/openvpn/crypto_polarssl.c
--- openvpn-2.3.2.orig/src/openvpn/crypto_polarssl.c	2013-08-13 03:24:16.460313793 +0200
+++ openvpn-2.3.2/src/openvpn/crypto_polarssl.c	2013-08-13 05:56:23.116370864 +0200
@@ -608,7 +608,7 @@ md_ctx_final (md_context_t *ctx, uint8_t
  * TODO: re-enable dmsg for crypto debug
  */
 void
-hmac_ctx_init (md_context_t *ctx, const uint8_t *key, int key_len, const md_info_t *kt)
+hmac_ctx_init (md_context_t *ctx, const uint8_t *key, int key_len, const md_info_t *kt, bool prf_use)
 {
   ASSERT(NULL != kt && NULL != ctx);
 
diff -urNp openvpn-2.3.2.orig/src/openvpn/init.c openvpn-2.3.2/src/openvpn/init.c
--- openvpn-2.3.2.orig/src/openvpn/init.c	2013-08-13 03:24:16.465313821 +0200
+++ openvpn-2.3.2/src/openvpn/init.c	2013-08-13 05:54:09.658008149 +0200
@@ -1352,12 +1352,12 @@ do_route (const struct options *options,
  */
 #if P2MP
 static void
-save_pulled_options_digest (struct context *c, const struct md5_digest *newdigest)
+save_pulled_options_digest (struct context *c, const struct sha1_digest *newdigest)
 {
   if (newdigest)
     c->c1.pulled_options_digest_save = *newdigest;
   else
-    md5_digest_clear (&c->c1.pulled_options_digest_save);
+    sha1_digest_clear (&c->c1.pulled_options_digest_save);
 }
 #endif
 
@@ -1649,8 +1649,8 @@ do_up (struct context *c, bool pulled_op
 	  if (!c->c2.did_open_tun
 	      && PULL_DEFINED (&c->options)
 	      && c->c1.tuntap
-	      && (!md5_digest_defined (&c->c1.pulled_options_digest_save) || !md5_digest_defined (&c->c2.pulled_options_digest)
-		  || !md5_digest_equal (&c->c1.pulled_options_digest_save, &c->c2.pulled_options_digest)))
+	      && (!sha1_digest_defined (&c->c1.pulled_options_digest_save) || !sha1_digest_defined (&c->c2.pulled_options_digest)
+		  || !sha1_digest_equal (&c->c1.pulled_options_digest_save, &c->c2.pulled_options_digest)))
 	    {
 	      /* if so, close tun, delete routes, then reinitialize tun and add routes */
 	      msg (M_INFO, "NOTE: Pulled options changed on restart, will need to close and reopen TUN/TAP device.");
@@ -2697,11 +2697,11 @@ do_compute_occ_strings (struct context *
 #ifdef ENABLE_CRYPTO
   msg (D_SHOW_OCC_HASH, "Local Options hash (VER=%s): '%s'",
        options_string_version (c->c2.options_string_local, &gc),
-       md5sum ((uint8_t*)c->c2.options_string_local,
+       sha1sum ((uint8_t*)c->c2.options_string_local,
 	       strlen (c->c2.options_string_local), 9, &gc));
   msg (D_SHOW_OCC_HASH, "Expected Remote Options hash (VER=%s): '%s'",
        options_string_version (c->c2.options_string_remote, &gc),
-       md5sum ((uint8_t*)c->c2.options_string_remote,
+       sha1sum ((uint8_t*)c->c2.options_string_remote,
 	       strlen (c->c2.options_string_remote), 9, &gc));
 #endif
 
diff -urNp openvpn-2.3.2.orig/src/openvpn/ntlm.c openvpn-2.3.2/src/openvpn/ntlm.c
--- openvpn-2.3.2.orig/src/openvpn/ntlm.c	2013-08-13 03:24:16.460313793 +0200
+++ openvpn-2.3.2/src/openvpn/ntlm.c	2013-08-13 05:54:09.658008149 +0200
@@ -90,7 +90,7 @@ gen_hmac_md5 (const char* data, int data
 	hmac_ctx_t hmac_ctx;
 	CLEAR(hmac_ctx);
 
-	hmac_ctx_init(&hmac_ctx, key, key_len, md5_kt);
+	hmac_ctx_init(&hmac_ctx, key, key_len, md5_kt, 0);
 	hmac_ctx_update(&hmac_ctx, (const unsigned char *)data, data_len);
 	hmac_ctx_final(&hmac_ctx, (unsigned char *)result);
 	hmac_ctx_cleanup(&hmac_ctx);
diff -urNp openvpn-2.3.2.orig/src/openvpn/openvpn.h openvpn-2.3.2/src/openvpn/openvpn.h
--- openvpn-2.3.2.orig/src/openvpn/openvpn.h	2013-08-13 03:24:16.465313821 +0200
+++ openvpn-2.3.2/src/openvpn/openvpn.h	2013-08-13 05:54:09.658008149 +0200
@@ -206,7 +206,7 @@ struct context_1
 #endif
 
   /* if client mode, hash of option strings we pulled from server */
-  struct md5_digest pulled_options_digest_save;
+  struct sha1_digest pulled_options_digest_save;
                                 /**< Hash of option strings received from the
                                  *   remote OpenVPN server.  Only used in
                                  *   client-mode. */
@@ -474,9 +474,9 @@ struct context_2
   bool did_pre_pull_restore;
 
   /* hash of pulled options, so we can compare when options change */
-  bool pulled_options_md5_init_done;
-  struct md5_state pulled_options_state;
-  struct md5_digest pulled_options_digest;
+  bool pulled_options_sha1_init_done;
+  struct sha1_state pulled_options_state;
+  struct sha1_digest pulled_options_digest;
 
   struct event_timeout server_poll_interval;
 
diff -urNp openvpn-2.3.2.orig/src/openvpn/push.c openvpn-2.3.2/src/openvpn/push.c
--- openvpn-2.3.2.orig/src/openvpn/push.c	2013-08-13 03:24:16.459313788 +0200
+++ openvpn-2.3.2/src/openvpn/push.c	2013-08-13 05:54:09.659008129 +0200
@@ -446,10 +446,10 @@ process_incoming_push_msg (struct contex
       if (ch == ',')
 	{
 	  struct buffer buf_orig = buf;
-	  if (!c->c2.pulled_options_md5_init_done)
+	  if (!c->c2.pulled_options_sha1_init_done)
 	    {
-	      md5_state_init (&c->c2.pulled_options_state);
-	      c->c2.pulled_options_md5_init_done = true;
+	      sha1_state_init (&c->c2.pulled_options_state);
+	      c->c2.pulled_options_sha1_init_done = true;
 	    }
 	  if (!c->c2.did_pre_pull_restore)
 	    {
@@ -465,13 +465,13 @@ process_incoming_push_msg (struct contex
 	      {
 	      case 0:
 	      case 1:
-		md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
-		md5_state_final (&c->c2.pulled_options_state, &c->c2.pulled_options_digest);
-	        c->c2.pulled_options_md5_init_done = false;
+		sha1_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
+		sha1_state_final (&c->c2.pulled_options_state, &c->c2.pulled_options_digest);
+	        c->c2.pulled_options_sha1_init_done = false;
 		ret = PUSH_MSG_REPLY;
 		break;
 	      case 2:
-		md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
+		sha1_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
 		ret = PUSH_MSG_CONTINUATION;
 		break;
 	      }
diff -urNp openvpn-2.3.2.orig/src/openvpn/ssl.c openvpn-2.3.2/src/openvpn/ssl.c
--- openvpn-2.3.2.orig/src/openvpn/ssl.c	2013-08-13 03:24:16.459313788 +0200
+++ openvpn-2.3.2/src/openvpn/ssl.c	2013-08-13 05:54:09.660008110 +0200
@@ -1342,8 +1342,8 @@ tls1_P_hash(const md_kt_t *md_kt,
   chunk = md_kt_size(md_kt);
   A1_len = md_kt_size(md_kt);
 
-  hmac_ctx_init(&ctx, sec, sec_len, md_kt);
-  hmac_ctx_init(&ctx_tmp, sec, sec_len, md_kt);
+  hmac_ctx_init(&ctx, sec, sec_len, md_kt, 1);
+  hmac_ctx_init(&ctx_tmp, sec, sec_len, md_kt, 1);
 
   hmac_ctx_update(&ctx,seed,seed_len);
   hmac_ctx_final(&ctx, A1);