Merge pull request #216 from haskell-crypto/aesccm-rebase

AES CCM mode
This commit is contained in:
Vincent Hanquez 2018-02-04 21:38:16 +00:00 committed by GitHub
commit 6c84a1605d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 574 additions and 24 deletions

View File

@ -59,6 +59,7 @@ instance BlockCipher CSTR where \
; ctrCombine (CSTR aes) (IV iv) = encryptCTR aes (IV iv) \ ; ctrCombine (CSTR aes) (IV iv) = encryptCTR aes (IV iv) \
; aeadInit AEAD_GCM (CSTR aes) iv = CryptoPassed $ AEAD (gcmMode aes) (gcmInit aes 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_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 \ ; aeadInit _ _ _ = CryptoFailed CryptoError_AEADModeNotSupported \
}; \ }; \
instance BlockCipher128 CSTR where \ instance BlockCipher128 CSTR where \

View File

@ -44,6 +44,10 @@ module Crypto.Cipher.AES.Primitive
-- * Incremental OCB -- * Incremental OCB
, ocbMode , ocbMode
, ocbInit , ocbInit
-- * CCM
, ccmMode
, ccmInit
) where ) where
import Data.Word import Data.Word
@ -73,6 +77,7 @@ instance BlockCipher AES where
ctrCombine = encryptCTR ctrCombine = encryptCTR
aeadInit AEAD_GCM aes iv = CryptoPassed $ AEAD (gcmMode aes) (gcmInit aes iv) 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_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 aeadInit _ _ _ = CryptoFailed CryptoError_AEADModeNotSupported
instance BlockCipher128 AES where instance BlockCipher128 AES where
xtsEncrypt = encryptXTS xtsEncrypt = encryptXTS
@ -96,6 +101,15 @@ ocbMode aes = AEADModeImpl
, aeadImplFinalize = ocbFinish aes , 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) -- | AES Context (pre-processed key)
newtype AES = AES ScrubbedBytes newtype AES = AES ScrubbedBytes
@ -109,12 +123,19 @@ newtype AESGCM = AESGCM ScrubbedBytes
newtype AESOCB = AESOCB ScrubbedBytes newtype AESOCB = AESOCB ScrubbedBytes
deriving (NFData) deriving (NFData)
-- | AESCCM State
newtype AESCCM = AESCCM ScrubbedBytes
deriving (NFData)
sizeGCM :: Int sizeGCM :: Int
sizeGCM = 80 sizeGCM = 80
sizeOCB :: Int sizeOCB :: Int
sizeOCB = 160 sizeOCB = 160
sizeCCM :: Int
sizeCCM = 80
keyToPtr :: AES -> (Ptr AES -> IO a) -> IO a keyToPtr :: AES -> (Ptr AES -> IO a) -> IO a
keyToPtr (AES b) f = withByteArray b (f . castPtr) 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 a <- withByteArray newSt $ \gcmStPtr -> f (castPtr gcmStPtr) aesPtr
return (a, AESOCB newSt) 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 -- | Initialize a new context with a key
-- --
-- Key needs to be of length 16, 24 or 32 bytes. Any other values will return failure -- 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 -> where computeTag = B.allocAndFreeze 16 $ \t ->
withOCBKeyAndCopySt ctx ocb (c_aes_ocb_finish (castPtr t)) >> return () 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" foreign import ccall "cryptonite_aes.h cryptonite_aes_initkey"
c_aes_init :: Ptr AES -> CString -> CUInt -> IO () 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" foreign import ccall "cryptonite_aes.h cryptonite_aes_ocb_finish"
c_aes_ocb_finish :: CString -> Ptr AESOCB -> Ptr AES -> IO () 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 ()

View File

@ -21,6 +21,8 @@ module Crypto.Cipher.Types
-- , cfb8Decrypt -- , cfb8Decrypt
-- * AEAD functions -- * AEAD functions
, AEADMode(..) , AEADMode(..)
, CCM_M(..)
, CCM_L(..)
, module Crypto.Cipher.Types.AEAD , module Crypto.Cipher.Types.AEAD
-- * Initial Vector type and constructor -- * Initial Vector type and constructor
, IV , IV

View File

