# HG changeset patch # User Bram Moolenaar # Date 1624302904 -7200 # Node ID 85d1e82ed134ec89dab499247a53ae61664272ad # Parent 55f296521ca33d6c0b84d5662c939480eab37e62 patch 8.2.3032: build problems with MSVC, other crypt issues with libsodium Commit: https://github.com/vim/vim/commit/226b28b96150e59375d2bff44e0aadd382b0c3f1 Author: Christian Brabandt Date: Mon Jun 21 21:08:08 2021 +0200 patch 8.2.3032: build problems with MSVC, other crypt issues with libsodium Problem: Build problems with MSVC, other crypt issues with libsodium. Solution: Adjust MSVC makefile. Disable swap file only when 'key' is set. Adjust error message used when key is wrong. Fix Coverity issues. (Christian Brabandt, closes #8420, closes #8411) diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -42,7 +42,11 @@ # Sound support: SOUND=yes (default is yes) # # Sodium support: SODIUM=[Path to Sodium directory] -# You need to install the msvc package from https://download.libsodium.org/libsodium/releases/ +# Dynamic built with libsodium +# You need to install the msvc package from +# https://download.libsodium.org/libsodium/releases/ +# and package the libsodium.dll with Vim +# # # DLL support (EXPERIMENTAL): VIMDLL=yes (default is no) # Creates vim{32,64}.dll, and stub gvim.exe and vim.exe. @@ -383,14 +387,14 @@ SODIUM = no ! if "$(CPU)" == "AMD64" SOD_LIB = $(SODIUM)\x64\Release\v140\dynamic ! elseif "$(CPU)" == "i386" -SOD_LIB = $(SODIUM)\x86\Release\v140\dynamic +SOD_LIB = $(SODIUM)\Win32\Release\v140\dynamic ! else SODIUM = no ! endif !endif !if "$(SODIUM)" != "no" -SOD_INC = -I $(SODIUM)\include +SOD_INC = /I "$(SODIUM)\include" SOD_DEFS = -DFEAT_SODIUM SOD_LIB = $(SOD_LIB)\libsodium.lib !endif @@ -514,7 +518,7 @@ CON_LIB = $(CON_LIB) /DELAYLOAD:comdlg32 CFLAGS = -c /W3 /GF /nologo $(CVARS) -I. -Iproto -DHAVE_PATHDEF -DWIN32 \ $(CSCOPE_DEFS) $(TERM_DEFS) $(SOUND_DEFS) $(NETBEANS_DEFS) $(CHANNEL_DEFS) \ - $(NBDEBUG_DEFS) $(XPM_DEFS) $(SOD_DEFS) \ + $(NBDEBUG_DEFS) $(XPM_DEFS) $(SOD_DEFS) $(SOD_INC) \ $(DEFINES) -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER) #>>>>> end of choices @@ -726,7 +730,7 @@ CFLAGS = $(CFLAGS) $(CFLAGS_DEPR) INCL = vim.h alloc.h ascii.h ex_cmds.h feature.h errors.h globals.h \ keymap.h macros.h option.h os_dos.h os_win32.h proto.h regexp.h \ - spell.h structs.h term.h beval.h $(NBDEBUG_INCL) $(SOD_INC) + spell.h structs.h term.h beval.h $(NBDEBUG_INCL) OBJ = \ $(OUTDIR)\arabic.obj \ diff --git a/src/crypt.c b/src/crypt.c --- a/src/crypt.c +++ b/src/crypt.c @@ -146,9 +146,9 @@ static cryptmethod_T cryptmethods[CRYPT_ FALSE, NULL, crypt_sodium_init, - crypt_sodium_encode, crypt_sodium_decode, + NULL, NULL, crypt_sodium_buffer_encode, crypt_sodium_buffer_decode, - crypt_sodium_encode, crypt_sodium_decode, + NULL, NULL, }, // NOTE: when adding a new method, use some random bytes for the magic key, @@ -250,6 +250,26 @@ crypt_get_header_len(int method_nr) + cryptmethods[method_nr].seed_len; } + +/* + * Get maximum crypt method specific length of the file header in bytes. + */ + int +crypt_get_max_header_len() +{ + int i; + int max = 0; + int temp = 0; + + for (i = 0; i < CRYPT_M_COUNT; ++i) + { + temp = crypt_get_header_len(i); + if (temp > max) + max = temp; + } + return max; +} + /* * Set the crypt method for buffer "buf" to "method_nr" using the int value as * returned by crypt_method_nr_from_name(). @@ -403,8 +423,10 @@ crypt_create_for_writing( #ifdef FEAT_SODIUM if (sodium_init() >= 0) { - randombytes_buf(salt, salt_len); - randombytes_buf(seed, seed_len); + if (salt_len > 0) + randombytes_buf(salt, salt_len); + if (seed_len > 0) + randombytes_buf(seed, seed_len); } else #endif @@ -581,6 +603,13 @@ crypt_check_method(int method) msg_scroll = TRUE; msg(_("Warning: Using a weak encryption method; see :help 'cm'")); } +} + +#ifdef FEAT_SODIUM + static void +crypt_check_swapfile_curbuf(void) +{ + int method = crypt_get_method_nr(curbuf); if (method == CRYPT_M_SOD) { // encryption uses padding and MAC, that does not work very well with @@ -590,11 +619,11 @@ crypt_check_method(int method) #ifdef FEAT_PERSISTENT_UNDO set_option_value((char_u *)"udf", 0, NULL, OPT_LOCAL); #endif - msg_scroll = TRUE; msg(_("Note: Encryption of swapfile not supported, disabling swap- and undofile")); } } +#endif void crypt_check_current_method(void) @@ -647,6 +676,9 @@ crypt_get_key( set_option_value((char_u *)"key", 0L, p1, OPT_LOCAL); crypt_free_key(p1); p1 = curbuf->b_p_key; +#ifdef FEAT_SODIUM + crypt_check_swapfile_curbuf(); +#endif } break; } @@ -654,10 +686,13 @@ crypt_get_key( } // since the user typed this, no need to wait for return - if (msg_didout) - msg_putchar('\n'); - need_wait_return = FALSE; - msg_didout = FALSE; + if (crypt_get_method_nr(curbuf) != CRYPT_M_SOD) + { + if (msg_didout) + msg_putchar('\n'); + need_wait_return = FALSE; + msg_didout = FALSE; + } crypt_free_key(p2); return p1; @@ -726,6 +761,7 @@ crypt_sodium_init( * "from" and "to" can be equal to encrypt in place. * Call needs to ensure that there is enough space in to (for the header) */ +#if 0 // Currently unused void crypt_sodium_encode( cryptstate_T *state UNUSED, @@ -764,11 +800,13 @@ crypt_sodium_encode( sod_st->count++; # endif } +#endif -/* TODO: Unused +/* * Decrypt "from[len]" into "to[len]". * "from" and "to" can be equal to encrypt in place. */ +#if 0 // Currently unused void crypt_sodium_decode( cryptstate_T *state UNUSED, @@ -841,6 +879,7 @@ fail: vim_free(buf_out); # endif } +#endif /* * Encrypt "from[len]" into "to[len]". @@ -864,7 +903,7 @@ crypt_sodium_buffer_encode( sodium_state_T *sod_st = state->method_state; int first = (sod_st->count == 0); - length = len + crypto_secretstream_xchacha20poly1305_ABYTES + length = (int)len + crypto_secretstream_xchacha20poly1305_ABYTES + (first ? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0); *buf_out = alloc_clear(length); if (*buf_out == NULL) diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -443,6 +443,6 @@ EXTERN char e_libsodium_decryption_faile EXTERN char e_libsodium_cannot_decrypt_buffer[] INIT(= N_("E1199: Cannot decrypt buffer, not enough space")); EXTERN char e_libsodium_decryption_failed[] - INIT(= N_("E1200: Decryption failed: corrupted chunk!")); + INIT(= N_("E1200: Decryption failed!")); EXTERN char e_libsodium_decryption_failed_premature[] INIT(= N_("E1201: Decryption failed: pre-mature end of file!")); diff --git a/src/fileio.c b/src/fileio.c --- a/src/fileio.c +++ b/src/fileio.c @@ -1213,6 +1213,7 @@ retry: * Read bytes from curbuf. Used for converting text read * from stdin. */ + eof = FALSE; if (read_buf_lnum > from) size = 0; else @@ -1261,6 +1262,7 @@ retry: if (!curbuf->b_p_eol) --tlen; size = tlen; + eof = TRUE; break; } } @@ -1276,7 +1278,7 @@ retry: // Let the crypt layer work with a buffer size of 8192 if (filesize == 0) // set size to 8K + Sodium Crypt Metadata - size = WRITEBUFSIZE + 36 + size = WRITEBUFSIZE + crypt_get_max_header_len() + crypto_secretstream_xchacha20poly1305_HEADERBYTES + crypto_secretstream_xchacha20poly1305_ABYTES; diff --git a/src/memline.c b/src/memline.c --- a/src/memline.c +++ b/src/memline.c @@ -497,7 +497,8 @@ ml_set_crypt_key( return; // no memfile yet, nothing to do old_method = crypt_method_nr_from_name(old_cm); - if (old_method == CRYPT_M_SOD || crypt_get_method_nr(buf) == CRYPT_M_SOD) + // Swapfile encryption not supported by XChaCha20 + if (crypt_get_method_nr(buf) == CRYPT_M_SOD && *buf->b_p_key != NUL) { // close the swapfile mf_close_file(buf, TRUE); diff --git a/src/proto/crypt.pro b/src/proto/crypt.pro --- a/src/proto/crypt.pro +++ b/src/proto/crypt.pro @@ -5,6 +5,7 @@ int crypt_works_inplace(cryptstate_T *st int crypt_get_method_nr(buf_T *buf); int crypt_whole_undofile(int method_nr); int crypt_get_header_len(int method_nr); +int crypt_get_max_header_len(void); void crypt_set_cm_option(buf_T *buf, int method_nr); int crypt_self_test(void); cryptstate_T *crypt_create(int method_nr, char_u *key, char_u *salt, int salt_len, char_u *seed, int seed_len); @@ -23,8 +24,6 @@ void crypt_check_current_method(void); char_u *crypt_get_key(int store, int twice); void crypt_append_msg(buf_T *buf); int crypt_sodium_init(cryptstate_T *state, char_u *key, char_u *salt, int salt_len, char_u *seed, int seed_len); -void crypt_sodium_encode(cryptstate_T *state, char_u *from, size_t len, char_u *to, int last); -void crypt_sodium_decode(cryptstate_T *state, char_u *from, size_t len, char_u *to, int last); long crypt_sodium_buffer_encode(cryptstate_T *state, char_u *from, size_t len, char_u **buf_out, int last); long crypt_sodium_buffer_decode(cryptstate_T *state, char_u *from, size_t len, char_u **buf_out, int last); /* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3032, +/**/ 3031, /**/ 3030,