From 55bf620365422446f2a2ffd1dd04d1492be95149 Mon Sep 17 00:00:00 2001 From: Baojun Wang Date: Wed, 31 May 2017 19:33:48 -0700 Subject: [PATCH] add aes ccm support --- Crypto/Cipher/AES.hs | 1 + Crypto/Cipher/AES/Primitive.hs | 116 ++++++++++++++++++ Crypto/Cipher/Types.hs | 2 + Crypto/Cipher/Types/Base.hs | 7 +- cbits/cryptonite_aes.c | 212 +++++++++++++++++++++++++++++++++ cbits/cryptonite_aes.h | 19 +++ 6 files changed, 356 insertions(+), 1 deletion(-) diff --git a/Crypto/Cipher/AES.hs b/Crypto/Cipher/AES.hs index 9b5cecf..5ce10c4 100644 --- a/Crypto/Cipher/AES.hs +++ b/Crypto/Cipher/AES.hs @@ -59,6 +59,7 @@ instance BlockCipher CSTR where \ ; ctrCombine (CSTR aes) (IV iv) = encryptCTR aes (IV iv) \ ; aeadInit AEAD_GCM (CSTR aes) iv = CryptoPassed $ AEAD (gcmMode aes) (gcmInit aes iv) \ ; aeadInit AEAD_OCB (CSTR aes) iv = CryptoPassed $ AEAD (ocbMode aes) (ocbInit aes iv) \ + ; aeadInit (AEAD_CCM n m l) (CSTR aes) iv = CryptoPassed $ AEAD (ccmMode aes) (ccmInit aes iv n m l) \ ; aeadInit _ _ _ = CryptoFailed CryptoError_AEADModeNotSupported \ }; \ instance BlockCipher128 CSTR where \ diff --git a/Crypto/Cipher/AES/Primitive.hs b/Crypto/Cipher/AES/Primitive.hs index 3536b6d..f139c17 100644 --- a/Crypto/Cipher/AES/Primitive.hs +++ b/Crypto/Cipher/AES/Primitive.hs @@ -44,6 +44,10 @@ module Crypto.Cipher.AES.Primitive -- * Incremental OCB , ocbMode , ocbInit + + -- * CCM + , ccmMode + , ccmInit ) where import Data.Word @@ -73,6 +77,7 @@ instance BlockCipher AES where ctrCombine = encryptCTR aeadInit AEAD_GCM aes iv = CryptoPassed $ AEAD (gcmMode aes) (gcmInit aes iv) aeadInit AEAD_OCB aes iv = CryptoPassed $ AEAD (ocbMode aes) (ocbInit aes iv) + aeadInit (AEAD_CCM n m l) aes iv = CryptoPassed $ AEAD (ccmMode aes) (ccmInit aes iv n m l) aeadInit _ _ _ = CryptoFailed CryptoError_AEADModeNotSupported instance BlockCipher128 AES where xtsEncrypt = encryptXTS @@ -96,6 +101,14 @@ ocbMode aes = AEADModeImpl , aeadImplFinalize = ocbFinish aes } +-- | Create an AES AEAD implementation for GCM +ccmMode :: AES -> AEADModeImpl AESCCM +ccmMode aes = AEADModeImpl + { aeadImplAppendHeader = ccmAppendAAD + , aeadImplEncrypt = ccmEncrypt aes + , aeadImplDecrypt = ccmDecrypt aes + , aeadImplFinalize = ccmFinish aes + } -- | AES Context (pre-processed key) newtype AES = AES ScrubbedBytes @@ -109,12 +122,19 @@ newtype AESGCM = AESGCM ScrubbedBytes newtype AESOCB = AESOCB ScrubbedBytes deriving (NFData) +-- | AESCCM State +newtype AESCCM = AESCCM ScrubbedBytes + deriving (NFData) + sizeGCM :: Int sizeGCM = 80 sizeOCB :: Int sizeOCB = 160 +sizeCCM :: Int +sizeCCM = 544 + keyToPtr :: AES -> (Ptr AES -> IO a) -> IO a keyToPtr (AES b) f = withByteArray b (f . castPtr) @@ -152,6 +172,16 @@ withOCBKeyAndCopySt aes (AESOCB gcmSt) f = a <- withByteArray newSt $ \gcmStPtr -> f (castPtr gcmStPtr) aesPtr return (a, AESOCB newSt) +withCCMKeyAndCopySt :: AES -> AESCCM -> (Ptr AESCCM -> Ptr AES -> IO a) -> IO (a, AESCCM) +withCCMKeyAndCopySt aes (AESCCM ccmSt) f = + keyToPtr aes $ \aesPtr -> do + newSt <- B.copy ccmSt (\_ -> return ()) + a <- withByteArray newSt $ \ccmStPtr -> f (castPtr ccmStPtr) aesPtr + return (a, AESCCM newSt) + +withNewCCMSt :: AESCCM -> (Ptr AESCCM -> IO ()) -> IO AESCCM +withNewCCMSt (AESCCM ccmSt) f = B.copy ccmSt (f . castPtr) >>= \sm2 -> return (AESCCM sm2) + -- | Initialize a new context with a key -- -- Key needs to be of length 16, 24 or 32 bytes. Any other values will return failure @@ -447,6 +477,78 @@ ocbFinish ctx ocb taglen = AuthTag $ B.take taglen computeTag where computeTag = B.allocAndFreeze 16 $ \t -> withOCBKeyAndCopySt ctx ocb (c_aes_ocb_finish (castPtr t)) >> return () +ccmGetM :: CCM_M -> Int +ccmGetL :: CCM_L -> Int +ccmGetM m = case m of + CCM_M4 -> 4 + CCM_M6 -> 6 + CCM_M8 -> 8 + CCM_M10 -> 10 + CCM_M12 -> 12 + CCM_M14 -> 14 + CCM_M16 -> 16 + +ccmGetL l = case l of + CCM_L2 -> 2 + CCM_L3 -> 3 + CCM_L4 -> 4 + +-- | initialize a ccm context +{-# NOINLINE ccmInit #-} +ccmInit :: ByteArrayAccess iv => AES -> iv -> Int -> CCM_M -> CCM_L -> AESCCM +ccmInit ctx iv n m l = unsafeDoIO $ do + sm <- B.alloc sizeCCM $ \ccmStPtr -> + withKeyAndIV ctx iv $ \k v -> + c_aes_ccm_init (castPtr ccmStPtr) k v (fromIntegral $ B.length iv) (fromIntegral n) (fromIntegral (ccmGetM m)) (fromIntegral (ccmGetL l)) + return $ AESCCM sm + +-- | append data which is only going to be authenticated to the CCM context. +-- +-- needs to happen after initialization and before appending encryption/decryption data. +{-# NOINLINE ccmAppendAAD #-} +ccmAppendAAD :: ByteArrayAccess aad => AESCCM -> aad -> AESCCM +ccmAppendAAD ccmSt input = unsafeDoIO doAppend + where doAppend = + withNewCCMSt ccmSt $ \ccmStPtr -> + withByteArray input $ \i -> + c_aes_ccm_aad ccmStPtr i (fromIntegral $ B.length input) + +doCTR :: (ByteArray ba, BlockCipher cipher) => cipher -> ba -> ba -> ba +doCTR ctx iv0 input = ctrCombine ctx (ivAdd (IV (B.convert iv0 :: B.Bytes)) 1) input + +-- | append data to encrypt and append to the CCM context +-- +-- the bytearray needs to be a multiple of AES block size, unless it's the last call to this function. +-- needs to happen after AAD appending, or after initialization if no AAD data. +{-# NOINLINE ccmEncrypt #-} +ccmEncrypt :: ByteArray ba => AES -> AESCCM -> ba -> (ba, AESCCM) +ccmEncrypt ctx ccm input = unsafeDoIO $ (withCCMKeyAndCopySt ctx ccm cbcmacAndIv >>= \(iv0, cc) -> return (doCTR ctx iv0 input, cc)) + where len = B.length input + cbcmacAndIv ccmStPtr aesPtr = + B.alloc 16 $ \o -> + withByteArray input $ \i -> + c_aes_ccm_encrypt (castPtr o) ccmStPtr aesPtr i (fromIntegral len) + +-- | append data to decrypt and append to the CCM context +-- +-- the bytearray needs to be a multiple of AES block size, unless it's the last call to this function. +-- needs to happen after AAD appending, or after initialization if no AAD data. +{-# NOINLINE ccmDecrypt #-} +ccmDecrypt :: ByteArray ba => AES -> AESCCM -> ba -> (ba, AESCCM) +ccmDecrypt ctx ccm input = unsafeDoIO $ withCCMKeyAndCopySt ctx ccm doDec + where len = B.length input + doDec ccmStPtr aesPtr = + B.alloc len $ \o -> + withByteArray input $ \i -> + c_aes_ccm_decrypt (castPtr o) ccmStPtr aesPtr i (fromIntegral len) + +-- | Generate the Tag from CCM context +{-# NOINLINE ccmFinish #-} +ccmFinish :: AES -> AESCCM -> Int -> AuthTag +ccmFinish ctx ccm taglen = AuthTag $ B.take taglen computeTag + where computeTag = B.allocAndFreeze 16 $ \t -> + withCCMKeyAndCopySt ctx ccm (c_aes_ccm_finish (castPtr t)) >> return () + ------------------------------------------------------------------------ foreign import ccall "cryptonite_aes.h cryptonite_aes_initkey" c_aes_init :: Ptr AES -> CString -> CUInt -> IO () @@ -508,3 +610,17 @@ foreign import ccall "cryptonite_aes.h cryptonite_aes_ocb_decrypt" foreign import ccall "cryptonite_aes.h cryptonite_aes_ocb_finish" c_aes_ocb_finish :: CString -> Ptr AESOCB -> Ptr AES -> IO () +foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_init" + c_aes_ccm_init :: Ptr AESCCM -> Ptr AES -> Ptr Word8 -> CUInt -> CULong -> CInt -> CInt -> IO () + +foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_aad" + c_aes_ccm_aad :: Ptr AESCCM -> CString -> CUInt -> IO () + +foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_encrypt" + c_aes_ccm_encrypt :: CString -> Ptr AESCCM -> Ptr AES -> CString -> CUInt -> IO () + +foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_decrypt" + c_aes_ccm_decrypt :: CString -> Ptr AESCCM -> Ptr AES -> CString -> CUInt -> IO () + +foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_finish" + c_aes_ccm_finish :: CString -> Ptr AESCCM -> Ptr AES -> IO () diff --git a/Crypto/Cipher/Types.hs b/Crypto/Cipher/Types.hs index 8ab88c0..ab5dd37 100644 --- a/Crypto/Cipher/Types.hs +++ b/Crypto/Cipher/Types.hs @@ -21,6 +21,8 @@ module Crypto.Cipher.Types -- , cfb8Decrypt -- * AEAD functions , AEADMode(..) + , CCM_M(..) + , CCM_L(..) , module Crypto.Cipher.Types.AEAD -- * Initial Vector type and constructor , IV diff --git a/Crypto/Cipher/Types/Base.hs b/Crypto/Cipher/Types/Base.hs index e2c1652..03a20f8 100644 --- a/Crypto/Cipher/Types/Base.hs +++ b/Crypto/Cipher/Types/Base.hs @@ -14,6 +14,8 @@ module Crypto.Cipher.Types.Base , Cipher(..) , AuthTag(..) , AEADMode(..) + , CCM_M(..) + , CCM_L(..) , DataUnitOffset ) where @@ -39,10 +41,13 @@ newtype AuthTag = AuthTag { unAuthTag :: Bytes } instance Eq AuthTag where (AuthTag a) == (AuthTag b) = B.constEq a b +data CCM_M = CCM_M4 | CCM_M6 | CCM_M8 | CCM_M10 | CCM_M12 | CCM_M14 | CCM_M16 deriving (Show, Eq) +data CCM_L = CCM_L2 | CCM_L3 | CCM_L4 deriving (Show, Eq) + -- | AEAD Mode data AEADMode = AEAD_OCB -- OCB3 - | AEAD_CCM + | AEAD_CCM Int CCM_M CCM_L | AEAD_EAX | AEAD_CWC | AEAD_GCM diff --git a/cbits/cryptonite_aes.c b/cbits/cryptonite_aes.c index a6be9c5..df6186d 100644 --- a/cbits/cryptonite_aes.c +++ b/cbits/cryptonite_aes.c @@ -52,6 +52,8 @@ void cryptonite_aes_generic_gcm_encrypt(uint8_t *output, aes_gcm *gcm, aes_key * void cryptonite_aes_generic_gcm_decrypt(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length); void cryptonite_aes_generic_ocb_encrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length); void cryptonite_aes_generic_ocb_decrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length); +void cryptonite_aes_generic_ccm_encrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length); +void cryptonite_aes_generic_ccm_decrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length); enum { /* init */ @@ -76,6 +78,9 @@ enum { /* ocb */ ENCRYPT_OCB_128, ENCRYPT_OCB_192, ENCRYPT_OCB_256, DECRYPT_OCB_128, DECRYPT_OCB_192, DECRYPT_OCB_256, + /* ccm */ + ENCRYPT_CCM_128, ENCRYPT_CCM_192, ENCRYPT_CCM_256, + DECRYPT_CCM_128, DECRYPT_CCM_192, DECRYPT_CCM_256, }; void *cryptonite_aes_branch_table[] = { @@ -129,6 +134,13 @@ void *cryptonite_aes_branch_table[] = { [DECRYPT_OCB_128] = cryptonite_aes_generic_ocb_decrypt, [DECRYPT_OCB_192] = cryptonite_aes_generic_ocb_decrypt, [DECRYPT_OCB_256] = cryptonite_aes_generic_ocb_decrypt, + /* CCM */ + [ENCRYPT_CCM_128] = cryptonite_aes_generic_ccm_encrypt, + [ENCRYPT_CCM_192] = cryptonite_aes_generic_ccm_encrypt, + [ENCRYPT_CCM_256] = cryptonite_aes_generic_ccm_encrypt, + [DECRYPT_CCM_128] = cryptonite_aes_generic_ccm_decrypt, + [DECRYPT_CCM_192] = cryptonite_aes_generic_ccm_decrypt, + [DECRYPT_CCM_256] = cryptonite_aes_generic_ccm_decrypt, }; typedef void (*init_f)(aes_key *, uint8_t *, uint8_t); @@ -138,6 +150,7 @@ typedef void (*ctr_f)(uint8_t *output, aes_key *key, aes_block *iv, uint8_t *inp typedef void (*xts_f)(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks); typedef void (*gcm_crypt_f)(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length); typedef void (*ocb_crypt_f)(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length); +typedef void (*ccm_crypt_f)(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length); typedef void (*block_f)(aes_block *output, aes_key *key, aes_block *input); #ifdef WITH_AESNI @@ -165,6 +178,10 @@ typedef void (*block_f)(aes_block *output, aes_key *key, aes_block *input); ((ocb_crypt_f) (cryptonite_aes_branch_table[ENCRYPT_OCB_128 + strength])) #define GET_OCB_DECRYPT(strength) \ ((ocb_crypt_f) (cryptonite_aes_branch_table[DECRYPT_OCB_128 + strength])) +#define GET_CCM_ENCRYPT(strength) \ + ((ccm_crypt_f) (cryptonite_aes_branch_table[ENCRYPT_CCM_128 + strength])) +#define GET_CCM_DECRYPT(strength) \ + ((ccm_crypt_f) (cryptonite_aes_branch_table[DECRYPT_CCM_128 + strength])) #define cryptonite_aes_encrypt_block(o,k,i) \ (((block_f) (cryptonite_aes_branch_table[ENCRYPT_BLOCK_128 + k->strength]))(o,k,i)) #define cryptonite_aes_decrypt_block(o,k,i) \ @@ -182,6 +199,8 @@ typedef void (*block_f)(aes_block *output, aes_key *key, aes_block *input); #define GET_GCM_DECRYPT(strength) cryptonite_aes_generic_gcm_decrypt #define GET_OCB_ENCRYPT(strength) cryptonite_aes_generic_ocb_encrypt #define GET_OCB_DECRYPT(strength) cryptonite_aes_generic_ocb_decrypt +#define GET_CCM_ENCRYPT(strength) cryptonite_aes_generic_ccm_encrypt +#define GET_CCM_DECRYPT(strength) cryptonite_aes_generic_ccm_decrypt #define cryptonite_aes_encrypt_block(o,k,i) cryptonite_aes_generic_encrypt_block(o,k,i) #define cryptonite_aes_decrypt_block(o,k,i) cryptonite_aes_generic_decrypt_block(o,k,i) #endif @@ -321,6 +340,18 @@ void cryptonite_aes_gcm_decrypt(uint8_t *output, aes_gcm *gcm, aes_key *key, uin d(output, gcm, key, input, length); } +void cryptonite_aes_ccm_encrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length) +{ + ccm_crypt_f e = GET_CCM_ENCRYPT(key->strength); + e(output, ccm, key, input, length); +} + +void cryptonite_aes_ccm_decrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length) +{ + ccm_crypt_f d = GET_CCM_DECRYPT(key->strength); + d(output, ccm, key, input, length); +} + void cryptonite_aes_ocb_encrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length) { ocb_crypt_f e = GET_OCB_ENCRYPT(key->strength); @@ -406,6 +437,156 @@ void cryptonite_aes_gcm_finish(uint8_t *tag, aes_gcm *gcm, aes_key *key) } } +static inline int ccm_b0_flags(int has_adata, int m, int l) +{ + return 8*m + l + (has_adata? 64: 0); +} + +/* depends on input size */ +static void ccm_encode_b0(block128* output, aes_ccm* ccm, int has_adata) +{ + int last = 15; + int m = ccm->length_M; + int l = ccm->length_L; + uint64_t msg_len = ccm->length_input; + + block128_zero(output); + block128_copy(output, &ccm->nonce); + output->b[0] = ccm_b0_flags(has_adata, (m-2)/2, l-1); + while (msg_len > 0) { + output->b[last--] = msg_len & 0xff; + msg_len >>= 8; + } +} + +/* encode adata length */ +static int ccm_encode_la(block128* output, uint64_t la) +{ + if (la < ( (1 << 16) - (1 << 8)) ) { + output->b[0] = (la >> 8) & 0xff; + output->b[1] = la & 0xff; + return 2; + } else if (la < (1ull << 32)) { + output->b[0] = 0xff; + output->b[1] = 0xfe; + output->b[2] = (la >> 24) & 0xff; + output->b[3] = (la >> 16) & 0xff; + output->b[4] = (la >> 8) & 0xff; + output->b[5] = la & 0xff; + return 6; + } else { + output->b[0] = 0xff; + output->b[1] = 0xff; + output->b[2] = (la >> 56) & 0xff; + output->b[3] = (la >> 48) & 0xff; + output->b[4] = (la >> 40) & 0xff; + output->b[5] = (la >> 32) & 0xff; + output->b[6] = (la >> 24) & 0xff; + output->b[7] = (la >> 16) & 0xff; + output->b[8] = (la >> 8) & 0xff; + output->b[9] = la & 0xff; + return 10; + } +} + +static void ccm_encode_ctr(block128* out, aes_ccm* ccm, unsigned int cnt) +{ + int last = 15; + block128_copy(out, &ccm->nonce); + out->b[0] = ccm->length_L - 1; + + while (cnt > 0) { + out->b[last--] = cnt & 0xff; + cnt >>= 8; + } +} + +static void ccm_cbcmac_add(aes_ccm* ccm, aes_key* key, block128* bi) +{ + block128_xor(&ccm->xi, bi); + cryptonite_aes_generic_encrypt_block(&ccm->xi, key, &ccm->xi); +} + +/* even though it is possible to support message size as large as 2^64, we support up to 2^32 only */ +void cryptonite_aes_ccm_init(aes_ccm *ccm, aes_key *key, uint8_t *nonce, uint32_t nonce_len, uint64_t input_size, int m, int l) +{ + memset(ccm, 0, sizeof(aes_ccm)); + + if (l < 2 || l > 4) return; + if (m != 4 && m != 6 && m != 8 && m != 10 + && m != 12 && m != 14 && m != 16) return; + + if (nonce_len != 15 - l) { + nonce_len = 15 - l; + } + + if (l <= 4) { + if (input_size >= (1ull << (8*l))) return; + } + + ccm->length_L = l; + ccm->length_M = m; + ccm->length_input = input_size; + + memcpy(&ccm->nonce.b[1], nonce, 15 - l); + memcpy(&ccm->aad_key, key, sizeof(aes_key)); + + ccm_encode_b0(&ccm->b0, ccm, 1); /* assume aad is present */ + ccm_encode_ctr(&ccm->iv, ccm, 0); + + cryptonite_aes_encrypt_block(&ccm->xi, key, &ccm->b0); +} + +/* even though l(a) can be as large as 2^64, we only handle aad up to 2 ^ 32 for practical reasons. + Also we don't support incremental aad add, because the 1st encoded adata has length information + */ +void cryptonite_aes_ccm_aad(aes_ccm *ccm, uint8_t *input, uint32_t length) +{ + block128 tmp; + aes_key* key = &ccm->aad_key; + + ccm->length_aad = length; + int len_len; + + block128_zero(&tmp); + len_len = ccm_encode_la(&tmp, length); + + if (length < 16 - len_len) { + memcpy(&tmp.b[len_len], input, length); + length = 0; + } else { + memcpy(&tmp.b[len_len], input, 16 - len_len); + input += 16 - len_len; + length -= 16 - len_len; + } + + ccm_cbcmac_add(ccm, key, &tmp); + + for (; length >= 16; input += 16, length -= 16) { + block128_copy(&tmp, (block128*)input); + ccm_cbcmac_add(ccm, key, &tmp); + + } + if (length > 0) { + block128_zero(&tmp); + block128_copy_bytes(&tmp, input, length); + ccm_cbcmac_add(ccm, key, &tmp); + } + + memset(&ccm->aad_key, 0, sizeof(aes_key)); +} + +void cryptonite_aes_ccm_finish(uint8_t *tag, aes_ccm *ccm, aes_key *key) +{ + block128 iv, s0; + block128 u; + + ccm_encode_ctr(&iv, ccm, 0); + cryptonite_aes_encrypt_block(&s0, key, &iv); + block128_vxor(&u, &ccm->xi, &s0); + memcpy(tag, u.b, ccm->length_M); +} + static inline void ocb_block_double(block128 *d, block128 *s) { unsigned int i; @@ -739,6 +920,37 @@ static void ocb_generic_crypt(uint8_t *output, aes_ocb *ocb, aes_key *key, } } +void cryptonite_aes_generic_ccm_encrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length) +{ + block128 tmp; + + /* when aad is absent, reset b0 block */ + if (ccm->length_aad == 0) { + ccm_encode_b0(&ccm->b0, ccm, 0); /* assume aad is present */ + cryptonite_aes_encrypt_block(&ccm->xi, key, &ccm->b0); + } + + if (length != ccm->length_input) { + return; + } + + for (;length >= 16; input += 16, length -= 16) { + block128_copy(&tmp, (block128*)input); + ccm_cbcmac_add(ccm, key, &tmp); + } + if (length > 0) { + block128_zero(&tmp); + block128_copy_bytes(&tmp, input, length); + ccm_cbcmac_add(ccm, key, &tmp); + } + block128_copy((block128*)output, &ccm->iv); +} + +void cryptonite_aes_generic_ccm_decrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length) +{ + cryptonite_aes_generic_ccm_encrypt(output, ccm, key, input, length); +} + void cryptonite_aes_generic_ocb_encrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length) { ocb_generic_crypt(output, ocb, key, input, length, 1); diff --git a/cbits/cryptonite_aes.h b/cbits/cryptonite_aes.h index 733e0a3..70fbd47 100644 --- a/cbits/cryptonite_aes.h +++ b/cbits/cryptonite_aes.h @@ -55,6 +55,19 @@ typedef struct { uint64_t length_input; } aes_gcm; +/* size = 544 */ +typedef struct { + aes_block iv; /* iv with counter = 0 block */ + aes_block xi; /* X_i: cbc mac */ + aes_block b0; /* block b0 */ + aes_block nonce; + aes_key aad_key; + uint64_t length_aad; + uint64_t length_input; + int length_M; + int length_L; +} aes_ccm; + typedef struct { block128 offset_aad; block128 offset_enc; @@ -97,4 +110,10 @@ void cryptonite_aes_ocb_encrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uin void cryptonite_aes_ocb_decrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length); void cryptonite_aes_ocb_finish(uint8_t *tag, aes_ocb *ocb, aes_key *key); +void cryptonite_aes_ccm_init(aes_ccm *ccm, aes_key *key, uint8_t *nonce, uint32_t len, uint64_t msg_size, int m, int l); +void cryptonite_aes_ccm_aad(aes_ccm *ccm, uint8_t *input, uint32_t length); +void cryptonite_aes_ccm_encrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length); +void cryptonite_aes_ccm_decrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length); +void cryptonite_aes_ccm_finish(uint8_t *tag, aes_ccm *ccm, aes_key *key); + #endif