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