[PATCH] Use memset for short constant length wipememory2

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] Use memset for short constant length wipememory2

Jussi Kivilinna-2
* src/g10lib.h (fast_wipememory2_inline): New.
(wipememory2): Use 'fast_wipememory2_inline', remove 'fast_wipememory2'
use; Use _gcry_fast_wipememory* only when _len is not constant.
(fast_wipememory_s, fast_wipememory2): Remove.
--

Use of memset allows better code generation by compiler -
for example, use of vector registers for memory clearing.

Signed-off-by: Jussi Kivilinna <[hidden email]>
---
 src/g10lib.h | 59 ++++++++++++++++------------------------------------
 1 file changed, 18 insertions(+), 41 deletions(-)

diff --git a/src/g10lib.h b/src/g10lib.h
index b0b73852..bc6e378f 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -359,56 +359,33 @@ void __gcry_burn_stack (unsigned int bytes);
      __gcry_burn_stack_dummy (); } while(0)
 
 /* To avoid that a compiler optimizes certain memset calls away, these
-   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_fast_wipememory. */
+   macros may be used instead.  For constant length buffers, memory
+   wiping is inlined.  For non-constant or large length buffers,
+   memory is wiped through _gcry_fast_wipememory. */
+#ifdef HAVE_GCC_ASM_VOLATILE_MEMORY
+#define fast_wipememory2_inline(_ptr,_set,_len) do { \
+      memset((_ptr), (_set), (_len)); \
+      asm volatile ("\n" :: "r" (_ptr) : "memory"); \
+    } while(0)
+#else
+#define fast_wipememory2_inline(_ptr,_set,_len) \
+    _gcry_fast_wipememory2((void *)_ptr, _set, _len)
+#endif
 #define wipememory2(_ptr,_set,_len) do { \
-      if (!CONSTANT_P(_len) || _len > 64) { \
+      if (!CONSTANT_P(_len)) { \
  if (CONSTANT_P(_set) && (_set) == 0) \
-  _gcry_fast_wipememory((void *)_ptr, _len); \
+  _gcry_fast_wipememory((void *)(_ptr), (_len)); \
  else \
-  _gcry_fast_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--; } \
+  _gcry_fast_wipememory2((void *)(_ptr), (_set), (_len)); \
+      } else { \
+ fast_wipememory2_inline((void *)(_ptr), (_set), (_len)); \
       } \
     } while(0)
-#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
+#define wipememory(_ptr,_len) wipememory2((_ptr),0,(_len))
 
 void _gcry_fast_wipememory(void *ptr, size_t len);
 void _gcry_fast_wipememory2(void *ptr, int set, size_t len);
 
-#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
-    defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
-    defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS)
-typedef struct fast_wipememory_s
-{
-  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(_vptr,_vset,_vlen)
-#endif
-
-
 /* Digit predicates.  */
 
 #define digitp(p)   (*(p) >= '0' && *(p) <= '9')
--
2.27.0


_______________________________________________
Gcrypt-devel mailing list
[hidden email]
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Use memset for short constant length wipememory2

GnuPG - Libgcrypt - Dev mailing list
Jussi Kivilinna wrote:
> Use of memset allows better code generation by compiler -
> for example, use of vector registers for memory clearing.
>  


Are you sure that this is a good idea?  The comment indicates that the
original purpose of not using memset was to ensure that a compiler
cannot optimize the call away.


-- Jacob

_______________________________________________
Gcrypt-devel mailing list
[hidden email]
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Use memset for short constant length wipememory2

Jussi Kivilinna-2
On 28.3.2021 5.05, Jacob Bachmeyer via Gcrypt-devel wrote:
> Jussi Kivilinna wrote:
>> Use of memset allows better code generation by compiler -
>> for example, use of vector registers for memory clearing.
>
>
> Are you sure that this is a good idea?  The comment indicates that the original purpose of not using memset was to ensure that a compiler cannot optimize the call away.
>

New approach uses inline assembly memory barrier to prevent optimizing away preceding memset:

     memset(ptr_memory_to_wipe, 0, memory_length);
     asm volatile ("\n"::"r"(ptr_memory_to_wipe):"memory");

I'll update the comment to better explain this.

-Jussi

_______________________________________________
Gcrypt-devel mailing list
[hidden email]
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel