Mercurial > vim
changeset 32719:185f2a160d5d v9.0.1682
patch 9.0.1682: sodium encryption is not portable
Commit: https://github.com/vim/vim/commit/6019fed0c50a31f0f9bb6c80e4e2b97d3f71565a
Author: Christian Brabandt <cb@256bit.org>
Date: Tue Jul 11 22:38:29 2023 +0200
patch 9.0.1682: sodium encryption is not portable
Problem: crypt: sodium encryption is not portable
Solution: use little-endian byte order for sodium encrypted files
As mentioned in #12586, sodium encryption only works on little ending
architectures, because reading and writing the sodium encryption
parameters are stored in the encrypted files in an arch-dependent way.
This of course fails for big-endian architectures like s390.
So make sure to use little-endian byte order when reading and writing
sodium encrypted files.
fixes: #12586
closes: 12655
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Wed, 09 Aug 2023 21:45:03 +0200 |
parents | 3dd63e73de28 |
children | a34d49643187 |
files | src/crypt.c src/version.c |
diffstat | 2 files changed, 90 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/src/crypt.c +++ b/src/crypt.c @@ -77,6 +77,12 @@ typedef struct { static int crypt_sodium_init_(cryptstate_T *state, char_u *key, crypt_arg_T *arg); static long crypt_sodium_buffer_decode(cryptstate_T *state, char_u *from, size_t len, char_u **buf_out, int last); static long crypt_sodium_buffer_encode(cryptstate_T *state, char_u *from, size_t len, char_u **buf_out, int last); +# if defined(FEAT_SODIUM) || defined(PROTO) +static void crypt_long_long_to_char(long long n, char_u *s); +static void crypt_int_to_char(int n, char_u *s); +static long long crypt_char_to_long_long(char_u *s); +static int crypt_char_to_int(char_u *s); +#endif #if defined(FEAT_EVAL) && defined(FEAT_SODIUM) static 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); #endif @@ -966,35 +972,45 @@ crypt_sodium_init_( // "cat_add" should not be NULL, check anyway for safety if (state->method_nr == CRYPT_M_SOD2 && arg->cat_add != NULL) { - memcpy(arg->cat_add, &opslimit, sizeof(opslimit)); - arg->cat_add += sizeof(opslimit); + char_u buffer[20]; + char_u *p = buffer; + vim_memset(buffer, 0, 20); - memcpy(arg->cat_add, &memlimit, sizeof(memlimit)); - arg->cat_add += sizeof(memlimit); + crypt_long_long_to_char(opslimit, p); + p += sizeof(opslimit); - memcpy(arg->cat_add, &alg, sizeof(alg)); - arg->cat_add += sizeof(alg); + crypt_long_long_to_char(memlimit, p); + p += sizeof(memlimit); + + crypt_int_to_char(alg, p); + memcpy(arg->cat_add, buffer, sizeof(opslimit) + sizeof(memlimit) + sizeof(alg)); } } else { + char_u buffer[20]; + char_u *p = buffer; + vim_memset(buffer, 0, 20); + int size = sizeof(opslimit) + + sizeof(memlimit) + sizeof(alg); + // Reading parameters from file - if (arg->cat_add_len - < (int)(sizeof(opslimit) + sizeof(memlimit) + sizeof(alg))) + if (arg->cat_add_len < size) { sodium_free(sd_state); return FAIL; } // derive the key from the file header - memcpy(&opslimit, arg->cat_add, sizeof(opslimit)); - arg->cat_add += sizeof(opslimit); + memcpy(p, arg->cat_add, size); + arg->cat_add += size; - memcpy(&memlimit, arg->cat_add, sizeof(memlimit)); - arg->cat_add += sizeof(memlimit); - - memcpy(&alg, arg->cat_add, sizeof(alg)); - arg->cat_add += sizeof(alg); + opslimit = crypt_char_to_long_long(p); + p += sizeof(opslimit); + memlimit = crypt_char_to_long_long(p); + p += sizeof(memlimit); + alg = crypt_char_to_int(p); + p += sizeof(alg); #ifdef FEAT_EVAL crypt_sodium_report_hash_params(opslimit, @@ -1327,6 +1343,63 @@ crypt_sodium_report_hash_params( } } #endif + + static void +crypt_long_long_to_char(long long n, char_u *s) +{ + int i; + for (i = 0; i < 8; i++) + { + s[i] = (char_u)(n & 0xff); + n = (unsigned)n >> 8; + } +} + + static void +crypt_int_to_char(int n, char_u *s) +{ + int i; + for (i = 0; i < 4; i++) + { + s[i] = (char_u)(n & 0xff); + n = (unsigned)n >> 8; + } +} + + static long long +crypt_char_to_long_long(char_u *s) +{ + unsigned long long retval = 0; + int i; + for (i = 7; i >= 0; i--) + { + if (i == 7) + retval = s[i]; + else + retval |= s[i]; + if (i > 0) + retval <<= 8; + } + return retval; +} + + static int +crypt_char_to_int(char_u *s) +{ + int retval = 0; + int i; + + for (i = 3; i >= 0; i--) + { + if (i == 3) + retval = s[i]; + else + retval |= s[i]; + if (i > 0) + retval <<= 8; + } + return retval; +} # endif #endif // FEAT_CRYPT