Mercurial > vim
comparison src/crypt.c @ 24970:7e9e53a0368f v8.2.3022
patch 8.2.3022: available encryption methods are not strong enough
Commit: https://github.com/vim/vim/commit/f573c6e1ed58d46d694c802eaf5ae3662a952744
Author: Christian Brabandt <cb@256bit.org>
Date: Sun Jun 20 14:02:16 2021 +0200
patch 8.2.3022: available encryption methods are not strong enough
Problem: Available encryption methods are not strong enough.
Solution: Add initial support for xchaha20. (Christian Brabandt,
closes #8394)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 20 Jun 2021 14:15:07 +0200 |
parents | c469e1930456 |
children | fa31a0ea09e1 |
comparison
equal
deleted
inserted
replaced
24969:445ed84ae76a | 24970:7e9e53a0368f |
---|---|
9 | 9 |
10 /* | 10 /* |
11 * crypt.c: Generic encryption support. | 11 * crypt.c: Generic encryption support. |
12 */ | 12 */ |
13 #include "vim.h" | 13 #include "vim.h" |
14 | |
15 #ifdef FEAT_SODIUM | |
16 # include <sodium.h> | |
17 #endif | |
14 | 18 |
15 #if defined(FEAT_CRYPT) || defined(PROTO) | 19 #if defined(FEAT_CRYPT) || defined(PROTO) |
16 /* | 20 /* |
17 * Optional encryption support. | 21 * Optional encryption support. |
18 * Mohsin Ahmed, mosh@sasi.com, 1998-09-24 | 22 * Mohsin Ahmed, mosh@sasi.com, 1998-09-24 |
31 | 35 |
32 typedef struct { | 36 typedef struct { |
33 char *name; // encryption name as used in 'cryptmethod' | 37 char *name; // encryption name as used in 'cryptmethod' |
34 char *magic; // magic bytes stored in file header | 38 char *magic; // magic bytes stored in file header |
35 int salt_len; // length of salt, or 0 when not using salt | 39 int salt_len; // length of salt, or 0 when not using salt |
36 int seed_len; // length of seed, or 0 when not using salt | 40 int seed_len; // length of seed, or 0 when not using seed |
37 #ifdef CRYPT_NOT_INPLACE | 41 #ifdef CRYPT_NOT_INPLACE |
38 int works_inplace; // encryption/decryption can be done in-place | 42 int works_inplace; // encryption/decryption can be done in-place |
39 #endif | 43 #endif |
40 int whole_undofile; // whole undo file is encrypted | 44 int whole_undofile; // whole undo file is encrypted |
41 | 45 |
47 char_u *salt, int salt_len, char_u *seed, int seed_len); | 51 char_u *salt, int salt_len, char_u *seed, int seed_len); |
48 | 52 |
49 // Function pointers for encoding/decoding from one buffer into another. | 53 // Function pointers for encoding/decoding from one buffer into another. |
50 // Optional, however, these or the _buffer ones should be configured. | 54 // Optional, however, these or the _buffer ones should be configured. |
51 void (*encode_fn)(cryptstate_T *state, char_u *from, size_t len, | 55 void (*encode_fn)(cryptstate_T *state, char_u *from, size_t len, |
52 char_u *to); | 56 char_u *to, int last); |
53 void (*decode_fn)(cryptstate_T *state, char_u *from, size_t len, | 57 void (*decode_fn)(cryptstate_T *state, char_u *from, size_t len, |
54 char_u *to); | 58 char_u *to, int last); |
55 | 59 |
56 // Function pointers for encoding and decoding, can buffer data if needed. | 60 // Function pointers for encoding and decoding, can buffer data if needed. |
57 // Optional (however, these or the above should be configured). | 61 // Optional (however, these or the above should be configured). |
58 long (*encode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len, | 62 long (*encode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len, |
59 char_u **newptr); | 63 char_u **newptr, int last); |
60 long (*decode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len, | 64 long (*decode_buffer_fn)(cryptstate_T *state, char_u *from, size_t len, |
61 char_u **newptr); | 65 char_u **newptr, int last); |
62 | 66 |
63 // Function pointers for in-place encoding and decoding, used for | 67 // Function pointers for in-place encoding and decoding, used for |
64 // crypt_*_inplace(). "from" and "to" arguments will be equal. | 68 // crypt_*_inplace(). "from" and "to" arguments will be equal. |
65 // These may be the same as decode_fn and encode_fn above, however an | 69 // These may be the same as decode_fn and encode_fn above, however an |
66 // algorithm may implement them in a way that is not interchangeable with | 70 // algorithm may implement them in a way that is not interchangeable with |
67 // the crypt_(en|de)code() interface (for example because it wishes to add | 71 // the crypt_(en|de)code() interface (for example because it wishes to add |
68 // padding to files). | 72 // padding to files). |
69 // This method is used for swap and undo files which have a rigid format. | 73 // This method is used for swap and undo files which have a rigid format. |
70 void (*encode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len, | 74 void (*encode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len, |
71 char_u *p2); | 75 char_u *p2, int last); |
72 void (*decode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len, | 76 void (*decode_inplace_fn)(cryptstate_T *state, char_u *p1, size_t len, |
73 char_u *p2); | 77 char_u *p2, int last); |
74 } cryptmethod_T; | 78 } cryptmethod_T; |
75 | 79 |
76 // index is method_nr of cryptstate_T, CRYPT_M_* | 80 // index is method_nr of cryptstate_T, CRYPT_M_* |
77 static cryptmethod_T cryptmethods[CRYPT_M_COUNT] = { | 81 static cryptmethod_T cryptmethods[CRYPT_M_COUNT] = { |
78 // PK_Zip; very weak | 82 // PK_Zip; very weak |
124 crypt_blowfish_encode, crypt_blowfish_decode, | 128 crypt_blowfish_encode, crypt_blowfish_decode, |
125 NULL, NULL, | 129 NULL, NULL, |
126 crypt_blowfish_encode, crypt_blowfish_decode, | 130 crypt_blowfish_encode, crypt_blowfish_decode, |
127 }, | 131 }, |
128 | 132 |
133 // XChaCha20 using libsodium | |
134 { | |
135 "xchacha20", | |
136 "VimCrypt~04!", | |
137 #ifdef FEAT_SODIUM | |
138 crypto_pwhash_argon2id_SALTBYTES, // 16 | |
139 #else | |
140 16, | |
141 #endif | |
142 8, | |
143 #ifdef CRYPT_NOT_INPLACE | |
144 FALSE, | |
145 #endif | |
146 FALSE, | |
147 NULL, | |
148 crypt_sodium_init, | |
149 crypt_sodium_encode, crypt_sodium_decode, | |
150 crypt_sodium_buffer_encode, crypt_sodium_buffer_decode, | |
151 crypt_sodium_encode, crypt_sodium_decode, | |
152 }, | |
153 | |
129 // NOTE: when adding a new method, use some random bytes for the magic key, | 154 // NOTE: when adding a new method, use some random bytes for the magic key, |
130 // to avoid that a text file is recognized as encrypted. | 155 // to avoid that a text file is recognized as encrypted. |
131 }; | 156 }; |
157 | |
158 #ifdef FEAT_SODIUM | |
159 typedef struct { | |
160 size_t count; | |
161 unsigned char key[crypto_box_SEEDBYTES]; | |
162 // 32, same as crypto_secretstream_xchacha20poly1305_KEYBYTES | |
163 crypto_secretstream_xchacha20poly1305_state | |
164 state; | |
165 } sodium_state_T; | |
166 #endif | |
132 | 167 |
133 #define CRYPT_MAGIC_LEN 12 // cannot change | 168 #define CRYPT_MAGIC_LEN 12 // cannot change |
134 static char crypt_magic_head[] = "VimCrypt~"; | 169 static char crypt_magic_head[] = "VimCrypt~"; |
135 | 170 |
136 /* | 171 /* |
258 if (state == NULL) | 293 if (state == NULL) |
259 return state; | 294 return state; |
260 | 295 |
261 state->method_nr = method_nr; | 296 state->method_nr = method_nr; |
262 if (cryptmethods[method_nr].init_fn( | 297 if (cryptmethods[method_nr].init_fn( |
263 state, key, salt, salt_len, seed, seed_len) == FAIL) | 298 state, key, salt, salt_len, seed, seed_len) == FAIL) |
264 { | 299 { |
265 vim_free(state); | 300 vim_free(state); |
266 return NULL; | 301 return NULL; |
267 } | 302 } |
268 return state; | 303 return state; |
363 seed = *header + CRYPT_MAGIC_LEN + salt_len; | 398 seed = *header + CRYPT_MAGIC_LEN + salt_len; |
364 | 399 |
365 // TODO: Should this be crypt method specific? (Probably not worth | 400 // TODO: Should this be crypt method specific? (Probably not worth |
366 // it). sha2_seed is pretty bad for large amounts of entropy, so make | 401 // it). sha2_seed is pretty bad for large amounts of entropy, so make |
367 // that into something which is suitable for anything. | 402 // that into something which is suitable for anything. |
368 sha2_seed(salt, salt_len, seed, seed_len); | 403 #ifdef FEAT_SODIUM |
369 } | 404 if (sodium_init() >= 0) |
370 | 405 { |
406 randombytes_buf(salt, salt_len); | |
407 randombytes_buf(seed, seed_len); | |
408 } | |
409 else | |
410 #endif | |
411 sha2_seed(salt, salt_len, seed, seed_len); | |
412 } | |
371 state = crypt_create(method_nr, key, salt, salt_len, seed, seed_len); | 413 state = crypt_create(method_nr, key, salt, salt_len, seed, seed_len); |
372 if (state == NULL) | 414 if (state == NULL) |
373 VIM_CLEAR(*header); | 415 VIM_CLEAR(*header); |
374 return state; | 416 return state; |
375 } | 417 } |
378 * Free the crypt state. | 420 * Free the crypt state. |
379 */ | 421 */ |
380 void | 422 void |
381 crypt_free_state(cryptstate_T *state) | 423 crypt_free_state(cryptstate_T *state) |
382 { | 424 { |
383 vim_free(state->method_state); | 425 #ifdef FEAT_SODIUM |
426 if (state->method_nr == CRYPT_M_SOD) | |
427 { | |
428 sodium_memzero(state->method_state, sizeof(sodium_state_T)); | |
429 sodium_free(state->method_state); | |
430 } | |
431 else | |
432 #endif | |
433 vim_free(state->method_state); | |
384 vim_free(state); | 434 vim_free(state); |
385 } | 435 } |
386 | 436 |
387 #ifdef CRYPT_NOT_INPLACE | 437 #ifdef CRYPT_NOT_INPLACE |
388 /* | 438 /* |
393 long | 443 long |
394 crypt_encode_alloc( | 444 crypt_encode_alloc( |
395 cryptstate_T *state, | 445 cryptstate_T *state, |
396 char_u *from, | 446 char_u *from, |
397 size_t len, | 447 size_t len, |
398 char_u **newptr) | 448 char_u **newptr, |
449 int last) | |
399 { | 450 { |
400 cryptmethod_T *method = &cryptmethods[state->method_nr]; | 451 cryptmethod_T *method = &cryptmethods[state->method_nr]; |
401 | 452 |
402 if (method->encode_buffer_fn != NULL) | 453 if (method->encode_buffer_fn != NULL) |
403 // Has buffer function, pass through. | 454 // Has buffer function, pass through. |
404 return method->encode_buffer_fn(state, from, len, newptr); | 455 return method->encode_buffer_fn(state, from, len, newptr, last); |
405 if (len == 0) | 456 if (len == 0) |
406 // Not buffering, just return EOF. | 457 // Not buffering, just return EOF. |
407 return (long)len; | 458 return (long)len; |
408 | 459 |
409 *newptr = alloc(len); | 460 *newptr = alloc(len + 50); |
410 if (*newptr == NULL) | 461 if (*newptr == NULL) |
411 return -1; | 462 return -1; |
412 method->encode_fn(state, from, len, *newptr); | 463 method->encode_fn(state, from, len, *newptr, last); |
413 return (long)len; | 464 return (long)len; |
414 } | 465 } |
415 | 466 |
416 /* | 467 /* |
417 * Decrypt "ptr[len]" and store the result in a newly allocated buffer, which | 468 * Decrypt "ptr[len]" and store the result in a newly allocated buffer, which |
421 long | 472 long |
422 crypt_decode_alloc( | 473 crypt_decode_alloc( |
423 cryptstate_T *state, | 474 cryptstate_T *state, |
424 char_u *ptr, | 475 char_u *ptr, |
425 long len, | 476 long len, |
426 char_u **newptr) | 477 char_u **newptr, |
478 int last) | |
427 { | 479 { |
428 cryptmethod_T *method = &cryptmethods[state->method_nr]; | 480 cryptmethod_T *method = &cryptmethods[state->method_nr]; |
429 | 481 |
430 if (method->decode_buffer_fn != NULL) | 482 if (method->decode_buffer_fn != NULL) |
431 // Has buffer function, pass through. | 483 // Has buffer function, pass through. |
432 return method->decode_buffer_fn(state, ptr, len, newptr); | 484 return method->decode_buffer_fn(state, ptr, len, newptr, last); |
433 | 485 |
434 if (len == 0) | 486 if (len == 0) |
435 // Not buffering, just return EOF. | 487 // Not buffering, just return EOF. |
436 return len; | 488 return len; |
437 | 489 |
438 *newptr = alloc(len); | 490 *newptr = alloc(len); |
439 if (*newptr == NULL) | 491 if (*newptr == NULL) |
440 return -1; | 492 return -1; |
441 method->decode_fn(state, ptr, len, *newptr); | 493 method->decode_fn(state, ptr, len, *newptr, last); |
442 return len; | 494 return len; |
443 } | 495 } |
444 #endif | 496 #endif |
445 | 497 |
446 /* | 498 /* |
449 void | 501 void |
450 crypt_encode( | 502 crypt_encode( |
451 cryptstate_T *state, | 503 cryptstate_T *state, |
452 char_u *from, | 504 char_u *from, |
453 size_t len, | 505 size_t len, |
454 char_u *to) | 506 char_u *to, |
455 { | 507 int last) |
456 cryptmethods[state->method_nr].encode_fn(state, from, len, to); | 508 { |
509 cryptmethods[state->method_nr].encode_fn(state, from, len, to, last); | |
457 } | 510 } |
458 | 511 |
459 #if 0 // unused | 512 #if 0 // unused |
460 /* | 513 /* |
461 * decrypting "from[len]" into "to[len]". | 514 * decrypting "from[len]" into "to[len]". |
463 void | 516 void |
464 crypt_decode( | 517 crypt_decode( |
465 cryptstate_T *state, | 518 cryptstate_T *state, |
466 char_u *from, | 519 char_u *from, |
467 size_t len, | 520 size_t len, |
468 char_u *to) | 521 char_u *to, |
469 { | 522 int last) |
470 cryptmethods[state->method_nr].decode_fn(state, from, len, to); | 523 { |
524 cryptmethods[state->method_nr].decode_fn(state, from, len, to, last); | |
471 } | 525 } |
472 #endif | 526 #endif |
473 | 527 |
474 /* | 528 /* |
475 * Simple inplace encryption, modifies "buf[len]" in place. | 529 * Simple inplace encryption, modifies "buf[len]" in place. |
476 */ | 530 */ |
477 void | 531 void |
478 crypt_encode_inplace( | 532 crypt_encode_inplace( |
479 cryptstate_T *state, | 533 cryptstate_T *state, |
480 char_u *buf, | 534 char_u *buf, |
481 size_t len) | 535 size_t len, |
482 { | 536 int last) |
483 cryptmethods[state->method_nr].encode_inplace_fn(state, buf, len, buf); | 537 { |
538 cryptmethods[state->method_nr].encode_inplace_fn(state, buf, len, | |
539 buf, last); | |
484 } | 540 } |
485 | 541 |
486 /* | 542 /* |
487 * Simple inplace decryption, modifies "buf[len]" in place. | 543 * Simple inplace decryption, modifies "buf[len]" in place. |
488 */ | 544 */ |
489 void | 545 void |
490 crypt_decode_inplace( | 546 crypt_decode_inplace( |
491 cryptstate_T *state, | 547 cryptstate_T *state, |
492 char_u *buf, | 548 char_u *buf, |
493 size_t len) | 549 size_t len, |
494 { | 550 int last) |
495 cryptmethods[state->method_nr].decode_inplace_fn(state, buf, len, buf); | 551 { |
552 cryptmethods[state->method_nr].decode_inplace_fn(state, buf, len, | |
553 buf, last); | |
496 } | 554 } |
497 | 555 |
498 /* | 556 /* |
499 * Free an allocated crypt key. Clear the text to make sure it doesn't stay | 557 * Free an allocated crypt key. Clear the text to make sure it doesn't stay |
500 * in memory anywhere. | 558 * in memory anywhere. |
520 { | 578 { |
521 if (method < CRYPT_M_BF2) | 579 if (method < CRYPT_M_BF2) |
522 { | 580 { |
523 msg_scroll = TRUE; | 581 msg_scroll = TRUE; |
524 msg(_("Warning: Using a weak encryption method; see :help 'cm'")); | 582 msg(_("Warning: Using a weak encryption method; see :help 'cm'")); |
583 } | |
584 if (method == CRYPT_M_SOD) | |
585 { | |
586 // encryption uses padding and MAC, that does not work very well with | |
587 // swap and undo files, so disable them | |
588 mf_close_file(curbuf, TRUE); // remove the swap file | |
589 set_option_value((char_u *)"swf", 0, NULL, OPT_LOCAL); | |
590 #ifdef FEAT_PERSISTENT_UNDO | |
591 set_option_value((char_u *)"udf", 0, NULL, OPT_LOCAL); | |
592 #endif | |
593 | |
594 msg_scroll = TRUE; | |
595 msg(_("Note: Encryption of swapfile not supported, disabling swap- and undofile")); | |
525 } | 596 } |
526 } | 597 } |
527 | 598 |
528 void | 599 void |
529 crypt_check_current_method(void) | 600 crypt_check_current_method(void) |
608 STRCAT(IObuff, *buf->b_p_cm == NUL ? p_cm : buf->b_p_cm); | 679 STRCAT(IObuff, *buf->b_p_cm == NUL ? p_cm : buf->b_p_cm); |
609 STRCAT(IObuff, "]"); | 680 STRCAT(IObuff, "]"); |
610 } | 681 } |
611 } | 682 } |
612 | 683 |
684 int | |
685 crypt_sodium_init( | |
686 cryptstate_T *state UNUSED, | |
687 char_u *key UNUSED, | |
688 char_u *salt UNUSED, | |
689 int salt_len UNUSED, | |
690 char_u *seed UNUSED, | |
691 int seed_len UNUSED) | |
692 { | |
693 # ifdef FEAT_SODIUM | |
694 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES | |
695 unsigned char dkey[crypto_box_SEEDBYTES]; // 32 | |
696 sodium_state_T *sd_state; | |
697 | |
698 if (sodium_init() < 0) | |
699 return FAIL; | |
700 | |
701 sd_state = (sodium_state_T *)sodium_malloc(sizeof(sodium_state_T)); | |
702 sodium_memzero(sd_state, sizeof(sodium_state_T)); | |
703 | |
704 // derive a key from the password | |
705 if (crypto_pwhash(dkey, sizeof(dkey), (const char *)key, STRLEN(key), salt, | |
706 crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE, | |
707 crypto_pwhash_ALG_DEFAULT) != 0) | |
708 { | |
709 // out of memory | |
710 sodium_free(sd_state); | |
711 return FAIL; | |
712 } | |
713 memcpy(sd_state->key, dkey, crypto_box_SEEDBYTES); | |
714 sd_state->count = 0; | |
715 state->method_state = sd_state; | |
716 | |
717 return OK; | |
718 # else | |
719 emsg(e_libsodium_not_built_in); | |
720 return FAIL; | |
721 # endif | |
722 } | |
723 | |
724 /* | |
725 * Encrypt "from[len]" into "to[len]". | |
726 * "from" and "to" can be equal to encrypt in place. | |
727 * Call needs to ensure that there is enough space in to (for the header) | |
728 */ | |
729 void | |
730 crypt_sodium_encode( | |
731 cryptstate_T *state UNUSED, | |
732 char_u *from UNUSED, | |
733 size_t len UNUSED, | |
734 char_u *to UNUSED, | |
735 int last UNUSED) | |
736 { | |
737 # ifdef FEAT_SODIUM | |
738 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES | |
739 sodium_state_T *sod_st = state->method_state; | |
740 unsigned char tag = last | |
741 ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0; | |
742 | |
743 if (sod_st->count == 0) | |
744 { | |
745 if (len <= crypto_secretstream_xchacha20poly1305_HEADERBYTES) | |
746 { | |
747 emsg(e_libsodium_cannot_encrypt_header); | |
748 return; | |
749 } | |
750 crypto_secretstream_xchacha20poly1305_init_push(&sod_st->state, | |
751 to, sod_st->key); | |
752 to += crypto_secretstream_xchacha20poly1305_HEADERBYTES; | |
753 } | |
754 | |
755 if (sod_st->count && len <= crypto_secretstream_xchacha20poly1305_ABYTES) | |
756 { | |
757 emsg(e_libsodium_cannot_encrypt_buffer); | |
758 return; | |
759 } | |
760 | |
761 crypto_secretstream_xchacha20poly1305_push(&sod_st->state, to, NULL, | |
762 from, len, NULL, 0, tag); | |
763 | |
764 sod_st->count++; | |
765 # endif | |
766 } | |
767 | |
768 /* TODO: Unused | |
769 * Decrypt "from[len]" into "to[len]". | |
770 * "from" and "to" can be equal to encrypt in place. | |
771 */ | |
772 void | |
773 crypt_sodium_decode( | |
774 cryptstate_T *state UNUSED, | |
775 char_u *from UNUSED, | |
776 size_t len UNUSED, | |
777 char_u *to UNUSED, | |
778 int last UNUSED) | |
779 { | |
780 # ifdef FEAT_SODIUM | |
781 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES | |
782 sodium_state_T *sod_st = state->method_state; | |
783 unsigned char tag; | |
784 unsigned long long buf_len; | |
785 char_u *p1 = from; | |
786 char_u *p2 = to; | |
787 char_u *buf_out; | |
788 | |
789 if (sod_st->count == 0 | |
790 && len <= crypto_secretstream_xchacha20poly1305_HEADERBYTES) | |
791 { | |
792 emsg(e_libsodium_cannot_decrypt_header); | |
793 return; | |
794 } | |
795 | |
796 buf_out = (char_u *)alloc(len); | |
797 | |
798 if (buf_out == NULL) | |
799 { | |
800 emsg(e_libsodium_cannot_allocate_buffer); | |
801 return; | |
802 } | |
803 if (sod_st->count == 0) | |
804 { | |
805 if (crypto_secretstream_xchacha20poly1305_init_pull( | |
806 &sod_st->state, from, sod_st->key) != 0) | |
807 { | |
808 emsg(e_libsodium_decryption_failed_header_incomplete); | |
809 goto fail; | |
810 } | |
811 | |
812 from += crypto_secretstream_xchacha20poly1305_HEADERBYTES; | |
813 len -= crypto_secretstream_xchacha20poly1305_HEADERBYTES; | |
814 | |
815 if (p1 == p2) | |
816 to += crypto_secretstream_xchacha20poly1305_HEADERBYTES; | |
817 } | |
818 | |
819 if (sod_st->count && len <= crypto_secretstream_xchacha20poly1305_ABYTES) | |
820 { | |
821 emsg(e_libsodium_cannot_decrypt_buffer); | |
822 return; | |
823 } | |
824 if (crypto_secretstream_xchacha20poly1305_pull(&sod_st->state, | |
825 buf_out, &buf_len, &tag, from, len, NULL, 0) != 0) | |
826 { | |
827 emsg(e_libsodium_decription_failed); | |
828 goto fail; | |
829 } | |
830 sod_st->count++; | |
831 | |
832 if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !last) | |
833 { | |
834 emsg(e_libsodium_decyption_failed_premature); | |
835 goto fail; | |
836 } | |
837 if (p1 == p2) | |
838 mch_memmove(p2, buf_out, buf_len); | |
839 | |
840 fail: | |
841 vim_free(buf_out); | |
842 # endif | |
843 } | |
844 | |
845 /* | |
846 * Encrypt "from[len]" into "to[len]". | |
847 * "from" and "to" can be equal to encrypt in place. | |
848 */ | |
849 long | |
850 crypt_sodium_buffer_encode( | |
851 cryptstate_T *state UNUSED, | |
852 char_u *from UNUSED, | |
853 size_t len UNUSED, | |
854 char_u **buf_out UNUSED, | |
855 int last UNUSED) | |
856 { | |
857 # ifdef FEAT_SODIUM | |
858 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES | |
859 unsigned long long out_len; | |
860 char_u *ptr; | |
861 unsigned char tag = last | |
862 ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0; | |
863 int length; | |
864 sodium_state_T *sod_st = state->method_state; | |
865 int first = (sod_st->count == 0); | |
866 | |
867 length = len + crypto_secretstream_xchacha20poly1305_ABYTES | |
868 + (first ? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0); | |
869 *buf_out = alloc_clear(length); | |
870 if (*buf_out == NULL) | |
871 { | |
872 emsg(e_libsodium_cannot_allocate_buffer); | |
873 return -1; | |
874 } | |
875 ptr = *buf_out; | |
876 | |
877 if (first) | |
878 { | |
879 crypto_secretstream_xchacha20poly1305_init_push(&sod_st->state, | |
880 ptr, sod_st->key); | |
881 ptr += crypto_secretstream_xchacha20poly1305_HEADERBYTES; | |
882 } | |
883 | |
884 crypto_secretstream_xchacha20poly1305_push(&sod_st->state, ptr, | |
885 &out_len, from, len, NULL, 0, tag); | |
886 | |
887 sod_st->count++; | |
888 return out_len + (first | |
889 ? crypto_secretstream_xchacha20poly1305_HEADERBYTES : 0); | |
890 # else | |
891 return -1; | |
892 # endif | |
893 } | |
894 | |
895 /* | |
896 * Decrypt "from[len]" into "to[len]". | |
897 * "from" and "to" can be equal to encrypt in place. | |
898 */ | |
899 long | |
900 crypt_sodium_buffer_decode( | |
901 cryptstate_T *state UNUSED, | |
902 char_u *from UNUSED, | |
903 size_t len UNUSED, | |
904 char_u **buf_out UNUSED, | |
905 int last UNUSED) | |
906 { | |
907 # ifdef FEAT_SODIUM | |
908 // crypto_box_SEEDBYTES == crypto_secretstream_xchacha20poly1305_KEYBYTES | |
909 sodium_state_T *sod_st = state->method_state; | |
910 unsigned char tag; | |
911 unsigned long long out_len; | |
912 *buf_out = alloc_clear(len); | |
913 if (*buf_out == NULL) | |
914 { | |
915 emsg(e_libsodium_cannot_allocate_buffer); | |
916 return -1; | |
917 } | |
918 | |
919 if (sod_st->count == 0) | |
920 { | |
921 if (crypto_secretstream_xchacha20poly1305_init_pull(&sod_st->state, | |
922 from, sod_st->key) != 0) | |
923 { | |
924 emsg(e_libsodium_decryption_failed_header_incomplete); | |
925 return -1; | |
926 } | |
927 from += crypto_secretstream_xchacha20poly1305_HEADERBYTES; | |
928 len -= crypto_secretstream_xchacha20poly1305_HEADERBYTES; | |
929 sod_st->count++; | |
930 } | |
931 if (crypto_secretstream_xchacha20poly1305_pull(&sod_st->state, | |
932 *buf_out, &out_len, &tag, from, len, NULL, 0) != 0) | |
933 { | |
934 emsg(e_libsodium_decription_failed); | |
935 return -1; | |
936 } | |
937 | |
938 if (tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !last) | |
939 emsg(e_libsodium_decyption_failed_premature); | |
940 return (long) out_len; | |
941 # else | |
942 return -1; | |
943 # endif | |
944 } | |
945 | |
613 #endif // FEAT_CRYPT | 946 #endif // FEAT_CRYPT |