blob: 09e90119641171089c73de06087968e02e2894df [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 {
ichizok35a2ec12023-04-25 15:27: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
36 int seed_len; // length of seed, or 0 when not using seed
37 int add_len; // additional length in the header needed for storing
38 // custom data
Bram Moolenaar987411d2019-01-18 22:48:34 +010039#ifdef CRYPT_NOT_INPLACE
ichizok35a2ec12023-04-25 15:27:27 +010040 int works_inplace; // encryption/decryption can be done in-place
Bram Moolenaar987411d2019-01-18 22:48:34 +010041#endif
ichizok35a2ec12023-04-25 15:27:27 +010042 int whole_undofile; // whole undo file is encrypted
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020043
Bram Moolenaarc667da52019-11-30 20:52:27 +010044 // Optional function pointer for a self-test.
ichizok35a2ec12023-04-25 15:27:27 +010045 int (*self_test_fn)(void);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020046
Bram Moolenaarad3ec762019-04-21 00:00:13 +020047 // Function pointer for initializing encryption/decryption.
ichizok35a2ec12023-04-25 15:27:27 +010048 int (* init_fn)(cryptstate_T *state, char_u *key, crypt_arg_T *arg);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020049
Bram Moolenaarc667da52019-11-30 20:52:27 +010050 // Function pointers for encoding/decoding from one buffer into another.
51 // Optional, however, these or the _buffer ones should be configured.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020052 void (*encode_fn)(cryptstate_T *state, char_u *from, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020053 char_u *to, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020054 void (*decode_fn)(cryptstate_T *state, char_u *from, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020055 char_u *to, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020056
Bram Moolenaarc667da52019-11-30 20:52:27 +010057 // Function pointers for encoding and decoding, can buffer data if needed.
58 // Optional (however, these or the above should be configured).
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020059 long (*encode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020060 char_u **newptr, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020061 long (*decode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020062 char_u **newptr, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020063
Bram Moolenaarc667da52019-11-30 20:52:27 +010064 // Function pointers for in-place encoding and decoding, used for
65 // crypt_*_inplace(). "from" and "to" arguments will be equal.
66 // These may be the same as decode_fn and encode_fn above, however an
67 // algorithm may implement them in a way that is not interchangeable with
68 // the crypt_(en|de)code() interface (for example because it wishes to add
69 // padding to files).
70 // This method is used for swap and undo files which have a rigid format.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020071 void (*encode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020072 char_u *p2, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020073 void (*decode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +020074 char_u *p2, int last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020075} cryptmethod_T;
76
Christian Brabandtaae58342023-04-23 17:50:22 +010077static int crypt_sodium_init_(cryptstate_T *state, char_u *key, crypt_arg_T *arg);
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +010078static long crypt_sodium_buffer_decode(cryptstate_T *state, char_u *from, size_t len, char_u **buf_out, int last);
79static long crypt_sodium_buffer_encode(cryptstate_T *state, char_u *from, size_t len, char_u **buf_out, int last);
Christian Brabandt6019fed2023-07-11 22:38:29 +020080# if defined(FEAT_SODIUM) || defined(PROTO)
81static void crypt_long_long_to_char(long long n, char_u *s);
82static void crypt_int_to_char(int n, char_u *s);
83static long long crypt_char_to_long_long(char_u *s);
84static int crypt_char_to_int(char_u *s);
85#endif
Christian Brabandtaae58342023-04-23 17:50:22 +010086#if defined(FEAT_EVAL) && defined(FEAT_SODIUM)
ichizok35a2ec12023-04-25 15:27:27 +010087static void crypt_sodium_report_hash_params(unsigned long long opslimit, unsigned long long ops_def, size_t memlimit, size_t mem_def, int alg, int alg_def);
Christian Brabandtaae58342023-04-23 17:50:22 +010088#endif
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +010089
Bram Moolenaarc667da52019-11-30 20:52:27 +010090// index is method_nr of cryptstate_T, CRYPT_M_*
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020091static cryptmethod_T cryptmethods[CRYPT_M_COUNT] = {
Bram Moolenaarc667da52019-11-30 20:52:27 +010092 // PK_Zip; very weak
Bram Moolenaar8f4ac012014-08-10 13:38:34 +020093 {
94 "zip",
95 "VimCrypt~01!",
96 0,
97 0,
Christian Brabandtaae58342023-04-23 17:50:22 +010098 0,
Bram Moolenaar987411d2019-01-18 22:48:34 +010099#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200100 TRUE,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100101#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200102 FALSE,
103 NULL,
104 crypt_zip_init,
105 crypt_zip_encode, crypt_zip_decode,
106 NULL, NULL,
107 crypt_zip_encode, crypt_zip_decode,
108 },
109
Bram Moolenaarc667da52019-11-30 20:52:27 +0100110 // Blowfish/CFB + SHA-256 custom key derivation; implementation issues.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200111 {
112 "blowfish",
113 "VimCrypt~02!",
114 8,
115 8,
Christian Brabandtaae58342023-04-23 17:50:22 +0100116 0,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100117#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200118 TRUE,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100119#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200120 FALSE,
121 blowfish_self_test,
122 crypt_blowfish_init,
123 crypt_blowfish_encode, crypt_blowfish_decode,
124 NULL, NULL,
125 crypt_blowfish_encode, crypt_blowfish_decode,
126 },
127
Bram Moolenaarc667da52019-11-30 20:52:27 +0100128 // Blowfish/CFB + SHA-256 custom key derivation; fixed.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200129 {
130 "blowfish2",
131 "VimCrypt~03!",
132 8,
133 8,
Christian Brabandtaae58342023-04-23 17:50:22 +0100134 0,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100135#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200136 TRUE,
Bram Moolenaar987411d2019-01-18 22:48:34 +0100137#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200138 TRUE,
139 blowfish_self_test,
140 crypt_blowfish_init,
141 crypt_blowfish_encode, crypt_blowfish_decode,
142 NULL, NULL,
143 crypt_blowfish_encode, crypt_blowfish_decode,
144 },
Bram Moolenaard23a8232018-02-10 18:45:26 +0100145
Christian Brabandtaae58342023-04-23 17:50:22 +0100146 // XChaCha20 using libsodium; implementation issues
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200147 {
148 "xchacha20",
149 "VimCrypt~04!",
150#ifdef FEAT_SODIUM
151 crypto_pwhash_argon2id_SALTBYTES, // 16
152#else
153 16,
154#endif
155 8,
Christian Brabandtaae58342023-04-23 17:50:22 +0100156 0,
157#ifdef CRYPT_NOT_INPLACE
158 FALSE,
159#endif
160 FALSE,
161 NULL,
162 crypt_sodium_init_,
163 NULL, NULL,
164 crypt_sodium_buffer_encode, crypt_sodium_buffer_decode,
165 NULL, NULL,
166 },
167 // XChaCha20 using libsodium; stores parameters in header
168 {
169 "xchacha20v2",
170 "VimCrypt~05!",
171#ifdef FEAT_SODIUM
172 crypto_pwhash_argon2id_SALTBYTES, // 16
173#else
174 16,
175#endif
176 8,
177 // sizeof(crypto_pwhash_OPSLIMIT_INTERACTIVE + crypto_pwhash_MEMLIMIT_INTERACTIVE + crypto_pwhash_ALG_DEFAULT)
178 20,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200179#ifdef CRYPT_NOT_INPLACE
180 FALSE,
181#endif
182 FALSE,
183 NULL,
K.Takataa8cdb4e2022-12-06 16:17:01 +0000184 crypt_sodium_init_,
Christian Brabandt226b28b2021-06-21 21:08:08 +0200185 NULL, NULL,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200186 crypt_sodium_buffer_encode, crypt_sodium_buffer_decode,
Christian Brabandt226b28b2021-06-21 21:08:08 +0200187 NULL, NULL,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200188 },
189
Bram Moolenaarc667da52019-11-30 20:52:27 +0100190 // NOTE: when adding a new method, use some random bytes for the magic key,
191 // to avoid that a text file is recognized as encrypted.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200192};
193
Yegappan Lakshmanana23a11b2023-02-21 14:27:41 +0000194#if defined(FEAT_SODIUM) || defined(PROTO)
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200195typedef struct {
196 size_t count;
197 unsigned char key[crypto_box_SEEDBYTES];
198 // 32, same as crypto_secretstream_xchacha20poly1305_KEYBYTES
199 crypto_secretstream_xchacha20poly1305_state
200 state;
201} sodium_state_T;
K.Takata1a8825d2022-01-19 13:32:57 +0000202
203
204# ifdef DYNAMIC_SODIUM
K.Takatad68b2fc2022-02-12 11:18:37 +0000205# ifdef MSWIN
206# define SODIUM_PROC FARPROC
207# define load_dll vimLoadLib
208# define symbol_from_dll GetProcAddress
209# define close_dll FreeLibrary
210# define load_dll_error GetWin32Error
211# else
212# error Dynamic loading of libsodium is not supported for now.
213//# define HINSTANCE void*
214//# define SODIUM_PROC void*
215//# define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
216//# define symbol_from_dll dlsym
217//# define close_dll dlclose
218//# define load_dll_error dlerror
219# endif
220
K.Takata1a8825d2022-01-19 13:32:57 +0000221# define sodium_init load_sodium
222# define sodium_free dll_sodium_free
223# define sodium_malloc dll_sodium_malloc
224# define sodium_memzero dll_sodium_memzero
225# define sodium_mlock dll_sodium_mlock
226# define sodium_munlock dll_sodium_munlock
227# define crypto_secretstream_xchacha20poly1305_init_push \
228 dll_crypto_secretstream_xchacha20poly1305_init_push
229# define crypto_secretstream_xchacha20poly1305_push \
230 dll_crypto_secretstream_xchacha20poly1305_push
231# define crypto_secretstream_xchacha20poly1305_init_pull \
232 dll_crypto_secretstream_xchacha20poly1305_init_pull
233# define crypto_secretstream_xchacha20poly1305_pull \
234 dll_crypto_secretstream_xchacha20poly1305_pull
235# define crypto_pwhash dll_crypto_pwhash
236# define randombytes_buf dll_randombytes_buf
K.Takataa8cdb4e2022-12-06 16:17:01 +0000237# define randombytes_random dll_randombytes_random
K.Takata1a8825d2022-01-19 13:32:57 +0000238
239static int (*dll_sodium_init)(void) = NULL;
240static void (*dll_sodium_free)(void *) = NULL;
241static void *(*dll_sodium_malloc)(const size_t) = NULL;
242static void (*dll_sodium_memzero)(void * const, const size_t) = NULL;
243static int (*dll_sodium_mlock)(void * const, const size_t) = NULL;
244static int (*dll_sodium_munlock)(void * const, const size_t) = NULL;
245static int (*dll_crypto_secretstream_xchacha20poly1305_init_push)
246 (crypto_secretstream_xchacha20poly1305_state *state,
247 unsigned char [],
248 const unsigned char []) = NULL;
249static int (*dll_crypto_secretstream_xchacha20poly1305_push)
250 (crypto_secretstream_xchacha20poly1305_state *state,
251 unsigned char *c, unsigned long long *clen_p,
252 const unsigned char *m, unsigned long long mlen,
253 const unsigned char *ad, unsigned long long adlen, unsigned char tag)
254 = NULL;
255static int (*dll_crypto_secretstream_xchacha20poly1305_init_pull)
256 (crypto_secretstream_xchacha20poly1305_state *state,
257 const unsigned char [],
258 const unsigned char []) = NULL;
259static int (*dll_crypto_secretstream_xchacha20poly1305_pull)
260 (crypto_secretstream_xchacha20poly1305_state *state,
261 unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
262 const unsigned char *c, unsigned long long clen,
263 const unsigned char *ad, unsigned long long adlen) = NULL;
264static int (*dll_crypto_pwhash)(unsigned char * const out,
265 unsigned long long outlen,
266 const char * const passwd, unsigned long long passwdlen,
267 const unsigned char * const salt,
268 unsigned long long opslimit, size_t memlimit, int alg)
269 = NULL;
270static void (*dll_randombytes_buf)(void * const buf, const size_t size);
K.Takataa8cdb4e2022-12-06 16:17:01 +0000271static uint32_t (*dll_randombytes_random)(void);
K.Takata1a8825d2022-01-19 13:32:57 +0000272
273static struct {
274 const char *name;
K.Takatad68b2fc2022-02-12 11:18:37 +0000275 SODIUM_PROC *ptr;
K.Takata1a8825d2022-01-19 13:32:57 +0000276} sodium_funcname_table[] = {
K.Takatad68b2fc2022-02-12 11:18:37 +0000277 {"sodium_init", (SODIUM_PROC*)&dll_sodium_init},
278 {"sodium_free", (SODIUM_PROC*)&dll_sodium_free},
279 {"sodium_malloc", (SODIUM_PROC*)&dll_sodium_malloc},
280 {"sodium_memzero", (SODIUM_PROC*)&dll_sodium_memzero},
281 {"sodium_mlock", (SODIUM_PROC*)&dll_sodium_mlock},
282 {"sodium_munlock", (SODIUM_PROC*)&dll_sodium_munlock},
283 {"crypto_secretstream_xchacha20poly1305_init_push", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_init_push},
284 {"crypto_secretstream_xchacha20poly1305_push", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_push},
285 {"crypto_secretstream_xchacha20poly1305_init_pull", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_init_pull},
286 {"crypto_secretstream_xchacha20poly1305_pull", (SODIUM_PROC*)&dll_crypto_secretstream_xchacha20poly1305_pull},
287 {"crypto_pwhash", (SODIUM_PROC*)&dll_crypto_pwhash},
288 {"randombytes_buf", (SODIUM_PROC*)&dll_randombytes_buf},
K.Takataa8cdb4e2022-12-06 16:17:01 +0000289 {"randombytes_random", (SODIUM_PROC*)&dll_randombytes_random},
K.Takata1a8825d2022-01-19 13:32:57 +0000290 {NULL, NULL}
291};
292
293 static int
K.Takatad68b2fc2022-02-12 11:18:37 +0000294sodium_runtime_link_init(int verbose)
K.Takata1a8825d2022-01-19 13:32:57 +0000295{
K.Takatad68b2fc2022-02-12 11:18:37 +0000296 static HINSTANCE hsodium = NULL;
K.Takatad8f86292022-03-07 15:16:15 +0000297 const char *libname = DYNAMIC_SODIUM_DLL;
K.Takata1a8825d2022-01-19 13:32:57 +0000298 int i;
299
300 if (hsodium != NULL)
K.Takatad68b2fc2022-02-12 11:18:37 +0000301 return OK;
K.Takata1a8825d2022-01-19 13:32:57 +0000302
K.Takatad68b2fc2022-02-12 11:18:37 +0000303 hsodium = load_dll(libname);
K.Takata1a8825d2022-01-19 13:32:57 +0000304 if (hsodium == NULL)
305 {
K.Takatad68b2fc2022-02-12 11:18:37 +0000306 if (verbose)
307 semsg(_(e_could_not_load_library_str_str), libname, load_dll_error());
308 return FAIL;
K.Takata1a8825d2022-01-19 13:32:57 +0000309 }
310
311 for (i = 0; sodium_funcname_table[i].ptr; ++i)
312 {
K.Takatad68b2fc2022-02-12 11:18:37 +0000313 if ((*sodium_funcname_table[i].ptr = symbol_from_dll(hsodium,
K.Takata1a8825d2022-01-19 13:32:57 +0000314 sodium_funcname_table[i].name)) == NULL)
315 {
K.Takatad8f86292022-03-07 15:16:15 +0000316 close_dll(hsodium);
K.Takata1a8825d2022-01-19 13:32:57 +0000317 hsodium = NULL;
K.Takatad68b2fc2022-02-12 11:18:37 +0000318 if (verbose)
319 semsg(_(e_could_not_load_library_function_str), sodium_funcname_table[i].name);
320 return FAIL;
K.Takata1a8825d2022-01-19 13:32:57 +0000321 }
322 }
K.Takatad68b2fc2022-02-12 11:18:37 +0000323 return OK;
324}
325
326 static int
327load_sodium(void)
328{
329 if (sodium_runtime_link_init(TRUE) == FAIL)
330 return -1;
K.Takata1a8825d2022-01-19 13:32:57 +0000331 return dll_sodium_init();
332}
333# endif
K.Takatad68b2fc2022-02-12 11:18:37 +0000334
335# if defined(DYNAMIC_SODIUM) || defined(PROTO)
336 int
337sodium_enabled(int verbose)
338{
339 return sodium_runtime_link_init(verbose) == OK;
340}
341# endif
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200342#endif
343
Bram Moolenaarc667da52019-11-30 20:52:27 +0100344#define CRYPT_MAGIC_LEN 12 // cannot change
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200345static char crypt_magic_head[] = "VimCrypt~";
346
347/*
348 * Return int value for crypt method name.
349 * 0 for "zip", the old method. Also for any non-valid value.
350 * 1 for "blowfish".
351 * 2 for "blowfish2".
352 */
353 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100354crypt_method_nr_from_name(char_u *name)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200355{
356 int i;
357
358 for (i = 0; i < CRYPT_M_COUNT; ++i)
359 if (STRCMP(name, cryptmethods[i].name) == 0)
360 return i;
361 return 0;
362}
363
364/*
365 * Get the crypt method used for a file from "ptr[len]", the magic text at the
366 * start of the file.
367 * Returns -1 when no encryption used.
368 */
369 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100370crypt_method_nr_from_magic(char *ptr, int len)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200371{
372 int i;
373
374 if (len < CRYPT_MAGIC_LEN)
375 return -1;
376
377 for (i = 0; i < CRYPT_M_COUNT; i++)
378 if (memcmp(ptr, cryptmethods[i].magic, CRYPT_MAGIC_LEN) == 0)
379 return i;
380
381 i = (int)STRLEN(crypt_magic_head);
382 if (len >= i && memcmp(ptr, crypt_magic_head, i) == 0)
Bram Moolenaar9d00e4a2022-01-05 17:49:15 +0000383 emsg(_(e_file_is_encrypted_with_unknown_method));
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200384
385 return -1;
386}
387
Bram Moolenaar987411d2019-01-18 22:48:34 +0100388#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200389/*
390 * Return TRUE if the crypt method for "method_nr" can be done in-place.
391 */
392 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100393crypt_works_inplace(cryptstate_T *state)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200394{
395 return cryptmethods[state->method_nr].works_inplace;
396}
Bram Moolenaar987411d2019-01-18 22:48:34 +0100397#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200398
399/*
400 * Get the crypt method for buffer "buf" as a number.
401 */
402 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100403crypt_get_method_nr(buf_T *buf)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200404{
405 return crypt_method_nr_from_name(*buf->b_p_cm == NUL ? p_cm : buf->b_p_cm);
406}
407
408/*
Christian Brabandtaae58342023-04-23 17:50:22 +0100409 * Returns True for Sodium Encryption.
410 */
411 int
412crypt_method_is_sodium(int method)
413{
414 return method == CRYPT_M_SOD || method == CRYPT_M_SOD2;
415}
416
417/*
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200418 * Return TRUE when the buffer uses an encryption method that encrypts the
419 * whole undo file, not only the text.
420 */
421 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100422crypt_whole_undofile(int method_nr)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200423{
424 return cryptmethods[method_nr].whole_undofile;
425}
426
427/*
Bram Moolenaar32aa1022019-11-02 22:54:41 +0100428 * Get crypt method specific length of the file header in bytes.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200429 */
430 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100431crypt_get_header_len(int method_nr)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200432{
433 return CRYPT_MAGIC_LEN
434 + cryptmethods[method_nr].salt_len
Christian Brabandtaae58342023-04-23 17:50:22 +0100435 + cryptmethods[method_nr].seed_len
436 + cryptmethods[method_nr].add_len;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200437}
438
Christian Brabandt226b28b2021-06-21 21:08:08 +0200439
Dominique Pelle748b3082022-01-08 12:41:16 +0000440#if defined(FEAT_SODIUM) || defined(PROTO)
Christian Brabandt226b28b2021-06-21 21:08:08 +0200441/*
442 * Get maximum crypt method specific length of the file header in bytes.
443 */
444 int
Yegappan Lakshmanana23a11b2023-02-21 14:27:41 +0000445crypt_get_max_header_len(void)
Christian Brabandt226b28b2021-06-21 21:08:08 +0200446{
447 int i;
448 int max = 0;
449 int temp = 0;
450
451 for (i = 0; i < CRYPT_M_COUNT; ++i)
452 {
453 temp = crypt_get_header_len(i);
454 if (temp > max)
455 max = temp;
456 }
457 return max;
458}
Dominique Pelle748b3082022-01-08 12:41:16 +0000459#endif
Christian Brabandt226b28b2021-06-21 21:08:08 +0200460
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200461/*
462 * Set the crypt method for buffer "buf" to "method_nr" using the int value as
463 * returned by crypt_method_nr_from_name().
464 */
465 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100466crypt_set_cm_option(buf_T *buf, int method_nr)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200467{
468 free_string_option(buf->b_p_cm);
469 buf->b_p_cm = vim_strsave((char_u *)cryptmethods[method_nr].name);
470}
471
472/*
473 * If the crypt method for the current buffer has a self-test, run it and
474 * return OK/FAIL.
475 */
476 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100477crypt_self_test(void)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200478{
479 int method_nr = crypt_get_method_nr(curbuf);
480
481 if (cryptmethods[method_nr].self_test_fn == NULL)
482 return OK;
483 return cryptmethods[method_nr].self_test_fn();
484}
485
486/*
487 * Allocate a crypt state and initialize it.
Bram Moolenaar6ee96582019-04-27 22:06:37 +0200488 * Return NULL for failure.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200489 */
490 cryptstate_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100491crypt_create(
492 int method_nr,
493 char_u *key,
Christian Brabandtaae58342023-04-23 17:50:22 +0100494 crypt_arg_T *crypt_arg)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200495{
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200496 cryptstate_T *state = ALLOC_ONE(cryptstate_T);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200497
Bram Moolenaar6ee96582019-04-27 22:06:37 +0200498 if (state == NULL)
499 return state;
500
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200501 state->method_nr = method_nr;
Christian Brabandtaae58342023-04-23 17:50:22 +0100502 if (cryptmethods[method_nr].init_fn(state, key, crypt_arg) == FAIL)
Bram Moolenaar6ee96582019-04-27 22:06:37 +0200503 {
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100504 vim_free(state);
505 return NULL;
Bram Moolenaar6ee96582019-04-27 22:06:37 +0200506 }
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200507 return state;
508}
509
510/*
511 * Allocate a crypt state from a file header and initialize it.
512 * Assumes that header contains at least the number of bytes that
513 * crypt_get_header_len() returns for "method_nr".
514 */
515 cryptstate_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100516crypt_create_from_header(
517 int method_nr,
518 char_u *key,
519 char_u *header)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200520{
Christian Brabandtaae58342023-04-23 17:50:22 +0100521 crypt_arg_T arg;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200522
Christian Brabandtaae58342023-04-23 17:50:22 +0100523 CLEAR_FIELD(arg);
524 arg.cat_init_from_file = TRUE;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200525
Christian Brabandtaae58342023-04-23 17:50:22 +0100526 arg.cat_salt_len = cryptmethods[method_nr].salt_len;
527 arg.cat_seed_len = cryptmethods[method_nr].seed_len;
528 arg.cat_add_len = cryptmethods[method_nr].add_len;
529 if (arg.cat_salt_len > 0)
530 arg.cat_salt = header + CRYPT_MAGIC_LEN;
531 if (arg.cat_seed_len > 0)
532 arg.cat_seed = header + CRYPT_MAGIC_LEN + arg.cat_salt_len;
533 if (arg.cat_add_len > 0)
Bram Moolenaar3a2a60c2023-05-27 18:02:55 +0100534 arg.cat_add = header + CRYPT_MAGIC_LEN
535 + arg.cat_salt_len + arg.cat_seed_len;
Christian Brabandtaae58342023-04-23 17:50:22 +0100536
537 return crypt_create(method_nr, key, &arg);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200538}
539
540/*
541 * Read the crypt method specific header data from "fp".
542 * Return an allocated cryptstate_T or NULL on error.
543 */
544 cryptstate_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100545crypt_create_from_file(FILE *fp, char_u *key)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200546{
547 int method_nr;
548 int header_len;
549 char magic_buffer[CRYPT_MAGIC_LEN];
550 char_u *buffer;
551 cryptstate_T *state;
552
553 if (fread(magic_buffer, CRYPT_MAGIC_LEN, 1, fp) != 1)
554 return NULL;
555 method_nr = crypt_method_nr_from_magic(magic_buffer, CRYPT_MAGIC_LEN);
556 if (method_nr < 0)
557 return NULL;
558
559 header_len = crypt_get_header_len(method_nr);
560 if ((buffer = alloc(header_len)) == NULL)
561 return NULL;
562 mch_memmove(buffer, magic_buffer, CRYPT_MAGIC_LEN);
563 if (header_len > CRYPT_MAGIC_LEN
564 && fread(buffer + CRYPT_MAGIC_LEN,
565 header_len - CRYPT_MAGIC_LEN, 1, fp) != 1)
566 {
567 vim_free(buffer);
568 return NULL;
569 }
570
571 state = crypt_create_from_header(method_nr, key, buffer);
572 vim_free(buffer);
573 return state;
574}
575
576/*
577 * Allocate a cryptstate_T for writing and initialize it with "key".
578 * Allocates and fills in the header and stores it in "header", setting
579 * "header_len". The header may include salt and seed, depending on
580 * cryptmethod. Caller must free header.
581 * Returns the state or NULL on failure.
582 */
583 cryptstate_T *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100584crypt_create_for_writing(
585 int method_nr,
586 char_u *key,
587 char_u **header,
588 int *header_len)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200589{
590 int len = crypt_get_header_len(method_nr);
Christian Brabandtaae58342023-04-23 17:50:22 +0100591 crypt_arg_T arg;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200592 cryptstate_T *state;
593
Christian Brabandtaae58342023-04-23 17:50:22 +0100594 CLEAR_FIELD(arg);
595 arg.cat_salt_len = cryptmethods[method_nr].salt_len;
596 arg.cat_seed_len = cryptmethods[method_nr].seed_len;
597 arg.cat_add_len = cryptmethods[method_nr].add_len;
598 arg.cat_init_from_file = FALSE;
599
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200600 *header_len = len;
601 *header = alloc(len);
602 if (*header == NULL)
603 return NULL;
604
605 mch_memmove(*header, cryptmethods[method_nr].magic, CRYPT_MAGIC_LEN);
Christian Brabandtaae58342023-04-23 17:50:22 +0100606 if (arg.cat_salt_len > 0 || arg.cat_seed_len > 0 || arg.cat_add_len > 0)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200607 {
Christian Brabandtaae58342023-04-23 17:50:22 +0100608 if (arg.cat_salt_len > 0)
609 arg.cat_salt = *header + CRYPT_MAGIC_LEN;
610 if (arg.cat_seed_len > 0)
611 arg.cat_seed = *header + CRYPT_MAGIC_LEN + arg.cat_salt_len;
612 if (arg.cat_add_len > 0)
Bram Moolenaar3a2a60c2023-05-27 18:02:55 +0100613 arg.cat_add = *header + CRYPT_MAGIC_LEN
614 + arg.cat_salt_len + arg.cat_seed_len;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200615
Bram Moolenaarc667da52019-11-30 20:52:27 +0100616 // TODO: Should this be crypt method specific? (Probably not worth
617 // it). sha2_seed is pretty bad for large amounts of entropy, so make
618 // that into something which is suitable for anything.
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200619#ifdef FEAT_SODIUM
620 if (sodium_init() >= 0)
621 {
Christian Brabandtaae58342023-04-23 17:50:22 +0100622 if (arg.cat_salt_len > 0)
623 randombytes_buf(arg.cat_salt, arg.cat_salt_len);
624 if (arg.cat_seed_len > 0)
625 randombytes_buf(arg.cat_seed, arg.cat_seed_len);
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200626 }
627 else
628#endif
Christian Brabandtaae58342023-04-23 17:50:22 +0100629 sha2_seed(arg.cat_salt, arg.cat_salt_len, arg.cat_seed, arg.cat_seed_len);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200630 }
Christian Brabandtaae58342023-04-23 17:50:22 +0100631 state = crypt_create(method_nr, key, &arg);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200632 if (state == NULL)
Bram Moolenaard23a8232018-02-10 18:45:26 +0100633 VIM_CLEAR(*header);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200634 return state;
635}
636
637/*
638 * Free the crypt state.
639 */
640 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100641crypt_free_state(cryptstate_T *state)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200642{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200643#ifdef FEAT_SODIUM
Christian Brabandtaae58342023-04-23 17:50:22 +0100644 if (crypt_method_is_sodium(state->method_nr))
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200645 {
Bram Moolenaar131530a2021-07-29 20:37:49 +0200646 sodium_munlock(((sodium_state_T *)state->method_state)->key,
647 crypto_box_SEEDBYTES);
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200648 sodium_memzero(state->method_state, sizeof(sodium_state_T));
649 sodium_free(state->method_state);
650 }
651 else
652#endif
653 vim_free(state->method_state);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200654 vim_free(state);
655}
656
Bram Moolenaar987411d2019-01-18 22:48:34 +0100657#ifdef CRYPT_NOT_INPLACE
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200658/*
659 * Encode "from[len]" and store the result in a newly allocated buffer, which
660 * is stored in "newptr".
661 * Return number of bytes in "newptr", 0 for need more or -1 on error.
662 */
663 long
Bram Moolenaar7454a062016-01-30 15:14:10 +0100664crypt_encode_alloc(
665 cryptstate_T *state,
666 char_u *from,
667 size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200668 char_u **newptr,
669 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200670{
671 cryptmethod_T *method = &cryptmethods[state->method_nr];
672
673 if (method->encode_buffer_fn != NULL)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100674 // Has buffer function, pass through.
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200675 return method->encode_buffer_fn(state, from, len, newptr, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200676 if (len == 0)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100677 // Not buffering, just return EOF.
Bram Moolenaar9b8f0212014-08-13 22:05:53 +0200678 return (long)len;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200679
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200680 *newptr = alloc(len + 50);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200681 if (*newptr == NULL)
682 return -1;
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200683 method->encode_fn(state, from, len, *newptr, last);
Bram Moolenaar9b8f0212014-08-13 22:05:53 +0200684 return (long)len;
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200685}
686
687/*
688 * Decrypt "ptr[len]" and store the result in a newly allocated buffer, which
689 * is stored in "newptr".
690 * Return number of bytes in "newptr", 0 for need more or -1 on error.
691 */
692 long
Bram Moolenaar7454a062016-01-30 15:14:10 +0100693crypt_decode_alloc(
694 cryptstate_T *state,
695 char_u *ptr,
696 long len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200697 char_u **newptr,
698 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200699{
700 cryptmethod_T *method = &cryptmethods[state->method_nr];
701
702 if (method->decode_buffer_fn != NULL)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100703 // Has buffer function, pass through.
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200704 return method->decode_buffer_fn(state, ptr, len, newptr, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200705
706 if (len == 0)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100707 // Not buffering, just return EOF.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200708 return len;
709
710 *newptr = alloc(len);
711 if (*newptr == NULL)
712 return -1;
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200713 method->decode_fn(state, ptr, len, *newptr, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200714 return len;
715}
Bram Moolenaar987411d2019-01-18 22:48:34 +0100716#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200717
718/*
719 * Encrypting "from[len]" into "to[len]".
720 */
721 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100722crypt_encode(
723 cryptstate_T *state,
724 char_u *from,
725 size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200726 char_u *to,
727 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200728{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200729 cryptmethods[state->method_nr].encode_fn(state, from, len, to, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200730}
731
Bram Moolenaar987411d2019-01-18 22:48:34 +0100732#if 0 // unused
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200733/*
734 * decrypting "from[len]" into "to[len]".
735 */
736 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100737crypt_decode(
738 cryptstate_T *state,
739 char_u *from,
740 size_t len,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200741 char_u *to,
742 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200743{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200744 cryptmethods[state->method_nr].decode_fn(state, from, len, to, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200745}
Bram Moolenaar987411d2019-01-18 22:48:34 +0100746#endif
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200747
748/*
749 * Simple inplace encryption, modifies "buf[len]" in place.
750 */
751 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100752crypt_encode_inplace(
753 cryptstate_T *state,
754 char_u *buf,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200755 size_t len,
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100756 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200757{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200758 cryptmethods[state->method_nr].encode_inplace_fn(state, buf, len,
759 buf, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200760}
761
762/*
763 * Simple inplace decryption, modifies "buf[len]" in place.
764 */
765 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100766crypt_decode_inplace(
767 cryptstate_T *state,
768 char_u *buf,
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200769 size_t len,
770 int last)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200771{
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200772 cryptmethods[state->method_nr].decode_inplace_fn(state, buf, len,
773 buf, last);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200774}
775
776/*
777 * Free an allocated crypt key. Clear the text to make sure it doesn't stay
778 * in memory anywhere.
779 */
780 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100781crypt_free_key(char_u *key)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200782{
783 char_u *p;
784
785 if (key != NULL)
786 {
787 for (p = key; *p != NUL; ++p)
788 *p = 0;
789 vim_free(key);
790 }
791}
792
793/*
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100794 * Check the crypt method and give a warning if it's outdated.
795 */
796 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100797crypt_check_method(int method)
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100798{
Christian Brabandtaae58342023-04-23 17:50:22 +0100799 if (method < CRYPT_M_BF2 || method == CRYPT_M_SOD)
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100800 {
801 msg_scroll = TRUE;
Bram Moolenaar32526b32019-01-19 17:43:09 +0100802 msg(_("Warning: Using a weak encryption method; see :help 'cm'"));
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100803 }
Christian Brabandt226b28b2021-06-21 21:08:08 +0200804}
805
Bram Moolenaar3a2a60c2023-05-27 18:02:55 +0100806/*
807 * If the crypt method for "curbuf" does not support encrypting the swap file
808 * then disable the swap file.
809 */
810 void
Christian Brabandt226b28b2021-06-21 21:08:08 +0200811crypt_check_swapfile_curbuf(void)
812{
Bram Moolenaar3a2a60c2023-05-27 18:02:55 +0100813#ifdef FEAT_SODIUM
Christian Brabandt226b28b2021-06-21 21:08:08 +0200814 int method = crypt_get_method_nr(curbuf);
Christian Brabandtaae58342023-04-23 17:50:22 +0100815 if (crypt_method_is_sodium(method))
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200816 {
817 // encryption uses padding and MAC, that does not work very well with
818 // swap and undo files, so disable them
819 mf_close_file(curbuf, TRUE); // remove the swap file
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100820 set_option_value_give_err((char_u *)"swf", 0, NULL, OPT_LOCAL);
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200821 msg_scroll = TRUE;
Christian Brabandt8a4c8122021-07-25 14:36:05 +0200822 msg(_("Note: Encryption of swapfile not supported, disabling swap file"));
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200823 }
Christian Brabandt226b28b2021-06-21 21:08:08 +0200824#endif
Bram Moolenaar3a2a60c2023-05-27 18:02:55 +0100825}
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100826
827 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100828crypt_check_current_method(void)
Bram Moolenaar3a0c9082014-11-12 15:15:42 +0100829{
830 crypt_check_method(crypt_get_method_nr(curbuf));
831}
832
833/*
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200834 * Ask the user for a crypt key.
835 * When "store" is TRUE, the new key is stored in the 'key' option, and the
836 * 'key' option value is returned: Don't free it.
837 * When "store" is FALSE, the typed key is returned in allocated memory.
838 * Returns NULL on failure.
839 */
840 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100841crypt_get_key(
842 int store,
Bram Moolenaarc667da52019-11-30 20:52:27 +0100843 int twice) // Ask for the key twice.
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200844{
845 char_u *p1, *p2 = NULL;
846 int round;
847
848 for (round = 0; ; ++round)
849 {
850 cmdline_star = TRUE;
851 cmdline_row = msg_row;
852 p1 = getcmdline_prompt(NUL, round == 0
853 ? (char_u *)_("Enter encryption key: ")
854 : (char_u *)_("Enter same key again: "), 0, EXPAND_NOTHING,
855 NULL);
856 cmdline_star = FALSE;
857
858 if (p1 == NULL)
859 break;
860
861 if (round == twice)
862 {
863 if (p2 != NULL && STRCMP(p1, p2) != 0)
864 {
Bram Moolenaar32526b32019-01-19 17:43:09 +0100865 msg(_("Keys don't match!"));
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200866 crypt_free_key(p1);
867 crypt_free_key(p2);
868 p2 = NULL;
Bram Moolenaarc667da52019-11-30 20:52:27 +0100869 round = -1; // do it again
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200870 continue;
871 }
872
873 if (store)
874 {
Bram Moolenaar31e5c602022-04-15 13:53:33 +0100875 set_option_value_give_err((char_u *)"key", 0L, p1, OPT_LOCAL);
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200876 crypt_free_key(p1);
877 p1 = curbuf->b_p_key;
Christian Brabandt226b28b2021-06-21 21:08:08 +0200878 crypt_check_swapfile_curbuf();
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200879 }
880 break;
881 }
882 p2 = p1;
883 }
884
Bram Moolenaarc667da52019-11-30 20:52:27 +0100885 // since the user typed this, no need to wait for return
Christian Brabandtaae58342023-04-23 17:50:22 +0100886 if (!crypt_method_is_sodium(crypt_get_method_nr(curbuf)))
Christian Brabandt226b28b2021-06-21 21:08:08 +0200887 {
888 if (msg_didout)
889 msg_putchar('\n');
890 need_wait_return = FALSE;
891 msg_didout = FALSE;
892 }
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200893
894 crypt_free_key(p2);
895 return p1;
896}
897
898
899/*
900 * Append a message to IObuff for the encryption/decryption method being used.
901 */
902 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100903crypt_append_msg(
904 buf_T *buf)
Bram Moolenaar8f4ac012014-08-10 13:38:34 +0200905{
906 if (crypt_get_method_nr(buf) == 0)
907 STRCAT(IObuff, _("[crypted]"));
908 else
909 {
910 STRCAT(IObuff, "[");
911 STRCAT(IObuff, *buf->b_p_cm == NUL ? p_cm : buf->b_p_cm);
912 STRCAT(IObuff, "]");
913 }
914}
915
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +0100916 static int
K.Takataa8cdb4e2022-12-06 16:17:01 +0000917crypt_sodium_init_(
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200918 cryptstate_T *state UNUSED,
919 char_u *key UNUSED,
Christian Brabandtaae58342023-04-23 17:50:22 +0100920 crypt_arg_T *arg UNUSED)
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200921{
922# ifdef FEAT_SODIUM
923 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
924 unsigned char dkey[crypto_box_SEEDBYTES]; // 32
925 sodium_state_T *sd_state;
Bram Moolenaar131530a2021-07-29 20:37:49 +0200926 int retval = 0;
Christian Brabandtaae58342023-04-23 17:50:22 +0100927 unsigned long long opslimit;
ichizok35a2ec12023-04-25 15:27:27 +0100928 unsigned long long memlimit;
Christian Brabandtaae58342023-04-23 17:50:22 +0100929 int alg;
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200930
931 if (sodium_init() < 0)
932 return FAIL;
933
934 sd_state = (sodium_state_T *)sodium_malloc(sizeof(sodium_state_T));
935 sodium_memzero(sd_state, sizeof(sodium_state_T));
936
Christian Brabandtaae58342023-04-23 17:50:22 +0100937 if ((state->method_nr == CRYPT_M_SOD2 && !arg->cat_init_from_file)
938 || state->method_nr == CRYPT_M_SOD)
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200939 {
Christian Brabandtaae58342023-04-23 17:50:22 +0100940 opslimit = crypto_pwhash_OPSLIMIT_INTERACTIVE;
941 memlimit = crypto_pwhash_MEMLIMIT_INTERACTIVE;
942 alg = crypto_pwhash_ALG_DEFAULT;
943
944#if 0
945 // For testing
946 if (state->method_nr == CRYPT_M_SOD2)
947 {
948 opslimit = crypto_pwhash_OPSLIMIT_MODERATE;
949 memlimit = crypto_pwhash_MEMLIMIT_MODERATE;
950 }
951#endif
952
953 // derive a key from the password
954 if (crypto_pwhash(dkey, sizeof(dkey), (const char *)key, STRLEN(key),
ichizok35a2ec12023-04-25 15:27:27 +0100955 arg->cat_salt, opslimit, (size_t)memlimit, alg) != 0)
Christian Brabandtaae58342023-04-23 17:50:22 +0100956 {
957 // out of memory
958 sodium_free(sd_state);
959 return FAIL;
960 }
961 memcpy(sd_state->key, dkey, crypto_box_SEEDBYTES);
962
963 retval += sodium_mlock(sd_state->key, crypto_box_SEEDBYTES);
964 retval += sodium_mlock(key, STRLEN(key));
965
966 if (retval < 0)
967 {
968 emsg(_(e_encryption_sodium_mlock_failed));
969 sodium_free(sd_state);
970 return FAIL;
971 }
Bram Moolenaar3a2a60c2023-05-27 18:02:55 +0100972 // "cat_add" should not be NULL, check anyway for safety
973 if (state->method_nr == CRYPT_M_SOD2 && arg->cat_add != NULL)
Christian Brabandtaae58342023-04-23 17:50:22 +0100974 {
Christian Brabandt6019fed2023-07-11 22:38:29 +0200975 char_u buffer[20];
976 char_u *p = buffer;
977 vim_memset(buffer, 0, 20);
Christian Brabandtaae58342023-04-23 17:50:22 +0100978
Christian Brabandt6019fed2023-07-11 22:38:29 +0200979 crypt_long_long_to_char(opslimit, p);
980 p += sizeof(opslimit);
Christian Brabandtaae58342023-04-23 17:50:22 +0100981
Christian Brabandt6019fed2023-07-11 22:38:29 +0200982 crypt_long_long_to_char(memlimit, p);
983 p += sizeof(memlimit);
984
985 crypt_int_to_char(alg, p);
986 memcpy(arg->cat_add, buffer, sizeof(opslimit) + sizeof(memlimit) + sizeof(alg));
Christian Brabandtaae58342023-04-23 17:50:22 +0100987 }
Christian Brabandtf573c6e2021-06-20 14:02:16 +0200988 }
Christian Brabandtaae58342023-04-23 17:50:22 +0100989 else
Bram Moolenaar131530a2021-07-29 20:37:49 +0200990 {
Christian Brabandt6019fed2023-07-11 22:38:29 +0200991 char_u buffer[20];
992 char_u *p = buffer;
993 vim_memset(buffer, 0, 20);
994 int size = sizeof(opslimit) +
995 sizeof(memlimit) + sizeof(alg);
996
Christian Brabandtaae58342023-04-23 17:50:22 +0100997 // Reading parameters from file
Christian Brabandt6019fed2023-07-11 22:38:29 +0200998 if (arg->cat_add_len < size)
Christian Brabandtaae58342023-04-23 17:50:22 +0100999 {
1000 sodium_free(sd_state);
1001 return FAIL;
1002 }
1003
1004 // derive the key from the file header
Christian Brabandt6019fed2023-07-11 22:38:29 +02001005 memcpy(p, arg->cat_add, size);
1006 arg->cat_add += size;
Christian Brabandtaae58342023-04-23 17:50:22 +01001007
Christian Brabandt6019fed2023-07-11 22:38:29 +02001008 opslimit = crypt_char_to_long_long(p);
1009 p += sizeof(opslimit);
1010 memlimit = crypt_char_to_long_long(p);
1011 p += sizeof(memlimit);
1012 alg = crypt_char_to_int(p);
1013 p += sizeof(alg);
Christian Brabandtaae58342023-04-23 17:50:22 +01001014
1015#ifdef FEAT_EVAL
1016 crypt_sodium_report_hash_params(opslimit,
1017 crypto_pwhash_OPSLIMIT_INTERACTIVE,
ichizok35a2ec12023-04-25 15:27:27 +01001018 (size_t)memlimit, crypto_pwhash_MEMLIMIT_INTERACTIVE,
Christian Brabandtaae58342023-04-23 17:50:22 +01001019 alg, crypto_pwhash_ALG_DEFAULT);
1020#endif
1021
1022 if (crypto_pwhash(dkey, sizeof(dkey), (const char *)key, STRLEN(key),
ichizok35a2ec12023-04-25 15:27:27 +01001023 arg->cat_salt, opslimit, (size_t)memlimit, alg) != 0)
Christian Brabandtaae58342023-04-23 17:50:22 +01001024 {
1025 // out of memory
1026 sodium_free(sd_state);
1027 return FAIL;
1028 }
1029 memcpy(sd_state->key, dkey, crypto_box_SEEDBYTES);
1030
1031 retval += sodium_mlock(sd_state->key, crypto_box_SEEDBYTES);
1032 retval += sodium_mlock(key, STRLEN(key));
1033
1034 if (retval < 0)
1035 {
1036 emsg(_(e_encryption_sodium_mlock_failed));
1037 sodium_free(sd_state);
1038 return FAIL;
1039 }
Bram Moolenaar131530a2021-07-29 20:37:49 +02001040 }
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001041 sd_state->count = 0;
1042 state->method_state = sd_state;
1043
1044 return OK;
1045# else
Bram Moolenaar50809a42023-05-20 16:39:07 +01001046 emsg(_(e_libsodium_not_built_in));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001047 return FAIL;
1048# endif
1049}
1050
1051/*
1052 * Encrypt "from[len]" into "to[len]".
1053 * "from" and "to" can be equal to encrypt in place.
1054 * Call needs to ensure that there is enough space in to (for the header)
1055 */
Christian Brabandt226b28b2021-06-21 21:08:08 +02001056#if 0 // Currently unused
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001057 void
1058crypt_sodium_encode(
1059 cryptstate_T *state UNUSED,
1060 char_u *from UNUSED,
1061 size_t len UNUSED,
1062 char_u *to UNUSED,
1063 int last UNUSED)
1064{
1065# ifdef FEAT_SODIUM
1066 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
1067 sodium_state_T *sod_st = state->method_state;
1068 unsigned char tag = last
1069 ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0;
1070
1071 if (sod_st->count == 0)
1072 {
1073 if (len <= crypto_secretstream_xchacha20poly1305_HEADERBYTES)
1074 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001075 emsg(_(e_libsodium_cannot_encrypt_header));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001076 return;
1077 }
1078 crypto_secretstream_xchacha20poly1305_init_push(&sod_st->state,
1079 to, sod_st->key);
1080 to += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1081 }
1082
1083 if (sod_st->count && len <= crypto_secretstream_xchacha20poly1305_ABYTES)
1084 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001085 emsg(_(e_libsodium_cannot_encrypt_buffer));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001086 return;
1087 }
1088
1089 crypto_secretstream_xchacha20poly1305_push(&sod_st->state, to, NULL,
1090 from, len, NULL, 0, tag);
1091
1092 sod_st->count++;
1093# endif
1094}
Christian Brabandt226b28b2021-06-21 21:08:08 +02001095#endif
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001096
Christian Brabandt226b28b2021-06-21 21:08:08 +02001097/*
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001098 * Decrypt "from[len]" into "to[len]".
1099 * "from" and "to" can be equal to encrypt in place.
1100 */
Christian Brabandt226b28b2021-06-21 21:08:08 +02001101#if 0 // Currently unused
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001102 void
1103crypt_sodium_decode(
1104 cryptstate_T *state UNUSED,
1105 char_u *from UNUSED,
1106 size_t len UNUSED,
1107 char_u *to UNUSED,
1108 int last UNUSED)
1109{
1110# ifdef FEAT_SODIUM
1111 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
1112 sodium_state_T *sod_st = state->method_state;
1113 unsigned char tag;
1114 unsigned long long buf_len;
1115 char_u *p1 = from;
1116 char_u *p2 = to;
1117 char_u *buf_out;
1118
1119 if (sod_st->count == 0
1120 && len <= crypto_secretstream_xchacha20poly1305_HEADERBYTES)
1121 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001122 emsg(_(e_libsodium_cannot_decrypt_header));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001123 return;
1124 }
1125
1126 buf_out = (char_u *)alloc(len);
1127
1128 if (buf_out == NULL)
1129 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001130 emsg(_(e_libsodium_cannot_allocate_buffer));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001131 return;
1132 }
1133 if (sod_st->count == 0)
1134 {
1135 if (crypto_secretstream_xchacha20poly1305_init_pull(
1136 &sod_st->state, from, sod_st->key) != 0)
1137 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001138 emsg(_(e_libsodium_decryption_failed_header_incomplete));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001139 goto fail;
1140 }
1141
1142 from += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1143 len -= crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1144
1145 if (p1 == p2)
1146 to += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1147 }
1148
1149 if (sod_st->count && len <= crypto_secretstream_xchacha20poly1305_ABYTES)
1150 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001151 emsg(_(e_libsodium_cannot_decrypt_buffer));
Dominique Pellecb54bc62021-06-21 20:15:37 +02001152 goto fail;
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001153 }
1154 if (crypto_secretstream_xchacha20poly1305_pull(&sod_st->state,
1155 buf_out, &buf_len, &tag, from, len, NULL, 0) != 0)
1156 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001157 emsg(_(e_libsodium_decryption_failed));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001158 goto fail;
1159 }
1160 sod_st->count++;
1161
1162 if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !last)
1163 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001164 emsg(_(e_libsodium_decryption_failed_premature));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001165 goto fail;
1166 }
1167 if (p1 == p2)
1168 mch_memmove(p2, buf_out, buf_len);
1169
1170fail:
1171 vim_free(buf_out);
1172# endif
1173}
Christian Brabandt226b28b2021-06-21 21:08:08 +02001174#endif
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001175
1176/*
1177 * Encrypt "from[len]" into "to[len]".
1178 * "from" and "to" can be equal to encrypt in place.
1179 */
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +01001180 static long
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001181crypt_sodium_buffer_encode(
1182 cryptstate_T *state UNUSED,
1183 char_u *from UNUSED,
1184 size_t len UNUSED,
1185 char_u **buf_out UNUSED,
1186 int last UNUSED)
1187{
1188# ifdef FEAT_SODIUM
1189 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
1190 unsigned long long out_len;
1191 char_u *ptr;
1192 unsigned char tag = last
1193 ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0;
1194 int length;
1195 sodium_state_T *sod_st = state->method_state;
1196 int first = (sod_st->count == 0);
1197
Christian Brabandt226b28b2021-06-21 21:08:08 +02001198 length = (int)len + crypto_secretstream_xchacha20poly1305_ABYTES
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001199 + (first ? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0);
1200 *buf_out = alloc_clear(length);
1201 if (*buf_out == NULL)
1202 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001203 emsg(_(e_libsodium_cannot_allocate_buffer));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001204 return -1;
1205 }
1206 ptr = *buf_out;
1207
1208 if (first)
1209 {
1210 crypto_secretstream_xchacha20poly1305_init_push(&sod_st->state,
1211 ptr, sod_st->key);
1212 ptr += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1213 }
1214
1215 crypto_secretstream_xchacha20poly1305_push(&sod_st->state, ptr,
1216 &out_len, from, len, NULL, 0, tag);
1217
1218 sod_st->count++;
1219 return out_len + (first
1220 ? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0);
1221# else
1222 return -1;
1223# endif
1224}
1225
1226/*
1227 * Decrypt "from[len]" into "to[len]".
1228 * "from" and "to" can be equal to encrypt in place.
1229 */
Yegappan Lakshmananee47eac2022-06-29 12:55:36 +01001230 static long
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001231crypt_sodium_buffer_decode(
1232 cryptstate_T *state UNUSED,
1233 char_u *from UNUSED,
1234 size_t len UNUSED,
1235 char_u **buf_out UNUSED,
1236 int last UNUSED)
1237{
1238# ifdef FEAT_SODIUM
1239 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES
1240 sodium_state_T *sod_st = state->method_state;
1241 unsigned char tag;
1242 unsigned long long out_len;
Christian Brabandtaae58342023-04-23 17:50:22 +01001243
1244 if (sod_st->count == 0
1245 && state->method_nr == CRYPT_M_SOD
1246 && len > WRITEBUFSIZE
1247 + crypto_secretstream_xchacha20poly1305_HEADERBYTES
1248 + crypto_secretstream_xchacha20poly1305_ABYTES)
1249 len -= cryptmethods[CRYPT_M_SOD2].add_len;
1250
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001251 *buf_out = alloc_clear(len);
1252 if (*buf_out == NULL)
1253 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001254 emsg(_(e_libsodium_cannot_allocate_buffer));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001255 return -1;
1256 }
1257
1258 if (sod_st->count == 0)
1259 {
1260 if (crypto_secretstream_xchacha20poly1305_init_pull(&sod_st->state,
1261 from, sod_st->key) != 0)
1262 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001263 emsg(_(e_libsodium_decryption_failed_header_incomplete));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001264 return -1;
1265 }
1266 from += crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1267 len -= crypto_secretstream_xchacha20poly1305_HEADERBYTES;
1268 sod_st->count++;
1269 }
1270 if (crypto_secretstream_xchacha20poly1305_pull(&sod_st->state,
1271 *buf_out, &out_len, &tag, from, len, NULL, 0) != 0)
1272 {
Bram Moolenaar50809a42023-05-20 16:39:07 +01001273 emsg(_(e_libsodium_decryption_failed));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001274 return -1;
1275 }
1276
1277 if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !last)
Bram Moolenaar50809a42023-05-20 16:39:07 +01001278 emsg(_(e_libsodium_decryption_failed_premature));
Christian Brabandtf573c6e2021-06-20 14:02:16 +02001279 return (long) out_len;
1280# else
1281 return -1;
1282# endif
1283}
1284
K.Takata1a8825d2022-01-19 13:32:57 +00001285# if defined(FEAT_SODIUM) || defined(PROTO)
Christian Brabandt19e6c4f2023-06-27 18:57:10 +01001286 void
1287crypt_sodium_lock_key(char_u *key)
1288{
1289 if (sodium_init() >= 0)
1290 sodium_mlock(key, STRLEN(key));
1291}
1292
K.Takata1a8825d2022-01-19 13:32:57 +00001293 int
1294crypt_sodium_munlock(void *const addr, const size_t len)
1295{
1296 return sodium_munlock(addr, len);
1297}
1298
1299 void
1300crypt_sodium_randombytes_buf(void *const buf, const size_t size)
1301{
1302 randombytes_buf(buf, size);
1303}
K.Takataa8cdb4e2022-12-06 16:17:01 +00001304
1305 int
1306crypt_sodium_init(void)
1307{
1308 return sodium_init();
1309}
1310
Zoltan Arpadffy1c8e2332023-12-05 16:04:23 +01001311 UINT32_T
K.Takataa8cdb4e2022-12-06 16:17:01 +00001312crypt_sodium_randombytes_random(void)
1313{
1314 return randombytes_random();
1315}
Christian Brabandtaae58342023-04-23 17:50:22 +01001316
1317#if defined(FEAT_EVAL) || defined(PROTO)
1318 static void
1319crypt_sodium_report_hash_params(
1320 unsigned long long opslimit,
1321 unsigned long long ops_def,
1322 size_t memlimit,
1323 size_t mem_def,
1324 int alg,
1325 int alg_def)
1326{
1327 if (p_verbose > 0)
1328 {
1329 verbose_enter();
1330 if (opslimit != ops_def)
1331 smsg(_("xchacha20v2: using custom opslimit \"%llu\" for Key derivation."), opslimit);
1332 else
1333 smsg(_("xchacha20v2: using default opslimit \"%llu\" for Key derivation."), opslimit);
1334 if (memlimit != mem_def)
1335 smsg(_("xchacha20v2: using custom memlimit \"%lu\" for Key derivation."), (unsigned long)memlimit);
1336 else
1337 smsg(_("xchacha20v2: using default memlimit \"%lu\" for Key derivation."), (unsigned long)memlimit);
1338 if (alg != alg_def)
1339 smsg(_("xchacha20v2: using custom algorithm \"%d\" for Key derivation."), alg);
1340 else
1341 smsg(_("xchacha20v2: using default algorithm \"%d\" for Key derivation."), alg);
1342 verbose_leave();
1343 }
1344}
1345#endif
Christian Brabandt6019fed2023-07-11 22:38:29 +02001346
1347 static void
1348crypt_long_long_to_char(long long n, char_u *s)
1349{
1350 int i;
1351 for (i = 0; i < 8; i++)
1352 {
1353 s[i] = (char_u)(n & 0xff);
1354 n = (unsigned)n >> 8;
1355 }
1356}
1357
1358 static void
1359crypt_int_to_char(int n, char_u *s)
1360{
1361 int i;
1362 for (i = 0; i < 4; i++)
1363 {
1364 s[i] = (char_u)(n & 0xff);
1365 n = (unsigned)n >> 8;
1366 }
1367}
1368
1369 static long long
1370crypt_char_to_long_long(char_u *s)
1371{
1372 unsigned long long retval = 0;
1373 int i;
1374 for (i = 7; i >= 0; i--)
1375 {
1376 if (i == 7)
1377 retval = s[i];
1378 else
1379 retval |= s[i];
1380 if (i > 0)
1381 retval <<= 8;
1382 }
1383 return retval;
1384}
1385
1386 static int
1387crypt_char_to_int(char_u *s)
1388{
1389 int retval = 0;
1390 int i;
1391
1392 for (i = 3; i >= 0; i--)
1393 {
1394 if (i == 3)
1395 retval = s[i];
1396 else
1397 retval |= s[i];
1398 if (i > 0)
1399 retval <<= 8;
1400 }
1401 return retval;
1402}
K.Takata1a8825d2022-01-19 13:32:57 +00001403# endif
1404
Bram Moolenaarc667da52019-11-30 20:52:27 +01001405#endif // FEAT_CRYPT