[PATCH] wipememory: use memset for non-constant length or large buffer wipes
Jussi Kivilinna
jussi.kivilinna at iki.fi
Sat Nov 3 13:48:31 CET 2018
* src/g10lib.h (CONSTANT_P): New.
(_gcry_wipememory2): New prototype.
(wipememory2): Use _gcry_wipememory2 if _len not constant expression or
lenght is larger than 64 bytes.
(FASTWIPE_T, FASTWIPE_MULT, fast_wipememory2_unaligned_head): Remove.
(fast_wipememory2): Always handle buffer as unaligned.
* src/misc.c (__gcry_burn_stack): Move memset_ptr variable to...
(memset_ptr): ... here. New.
(_gcry_wipememory2): New.
--
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
0 files changed
diff --git a/src/g10lib.h b/src/g10lib.h
index c64cbcf2a..9b2147812 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -76,11 +76,13 @@
#endif
#if __GNUC__ >= 3
-#define LIKELY( expr ) __builtin_expect( !!(expr), 1 )
-#define UNLIKELY( expr ) __builtin_expect( !!(expr), 0 )
+#define LIKELY(expr) __builtin_expect( !!(expr), 1 )
+#define UNLIKELY(expr) __builtin_expect( !!(expr), 0 )
+#define CONSTANT_P(expr) __builtin_constant_p( expr )
#else
-#define LIKELY( expr ) (!!(expr))
-#define UNLIKELY( expr ) (!!(expr))
+#define LIKELY(expr) (!!(expr))
+#define UNLIKELY(expr) (!!(expr))
+#define CONSTANT_P(expr) (0)
#endif
/* Gettext macros. */
@@ -334,60 +336,50 @@ void __gcry_burn_stack (unsigned int bytes);
/* To avoid that a compiler optimizes certain memset calls away, these
- macros may be used instead. */
+ macros may be used instead. For small constant length buffers,
+ memory wiping is inlined. For non-constant or large length buffers,
+ memory is wiped with memset through _gcry_wipememory. */
+void _gcry_wipememory2(void *ptr, int set, size_t len);
#define wipememory2(_ptr,_set,_len) do { \
- volatile char *_vptr=(volatile char *)(_ptr); \
- size_t _vlen=(_len); \
- unsigned char _vset=(_set); \
- fast_wipememory2(_vptr,_vset,_vlen); \
- while(_vlen) { *_vptr=(_vset); _vptr++; _vlen--; } \
- } while(0)
+ if (!CONSTANT_P(_len) || _len > 64) { \
+ _gcry_wipememory2((void *)_ptr, _set, _len); \
+ } else {\
+ volatile char *_vptr = (volatile char *)(_ptr); \
+ size_t _vlen = (_len); \
+ const unsigned char _vset = (_set); \
+ fast_wipememory2(_vptr, _vset, _vlen); \
+ while(_vlen) { *_vptr = (_vset); _vptr++; _vlen--; } \
+ } \
+ } while(0)
#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
-#define FASTWIPE_T u64
-#define FASTWIPE_MULT (U64_C(0x0101010101010101))
-
-/* Following architectures can handle unaligned accesses fast. */
#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
- defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS) && \
- (defined(__i386__) || defined(__x86_64__) || \
- defined(__powerpc__) || defined(__powerpc64__) || \
- (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \
- defined(__aarch64__))
-#define fast_wipememory2_unaligned_head(_ptr,_set,_len) /*do nothing*/
+ defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS)
typedef struct fast_wipememory_s
{
- FASTWIPE_T a;
+ u64 a;
} __attribute__((packed, aligned(1), may_alias)) fast_wipememory_t;
+/* fast_wipememory may leave tail bytes unhandled, in which case tail bytes
+ are handled by wipememory. */
+# define fast_wipememory2(_vptr,_vset,_vlen) do { \
+ fast_wipememory_t _vset_long; \
+ if (_vlen < sizeof(fast_wipememory_t)) \
+ break; \
+ _vset_long.a = (_vset); \
+ _vset_long.a *= U64_C(0x0101010101010101); \
+ do { \
+ volatile fast_wipememory_t *_vptr_long = \
+ (volatile void *)_vptr; \
+ _vptr_long->a = _vset_long.a; \
+ _vlen -= sizeof(fast_wipememory_t); \
+ _vptr += sizeof(fast_wipememory_t); \
+ } while (_vlen >= sizeof(fast_wipememory_t)); \
+ } while (0)
#else
-#define fast_wipememory2_unaligned_head(_vptr,_vset,_vlen) do { \
- while(UNLIKELY((size_t)(_vptr)&(sizeof(FASTWIPE_T)-1)) && _vlen) \
- { *_vptr=(_vset); _vptr++; _vlen--; } \
- } while(0)
-typedef struct fast_wipememory_s
-{
- FASTWIPE_T a;
-} fast_wipememory_t;
+# define fast_wipememory2(_vptr,_vset,_vlen)
#endif
-/* fast_wipememory2 may leave tail bytes unhandled, in which case tail bytes
- are handled by wipememory2. */
-#define fast_wipememory2(_vptr,_vset,_vlen) do { \
- FASTWIPE_T _vset_long = _vset; \
- fast_wipememory2_unaligned_head(_vptr,_vset,_vlen); \
- if (_vlen < sizeof(FASTWIPE_T)) \
- break; \
- _vset_long *= FASTWIPE_MULT; \
- do { \
- volatile fast_wipememory_t *_vptr_long = \
- (volatile void *)_vptr; \
- _vptr_long->a = _vset_long; \
- _vlen -= sizeof(FASTWIPE_T); \
- _vptr += sizeof(FASTWIPE_T); \
- } while (_vlen >= sizeof(FASTWIPE_T)); \
- } while (0)
-
/* Digit predicates. */
diff --git a/src/misc.c b/src/misc.c
index 47d2dc712..420ce74db 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -32,6 +32,8 @@
static int verbosity_level = 0;
+static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
+
static void (*fatal_error_handler)(void*,int, const char*) = NULL;
static void *fatal_error_handler_value = 0;
static void (*log_handler)(void*,int, const char*, va_list) = NULL;
@@ -497,23 +499,29 @@ _gcry_strtokenize (const char *string, const char *delim)
}
+void
+_gcry_wipememory2 (void *ptr, int set, size_t len)
+{
+ memset_ptr (ptr, set, len);
+}
+
+
void
__gcry_burn_stack (unsigned int bytes)
{
#ifdef HAVE_VLA
- static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
- /* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
- unsigned int buflen = ((!bytes + bytes) + 63) & ~63;
- char buf[buflen];
+ /* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
+ unsigned int buflen = ((!bytes + bytes) + 63) & ~63;
+ char buf[buflen];
- memset_ptr (buf, 0, sizeof buf);
+ memset_ptr (buf, 0, buflen);
#else
- volatile char buf[64];
+ volatile char buf[64];
- wipememory (buf, sizeof buf);
+ wipememory (buf, sizeof buf);
- if (bytes > sizeof buf)
- _gcry_burn_stack (bytes - sizeof buf);
+ if (bytes > sizeof buf)
+ _gcry_burn_stack (bytes - sizeof buf);
#endif
}
More information about the Gcrypt-devel
mailing list