In preparation for AEAD cipher modes, which will need the same
functionality.

Should not change any behaviour.

Signed-off-by: Steffan Karger <stef...@karger.me>
---
 src/openvpn/crypto.c | 52 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
index e92125e..9c0c353 100644
--- a/src/openvpn/crypto.c
+++ b/src/openvpn/crypto.c
@@ -232,6 +232,41 @@ err:
   return;
 }

+/**
+ * Check packet ID for replay, and perform replay administration.
+ *
+ * @param opt  Crypto options for this packet, contains replay state.
+ * @param pin  Packet ID read from packet.
+ * @param error_prefix Prefix to use when printing error messages.
+ * @param gc   Garbage collector to use.
+ *
+ * @return true if packet ID is validated to be not a replay, false otherwise.
+ */
+static bool crypto_check_replay(struct crypto_options *opt,
+    const struct packet_id_net *pin, const char *error_prefix,
+    struct gc_arena *gc) {
+  bool ret = false;
+  packet_id_reap_test (&opt->packet_id.rec);
+  if (packet_id_test (&opt->packet_id.rec, pin))
+    {
+      packet_id_add (&opt->packet_id.rec, pin);
+      if (opt->pid_persist && (opt->flags & CO_PACKET_ID_LONG_FORM))
+       packet_id_persist_save_obj (opt->pid_persist, &opt->packet_id);
+      ret = true;
+    }
+  else
+    {
+      if (!(opt->flags & CO_MUTE_REPLAY_WARNINGS))
+       {
+         msg (D_REPLAY_ERRORS, "%s: bad packet ID (may be a replay): %s -- "
+             "see the man page entry for --no-replay and --replay-window for "
+             "more info or silence this warning with --mute-replay-warnings",
+             error_prefix, packet_id_net_print (pin, true, gc));
+       }
+    }
+  return ret;
+}
+
 /*
  * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet.
  *
@@ -373,22 +408,9 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
            }
        }

-      if (have_pin)
+      if (have_pin && !crypto_check_replay(opt, &pin, error_prefix, &gc))
        {
-         packet_id_reap_test (&opt->packet_id.rec);
-         if (packet_id_test (&opt->packet_id.rec, &pin))
-           {
-             packet_id_add (&opt->packet_id.rec, &pin);
-             if (opt->pid_persist && (opt->flags & CO_PACKET_ID_LONG_FORM))
-               packet_id_persist_save_obj (opt->pid_persist, &opt->packet_id);
-           }
-         else
-           {
-             if (!(opt->flags & CO_MUTE_REPLAY_WARNINGS))
-             msg (D_REPLAY_ERRORS, "%s: bad packet ID (may be a replay): %s -- 
see the man page entry for --no-replay and --replay-window for more info or 
silence this warning with --mute-replay-warnings",
-                  error_prefix, packet_id_net_print (&pin, true, &gc));
-             goto error_exit;
-           }
+         goto error_exit;
        }
       *buf = work;
     }
-- 
2.5.0


Reply via email to