Skip to content
This repository was archived by the owner on Mar 5, 2024. It is now read-only.

Commit 28b33ec

Browse files
committed
Abstraction for architecture dependent secure memset.
In ecc_dh.c it is widely used to zero out the memory used for holding sensitive information, such as private keys. This memory is cleared by a memset, but as this is done right at function return, this memset will most likely be optimized out by the compiler, as the memory will no longer be used, hence no need to set it. To prevent the memset from being optimized out, it is necessary to place a memory barrier at the memset, but such a barrier is compiler depended. To solve the above, a _set_secure function has been introduced. This defaults to an inlined function calling memset and, in cases where the compiler defines __GNUC__, adds a memory barrier which ensures that the memset is not optimized out. For compilers, not defining the __GNUC__, it may be necessary to define TINYCRYPT_ARCH_HAS_SET_SECURE which then declares the _set_secure function extern, thus meaning that it will require target implementation, which in turn allows for architecture/compiler dependent implementation. This also fixes the memset's in uECC_make_key and uECC_make_key_with_d which actually was missing the memory barrier. Fixes #32 Signed-off-by: Danny Oerndrup <[email protected]>
1 parent 6e0eb53 commit 28b33ec

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

lib/include/tinycrypt/utils.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
#include <stdint.h>
4343
#include <stddef.h>
44+
#include <string.h>
4445

4546
#ifdef __cplusplus
4647
extern "C" {
@@ -69,6 +70,31 @@ unsigned int _copy(uint8_t *to, unsigned int to_len,
6970
*/
7071
void _set(void *to, uint8_t val, unsigned int len);
7172

73+
/**
74+
* @brief Set the value 'val' into the buffer 'to', 'len' times, in a way
75+
* which does not risk getting optimized out by the compiler
76+
* In cases where the compiler does not set __GNUC__ and where the
77+
* optimization level removes the memset, it may be necessary to
78+
* implement a _set_secure function and define the
79+
* TINYCRYPT_ARCH_HAS_SET_SECURE, which then can ensure that the
80+
* memset does not get optimized out.
81+
*
82+
* @param to OUT -- destination buffer
83+
* @param val IN -- value to be set in 'to'
84+
* @param len IN -- number of times the value will be copied
85+
*/
86+
#ifdef TINYCRYPT_ARCH_HAS_SET_SECURE
87+
extern void _set_secure(void *to, uint8_t val, unsigned int len);
88+
#else /* ! TINYCRYPT_ARCH_HAS_SET_SECURE */
89+
static inline void _set_secure(void *to, uint8_t val, unsigned int len)
90+
{
91+
(void) memset(to, val, len);
92+
#ifdef __GNUC__
93+
__asm__ __volatile__("" :: "g"(to) : "memory");
94+
#endif /* __GNUC__ */
95+
}
96+
#endif /* TINYCRYPT_ARCH_HAS_SET_SECURE */
97+
7298
/*
7399
* @brief AES specific doubling function, which utilizes
74100
* the finite field used by AES.

lib/source/ecc_dh.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include <tinycrypt/constants.h>
5858
#include <tinycrypt/ecc.h>
5959
#include <tinycrypt/ecc_dh.h>
60+
#include <tinycrypt/utils.h>
6061
#include <string.h>
6162

6263
#if default_RNG_defined
@@ -92,7 +93,7 @@ int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
9293
_public + curve->num_words);
9394

9495
/* erasing temporary buffer used to store secret: */
95-
memset(_private, 0, NUM_ECC_BYTES);
96+
_set_secure(_private, 0, NUM_ECC_BYTES);
9697

9798
return 1;
9899
}
@@ -133,7 +134,7 @@ int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve)
133134
_public + curve->num_words);
134135

135136
/* erasing temporary buffer that stored secret: */
136-
memset(_private, 0, NUM_ECC_BYTES);
137+
_set_secure(_private, 0, NUM_ECC_BYTES);
137138

138139
return 1;
139140
}
@@ -189,12 +190,9 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
189190

190191
clear_and_out:
191192
/* erasing temporary buffer used to store secret: */
192-
memset(p2, 0, sizeof(p2));
193-
__asm__ __volatile__("" :: "g"(p2) : "memory");
194-
memset(tmp, 0, sizeof(tmp));
195-
__asm__ __volatile__("" :: "g"(tmp) : "memory");
196-
memset(_private, 0, sizeof(_private));
197-
__asm__ __volatile__("" :: "g"(_private) : "memory");
193+
_set_secure(p2, 0, sizeof(p2));
194+
_set_secure(tmp, 0, sizeof(tmp));
195+
_set_secure(_private, 0, sizeof(_private));
198196

199197
return r;
200198
}

0 commit comments

Comments
 (0)