blob: d66e50cc48a8bdb39ade85834a1b4624a2cd2609 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar8f4ac012014-08-10 13:38:34 +02002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * crypt.c: Generic encryption support.
12 */
13#include "vim.h"
14
15#if defined(FEAT_CRYPT) || defined(PROTO)
16/*
17 * Optional encryption support.
18 * Mohsin Ahmed, mosh@sasi.com, 1998-09-24
19 * Based on zip/crypt sources.
20 * Refactored by David Leadbeater, 2014.
21 *
22 * NOTE FOR USA: Since 2000 exporting this code from the USA is allowed to
23 * most countries. There are a few exceptions, but that still should not be a
24 * problem since this code was originally created in Europe and India.
25 *
26 * Blowfish addition originally made by Mohsin Ahmed,
27 * http://www.cs.albany.edu/~mosh 2010-03-14
28 * Based on blowfish by Bruce Schneier (http://www.schneier.com/blowfish.html)
29 * and sha256 by Christophe Devine.
30 */
31
32typedef struct {
Bram Moolenaarc667da52019-11-30 20:52:27 +010033 char *name; // encryption name as used in 'cryptmethod'
34 char *magic; // magic bytes stored in file header
35 int salt_len; // length of salt, or 0 when not using salt
Christian Brabandtf573c6e2021-06-20 14:02:16 +020036 int seed_len; // length of seed, or 0 when not using seed
Bram Moolenaar987411d2019-01-18 22:48:34 +010037#ifdef CRYPT_NOT_INPLACE
Bram Moolenaarc667da52019-11-30 20:52:27 +010038 int works_inplace; // encryption/decryption can be done in-place
Bram Moolenaar987411d2019-01-18 22:48:34 +010039#endif
Bram Moolenaarc667da52019-11-30 20:52:27 +010040 int whole_undofile; // whole undo file is encrypted
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020041
Bram Moolenaarc667da52019-11-30 20:52:27 +010042 // Optional function pointer for a self-test.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020043 int (* self_test_fn)();
44
Bram Moolenaarad3ec762019-04-21 00:00:13 +020045 // Function pointer for initializing encryption/decryption.
Bram Moolenaar6ee96582019-04-27 22:06:37 +020046 int (* init_fn)(cryptstate_T *state, char_u *key,
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020047 char_u *salt, int salt_len, char_u *seed, int seed_len);
48
Bram Moolenaarc667da52019-11-30 20:52:27 +010049 // Function pointers for encoding/decoding from one buffer into another.
50 // Optional, however, these or the _buffer ones should be configured.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020051 void (*encode_fn)(cryptstate_T *state, char_u *from, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020052 char_u *to, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020053 void (*decode_fn)(cryptstate_T *state, char_u *from, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020054 char_u *to, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020055
Bram Moolenaarc667da52019-11-30 20:52:27 +010056 // Function pointers for encoding and decoding, can buffer data if needed.
57 // Optional (however, these or the above should be configured).
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020058 long (*encode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020059 char_u **newptr, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020060 long (*decode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020061 char_u **newptr, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020062
Bram Moolenaarc667da52019-11-30 20:52:27 +010063 // Function pointers for in-place encoding and decoding, used for
64 // crypt_*_inplace(). "from" and "to" arguments will be equal.
65 // These may be the same as decode_fn and encode_fn above, however an
66 // algorithm may implement them in a way that is not interchangeable with
67 // the crypt_(en|de)code() interface (for example because it wishes to add
68 // padding to files).
69 // This method is used for swap and undo files which have a rigid format.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020070 void (*encode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020071 char_u *p2, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020072 void (*decode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020073 char_u *p2, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020074} cryptmethod_T;
75
Bram Moolenaarc667da52019-11-30 20:52:27 +010076// index is method_nr of cryptstate_T, CRYPT_M_*
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020077static cryptmethod_T cryptmethods[CRYPT_M_COUNT] = {
Bram Moolenaarc667da52019-11-30 20:52:27 +010078 // PK_Zip; very weak
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020079 {
80 "zip",
81 "VimCrypt~01!",
82 0,
83 0,
Bram Moolenaar987411d2019-01-18 22:48:34 +010084#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020085 TRUE,
Bram Moolenaar987411d2019-01-18 22:48:34 +010086#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020087 FALSE,
88 NULL,
89 crypt_zip_init,
90 crypt_zip_encode, crypt_zip_decode,
91 NULL, NULL,
92 crypt_zip_encode, crypt_zip_decode,
93 },
94
Bram Moolenaarc667da52019-11-30 20:52:27 +010095 // Blowfish/CFB + SHA-256 custom key derivation; implementation issues.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020096 {
97 "blowfish",
98 "VimCrypt~02!",
99 8,
100 8,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100101#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200102 TRUE,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100103#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200104 FALSE,
105 blowfish_self_test,
106 crypt_blowfish_init,
107 crypt_blowfish_encode, crypt_blowfish_decode,
108 NULL, NULL,
109 crypt_blowfish_encode, crypt_blowfish_decode,
110 },
111
Bram Moolenaarc667da52019-11-30 20:52:27 +0100112 // Blowfish/CFB + SHA-256 custom key derivation; fixed.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200113 {
114 "blowfish2",
115 "VimCrypt~03!",
116 8,
117 8,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100118#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200119 TRUE,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100120#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200121 TRUE,
122 blowfish_self_test,
123 crypt_blowfish_init,
124 crypt_blowfish_encode, crypt_blowfish_decode,
125 NULL, NULL,
126 crypt_blowfish_encode, crypt_blowfish_decode,
127 },
Bram Moolenaard23a8232018-02-10 18:45:26 +0100128
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200129 // XChaCha20 using libsodium
130 {
131 "xchacha20",
132 "VimCrypt~04!",
133#ifdef FEAT_SODIUM
134 crypto_pwhash_argon2id_SALTBYTES, // 16
135#else
136 16,
137#endif
138 8,
139#ifdef CRYPT_NOT_INPLACE
140 FALSE,
141#endif
142 FALSE,
143 NULL,
144 crypt_sodium_init,
Christian Brabandt226b28b2021-06-21 21:08:08 +0200145 NULL, NULL,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200146 crypt_sodium_buffer_encode, crypt_sodium_buffer_decode,
Christian Brabandt226b28b2021-06-21 21:08:08 +0200147 NULL, NULL,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200148 },
149
Bram Moolenaarc667da52019-11-30 20:52:27 +0100150 // NOTE: when adding a new method, use some random bytes for the magic key,
151 // to avoid that a text file is recognized as encrypted.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200152};
153
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200154#ifdef FEAT_SODIUM
155typedef struct {
156 size_t count;
157 unsigned char key[crypto_box_SEEDBYTES];
158 // 32, same as crypto_secretstream_xchacha20poly1305_KEYBYTES
159 crypto_secretstream_xchacha20poly1305_state
160 state;
161} sodium_state_T;
K.Takata1a8825d2022-01-19 13:32:57 +0000162
163
164# ifdef DYNAMIC_SODIUM
K.Takatad68b2fc2022-02-12 11:18:37 +0000165# ifdef MSWIN
166# define SODIUM_PROC FARPROC
167# define load_dll vimLoadLib
168# define symbol_from_dll GetProcAddress
169# define close_dll FreeLibrary
170# define load_dll_error GetWin32Error
171# else
172# error Dynamic loading of libsodium is not supported for now.
173//# define HINSTANCE void*
174//# define SODIUM_PROC void*
175//# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
176//# define symbol_from_dll dlsym
177//# define close_dll dlclose
178//# define load_dll_error dlerror
179# endif
180
K.Takata1a8825d2022-01-19 13:32:57 +0000181# define sodium_init load_sodium
182# define sodium_free dll_sodium_free
183# define sodium_malloc dll_sodium_malloc
184# define sodium_memzero dll_sodium_memzero
185# define sodium_mlock dll_sodium_mlock
186# define sodium_munlock dll_sodium_munlock
187# define crypto_secretstream_xchacha20poly1305_init_push \
188 dll_crypto_secretstream_xchacha20poly1305_init_push
189# define crypto_secretstream_xchacha20poly1305_push \
190 dll_crypto_secretstream_xchacha20poly1305_push
191# define crypto_secretstream_xchacha20poly1305_init_pull \
192 dll_crypto_secretstream_xchacha20poly1305_init_pull
193# define crypto_secretstream_xchacha20poly1305_pull \
194 dll_crypto_secretstream_xchacha20poly1305_pull
195# define crypto_pwhash dll_crypto_pwhash
196# define randombytes_buf dll_randombytes_buf
197
198static int (*dll_sodium_init)(void) = NULL;
199static void (*dll_sodium_free)(void *) = NULL;
200static void *(*dll_sodium_malloc)(const size_t) = NULL;
201static void (*dll_sodium_memzero)(void * const, const size_t) = NULL;
202static int (*dll_sodium_mlock)(void * const, const size_t) = NULL;
203static int (*dll_sodium_munlock)(void * const, const size_t) = NULL;
204static int (*dll_crypto_secretstream_xchacha20poly1305_init_push)
205 (crypto_secretstream_xchacha20poly1305_state *state,
206 unsigned char [],
207 const unsigned char []) = NULL;
208static int (*dll_crypto_secretstream_xchacha20poly1305_push)
209 (crypto_secretstream_xchacha20poly1305_state *state,
210 unsigned char *c, unsigned long long *clen_p,
211 const unsigned char *m, unsigned long long mlen,
212 const unsigned char *ad, unsigned long long adlen, unsigned char tag)
213 = NULL;
214static int (*dll_crypto_secretstream_xchacha20poly1305_init_pull)
215 (crypto_secretstream_xchacha20poly1305_state *state,
216 const unsigned char [],
217 const unsigned char []) = NULL;
218static int (*dll_crypto_secretstream_xchacha20poly1305_pull)
219 (crypto_secretstream_xchacha20poly1305_state *state,
220 unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
221 const unsigned char *c, unsigned long long clen,
222 const unsigned char *ad, unsigned long long adlen) = NULL;
223static int (*dll_crypto_pwhash)(unsigned char * const out,
224 unsigned long long outlen,
225 const char * const passwd, unsigned long long passwdlen,
226 const unsigned char * const salt,
227 unsigned long long opslimit, size_t memlimit, int alg)
228 = NULL;
229static void (*dll_randombytes_buf)(void * const buf, const size_t size);
230
231static struct {
232 const char *name;
K.Takatad68b2fc2022-02-12 11:18:37 +0000233 SODIUM_PROC *ptr;
K.Takata1a8825d2022-01-19 13:32:57 +0000234} sodium_funcname_table[] = {
K.Takatad68b2fc2022-02-12 11:18:37 +0000235 {"sodium_init", (SODIUM_PROC*)&dll_sodium_init},
236 {"sodium_free", (SODIUM_PROC*)&dll_sodium_free},
237 {"sodium_malloc", (SODIUM_PROC*)&dll_sodium_malloc},
238 {"sodium_memzero", (SODIUM_PROC*)&dll_sodium_memzero},
239 {"sodium_mlock", (SODIUM_PROC*)&dll_sodium_mlock},
240 {"sodium_munlock", (SODIUM_PROC*)&dll_sodium_munlock},
241 {"crypto_secretstream_xchacha20poly1305_init_push", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_init_push},
242 {"crypto_secretstream_xchacha20poly1305_push", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_push},
243 {"crypto_secretstream_xchacha20poly1305_init_pull", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_init_pull},
244 {"crypto_secretstream_xchacha20poly1305_pull", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_pull},
245 {"crypto_pwhash", (SODIUM_PROC*)&dll_crypto_pwhash},
246 {"randombytes_buf", (SODIUM_PROC*)&dll_randombytes_buf},
K.Takata1a8825d2022-01-19 13:32:57 +0000247 {NULL, NULL}
248};
249
250 static int
K.Takatad68b2fc2022-02-12 11:18:37 +0000251sodium_runtime_link_init(int verbose)
K.Takata1a8825d2022-01-19 13:32:57 +0000252{
K.Takatad68b2fc2022-02-12 11:18:37 +0000253 static HINSTANCE hsodium = NULL;
254 const char *libname = "libsodium.dll";
K.Takata1a8825d2022-01-19 13:32:57 +0000255 int i;
256
257 if (hsodium != NULL)
K.Takatad68b2fc2022-02-12 11:18:37 +0000258 return OK;
K.Takata1a8825d2022-01-19 13:32:57 +0000259
K.Takatad68b2fc2022-02-12 11:18:37 +0000260 hsodium = load_dll(libname);
K.Takata1a8825d2022-01-19 13:32:57 +0000261 if (hsodium == NULL)
262 {
K.Takatad68b2fc2022-02-12 11:18:37 +0000263 if (verbose)
264 semsg(_(e_could_not_load_library_str_str), libname, load_dll_error());
265 return FAIL;
K.Takata1a8825d2022-01-19 13:32:57 +0000266 }
267
268 for (i = 0; sodium_funcname_table[i].ptr; ++i)
269 {
K.Takatad68b2fc2022-02-12 11:18:37 +0000270 if ((*sodium_funcname_table[i].ptr = symbol_from_dll(hsodium,
K.Takata1a8825d2022-01-19 13:32:57 +0000271 sodium_funcname_table[i].name)) == NULL)
272 {
273 FreeLibrary(hsodium);
274 hsodium = NULL;
K.Takatad68b2fc2022-02-12 11:18:37 +0000275 if (verbose)
276 semsg(_(e_could_not_load_library_function_str), sodium_funcname_table[i].name);
277 return FAIL;
K.Takata1a8825d2022-01-19 13:32:57 +0000278 }
279 }
K.Takatad68b2fc2022-02-12 11:18:37 +0000280 return OK;
281}
282
283 static int
284load_sodium(void)
285{
286 if (sodium_runtime_link_init(TRUE) == FAIL)
287 return -1;
K.Takata1a8825d2022-01-19 13:32:57 +0000288 return dll_sodium_init();
289}
290# endif
K.Takatad68b2fc2022-02-12 11:18:37 +0000291
292# if defined(DYNAMIC_SODIUM) || defined(PROTO)
293 int
294sodium_enabled(int verbose)
295{
296 return sodium_runtime_link_init(verbose) == OK;
297}
298# endif
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200299#endif
300
Bram Moolenaarc667da52019-11-30 20:52:27 +0100301#define CRYPT_MAGIC_LEN 12 // cannot change
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200302static char crypt_magic_head[] = "VimCrypt~";
303
304/*
305 * Return int value for crypt method name.
306 * 0 for "zip", the old method. Also for any non-valid value.
307 * 1 for "blowfish".
308 * 2 for "blowfish2".
309 */
310 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100311crypt_method_nr_from_name(char_u *name)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200312{
313 int i;
314
315 for (i = 0; i < CRYPT_M_COUNT; ++i)
316 if (STRCMP(name, cryptmethods[i].name) == 0)
317 return i;
318 return 0;
319}
320
321/*
322 * Get the crypt method used for a file from "ptr[len]", the magic text at the
323 * start of the file.
324 * Returns -1 when no encryption used.
325 */
326 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100327crypt_method_nr_from_magic(char *ptr, int len)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200328{
329 int i;
330
331 if (len < CRYPT_MAGIC_LEN)
332 return -1;
333
334 for (i = 0; i < CRYPT_M_COUNT; i++)
335 if (memcmp(ptr, cryptmethods[i].magic, CRYPT_MAGIC_LEN) == 0)
336 return i;
337
338 i = (int)STRLEN(crypt_magic_head);
339 if (len >= i && memcmp(ptr, crypt_magic_head, i) == 0)
Bram Moolenaar9d00e4a2022-01-05 17:49:15 +0000340 emsg(_(e_file_is_encrypted_with_unknown_method));
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200341
342 return -1;
343}
344
Bram Moolenaar987411d2019-01-18 22:48:34 +0100345#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200346/*
347 * Return TRUE if the crypt method for "method_nr" can be done in-place.
348 */
349 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100350crypt_works_inplace(cryptstate_T *state)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200351{
352 return cryptmethods[state->method_nr].works_inplace;
353}
Bram Moolenaar987411d2019-01-18 22:48:34 +0100354#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200355
356/*
357 * Get the crypt method for buffer "buf" as a number.
358 */
359 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100360crypt_get_method_nr(buf_T *buf)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200361{
362 return crypt_method_nr_from_name(*buf->b_p_cm == NUL ? p_cm : buf->b_p_cm);
363}
364
365/*
366 * Return TRUE when the buffer uses an encryption method that encrypts the
367 * whole undo file, not only the text.
368 */
369 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100370crypt_whole_undofile(int method_nr)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200371{
372 return cryptmethods[method_nr].whole_undofile;
373}
374
375/*
Bram Moolenaar32aa1022019-11-02 22:54:41 +0100376 * Get crypt method specific length of the file header in bytes.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200377 */
378 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100379crypt_get_header_len(int method_nr)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200380{
381 return CRYPT_MAGIC_LEN
382 + cryptmethods[method_nr].salt_len
383 + cryptmethods[method_nr].seed_len;
384}
385
Christian Brabandt226b28b2021-06-21 21:08:08 +0200386
Dominique Pelle748b3082022-01-08 12:41:16 +0000387#if defined(FEAT_SODIUM) || defined(PROTO)
Christian Brabandt226b28b2021-06-21 21:08:08 +0200388/*
389 * Get maximum crypt method specific length of the file header in bytes.
390 */
391 int
392crypt_get_max_header_len()
393{
394 int i;
395 int max = 0;
396 int temp = 0;
397
398 for (i = 0; i < CRYPT_M_COUNT; ++i)
399 {
400 temp = crypt_get_header_len(i);
401 if (temp > max)
402 max = temp;
403 }
404 return max;
405}
Dominique Pelle748b3082022-01-08 12:41:16 +0000406#endif
Christian Brabandt226b28b2021-06-21 21:08:08 +0200407
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200408/*
409 * Set the crypt method for buffer "buf" to "method_nr" using the int value as
410 * returned by crypt_method_nr_from_name().
411 */
412 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100413crypt_set_cm_option(buf_T *buf, int method_nr)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200414{
415 free_string_option(buf->b_p_cm);
416 buf->b_p_cm = vim_strsave((char_u *)cryptmethods[method_nr].name);
417}
418
419/*
420 * If the crypt method for the current buffer has a self-test, run it and
421 * return OK/FAIL.
422 */
423 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100424crypt_self_test(void)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200425{
426 int method_nr = crypt_get_method_nr(curbuf);
427
428 if (cryptmethods[method_nr].self_test_fn == NULL)
429 return OK;
430 return cryptmethods[method_nr].self_test_fn();
431}
432
433/*
434 * Allocate a crypt state and initialize it.
Bram Moolenaar6ee96582019-04-27 22:06:37 +0200435 * Return NULL for failure.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200436 */
437 cryptstate_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100438crypt_create(
439 int method_nr,
440 char_u *key,
441 char_u *salt,
442 int salt_len,
443 char_u *seed,
444 int seed_len)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200445{
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200446 cryptstate_T *state = ALLOC_ONE(cryptstate_T);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200447
Bram Moolenaar6ee96582019-04-27 22:06:37 +0200448 if (state == NULL)
449 return state;
450
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200451 state->method_nr = method_nr;
Bram Moolenaar6ee96582019-04-27 22:06:37 +0200452 if (cryptmethods[method_nr].init_fn(
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200453 state, key, salt, salt_len, seed, seed_len) == FAIL)
Bram Moolenaar6ee96582019-04-27 22:06:37 +0200454 {
455 vim_free(state);
456 return NULL;
457 }
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200458 return state;
459}
460
461/*
462 * Allocate a crypt state from a file header and initialize it.
463 * Assumes that header contains at least the number of bytes that
464 * crypt_get_header_len() returns for "method_nr".
465 */
466 cryptstate_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100467crypt_create_from_header(
468 int method_nr,
469 char_u *key,
470 char_u *header)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200471{
472 char_u *salt = NULL;
473 char_u *seed = NULL;
474 int salt_len = cryptmethods[method_nr].salt_len;
475 int seed_len = cryptmethods[method_nr].seed_len;
476
477 if (salt_len > 0)
478 salt = header + CRYPT_MAGIC_LEN;
479 if (seed_len > 0)
480 seed = header + CRYPT_MAGIC_LEN + salt_len;
481
482 return crypt_create(method_nr, key, salt, salt_len, seed, seed_len);
483}
484
485/*
486 * Read the crypt method specific header data from "fp".
487 * Return an allocated cryptstate_T or NULL on error.
488 */
489 cryptstate_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100490crypt_create_from_file(FILE *fp, char_u *key)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200491{
492 int method_nr;
493 int header_len;
494 char magic_buffer[CRYPT_MAGIC_LEN];
495 char_u *buffer;
496 cryptstate_T *state;
497
498 if (fread(magic_buffer, CRYPT_MAGIC_LEN, 1, fp) != 1)
499 return NULL;
500 method_nr = crypt_method_nr_from_magic(magic_buffer, CRYPT_MAGIC_LEN);
501 if (method_nr < 0)
502 return NULL;
503
504 header_len = crypt_get_header_len(method_nr);
505 if ((buffer = alloc(header_len)) == NULL)
506 return NULL;
507 mch_memmove(buffer, magic_buffer, CRYPT_MAGIC_LEN);
508 if (header_len > CRYPT_MAGIC_LEN
509 && fread(buffer + CRYPT_MAGIC_LEN,
510 header_len - CRYPT_MAGIC_LEN, 1, fp) != 1)
511 {
512 vim_free(buffer);
513 return NULL;
514 }
515
516 state = crypt_create_from_header(method_nr, key, buffer);
517 vim_free(buffer);
518 return state;
519}
520
521/*
522 * Allocate a cryptstate_T for writing and initialize it with "key".
523 * Allocates and fills in the header and stores it in "header", setting
524 * "header_len". The header may include salt and seed, depending on
525 * cryptmethod. Caller must free header.
526 * Returns the state or NULL on failure.
527 */
528 cryptstate_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100529crypt_create_for_writing(
530 int method_nr,
531 char_u *key,
532 char_u **header,
533 int *header_len)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200534{
535 int len = crypt_get_header_len(method_nr);
536 char_u *salt = NULL;
537 char_u *seed = NULL;
538 int salt_len = cryptmethods[method_nr].salt_len;
539 int seed_len = cryptmethods[method_nr].seed_len;
540 cryptstate_T *state;
541
542 *header_len = len;
543 *header = alloc(len);
544 if (*header == NULL)
545 return NULL;
546
547 mch_memmove(*header, cryptmethods[method_nr].magic, CRYPT_MAGIC_LEN);
548 if (salt_len > 0 || seed_len > 0)
549 {
550 if (salt_len > 0)
551 salt = *header + CRYPT_MAGIC_LEN;
552 if (seed_len > 0)
553 seed = *header + CRYPT_MAGIC_LEN + salt_len;
554
Bram Moolenaarc667da52019-11-30 20:52:27 +0100555 // TODO: Should this be crypt method specific? (Probably not worth
556 // it). sha2_seed is pretty bad for large amounts of entropy, so make
557 // that into something which is suitable for anything.
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200558#ifdef FEAT_SODIUM
559 if (sodium_init() >= 0)
560 {
Christian Brabandt226b28b2021-06-21 21:08:08 +0200561 if (salt_len > 0)
562 randombytes_buf(salt, salt_len);
563 if (seed_len > 0)
564 randombytes_buf(seed, seed_len);
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200565 }
566 else
567#endif
568 sha2_seed(salt, salt_len, seed, seed_len);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200569 }
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200570 state = crypt_create(method_nr, key, salt, salt_len, seed, seed_len);
571 if (state == NULL)
Bram Moolenaard23a8232018-02-10 18:45:26 +0100572 VIM_CLEAR(*header);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200573 return state;
574}
575
576/*
577 * Free the crypt state.
578 */
579 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100580crypt_free_state(cryptstate_T *state)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200581{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200582#ifdef FEAT_SODIUM
583 if (state->method_nr == CRYPT_M_SOD)
584 {
Bram Moolenaar131530a2021-07-29 20:37:49 +0200585 sodium_munlock(((sodium_state_T *)state->method_state)->key,
586 crypto_box_SEEDBYTES);
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200587 sodium_memzero(state->method_state, sizeof(sodium_state_T));
588 sodium_free(state->method_state);
589 }
590 else
591#endif
592 vim_free(state->method_state);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200593 vim_free(state);
594}
595
Bram Moolenaar987411d2019-01-18 22:48:34 +0100596#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200597/*
598 * Encode "from[len]" and store the result in a newly allocated buffer, which
599 * is stored in "newptr".
600 * Return number of bytes in "newptr", 0 for need more or -1 on error.
601 */
602 long
Bram Moolenaar7454a062016-01-30 15:14:10 +0100603crypt_encode_alloc(
604 cryptstate_T *state,
605 char_u *from,
606 size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200607 char_u **newptr,
608 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200609{
610 cryptmethod_T *method = &cryptmethods[state->method_nr];
611
612 if (method->encode_buffer_fn != NULL)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100613 // Has buffer function, pass through.
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200614 return method->encode_buffer_fn(state, from, len, newptr, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200615 if (len == 0)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100616 // Not buffering, just return EOF.
Bram Moolenaar9b8f0212014-08-13 22:05:53 +0200617 return (long)len;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200618
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200619 *newptr = alloc(len + 50);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200620 if (*newptr == NULL)
621 return -1;
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200622 method->encode_fn(state, from, len, *newptr, last);
Bram Moolenaar9b8f0212014-08-13 22:05:53 +0200623 return (long)len;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200624}
625
626/*
627 * Decrypt "ptr[len]" and store the result in a newly allocated buffer, which
628 * is stored in "newptr".
629 * Return number of bytes in "newptr", 0 for need more or -1 on error.
630 */
631 long
Bram Moolenaar7454a062016-01-30 15:14:10 +0100632crypt_decode_alloc(
633 cryptstate_T *state,
634 char_u *ptr,
635 long len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200636 char_u **newptr,
637 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200638{
639 cryptmethod_T *method = &cryptmethods[state->method_nr];
640
641 if (method->decode_buffer_fn != NULL)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100642 // Has buffer function, pass through.
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200643 return method->decode_buffer_fn(state, ptr, len, newptr, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200644
645 if (len == 0)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100646 // Not buffering, just return EOF.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200647 return len;
648
649 *newptr = alloc(len);
650 if (*newptr == NULL)
651 return -1;
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200652 method->decode_fn(state, ptr, len, *newptr, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200653 return len;
654}
Bram Moolenaar987411d2019-01-18 22:48:34 +0100655#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200656
657/*
658 * Encrypting "from[len]" into "to[len]".
659 */
660 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100661crypt_encode(
662 cryptstate_T *state,
663 char_u *from,
664 size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200665 char_u *to,
666 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200667{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200668 cryptmethods[state->method_nr].encode_fn(state, from, len, to, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200669}
670
Bram Moolenaar987411d2019-01-18 22:48:34 +0100671#if 0 // unused
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200672/*
673 * decrypting "from[len]" into "to[len]".
674 */
675 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100676crypt_decode(
677 cryptstate_T *state,
678 char_u *from,
679 size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200680 char_u *to,
681 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200682{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200683 cryptmethods[state->method_nr].decode_fn(state, from, len, to, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200684}
Bram Moolenaar987411d2019-01-18 22:48:34 +0100685#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200686
687/*
688 * Simple inplace encryption, modifies "buf[len]" in place.
689 */
690 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100691crypt_encode_inplace(
692 cryptstate_T *state,
693 char_u *buf,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200694 size_t len,
695 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200696{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200697 cryptmethods[state->method_nr].encode_inplace_fn(state, buf, len,
698 buf, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200699}
700
701/*
702 * Simple inplace decryption, modifies "buf[len]" in place.
703 */
704 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100705crypt_decode_inplace(
706 cryptstate_T *state,
707 char_u *buf,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200708 size_t len,
709 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200710{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200711 cryptmethods[state->method_nr].decode_inplace_fn(state, buf, len,
712 buf, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200713}
714
715/*
716 * Free an allocated crypt key. Clear the text to make sure it doesn't stay
717 * in memory anywhere.
718 */
719 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100720crypt_free_key(char_u *key)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200721{
722 char_u *p;
723
724 if (key != NULL)
725 {
726 for (p = key; *p != NUL; ++p)
727 *p = 0;
728 vim_free(key);
729 }
730}
731
732/*
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100733 * Check the crypt method and give a warning if it's outdated.
734 */
735 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100736crypt_check_method(int method)
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100737{
738 if (method < CRYPT_M_BF2)
739 {
740 msg_scroll = TRUE;
Bram Moolenaar32526b32019-01-19 17:43:09 +0100741 msg(_("Warning: Using a weak encryption method; see :help 'cm'"));
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100742 }
Christian Brabandt226b28b2021-06-21 21:08:08 +0200743}
744
745#ifdef FEAT_SODIUM
746 static void
747crypt_check_swapfile_curbuf(void)
748{
749 int method = crypt_get_method_nr(curbuf);
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200750 if (method == CRYPT_M_SOD)
751 {
752 // encryption uses padding and MAC, that does not work very well with
753 // swap and undo files, so disable them
754 mf_close_file(curbuf, TRUE); // remove the swap file
755 set_option_value((char_u *)"swf", 0, NULL, OPT_LOCAL);
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200756 msg_scroll = TRUE;
Christian Brabandt8a4c8122021-07-25 14:36:05 +0200757 msg(_("Note: Encryption of swapfile not supported, disabling swap file"));
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200758 }
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100759}
Christian Brabandt226b28b2021-06-21 21:08:08 +0200760#endif
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100761
762 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100763crypt_check_current_method(void)
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100764{
765 crypt_check_method(crypt_get_method_nr(curbuf));
766}
767
768/*
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200769 * Ask the user for a crypt key.
770 * When "store" is TRUE, the new key is stored in the 'key' option, and the
771 * 'key' option value is returned: Don't free it.
772 * When "store" is FALSE, the typed key is returned in allocated memory.
773 * Returns NULL on failure.
774 */
775 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100776crypt_get_key(
777 int store,
Bram Moolenaarc667da52019-11-30 20:52:27 +0100778 int twice) // Ask for the key twice.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200779{
780 char_u *p1, *p2 = NULL;
781 int round;
782
783 for (round = 0; ; ++round)
784 {
785 cmdline_star = TRUE;
786 cmdline_row = msg_row;
787 p1 = getcmdline_prompt(NUL, round == 0
788 ? (char_u *)_("Enter encryption key: ")
789 : (char_u *)_("Enter same key again: "), 0, EXPAND_NOTHING,
790 NULL);
791 cmdline_star = FALSE;
792
793 if (p1 == NULL)
794 break;
795
796 if (round == twice)
797 {
798 if (p2 != NULL && STRCMP(p1, p2) != 0)
799 {
Bram Moolenaar32526b32019-01-19 17:43:09 +0100800 msg(_("Keys don't match!"));
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200801 crypt_free_key(p1);
802 crypt_free_key(p2);
803 p2 = NULL;
Bram Moolenaarc667da52019-11-30 20:52:27 +0100804 round = -1; // do it again
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200805 continue;
806 }
807
808 if (store)
809 {
810 set_option_value((char_u *)"key", 0L, p1, OPT_LOCAL);
811 crypt_free_key(p1);
812 p1 = curbuf->b_p_key;
Christian Brabandt226b28b2021-06-21 21:08:08 +0200813#ifdef FEAT_SODIUM
814 crypt_check_swapfile_curbuf();
815#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200816 }
817 break;
818 }
819 p2 = p1;
820 }
821
Bram Moolenaarc667da52019-11-30 20:52:27 +0100822 // since the user typed this, no need to wait for return
Christian Brabandt226b28b2021-06-21 21:08:08 +0200823 if (crypt_get_method_nr(curbuf) != CRYPT_M_SOD)
824 {
825 if (msg_didout)
826 msg_putchar('\n');
827 need_wait_return = FALSE;
828 msg_didout = FALSE;
829 }
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200830
831 crypt_free_key(p2);
832 return p1;
833}
834
835
836/*
837 * Append a message to IObuff for the encryption/decryption method being used.
838 */
839 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100840crypt_append_msg(
841 buf_T *buf)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200842{
843 if (crypt_get_method_nr(buf) == 0)
844 STRCAT(IObuff, _("[crypted]"));
845 else
846 {
847 STRCAT(IObuff, "[");
848 STRCAT(IObuff, *buf->b_p_cm == NUL ? p_cm : buf->b_p_cm);
849 STRCAT(IObuff, "]");
850 }
851}
852
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200853 int
854crypt_sodium_init(
855 cryptstate_T *state UNUSED,
856 char_u *key UNUSED,
857 char_u *salt UNUSED,
858 int salt_len UNUSED,
859 char_u *seed UNUSED,
860 int seed_len UNUSED)
861{
862# ifdef FEAT_SODIUM
863 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
864 unsigned char dkey[crypto_box_SEEDBYTES]; // 32
865 sodium_state_T *sd_state;
Bram Moolenaar131530a2021-07-29 20:37:49 +0200866 int retval = 0;
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200867
868 if (sodium_init() < 0)
869 return FAIL;
870
871 sd_state = (sodium_state_T *)sodium_malloc(sizeof(sodium_state_T));
872 sodium_memzero(sd_state, sizeof(sodium_state_T));
873
874 // derive a key from the password
875 if (crypto_pwhash(dkey, sizeof(dkey), (const char *)key, STRLEN(key), salt,
876 crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE,
877 crypto_pwhash_ALG_DEFAULT) != 0)
878 {
879 // out of memory
880 sodium_free(sd_state);
881 return FAIL;
882 }
883 memcpy(sd_state->key, dkey, crypto_box_SEEDBYTES);
Bram Moolenaar131530a2021-07-29 20:37:49 +0200884
885 retval += sodium_mlock(sd_state->key, crypto_box_SEEDBYTES);
886 retval += sodium_mlock(key, STRLEN(key));
887
888 if (retval < 0)
889 {
890 emsg(_(e_encryption_sodium_mlock_failed));
891 sodium_free(sd_state);
892 return FAIL;
893 }
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200894 sd_state->count = 0;
895 state->method_state = sd_state;
896
897 return OK;
898# else
899 emsg(e_libsodium_not_built_in);
900 return FAIL;
901# endif
902}
903
904/*
905 * Encrypt "from[len]" into "to[len]".
906 * "from" and "to" can be equal to encrypt in place.
907 * Call needs to ensure that there is enough space in to (for the header)
908 */
Christian Brabandt226b28b2021-06-21 21:08:08 +0200909#if 0 // Currently unused
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200910 void
911crypt_sodium_encode(
912 cryptstate_T *state UNUSED,
913 char_u *from UNUSED,
914 size_t len UNUSED,
915 char_u *to UNUSED,
916 int last UNUSED)
917{
918# ifdef FEAT_SODIUM
919 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
920 sodium_state_T *sod_st = state->method_state;
921 unsigned char tag = last
922 ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0;
923
924 if (sod_st->count == 0)
925 {
926 if (len <= crypto_secretstream_xchacha20poly1305_HEADERBYTES)
927 {
928 emsg(e_libsodium_cannot_encrypt_header);
929 return;
930 }
931 crypto_secretstream_xchacha20poly1305_init_push(&sod_st->state,
932 to, sod_st->key);
933 to += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
934 }
935
936 if (sod_st->count && len <= crypto_secretstream_xchacha20poly1305_ABYTES)
937 {
938 emsg(e_libsodium_cannot_encrypt_buffer);
939 return;
940 }
941
942 crypto_secretstream_xchacha20poly1305_push(&sod_st->state, to, NULL,
943 from, len, NULL, 0, tag);
944
945 sod_st->count++;
946# endif
947}
Christian Brabandt226b28b2021-06-21 21:08:08 +0200948#endif
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200949
Christian Brabandt226b28b2021-06-21 21:08:08 +0200950/*
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200951 * Decrypt "from[len]" into "to[len]".
952 * "from" and "to" can be equal to encrypt in place.
953 */
Christian Brabandt226b28b2021-06-21 21:08:08 +0200954#if 0 // Currently unused
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200955 void
956crypt_sodium_decode(
957 cryptstate_T *state UNUSED,
958 char_u *from UNUSED,
959 size_t len UNUSED,
960 char_u *to UNUSED,
961 int last UNUSED)
962{
963# ifdef FEAT_SODIUM
964 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
965 sodium_state_T *sod_st = state->method_state;
966 unsigned char tag;
967 unsigned long long buf_len;
968 char_u *p1 = from;
969 char_u *p2 = to;
970 char_u *buf_out;
971
972 if (sod_st->count == 0
973 && len <= crypto_secretstream_xchacha20poly1305_HEADERBYTES)
974 {
975 emsg(e_libsodium_cannot_decrypt_header);
976 return;
977 }
978
979 buf_out = (char_u *)alloc(len);
980
981 if (buf_out == NULL)
982 {
983 emsg(e_libsodium_cannot_allocate_buffer);
984 return;
985 }
986 if (sod_st->count == 0)
987 {
988 if (crypto_secretstream_xchacha20poly1305_init_pull(
989 &sod_st->state, from, sod_st->key) != 0)
990 {
991 emsg(e_libsodium_decryption_failed_header_incomplete);
992 goto fail;
993 }
994
995 from += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
996 len -= crypto_secretstream_xchacha20poly1305_HEADERBYTES;
997
998 if (p1 == p2)
999 to += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1000 }
1001
1002 if (sod_st->count && len <= crypto_secretstream_xchacha20poly1305_ABYTES)
1003 {
1004 emsg(e_libsodium_cannot_decrypt_buffer);
Dominique Pellecb54bc62021-06-21 20:15:37 +02001005 goto fail;
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001006 }
1007 if (crypto_secretstream_xchacha20poly1305_pull(&sod_st->state,
1008 buf_out, &buf_len, &tag, from, len, NULL, 0) != 0)
1009 {
Dominique Pellecb54bc62021-06-21 20:15:37 +02001010 emsg(e_libsodium_decryption_failed);
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001011 goto fail;
1012 }
1013 sod_st->count++;
1014
1015 if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !last)
1016 {
Dominique Pellecb54bc62021-06-21 20:15:37 +02001017 emsg(e_libsodium_decryption_failed_premature);
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001018 goto fail;
1019 }
1020 if (p1 == p2)
1021 mch_memmove(p2, buf_out, buf_len);
1022
1023fail:
1024 vim_free(buf_out);
1025# endif
1026}
Christian Brabandt226b28b2021-06-21 21:08:08 +02001027#endif
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001028
1029/*
1030 * Encrypt "from[len]" into "to[len]".
1031 * "from" and "to" can be equal to encrypt in place.
1032 */
1033 long
1034crypt_sodium_buffer_encode(
1035 cryptstate_T *state UNUSED,
1036 char_u *from UNUSED,
1037 size_t len UNUSED,
1038 char_u **buf_out UNUSED,
1039 int last UNUSED)
1040{
1041# ifdef FEAT_SODIUM
1042 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
1043 unsigned long long out_len;
1044 char_u *ptr;
1045 unsigned char tag = last
1046 ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0;
1047 int length;
1048 sodium_state_T *sod_st = state->method_state;
1049 int first = (sod_st->count == 0);
1050
Christian Brabandt226b28b2021-06-21 21:08:08 +02001051 length = (int)len + crypto_secretstream_xchacha20poly1305_ABYTES
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001052 + (first ? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0);
1053 *buf_out = alloc_clear(length);
1054 if (*buf_out == NULL)
1055 {
1056 emsg(e_libsodium_cannot_allocate_buffer);
1057 return -1;
1058 }
1059 ptr = *buf_out;
1060
1061 if (first)
1062 {
1063 crypto_secretstream_xchacha20poly1305_init_push(&sod_st->state,
1064 ptr, sod_st->key);
1065 ptr += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1066 }
1067
1068 crypto_secretstream_xchacha20poly1305_push(&sod_st->state, ptr,
1069 &out_len, from, len, NULL, 0, tag);
1070
1071 sod_st->count++;
1072 return out_len + (first
1073 ? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0);
1074# else
1075 return -1;
1076# endif
1077}
1078
1079/*
1080 * Decrypt "from[len]" into "to[len]".
1081 * "from" and "to" can be equal to encrypt in place.
1082 */
1083 long
1084crypt_sodium_buffer_decode(
1085 cryptstate_T *state UNUSED,
1086 char_u *from UNUSED,
1087 size_t len UNUSED,
1088 char_u **buf_out UNUSED,
1089 int last UNUSED)
1090{
1091# ifdef FEAT_SODIUM
1092 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
1093 sodium_state_T *sod_st = state->method_state;
1094 unsigned char tag;
1095 unsigned long long out_len;
1096 *buf_out = alloc_clear(len);
1097 if (*buf_out == NULL)
1098 {
1099 emsg(e_libsodium_cannot_allocate_buffer);
1100 return -1;
1101 }
1102
1103 if (sod_st->count == 0)
1104 {
1105 if (crypto_secretstream_xchacha20poly1305_init_pull(&sod_st->state,
1106 from, sod_st->key) != 0)
1107 {
1108 emsg(e_libsodium_decryption_failed_header_incomplete);
1109 return -1;
1110 }
1111 from += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1112 len -= crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1113 sod_st->count++;
1114 }
1115 if (crypto_secretstream_xchacha20poly1305_pull(&sod_st->state,
1116 *buf_out, &out_len, &tag, from, len, NULL, 0) != 0)
1117 {
Dominique Pellecb54bc62021-06-21 20:15:37 +02001118 emsg(e_libsodium_decryption_failed);
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001119 return -1;
1120 }
1121
1122 if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !last)
Dominique Pellecb54bc62021-06-21 20:15:37 +02001123 emsg(e_libsodium_decryption_failed_premature);
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001124 return (long) out_len;
1125# else
1126 return -1;
1127# endif
1128}
1129
K.Takata1a8825d2022-01-19 13:32:57 +00001130# if defined(FEAT_SODIUM) || defined(PROTO)
1131 int
1132crypt_sodium_munlock(void *const addr, const size_t len)
1133{
1134 return sodium_munlock(addr, len);
1135}
1136
1137 void
1138crypt_sodium_randombytes_buf(void *const buf, const size_t size)
1139{
1140 randombytes_buf(buf, size);
1141}
1142# endif
1143
Bram Moolenaarc667da52019-11-30 20:52:27 +01001144#endif // FEAT_CRYPT