mirror of
https://github.com/jedisct1/libsodium.git
synced 2024-12-19 18:15:18 -07:00
Implement key shielding to protect against side channels
We may want to fold this into `sodium_mprotect_*()` instead of exposing these functions. The drawback is that a transition from PROT_NONE to PROT_READ (or the other way round) would need an intermediary state in PROT_WRITE for shielding/unshielding. Shielding is also not thread-safe, while the `mprotect_*()` functions are, and adding locks would make things more complicated than they probably should.
This commit is contained in:
parent
60f4bc8212
commit
bfeca0eb73
@ -158,6 +158,12 @@ int sodium_mprotect_readonly(void *ptr) __attribute__ ((nonnull));
|
||||
SODIUM_EXPORT
|
||||
int sodium_mprotect_readwrite(void *ptr) __attribute__ ((nonnull));
|
||||
|
||||
SODIUM_EXPORT
|
||||
int sodium_mshield(void *ptr) __attribute__ ((nonnull));
|
||||
|
||||
SODIUM_EXPORT
|
||||
int sodium_munshield(void *ptr) __attribute__ ((nonnull));
|
||||
|
||||
SODIUM_EXPORT
|
||||
int sodium_pad(size_t *padded_buflen_p, unsigned char *buf,
|
||||
size_t unpadded_buflen, size_t blocksize, size_t max_buflen)
|
||||
|
@ -43,7 +43,10 @@ void *alloca (size_t);
|
||||
#endif
|
||||
|
||||
#include "core.h"
|
||||
#include "crypto_generichash.h"
|
||||
#include "crypto_stream.h"
|
||||
#include "randombytes.h"
|
||||
#include "private/common.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifndef ENOSYS
|
||||
@ -58,6 +61,8 @@ void *alloca (size_t);
|
||||
#define CANARY_SIZE 16U
|
||||
#define GARBAGE_VALUE 0xdb
|
||||
|
||||
#define SHIELDING_PREKEY_SIZE 16384U
|
||||
|
||||
#ifndef MAP_NOCORE
|
||||
# ifdef MAP_CONCEAL
|
||||
# define MAP_NOCORE MAP_CONCEAL
|
||||
@ -87,6 +92,7 @@ void *alloca (size_t);
|
||||
|
||||
static size_t page_size;
|
||||
static unsigned char canary[CANARY_SIZE];
|
||||
static unsigned char shielding_prekey[SHIELDING_PREKEY_SIZE];
|
||||
|
||||
/* LCOV_EXCL_START */
|
||||
#ifdef HAVE_WEAK_SYMBOLS
|
||||
@ -402,7 +408,11 @@ _sodium_alloc_init(void)
|
||||
sodium_misuse(); /* LCOV_EXCL_LINE */
|
||||
}
|
||||
#endif
|
||||
randombytes_buf(canary, sizeof canary);
|
||||
COMPILER_ASSERT(sizeof shielding_prekey >= randombytes_SEEDBYTES);
|
||||
randombytes_buf(shielding_prekey, randombytes_SEEDBYTES);
|
||||
randombytes_buf_deterministic(canary, sizeof canary, shielding_prekey);
|
||||
shielding_prekey[0] ^= 0x01;
|
||||
randombytes_buf_deterministic(shielding_prekey, sizeof shielding_prekey, shielding_prekey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -715,6 +725,38 @@ sodium_mprotect_readwrite(void *ptr)
|
||||
return _sodium_mprotect(ptr, _mprotect_readwrite);
|
||||
}
|
||||
|
||||
int
|
||||
sodium_mshield(void *ptr)
|
||||
{
|
||||
unsigned char shielding_key[crypto_stream_KEYBYTES];
|
||||
unsigned char nonce[crypto_stream_NONCEBYTES];
|
||||
unsigned char *base_ptr;
|
||||
unsigned char *unprotected_ptr;
|
||||
size_t unprotected_size;
|
||||
|
||||
unprotected_ptr = _unprotected_ptr_from_user_ptr(ptr);
|
||||
base_ptr = unprotected_ptr - page_size * 2U;
|
||||
memcpy(&unprotected_size, base_ptr, sizeof unprotected_size);
|
||||
|
||||
crypto_generichash(shielding_key, sizeof shielding_key,
|
||||
shielding_prekey, sizeof shielding_prekey, NULL, 0);
|
||||
COMPILER_ASSERT(sizeof nonce >= (sizeof unprotected_ptr) + (sizeof unprotected_size));
|
||||
memset(nonce, 0, sizeof nonce);
|
||||
memcpy(nonce, &unprotected_ptr, sizeof unprotected_ptr);
|
||||
memcpy(nonce + sizeof unprotected_ptr, &unprotected_size, sizeof unprotected_size);
|
||||
crypto_stream_xor(unprotected_ptr, unprotected_ptr, unprotected_size, nonce, shielding_prekey);
|
||||
sodium_memzero(shielding_key, sizeof shielding_key);
|
||||
sodium_memzero(nonce, sizeof nonce);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sodium_munshield(void *ptr)
|
||||
{
|
||||
return sodium_mshield(ptr);
|
||||
}
|
||||
|
||||
int
|
||||
sodium_pad(size_t *padded_buflen_p, unsigned char *buf,
|
||||
size_t unpadded_buflen, size_t blocksize, size_t max_buflen)
|
||||
|
@ -40,10 +40,25 @@ segv_handler(int sig)
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
void * buf;
|
||||
void *buf;
|
||||
void *buf2;
|
||||
size_t size;
|
||||
unsigned int i;
|
||||
|
||||
size = randombytes_uniform(100U);
|
||||
if ((buf = sodium_malloc(size)) == NULL ||
|
||||
(buf2 = sodium_malloc(size)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
randombytes_buf(buf, size);
|
||||
memcpy(buf2, buf, size);
|
||||
sodium_mshield(buf);
|
||||
assert(size == 0U || memcmp(buf, buf2, size) != 0);
|
||||
sodium_munshield(buf);
|
||||
assert(size == 0U || memcmp(buf, buf2, size) == 0);
|
||||
sodium_free(buf2);
|
||||
sodium_free(buf);
|
||||
|
||||
if (sodium_malloc(SIZE_MAX - 1U) != NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user