diff options
author | Christian Brabandt <cb@256bit.org> | 2023-04-23 17:50:22 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2023-04-23 17:50:22 +0100 |
commit | aae583441bcdbb0bfef3b8a1d193e04ae09ca95d (patch) | |
tree | e3cf7c27fc02e1232fe5ab8f8da32581e9782718 /src/fileio.c | |
parent | dcd40cfca0fe0e65d405ce9711745a8ec846c30c (diff) |
patch 9.0.1481: decrypting with libsodium may fail if the library changesv9.0.1481
Problem: Decrypting with libsodium may fail if the library changes.
Solution: Add parameters used to the encrypted file header. (Christian
Brabandt, closes #12279)
Diffstat (limited to 'src/fileio.c')
-rw-r--r-- | src/fileio.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/fileio.c b/src/fileio.c index 19664201e9..8d3e6f5fa7 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -218,6 +218,9 @@ readfile( int using_b_fname; static char *msg_is_a_directory = N_("is a directory"); int eof; +#ifdef FEAT_SODIUM + int may_need_lseek = FALSE; +#endif au_did_filetype = FALSE; // reset before triggering any autocommands @@ -1282,15 +1285,43 @@ retry: */ # ifdef FEAT_SODIUM // Let the crypt layer work with a buffer size of 8192 + // + // Sodium encryption requires a fixed block size to + // successfully decrypt. However, unfortunately the file + // header size changes between xchacha20 and xchacha20v2 by + // 'add_len' bytes. + // So we will now read the maximum header size + encryption + // metadata, but after determining to read an xchacha20 + // encrypted file, we have to rewind the file descriptor by + // 'add_len' bytes in the second round. + // + // Be careful with changing it, it needs to stay the same + // for reading back previously encrypted files! if (filesize == 0) + { // set size to 8K + Sodium Crypt Metadata size = WRITEBUFSIZE + crypt_get_max_header_len() + crypto_secretstream_xchacha20poly1305_HEADERBYTES + crypto_secretstream_xchacha20poly1305_ABYTES; + may_need_lseek = TRUE; + } - else if (filesize > 0 && (curbuf->b_cryptstate != NULL && - curbuf->b_cryptstate->method_nr == CRYPT_M_SOD)) + else if (filesize > 0 && (curbuf->b_cryptstate != NULL + && crypt_method_is_sodium( + curbuf->b_cryptstate->method_nr))) + { size = WRITEBUFSIZE + crypto_secretstream_xchacha20poly1305_ABYTES; + // need to rewind by - add_len from CRYPT_M_SOD2 (see + // description above) + if (curbuf->b_cryptstate->method_nr == CRYPT_M_SOD + && !eof && may_need_lseek) + { + lseek(fd, crypt_get_header_len( + curbuf->b_cryptstate->method_nr) + - crypt_get_max_header_len(), SEEK_CUR); + may_need_lseek = FALSE; + } + } # endif eof = size; size = read_eintr(fd, ptr, size); |