On Dec 27, 2016, at 1:11 AM, Niels Möller nisse@lysator.liu.se wrote:
If you'd like to experiment, you could try writing a
umac32_digest_pure (const struct umac32_ctx *ctx, ...)
which doesn't modify the context, to see what it takes. Probably can't use the "padding cache" optimization, though.
I looked over the code today, and it turns out that it’s a fairly clean change. We can even keep the “padding cache” optimization. A key thing to realize is that it ok to modify parts of the context, as long as they don’t affect future calculations. In other words, it’s ok to write things like padding data to the input buffer which are “beyond the end”, since later calls update() will simply overwrite this padding as long as the “index” value is unchanged. Similarly, it’s ok to update the padding cache and set the flag for that, as long as the two low-order bits of the nonce_low value aren’t changed and the nonce is never incremented.
More specifically, the only parts of the context which need to be updated but which should not be modified in place are the l2_state[] array and the count value. If a local copy of these values is made on the stack and used in place of the values in the context, you get the right result. Other things like the index value and the nonce only need to be read and not updated, and the nonce increment and the final reset of the index and count can just be removed entirely.
Attached is a patch which implements new snapshot_digest() functions for all of umac32, umac64, umac96, and umac128. I tested these against a full range of input buffer sizes and incremental buffer additions to make sure I caught all the different edge cases and I feel pretty confident in the results. The resulting digest values were validated by calling the original unmodified digest function as a reference. I tested both the output of snapshot_digest() against digest() and then the result of calling update(), snapshot_digest(), update() again, and the original digest(), making sure I got the same results as I would have when calculating digest() on the combined data from both updates in a separate umac context.