@ -14,6 +14,8 @@ module Crypto.Cipher.Types.Base
, Cipher(..) , Cipher(..)
, AuthTag(..) , AuthTag(..)
, AEADMode(..) , AEADMode(..)
, CCM_M(..)
, CCM_L(..)
, DataUnitOffset , DataUnitOffset
) where ) where
@ -39,10 +41,13 @@ newtype AuthTag = AuthTag { unAuthTag :: Bytes }
instance Eq AuthTag where instance Eq AuthTag where
(AuthTag a) == (AuthTag b) = B.constEq a b (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 -- | AEAD Mode
data AEADMode = data AEADMode =
AEAD_OCB -- OCB3 AEAD_OCB -- OCB3
| AEAD_CCM | AEAD_CCM Int CCM_M CCM_L
| AEAD_EAX | AEAD_EAX
| AEAD_CWC | AEAD_CWC
| AEAD_GCM | AEAD_GCM

View File

@ -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_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_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_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 { enum {
/* init */ /* init */
@ -76,6 +78,9 @@ enum {
/* ocb */ /* ocb */
ENCRYPT_OCB_128, ENCRYPT_OCB_192, ENCRYPT_OCB_256, ENCRYPT_OCB_128, ENCRYPT_OCB_192, ENCRYPT_OCB_256,
DECRYPT_OCB_128, DECRYPT_OCB_192, DECRYPT_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[] = { void *cryptonite_aes_branch_table[] = {
@ -129,6 +134,13 @@ void *cryptonite_aes_branch_table[] = {
[DECRYPT_OCB_128] = cryptonite_aes_generic_ocb_decrypt, [DECRYPT_OCB_128] = cryptonite_aes_generic_ocb_decrypt,
[DECRYPT_OCB_192] = cryptonite_aes_generic_ocb_decrypt, [DECRYPT_OCB_192] = cryptonite_aes_generic_ocb_decrypt,
[DECRYPT_OCB_256] = 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); 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 (*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 (*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 (*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); typedef void (*block_f)(aes_block *output, aes_key *key, aes_block *input);
#ifdef WITH_AESNI #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])) ((ocb_crypt_f) (cryptonite_aes_branch_table[ENCRYPT_OCB_128 + strength]))
#define GET_OCB_DECRYPT(strength) \ #define GET_OCB_DECRYPT(strength) \
((ocb_crypt_f) (cryptonite_aes_branch_table[DECRYPT_OCB_128 + 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) \ #define cryptonite_aes_encrypt_block(o,k,i) \
(((block_f) (cryptonite_aes_branch_table[ENCRYPT_BLOCK_128 + k->strength]))(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) \ #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_GCM_DECRYPT(strength) cryptonite_aes_generic_gcm_decrypt
#define GET_OCB_ENCRYPT(strength) cryptonite_aes_generic_ocb_encrypt #define GET_OCB_ENCRYPT(strength) cryptonite_aes_generic_ocb_encrypt
#define GET_OCB_DECRYPT(strength) cryptonite_aes_generic_ocb_decrypt #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_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) #define cryptonite_aes_decrypt_block(o,k,i) cryptonite_aes_generic_decrypt_block(o,k,i)
#endif #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); 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) 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); 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) static inline void ocb_block_double(block128 *d, block128 *s)
{ {
unsigned int i; 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) 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); ocb_generic_crypt(output, ocb, key, input, length, 1);

View File

@ -55,6 +55,18 @@ typedef struct {
uint64_t length_input; uint64_t length_input;
} aes_gcm; } 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 { typedef struct {
block128 offset_aad; block128 offset_aad;
block128 offset_enc; 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_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_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 #endif

View File

@ -377,6 +377,7 @@ Test-Suite test-cryptonite
KAT_AES.KATCBC KAT_AES.KATCBC
KAT_AES.KATECB KAT_AES.KATECB
KAT_AES.KATGCM KAT_AES.KATGCM
KAT_AES.KATCCM
KAT_AES.KATOCB3 KAT_AES.KATOCB3
KAT_AES.KATXTS KAT_AES.KATXTS
KAT_AES KAT_AES

View File

@ -16,8 +16,8 @@ import Imports
import Data.Maybe import Data.Maybe
import Crypto.Error import Crypto.Error
import Crypto.Cipher.Types import Crypto.Cipher.Types
import Data.ByteArray as B hiding (pack, null) import Data.ByteArray as B hiding (pack, null, length)
import qualified Data.ByteString as B hiding (all) import qualified Data.ByteString as B hiding (all, take, replicate)
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- KAT -- KAT
@ -161,7 +161,7 @@ testKATs kats cipher = testGroup "KAT"
++ maybeGroup makeCFBTest "CFB" (kat_CFB kats) ++ maybeGroup makeCFBTest "CFB" (kat_CFB kats)
++ maybeGroup makeCTRTest "CTR" (kat_CTR kats) ++ maybeGroup makeCTRTest "CTR" (kat_CTR kats)
-- ++ maybeGroup makeXTSTest "XTS" (kat_XTS kats) -- ++ maybeGroup makeXTSTest "XTS" (kat_XTS kats)
-- ++ maybeGroup makeAEADTest "AEAD" (kat_AEAD kats) ++ maybeGroup makeAEADTest "AEAD" (kat_AEAD kats)
) )
where makeECBTest i d = where makeECBTest i d =
[ testCase ("E" ++ i) (ecbEncrypt ctx (ecbPlaintext d) @?= ecbCiphertext 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 ("E" ++ i) (xtsEncrypt ctx iv 0 (xtsPlaintext d) @?= xtsCiphertext d)
, testCase ("D" ++ i) (xtsDecrypt ctx iv 0 (xtsCiphertext d) @?= xtsPlaintext d) , testCase ("D" ++ i) (xtsDecrypt ctx iv 0 (xtsCiphertext d) @?= xtsPlaintext d)
] ]
where ctx1 = cipherInit (cipherMakeKey cipher $ xtsKey1 d) where ctx1 = cipherInitNoErr (cipherMakeKey cipher $ xtsKey1 d)
ctx2 = cipherInit (cipherMakeKey cipher $ xtsKey2 d) ctx2 = cipherInitNoErr (cipherMakeKey cipher $ xtsKey2 d)
ctx = (ctx1, ctx2) ctx = (ctx1, ctx2)
iv = cipherMakeIV cipher $ xtsIV d iv = cipherMakeIV cipher $ xtsIV d
-}
makeAEADTest i d = makeAEADTest i d =
[ testCase ("AE" ++ i) (etag @?= aeadTag d) [ testCase ("AE" ++ i) (etag @?= AuthTag (B.convert (aeadTag d)))
, testCase ("AD" ++ i) (dtag @?= aeadTag d) , testCase ("AD" ++ i) (dtag @?= AuthTag (B.convert (aeadTag d)))
, testCase ("E" ++ i) (ebs @?= aeadCiphertext d) , testCase ("E" ++ i) (ebs @?= aeadCiphertext d)
, testCase ("D" ++ i) (dbs @?= aeadPlaintext d) , testCase ("D" ++ i) (dbs @?= aeadPlaintext d)
] ]
where ctx = cipherInit (cipherMakeKey cipher $ aeadKey d) where ctx = cipherInitNoErr (cipherMakeKey cipher $ aeadKey d)
aead = maybe (error $ "cipher doesn't support aead mode: " ++ show (aeadMode d)) id aead = aeadInitNoErr (aeadMode d) ctx (aeadIV d)
$ aeadInit (aeadMode d) ctx (aeadIV d)
aeadHeaded = aeadAppendHeader aead (aeadHeader d) aeadHeaded = aeadAppendHeader aead (aeadHeader d)
(ebs,aeadEFinal) = aeadEncrypt aeadHeaded (aeadPlaintext d) (ebs,aeadEFinal) = aeadEncrypt aeadHeaded (aeadPlaintext d)
(dbs,aeadDFinal) = aeadDecrypt aeadHeaded (aeadCiphertext d) (dbs,aeadDFinal) = aeadDecrypt aeadHeaded (aeadCiphertext d)
etag = aeadFinalize aeadEFinal (aeadTaglen d) etag = aeadFinalize aeadEFinal (aeadTaglen d)
dtag = aeadFinalize aeadDFinal (aeadTaglen d) dtag = aeadFinalize aeadDFinal (aeadTaglen d)
-}
cipherInitNoErr :: BlockCipher c => Key c -> c cipherInitNoErr :: BlockCipher c => Key c -> c
cipherInitNoErr (Key k) = cipherInitNoErr (Key k) =
@ -217,6 +216,11 @@ testKATs kats cipher = testGroup "KAT"
CryptoPassed a -> a CryptoPassed a -> a
CryptoFailed e -> error (show e) 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 -- Properties
------------------------------------------------------------------------ ------------------------------------------------------------------------
@ -389,7 +393,7 @@ testBlockCipherModes cipher =
testBlockCipherAEAD :: BlockCipher a => a -> [TestTree] testBlockCipherAEAD :: BlockCipher a => a -> [TestTree]
testBlockCipherAEAD cipher = testBlockCipherAEAD cipher =
[ testProperty "OCB" (aeadProp AEAD_OCB) [ 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 "EAX" (aeadProp AEAD_EAX)
, testProperty "CWC" (aeadProp AEAD_CWC) , testProperty "CWC" (aeadProp AEAD_CWC)
, testProperty "GCM" (aeadProp AEAD_GCM) , testProperty "GCM" (aeadProp AEAD_GCM)
@ -398,7 +402,7 @@ testBlockCipherAEAD cipher =
toTests :: BlockCipher a => a -> (AEADMode -> AEADUnit a -> Bool) toTests :: BlockCipher a => a -> (AEADMode -> AEADUnit a -> Bool)
toTests _ = testProperty_AEAD toTests _ = testProperty_AEAD
testProperty_AEAD mode (AEADUnit key testIV (unPlaintext -> aad) (unPlaintext -> plaintext)) = withCtx key $ \ctx -> 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 -> CryptoPassed iniAead ->
let aead = aeadAppendHeader iniAead aad let aead = aeadAppendHeader iniAead aad
(eText, aeadE) = aeadEncrypt aead plaintext (eText, aeadE) = aeadEncrypt aead plaintext
@ -409,6 +413,10 @@ testBlockCipherAEAD cipher =
CryptoFailed err CryptoFailed err
| err == CryptoError_AEADModeNotSupported -> True | err == CryptoError_AEADModeNotSupported -> True
| otherwise -> error ("testProperty_AEAD: " ++ show err) | 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 :: Cipher c => Key c -> (c -> a) -> a
withCtx (Key key) f = withCtx (Key key) f =

View File

@ -3,13 +3,16 @@ module KAT_AES (tests) where
import Imports import Imports
import BlockCipher import BlockCipher
import Data.Maybe
import Crypto.Cipher.Types import Crypto.Cipher.Types
import qualified Crypto.Cipher.AES as AES import qualified Crypto.Cipher.AES as AES
import qualified Data.ByteString as B
import qualified KAT_AES.KATECB as KATECB import qualified KAT_AES.KATECB as KATECB
import qualified KAT_AES.KATCBC as KATCBC import qualified KAT_AES.KATCBC as KATCBC
import qualified KAT_AES.KATXTS as KATXTS import qualified KAT_AES.KATXTS as KATXTS
import qualified KAT_AES.KATGCM as KATGCM import qualified KAT_AES.KATGCM as KATGCM
import qualified KAT_AES.KATCCM as KATCCM
import qualified KAT_AES.KATOCB3 as KATOCB3 import qualified KAT_AES.KATOCB3 as KATOCB3
{- {-
@ -37,6 +40,23 @@ toKatAEAD mode (k,iv,h,p,c,taglen,tag) =
toKatGCM = toKatAEAD AEAD_GCM toKatGCM = toKatAEAD AEAD_GCM
toKatOCB = toKatAEAD AEAD_OCB 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 kats128 = defaultKATs
{ kat_ECB = map toKatECB KATECB.vectors_aes128_enc { kat_ECB = map toKatECB KATECB.vectors_aes128_enc
, kat_CBC = map toKatCBC KATCBC.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_XTS = map toKatXTS KATXTS.vectors_aes128_enc
, kat_AEAD = map toKatGCM KATGCM.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 kats192 = defaultKATs

155
tests/KAT_AES/KATCCM.hs Normal file
View File

@ -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)
]

View File

@ -132,17 +132,17 @@ instance HashAlgorithm a => Arbitrary (MacIncrementalList a) where
macIncrementalTests :: [TestTree] macIncrementalTests :: [TestTree]
macIncrementalTests = macIncrementalTests =
[ testProperties MD5 [ testIncrProperties MD5
, testProperties SHA1 , testIncrProperties SHA1
, testProperties SHA256 , testIncrProperties SHA256
, testProperties SHA3_224 , testIncrProperties SHA3_224
, testProperties SHA3_256 , testIncrProperties SHA3_256
, testProperties SHA3_384 , testIncrProperties SHA3_384
, testProperties SHA3_512 , testIncrProperties SHA3_512
] ]
where where
--testProperties :: HashAlgorithm a => a -> [Property] --testIncrProperties :: HashAlgorithm a => a -> [Property]
testProperties a = testGroup (show a) testIncrProperties a = testGroup (show a)
[ testProperty "list-one" (prop_inc0 a) [ testProperty "list-one" (prop_inc0 a)
, testProperty "list-multi" (prop_inc1 a) , testProperty "list-multi" (prop_inc1 a)
] ]