wipememory: use memset for non-constant length or large buffer wipes
authorJussi Kivilinna <jussi.kivilinna@iki.fi>
Mon, 5 Nov 2018 18:42:58 +0000 (20:42 +0200)
committerJussi Kivilinna <jussi.kivilinna@iki.fi>
Mon, 5 Nov 2018 18:42:58 +0000 (20:42 +0200)
* 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@iki.fi>
src/g10lib.h
src/misc.c

index c64cbcf..9b21478 100644 (file)
 #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.  */
 
index 47d2dc7..420ce74 100644 (file)
@@ -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;
@@ -498,22 +500,28 @@ _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
 }