KDFs
KDFs copied to clipboard
Abstract Hkdf and HkdfExtract over hmac::Mac
I might be missing something about the rational behind the HmacImpl sealed trait (like some implicit invariant), but I'm wondering why Hkdf and HkdfExtract are not parametrized by hmac::Mac instead. This trait already provides OutputSizeUser.
This would be useful when someone has both a Digest and a Mac hardware implementation and would like to compute HKDF using that Mac hardware implementation instead of using the SimpleHmac software implementation on top of the Digest hardware implementation.
Sounds good to me. It would be nice to be able to support hardware accelerators.
Note that HKDF is defined in terms of HMAC. So I don't think it will be correct to use the Mac trait here. At the very least, we would need a trait for a MAC function which can be initialized with keys of any length. We also use the sealed trait to hide these unwieldy bounds, but it should be solved in future releases (see https://github.com/RustCrypto/MACs/issues/104). Right now we rely on block-level API in our implementation to reduce size of the Hkdf struct, to support slice-based hardware implementations we would need a bit of redesign.
AFAIK HMAC is usually supported in HSM-like hardware to protect keys from leaking, not for efficiency sake. Can you provide an example of hardware which you would like to target?
Good point, an HmacMarker would be needed to replace the sealed trait (similar to the existing HashMarker and MacMarker), or the sealed trait could be renamed and exposed.
I'm not following the block-level API comment. The code only seems to use slices. However something to note is that the current implementation optimizes by reusing the core. An implementation that doesn't permit this (hardware implementations usually don't) would just define the core to be the pseudo random key and not precompute anything.
I sadly cannot provide an example hardware. But yes this is not about performance.
(I'm currently on vacations for 3 weeks so might not be able to reply until then.)
AFAIK HMAC is usually supported in HSM-like hardware to protect keys from leaking, not for efficiency sake.
When I say "cryptographic accelerator" I mean TPM/SEP-like cryptographic coprocessor, and yes one of its main purposes of the kind I have in mind is to airgap and provide access control around keys including preventing exfiltration of the raw key material, but also such coprocessors include fixed functions of various cryptographic algorithms that run faster than the software equivalent on an MCU, so it's a little of both. I have one device that works this way with a baked-in device unique hardware key, however we did not wrap the HMAC functionality it provides, but instead we wrapped the device unique keyed AES functionality and use that to store the encryption of the base derivation key which we use to initialize HKDF, which works too.
But also, I maintain crates like yubikey and yubihsm which also provide hardware-backed HMAC, though these do not provide a trait-based API like we're discussing. FWIW here's an example of the current HMAC-based API:
https://docs.rs/yubihsm/latest/yubihsm/client/struct.Client.html#method.sign_hmac
It would need a sort of proxy type which knows the key ID a priori to implement a Mac-like API.
At the very least, we would need a trait for a MAC function which can be initialized with keys of any length.
Well it'd be really nice to completely decouple KeyInit and Mac so the latter can be used with ^^^ devices which don't accept a raw key at all, but rather a "handle" to a key stored in hardware.
@ia0
I'm not following the block-level API comment.
See how the Hkdf struct is defined. It uses I::Core, which does have any internal buffers. In the case of hardware-based implementation we would need to use some kind of handle there.
@tarcieri
FWIW here's an example of the current HMAC-based API:
Note that for HKDF we need an update-based API. If YubiHSM provides only whole message signing API, then a wrapper would need to assemble a full message on heap, which will be somewhat inefficient.
See how the
Hkdfstruct is defined. It usesI::Core, which does have any internal buffers.
It's probably simpler if I write a PR when I'm back in 3 weeks. There looks like there is a misunderstanding on what is being achieved here, since your comments don't seem to reply to what I say. Code is probably easier to understand.
Sorry for the very long delay, but I finally got time to get to this. I've created #82 to show an example of what I mean. Here are the main points:
- [library] Expose the sealed trait as
HmacImplremoving one hop (this is just for illustration, of course documentation and other things need to be addressed) - [test] I chose as example a hardware that can run a single HMAC instance which is what I have
- Note that the current HMAC (and hash) APIs don't support errors which is not great when implementing them with hardware. Hardware can always fail in particular when it has security protection and detects glitch attempts (changes in temperature or voltage for example). But I have an idea to work around this limitation: https://github.com/google/wasefire/issues/176