0
0
mirror of https://github.com/vim/vim.git synced 2025-09-27 04:14:06 -04:00

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
This commit is contained in:
Christian Brabandt
2023-07-11 22:38:29 +02:00
parent 92f076e53e
commit 6019fed0c5
2 changed files with 90 additions and 15 deletions

View File

@@ -77,6 +77,12 @@ typedef struct {
static int crypt_sodium_init_(cryptstate_T *state, char_u *key, crypt_arg_T *arg); 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_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); 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) #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); 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 #endif
@@ -966,35 +972,45 @@ crypt_sodium_init_(
// "cat_add" should not be NULL, check anyway for safety // "cat_add" should not be NULL, check anyway for safety
if (state->method_nr == CRYPT_M_SOD2 && arg->cat_add != NULL) if (state->method_nr == CRYPT_M_SOD2 && arg->cat_add != NULL)
{ {
memcpy(arg->cat_add, &opslimit, sizeof(opslimit)); char_u buffer[20];
arg->cat_add += sizeof(opslimit); char_u *p = buffer;
vim_memset(buffer, 0, 20);
memcpy(arg->cat_add, &memlimit, sizeof(memlimit)); crypt_long_long_to_char(opslimit, p);
arg->cat_add += sizeof(memlimit); p += sizeof(opslimit);
memcpy(arg->cat_add, &alg, sizeof(alg)); crypt_long_long_to_char(memlimit, p);
arg->cat_add += sizeof(alg); p += sizeof(memlimit);
crypt_int_to_char(alg, p);
memcpy(arg->cat_add, buffer, sizeof(opslimit) + sizeof(memlimit) + sizeof(alg));
} }
} }
else 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 // Reading parameters from file
if (arg->cat_add_len if (arg->cat_add_len < size)
< (int)(sizeof(opslimit) + sizeof(memlimit) + sizeof(alg)))
{ {
sodium_free(sd_state); sodium_free(sd_state);
return FAIL; return FAIL;
} }
// derive the key from the file header // derive the key from the file header
memcpy(&opslimit, arg->cat_add, sizeof(opslimit)); memcpy(p, arg->cat_add, size);
arg->cat_add += sizeof(opslimit); arg->cat_add += size;
memcpy(&memlimit, arg->cat_add, sizeof(memlimit)); opslimit = crypt_char_to_long_long(p);
arg->cat_add += sizeof(memlimit); p += sizeof(opslimit);
memlimit = crypt_char_to_long_long(p);
memcpy(&alg, arg->cat_add, sizeof(alg)); p += sizeof(memlimit);
arg->cat_add += sizeof(alg); alg = crypt_char_to_int(p);
p += sizeof(alg);
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
crypt_sodium_report_hash_params(opslimit, crypt_sodium_report_hash_params(opslimit,
@@ -1327,6 +1343,63 @@ crypt_sodium_report_hash_params(
} }
} }
#endif #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
#endif // FEAT_CRYPT #endif // FEAT_CRYPT

View File

@@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1682,
/**/ /**/
1681, 1681,
/**/ /**/