briansmith / ring

Safe, fast, small crypto using Rust
Other
3.75k stars 704 forks source link

Add Cipher-based Message Authentication Code (CMAC) #293

Open a-dma opened 8 years ago

a-dma commented 8 years ago

Add an implementation of CMAC.

CMAC is a Cipher-Based MAC that improves some of the problems found in CBC-MAC. It was introduced by NIST in SP-800-38B as a mode of operation for approved symmetric block chipers, namely AES and TDEA.

The most common implementation (that I am aware of) is AES-CMAC, further defined in RFC 4493.

CMAC has similar use cases and security guarantees as HMAC, with the difference that it uses a different primitive (symmetric cipher instead of hash function). This makes it more convenient when the primitive has already been implemented for other purposes, e.g., encryption.

CMAC is public domain.

Other possibly relevant documents are:

briansmith commented 8 years ago

Which important standard protocols implement this, which you are implementing?

Which organizations or products, open-source or otherwise, would use this capability of ring, if it were added?

a-dma commented 8 years ago

Which important standard protocols implement this, which you are implementing?

AFAIK IPSec is using it, but more generally anywhere where CBC-MAC is in use this would be a suitable replacement.

Which organizations or products, open-source or otherwise, would use this capability of ring, if it were added?

I (Yubico) might be interested in doing some work with Rust and having a capable and maintained cryptographic library is vital. We would of course contribute back (at the very least) any work done on the library itself.

briansmith commented 8 years ago

I see that @a-dma already implemented AES-CMAC in Rust for rust-crypto at https://github.com/DaGenix/rust-crypto/pull/377.

It is already in BoringSSL (see https://boringssl.googlesource.com/boringssl/+/master/crypto/cmac/cmac.c) but was removed from ring in 7ac9cdfd3d5149591e82f2bb5ddd00dc32221ac9.

The new reference for the NIST spec is http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf.

To add it back to ring, I think we'd need to:

briansmith commented 8 years ago

Resurrect the binary_field_mul_x function in BoringSSL's crypto/cmac/cmac.c, renaming it GFp_cmac_binary_field_mul_x and making it non-static. (This is keeping with the current short-term strategy of keeping all secret-key-twiddling in C and/or assembly language in ring until we have a plan for constant-time coding in Rust.)

Actually, it would probably be better to just write a from-scratch implementation of the field binary multiplication function in C, instead of using the BoringSSL/OpenSSL implementation, for licensing reasons. In particular, if we were to write a from-scratch implementation then the license for the whole CMAC implementation would be the ISC-like license, which is highly desirable.

briansmith commented 8 years ago

We also need to ensure that we are restricting the maximum amount of data/blocks/whatever according to the maximums prescribed for CMAC. The code should include a link to the documentation of this maximum.

a-dma commented 8 years ago

Rename ring::hmac to ring::mac. Generalize the ring::mac interface so that it supports both HMAC and CMAC using the same API. This might involve, for example, adding a struct HMACAlgorithm { digest_alg: &'static digest::Algorithm } and then defining ring::mac::HMAC_SHA256, et al. Then we'd also add struct CMACAlgorithm and then add ring::mac::CMAC_AES_128 and ring::mac::CMAC_AES_256 of type &'static CMACAlgorithm. Or, maybe we can somehow abstract the differences between HMACAlgorithm and CMACAlgorithm into a single ring::mac::Algorithm.

I think this should be a separate issue. More HMAC algorithms could be added as well (HAMC-SHA384, HMAC-SHA512) while changing the abstraction layer.

briansmith commented 8 years ago

I think this should be a separate issue.

If you or somebody else contributes the initial work of creating a CMAC API that is similar to the HMAC API, I would accept that without the rest of the stuff being done. I'd be happy to do the work to unify the HMAC and CMAC APIs if people don't want to do that.

More HMAC algorithms could be added as well (HAMC-SHA384, HMAC-SHA512) while changing the abstraction layer.

HMAC-SHA384 and HMAC-SHA512 are already supported, right?

briansmith commented 8 years ago

@a-dma I have some questions to ask you privately about this. Could you please email me: brian@briansmith.org? Thanks!

flybayer commented 7 years ago

I would love to see this added. I'm writing LoRaWAN network code. Its protocol uses AES-CMAC to validate RF packet integrity.

briansmith commented 7 years ago

@flybayer Would you be interested in trying to make a PR for this? I would love to see it as well.

a-dma commented 7 years ago

@briansmith hey, I started looking at this in my spare time, but I ran into a few issues, and before I dig myself into a rabbit hole, I thought I'd ask you about which way you'd like this to be implemented. First off I'll start by looking at CMAC-AES. No TDEA, at least for now (that doesn't seems to be available anyway).

Next, I see a couple of way to do this: 1) Reintroduce the old cmac.c from BoringSSL as you suggested, but in that case we need to replace things like EVP_CIPHER_CTX and EVP_Cipher with something else. If you prefer this method I'd like some ideas on how to do that in a way that would be OK with you;

2) Define a "raw" AES Algorithm (similar to an aead::Algorithm) that calls into GFp_aes_set_key and GFp_aes_encrypt, and implement the actual CMAC logic in Rust.

Thanks

jpopesculian commented 5 years ago

@briansmith I'd like to bump this as Intel SGX also uses CMAC to verify Reports generated for attestation