add aes ccm support
This commit is contained in:
parent
28f604f7bd
commit
55bf620365
@ -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 \
|
||||
|
||||
@ -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 ()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user