Added memory locking for secrets (#1491)
When caching a PIN in memory or using an OpenSSL private key this data should not be swapped to disk.
This commit is contained in:
parent
6bf67f7917
commit
ea6f7cfe1d
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "common/libscdl.h"
|
||||
#include "internal.h"
|
||||
#include "sc-ossl-compat.h"
|
||||
|
||||
static int ignored_reader(sc_context_t *ctx, sc_reader_t *reader)
|
||||
{
|
||||
|
@ -831,6 +832,13 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
|
|||
return r;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPENSSL
|
||||
if (!CRYPTO_secure_malloc_initialized()) {
|
||||
/* XXX What's a reasonable amount of secure heap? */
|
||||
CRYPTO_secure_malloc_init(4096, 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
process_config_file(ctx, &opts);
|
||||
sc_log(ctx, "==================================="); /* first thing in the log */
|
||||
sc_log(ctx, "opensc version: %s", sc_get_version());
|
||||
|
|
|
@ -131,6 +131,8 @@ sc_lock
|
|||
sc_logout
|
||||
sc_make_cache_dir
|
||||
sc_mem_clear
|
||||
sc_mem_secure_alloc
|
||||
sc_mem_secure_free
|
||||
sc_mem_reverse
|
||||
sc_match_atr_block
|
||||
sc_path_print
|
||||
|
|
|
@ -1366,6 +1366,8 @@ int sc_base64_decode(const char *in, u8 *out, size_t outlen);
|
|||
* @param len length of the memory buffer
|
||||
*/
|
||||
void sc_mem_clear(void *ptr, size_t len);
|
||||
void *sc_mem_secure_alloc(size_t len);
|
||||
void sc_mem_secure_free(void *ptr, size_t len);
|
||||
int sc_mem_reverse(unsigned char *buf, size_t len);
|
||||
|
||||
int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize);
|
||||
|
|
|
@ -2496,8 +2496,15 @@ sc_pkcs15_make_absolute_path(const struct sc_path *parent, struct sc_path *child
|
|||
void sc_pkcs15_free_object_content(struct sc_pkcs15_object *obj)
|
||||
{
|
||||
if (obj->content.value && obj->content.len) {
|
||||
sc_mem_clear(obj->content.value, obj->content.len);
|
||||
free(obj->content.value);
|
||||
if (SC_PKCS15_TYPE_AUTH & obj->type
|
||||
|| SC_PKCS15_TYPE_SKEY & obj->type
|
||||
|| SC_PKCS15_TYPE_PRKEY & obj->type) {
|
||||
/* clean everything that potentially contains a secret */
|
||||
sc_mem_clear(obj->content.value, obj->content.len);
|
||||
sc_mem_secure_free(obj->content.value, obj->content.len);
|
||||
} else {
|
||||
free(obj->content.value);
|
||||
}
|
||||
}
|
||||
obj->content.value = NULL;
|
||||
obj->content.len = 0;
|
||||
|
@ -2521,7 +2528,13 @@ sc_pkcs15_allocate_object_content(struct sc_context *ctx, struct sc_pkcs15_objec
|
|||
/* Need to pass by temporary variable,
|
||||
* because 'value' and 'content.value' pointers can be the sames.
|
||||
*/
|
||||
tmp_buf = calloc(sizeof *tmp_buf, len);
|
||||
if (SC_PKCS15_TYPE_AUTH & obj->type
|
||||
|| SC_PKCS15_TYPE_SKEY & obj->type
|
||||
|| SC_PKCS15_TYPE_PRKEY & obj->type) {
|
||||
tmp_buf = sc_mem_secure_alloc(len);
|
||||
} else {
|
||||
tmp_buf = malloc(len);
|
||||
}
|
||||
if (!tmp_buf)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
|
|
@ -230,6 +230,19 @@ static sc_ossl_inline int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
|
|||
}
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
|
||||
static sc_ossl_inline int CRYPTO_secure_malloc_init(size_t size, int minsize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sc_ossl_inline int CRYPTO_secure_malloc_initialized()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <openssl/crypto.h> /* for OPENSSL_cleanse */
|
||||
#endif
|
||||
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#ifdef PACKAGE_VERSION
|
||||
|
@ -42,6 +43,19 @@ static const char *sc_version = PACKAGE_VERSION;
|
|||
static const char *sc_version = "(undef)";
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define PAGESIZE 0
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#ifndef PAGESIZE
|
||||
#define PAGESIZE 0
|
||||
#endif
|
||||
#endif
|
||||
static size_t page_size = PAGESIZE;
|
||||
|
||||
const char *sc_get_version(void)
|
||||
{
|
||||
return sc_version;
|
||||
|
@ -826,6 +840,52 @@ int _sc_parse_atr(sc_reader_t *reader)
|
|||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static void init_page_size()
|
||||
{
|
||||
if (page_size == 0) {
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO system_info;
|
||||
GetSystemInfo(&system_info);
|
||||
page_size = system_info.dwPageSize;
|
||||
#else
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
if ((long) page_size < 0) {
|
||||
page_size = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void *sc_mem_secure_alloc(size_t len)
|
||||
{
|
||||
void *p;
|
||||
|
||||
init_page_size();
|
||||
if (page_size > 0) {
|
||||
size_t pages = (len + page_size - 1) / page_size;
|
||||
len = pages * page_size;
|
||||
}
|
||||
|
||||
p = malloc(len);
|
||||
#ifdef _WIN32
|
||||
VirtualLock(p, len);
|
||||
#else
|
||||
mlock(p, len);
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void sc_mem_secure_free(void *ptr, size_t len)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
VirtualUnlock(ptr, len);
|
||||
#else
|
||||
munlock(ptr, len);
|
||||
#endif
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void sc_mem_clear(void *ptr, size_t len)
|
||||
{
|
||||
if (len > 0) {
|
||||
|
|
|
@ -187,7 +187,7 @@ CK_RV push_login_state(struct sc_pkcs11_slot *slot,
|
|||
}
|
||||
|
||||
if (pPin && ulPinLen) {
|
||||
login->pPin = calloc((sizeof *pPin), ulPinLen);
|
||||
login->pPin = sc_mem_secure_alloc((sizeof *pPin)*ulPinLen);
|
||||
if (login->pPin == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ err:
|
|||
if (login) {
|
||||
if (login->pPin) {
|
||||
sc_mem_clear(login->pPin, login->ulPinLen);
|
||||
free(login->pPin);
|
||||
sc_mem_secure_free(login->pPin, login->ulPinLen);
|
||||
}
|
||||
free(login);
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ void pop_login_state(struct sc_pkcs11_slot *slot)
|
|||
struct sc_pkcs11_login *login = list_get_at(&slot->logins, size-1);
|
||||
if (login) {
|
||||
sc_mem_clear(login->pPin, login->ulPinLen);
|
||||
free(login->pPin);
|
||||
sc_mem_secure_free(login->pPin, login->ulPinLen);
|
||||
free(login);
|
||||
}
|
||||
if (0 > list_delete_at(&slot->logins, size-1))
|
||||
|
@ -238,7 +238,7 @@ void pop_all_login_states(struct sc_pkcs11_slot *slot)
|
|||
struct sc_pkcs11_login *login = list_fetch(&slot->logins);
|
||||
while (login) {
|
||||
sc_mem_clear(login->pPin, login->ulPinLen);
|
||||
free(login->pPin);
|
||||
sc_mem_secure_free(login->pPin, login->ulPinLen);
|
||||
free(login);
|
||||
login = list_fetch(&slot->logins);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue