diff options
author | Bram Moolenaar <Bram@vim.org> | 2014-08-10 13:38:34 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2014-08-10 13:38:34 +0200 |
commit | 8f4ac01544b44bdd906d241e4f203de7496e5ac8 (patch) | |
tree | 52ee7ff7368d7953f2baa3d7d015c539b11a345e /src/misc2.c | |
parent | 0106b4b89127b043eddf711c750364b487deb794 (diff) | |
download | vim-git-8f4ac01544b44bdd906d241e4f203de7496e5ac8.tar.gz |
updated for version 7.4.399v7.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)
Diffstat (limited to 'src/misc2.c')
-rw-r--r-- | src/misc2.c | 335 |
1 files changed, 17 insertions, 318 deletions
diff --git a/src/misc2.c b/src/misc2.c index 1a5b370ba..1f8878f67 100644 --- 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; } } } |