diff --git a/Crypto/Cipher/AES.hs b/Crypto/Cipher/AES.hs index 9b5cecf..97a1801 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 = 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..8241013 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 = AEAD (ccmMode aes) <$> ccmInit aes iv n m l aeadInit _ _ _ = CryptoFailed CryptoError_AEADModeNotSupported instance BlockCipher128 AES where xtsEncrypt = encryptXTS @@ -96,6 +101,15 @@ ocbMode aes = AEADModeImpl , aeadImplFinalize = ocbFinish aes } +-- | Create an AES AEAD implementation for CCM +ccmMode :: AES -> AEADModeImpl AESCCM +ccmMode aes = AEADModeImpl + { aeadImplAppendHeader = ccmAppendAAD aes + , aeadImplEncrypt = ccmEncrypt aes + , aeadImplDecrypt = ccmDecrypt aes + , aeadImplFinalize = ccmFinish aes + } + -- | AES Context (pre-processed key) newtype AES = AES ScrubbedBytes @@ -109,12 +123,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 = 80 + keyToPtr :: AES -> (Ptr AES -> IO a) -> IO a keyToPtr (AES b) f = withByteArray b (f . castPtr) @@ -152,6 +173,13 @@ 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) + -- | 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 +475,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 -> CryptoFailable AESCCM +ccmInit ctx iv n m l + | 15 - li /= B.length iv = CryptoFailed CryptoError_IvSizeInvalid + | otherwise = 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 mi) (fromIntegral li) + return $ CryptoPassed (AESCCM sm) + where + mi = ccmGetM m + li = ccmGetL l + +-- | 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 => AES -> AESCCM -> aad -> AESCCM +ccmAppendAAD ctx ccm input = unsafeDoIO $ snd <$> withCCMKeyAndCopySt ctx ccm doAppend + where doAppend ccmStPtr aesPtr = + withByteArray input $ \i -> c_aes_ccm_aad ccmStPtr aesPtr i (fromIntegral $ B.length 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 + where len = B.length input + cbcmacAndIv ccmStPtr aesPtr = + B.alloc len $ \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 cbcmacAndIv + where len = B.length input + cbcmacAndIv 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 +608,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 -> CUInt -> CInt -> CInt -> IO () + +foreign import ccall "cryptonite_aes.h cryptonite_aes_ccm_aad" + c_aes_ccm_aad :: Ptr AESCCM -> Ptr AES -> 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..0b017fc 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,140 @@ void cryptonite_aes_gcm_finish(uint8_t *tag, aes_gcm *gcm, aes_key *key) } } +static inline uint8_t ccm_b0_flags(uint32_t has_adata, uint32_t m, uint32_t l) +{ + return 8*m + l + (has_adata? 64: 0); +} + +/* depends on input size */ +static void ccm_encode_b0(block128* output, aes_ccm* ccm, uint32_t has_adata) +{ + int last = 15; + uint32_t m = ccm->length_M; + uint32_t l = ccm->length_L; + uint32_t msg_len = ccm->length_input; + + block128_zero(output); + block128_copy_aligned(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, uint32_t la) +{ + if (la < ( (1 << 16) - (1 << 8)) ) { + output->b[0] = (la >> 8) & 0xff; + output->b[1] = la & 0xff; + return 2; + } else { + 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; + } +} + +static void ccm_encode_ctr(block128* out, aes_ccm* ccm, unsigned int cnt) +{ + int last = 15; + block128_copy_aligned(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_aligned(&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, uint32_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, nonce_len); + + ccm_encode_b0(&ccm->b0, ccm, 1); /* assume aad is present */ + 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, aes_key *key, uint8_t *input, uint32_t length) +{ + block128 tmp; + + if (ccm->length_aad != 0) return; + + 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); + } + block128_copy_aligned(&ccm->header_cbcmac, &ccm->xi); +} + +void cryptonite_aes_ccm_finish(uint8_t *tag, aes_ccm *ccm, aes_key *key) +{ + block128 iv, s0; + + block128_zero(&iv); + ccm_encode_ctr(&iv, ccm, 0); + cryptonite_aes_encrypt_block(&s0, key, &iv); + block128_vxor((block128*)tag, &ccm->xi, &s0); +} + static inline void ocb_block_double(block128 *d, block128 *s) { unsigned int i; @@ -739,6 +904,66 @@ 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, ctr; + + /* 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); + block128_copy_aligned(&ccm->header_cbcmac, &ccm->xi); + } + + if (length != ccm->length_input) { + return; + } + + ccm_encode_ctr(&ctr, ccm, 1); + cryptonite_aes_encrypt_ctr(output, key, &ctr, input, length); + + 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); + } +} + +void cryptonite_aes_generic_ccm_decrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length) +{ + block128 tmp, ctr; + + if (length != ccm->length_input) { + return; + } + + /* 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); + block128_copy_aligned(&ccm->header_cbcmac, &ccm->xi); + } + + ccm_encode_ctr(&ctr, ccm, 1); + cryptonite_aes_encrypt_ctr(output, key, &ctr, input, length); + block128_copy_aligned(&ccm->xi, &ccm->header_cbcmac); + input = output; + + 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); + } +} + 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..05e147d 100644 --- a/cbits/cryptonite_aes.h +++ b/cbits/cryptonite_aes.h @@ -55,6 +55,18 @@ typedef struct { uint64_t length_input; } aes_gcm; +/* size = 4*16+4*4= 80 */ +typedef struct { + aes_block xi; + aes_block header_cbcmac; + aes_block b0; + aes_block nonce; + uint32_t length_aad; + uint32_t length_input; + uint32_t length_M; + uint32_t length_L; +} aes_ccm; + typedef struct { block128 offset_aad; block128 offset_enc; @@ -97,4 +109,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, uint32_t msg_size, int m, int l); +void cryptonite_aes_ccm_aad(aes_ccm *ccm, aes_key *key, 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 diff --git a/cryptonite.cabal b/cryptonite.cabal index b7c2a51..233fc4e 100644 --- a/cryptonite.cabal +++ b/cryptonite.cabal @@ -377,6 +377,7 @@ Test-Suite test-cryptonite KAT_AES.KATCBC KAT_AES.KATECB KAT_AES.KATGCM + KAT_AES.KATCCM KAT_AES.KATOCB3 KAT_AES.KATXTS KAT_AES diff --git a/tests/BlockCipher.hs b/tests/BlockCipher.hs index 3243f70..2fc1248 100644 --- a/tests/BlockCipher.hs +++ b/tests/BlockCipher.hs @@ -16,8 +16,8 @@ import Imports import Data.Maybe import Crypto.Error import Crypto.Cipher.Types -import Data.ByteArray as B hiding (pack, null) -import qualified Data.ByteString as B hiding (all) +import Data.ByteArray as B hiding (pack, null, length) +import qualified Data.ByteString as B hiding (all, take, replicate) ------------------------------------------------------------------------ -- KAT @@ -161,7 +161,7 @@ testKATs kats cipher = testGroup "KAT" ++ maybeGroup makeCFBTest "CFB" (kat_CFB kats) ++ maybeGroup makeCTRTest "CTR" (kat_CTR kats) -- ++ maybeGroup makeXTSTest "XTS" (kat_XTS kats) - -- ++ maybeGroup makeAEADTest "AEAD" (kat_AEAD kats) + ++ maybeGroup makeAEADTest "AEAD" (kat_AEAD kats) ) where makeECBTest i d = [ testCase ("E" ++ i) (ecbEncrypt ctx (ecbPlaintext d) @?= ecbCiphertext d) @@ -191,25 +191,24 @@ testKATs kats cipher = testGroup "KAT" [ testCase ("E" ++ i) (xtsEncrypt ctx iv 0 (xtsPlaintext d) @?= xtsCiphertext d) , testCase ("D" ++ i) (xtsDecrypt ctx iv 0 (xtsCiphertext d) @?= xtsPlaintext d) ] - where ctx1 = cipherInit (cipherMakeKey cipher $ xtsKey1 d) - ctx2 = cipherInit (cipherMakeKey cipher $ xtsKey2 d) + where ctx1 = cipherInitNoErr (cipherMakeKey cipher $ xtsKey1 d) + ctx2 = cipherInitNoErr (cipherMakeKey cipher $ xtsKey2 d) ctx = (ctx1, ctx2) iv = cipherMakeIV cipher $ xtsIV d +-} makeAEADTest i d = - [ testCase ("AE" ++ i) (etag @?= aeadTag d) - , testCase ("AD" ++ i) (dtag @?= aeadTag d) + [ testCase ("AE" ++ i) (etag @?= AuthTag (B.convert (aeadTag d))) + , testCase ("AD" ++ i) (dtag @?= AuthTag (B.convert (aeadTag d))) , testCase ("E" ++ i) (ebs @?= aeadCiphertext d) , testCase ("D" ++ i) (dbs @?= aeadPlaintext d) ] - where ctx = cipherInit (cipherMakeKey cipher $ aeadKey d) - aead = maybe (error $ "cipher doesn't support aead mode: " ++ show (aeadMode d)) id - $ aeadInit (aeadMode d) ctx (aeadIV d) + where ctx = cipherInitNoErr (cipherMakeKey cipher $ aeadKey d) + aead = aeadInitNoErr (aeadMode d) ctx (aeadIV d) aeadHeaded = aeadAppendHeader aead (aeadHeader d) (ebs,aeadEFinal) = aeadEncrypt aeadHeaded (aeadPlaintext d) (dbs,aeadDFinal) = aeadDecrypt aeadHeaded (aeadCiphertext d) etag = aeadFinalize aeadEFinal (aeadTaglen d) dtag = aeadFinalize aeadDFinal (aeadTaglen d) --} cipherInitNoErr :: BlockCipher c => Key c -> c cipherInitNoErr (Key k) = @@ -217,6 +216,11 @@ testKATs kats cipher = testGroup "KAT" CryptoPassed a -> a CryptoFailed e -> error (show e) + aeadInitNoErr :: (ByteArrayAccess iv, BlockCipher cipher) => AEADMode -> cipher -> iv -> AEAD cipher + aeadInitNoErr mode ct iv = + case aeadInit mode ct iv of + CryptoPassed a -> a + CryptoFailed _ -> error $ "cipher doesn't support aead mode: " ++ show mode ------------------------------------------------------------------------ -- Properties ------------------------------------------------------------------------ @@ -389,7 +393,7 @@ testBlockCipherModes cipher = testBlockCipherAEAD :: BlockCipher a => a -> [TestTree] testBlockCipherAEAD cipher = [ testProperty "OCB" (aeadProp AEAD_OCB) - , testProperty "CCM" (aeadProp AEAD_CCM) + , testProperty "CCM" (aeadProp (AEAD_CCM 0 CCM_M16 CCM_L2)) , testProperty "EAX" (aeadProp AEAD_EAX) , testProperty "CWC" (aeadProp AEAD_CWC) , testProperty "GCM" (aeadProp AEAD_GCM) @@ -398,7 +402,7 @@ testBlockCipherAEAD cipher = toTests :: BlockCipher a => a -> (AEADMode -> AEADUnit a -> Bool) toTests _ = testProperty_AEAD testProperty_AEAD mode (AEADUnit key testIV (unPlaintext -> aad) (unPlaintext -> plaintext)) = withCtx key $ \ctx -> - case aeadInit mode ctx testIV of + case aeadInit mode' ctx iv' of CryptoPassed iniAead -> let aead = aeadAppendHeader iniAead aad (eText, aeadE) = aeadEncrypt aead plaintext @@ -409,6 +413,10 @@ testBlockCipherAEAD cipher = CryptoFailed err | err == CryptoError_AEADModeNotSupported -> True | otherwise -> error ("testProperty_AEAD: " ++ show err) + where (mode', iv') = updateCcmInputSize mode (B.length plaintext) testIV + updateCcmInputSize aeadmode k iv = case aeadmode of + AEAD_CCM _ m l -> (AEAD_CCM k m l, B.take 13 (iv <> (B.replicate 15 0))) + aeadOther -> (aeadOther, iv) withCtx :: Cipher c => Key c -> (c -> a) -> a withCtx (Key key) f = diff --git a/tests/KAT_AES.hs b/tests/KAT_AES.hs index e9a06ab..cf098a3 100644 --- a/tests/KAT_AES.hs +++ b/tests/KAT_AES.hs @@ -3,13 +3,16 @@ module KAT_AES (tests) where import Imports import BlockCipher +import Data.Maybe import Crypto.Cipher.Types import qualified Crypto.Cipher.AES as AES +import qualified Data.ByteString as B import qualified KAT_AES.KATECB as KATECB import qualified KAT_AES.KATCBC as KATCBC import qualified KAT_AES.KATXTS as KATXTS import qualified KAT_AES.KATGCM as KATGCM +import qualified KAT_AES.KATCCM as KATCCM import qualified KAT_AES.KATOCB3 as KATOCB3 {- @@ -37,6 +40,23 @@ toKatAEAD mode (k,iv,h,p,c,taglen,tag) = toKatGCM = toKatAEAD AEAD_GCM toKatOCB = toKatAEAD AEAD_OCB +toKatCCM (k,iv,h,i,o,m) = + KAT_AEAD { aeadMode = AEAD_CCM (B.length i) (ccmMVal m) CCM_L2 + , aeadKey = k + , aeadIV = iv + , aeadHeader = h + , aeadPlaintext = i + , aeadCiphertext = ct + , aeadTaglen = m + , aeadTag = at + } + where ccmMVal x = fromMaybe (error $ "unsupported CCM tag length: " ++ show x) $ + lookup x [ (4, CCM_M4), (6, CCM_M6), (8, CCM_M8), (10, CCM_M10) + , (12, CCM_M12), (14, CCM_M14), (16, CCM_M16) + ] + ctWithTag = B.drop (B.length h) o + (ct, at) = B.splitAt (B.length ctWithTag - m) ctWithTag + kats128 = defaultKATs { kat_ECB = map toKatECB KATECB.vectors_aes128_enc , kat_CBC = map toKatCBC KATCBC.vectors_aes128_enc @@ -48,7 +68,8 @@ kats128 = defaultKATs ] , kat_XTS = map toKatXTS KATXTS.vectors_aes128_enc , kat_AEAD = map toKatGCM KATGCM.vectors_aes128_enc ++ - map toKatOCB KATOCB3.vectors_aes128_enc + map toKatOCB KATOCB3.vectors_aes128_enc ++ + map toKatCCM KATCCM.vectors_aes128_enc } kats192 = defaultKATs diff --git a/tests/KAT_AES/KATCCM.hs b/tests/KAT_AES/KATCCM.hs new file mode 100644 index 0000000..4f3c197 --- /dev/null +++ b/tests/KAT_AES/KATCCM.hs @@ -0,0 +1,155 @@ +{-# LANGUAGE OverloadedStrings #-} +module KAT_AES.KATCCM where + +import qualified Data.ByteString as B + +-- (key, iv, header, in, out+atag, taglen) +type KATCCM = (B.ByteString, B.ByteString, B.ByteString, B.ByteString, B.ByteString, Int) + +vectors_aes128_enc :: [KATCCM] +vectors_aes128_enc = + [ ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x03\x02\x01\x00\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07" + , {- in = -} "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x58\x8c\x97\x9a\x61\xc6\x63\xd2\xf0\x66\xd0\xc2\xc0\xf9\x89\x80\x6d\x5f\x6b\x61\xda\xc3\x84\x17\xe8\xd1\x2c\xfd\xf9\x26\xe0" + , {- M = -} 8) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x04\x03\x02\x01\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07" + , {- in = -} "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x72\xc9\x1a\x36\xe1\x35\xf8\xcf\x29\x1c\xa8\x94\x08\x5c\x87\xe3\xcc\x15\xc4\x39\xc9\xe4\x3a\x3b\xa0\x91\xd5\x6e\x10\x40\x09\x16" + , {- M = -} 8) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x05\x04\x03\x02\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07" + , {- in = -} "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x51\xb1\xe5\xf4\x4a\x19\x7d\x1d\xa4\x6b\x0f\x8e\x2d\x28\x2a\xe8\x71\xe8\x38\xbb\x64\xda\x85\x96\x57\x4a\xda\xa7\x6f\xbd\x9f\xb0\xc5" + , {- M = -} 8) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x06\x05\x04\x03\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" + , {- in = -} "\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\xa2\x8c\x68\x65\x93\x9a\x9a\x79\xfa\xaa\x5c\x4c\x2a\x9d\x4a\x91\xcd\xac\x8c\x96\xc8\x61\xb9\xc9\xe6\x1e\xf1" + , {- M = -} 8) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x07\x06\x05\x04\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" + , {- in = -} "\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb\x9d\x4e\x13\x12\x53\x65\x8a\xd8\x6e\xbd\xca\x3e\x51\xe8\x3f\x07\x7d\x9c\x2d\x93" + , {- M = -} 8) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x08\x07\x06\x05\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" + , {- in = -} "\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x6f\xc1\xb0\x11\xf0\x06\x56\x8b\x51\x71\xa4\x2d\x95\x3d\x46\x9b\x25\x70\xa4\xbd\x87\x40\x5a\x04\x43\xac\x91\xcb\x94" + , {- M = -} 8) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x09\x08\x07\x06\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07" + , {- in = -} "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x01\x35\xd1\xb2\xc9\x5f\x41\xd5\xd1\xd4\xfe\xc1\x85\xd1\x66\xb8\x09\x4e\x99\x9d\xfe\xd9\x6c\x04\x8c\x56\x60\x2c\x97\xac\xbb\x74\x90" + , {- M = -} 10) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x0a\x09\x08\x07\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07" + , {- in = -} "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x7b\x75\x39\x9a\xc0\x83\x1d\xd2\xf0\xbb\xd7\x58\x79\xa2\xfd\x8f\x6c\xae\x6b\x6c\xd9\xb7\xdb\x24\xc1\x7b\x44\x33\xf4\x34\x96\x3f\x34\xb4" + , {- M = -} 10) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x0b\x0a\x09\x08\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07" + , {- in = -} "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x82\x53\x1a\x60\xcc\x24\x94\x5a\x4b\x82\x79\x18\x1a\xb5\xc8\x4d\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1\x97\xea\x9c\x07\xe5\x6b\x5e\xb1\x7e\x5f\x4e" + , {- M = -} 10) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x0c\x0b\x0a\x09\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" + , {- in = -} "\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x07\x34\x25\x94\x15\x77\x85\x15\x2b\x07\x40\x98\x33\x0a\xbb\x14\x1b\x94\x7b\x56\x6a\xa9\x40\x6b\x4d\x99\x99\x88\xdd" + , {- M = -} 10) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x0d\x0c\x0b\x0a\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" + , {- in = -} "\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x67\x6b\xb2\x03\x80\xb0\xe3\x01\xe8\xab\x79\x59\x0a\x39\x6d\xa7\x8b\x83\x49\x34\xf5\x3a\xa2\xe9\x10\x7a\x8b\x6c\x02\x2c" + , {- M = -} 10) + , ( {- key = -} "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" + , {- iv = -} "\x00\x00\x00\x0e\x0d\x0c\x0b\xa0\xa1\xa2\xa3\xa4\xa5" + , {- hdr = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" + , {- in = -} "\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" + , {- out = -} "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\xc0\xff\xa0\xd6\xf0\x5b\xdb\x67\xf2\x4d\x43\xa4\x33\x8d\x2a\xa4\xbe\xd7\xb2\x0e\x43\xcd\x1a\xa3\x16\x62\xe7\xad\x65\xd6\xdb" + , {- M = -} 10) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x41\x2b\x4e\xa9\xcd\xbe\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\x0b\xe1\xa8\x8b\xac\xe0\x18\xb1" + , {- in = -} "\x08\xe8\xcf\x97\xd8\x20\xea\x25\x84\x60\xe9\x6a\xd9\xcf\x52\x89\x05\x4d\x89\x5c\xea\xc4\x7c" + , {- out = -} "\x0b\xe1\xa8\x8b\xac\xe0\x18\xb1\x4c\xb9\x7f\x86\xa2\xa4\x68\x9a\x87\x79\x47\xab\x80\x91\xef\x53\x86\xa6\xff\xbd\xd0\x80\xf8\xe7\x8c\xf7\xcb\x0c\xdd\xd7\xb3" + , {- M = -} 8) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x33\x56\x8e\xf7\xb2\x63\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb" + , {- in = -} "\x90\x20\xea\x6f\x91\xbd\xd8\x5a\xfa\x00\x39\xba\x4b\xaf\xf9\xbf\xb7\x9c\x70\x28\x94\x9c\xd0\xec" + , {- out = -} "\x63\x01\x8f\x76\xdc\x8a\x1b\xcb\x4c\xcb\x1e\x7c\xa9\x81\xbe\xfa\xa0\x72\x6c\x55\xd3\x78\x06\x12\x98\xc8\x5c\x92\x81\x4a\xbc\x33\xc5\x2e\xe8\x1d\x7d\x77\xc0\x8a" + , {- M = -} 8) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x10\x3f\xe4\x13\x36\x71\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\xaa\x6c\xfa\x36\xca\xe8\x6b\x40" + , {- in = -} "\xb9\x16\xe0\xea\xcc\x1c\x00\xd7\xdc\xec\x68\xec\x0b\x3b\xbb\x1a\x02\xde\x8a\x2d\x1a\xa3\x46\x13\x2e" + , {- out = -} "\xaa\x6c\xfa\x36\xca\xe8\x6b\x40\xb1\xd2\x3a\x22\x20\xdd\xc0\xac\x90\x0d\x9a\xa0\x3c\x61\xfc\xf4\xa5\x59\xa4\x41\x77\x67\x08\x97\x08\xa7\x76\x79\x6e\xdb\x72\x35\x06" + , {- M = -} 8) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x76\x4c\x63\xb8\x05\x8e\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\xd0\xd0\x73\x5c\x53\x1e\x1b\xec\xf0\x49\xc2\x44" + , {- in = -} "\x12\xda\xac\x56\x30\xef\xa5\x39\x6f\x77\x0c\xe1\xa6\x6b\x21\xf7\xb2\x10\x1c" + , {- out = -} "\xd0\xd0\x73\x5c\x53\x1e\x1b\xec\xf0\x49\xc2\x44\x14\xd2\x53\xc3\x96\x7b\x70\x60\x9b\x7c\xbb\x7c\x49\x91\x60\x28\x32\x45\x26\x9a\x6f\x49\x97\x5b\xca\xde\xaf" + , {- M = -} 8) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\xf8\xb6\x78\x09\x4e\x3b\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\x77\xb6\x0f\x01\x1c\x03\xe1\x52\x58\x99\xbc\xae" + , {- in = -} "\xe8\x8b\x6a\x46\xc7\x8d\x63\xe5\x2e\xb8\xc5\x46\xef\xb5\xde\x6f\x75\xe9\xcc\x0d" + , {- out = -} "\x77\xb6\x0f\x01\x1c\x03\xe1\x52\x58\x99\xbc\xae\x55\x45\xff\x1a\x08\x5e\xe2\xef\xbf\x52\xb2\xe0\x4b\xee\x1e\x23\x36\xc7\x3e\x3f\x76\x2c\x0c\x77\x44\xfe\x7e\x3c" + , {- M = -} 8) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\xd5\x60\x91\x2d\x3f\x70\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81\x20\xea\x60\xc0" + , {- in = -} "\x64\x35\xac\xba\xfb\x11\xa8\x2e\x2f\x07\x1d\x7c\xa4\xa5\xeb\xd9\x3a\x80\x3b\xa8\x7f" + , {- out = -} "\xcd\x90\x44\xd2\xb7\x1f\xdb\x81\x20\xea\x60\xc0\x00\x97\x69\xec\xab\xdf\x48\x62\x55\x94\xc5\x92\x51\xe6\x03\x57\x22\x67\x5e\x04\xc8\x47\x09\x9e\x5a\xe0\x70\x45\x51" + , {- M = -} 8) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x42\xff\xf8\xf1\x95\x1c\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8" + , {- in = -} "\x8a\x19\xb9\x50\xbc\xf7\x1a\x01\x8e\x5e\x67\x01\xc9\x17\x87\x65\x98\x09\xd6\x7d\xbe\xdd\x18" + , {- out = -} "\xd8\x5b\xc7\xe6\x9f\x94\x4f\xb8\xbc\x21\x8d\xaa\x94\x74\x27\xb6\xdb\x38\x6a\x99\xac\x1a\xef\x23\xad\xe0\xb5\x29\x39\xcb\x6a\x63\x7c\xf9\xbe\xc2\x40\x88\x97\xc6\xba" + , {- M = -} 10) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x92\x0f\x40\xe5\x6c\xdc\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\x74\xa0\xeb\xc9\x06\x9f\x5b\x37" + , {- in = -} "\x17\x61\x43\x3c\x37\xc5\xa3\x5f\xc1\xf3\x9f\x40\x63\x02\xeb\x90\x7c\x61\x63\xbe\x38\xc9\x84\x37" + , {- out = -} "\x74\xa0\xeb\xc9\x06\x9f\x5b\x37\x58\x10\xe6\xfd\x25\x87\x40\x22\xe8\x03\x61\xa4\x78\xe3\xe9\xcf\x48\x4a\xb0\x4f\x44\x7e\xff\xf6\xf0\xa4\x77\xcc\x2f\xc9\xbf\x54\x89\x44" + , {- M = -} 10) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x27\xca\x0c\x71\x20\xbc\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\x44\xa3\xaa\x3a\xae\x64\x75\xca" + , {- in = -} "\xa4\x34\xa8\xe5\x85\x00\xc6\xe4\x15\x30\x53\x88\x62\xd6\x86\xea\x9e\x81\x30\x1b\x5a\xe4\x22\x6b\xfa" + , {- out = -} "\x44\xa3\xaa\x3a\xae\x64\x75\xca\xf2\xbe\xed\x7b\xc5\x09\x8e\x83\xfe\xb5\xb3\x16\x08\xf8\xe2\x9c\x38\x81\x9a\x89\xc8\xe7\x76\xf1\x54\x4d\x41\x51\xa4\xed\x3a\x8b\x87\xb9\xce" + , {- M = -} 10) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x5b\x8c\xcb\xcd\x9a\xf8\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\xec\x46\xbb\x63\xb0\x25\x20\xc3\x3c\x49\xfd\x70" + , {- in = -} "\xb9\x6b\x49\xe2\x1d\x62\x17\x41\x63\x28\x75\xdb\x7f\x6c\x92\x43\xd2\xd7\xc2" + , {- out = -} "\xec\x46\xbb\x63\xb0\x25\x20\xc3\x3c\x49\xfd\x70\x31\xd7\x50\xa0\x9d\xa3\xed\x7f\xdd\xd4\x9a\x20\x32\xaa\xbf\x17\xec\x8e\xbf\x7d\x22\xc8\x08\x8c\x66\x6b\xe5\xc1\x97" + , {- M = -} 10) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x3e\xbe\x94\x04\x4b\x9a\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\x47\xa6\x5a\xc7\x8b\x3d\x59\x42\x27\xe8\x5e\x71" + , {- in = -} "\xe2\xfc\xfb\xb8\x80\x44\x2c\x73\x1b\xf9\x51\x67\xc8\xff\xd7\x89\x5e\x33\x70\x76" + , {- out = -} "\x47\xa6\x5a\xc7\x8b\x3d\x59\x42\x27\xe8\x5e\x71\xe8\x82\xf1\xdb\xd3\x8c\xe3\xed\xa7\xc2\x3f\x04\xdd\x65\x07\x1e\xb4\x13\x42\xac\xdf\x7e\x00\xdc\xce\xc7\xae\x52\x98\x7d" + , {- M = -} 10) + , ( {- key = -} "\xd7\x82\x8d\x13\xb2\xb0\xbd\xc3\x25\xa7\x62\x36\xdf\x93\xcc\x6b" + , {- iv = -} "\x00\x8d\x49\x3b\x30\xae\x8b\x3c\x96\x96\x76\x6c\xfa" + , {- hdr = -} "\x6e\x37\xa6\xef\x54\x6d\x95\x5d\x34\xab\x60\x59" + , {- in = -} "\xab\xf2\x1c\x0b\x02\xfe\xb8\x8f\x85\x6d\xf4\xa3\x73\x81\xbc\xe3\xcc\x12\x85\x17\xd4" + , {- out = -} "\x6e\x37\xa6\xef\x54\x6d\x95\x5d\x34\xab\x60\x59\xf3\x29\x05\xb8\x8a\x64\x1b\x04\xb9\xc9\xff\xb5\x8c\xc3\x90\x90\x0f\x3d\xa1\x2a\xb1\x6d\xce\x9e\x82\xef\xa1\x6d\xa6\x20\x59" + , {- M = -} 10) + ] diff --git a/tests/KAT_HMAC.hs b/tests/KAT_HMAC.hs index 90b222f..74cc157 100644 --- a/tests/KAT_HMAC.hs +++ b/tests/KAT_HMAC.hs @@ -132,17 +132,17 @@ instance HashAlgorithm a => Arbitrary (MacIncrementalList a) where macIncrementalTests :: [TestTree] macIncrementalTests = - [ testProperties MD5 - , testProperties SHA1 - , testProperties SHA256 - , testProperties SHA3_224 - , testProperties SHA3_256 - , testProperties SHA3_384 - , testProperties SHA3_512 + [ testIncrProperties MD5 + , testIncrProperties SHA1 + , testIncrProperties SHA256 + , testIncrProperties SHA3_224 + , testIncrProperties SHA3_256 + , testIncrProperties SHA3_384 + , testIncrProperties SHA3_512 ] where - --testProperties :: HashAlgorithm a => a -> [Property] - testProperties a = testGroup (show a) + --testIncrProperties :: HashAlgorithm a => a -> [Property] + testIncrProperties a = testGroup (show a) [ testProperty "list-one" (prop_inc0 a) , testProperty "list-multi" (prop_inc1 a) ]