diff src/misc2.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 ef83b423ebf7
children 63121fdd093f
line wrap: on
line diff
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -3803,322 +3803,6 @@ update_mouseshape(shape_idx)
 #endif /* CURSOR_SHAPE */
 
 
-#ifdef FEAT_CRYPT
-/*
- * 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.
- *
- * Blowfish addition originally made by Mohsin Ahmed,
- * http://www.cs.albany.edu/~mosh 2010-03-14
- * Based on blowfish by Bruce Schneier (http://www.schneier.com/blowfish.html)
- * and sha256 by Christophe Devine.
- */
-
-/* from zip.h */
-
-typedef unsigned short ush;	/* unsigned 16-bit value */
-typedef unsigned long  ulg;	/* unsigned 32-bit value */
-
-static void make_crc_tab __ARGS((void));
-
-static ulg crc_32_tab[256];
-
-/*
- * Fill the CRC table.
- */
-    static void
-make_crc_tab()
-{
-    ulg		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) * (ulg)0xedb88320L);
-	crc_32_tab[t] = v;
-    }
-    done = TRUE;
-}
-
-#define CRC32(c, b) (crc_32_tab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
-
-static ulg keys[3]; /* keys defining the pseudo-random sequence */
-
-/*
- * Return the next byte in the pseudo-random sequence.
- */
-#define DECRYPT_BYTE_ZIP(t) { \
-    ush temp; \
- \
-    temp = (ush)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(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)); \
-}
-
-static int crypt_busy = 0;
-static ulg saved_keys[3];
-static int saved_crypt_method;
-
-/*
- * Return int value for crypt method string:
- * 0 for "zip", the old method.  Also for any non-valid value.
- * 1 for "blowfish".
- */
-    int
-crypt_method_from_string(s)
-    char_u  *s;
-{
-    return *s == 'b' ? 1 : 0;
-}
-
-/*
- * Get the crypt method for buffer "buf" as a number.
- */
-    int
-get_crypt_method(buf)
-    buf_T *buf;
-{
-    return crypt_method_from_string(*buf->b_p_cm == NUL ? p_cm : buf->b_p_cm);
-}
-
-/*
- * Set the crypt method for buffer "buf" to "method" using the int value as
- * returned by crypt_method_from_string().
- */
-    void
-set_crypt_method(buf, method)
-    buf_T   *buf;
-    int	    method;
-{
-    free_string_option(buf->b_p_cm);
-    buf->b_p_cm = vim_strsave((char_u *)(method == 0 ? "zip" : "blowfish"));
-}
-
-/*
- * Prepare for initializing encryption.  If already doing encryption then save
- * the state.
- * Must always be called symmetrically with crypt_pop_state().
- */
-    void
-crypt_push_state()
-{
-    if (crypt_busy == 1)
-    {
-	/* save the state */
-	if (use_crypt_method == 0)
-	{
-	    saved_keys[0] = keys[0];
-	    saved_keys[1] = keys[1];
-	    saved_keys[2] = keys[2];
-	}
-	else
-	    bf_crypt_save();
-	saved_crypt_method = use_crypt_method;
-    }
-    else if (crypt_busy > 1)
-	EMSG2(_(e_intern2), "crypt_push_state()");
-    ++crypt_busy;
-}
-
-/*
- * End encryption.  If doing encryption before crypt_push_state() then restore
- * the saved state.
- * Must always be called symmetrically with crypt_push_state().
- */
-    void
-crypt_pop_state()
-{
-    --crypt_busy;
-    if (crypt_busy == 1)
-    {
-	use_crypt_method = saved_crypt_method;
-	if (use_crypt_method == 0)
-	{
-	    keys[0] = saved_keys[0];
-	    keys[1] = saved_keys[1];
-	    keys[2] = saved_keys[2];
-	}
-	else
-	    bf_crypt_restore();
-    }
-}
-
-/*
- * Encrypt "from[len]" into "to[len]".
- * "from" and "to" can be equal to encrypt in place.
- */
-    void
-crypt_encode(from, len, to)
-    char_u	*from;
-    size_t	len;
-    char_u	*to;
-{
-    size_t	i;
-    int		ztemp, t;
-
-    if (use_crypt_method == 0)
-	for (i = 0; i < len; ++i)
-	{
-	    ztemp = from[i];
-	    DECRYPT_BYTE_ZIP(t);
-	    UPDATE_KEYS_ZIP(ztemp);
-	    to[i] = t ^ ztemp;
-	}
-    else
-	bf_crypt_encode(from, len, to);
-}
-
-/*
- * Decrypt "ptr[len]" in place.
- */
-    void
-crypt_decode(ptr, len)
-    char_u	*ptr;
-    long	len;
-{
-    char_u *p;
-
-    if (use_crypt_method == 0)
-	for (p = ptr; p < ptr + len; ++p)
-	{
-	    ush temp;
-
-	    temp = (ush)keys[2] | 2;
-	    temp = (int)(((unsigned)(temp * (temp ^ 1U)) >> 8) & 0xff);
-	    UPDATE_KEYS_ZIP(*p ^= temp);
-	}
-    else
-	bf_crypt_decode(ptr, len);
-}
-
-/*
- * Initialize the encryption keys and the random header according to
- * the given password.
- * If "passwd" is NULL or empty, don't do anything.
- */
-    void
-crypt_init_keys(passwd)
-    char_u *passwd;		/* password string with which to modify keys */
-{
-    if (passwd != NULL && *passwd != NUL)
-    {
-	if (use_crypt_method == 0)
-	{
-	    char_u *p;
-
-	    make_crc_tab();
-	    keys[0] = 305419896L;
-	    keys[1] = 591751049L;
-	    keys[2] = 878082192L;
-	    for (p = passwd; *p!= NUL; ++p)
-	    {
-		UPDATE_KEYS_ZIP((int)*p);
-	    }
-	}
-	else
-	    bf_crypt_init_keys(passwd);
-    }
-}
-
-/*
- * Free an allocated crypt key.  Clear the text to make sure it doesn't stay
- * in memory anywhere.
- */
-    void
-free_crypt_key(key)
-    char_u *key;
-{
-    char_u *p;
-
-    if (key != NULL)
-    {
-	for (p = key; *p != NUL; ++p)
-	    *p = 0;
-	vim_free(key);
-    }
-}
-
-/*
- * Ask the user for a crypt key.
- * When "store" is TRUE, the new key is stored in the 'key' option, and the
- * 'key' option value is returned: Don't free it.
- * When "store" is FALSE, the typed key is returned in allocated memory.
- * Returns NULL on failure.
- */
-    char_u *
-get_crypt_key(store, twice)
-    int		store;
-    int		twice;	    /* Ask for the key twice. */
-{
-    char_u	*p1, *p2 = NULL;
-    int		round;
-
-    for (round = 0; ; ++round)
-    {
-	cmdline_star = TRUE;
-	cmdline_row = msg_row;
-	p1 = getcmdline_prompt(NUL, round == 0
-		? (char_u *)_("Enter encryption key: ")
-		: (char_u *)_("Enter same key again: "), 0, EXPAND_NOTHING,
-		NULL);
-	cmdline_star = FALSE;
-
-	if (p1 == NULL)
-	    break;
-
-	if (round == twice)
-	{
-	    if (p2 != NULL && STRCMP(p1, p2) != 0)
-	    {
-		MSG(_("Keys don't match!"));
-		free_crypt_key(p1);
-		free_crypt_key(p2);
-		p2 = NULL;
-		round = -1;		/* do it again */
-		continue;
-	    }
-
-	    if (store)
-	    {
-		set_option_value((char_u *)"key", 0L, p1, OPT_LOCAL);
-		free_crypt_key(p1);
-		p1 = curbuf->b_p_key;
-	    }
-	    break;
-	}
-	p2 = p1;
-    }
-
-    /* since the user typed this, no need to wait for return */
-    if (msg_didout)
-	msg_putchar('\n');
-    need_wait_return = FALSE;
-    msg_didout = FALSE;
-
-    free_crypt_key(p2);
-    return p1;
-}
-
-#endif /* FEAT_CRYPT */
-
 /* TODO: make some #ifdef for this */
 /*--------[ file searching ]-------------------------------------------------*/
 /*
@@ -6588,8 +6272,23 @@ put_time(fd, the_time)
     FILE	*fd;
     time_t	the_time;
 {
+    char_u	buf[8];
+
+    time_to_bytes(the_time, buf);
+    fwrite(buf, (size_t)8, (size_t)1, fd);
+}
+
+/*
+ * Write time_t to "buf[8]".
+ */
+    void
+time_to_bytes(the_time, buf)
+    time_t	the_time;
+    char_u	*buf;
+{
     int		c;
     int		i;
+    int		bi = 0;
     time_t	wtime = the_time;
 
     /* time_t can be up to 8 bytes in size, more than long_u, thus we
@@ -6603,7 +6302,7 @@ put_time(fd, the_time)
     {
 	if (i + 1 > (int)sizeof(time_t))
 	    /* ">>" doesn't work well when shifting more bits than avail */
-	    putc(0, fd);
+	    buf[bi++] = 0;
 	else
 	{
 #if defined(SIZEOF_TIME_T) && SIZEOF_TIME_T > 4
@@ -6611,7 +6310,7 @@ put_time(fd, the_time)
 #else
 	    c = (int)((long_u)wtime >> (i * 8));
 #endif
-	    putc(c, fd);
+	    buf[bi++] = c;
 	}
     }
 }