Mercurial > vim
annotate src/crypt.c @ 20666:e66b9b38cfab
Added tag v8.2.0886 for changeset 6ff992bf4c829024db2f16b442346e9723925f51
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 02 Jun 2020 21:45:04 +0200 |
parents | c469e1930456 |
children | 7e9e53a0368f |
rev | line source |
---|---|
10042
4aead6a9b7a9
commit https://github.com/vim/vim/commit/edf3f97ae2af024708ebb4ac614227327033ca47
Christian Brabandt <cb@256bit.org>
parents:
7817
diff
changeset
|
1 /* vi:set ts=8 sts=4 sw=4 noet: |
6122 | 2 * |
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 | |
32 typedef struct { | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
33 char *name; // encryption name as used in 'cryptmethod' |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
34 char *magic; // magic bytes stored in file header |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
35 int salt_len; // length of salt, or 0 when not using salt |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
36 int seed_len; // length of seed, or 0 when not using salt |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
37 #ifdef CRYPT_NOT_INPLACE |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
38 int works_inplace; // encryption/decryption can be done in-place |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
39 #endif |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
40 int whole_undofile; // whole undo file is encrypted |
6122 | 41 |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
42 // Optional function pointer for a self-test. |
6122 | 43 int (* self_test_fn)(); |
44 | |
16378
3d6b282e2d6e
patch 8.1.1194: typos and small problems in source files
Bram Moolenaar <Bram@vim.org>
parents:
15967
diff
changeset
|
45 // Function pointer for initializing encryption/decryption. |
16429
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
46 int (* init_fn)(cryptstate_T *state, char_u *key, |
6122 | 47 char_u *salt, int salt_len, char_u *seed, int seed_len); |
48 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
49 // Function pointers for encoding/decoding from one buffer into another. |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
50 // Optional, however, these or the _buffer ones should be configured. |
6122 | 51 void (*encode_fn)(cryptstate_T *state, char_u *from, size_t len, |
52 char_u *to); | |
53 void (*decode_fn)(cryptstate_T *state, char_u *from, size_t len, | |
54 char_u *to); | |
55 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
56 // Function pointers for encoding and decoding, can buffer data if needed. |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
57 // Optional (however, these or the above should be configured). |
6122 | 58 long (*encode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len, |
59 char_u **newptr); | |
60 long (*decode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len, | |
61 char_u **newptr); | |
62 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
63 // Function pointers for in-place encoding and decoding, used for |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
64 // crypt_*_inplace(). "from" and "to" arguments will be equal. |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
65 // These may be the same as decode_fn and encode_fn above, however an |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
66 // algorithm may implement them in a way that is not interchangeable with |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
67 // the crypt_(en|de)code() interface (for example because it wishes to add |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
68 // padding to files). |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
69 // This method is used for swap and undo files which have a rigid format. |
6122 | 70 void (*encode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len, |
71 char_u *p2); | |
72 void (*decode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len, | |
73 char_u *p2); | |
74 } cryptmethod_T; | |
75 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
76 // index is method_nr of cryptstate_T, CRYPT_M_* |
6122 | 77 static cryptmethod_T cryptmethods[CRYPT_M_COUNT] = { |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
78 // PK_Zip; very weak |
6122 | 79 { |
80 "zip", | |
81 "VimCrypt~01!", | |
82 0, | |
83 0, | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
84 #ifdef CRYPT_NOT_INPLACE |
6122 | 85 TRUE, |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
86 #endif |
6122 | 87 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 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
95 // Blowfish/CFB + SHA-256 custom key derivation; implementation issues. |
6122 | 96 { |
97 "blowfish", | |
98 "VimCrypt~02!", | |
99 8, | |
100 8, | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
101 #ifdef CRYPT_NOT_INPLACE |
6122 | 102 TRUE, |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
103 #endif |
6122 | 104 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 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
112 // Blowfish/CFB + SHA-256 custom key derivation; fixed. |
6122 | 113 { |
114 "blowfish2", | |
115 "VimCrypt~03!", | |
116 8, | |
117 8, | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
118 #ifdef CRYPT_NOT_INPLACE |
6122 | 119 TRUE, |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
120 #endif |
6122 | 121 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 }, | |
13244
ac42c4b11dbc
patch 8.0.1496: clearing a pointer takes two lines
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
128 |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
129 // NOTE: when adding a new method, use some random bytes for the magic key, |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
130 // to avoid that a text file is recognized as encrypted. |
6122 | 131 }; |
132 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
133 #define CRYPT_MAGIC_LEN 12 // cannot change |
6122 | 134 static char crypt_magic_head[] = "VimCrypt~"; |
135 | |
136 /* | |
137 * Return int value for crypt method name. | |
138 * 0 for "zip", the old method. Also for any non-valid value. | |
139 * 1 for "blowfish". | |
140 * 2 for "blowfish2". | |
141 */ | |
142 int | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
143 crypt_method_nr_from_name(char_u *name) |
6122 | 144 { |
145 int i; | |
146 | |
147 for (i = 0; i < CRYPT_M_COUNT; ++i) | |
148 if (STRCMP(name, cryptmethods[i].name) == 0) | |
149 return i; | |
150 return 0; | |
151 } | |
152 | |
153 /* | |
154 * Get the crypt method used for a file from "ptr[len]", the magic text at the | |
155 * start of the file. | |
156 * Returns -1 when no encryption used. | |
157 */ | |
158 int | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
159 crypt_method_nr_from_magic(char *ptr, int len) |
6122 | 160 { |
161 int i; | |
162 | |
163 if (len < CRYPT_MAGIC_LEN) | |
164 return -1; | |
165 | |
166 for (i = 0; i < CRYPT_M_COUNT; i++) | |
167 if (memcmp(ptr, cryptmethods[i].magic, CRYPT_MAGIC_LEN) == 0) | |
168 return i; | |
169 | |
170 i = (int)STRLEN(crypt_magic_head); | |
171 if (len >= i && memcmp(ptr, crypt_magic_head, i) == 0) | |
15470
55ccc2d353bd
patch 8.1.0743: giving error messages is not flexible
Bram Moolenaar <Bram@vim.org>
parents:
13244
diff
changeset
|
172 emsg(_("E821: File is encrypted with unknown method")); |
6122 | 173 |
174 return -1; | |
175 } | |
176 | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
177 #ifdef CRYPT_NOT_INPLACE |
6122 | 178 /* |
179 * Return TRUE if the crypt method for "method_nr" can be done in-place. | |
180 */ | |
181 int | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
182 crypt_works_inplace(cryptstate_T *state) |
6122 | 183 { |
184 return cryptmethods[state->method_nr].works_inplace; | |
185 } | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
186 #endif |
6122 | 187 |
188 /* | |
189 * Get the crypt method for buffer "buf" as a number. | |
190 */ | |
191 int | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
192 crypt_get_method_nr(buf_T *buf) |
6122 | 193 { |
194 return crypt_method_nr_from_name(*buf->b_p_cm == NUL ? p_cm : buf->b_p_cm); | |
195 } | |
196 | |
197 /* | |
198 * Return TRUE when the buffer uses an encryption method that encrypts the | |
199 * whole undo file, not only the text. | |
200 */ | |
201 int | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
202 crypt_whole_undofile(int method_nr) |
6122 | 203 { |
204 return cryptmethods[method_nr].whole_undofile; | |
205 } | |
206 | |
207 /* | |
18498
9e6d5a4abb1c
patch 8.1.2243: typos in comments
Bram Moolenaar <Bram@vim.org>
parents:
16825
diff
changeset
|
208 * Get crypt method specific length of the file header in bytes. |
6122 | 209 */ |
210 int | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
211 crypt_get_header_len(int method_nr) |
6122 | 212 { |
213 return CRYPT_MAGIC_LEN | |
214 + cryptmethods[method_nr].salt_len | |
215 + cryptmethods[method_nr].seed_len; | |
216 } | |
217 | |
218 /* | |
219 * Set the crypt method for buffer "buf" to "method_nr" using the int value as | |
220 * returned by crypt_method_nr_from_name(). | |
221 */ | |
222 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
223 crypt_set_cm_option(buf_T *buf, int method_nr) |
6122 | 224 { |
225 free_string_option(buf->b_p_cm); | |
226 buf->b_p_cm = vim_strsave((char_u *)cryptmethods[method_nr].name); | |
227 } | |
228 | |
229 /* | |
230 * If the crypt method for the current buffer has a self-test, run it and | |
231 * return OK/FAIL. | |
232 */ | |
233 int | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
234 crypt_self_test(void) |
6122 | 235 { |
236 int method_nr = crypt_get_method_nr(curbuf); | |
237 | |
238 if (cryptmethods[method_nr].self_test_fn == NULL) | |
239 return OK; | |
240 return cryptmethods[method_nr].self_test_fn(); | |
241 } | |
242 | |
243 /* | |
244 * Allocate a crypt state and initialize it. | |
16429
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
245 * Return NULL for failure. |
6122 | 246 */ |
247 cryptstate_T * | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
248 crypt_create( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
249 int method_nr, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
250 char_u *key, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
251 char_u *salt, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
252 int salt_len, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
253 char_u *seed, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
254 int seed_len) |
6122 | 255 { |
16825
ce04ebdf26b8
patch 8.1.1414: alloc() returning "char_u *" causes a lot of type casts
Bram Moolenaar <Bram@vim.org>
parents:
16782
diff
changeset
|
256 cryptstate_T *state = ALLOC_ONE(cryptstate_T); |
6122 | 257 |
16429
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
258 if (state == NULL) |
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
259 return state; |
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
260 |
6122 | 261 state->method_nr = method_nr; |
16429
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
262 if (cryptmethods[method_nr].init_fn( |
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
263 state, key, salt, salt_len, seed, seed_len) == FAIL) |
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
264 { |
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
265 vim_free(state); |
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
266 return NULL; |
a1229400434a
patch 8.1.1219: not checking for NULL return from alloc()
Bram Moolenaar <Bram@vim.org>
parents:
16378
diff
changeset
|
267 } |
6122 | 268 return state; |
269 } | |
270 | |
271 /* | |
272 * Allocate a crypt state from a file header and initialize it. | |
273 * Assumes that header contains at least the number of bytes that | |
274 * crypt_get_header_len() returns for "method_nr". | |
275 */ | |
276 cryptstate_T * | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
277 crypt_create_from_header( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
278 int method_nr, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
279 char_u *key, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
280 char_u *header) |
6122 | 281 { |
282 char_u *salt = NULL; | |
283 char_u *seed = NULL; | |
284 int salt_len = cryptmethods[method_nr].salt_len; | |
285 int seed_len = cryptmethods[method_nr].seed_len; | |
286 | |
287 if (salt_len > 0) | |
288 salt = header + CRYPT_MAGIC_LEN; | |
289 if (seed_len > 0) | |
290 seed = header + CRYPT_MAGIC_LEN + salt_len; | |
291 | |
292 return crypt_create(method_nr, key, salt, salt_len, seed, seed_len); | |
293 } | |
294 | |
295 /* | |
296 * Read the crypt method specific header data from "fp". | |
297 * Return an allocated cryptstate_T or NULL on error. | |
298 */ | |
299 cryptstate_T * | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
300 crypt_create_from_file(FILE *fp, char_u *key) |
6122 | 301 { |
302 int method_nr; | |
303 int header_len; | |
304 char magic_buffer[CRYPT_MAGIC_LEN]; | |
305 char_u *buffer; | |
306 cryptstate_T *state; | |
307 | |
308 if (fread(magic_buffer, CRYPT_MAGIC_LEN, 1, fp) != 1) | |
309 return NULL; | |
310 method_nr = crypt_method_nr_from_magic(magic_buffer, CRYPT_MAGIC_LEN); | |
311 if (method_nr < 0) | |
312 return NULL; | |
313 | |
314 header_len = crypt_get_header_len(method_nr); | |
315 if ((buffer = alloc(header_len)) == NULL) | |
316 return NULL; | |
317 mch_memmove(buffer, magic_buffer, CRYPT_MAGIC_LEN); | |
318 if (header_len > CRYPT_MAGIC_LEN | |
319 && fread(buffer + CRYPT_MAGIC_LEN, | |
320 header_len - CRYPT_MAGIC_LEN, 1, fp) != 1) | |
321 { | |
322 vim_free(buffer); | |
323 return NULL; | |
324 } | |
325 | |
326 state = crypt_create_from_header(method_nr, key, buffer); | |
327 vim_free(buffer); | |
328 return state; | |
329 } | |
330 | |
331 /* | |
332 * Allocate a cryptstate_T for writing and initialize it with "key". | |
333 * Allocates and fills in the header and stores it in "header", setting | |
334 * "header_len". The header may include salt and seed, depending on | |
335 * cryptmethod. Caller must free header. | |
336 * Returns the state or NULL on failure. | |
337 */ | |
338 cryptstate_T * | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
339 crypt_create_for_writing( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
340 int method_nr, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
341 char_u *key, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
342 char_u **header, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
343 int *header_len) |
6122 | 344 { |
345 int len = crypt_get_header_len(method_nr); | |
346 char_u *salt = NULL; | |
347 char_u *seed = NULL; | |
348 int salt_len = cryptmethods[method_nr].salt_len; | |
349 int seed_len = cryptmethods[method_nr].seed_len; | |
350 cryptstate_T *state; | |
351 | |
352 *header_len = len; | |
353 *header = alloc(len); | |
354 if (*header == NULL) | |
355 return NULL; | |
356 | |
357 mch_memmove(*header, cryptmethods[method_nr].magic, CRYPT_MAGIC_LEN); | |
358 if (salt_len > 0 || seed_len > 0) | |
359 { | |
360 if (salt_len > 0) | |
361 salt = *header + CRYPT_MAGIC_LEN; | |
362 if (seed_len > 0) | |
363 seed = *header + CRYPT_MAGIC_LEN + salt_len; | |
364 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
365 // TODO: Should this be crypt method specific? (Probably not worth |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
366 // it). sha2_seed is pretty bad for large amounts of entropy, so make |
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
367 // that into something which is suitable for anything. |
6122 | 368 sha2_seed(salt, salt_len, seed, seed_len); |
369 } | |
370 | |
371 state = crypt_create(method_nr, key, salt, salt_len, seed, seed_len); | |
372 if (state == NULL) | |
13244
ac42c4b11dbc
patch 8.0.1496: clearing a pointer takes two lines
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
373 VIM_CLEAR(*header); |
6122 | 374 return state; |
375 } | |
376 | |
377 /* | |
378 * Free the crypt state. | |
379 */ | |
380 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
381 crypt_free_state(cryptstate_T *state) |
6122 | 382 { |
383 vim_free(state->method_state); | |
384 vim_free(state); | |
385 } | |
386 | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
387 #ifdef CRYPT_NOT_INPLACE |
6122 | 388 /* |
389 * Encode "from[len]" and store the result in a newly allocated buffer, which | |
390 * is stored in "newptr". | |
391 * Return number of bytes in "newptr", 0 for need more or -1 on error. | |
392 */ | |
393 long | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
394 crypt_encode_alloc( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
395 cryptstate_T *state, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
396 char_u *from, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
397 size_t len, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
398 char_u **newptr) |
6122 | 399 { |
400 cryptmethod_T *method = &cryptmethods[state->method_nr]; | |
401 | |
402 if (method->encode_buffer_fn != NULL) | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
403 // Has buffer function, pass through. |
6122 | 404 return method->encode_buffer_fn(state, from, len, newptr); |
405 if (len == 0) | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
406 // Not buffering, just return EOF. |
6132 | 407 return (long)len; |
6122 | 408 |
16782
fc58fee685e2
patch 8.1.1393: unnecessary type casts
Bram Moolenaar <Bram@vim.org>
parents:
16429
diff
changeset
|
409 *newptr = alloc(len); |
6122 | 410 if (*newptr == NULL) |
411 return -1; | |
412 method->encode_fn(state, from, len, *newptr); | |
6132 | 413 return (long)len; |
6122 | 414 } |
415 | |
416 /* | |
417 * Decrypt "ptr[len]" and store the result in a newly allocated buffer, which | |
418 * is stored in "newptr". | |
419 * Return number of bytes in "newptr", 0 for need more or -1 on error. | |
420 */ | |
421 long | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
422 crypt_decode_alloc( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
423 cryptstate_T *state, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
424 char_u *ptr, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
425 long len, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
426 char_u **newptr) |
6122 | 427 { |
428 cryptmethod_T *method = &cryptmethods[state->method_nr]; | |
429 | |
430 if (method->decode_buffer_fn != NULL) | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
431 // Has buffer function, pass through. |
6122 | 432 return method->decode_buffer_fn(state, ptr, len, newptr); |
433 | |
434 if (len == 0) | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
435 // Not buffering, just return EOF. |
6122 | 436 return len; |
437 | |
438 *newptr = alloc(len); | |
439 if (*newptr == NULL) | |
440 return -1; | |
441 method->decode_fn(state, ptr, len, *newptr); | |
442 return len; | |
443 } | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
444 #endif |
6122 | 445 |
446 /* | |
447 * Encrypting "from[len]" into "to[len]". | |
448 */ | |
449 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
450 crypt_encode( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
451 cryptstate_T *state, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
452 char_u *from, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
453 size_t len, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
454 char_u *to) |
6122 | 455 { |
456 cryptmethods[state->method_nr].encode_fn(state, from, len, to); | |
457 } | |
458 | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
459 #if 0 // unused |
6122 | 460 /* |
461 * decrypting "from[len]" into "to[len]". | |
462 */ | |
463 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
464 crypt_decode( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
465 cryptstate_T *state, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
466 char_u *from, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
467 size_t len, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
468 char_u *to) |
6122 | 469 { |
470 cryptmethods[state->method_nr].decode_fn(state, from, len, to); | |
471 } | |
15531
959cf4c63b18
patch 8.1.0773: not all crypt code is tested
Bram Moolenaar <Bram@vim.org>
parents:
15470
diff
changeset
|
472 #endif |
6122 | 473 |
474 /* | |
475 * Simple inplace encryption, modifies "buf[len]" in place. | |
476 */ | |
477 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
478 crypt_encode_inplace( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
479 cryptstate_T *state, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
480 char_u *buf, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
481 size_t len) |
6122 | 482 { |
483 cryptmethods[state->method_nr].encode_inplace_fn(state, buf, len, buf); | |
484 } | |
485 | |
486 /* | |
487 * Simple inplace decryption, modifies "buf[len]" in place. | |
488 */ | |
489 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
490 crypt_decode_inplace( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
491 cryptstate_T *state, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
492 char_u *buf, |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
493 size_t len) |
6122 | 494 { |
495 cryptmethods[state->method_nr].decode_inplace_fn(state, buf, len, buf); | |
496 } | |
497 | |
498 /* | |
499 * Free an allocated crypt key. Clear the text to make sure it doesn't stay | |
500 * in memory anywhere. | |
501 */ | |
502 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
503 crypt_free_key(char_u *key) |
6122 | 504 { |
505 char_u *p; | |
506 | |
507 if (key != NULL) | |
508 { | |
509 for (p = key; *p != NUL; ++p) | |
510 *p = 0; | |
511 vim_free(key); | |
512 } | |
513 } | |
514 | |
515 /* | |
6353 | 516 * Check the crypt method and give a warning if it's outdated. |
517 */ | |
518 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
519 crypt_check_method(int method) |
6353 | 520 { |
521 if (method < CRYPT_M_BF2) | |
522 { | |
523 msg_scroll = TRUE; | |
15543
dd725a8ab112
patch 8.1.0779: argument for message functions is inconsistent
Bram Moolenaar <Bram@vim.org>
parents:
15531
diff
changeset
|
524 msg(_("Warning: Using a weak encryption method; see :help 'cm'")); |
6353 | 525 } |
526 } | |
527 | |
528 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
529 crypt_check_current_method(void) |
6353 | 530 { |
531 crypt_check_method(crypt_get_method_nr(curbuf)); | |
532 } | |
533 | |
534 /* | |
6122 | 535 * Ask the user for a crypt key. |
536 * When "store" is TRUE, the new key is stored in the 'key' option, and the | |
537 * 'key' option value is returned: Don't free it. | |
538 * When "store" is FALSE, the typed key is returned in allocated memory. | |
539 * Returns NULL on failure. | |
540 */ | |
541 char_u * | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
542 crypt_get_key( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
543 int store, |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
544 int twice) // Ask for the key twice. |
6122 | 545 { |
546 char_u *p1, *p2 = NULL; | |
547 int round; | |
548 | |
549 for (round = 0; ; ++round) | |
550 { | |
551 cmdline_star = TRUE; | |
552 cmdline_row = msg_row; | |
553 p1 = getcmdline_prompt(NUL, round == 0 | |
554 ? (char_u *)_("Enter encryption key: ") | |
555 : (char_u *)_("Enter same key again: "), 0, EXPAND_NOTHING, | |
556 NULL); | |
557 cmdline_star = FALSE; | |
558 | |
559 if (p1 == NULL) | |
560 break; | |
561 | |
562 if (round == twice) | |
563 { | |
564 if (p2 != NULL && STRCMP(p1, p2) != 0) | |
565 { | |
15543
dd725a8ab112
patch 8.1.0779: argument for message functions is inconsistent
Bram Moolenaar <Bram@vim.org>
parents:
15531
diff
changeset
|
566 msg(_("Keys don't match!")); |
6122 | 567 crypt_free_key(p1); |
568 crypt_free_key(p2); | |
569 p2 = NULL; | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
570 round = -1; // do it again |
6122 | 571 continue; |
572 } | |
573 | |
574 if (store) | |
575 { | |
576 set_option_value((char_u *)"key", 0L, p1, OPT_LOCAL); | |
577 crypt_free_key(p1); | |
578 p1 = curbuf->b_p_key; | |
579 } | |
580 break; | |
581 } | |
582 p2 = p1; | |
583 } | |
584 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
585 // since the user typed this, no need to wait for return |
6122 | 586 if (msg_didout) |
587 msg_putchar('\n'); | |
588 need_wait_return = FALSE; | |
589 msg_didout = FALSE; | |
590 | |
591 crypt_free_key(p2); | |
592 return p1; | |
593 } | |
594 | |
595 | |
596 /* | |
597 * Append a message to IObuff for the encryption/decryption method being used. | |
598 */ | |
599 void | |
7817
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
600 crypt_append_msg( |
83861277e6a3
commit https://github.com/vim/vim/commit/7454a06e2642d2b37afad1c5e71cec68081ca4ff
Christian Brabandt <cb@256bit.org>
parents:
6353
diff
changeset
|
601 buf_T *buf) |
6122 | 602 { |
603 if (crypt_get_method_nr(buf) == 0) | |
604 STRCAT(IObuff, _("[crypted]")); | |
605 else | |
606 { | |
607 STRCAT(IObuff, "["); | |
608 STRCAT(IObuff, *buf->b_p_cm == NUL ? p_cm : buf->b_p_cm); | |
609 STRCAT(IObuff, "]"); | |
610 } | |
611 } | |
612 | |
18757
c469e1930456
patch 8.1.2368: using old C style comments
Bram Moolenaar <Bram@vim.org>
parents:
18498
diff
changeset
|
613 #endif // FEAT_CRYPT |