Boost logo

Boost :

From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2024-07-10 15:26:20


On 7/10/24 14:59, Peter Dimov via Boost wrote:
> Ruben Perez wrote:
>> There is OPENSSL_Cleanse, which does a similar job. I found it surprisingly
>> simple - I wonder if this is just enough or there are any corner cases where this
>> doesn't work:
>> https://github.com/openssl/openssl/blob/b544047c99c4a7413f793afe82ab1c165f85b5b6/crypto/mem_clr.c#L22
>
> That's an interesting approach. I can't offhand think of a reason why it wouldn't
> work.

The compiler might convert OPENSSL_cleanse to something like this:

  void OPENSSL_cleanse(void *ptr, size_t len)
  {
    memset_t func = memset_func;
    if (func != memset)
      func(ptr, 0, len);
    else
      memset(ptr, 0, len);
  }

The purpose here is that, if memset_func is actually memset most of the
time, it can further optimize the call to memset, including to
completely remove it, depending on the call context. The
(well-predictable) branch is typically cheaper than an indirect call. I
think I've seen compilers do something along those lines as a result of
call devirtualization, especially with IPO and LTCG.

I'm not saying that's what actually happens in OpenSSL, just that
something like this is possible. I think, a dummy asm statement is more
reliable and more efficient.

  void secure_cleanse(void *ptr, size_t len)
  {
    memset(ptr, 0, len); // a normal memset, optimizations are welcome
    __asm__ __volatile__ ("" : : "r" (ptr), "r" (len) : "memory");
  }

You can even make that function inline and it'll work, and in an optimal
way, too.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk