Proposal: Remove bundled libaes_siv, use OpenSSL native AES-SIV

Hal Murray halmurray at sonic.net
Sun Jun 28 06:24:19 UTC 2026


> Your memory that libaes_siv "works with FIPS" is backwards. The
> deprecated CMAC_CTX APIs bypass the provider layer entirely, which means
> they bypass FIPS enforcement. That's a compliance problem, not a feature.

Another example of how interesting words are, especially the little ones. 
:)

What I meant by "works" is that the code didn't work.  I have a Fedora 
system that's running in FIPS mode.  On that box, attic/aead-timing.c does 
the following:

#     cKL=cookieKeyLen, wKL=wireKeyLen, CL=cookieLen
#            cKL wKL  CL  ns/op sec/run  Cookie Alg
LIB Encrypt   32  32 104   2425   2.425  AES_SIV_CMAC_256
LIB Decrypt   32  32 104   2461   2.461
CookieEncryptSSL: Can't find cipher AES-128-SIV.

-------

Your patch doesn't build on my system.

../../libntp/aes_siv_evp.c: In function \u2018AES_SIV_Decrypt\u2019:
../../libntp/aes_siv_evp.c:251:46: error: cast discards \u2018const\u2019 
qualifier from pointer target type [-Werror=cast-qual]
  251 |                                 SIV_TAG_LEN, (void *)tag_in) != 1) 
{
      |                                              ^
cc1: all warnings being treated as errors

-------

You are inserting a wrapper that implements the old API.  One of the 
reasons to switch to the OpenSSL code is that they support a few 
algorithms that use shorter keys which means shorter packets and that 
might be interesting.

The old API doesn't have an explicit parameter to tell it which algorithm 
to use.  It deduces that from the length of the key.  That doesn't work if 
we also want to use the new algorithms -- some of them have the same key 
lengths as the 3 existing modes.

If OpenSSL has an API where one-call does everything, we should switch to 
that.

        /* Reset context for new operation */
        EVP_CIPHER_CTX_reset(ctx->cipher_ctx);

I don't think you need that.  Their documentation has never been clear 
about xxx_reset.  I think it just releases memory and whatever.  I got rid 
of all of the similar calls that I could find.  No problems.  XXX_init 
does everything needed to get to the right state.

-------

> The EVP dispatch overhead is a few function pointer indirections per
> operation. Nanoseconds. NTS cookie operations happen once per key
> exchange, not per packet. The actual NTP packet processing doesn't touch
> AES-SIV at all. Even on a server handling thousands of NTS-KE sessions
> per second, the difference would be unmeasurable noise.

I hang out with performance geeks.  What should be simple like that often 
ends up being a lot more expensive that you would expect.

On the server side, there are 4 AEAD operations:
  decoding the client cookie
  checking the client request packet
  making the new cookie
  authenticating/encrypting the servers response packet

> Happy to run benchmarks if you want numbers, but I'm confident we're
> optimizing something that doesn't matter. 

It should be nanoseconds.  It's not.  It's close to a microsecond, and 
that's on an old but reasonably fast PC.  The catch is that the whole 
server side processing is small enough that a few microseconds here, a few 
microseconds there and pretty soon we're talking real cycles.

Poke around in attic.  There are a couple of interesting routines.  I 
think they all just handle cookie operations.  We should extend them to 
packets.  (I thought I saw one that had a typo, but I can't find it now.  
The column head said ns but it was printing out microseconds.

------

Should we add another statistics file?
  Suppose we collect 4 time stamps:
    just before the read()
    just after the read()
    just before the send()
    just after the send()
That gives us 3 chunks of time:  read, think, send
If we collect those and print the totals/averages every hour, we can 
collect some real data.

We need several sets.  One for no crypto.  One for shared keys.  One for 
NTS.

I'd like to be able to investigate the long tails.  I don't know how to do 
that without haveing a big pile of samples.  We could make a histogram for 
each bucket, and/or a configurable parameter to split each bucket into 
faster/slower than a parameter.

--------

Another slow area is gettng random numbers.  OpenSSL does a few syscalls 
to get the PID and such to scramble the randomness a bit.  But that's 
expensive if you are only getting 16 or 32 bytes for nonces or keys.  
(James put in a wrapper aroud our calls to random to code that gets big 
chunks and doles them out as needed.)

-- 
These are my opinions.  I hate spam.





More information about the devel mailing list