diff src/crypt_zip.c @ 6122:18ac55444b37 v7.4.399

updated for version 7.4.399 Problem: Encryption implementation is messy. Blowfish encryption has a weakness. Solution: Refactor the encryption, store the state in an allocated struct instead of using a save/restore mechanism. Introduce the "blowfish2" method, which does not have the weakness and encrypts the whole undo file. (largely by David Leadbeater)
author Bram Moolenaar <bram@vim.org>
date Sun, 10 Aug 2014 13:38:34 +0200
parents
children af3c41a3c53f
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/crypt_zip.c
@@ -0,0 +1,158 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved	by Bram Moolenaar
+ *
+ * Do ":help uganda"  in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * crypt_zip.c: Zip encryption support.
+ */
+#include "vim.h"
+
+#if defined(FEAT_CRYPT) || defined(PROTO)
+/*
+ * Optional encryption support.
+ * Mohsin Ahmed, mosh@sasi.com, 98-09-24
+ * Based on zip/crypt sources.
+ *
+ * NOTE FOR USA: Since 2000 exporting this code from the USA is allowed to
+ * most countries.  There are a few exceptions, but that still should not be a
+ * problem since this code was originally created in Europe and India.
+ */
+
+/* Need a type that should be 32 bits. 64 also works but wastes space. */
+# if VIM_SIZEOF_INT >= 4
+typedef unsigned int u32_T;	/* int is at least 32 bits */
+# else
+typedef unsigned long u32_T;	/* long should be 32 bits or more */
+# endif
+
+/* The state of encryption, referenced by cryptstate_T. */
+typedef struct {
+    u32_T keys[3];
+} zip_state_T;
+
+
+static void make_crc_tab __ARGS((void));
+
+static u32_T crc_32_table[256];
+
+/*
+ * Fill the CRC table, if not done already.
+ */
+    static void
+make_crc_tab()
+{
+    u32_T	s, t, v;
+    static int	done = FALSE;
+
+    if (done)
+	return;
+    for (t = 0; t < 256; t++)
+    {
+	v = t;
+	for (s = 0; s < 8; s++)
+	    v = (v >> 1) ^ ((v & 1) * (u32_T)0xedb88320L);
+	crc_32_table[t] = v;
+    }
+    done = TRUE;
+}
+
+#define CRC32(c, b) (crc_32_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
+
+/*
+ * Return the next byte in the pseudo-random sequence.
+ */
+#define DECRYPT_BYTE_ZIP(keys, t) { \
+    short_u temp = (short_u)keys[2] | 2; \
+    t = (int)(((unsigned)(temp * (temp ^ 1U)) >> 8) & 0xff); \
+}
+
+/*
+ * Update the encryption keys with the next byte of plain text.
+ */
+#define UPDATE_KEYS_ZIP(keys, c) { \
+    keys[0] = CRC32(keys[0], (c)); \
+    keys[1] += keys[0] & 0xff; \
+    keys[1] = keys[1] * 134775813L + 1; \
+    keys[2] = CRC32(keys[2], (int)(keys[1] >> 24)); \
+}
+
+/*
+ * Initialize for encryption/decryption.
+ */
+    void
+crypt_zip_init(state, key, salt, salt_len, seed, seed_len)
+    cryptstate_T    *state;
+    char_u	    *key;
+    char_u	    *salt UNUSED;
+    int		    salt_len UNUSED;
+    char_u	    *seed UNUSED;
+    int		    seed_len UNUSED;
+{
+    char_u	*p;
+    zip_state_T	*zs;
+
+    zs = (zip_state_T *)alloc(sizeof(zip_state_T));
+    state->method_state = zs;
+
+    make_crc_tab();
+    zs->keys[0] = 305419896L;
+    zs->keys[1] = 591751049L;
+    zs->keys[2] = 878082192L;
+    for (p = key; *p != NUL; ++p)
+    {
+	UPDATE_KEYS_ZIP(zs->keys, (int)*p);
+    }
+}
+
+/*
+ * Encrypt "from[len]" into "to[len]".
+ * "from" and "to" can be equal to encrypt in place.
+ */
+    void
+crypt_zip_encode(state, from, len, to)
+    cryptstate_T *state;
+    char_u	*from;
+    size_t	len;
+    char_u	*to;
+{
+    zip_state_T *zs = state->method_state;
+    size_t	i;
+    int		ztemp, t;
+
+    for (i = 0; i < len; ++i)
+    {
+	ztemp = from[i];
+	DECRYPT_BYTE_ZIP(zs->keys, t);
+	UPDATE_KEYS_ZIP(zs->keys, ztemp);
+	to[i] = t ^ ztemp;
+    }
+}
+
+/*
+ * Decrypt "from[len]" into "to[len]".
+ */
+    void
+crypt_zip_decode(state, from, len, to)
+    cryptstate_T *state;
+    char_u	*from;
+    size_t	len;
+    char_u	*to;
+{
+    zip_state_T *zs = state->method_state;
+    size_t	i;
+    short_u	temp;
+
+    for (i = 0; i < len; ++i)
+    {
+	temp = (short_u)zs->keys[2] | 2;
+	temp = (int)(((unsigned)(temp * (temp ^ 1U)) >> 8) & 0xff);
+	UPDATE_KEYS_ZIP(zs->keys, to[i] = from[i] ^ temp);
+    }
+}
+
+#endif /* FEAT_CRYPT */