diff src/fileio.c @ 24970:7e9e53a0368f v8.2.3022

patch 8.2.3022: available encryption methods are not strong enough Commit: https://github.com/vim/vim/commit/f573c6e1ed58d46d694c802eaf5ae3662a952744 Author: Christian Brabandt <cb@256bit.org> Date: Sun Jun 20 14:02:16 2021 +0200 patch 8.2.3022: available encryption methods are not strong enough Problem: Available encryption methods are not strong enough. Solution: Add initial support for xchaha20. (Christian Brabandt, closes #8394)
author Bram Moolenaar <Bram@vim.org>
date Sun, 20 Jun 2021 14:15:07 +0200
parents 7334bf933510
children 85d1e82ed134
line wrap: on
line diff
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -13,6 +13,10 @@
 
 #include "vim.h"
 
+#ifdef FEAT_SODIUM
+# include <sodium.h>
+#endif
+
 #if defined(__TANDEM)
 # include <limits.h>		// for SSIZE_MAX
 #endif
@@ -148,6 +152,8 @@ readfile(
     char_u	*p;
     off_T	filesize = 0;
     int		skip_read = FALSE;
+    off_T       filesize_disk = 0;      // file size read from disk
+    off_T       filesize_count = 0;     // counter
 #ifdef FEAT_CRYPT
     char_u	*cryptkey = NULL;
     int		did_ask_for_key = FALSE;
@@ -215,6 +221,7 @@ readfile(
     int		using_b_ffname;
     int		using_b_fname;
     static char *msg_is_a_directory = N_("is a directory");
+    int         eof;
 
     au_did_filetype = FALSE; // reset before triggering any autocommands
 
@@ -405,6 +412,7 @@ readfile(
 	{
 	    buf_store_time(curbuf, &st, fname);
 	    curbuf->b_mtime_read = curbuf->b_mtime;
+	    filesize_disk = st.st_size;
 #ifdef UNIX
 	    /*
 	     * Use the protection bits of the original file for the swap file.
@@ -1080,6 +1088,7 @@ retry:
     {
 	linerest = 0;
 	filesize = 0;
+	filesize_count = 0;
 	skip_count = lines_to_skip;
 	read_count = lines_to_read;
 	conv_restlen = 0;
@@ -1263,7 +1272,23 @@ retry:
 		    /*
 		     * Read bytes from the file.
 		     */
+# ifdef FEAT_SODIUM
+		    // Let the crypt layer work with a buffer size of 8192
+		    if (filesize == 0)
+			// set size to 8K + Sodium Crypt Metadata
+			size = WRITEBUFSIZE + 36
+		     + crypto_secretstream_xchacha20poly1305_HEADERBYTES
+		     + crypto_secretstream_xchacha20poly1305_ABYTES;
+
+		    else if (filesize > 0 && (curbuf->b_cryptstate != NULL &&
+			 curbuf->b_cryptstate->method_nr == CRYPT_M_SOD))
+			size = WRITEBUFSIZE + crypto_secretstream_xchacha20poly1305_ABYTES;
+# endif
+		    eof = size;
 		    size = read_eintr(fd, ptr, size);
+		    filesize_count += size;
+		    // hit end of file
+		    eof = (size < eof || filesize_count == filesize_disk);
 		}
 
 #ifdef FEAT_CRYPT
@@ -1285,7 +1310,8 @@ retry:
 		    if (crypt_works_inplace(curbuf->b_cryptstate))
 		    {
 # endif
-			crypt_decode_inplace(curbuf->b_cryptstate, ptr, size);
+			crypt_decode_inplace(curbuf->b_cryptstate, ptr,
+								    size, eof);
 # ifdef CRYPT_NOT_INPLACE
 		    }
 		    else
@@ -1294,8 +1320,16 @@ retry:
 			int	decrypted_size;
 
 			decrypted_size = crypt_decode_alloc(
-				    curbuf->b_cryptstate, ptr, size, &newptr);
-
+				    curbuf->b_cryptstate, ptr, size,
+								 &newptr, eof);
+
+			if (decrypted_size < 0)
+			{
+			    // error message already given
+			    error = TRUE;
+			    vim_free(newptr);
+			    break;
+			}
 			// If the crypt layer is buffering, not producing
 			// anything yet, need to read more.
 			if (decrypted_size == 0)
@@ -1325,6 +1359,7 @@ retry:
 			    if (newptr != NULL)
 				mch_memmove(new_buffer + linerest, newptr,
 							      decrypted_size);
+			    vim_free(newptr);
 			}
 
 			if (new_buffer != NULL)
@@ -1334,6 +1369,7 @@ retry:
 			    new_buffer = NULL;
 			    line_start = buffer;
 			    ptr = buffer + linerest;
+			    real_size = size;
 			}
 			size = decrypted_size;
 		    }