# HG changeset patch # User Bram Moolenaar # Date 1274041974 -7200 # Node ID f60a0c9cbe6ceb3a575ee49815c8155cd1aeb482 # Parent c6f1aa1e9f32e9d32156d246dc7d913fd5ef8d6f Add the blowfish encryption patch from Mohsin Ahmed. Needs more work. diff --git a/Filelist b/Filelist --- 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 --- 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 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2049,6 +2049,19 @@ A jump table for the options with a shor 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 shor 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 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -30,6 +30,17 @@ be worked on, but only if you sponsor Vi *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 --- 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 --- a/src/Make_ivc.mak +++ b/src/Make_ivc.mak @@ -210,6 +210,7 @@ ALL : .\$(VIM).exe vimrun.exe install.ex 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 --- 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 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -453,6 +453,8 @@ INCL = vim.h os_win32.h ascii.h feature. $(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 --- 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 @@ scoptions: Make_sas.mak $(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 --- 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 " @@ -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 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) $(HAN 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 --- /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 --- 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 --- a/src/feature.h +++ b/src/feature.h @@ -592,7 +592,7 @@ /* * +cryptv Encryption (by Mohsin Ahmed ). */ -#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 --- 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 __AR 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, 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, 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); - } - } - /* When starting to edit a new file which does not have - * encryption, clear the 'key' option, except when - * starting up (called with -x argument) */ + *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) */ 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 --- a/src/globals.h +++ b/src/globals.h @@ -105,6 +105,10 @@ EXTERN int exec_from_reg INIT(= FALSE); 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 --- 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 --- 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 --- 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, err #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 --- 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 --- a/src/proto.h +++ b/src/proto.h @@ -69,6 +69,9 @@ extern int _stricoll __ARGS((char *a, ch # 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 el # 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 --- /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 --- 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 --- /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 --- /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 --- 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 --- a/src/testdir/Make_dos.mak +++ b/src/testdir/Make_dos.mak @@ -27,7 +27,7 @@ SCRIPTS = test3.out test4.out test5.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 --- a/src/testdir/Make_ming.mak +++ b/src/testdir/Make_ming.mak @@ -46,7 +46,7 @@ SCRIPTS = test3.out test4.out test5.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 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -23,7 +23,7 @@ SCRIPTS = test1.out test2.out test3.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 --- /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 --- /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