summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Filelist4
-rw-r--r--runtime/doc/editing.txt5
-rw-r--r--runtime/doc/options.txt15
-rw-r--r--runtime/doc/todo.txt13
-rw-r--r--src/Make_bc5.mak2
-rw-r--r--src/Make_ivc.mak2
-rw-r--r--src/Make_manx.mak4
-rw-r--r--src/Make_mvc.mak8
-rw-r--r--src/Make_sas.mak6
-rw-r--r--src/Makefile20
-rw-r--r--src/blowfish.c581
-rw-r--r--src/ex_docmd.c3
-rw-r--r--src/feature.h2
-rw-r--r--src/fileio.c107
-rw-r--r--src/globals.h4
-rw-r--r--src/main.c1
-rw-r--r--src/misc2.c52
-rw-r--r--src/option.c22
-rw-r--r--src/option.h1
-rw-r--r--src/proto.h6
-rw-r--r--src/proto/blowfish.pro7
-rw-r--r--src/proto/misc2.pro3
-rw-r--r--src/proto/sha256.pro5
-rw-r--r--src/sha256.c429
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/Make_dos.mak2
-rw-r--r--src/testdir/Make_ming.mak2
-rw-r--r--src/testdir/Makefile4
-rw-r--r--src/testdir/test71.in37
-rw-r--r--src/testdir/test71.ok6
30 files changed, 1306 insertions, 48 deletions
diff --git a/Filelist b/Filelist
index 7d2db2db5..8e80e4473 100644
--- a/Filelist
+++ b/Filelist
@@ -7,6 +7,7 @@ SRC_ALL = \
src/arabic.c \
src/arabic.h \
src/ascii.h \
+ src/blowfish.c \
src/buffer.c \
src/charset.c \
src/diff.c \
@@ -58,6 +59,7 @@ SRC_ALL = \
src/regexp.h \
src/screen.c \
src/search.c \
+ src/sha256.c \
src/structs.h \
src/spell.c \
src/syntax.c \
@@ -79,6 +81,7 @@ SRC_ALL = \
src/testdir/test49.vim \
src/testdir/test60.vim \
src/proto.h \
+ src/proto/blowfish.pro \
src/proto/buffer.pro \
src/proto/charset.pro \
src/proto/diff.pro \
@@ -116,6 +119,7 @@ SRC_ALL = \
src/proto/regexp.pro \
src/proto/screen.pro \
src/proto/search.pro \
+ src/proto/sha256.pro \
src/proto/spell.pro \
src/proto/syntax.pro \
src/proto/tag.pro \
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index 87e859f72..98d4d633e 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -1361,6 +1361,11 @@ the file is encrypted.
To disable the encryption, reset the 'key' option to an empty value: >
:set key=
+You can use the 'cryptmethod' option to select the type of encryption. Do
+this before writing the file. When reading an encrypted file it will be set
+automatically to the method used when that file was written. You can change
+'cryptmethod' before writing that file to change the method.
+
When reading a file that has been encrypted and this option is not empty, it
will be used for decryption. If the value is empty, you will be prompted to
enter the key. If you don't enter a key, the file is edited without being
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index f1785bb85..da0ef5bf9 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2049,6 +2049,19 @@ A jump table for the options with a short description can be found at |Q_op|.
with system specific functions.
+ *'cryptmethod'* *'cm'*
+'cryptmethod' number (default 0)
+ local to buffer
+ {not in Vi}
+ Method used for encryption when the buffer is written to a file:
+ 0 PkZip compatible method. A weak kind of encryption.
+ backwards compatible with Vim 7.2 and older.
+ 1 Blowfish method. Strong encryption. Not compatible
+ with Vim 7.2 and older.
+ When reading an encrypted file 'cryptmethod' will be set automatically
+ to detected method for the file being read.
+
+
*'cscopepathcomp'* *'cspc'*
'cscopepathcomp' 'cspc' number (default 0)
global
@@ -4141,7 +4154,7 @@ A jump table for the options with a short description can be found at |Q_op|.
local to buffer
{not in Vi}
The key that is used for encrypting and decrypting the current buffer.
- See |encryption|.
+ See |encryption| and 'cryptmethod'.
Careful: Do not set the key value by hand, someone might see the typed
key. Use the |:X| command. But you can make 'key' empty: >
:set key=
diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt
index 48a19c9b1..fcb6b0c0c 100644
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -30,6 +30,17 @@ be worked on, but only if you sponsor Vim development. See |sponsor|.
*known-bugs*
-------------------- Known bugs and current work -----------------------
+check blowfish.c
+check sha256.c
+Use 'cm' option only when FEAT_CRYPT is defined.
+When not full match with magic, check for head and give warning about
+unsupported crypt method.
+if 'enc' is ucs-2, does utf-8 to ucs-2 encoding always work for seed?
+
+Crypt update:
+- move bf_self_test() and sha256_self_test() elsewhere
+- Update E000 to error number.
+
Cursor positioning wrong with 0x200e character. (John Becket, 2010 May 6)
E315 when trying to change a file in FileChangedRO autocommand event.
@@ -1082,8 +1093,6 @@ restored. (Luc St-Louis)
Vim 7.3:
Patches to include:
-- Add patch for 'relativenumber' option? Markus Heidelberg, 2008 Jun 27.
- Update 2010 May 2.
- Add blowfish encryption. Openssl has an implementation. Also by Paul
Kocher (LGPL), close to original. Mohsin also has some ideas.
Take four bytes and turn them into unsigned to avoid byte-order problems.
diff --git a/src/Make_bc5.mak b/src/Make_bc5.mak
index a1d92bdd3..1373b4eb5 100644
--- a/src/Make_bc5.mak
+++ b/src/Make_bc5.mak
@@ -533,6 +533,7 @@ vimwinmain = \
!endif
vimobj = \
+ $(OBJDIR)\blowfish.obj \
$(OBJDIR)\buffer.obj \
$(OBJDIR)\charset.obj \
$(OBJDIR)\diff.obj \
@@ -567,6 +568,7 @@ vimobj = \
$(OBJDIR)\regexp.obj \
$(OBJDIR)\screen.obj \
$(OBJDIR)\search.obj \
+ $(OBJDIR)\sha256.obj \
$(OBJDIR)\spell.obj \
$(OBJDIR)\syntax.obj \
$(OBJDIR)\tag.obj \
diff --git a/src/Make_ivc.mak b/src/Make_ivc.mak
index 2d118d5a6..1b06affae 100644
--- a/src/Make_ivc.mak
+++ b/src/Make_ivc.mak
@@ -210,6 +210,7 @@ ALL : .\$(VIM).exe vimrun.exe install.exe uninstal.exe xxd/xxd.exe GvimExt/gvime
LINK32_OBJS= \
$(EXTRAS) \
+ "$(INTDIR)/blowfish.obj" \
"$(INTDIR)/buffer.obj" \
"$(INTDIR)/charset.obj" \
"$(INTDIR)/diff.obj" \
@@ -246,6 +247,7 @@ LINK32_OBJS= \
"$(INTDIR)/regexp.obj" \
"$(INTDIR)/screen.obj" \
"$(INTDIR)/search.obj" \
+ "$(INTDIR)/sha256.obj" \
"$(INTDIR)/spell.obj" \
"$(INTDIR)/syntax.obj" \
"$(INTDIR)/tag.obj" \
diff --git a/src/Make_manx.mak b/src/Make_manx.mak
index b8e7852de..c4b3bcb1d 100644
--- a/src/Make_manx.mak
+++ b/src/Make_manx.mak
@@ -124,7 +124,8 @@ OBJ = obj/buffer.o \
obj/window.o \
$(TERMLIB)
-PRO = proto/buffer.pro \
+PRO = proto/blowfish.pro \
+ proto/buffer.pro \
proto/charset.pro \
proto/diff.pro \
proto/digraph.pro \
@@ -159,6 +160,7 @@ PRO = proto/buffer.pro \
proto/regexp.pro \
proto/screen.pro \
proto/search.pro \
+ proto/sha256.pro \
proto/spell.pro \
proto/syntax.pro \
proto/tag.pro \
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index 38ced6e5c..16afb4061 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -453,6 +453,8 @@ INCL = vim.h os_win32.h ascii.h feature.h globals.h keymap.h macros.h \
$(NBDEBUG_INCL)
OBJ = \
+ $(OUTDIR)\blowfish.obj \
+ $(OUTDIR)\sha256.obj \
$(OUTDIR)\buffer.obj \
$(OUTDIR)\charset.obj \
$(OUTDIR)\diff.obj \
@@ -912,6 +914,10 @@ testclean:
$(OUTDIR)/buffer.obj: $(OUTDIR) buffer.c $(INCL)
+$(OUTDIR)/blowfish.obj: $(OUTDIR) blowfish.c $(INCL)
+
+$(OUTDIR)/sha256.obj: $(OUTDIR) sha256.c $(INCL)
+
$(OUTDIR)/charset.obj: $(OUTDIR) charset.c $(INCL)
$(OUTDIR)/diff.obj: $(OUTDIR) diff.c $(INCL)
@@ -1080,6 +1086,7 @@ auto:
# End Custom Build
proto.h: \
+ proto/blowfish.pro \
proto/buffer.pro \
proto/charset.pro \
proto/diff.pro \
@@ -1115,6 +1122,7 @@ proto.h: \
proto/regexp.pro \
proto/screen.pro \
proto/search.pro \
+ proto/sha256.pro \
proto/spell.pro \
proto/syntax.pro \
proto/tag.pro \
diff --git a/src/Make_sas.mak b/src/Make_sas.mak
index 98ec528be..7cbb888bd 100644
--- a/src/Make_sas.mak
+++ b/src/Make_sas.mak
@@ -179,6 +179,7 @@ OBJ = \
$(TERMLIB)
PRO = \
+ proto/blowfish.pro \
proto/buffer.pro \
proto/charset.pro \
proto/diff.pro \
@@ -214,6 +215,7 @@ PRO = \
proto/regexp.pro \
proto/screen.pro \
proto/search.pro \
+ proto/sha256.pro \
proto/spell.pro \
proto/syntax.pro \
proto/tag.pro \
@@ -278,6 +280,8 @@ $(PRO): $(GST) vim.h
$(CC) $(CFLAGS) GPFILE=proto/$*.pro $(PROPT) $*.c
# dependancies
+blowfish.o: blowfish.c
+proto/blowfish.pro: blowfish.c
buffer.o: buffer.c
proto/buffer.pro: buffer.c
charset.o: charset.c
@@ -348,6 +352,8 @@ screen.o: screen.c
proto/screen.pro: screen.c
search.o: search.c
proto/search.pro: search.c
+sha256.o: sha256.c
+proto/sha256.pro: sha256.c
spell.o: spell.c
proto/spell.pro: spell.c
syntax.o: syntax.c
diff --git a/src/Makefile b/src/Makefile
index f6b6e6f1f..74d6e88c4 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -468,7 +468,7 @@ CClink = $(CC)
#CONF_OPT_FEAT = --with-features=small
#CONF_OPT_FEAT = --with-features=normal
#CONF_OPT_FEAT = --with-features=big
-#CONF_OPT_FEAT = --with-features=huge
+CONF_OPT_FEAT = --with-features=huge
# COMPILED BY - For including a specific e-mail address for ":version".
#CONF_OPT_COMPBY = "--with-compiledby=John Doe <JohnDoe@yahoo.com>"
@@ -536,9 +536,9 @@ CClink = $(CC)
#CFLAGS = -g -O2 '-DSTARTUPTIME="vimstartup"' -fno-strength-reduce -Wall -Wmissing-prototypes
# Use this with GCC to check for mistakes, unused arguments, etc.
-#CFLAGS = -g -Wall -Wextra -Wmissing-prototypes -Wunreachable-code -D_FORTIFY_SOURCE=1
-#PYTHON_CFLAGS_EXTRA = -Wno-missing-field-initializers
-#MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code -Wno-unused-parameter
+CFLAGS = -g -Wall -Wextra -Wmissing-prototypes -Wunreachable-code -D_FORTIFY_SOURCE=1
+PYTHON_CFLAGS_EXTRA = -Wno-missing-field-initializers
+MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code -Wno-unused-parameter
# EFENCE - Electric-Fence malloc debugging: catches memory accesses beyond
# allocated memory (and makes every malloc()/free() very slow).
@@ -1377,6 +1377,7 @@ DEST_MAN_RU_U = $(DEST_MAN_TOP)/ru.UTF-8$(MAN1DIR)
TAGS_INCL = *.h
BASIC_SRC = \
+ blowfish.c \
buffer.c \
charset.c \
diff.c \
@@ -1415,6 +1416,7 @@ BASIC_SRC = \
regexp.c \
screen.c \
search.c \
+ sha256.c \
spell.c \
syntax.c \
tag.c \
@@ -1449,6 +1451,7 @@ LINT_SRC = $(BASIC_SRC) $(GUI_SRC) $(HANGULIN_SRC) $(PYTHON_SRC) $(TCL_SRC) \
OBJ = \
objects/buffer.o \
+ objects/blowfish.o \
objects/charset.o \
objects/diff.o \
objects/digraph.o \
@@ -1487,6 +1490,7 @@ OBJ = \
objects/regexp.o \
objects/screen.o \
objects/search.o \
+ objects/sha256.o \
objects/spell.o \
objects/syntax.o \
$(SNIFF_OBJ) \
@@ -1507,6 +1511,7 @@ OBJ = \
$(WSDEBUG_OBJ)
PRO_AUTO = \
+ blowfish.pro \
buffer.pro \
charset.pro \
diff.pro \
@@ -1547,6 +1552,7 @@ PRO_AUTO = \
regexp.pro \
screen.pro \
search.pro \
+ sha256.pro \
spell.pro \
syntax.pro \
tag.pro \
@@ -2337,6 +2343,9 @@ auto/pathdef.c: Makefile auto/config.mk
objects:
mkdir objects
+objects/blowfish.o: blowfish.c
+ $(CCC) -o $@ blowfish.c
+
objects/buffer.o: buffer.c
$(CCC) -o $@ buffer.c
@@ -2547,6 +2556,9 @@ objects/screen.o: screen.c
objects/search.o: search.c
$(CCC) -o $@ search.c
+objects/sha256.o: sha256.c
+ $(CCC) -o $@ sha256.c
+
objects/spell.o: spell.c
$(CCC) -o $@ spell.c
diff --git a/src/blowfish.c b/src/blowfish.c
new file mode 100644
index 000000000..f5b8e9070
--- /dev/null
+++ b/src/blowfish.c
@@ -0,0 +1,581 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * Blowfish encryption for vim; in Blowfish output feedback mode.
+ * GPL(C) Mohsin Ahmed, http://www.cs.albany.edu/~mosh
+ * Based on http://www.schneier.com/blowfish.html by Bruce Schneier.
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_CRYPT)
+
+#define ARRAY_LENGTH(A) (sizeof(A)/sizeof(A[0]))
+
+#define BF_BLOCK 8
+#define BF_OFB_LEN (8*(BF_BLOCK))
+
+typedef union {
+ long_u ul[2];
+ char_u uc[8];
+} block8;
+
+#ifdef __BORLANDC__
+# define LITTLE_ENDIAN
+#else
+# if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
+# if (('1234' >> 24) == '1')
+# define LITTLE_ENDIAN 1
+# else
+# if (('4321' >> 24) == '1')
+# define BIG_ENDIAN 1
+# endif
+# endif
+# endif
+#endif
+
+static void bf_e_block __ARGS((long_u *p_xl, long_u *p_xr));
+static void bf_e_cblock __ARGS((char_u *block));
+static int bf_check_tables __ARGS((long_u ipa[18], long_u sbi[4][256], long_u val));
+static int bf_self_test __ARGS((void));
+
+// Blowfish code
+static long_u pax[18];
+static long_u ipa[18] = {
+ 0x243f6a88u, 0x85a308d3u, 0x13198a2eu,
+ 0x03707344u, 0xa4093822u, 0x299f31d0u,
+ 0x082efa98u, 0xec4e6c89u, 0x452821e6u,
+ 0x38d01377u, 0xbe5466cfu, 0x34e90c6cu,
+ 0xc0ac29b7u, 0xc97c50ddu, 0x3f84d5b5u,
+ 0xb5470917u, 0x9216d5d9u, 0x8979fb1bu
+};
+
+static long_u sbx[4][256];
+static long_u sbi[4][256] = {
+ {0xd1310ba6u, 0x98dfb5acu, 0x2ffd72dbu, 0xd01adfb7u,
+ 0xb8e1afedu, 0x6a267e96u, 0xba7c9045u, 0xf12c7f99u,
+ 0x24a19947u, 0xb3916cf7u, 0x0801f2e2u, 0x858efc16u,
+ 0x636920d8u, 0x71574e69u, 0xa458fea3u, 0xf4933d7eu,
+ 0x0d95748fu, 0x728eb658u, 0x718bcd58u, 0x82154aeeu,
+ 0x7b54a41du, 0xc25a59b5u, 0x9c30d539u, 0x2af26013u,
+ 0xc5d1b023u, 0x286085f0u, 0xca417918u, 0xb8db38efu,
+ 0x8e79dcb0u, 0x603a180eu, 0x6c9e0e8bu, 0xb01e8a3eu,
+ 0xd71577c1u, 0xbd314b27u, 0x78af2fdau, 0x55605c60u,
+ 0xe65525f3u, 0xaa55ab94u, 0x57489862u, 0x63e81440u,
+ 0x55ca396au, 0x2aab10b6u, 0xb4cc5c34u, 0x1141e8ceu,
+ 0xa15486afu, 0x7c72e993u, 0xb3ee1411u, 0x636fbc2au,
+ 0x2ba9c55du, 0x741831f6u, 0xce5c3e16u, 0x9b87931eu,
+ 0xafd6ba33u, 0x6c24cf5cu, 0x7a325381u, 0x28958677u,
+ 0x3b8f4898u, 0x6b4bb9afu, 0xc4bfe81bu, 0x66282193u,
+ 0x61d809ccu, 0xfb21a991u, 0x487cac60u, 0x5dec8032u,
+ 0xef845d5du, 0xe98575b1u, 0xdc262302u, 0xeb651b88u,
+ 0x23893e81u, 0xd396acc5u, 0x0f6d6ff3u, 0x83f44239u,
+ 0x2e0b4482u, 0xa4842004u, 0x69c8f04au, 0x9e1f9b5eu,
+ 0x21c66842u, 0xf6e96c9au, 0x670c9c61u, 0xabd388f0u,
+ 0x6a51a0d2u, 0xd8542f68u, 0x960fa728u, 0xab5133a3u,
+ 0x6eef0b6cu, 0x137a3be4u, 0xba3bf050u, 0x7efb2a98u,
+ 0xa1f1651du, 0x39af0176u, 0x66ca593eu, 0x82430e88u,
+ 0x8cee8619u, 0x456f9fb4u, 0x7d84a5c3u, 0x3b8b5ebeu,
+ 0xe06f75d8u, 0x85c12073u, 0x401a449fu, 0x56c16aa6u,
+ 0x4ed3aa62u, 0x363f7706u, 0x1bfedf72u, 0x429b023du,
+ 0x37d0d724u, 0xd00a1248u, 0xdb0fead3u, 0x49f1c09bu,
+ 0x075372c9u, 0x80991b7bu, 0x25d479d8u, 0xf6e8def7u,
+ 0xe3fe501au, 0xb6794c3bu, 0x976ce0bdu, 0x04c006bau,
+ 0xc1a94fb6u, 0x409f60c4u, 0x5e5c9ec2u, 0x196a2463u,
+ 0x68fb6fafu, 0x3e6c53b5u, 0x1339b2ebu, 0x3b52ec6fu,
+ 0x6dfc511fu, 0x9b30952cu, 0xcc814544u, 0xaf5ebd09u,
+ 0xbee3d004u, 0xde334afdu, 0x660f2807u, 0x192e4bb3u,
+ 0xc0cba857u, 0x45c8740fu, 0xd20b5f39u, 0xb9d3fbdbu,
+ 0x5579c0bdu, 0x1a60320au, 0xd6a100c6u, 0x402c7279u,
+ 0x679f25feu, 0xfb1fa3ccu, 0x8ea5e9f8u, 0xdb3222f8u,
+ 0x3c7516dfu, 0xfd616b15u, 0x2f501ec8u, 0xad0552abu,
+ 0x323db5fau, 0xfd238760u, 0x53317b48u, 0x3e00df82u,
+ 0x9e5c57bbu, 0xca6f8ca0u, 0x1a87562eu, 0xdf1769dbu,
+ 0xd542a8f6u, 0x287effc3u, 0xac6732c6u, 0x8c4f5573u,
+ 0x695b27b0u, 0xbbca58c8u, 0xe1ffa35du, 0xb8f011a0u,
+ 0x10fa3d98u, 0xfd2183b8u, 0x4afcb56cu, 0x2dd1d35bu,
+ 0x9a53e479u, 0xb6f84565u, 0xd28e49bcu, 0x4bfb9790u,
+ 0xe1ddf2dau, 0xa4cb7e33u, 0x62fb1341u, 0xcee4c6e8u,
+ 0xef20cadau, 0x36774c01u, 0xd07e9efeu, 0x2bf11fb4u,
+ 0x95dbda4du, 0xae909198u, 0xeaad8e71u, 0x6b93d5a0u,
+ 0xd08ed1d0u, 0xafc725e0u, 0x8e3c5b2fu, 0x8e7594b7u,
+ 0x8ff6e2fbu, 0xf2122b64u, 0x8888b812u, 0x900df01cu,
+ 0x4fad5ea0u, 0x688fc31cu, 0xd1cff191u, 0xb3a8c1adu,
+ 0x2f2f2218u, 0xbe0e1777u, 0xea752dfeu, 0x8b021fa1u,
+ 0xe5a0cc0fu, 0xb56f74e8u, 0x18acf3d6u, 0xce89e299u,
+ 0xb4a84fe0u, 0xfd13e0b7u, 0x7cc43b81u, 0xd2ada8d9u,
+ 0x165fa266u, 0x80957705u, 0x93cc7314u, 0x211a1477u,
+ 0xe6ad2065u, 0x77b5fa86u, 0xc75442f5u, 0xfb9d35cfu,
+ 0xebcdaf0cu, 0x7b3e89a0u, 0xd6411bd3u, 0xae1e7e49u,
+ 0x00250e2du, 0x2071b35eu, 0x226800bbu, 0x57b8e0afu,
+ 0x2464369bu, 0xf009b91eu, 0x5563911du, 0x59dfa6aau,
+ 0x78c14389u, 0xd95a537fu, 0x207d5ba2u, 0x02e5b9c5u,
+ 0x83260376u, 0x6295cfa9u, 0x11c81968u, 0x4e734a41u,
+ 0xb3472dcau, 0x7b14a94au, 0x1b510052u, 0x9a532915u,
+ 0xd60f573fu, 0xbc9bc6e4u, 0x2b60a476u, 0x81e67400u,
+ 0x08ba6fb5u, 0x571be91fu, 0xf296ec6bu, 0x2a0dd915u,
+ 0xb6636521u, 0xe7b9f9b6u, 0xff34052eu, 0xc5855664u,
+ 0x53b02d5du, 0xa99f8fa1u, 0x08ba4799u, 0x6e85076au},
+ {0x4b7a70e9u, 0xb5b32944u, 0xdb75092eu, 0xc4192623u,
+ 0xad6ea6b0u, 0x49a7df7du, 0x9cee60b8u, 0x8fedb266u,
+ 0xecaa8c71u, 0x699a17ffu, 0x5664526cu, 0xc2b19ee1u,
+ 0x193602a5u, 0x75094c29u, 0xa0591340u, 0xe4183a3eu,
+ 0x3f54989au, 0x5b429d65u, 0x6b8fe4d6u, 0x99f73fd6u,
+ 0xa1d29c07u, 0xefe830f5u, 0x4d2d38e6u, 0xf0255dc1u,
+ 0x4cdd2086u, 0x8470eb26u, 0x6382e9c6u, 0x021ecc5eu,
+ 0x09686b3fu, 0x3ebaefc9u, 0x3c971814u, 0x6b6a70a1u,
+ 0x687f3584u, 0x52a0e286u, 0xb79c5305u, 0xaa500737u,
+ 0x3e07841cu, 0x7fdeae5cu, 0x8e7d44ecu, 0x5716f2b8u,
+ 0xb03ada37u, 0xf0500c0du, 0xf01c1f04u, 0x0200b3ffu,
+ 0xae0cf51au, 0x3cb574b2u, 0x25837a58u, 0xdc0921bdu,
+ 0xd19113f9u, 0x7ca92ff6u, 0x94324773u, 0x22f54701u,
+ 0x3ae5e581u, 0x37c2dadcu, 0xc8b57634u, 0x9af3dda7u,
+ 0xa9446146u, 0x0fd0030eu, 0xecc8c73eu, 0xa4751e41u,
+ 0xe238cd99u, 0x3bea0e2fu, 0x3280bba1u, 0x183eb331u,
+ 0x4e548b38u, 0x4f6db908u, 0x6f420d03u, 0xf60a04bfu,
+ 0x2cb81290u, 0x24977c79u, 0x5679b072u, 0xbcaf89afu,
+ 0xde9a771fu, 0xd9930810u, 0xb38bae12u, 0xdccf3f2eu,
+ 0x5512721fu, 0x2e6b7124u, 0x501adde6u, 0x9f84cd87u,
+ 0x7a584718u, 0x7408da17u, 0xbc9f9abcu, 0xe94b7d8cu,
+ 0xec7aec3au, 0xdb851dfau, 0x63094366u, 0xc464c3d2u,
+ 0xef1c1847u, 0x3215d908u, 0xdd433b37u, 0x24c2ba16u,
+ 0x12a14d43u, 0x2a65c451u, 0x50940002u, 0x133ae4ddu,
+ 0x71dff89eu, 0x10314e55u, 0x81ac77d6u, 0x5f11199bu,
+ 0x043556f1u, 0xd7a3c76bu, 0x3c11183bu, 0x5924a509u,
+ 0xf28fe6edu, 0x97f1fbfau, 0x9ebabf2cu, 0x1e153c6eu,
+ 0x86e34570u, 0xeae96fb1u, 0x860e5e0au, 0x5a3e2ab3u,
+ 0x771fe71cu, 0x4e3d06fau, 0x2965dcb9u, 0x99e71d0fu,
+ 0x803e89d6u, 0x5266c825u, 0x2e4cc978u, 0x9c10b36au,
+ 0xc6150ebau, 0x94e2ea78u, 0xa5fc3c53u, 0x1e0a2df4u,
+ 0xf2f74ea7u, 0x361d2b3du, 0x1939260fu, 0x19c27960u,
+ 0x5223a708u, 0xf71312b6u, 0xebadfe6eu, 0xeac31f66u,
+ 0xe3bc4595u, 0xa67bc883u, 0xb17f37d1u, 0x018cff28u,
+ 0xc332ddefu, 0xbe6c5aa5u, 0x65582185u, 0x68ab9802u,
+ 0xeecea50fu, 0xdb2f953bu, 0x2aef7dadu, 0x5b6e2f84u,
+ 0x1521b628u, 0x29076170u, 0xecdd4775u, 0x619f1510u,
+ 0x13cca830u, 0xeb61bd96u, 0x0334fe1eu, 0xaa0363cfu,
+ 0xb5735c90u, 0x4c70a239u, 0xd59e9e0bu, 0xcbaade14u,
+ 0xeecc86bcu, 0x60622ca7u, 0x9cab5cabu, 0xb2f3846eu,
+ 0x648b1eafu, 0x19bdf0cau, 0xa02369b9u, 0x655abb50u,
+ 0x40685a32u, 0x3c2ab4b3u, 0x319ee9d5u, 0xc021b8f7u,
+ 0x9b540b19u, 0x875fa099u, 0x95f7997eu, 0x623d7da8u,
+ 0xf837889au, 0x97e32d77u, 0x11ed935fu, 0x16681281u,
+ 0x0e358829u, 0xc7e61fd6u, 0x96dedfa1u, 0x7858ba99u,
+ 0x57f584a5u, 0x1b227263u, 0x9b83c3ffu, 0x1ac24696u,
+ 0xcdb30aebu, 0x532e3054u, 0x8fd948e4u, 0x6dbc3128u,
+ 0x58ebf2efu, 0x34c6ffeau, 0xfe28ed61u, 0xee7c3c73u,
+ 0x5d4a14d9u, 0xe864b7e3u, 0x42105d14u, 0x203e13e0u,
+ 0x45eee2b6u, 0xa3aaabeau, 0xdb6c4f15u, 0xfacb4fd0u,
+ 0xc742f442u, 0xef6abbb5u, 0x654f3b1du, 0x41cd2105u,
+ 0xd81e799eu, 0x86854dc7u, 0xe44b476au, 0x3d816250u,
+ 0xcf62a1f2u, 0x5b8d2646u, 0xfc8883a0u, 0xc1c7b6a3u,
+ 0x7f1524c3u, 0x69cb7492u, 0x47848a0bu, 0x5692b285u,
+ 0x095bbf00u, 0xad19489du, 0x1462b174u, 0x23820e00u,
+ 0x58428d2au, 0x0c55f5eau, 0x1dadf43eu, 0x233f7061u,
+ 0x3372f092u, 0x8d937e41u, 0xd65fecf1u, 0x6c223bdbu,
+ 0x7cde3759u, 0xcbee7460u, 0x4085f2a7u, 0xce77326eu,
+ 0xa6078084u, 0x19f8509eu, 0xe8efd855u, 0x61d99735u,
+ 0xa969a7aau, 0xc50c06c2u, 0x5a04abfcu, 0x800bcadcu,
+ 0x9e447a2eu, 0xc3453484u, 0xfdd56705u, 0x0e1e9ec9u,
+ 0xdb73dbd3u, 0x105588cdu, 0x675fda79u, 0xe3674340u,
+ 0xc5c43465u, 0x713e38d8u, 0x3d28f89eu, 0xf16dff20u,
+ 0x153e21e7u, 0x8fb03d4au, 0xe6e39f2bu, 0xdb83adf7u},
+ {0xe93d5a68u, 0x948140f7u, 0xf64c261cu, 0x94692934u,
+ 0x411520f7u, 0x7602d4f7u, 0xbcf46b2eu, 0xd4a20068u,
+ 0xd4082471u, 0x3320f46au, 0x43b7d4b7u, 0x500061afu,
+ 0x1e39f62eu, 0x97244546u, 0x14214f74u, 0xbf8b8840u,
+ 0x4d95fc1du, 0x96b591afu, 0x70f4ddd3u, 0x66a02f45u,
+ 0xbfbc09ecu, 0x03bd9785u, 0x7fac6dd0u, 0x31cb8504u,
+ 0x96eb27b3u, 0x55fd3941u, 0xda2547e6u, 0xabca0a9au,
+ 0x28507825u, 0x530429f4u, 0x0a2c86dau, 0xe9b66dfbu,
+ 0x68dc1462u, 0xd7486900u, 0x680ec0a4u, 0x27a18deeu,
+ 0x4f3ffea2u, 0xe887ad8cu, 0xb58ce006u, 0x7af4d6b6u,
+ 0xaace1e7cu, 0xd3375fecu, 0xce78a399u, 0x406b2a42u,
+ 0x20fe9e35u, 0xd9f385b9u, 0xee39d7abu, 0x3b124e8bu,
+ 0x1dc9faf7u, 0x4b6d1856u, 0x26a36631u, 0xeae397b2u,
+ 0x3a6efa74u, 0xdd5b4332u, 0x6841e7f7u, 0xca7820fbu,
+ 0xfb0af54eu, 0xd8feb397u, 0x454056acu, 0xba489527u,
+ 0x55533a3au, 0x20838d87u, 0xfe6ba9b7u, 0xd096954bu,
+ 0x55a867bcu, 0xa1159a58u, 0xcca92963u, 0x99e1db33u,
+ 0xa62a4a56u, 0x3f3125f9u, 0x5ef47e1cu, 0x9029317cu,
+ 0xfdf8e802u, 0x04272f70u, 0x80bb155cu, 0x05282ce3u,
+ 0x95c11548u, 0xe4c66d22u, 0x48c1133fu, 0xc70f86dcu,
+ 0x07f9c9eeu, 0x41041f0fu, 0x404779a4u, 0x5d886e17u,
+ 0x325f51ebu, 0xd59bc0d1u, 0xf2bcc18fu, 0x41113564u,
+ 0x257b7834u, 0x602a9c60u, 0xdff8e8a3u, 0x1f636c1bu,
+ 0x0e12b4c2u, 0x02e1329eu, 0xaf664fd1u, 0xcad18115u,
+ 0x6b2395e0u, 0x333e92e1u, 0x3b240b62u, 0xeebeb922u,
+ 0x85b2a20eu, 0xe6ba0d99u, 0xde720c8cu, 0x2da2f728u,
+ 0xd0127845u, 0x95b794fdu, 0x647d0862u, 0xe7ccf5f0u,
+ 0x5449a36fu, 0x877d48fau, 0xc39dfd27u, 0xf33e8d1eu,
+ 0x0a476341u, 0x992eff74u, 0x3a6f6eabu, 0xf4f8fd37u,
+ 0xa812dc60u, 0xa1ebddf8u, 0x991be14cu, 0xdb6e6b0du,
+ 0xc67b5510u, 0x6d672c37u, 0x2765d43bu, 0xdcd0e804u,
+ 0xf1290dc7u, 0xcc00ffa3u, 0xb5390f92u, 0x690fed0bu,
+ 0x667b9ffbu, 0xcedb7d9cu, 0xa091cf0bu, 0xd9155ea3u,
+ 0xbb132f88u, 0x515bad24u, 0x7b9479bfu, 0x763bd6ebu,
+ 0x37392eb3u, 0xcc115979u, 0x8026e297u, 0xf42e312du,
+ 0x6842ada7u, 0xc66a2b3bu, 0x12754cccu, 0x782ef11cu,
+ 0x6a124237u, 0xb79251e7u, 0x06a1bbe6u, 0x4bfb6350u,
+ 0x1a6b1018u, 0x11caedfau, 0x3d25bdd8u, 0xe2e1c3c9u,
+ 0x44421659u, 0x0a121386u, 0xd90cec6eu, 0xd5abea2au,
+ 0x64af674eu, 0xda86a85fu, 0xbebfe988u, 0x64e4c3feu,
+ 0x9dbc8057u, 0xf0f7c086u, 0x60787bf8u, 0x6003604du,
+ 0xd1fd8346u, 0xf6381fb0u, 0x7745ae04u, 0xd736fcccu,
+ 0x83426b33u, 0xf01eab71u, 0xb0804187u, 0x3c005e5fu,
+ 0x77a057beu, 0xbde8ae24u, 0x55464299u, 0xbf582e61u,
+ 0x4e58f48fu, 0xf2ddfda2u, 0xf474ef38u, 0x8789bdc2u,
+ 0x5366f9c3u, 0xc8b38e74u, 0xb475f255u, 0x46fcd9b9u,
+ 0x7aeb2661u, 0x8b1ddf84u, 0x846a0e79u, 0x915f95e2u,
+ 0x466e598eu, 0x20b45770u, 0x8cd55591u, 0xc902de4cu,
+ 0xb90bace1u, 0xbb8205d0u, 0x11a86248u, 0x7574a99eu,
+ 0xb77f19b6u, 0xe0a9dc09u, 0x662d09a1u, 0xc4324633u,
+ 0xe85a1f02u, 0x09f0be8cu, 0x4a99a025u, 0x1d6efe10u,
+ 0x1ab93d1du, 0x0ba5a4dfu, 0xa186f20fu, 0x2868f169u,
+ 0xdcb7da83u, 0x573906feu, 0xa1e2ce9bu, 0x4fcd7f52u,
+ 0x50115e01u, 0xa70683fau, 0xa002b5c4u, 0x0de6d027u,
+ 0x9af88c27u, 0x773f8641u, 0xc3604c06u, 0x61a806b5u,
+ 0xf0177a28u, 0xc0f586e0u, 0x006058aau, 0x30dc7d62u,
+ 0x11e69ed7u, 0x2338ea63u, 0x53c2dd94u, 0xc2c21634u,
+ 0xbbcbee56u, 0x90bcb6deu, 0xebfc7da1u, 0xce591d76u,
+ 0x6f05e409u, 0x4b7c0188u, 0x39720a3du, 0x7c927c24u,
+ 0x86e3725fu, 0x724d9db9u, 0x1ac15bb4u, 0xd39eb8fcu,
+ 0xed545578u, 0x08fca5b5u, 0xd83d7cd3u, 0x4dad0fc4u,
+ 0x1e50ef5eu, 0xb161e6f8u, 0xa28514d9u, 0x6c51133cu,
+ 0x6fd5c7e7u, 0x56e14ec4u, 0x362abfceu, 0xddc6c837u,
+ 0xd79a3234u, 0x92638212u, 0x670efa8eu, 0x406000e0u},
+ {0x3a39ce37u, 0xd3faf5cfu, 0xabc27737u, 0x5ac52d1bu,
+ 0x5cb0679eu, 0x4fa33742u, 0xd3822740u, 0x99bc9bbeu,
+ 0xd5118e9du, 0xbf0f7315u, 0xd62d1c7eu, 0xc700c47bu,
+ 0xb78c1b6bu, 0x21a19045u, 0xb26eb1beu, 0x6a366eb4u,
+ 0x5748ab2fu, 0xbc946e79u, 0xc6a376d2u, 0x6549c2c8u,
+ 0x530ff8eeu, 0x468dde7du, 0xd5730a1du, 0x4cd04dc6u,
+ 0x2939bbdbu, 0xa9ba4650u, 0xac9526e8u, 0xbe5ee304u,
+ 0xa1fad5f0u, 0x6a2d519au, 0x63ef8ce2u, 0x9a86ee22u,
+ 0xc089c2b8u, 0x43242ef6u, 0xa51e03aau, 0x9cf2d0a4u,
+ 0x83c061bau, 0x9be96a4du, 0x8fe51550u, 0xba645bd6u,
+ 0x2826a2f9u, 0xa73a3ae1u, 0x4ba99586u, 0xef5562e9u,
+ 0xc72fefd3u, 0xf752f7dau, 0x3f046f69u, 0x77fa0a59u,
+ 0x80e4a915u, 0x87b08601u, 0x9b09e6adu, 0x3b3ee593u,
+ 0xe990fd5au, 0x9e34d797u, 0x2cf0b7d9u, 0x022b8b51u,
+ 0x96d5ac3au, 0x017da67du, 0xd1cf3ed6u, 0x7c7d2d28u,
+ 0x1f9f25cfu, 0xadf2b89bu, 0x5ad6b472u, 0x5a88f54cu,
+ 0xe029ac71u, 0xe019a5e6u, 0x47b0acfdu, 0xed93fa9bu,
+ 0xe8d3c48du, 0x283b57ccu, 0xf8d56629u, 0x79132e28u,
+ 0x785f0191u, 0xed756055u, 0xf7960e44u, 0xe3d35e8cu,
+ 0x15056dd4u, 0x88f46dbau, 0x03a16125u, 0x0564f0bdu,
+ 0xc3eb9e15u, 0x3c9057a2u, 0x97271aecu, 0xa93a072au,
+ 0x1b3f6d9bu, 0x1e6321f5u, 0xf59c66fbu, 0x26dcf319u,
+ 0x7533d928u, 0xb155fdf5u, 0x03563482u, 0x8aba3cbbu,
+ 0x28517711u, 0xc20ad9f8u, 0xabcc5167u, 0xccad925fu,
+ 0x4de81751u, 0x3830dc8eu, 0x379d5862u, 0x9320f991u,
+ 0xea7a90c2u, 0xfb3e7bceu, 0x5121ce64u, 0x774fbe32u,
+ 0xa8b6e37eu, 0xc3293d46u, 0x48de5369u, 0x6413e680u,
+ 0xa2ae0810u, 0xdd6db224u, 0x69852dfdu, 0x09072166u,
+ 0xb39a460au, 0x6445c0ddu, 0x586cdecfu, 0x1c20c8aeu,
+ 0x5bbef7ddu, 0x1b588d40u, 0xccd2017fu, 0x6bb4e3bbu,
+ 0xdda26a7eu, 0x3a59ff45u, 0x3e350a44u, 0xbcb4cdd5u,
+ 0x72eacea8u, 0xfa6484bbu, 0x8d6612aeu, 0xbf3c6f47u,
+ 0xd29be463u, 0x542f5d9eu, 0xaec2771bu, 0xf64e6370u,
+ 0x740e0d8du, 0xe75b1357u, 0xf8721671u, 0xaf537d5du,
+ 0x4040cb08u, 0x4eb4e2ccu, 0x34d2466au, 0x0115af84u,
+ 0xe1b00428u, 0x95983a1du, 0x06b89fb4u, 0xce6ea048u,
+ 0x6f3f3b82u, 0x3520ab82u, 0x011a1d4bu, 0x277227f8u,
+ 0x611560b1u, 0xe7933fdcu, 0xbb3a792bu, 0x344525bdu,
+ 0xa08839e1u, 0x51ce794bu, 0x2f32c9b7u, 0xa01fbac9u,
+ 0xe01cc87eu, 0xbcc7d1f6u, 0xcf0111c3u, 0xa1e8aac7u,
+ 0x1a908749u, 0xd44fbd9au, 0xd0dadecbu, 0xd50ada38u,
+ 0x0339c32au, 0xc6913667u, 0x8df9317cu, 0xe0b12b4fu,
+ 0xf79e59b7u, 0x43f5bb3au, 0xf2d519ffu, 0x27d9459cu,
+ 0xbf97222cu, 0x15e6fc2au, 0x0f91fc71u, 0x9b941525u,
+ 0xfae59361u, 0xceb69cebu, 0xc2a86459u, 0x12baa8d1u,
+ 0xb6c1075eu, 0xe3056a0cu, 0x10d25065u, 0xcb03a442u,
+ 0xe0ec6e0eu, 0x1698db3bu, 0x4c98a0beu, 0x3278e964u,
+ 0x9f1f9532u, 0xe0d392dfu, 0xd3a0342bu, 0x8971f21eu,
+ 0x1b0a7441u, 0x4ba3348cu, 0xc5be7120u, 0xc37632d8u,
+ 0xdf359f8du, 0x9b992f2eu, 0xe60b6f47u, 0x0fe3f11du,
+ 0xe54cda54u, 0x1edad891u, 0xce6279cfu, 0xcd3e7e6fu,
+ 0x1618b166u, 0xfd2c1d05u, 0x848fd2c5u, 0xf6fb2299u,
+ 0xf523f357u, 0xa6327623u, 0x93a83531u, 0x56cccd02u,
+ 0xacf08162u, 0x5a75ebb5u, 0x6e163697u, 0x88d273ccu,
+ 0xde966292u, 0x81b949d0u, 0x4c50901bu, 0x71c65614u,
+ 0xe6c6c7bdu, 0x327a140au, 0x45e1d006u, 0xc3f27b9au,
+ 0xc9aa53fdu, 0x62a80f00u, 0xbb25bfe2u, 0x35bdd2f6u,
+ 0x71126905u, 0xb2040222u, 0xb6cbcf7cu, 0xcd769c2bu,
+ 0x53113ec0u, 0x1640e3d3u, 0x38abbd60u, 0x2547adf0u,
+ 0xba38209cu, 0xf746ce76u, 0x77afa1c5u, 0x20756060u,
+ 0x85cbfe4eu, 0x8ae88dd8u, 0x7aaaf9b0u, 0x4cf9aa7eu,
+ 0x1948c25cu, 0x02fb8a8cu, 0x01c36ae4u, 0xd6ebe1f9u,
+ 0x90d4f869u, 0xa65cdea0u, 0x3f09252du, 0xc208e69fu,
+ 0xb74e6132u, 0xce77e25bu, 0x578fdfe3u, 0x3ac372e6u
+ }
+};
+
+
+#define F1(i) \
+ xl ^= pax[i]; \
+ xr ^= ((sbx[0][xl>>24] + \
+ sbx[1][(xl&0xFF0000)>>16]) ^ \
+ sbx[2][(xl&0xFF00)>>8]) + \
+ sbx[3][xl&0xFF];
+
+#define F2(i) \
+ xr ^= pax[i]; \
+ xl ^= ((sbx[0][xr>>24] + \
+ sbx[1][(xr&0xFF0000)>>16]) ^ \
+ sbx[2][(xr&0xFF00)>>8]) + \
+ sbx[3][xr&0xFF];
+
+
+ static void
+bf_e_block(p_xl, p_xr)
+ long_u *p_xl;
+ long_u *p_xr;
+{
+ long_u temp, xl = *p_xl, xr = *p_xr;
+
+ F1(0) F2(1) F1(2) F2(3) F1(4) F2(5) F1(6) F2(7)
+ F1(8) F2(9) F1(10) F2(11) F1(12) F2(13) F1(14) F2(15)
+ xl ^= pax[16]; xr ^= pax[17];
+ temp = xl; xl = xr; xr = temp;
+ *p_xl = xl; *p_xr = xr;
+}
+
+#if 0 /* not used */
+ static void
+bf_d_block(p_xl, p_xr)
+ long_u *p_xl;
+ long_u *p_xr;
+{
+ long_u temp, xl = *p_xl, xr = *p_xr;
+ F1(17) F2(16) F1(15) F2(14) F1(13) F2(12) F1(11) F2(10)
+ F1(9) F2(8) F1(7) F2(6) F1(5) F2(4) F1(3) F2(2)
+ xl ^= pax[1];
+ xr ^= pax[0];
+ temp = xl; xl = xr; xr = temp;
+ *p_xl = xl; *p_xr = xr;
+}
+#endif
+
+
+#ifdef BIG_ENDIAN
+# define htonl2(x) \
+ x = ((((x) & 0xffL) << 24) | (((x) & 0xff00L) << 8) | \
+ (((x) & 0xff0000L) >> 8) | (((x) & 0xff000000L) >> 24))
+#else
+# define htonl2(x)
+#endif
+
+ static void
+bf_e_cblock(block)
+ char_u *block;
+{
+ block8 bk;
+ memcpy(bk.uc, block, 8);
+ htonl2(bk.ul[0]);
+ htonl2(bk.ul[1]);
+ bf_e_block(&bk.ul[0], &bk.ul[1]);
+ htonl2(bk.ul[0]);
+ htonl2(bk.ul[1]);
+ memcpy(block, bk.uc, 8);
+}
+
+#if 0 /* not used */
+ void
+bf_d_cblock(block)
+ char_u *block;
+{
+ block8 bk;
+ memcpy(bk.uc, block, 8);
+ htonl2(bk.ul[0]); htonl2(bk.ul[1]);
+ bf_d_block(&bk.ul[0], &bk.ul[1]);
+ htonl2(bk.ul[0]); htonl2(bk.ul[1]);
+ memcpy(block, bk.uc, 8);
+}
+#endif
+
+ void
+bf_key_init(password)
+ char_u *password;
+{
+ int i, j, keypos = 0;
+ long_u val, data_l, data_r;
+ char *key;
+ int keylen;
+
+ key = sha256_key((char *)password);
+ keylen = STRLEN(key);
+ for (i = 0; i < 256; ++i)
+ {
+ sbx[0][i] = sbi[0][i];
+ sbx[1][i] = sbi[1][i];
+ sbx[2][i] = sbi[2][i];
+ sbx[3][i] = sbi[3][i];
+ }
+
+ for (i = 0; i < 18; ++i)
+ {
+ val = 0;
+ for (j = 0; j < 4; ++j)
+ val = (val << 8) | (key[keypos++ % keylen] & 0xff);
+ pax[i] = ipa[i] ^ val;
+ }
+
+ data_l = data_r = 0;
+ for (i = 0; i < 18; i += 2)
+ {
+ bf_e_block(&data_l, &data_r);
+ pax[i + 0] = data_l;
+ pax[i + 1] = data_r;
+ }
+
+ for (i = 0; i < 4; ++i)
+ {
+ for (j = 0; j < 256; j += 2)
+ {
+ bf_e_block(&data_l, &data_r);
+ sbx[i][j + 0] = data_l;
+ sbx[i][j + 1] = data_r;
+ }
+ }
+}
+
+/*
+ * BF Self test for corrupted tables or instructions
+ */
+ static int
+bf_check_tables(ipa, sbi, val)
+ long_u ipa[18];
+ long_u sbi[4][256];
+ long_u val;
+{
+ int i, j;
+ long_u c = 0;
+
+ for (i = 0; i < 18; i++)
+ c ^= ipa[i];
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 256; j++)
+ c ^= sbi[i][j];
+ return c == val;
+}
+
+typedef struct {
+ char_u password[64];
+ char_u plaintxt[8];
+ char_u cryptxt[8];
+ long_u keysum;
+} struct_bf_test_data;
+
+// Assert bf(password, plaintxt) is cryptxt.
+// Assert csum(pax sbx(password)) is keysum.
+static struct_bf_test_data bf_test_data[] = {
+ {
+ "password",
+ "plaintxt",
+#if 0 /* This value doesn't work, why??? */
+ "\x55\xca\x56\x3a\xef\xe1\x9c\x73", /* cryptxt */
+#else
+ "\x47\xd9\x67\x49\x91\xc5\x9a\x95", /* cryptxt */
+#endif
+ 0x5de01bdbu, /* keysum */
+ },
+};
+
+/*
+ * Return FAIL when there is something wrong with blowfish encryption.
+ */
+ static int
+bf_self_test()
+{
+ int i, bn;
+ int err = 0;
+ block8 bk;
+
+ if (!bf_check_tables(ipa, sbi, 0x6ffa520a))
+ err++;
+
+ bn = ARRAY_LENGTH(bf_test_data);
+ for (i = 0; i < bn; i++)
+ {
+ bf_key_init((char_u *)(bf_test_data[i].password));
+ if (!bf_check_tables(pax, sbx, bf_test_data[i].keysum))
+ err++;
+
+ /* Don't modify bf_test_data[i].plaintxt, self test is idempotent. */
+ memcpy(bk.uc, bf_test_data[i].plaintxt, 8);
+ bf_e_cblock(bk.uc);
+ if (memcmp(bk.uc, bf_test_data[i].cryptxt, 8) != 0)
+ err++;
+ }
+
+ return err > 0 ? FAIL : OK;
+}
+
+/* Output feedback mode. */
+static int randbyte_offset = 0;
+static int update_offset = 0;
+static char_u ofb_buffer[BF_OFB_LEN]; /* 64 bytes */
+
+/*
+ * Initialize with seed "iv[iv_len]".
+ */
+ void
+bf_ofb_init(iv, iv_len)
+ char_u *iv;
+ int iv_len;
+{
+ int i, mi;
+
+ randbyte_offset = update_offset = 0;
+ memset(ofb_buffer, 0, BF_OFB_LEN);
+ if (iv_len > 0)
+ {
+ mi = iv_len > BF_OFB_LEN ? iv_len : BF_OFB_LEN;
+ for (i = 0; i < mi; i++)
+ ofb_buffer[i % BF_OFB_LEN] ^= iv[i % iv_len];
+ }
+}
+
+ void
+bf_ofb_update(c)
+ int c;
+{
+ ofb_buffer[update_offset++] ^= (char_u)c;
+ if (update_offset == BF_OFB_LEN)
+ update_offset = 0;
+}
+
+ int
+bf_ranbyte()
+{
+ int current_byte = randbyte_offset++;
+ int current_block = (current_byte / BF_BLOCK) * BF_BLOCK;
+
+ if (randbyte_offset == BF_OFB_LEN)
+ randbyte_offset = 0;
+ if ((current_byte % BF_BLOCK) == 0)
+ bf_e_cblock(&ofb_buffer[current_block]);
+ return ofb_buffer[current_byte];
+}
+
+/*
+ * Run a test to check if the encryption works as expected.
+ * Give an error and return FAIL when not.
+ */
+ int
+blowfish_self_test()
+{
+ if (sha256_self_test() == FAIL)
+ {
+ EMSG2(_("E000: sha256 test failed"),"");
+ return FAIL;
+ }
+ if (bf_self_test() == FAIL)
+ {
+ EMSG2(_("E000: Blowfish test failed"),"");
+ return FAIL;
+ }
+ return OK;
+}
+
+#endif /* FEAT_CRYPT */
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 13e26d514..fd7471d3d 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -11123,7 +11123,8 @@ ex_match(eap)
ex_X(eap)
exarg_T *eap UNUSED;
{
- (void)get_crypt_key(TRUE, TRUE);
+ if (curbuf->b_p_cm == 0 || blowfish_self_test() == OK)
+ (void)get_crypt_key(TRUE, TRUE);
}
#endif
diff --git a/src/feature.h b/src/feature.h
index ea2e5887d..4568ffc1d 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -592,7 +592,7 @@
/*
* +cryptv Encryption (by Mohsin Ahmed <mosh@sasi.com>).
*/
-#if defined(FEAT_NORMAL) || defined(PROTO)
+#if defined(FEAT_NORMAL) && !defined(FEAT_CRYPT) || defined(PROTO)
# define FEAT_CRYPT
#endif
diff --git a/src/fileio.c b/src/fileio.c
index c36796972..ad5fddde2 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -33,8 +33,14 @@
#define SMBUFSIZE 256 /* size of emergency write buffer */
#ifdef FEAT_CRYPT
-# define CRYPT_MAGIC "VimCrypt~01!" /* "01" is the version nr */
+char crypt_magic_01[] = "VimCrypt~01!";
+char crypt_magic_02[] = "VimCrypt~02!";
# define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */
+
+/* crypt_magic[0] is pkzip crypt, crypt_magic[1] is sha2+blowfish */
+static char *crypt_magic[] = {crypt_magic_01, crypt_magic_02};
+static int crypt_seed_len[] = {0, 8};
+#define CRYPT_SEED_LEN_MAX 8
#endif
/* Is there any system that doesn't have access()? */
@@ -54,6 +60,7 @@ static char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fd
static void check_marks_read __ARGS((void));
#endif
#ifdef FEAT_CRYPT
+static int get_crypt_method __ARGS((char *ptr, int len));
static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile));
#endif
#ifdef UNIX
@@ -1425,7 +1432,9 @@ retry:
*/
if ((filesize == 0
# ifdef FEAT_CRYPT
- || (filesize == CRYPT_MAGIC_LEN && cryptkey != NULL)
+ || (filesize == (CRYPT_MAGIC_LEN
+ + crypt_seed_len[use_crypt_method])
+ && cryptkey != NULL)
# endif
)
&& (fio_flags == FIO_UCSBOM
@@ -2241,7 +2250,7 @@ failed:
#ifdef FEAT_CRYPT
if (cryptkey != curbuf->b_p_key)
- vim_free(cryptkey);
+ free_crypt_key(cryptkey);
#endif
#ifdef FEAT_MBYTE
@@ -2456,7 +2465,8 @@ failed:
c = TRUE;
#ifdef FEAT_CRYPT
if (cryptkey != NULL)
- msg_add_lines(c, (long)linecnt, filesize - CRYPT_MAGIC_LEN);
+ msg_add_lines(c, (long)linecnt, filesize
+ - CRYPT_MAGIC_LEN - crypt_seed_len[use_crypt_method]);
else
#endif
msg_add_lines(c, (long)linecnt, filesize);
@@ -2783,7 +2793,29 @@ check_marks_read()
#ifdef FEAT_CRYPT
/*
- * Check for magic number used for encryption.
+ * Get the crypt method used for a file from "ptr[len]", the magic text at the
+ * start of the file.
+ * Returns -1 when no encryption used.
+ */
+ static int
+get_crypt_method(ptr, len)
+ char *ptr;
+ int len;
+{
+ int i;
+
+ for (i = 0; i < (int)(sizeof(crypt_magic) / sizeof(crypt_magic[0])); i++)
+ {
+ if (len < (CRYPT_MAGIC_LEN + crypt_seed_len[i]))
+ continue;
+ if (memcmp(ptr, crypt_magic[i], CRYPT_MAGIC_LEN) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * Check for magic number used for encryption. Applies to the current buffer.
* If found, the magic number is removed from ptr[*sizep] and *sizep and
* *filesizep are updated.
* Return the (new) encryption key, NULL for no encryption.
@@ -2796,17 +2828,23 @@ check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile)
long *filesizep; /* nr of bytes used from file */
int newfile; /* editing a new buffer */
{
- if (*sizep >= CRYPT_MAGIC_LEN
- && STRNCMP(ptr, CRYPT_MAGIC, CRYPT_MAGIC_LEN) == 0)
+ int method = get_crypt_method((char *)ptr, *sizep);
+
+ if (method >= 0)
{
+ curbuf->b_p_cm = method;
+ use_crypt_method = method;
+ if (method > 0)
+ (void)blowfish_self_test();
if (cryptkey == NULL)
{
if (*curbuf->b_p_key)
cryptkey = curbuf->b_p_key;
else
{
- /* When newfile is TRUE, store the typed key
- * in the 'key' option and don't free it. */
+ /* When newfile is TRUE, store the typed key in the 'key'
+ * option and don't free it. bf needs hash of the key saved.
+ */
cryptkey = get_crypt_key(newfile, FALSE);
/* check if empty key entered */
if (cryptkey != NULL && *cryptkey == NUL)
@@ -2820,17 +2858,24 @@ check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile)
if (cryptkey != NULL)
{
- crypt_init_keys(cryptkey);
+ int seed_len = crypt_seed_len[method];
+
+ if (method == 0)
+ crypt_init_keys(cryptkey);
+ else
+ {
+ bf_key_init(cryptkey);
+ bf_ofb_init(ptr + CRYPT_MAGIC_LEN, seed_len);
+ }
/* Remove magic number from the text */
- *filesizep += CRYPT_MAGIC_LEN;
- *sizep -= CRYPT_MAGIC_LEN;
- mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN, (size_t)*sizep);
+ *filesizep += CRYPT_MAGIC_LEN + seed_len;
+ *sizep -= CRYPT_MAGIC_LEN + seed_len;
+ mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN + seed_len, (size_t)*sizep);
}
}
- /* When starting to edit a new file which does not have
- * encryption, clear the 'key' option, except when
- * starting up (called with -x argument) */
+ /* When starting to edit a new file which does not have encryption, clear
+ * the 'key' option, except when starting up (called with -x argument) */
else if (newfile && *curbuf->b_p_key && !starting)
set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
@@ -4229,12 +4274,30 @@ restore_backup:
#ifdef FEAT_CRYPT
if (*buf->b_p_key && !filtering)
{
- crypt_init_keys(buf->b_p_key);
- /* Write magic number, so that Vim knows that this file is encrypted
- * when reading it again. This also undergoes utf-8 to ucs-2/4
- * conversion when needed. */
- write_info.bw_buf = (char_u *)CRYPT_MAGIC;
- write_info.bw_len = CRYPT_MAGIC_LEN;
+ char_u header[CRYPT_MAGIC_LEN + CRYPT_SEED_LEN_MAX + 2];
+ int seed_len = crypt_seed_len[buf->b_p_cm];
+
+ use_crypt_method = buf->b_p_cm; /* select pkzip or blowfish */
+
+ memset(header, 0, sizeof(header));
+ vim_strncpy(header, (char_u *)crypt_magic[use_crypt_method],
+ CRYPT_MAGIC_LEN);
+
+ if (buf->b_p_cm == 0)
+ crypt_init_keys(buf->b_p_key);
+ else
+ {
+ /* Using blowfish, add seed. */
+ sha2_seed(header + CRYPT_MAGIC_LEN, seed_len); /* create iv */
+ bf_ofb_init(header + CRYPT_MAGIC_LEN, seed_len);
+ bf_key_init(buf->b_p_key);
+ }
+
+ /* Write magic number, so that Vim knows that this file is
+ * encrypted when reading it again. This also undergoes utf-8 to
+ * ucs-2/4 conversion when needed. */
+ write_info.bw_buf = (char_u *)header;
+ write_info.bw_len = CRYPT_MAGIC_LEN + seed_len;
write_info.bw_flags = FIO_NOCONVERT;
if (buf_write_bytes(&write_info) == FAIL)
end = 0;
diff --git a/src/globals.h b/src/globals.h
index d2b898c8f..a65a2e3b5 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -105,6 +105,10 @@ EXTERN int exec_from_reg INIT(= FALSE); /* executing register */
EXTERN int screen_cleared INIT(= FALSE); /* screen has been cleared */
+#ifdef FEAT_CRYPT
+EXTERN int use_crypt_method INIT(= 0);
+#endif
+
/*
* When '$' is included in 'cpoptions' option set:
* When a change command is given that deletes only part of a line, a dollar
diff --git a/src/main.c b/src/main.c
index 0330f6abc..7e741def2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -797,6 +797,7 @@ main
#ifdef FEAT_CRYPT
if (params.ask_for_key)
{
+ (void)blowfish_self_test();
(void)get_crypt_key(TRUE, TRUE);
TIME_MSG("getting crypt key");
}
diff --git a/src/misc2.c b/src/misc2.c
index 8cd568304..3abef1562 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -3685,6 +3685,11 @@ update_mouseshape(shape_idx)
* 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 */
@@ -3730,6 +3735,8 @@ decrypt_byte()
{
ush temp;
+ if (use_crypt_method > 0)
+ return bf_ranbyte();
temp = (ush)keys[2] | 2;
return (int)(((unsigned)(temp * (temp ^ 1)) >> 8) & 0xff);
}
@@ -3737,15 +3744,19 @@ decrypt_byte()
/*
* Update the encryption keys with the next byte of plain text
*/
- int
+ void
update_keys(c)
int c; /* byte of plain text */
{
- 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));
- return c;
+ if (use_crypt_method > 0)
+ bf_ofb_update( (unsigned char) c);
+ else
+ {
+ 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));
+ }
}
/*
@@ -3769,8 +3780,26 @@ 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 in stored in the 'key' option, and the
+ * 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.
@@ -3801,16 +3830,17 @@ get_crypt_key(store, twice)
if (p2 != NULL && STRCMP(p1, p2) != 0)
{
MSG(_("Keys don't match!"));
- vim_free(p1);
- vim_free(p2);
+ 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);
- vim_free(p1);
+ free_crypt_key(p1);
p1 = curbuf->b_p_key;
}
break;
@@ -3822,7 +3852,7 @@ get_crypt_key(store, twice)
need_wait_return = FALSE;
msg_didout = FALSE;
- vim_free(p2);
+ free_crypt_key(p2);
return p1;
}
diff --git a/src/option.c b/src/option.c
index c9cad3208..e7ec0c8b9 100644
--- a/src/option.c
+++ b/src/option.c
@@ -77,6 +77,7 @@
#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
# define PV_CINW OPT_BUF(BV_CINW)
#endif
+#define PV_CM OPT_BUF(BV_CM)
#ifdef FEAT_FOLDING
# define PV_CMS OPT_BUF(BV_CMS)
#endif
@@ -277,6 +278,7 @@ static char_u *p_cino;
#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
static char_u *p_cinw;
#endif
+static long p_cm;
#ifdef FEAT_COMMENTS
static char_u *p_com;
#endif
@@ -834,6 +836,9 @@ static struct vimoption
(char_u *)&p_cpo, PV_NONE,
{(char_u *)CPO_VI, (char_u *)CPO_VIM}
SCRIPTID_INIT},
+ {"cryptmethod", "cm", P_NUM|P_VI_DEF|P_VIM,
+ (char_u *)&p_cm, PV_CM,
+ {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT},
{"cscopepathcomp", "cspc", P_NUM|P_VI_DEF|P_VIM,
#ifdef FEAT_CSCOPE
(char_u *)&p_cspc, PV_NONE,
@@ -7870,6 +7875,22 @@ set_num_option(opt_idx, varp, value, errbuf, errbuflen, opt_flags)
#endif
+ else if (pp == &curbuf->b_p_cm)
+ {
+ if (curbuf->b_p_cm < 0)
+ {
+ errmsg = e_positive;
+ curbuf->b_p_cm = 0;
+ }
+ if (curbuf->b_p_cm > 1)
+ {
+ errmsg = e_invarg;
+ curbuf->b_p_cm = 1;
+ }
+ if (curbuf->b_p_cm > 0 && blowfish_self_test() == FAIL)
+ curbuf->b_p_cm = 0;
+ }
+
#ifdef FEAT_WINDOWS
/* (re)set last window status line */
else if (pp == &p_ls)
@@ -9286,6 +9307,7 @@ get_varp(p)
case PV_CINK: return (char_u *)&(curbuf->b_p_cink);
case PV_CINO: return (char_u *)&(curbuf->b_p_cino);
#endif
+ case PV_CM: return (char_u *)&(curbuf->b_p_cm);
#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
case PV_CINW: return (char_u *)&(curbuf->b_p_cinw);
#endif
diff --git a/src/option.h b/src/option.h
index b635db175..b49c0c47f 100644
--- a/src/option.h
+++ b/src/option.h
@@ -908,6 +908,7 @@ enum
#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
, BV_CINW
#endif
+ , BV_CM
#ifdef FEAT_FOLDING
, BV_CMS
#endif
diff --git a/src/proto.h b/src/proto.h
index 85f49378c..dd2e14654 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -69,6 +69,9 @@ extern int _stricoll __ARGS((char *a, char *b));
# include "os_qnx.pro"
# endif
+# ifdef FEAT_CRYPT
+# include "blowfish.pro"
+# endif
# include "buffer.pro"
# include "charset.pro"
# ifdef FEAT_CSCOPE
@@ -146,6 +149,9 @@ void qsort __ARGS((void *base, size_t elm_count, size_t elm_size, int (*cmp)(con
# endif
# include "regexp.pro"
# include "screen.pro"
+# ifdef FEAT_CRYPT
+# include "sha256.pro"
+# endif
# include "search.pro"
# include "spell.pro"
# include "syntax.pro"
diff --git a/src/proto/blowfish.pro b/src/proto/blowfish.pro
new file mode 100644
index 000000000..6b6628742
--- /dev/null
+++ b/src/proto/blowfish.pro
@@ -0,0 +1,7 @@
+/* blowfish.c */
+void bf_key_init __ARGS((char_u *password));
+void bf_ofb_init __ARGS((char_u *iv, int iv_len));
+void bf_ofb_update __ARGS((int c));
+int bf_ranbyte __ARGS((void));
+int blowfish_self_test __ARGS((void));
+/* vim: set ft=c : */
diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro
index 5c4cc4210..9b27b7e3d 100644
--- a/src/proto/misc2.pro
+++ b/src/proto/misc2.pro
@@ -81,8 +81,9 @@ char_u *parse_shape_opt __ARGS((int what));
int get_shape_idx __ARGS((int mouse));
void update_mouseshape __ARGS((int shape_idx));
int decrypt_byte __ARGS((void));
-int update_keys __ARGS((int c));
+void update_keys __ARGS((int c));
void crypt_init_keys __ARGS((char_u *passwd));
+void free_crypt_key __ARGS((char_u *key));
char_u *get_crypt_key __ARGS((int store, int twice));
void *vim_findfile_init __ARGS((char_u *path, char_u *filename, char_u *stopdirs, int level, int free_visited, int find_what, void *search_ctx_arg, int tagfile, char_u *rel_fname));
char_u *vim_findfile_stopdir __ARGS((char_u *buf));
diff --git a/src/proto/sha256.pro b/src/proto/sha256.pro
new file mode 100644
index 000000000..635721c8c
--- /dev/null
+++ b/src/proto/sha256.pro
@@ -0,0 +1,5 @@
+/* sha256.c */
+char *sha256_key __ARGS((char *buf));
+int sha256_self_test __ARGS((void));
+void sha2_seed __ARGS((char_u header[], int header_len));
+/* vim: set ft=c : */
diff --git a/src/sha256.c b/src/sha256.c
new file mode 100644
index 000000000..24e57b986
--- /dev/null
+++ b/src/sha256.c
@@ -0,0 +1,429 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * FIPS-180-2 compliant SHA-256 implementation
+ * GPL by Christophe Devine.
+ * Modified for md5deep, in public domain.
+ * Modified For Vim, GPL(C) Mohsin Ahmed, http://www.cs.albany.edu/~mosh
+ *
+ * Vim specific notes:
+ * Functions exported by this file:
+ * 1. sha256_key() hashes the password to 64 bytes char string.
+ * 2. sha2_seed() generates a random header.
+ * sha256_self_test() is implicitly called once.
+ */
+
+#include "vim.h"
+
+#ifdef FEAT_CRYPT
+
+typedef unsigned long uint32_t;
+
+typedef struct {
+ uint32_t total[2];
+ uint32_t state[8];
+ char_u buffer[64];
+} context_sha256_T;
+
+static void sha256_starts __ARGS((context_sha256_T *ctx));
+static void sha256_process __ARGS((context_sha256_T *ctx, char_u data[64]));
+static void sha256_update __ARGS((context_sha256_T *ctx, char_u *input, uint32_t length));
+static void sha256_finish __ARGS((context_sha256_T *ctx, char_u digest[32]));
+static char *sha256_bytes __ARGS((char *buf, int buflen));
+static unsigned int get_some_time __ARGS((void));
+
+
+#define GET_UINT32(n, b, i) \
+{ \
+ (n) = ( (uint32_t)(b)[(i) ] << 24) \
+ | ( (uint32_t)(b)[(i) + 1] << 16) \
+ | ( (uint32_t)(b)[(i) + 2] << 8) \
+ | ( (uint32_t)(b)[(i) + 3] ); \
+}
+
+#define PUT_UINT32(n,b,i) \
+{ \
+ (b)[(i) ] = (char_u)((n) >> 24); \
+ (b)[(i) + 1] = (char_u)((n) >> 16); \
+ (b)[(i) + 2] = (char_u)((n) >> 8); \
+ (b)[(i) + 3] = (char_u)((n) ); \
+}
+
+ static void
+sha256_starts(ctx)
+ context_sha256_T *ctx;
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+}
+
+ static void
+sha256_process(ctx, data)
+ context_sha256_T *ctx;
+ char_u data[64];
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A, B, C, D, E, F, G, H;
+
+ GET_UINT32(W[0], data, 0);
+ GET_UINT32(W[1], data, 4);
+ GET_UINT32(W[2], data, 8);
+ GET_UINT32(W[3], data, 12);
+ GET_UINT32(W[4], data, 16);
+ GET_UINT32(W[5], data, 20);
+ GET_UINT32(W[6], data, 24);
+ GET_UINT32(W[7], data, 28);
+ GET_UINT32(W[8], data, 32);
+ GET_UINT32(W[9], data, 36);
+ GET_UINT32(W[10], data, 40);
+ GET_UINT32(W[11], data, 44);
+ GET_UINT32(W[12], data, 48);
+ GET_UINT32(W[13], data, 52);
+ GET_UINT32(W[14], data, 56);
+ GET_UINT32(W[15], data, 60);
+
+#define SHR(x, n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x, n) (SHR(x, n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+
+#define F0(x, y, z) ((x & y) | (z & (x | y)))
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e, f, g) + K + x; \
+ temp2 = S2(a) + F0(a, b, c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+ F = ctx->state[5];
+ G = ctx->state[6];
+ H = ctx->state[7];
+
+ P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98);
+ P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491);
+ P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF);
+ P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5);
+ P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B);
+ P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1);
+ P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4);
+ P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5);
+ P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98);
+ P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01);
+ P( G, H, A, B, C, D, E, F, W[10], 0x243185BE);
+ P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
+ P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
+ P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
+ P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
+ P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
+ P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
+ P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
+ P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
+ P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
+ P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
+ P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
+ P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
+ P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
+ P( A, B, C, D, E, F, G, H, R(24), 0x983E5152);
+ P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
+ P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
+ P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
+ P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
+ P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
+ P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
+ P( B, C, D, E, F, G, H, A, R(31), 0x14292967);
+ P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
+ P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
+ P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
+ P( F, G, H, A, B, C, D, E, R(35), 0x53380D13);
+ P( E, F, G, H, A, B, C, D, R(36), 0x650A7354);
+ P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
+ P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
+ P( B, C, D, E, F, G, H, A, R(39), 0x92722C85);
+ P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
+ P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
+ P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
+ P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
+ P( E, F, G, H, A, B, C, D, R(44), 0xD192E819);
+ P( D, E, F, G, H, A, B, C, R(45), 0xD6990624);
+ P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
+ P( B, C, D, E, F, G, H, A, R(47), 0x106AA070);
+ P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
+ P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
+ P( G, H, A, B, C, D, E, F, R(50), 0x2748774C);
+ P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
+ P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
+ P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
+ P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
+ P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
+ P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
+ P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
+ P( G, H, A, B, C, D, E, F, R(58), 0x84C87814);
+ P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
+ P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
+ P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
+ P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
+ P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+ ctx->state[5] += F;
+ ctx->state[6] += G;
+ ctx->state[7] += H;
+}
+
+ static void
+sha256_update(ctx, input, length)
+ context_sha256_T *ctx;
+ char_u *input;
+ uint32_t length;
+{
+ uint32_t left, fill;
+
+ if (length == 0)
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += length;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if (ctx->total[0] < length)
+ ctx->total[1]++;
+
+ if (left && length >= fill)
+ {
+ memcpy((void *)(ctx->buffer + left), (void *)input, fill);
+ sha256_process(ctx, ctx->buffer);
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while (length >= 64)
+ {
+ sha256_process(ctx, input);
+ length -= 64;
+ input += 64;
+ }
+
+ if (length)
+ memcpy((void *)(ctx->buffer + left), (void *)input, length);
+}
+
+static char_u sha256_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+ static void
+sha256_finish(ctx, digest)
+ context_sha256_T *ctx;
+ char_u digest[32];
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ char_u msglen[8];
+
+ high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+ low = (ctx->total[0] << 3);
+
+ PUT_UINT32(high, msglen, 0);
+ PUT_UINT32(low, msglen, 4);
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ sha256_update(ctx, sha256_padding, padn);
+ sha256_update(ctx, msglen, 8);
+
+ PUT_UINT32(ctx->state[0], digest, 0);
+ PUT_UINT32(ctx->state[1], digest, 4);
+ PUT_UINT32(ctx->state[2], digest, 8);
+ PUT_UINT32(ctx->state[3], digest, 12);
+ PUT_UINT32(ctx->state[4], digest, 16);
+ PUT_UINT32(ctx->state[5], digest, 20);
+ PUT_UINT32(ctx->state[6], digest, 24);
+ PUT_UINT32(ctx->state[7], digest, 28);
+}
+
+ static char *
+sha256_bytes(buf, buflen)
+ char *buf;
+ int buflen;
+{
+ char_u sha256sum[32];
+ static char hexit[65];
+ int j;
+ context_sha256_T ctx;
+
+ sha256_self_test();
+
+ sha256_starts(&ctx);
+ sha256_update(&ctx, (char_u *)buf, buflen);
+ sha256_finish(&ctx, sha256sum);
+ for (j = 0; j < 32; j++)
+ sprintf(hexit + j * 2, "%02x", sha256sum[j]);
+ hexit[sizeof(hexit) - 1] = '\0';
+ return hexit;
+}
+
+/*
+ * Returns sha256(buf) as 64 hex chars.
+ */
+ char *
+sha256_key(buf)
+ char *buf;
+{
+ static char *hexit = 0;
+ int buflen;
+
+ /* No passwd means don't encrypt */
+ if (buf == NULL || *buf == NUL)
+ return "";
+
+ /* if password is "0", reuse previous hash, for user convienience. */
+ if (!strcmp(buf, "0") && hexit)
+ return hexit;
+
+ buflen = strlen(buf);
+ hexit = sha256_bytes(buf, buflen);
+ return hexit;
+}
+
+/*
+ * These are the standard FIPS-180-2 test vectors
+ */
+
+static char *sha_self_test_msg[] = {
+ "abc",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ NULL
+};
+
+static char *sha_self_test_vector[] = {
+ "ba7816bf8f01cfea414140de5dae2223" \
+ "b00361a396177a9cb410ff61f20015ad",
+ "248d6a61d20638b8e5c026930c3e6039" \
+ "a33ce45964ff2167f6ecedd419db06c1",
+ "cdc76e5c9914fb9281a1c7e284d73e67" \
+ "f1809a48a497200e046d39ccc7112cd0"
+};
+
+/*
+ * Perform a test on the SHA256 algorithm.
+ * Return FAIL or OK.
+ */
+ int
+sha256_self_test()
+{
+ int i, j;
+ char output[65];
+ context_sha256_T ctx;
+ char_u buf[1000];
+ char_u sha256sum[32];
+ static int failures = 0;
+ char *hexit;
+ static int sha256_self_tested = 0;
+
+ if (sha256_self_tested > 0)
+ return failures > 0 ? FAIL : OK;
+ sha256_self_tested = 1;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (i < 2)
+ {
+ hexit = sha256_bytes(sha_self_test_msg[i],
+ strlen(sha_self_test_msg[i]));
+ strcpy(output, hexit);
+ }
+ else
+ {
+ sha256_starts(&ctx);
+ memset(buf, 'a', 1000);
+ for (j = 0; j < 1000; j++)
+ sha256_update(&ctx, (char_u *)buf, 1000);
+ sha256_finish(&ctx, sha256sum);
+ for (j = 0; j < 32; j++)
+ sprintf(output + j * 2, "%02x", sha256sum[j]);
+ }
+ if (memcmp(output, sha_self_test_vector[i], 64))
+ {
+ failures++;
+ output[sizeof(output) - 1] = '\0';
+ /* printf("sha256_self_test %d failed %s\n", i, output); */
+ }
+ }
+ return failures > 0 ? FAIL : OK;
+}
+
+ static unsigned int
+get_some_time()
+{
+#ifdef HAVE_GETTIMEOFDAY
+ struct timeval tv;
+
+ /* Using usec makes it less predictable. */
+ gettimeofday(&tv, NULL);
+ return (unsigned int)(tv.tv_sec + tv.tv_usec);
+#else
+ return (unsigned int)time(NULL);
+#endif
+}
+
+/*
+ * set header = sha2_seed(random_data);
+ */
+ void
+sha2_seed(header, header_len)
+ char_u header[];
+ int header_len;
+{
+ int i;
+ static char_u random_data[1000];
+ char_u sha256sum[32];
+ context_sha256_T ctx;
+ srand(get_some_time());
+
+ for (i = 0; i < (int)sizeof(random_data) - 1; i++)
+ random_data[i] = (char_u)((get_some_time() ^ rand()) & 0xff);
+ sha256_starts(&ctx);
+ sha256_update(&ctx, (char_u *)random_data, sizeof(random_data));
+ sha256_finish(&ctx, sha256sum);
+
+ for (i = 0; i < header_len; i++)
+ header[i] = sha256sum[i % sizeof(sha256sum)];
+}
+
+#endif /* FEAT_CRYPT */
diff --git a/src/structs.h b/src/structs.h
index 72bd96cd4..5aceb59a8 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1358,6 +1358,7 @@ struct file_buffer
#ifdef FEAT_INS_EXPAND
char_u *b_p_cpt; /* 'complete' */
#endif
+ long b_p_cm; /* 'cryptmethod' */
#ifdef FEAT_COMPL_FUNC
char_u *b_p_cfu; /* 'completefunc' */
char_u *b_p_ofu; /* 'omnifunc' */
diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak
index 8f35c7bd1..4b1af5f86 100644
--- a/src/testdir/Make_dos.mak
+++ b/src/testdir/Make_dos.mak
@@ -27,7 +27,7 @@ SCRIPTS = test3.out test4.out test5.out test6.out test7.out \
test30.out test31.out test32.out test33.out test34.out \
test37.out test38.out test39.out test40.out test41.out \
test42.out test52.out test65.out test66.out test67.out \
- test68.out test69.out
+ test68.out test69.out test71.out
SCRIPTS32 = test50.out test70.out
diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak
index 760bb21dd..960f5b209 100644
--- a/src/testdir/Make_ming.mak
+++ b/src/testdir/Make_ming.mak
@@ -46,7 +46,7 @@ SCRIPTS = test3.out test4.out test5.out test6.out test7.out \
test30.out test31.out test32.out test33.out test34.out \
test37.out test38.out test39.out test40.out test41.out \
test42.out test52.out test65.out test66.out test67.out \
- test68.out test69.out
+ test68.out test69.out test71.out
SCRIPTS32 = test50.out test70.out
diff --git a/src/testdir/Makefile b/src/testdir/Makefile
index 073a2841d..6a8e85f6b 100644
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -23,7 +23,7 @@ SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
test54.out test55.out test56.out test57.out test58.out \
test59.out test60.out test61.out test62.out test63.out \
test64.out test65.out test66.out test67.out test68.out \
- test69.out test70.out
+ test69.out test70.out test71.out
SCRIPTS_GUI = test16.out
@@ -69,7 +69,7 @@ test1.out: test1.in
fi \
else echo $* NO OUTPUT >>test.log; \
fi"
- -rm -rf X* test.ok viminfo
+ #-rm -rf X* test.ok viminfo
test49.out: test49.vim
diff --git a/src/testdir/test71.in b/src/testdir/test71.in
new file mode 100644
index 000000000..a2eadd3c1
--- /dev/null
+++ b/src/testdir/test71.in
@@ -0,0 +1,37 @@
+Test for encryption.
+
+STARTTEST
+:so small.vim
+:/^start of testfile/+1
+:let lines = getline('.', '$')
+:new
+:call append(0, lines)
+:$d
+:X
+foobar
+foobar
+:w! Xtestfile
+:bwipe!
+:e Xtestfile
+foobar
+:let dec1_lines = getline('.', '$')
+:%s/^/2/
+:set key=
+:set cryptmethod=1
+:X
+barfoo
+barfoo
+:w! Xtestfile
+:bwipe!
+:e Xtestfile
+barfoo
+:call append(0, dec1_lines)
+:set key=
+:w! test.out
+:qa!
+ENDTEST
+
+start of testfile
+01234567890123456789012345678901234567
+line 2 foo bar blah
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
diff --git a/src/testdir/test71.ok b/src/testdir/test71.ok
new file mode 100644
index 000000000..5820892b6
--- /dev/null
+++ b/src/testdir/test71.ok
@@ -0,0 +1,6 @@
+01234567890123456789012345678901234567
+line 2 foo bar blah
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+201234567890123456789012345678901234567
+2line 2 foo bar blah
+2line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx