refactor some stuff
This commit is contained in:
parent
ca125f3e66
commit
39ee0a4aa2
@ -50,8 +50,9 @@ import Foreign.Storable
|
|||||||
-- | an IV parametrized by the cipher
|
-- | an IV parametrized by the cipher
|
||||||
data IV c = forall byteArray . ByteArray byteArray => IV byteArray
|
data IV c = forall byteArray . ByteArray byteArray => IV byteArray
|
||||||
|
|
||||||
instance BlockCipher c => ByteArray (IV c) where
|
instance BlockCipher c => ByteArrayAccess (IV c) where
|
||||||
|
withByteArray (IV z) f = withByteArray z f
|
||||||
|
byteArrayLength (IV z) = byteArrayLength z
|
||||||
|
|
||||||
type XTS cipher = (cipher, cipher)
|
type XTS cipher = (cipher, cipher)
|
||||||
-> IV cipher -- ^ Usually represent the Data Unit (e.g. disk sector)
|
-> IV cipher -- ^ Usually represent the Data Unit (e.g. disk sector)
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
{-# LANGUAGE UnboxedTuples #-}
|
{-# LANGUAGE UnboxedTuples #-}
|
||||||
module Crypto.Internal.ByteArray
|
module Crypto.Internal.ByteArray
|
||||||
( ByteArray(..)
|
( ByteArray(..)
|
||||||
|
, ByteArrayAccess(..)
|
||||||
, byteArrayAllocAndFreeze
|
, byteArrayAllocAndFreeze
|
||||||
, empty
|
, empty
|
||||||
, byteArrayCopyAndFreeze
|
, byteArrayCopyAndFreeze
|
||||||
@ -36,32 +37,37 @@ import Data.ByteString (ByteString)
|
|||||||
import qualified Data.ByteString as B (length)
|
import qualified Data.ByteString as B (length)
|
||||||
import qualified Data.ByteString.Internal as B
|
import qualified Data.ByteString.Internal as B
|
||||||
|
|
||||||
class ByteArray ba where
|
class ByteArrayAccess ba where
|
||||||
byteArrayAlloc :: Int -> (Ptr p -> IO ()) -> IO ba
|
|
||||||
byteArrayLength :: ba -> Int
|
byteArrayLength :: ba -> Int
|
||||||
withByteArray :: ba -> (Ptr p -> IO a) -> IO a
|
withByteArray :: ba -> (Ptr p -> IO a) -> IO a
|
||||||
|
|
||||||
instance ByteArray Bytes where
|
class ByteArrayAccess ba => ByteArray ba where
|
||||||
byteArrayAlloc = bytesAlloc
|
byteArrayAlloc :: Int -> (Ptr p -> IO ()) -> IO ba
|
||||||
|
|
||||||
|
instance ByteArrayAccess Bytes where
|
||||||
byteArrayLength = bytesLength
|
byteArrayLength = bytesLength
|
||||||
withByteArray = withBytes
|
withByteArray = withBytes
|
||||||
|
instance ByteArray Bytes where
|
||||||
|
byteArrayAlloc = bytesAlloc
|
||||||
|
|
||||||
|
instance ByteArrayAccess ByteString where
|
||||||
|
byteArrayLength = B.length
|
||||||
|
withByteArray b f = withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off)
|
||||||
|
where (fptr, off, _) = B.toForeignPtr b
|
||||||
instance ByteArray ByteString where
|
instance ByteArray ByteString where
|
||||||
byteArrayAlloc sz f = do
|
byteArrayAlloc sz f = do
|
||||||
fptr <- B.mallocByteString sz
|
fptr <- B.mallocByteString sz
|
||||||
withForeignPtr fptr (f . castPtr)
|
withForeignPtr fptr (f . castPtr)
|
||||||
return $! B.PS fptr 0 sz
|
return $! B.PS fptr 0 sz
|
||||||
byteArrayLength = B.length
|
|
||||||
withByteArray b f = withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off)
|
|
||||||
where (fptr, off, _) = B.toForeignPtr b
|
|
||||||
|
|
||||||
|
instance ByteArrayAccess SecureMem where
|
||||||
|
byteArrayLength = secureMemGetSize
|
||||||
|
withByteArray b f = withSecureMemPtr b (f . castPtr)
|
||||||
instance ByteArray SecureMem where
|
instance ByteArray SecureMem where
|
||||||
byteArrayAlloc sz f = do
|
byteArrayAlloc sz f = do
|
||||||
out <- allocateSecureMem sz
|
out <- allocateSecureMem sz
|
||||||
withSecureMemPtr out (f . castPtr)
|
withSecureMemPtr out (f . castPtr)
|
||||||
return out
|
return out
|
||||||
byteArrayLength = secureMemGetSize
|
|
||||||
withByteArray b f = withSecureMemPtr b (f . castPtr)
|
|
||||||
|
|
||||||
byteArrayAllocAndFreeze :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
|
byteArrayAllocAndFreeze :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
|
||||||
byteArrayAllocAndFreeze sz f = unsafeDoIO (byteArrayAlloc sz f)
|
byteArrayAllocAndFreeze sz f = unsafeDoIO (byteArrayAlloc sz f)
|
||||||
@ -72,7 +78,7 @@ empty = unsafeDoIO (byteArrayAlloc 0 $ \_ -> return ())
|
|||||||
-- | Create a xor of bytes between a and b.
|
-- | Create a xor of bytes between a and b.
|
||||||
--
|
--
|
||||||
-- the returns byte array is the size of the smallest input.
|
-- the returns byte array is the size of the smallest input.
|
||||||
byteArrayXor :: (ByteArray a, ByteArray b, ByteArray c) => a -> b -> c
|
byteArrayXor :: (ByteArrayAccess a, ByteArrayAccess b, ByteArray c) => a -> b -> c
|
||||||
byteArrayXor a b =
|
byteArrayXor a b =
|
||||||
byteArrayAllocAndFreeze n $ \pc ->
|
byteArrayAllocAndFreeze n $ \pc ->
|
||||||
withByteArray a $ \pa ->
|
withByteArray a $ \pa ->
|
||||||
@ -122,4 +128,5 @@ byteArrayToW64BE :: ByteArray bs => bs -> Int -> Word64
|
|||||||
byteArrayToW64BE bs ofs = unsafeDoIO $ withByteArray bs $ \p -> fromBE64 <$> peek (p `plusPtr` ofs)
|
byteArrayToW64BE bs ofs = unsafeDoIO $ withByteArray bs $ \p -> fromBE64 <$> peek (p `plusPtr` ofs)
|
||||||
|
|
||||||
-- move me elsewhere. not working properly for big endian machine, as it should be id
|
-- move me elsewhere. not working properly for big endian machine, as it should be id
|
||||||
|
fromBE64 :: Word64 -> Word64
|
||||||
fromBE64 = byteSwap64
|
fromBE64 = byteSwap64
|
||||||
|
|||||||
@ -92,6 +92,7 @@ data KATs = KATs
|
|||||||
|
|
||||||
defaultKATs = KATs [] [] [] [] [] []
|
defaultKATs = KATs [] [] [] [] [] []
|
||||||
|
|
||||||
|
{-
|
||||||
testECB (_, _, cipherInit) ecbEncrypt ecbDecrypt kats =
|
testECB (_, _, cipherInit) ecbEncrypt ecbDecrypt kats =
|
||||||
testGroup "ECB" (concatMap katTest (zip is kats) {- ++ propTests-})
|
testGroup "ECB" (concatMap katTest (zip is kats) {- ++ propTests-})
|
||||||
where katTest (i,d) =
|
where katTest (i,d) =
|
||||||
@ -145,6 +146,67 @@ testKatAEAD cipherInit aeadInit aeadAppendHeader aeadEncrypt aeadDecrypt aeadFin
|
|||||||
(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)
|
||||||
|
-}
|
||||||
|
|
||||||
|
testKATs :: BlockCipher cipher
|
||||||
|
=> KATs
|
||||||
|
-> cipher
|
||||||
|
-> TestTree
|
||||||
|
testKATs kats cipher = testGroup "KAT"
|
||||||
|
( maybeGroup makeECBTest "ECB" (kat_ECB kats)
|
||||||
|
++ maybeGroup makeCBCTest "CBC" (kat_CBC kats)
|
||||||
|
++ maybeGroup makeCFBTest "CFB" (kat_CFB kats)
|
||||||
|
++ maybeGroup makeCTRTest "CTR" (kat_CTR kats)
|
||||||
|
-- ++ maybeGroup makeXTSTest "XTS" (kat_XTS kats)
|
||||||
|
-- ++ maybeGroup makeAEADTest "AEAD" (kat_AEAD kats)
|
||||||
|
)
|
||||||
|
where makeECBTest i d =
|
||||||
|
[ testCase ("E" ++ i) (ecbEncrypt ctx (ecbPlaintext d) @?= ecbCiphertext d)
|
||||||
|
, testCase ("D" ++ i) (ecbDecrypt ctx (ecbCiphertext d) @?= ecbPlaintext d)
|
||||||
|
]
|
||||||
|
where ctx = cipherInit (cipherMakeKey cipher $ ecbKey d)
|
||||||
|
makeCBCTest i d =
|
||||||
|
[ testCase ("E" ++ i) (cbcEncrypt ctx iv (cbcPlaintext d) @?= cbcCiphertext d)
|
||||||
|
, testCase ("D" ++ i) (cbcDecrypt ctx iv (cbcCiphertext d) @?= cbcPlaintext d)
|
||||||
|
]
|
||||||
|
where ctx = cipherInit (cipherMakeKey cipher $ cbcKey d)
|
||||||
|
iv = cipherMakeIV cipher $ cbcIV d
|
||||||
|
makeCFBTest i d =
|
||||||
|
[ testCase ("E" ++ i) (cfbEncrypt ctx iv (cfbPlaintext d) @?= cfbCiphertext d)
|
||||||
|
, testCase ("D" ++ i) (cfbDecrypt ctx iv (cfbCiphertext d) @?= cfbPlaintext d)
|
||||||
|
]
|
||||||
|
where ctx = cipherInit (cipherMakeKey cipher $ cfbKey d)
|
||||||
|
iv = cipherMakeIV cipher $ cfbIV d
|
||||||
|
makeCTRTest i d =
|
||||||
|
[ testCase ("E" ++ i) (ctrCombine ctx iv (ctrPlaintext d) @?= ctrCiphertext d)
|
||||||
|
, testCase ("D" ++ i) (ctrCombine ctx iv (ctrCiphertext d) @?= ctrPlaintext d)
|
||||||
|
]
|
||||||
|
where ctx = cipherInit (cipherMakeKey cipher $ ctrKey d)
|
||||||
|
iv = cipherMakeIV cipher $ ctrIV d
|
||||||
|
{-
|
||||||
|
makeXTSTest i d =
|
||||||
|
[ 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)
|
||||||
|
ctx = (ctx1, ctx2)
|
||||||
|
iv = cipherMakeIV cipher $ xtsIV d
|
||||||
|
makeAEADTest i d =
|
||||||
|
[ testCase ("AE" ++ i) (etag @?= aeadTag d)
|
||||||
|
, testCase ("AD" ++ i) (dtag @?= 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)
|
||||||
|
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)
|
||||||
|
-}
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- Properties
|
-- Properties
|
||||||
@ -203,11 +265,11 @@ instance Show (CFB8Unit a) where
|
|||||||
instance Show (CTRUnit a) where
|
instance Show (CTRUnit a) where
|
||||||
show (CTRUnit key iv b) = "CTR(key=" ++ show key ++ ",iv=" ++ show (unPlaintext iv) ++ ",input=" ++ show b ++ ")"
|
show (CTRUnit key iv b) = "CTR(key=" ++ show key ++ ",iv=" ++ show (unPlaintext iv) ++ ",input=" ++ show b ++ ")"
|
||||||
instance Show (XTSUnit a) where
|
instance Show (XTSUnit a) where
|
||||||
show (XTSUnit key1 key2 iv b) = "XTS(key1=" ++ show (toBytes key1) ++ ",key2=" ++ show (toBytes key2) ++ ",iv=" ++ show (toBytes iv) ++ ",input=" ++ show b ++ ")"
|
show (XTSUnit key1 key2 iv b) = "XTS(key1=" ++ show key1 ++ ",key2=" ++ show key2 ++ ",iv=" ++ show (unPlaintext iv) ++ ",input=" ++ show b ++ ")"
|
||||||
instance Show (AEADUnit a) where
|
instance Show (AEADUnit a) where
|
||||||
show (AEADUnit key iv aad b) = "AEAD(key=" ++ show (toBytes key) ++ ",iv=" ++ show iv ++ ",aad=" ++ show (toBytes aad) ++ ",input=" ++ show b ++ ")"
|
show (AEADUnit key iv aad b) = "AEAD(key=" ++ show key ++ ",iv=" ++ show iv ++ ",aad=" ++ show (unPlaintext aad) ++ ",input=" ++ show b ++ ")"
|
||||||
instance Show (StreamUnit a) where
|
instance Show (StreamUnit a) where
|
||||||
show (StreamUnit key b) = "Stream(key=" ++ show (toBytes key) ++ ",input=" ++ show b ++ ")"
|
show (StreamUnit key b) = "Stream(key=" ++ show key ++ ",input=" ++ show b ++ ")"
|
||||||
|
|
||||||
-- | Generate an arbitrary valid key for a specific block cipher
|
-- | Generate an arbitrary valid key for a specific block cipher
|
||||||
generateKey :: Cipher a => Gen (Key a)
|
generateKey :: Cipher a => Gen (Key a)
|
||||||
@ -281,7 +343,7 @@ testBlockCipherBasic cipher = [ testProperty "ECB" ecbProp ]
|
|||||||
where ecbProp = toTests cipher
|
where ecbProp = toTests cipher
|
||||||
toTests :: BlockCipher a => a -> (ECBUnit a -> Bool)
|
toTests :: BlockCipher a => a -> (ECBUnit a -> Bool)
|
||||||
toTests _ = testProperty_ECB
|
toTests _ = testProperty_ECB
|
||||||
testProperty_ECB (ECBUnit (cipherInit -> ctx) (toBytes -> plaintext)) =
|
testProperty_ECB (ECBUnit (cipherInit -> ctx) (unPlaintext -> plaintext)) =
|
||||||
plaintext `assertEq` ecbDecrypt ctx (ecbEncrypt ctx plaintext)
|
plaintext `assertEq` ecbDecrypt ctx (ecbEncrypt ctx plaintext)
|
||||||
|
|
||||||
testBlockCipherModes :: BlockCipher a => a -> [TestTree]
|
testBlockCipherModes :: BlockCipher a => a -> [TestTree]
|
||||||
@ -300,18 +362,18 @@ testBlockCipherModes cipher =
|
|||||||
--,testProperty_CFB8
|
--,testProperty_CFB8
|
||||||
,testProperty_CTR
|
,testProperty_CTR
|
||||||
)
|
)
|
||||||
testProperty_CBC (CBCUnit (cipherInit -> ctx) testIV (toBytes -> plaintext)) =
|
testProperty_CBC (CBCUnit (cipherInit -> ctx) testIV (unPlaintext -> plaintext)) =
|
||||||
plaintext `assertEq` cbcDecrypt ctx testIV (cbcEncrypt ctx testIV plaintext)
|
plaintext `assertEq` cbcDecrypt ctx testIV (cbcEncrypt ctx testIV plaintext)
|
||||||
|
|
||||||
testProperty_CFB (CFBUnit (cipherInit -> ctx) testIV (toBytes -> plaintext)) =
|
testProperty_CFB (CFBUnit (cipherInit -> ctx) testIV (unPlaintext -> plaintext)) =
|
||||||
plaintext `assertEq` cfbDecrypt ctx testIV (cfbEncrypt ctx testIV plaintext)
|
plaintext `assertEq` cfbDecrypt ctx testIV (cfbEncrypt ctx testIV plaintext)
|
||||||
|
|
||||||
{-
|
{-
|
||||||
testProperty_CFB8 (CFB8Unit (cipherInit -> ctx) testIV (toBytes -> plaintext)) =
|
testProperty_CFB8 (CFB8Unit (cipherInit -> ctx) testIV (unPlaintext -> plaintext)) =
|
||||||
plaintext `assertEq` cfb8Decrypt ctx testIV (cfb8Encrypt ctx testIV plaintext)
|
plaintext `assertEq` cfb8Decrypt ctx testIV (cfb8Encrypt ctx testIV plaintext)
|
||||||
-}
|
-}
|
||||||
|
|
||||||
testProperty_CTR (CTRUnit (cipherInit -> ctx) testIV (toBytes -> plaintext)) =
|
testProperty_CTR (CTRUnit (cipherInit -> ctx) testIV (unPlaintext -> plaintext)) =
|
||||||
plaintext `assertEq` ctrCombine ctx testIV (ctrCombine ctx testIV plaintext)
|
plaintext `assertEq` ctrCombine ctx testIV (ctrCombine ctx testIV plaintext)
|
||||||
|
|
||||||
testBlockCipherAEAD :: BlockCipher a => a -> [TestTree]
|
testBlockCipherAEAD :: BlockCipher a => a -> [TestTree]
|
||||||
@ -325,7 +387,7 @@ testBlockCipherAEAD cipher =
|
|||||||
where aeadProp = toTests cipher
|
where aeadProp = toTests 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 (cipherInit -> ctx) testIV (toBytes -> aad) (toBytes -> plaintext)) =
|
testProperty_AEAD mode (AEADUnit (cipherInit -> ctx) testIV (unPlaintext -> aad) (unPlaintext -> plaintext)) =
|
||||||
case aeadInit mode ctx testIV of
|
case aeadInit mode ctx testIV of
|
||||||
Just iniAead ->
|
Just iniAead ->
|
||||||
let aead = aeadAppendHeader iniAead aad
|
let aead = aeadAppendHeader iniAead aad
|
||||||
@ -368,5 +430,18 @@ assertEq :: ByteString -> ByteString -> Bool
|
|||||||
assertEq b1 b2 | b1 /= b2 = error ("b1: " ++ show b1 ++ " b2: " ++ show b2)
|
assertEq b1 b2 | b1 /= b2 = error ("b1: " ++ show b1 ++ " b2: " ++ show b2)
|
||||||
| otherwise = True
|
| otherwise = True
|
||||||
|
|
||||||
|
cipherMakeKey :: Cipher cipher => cipher -> ByteString -> Key cipher
|
||||||
|
cipherMakeKey c bs = bs
|
||||||
|
|
||||||
|
cipherMakeIV :: BlockCipher cipher => cipher -> ByteString -> IV cipher
|
||||||
|
cipherMakeIV _ bs = fromJust $ makeIV bs
|
||||||
|
|
||||||
|
maybeGroup :: (String -> t -> [TestTree]) -> TestName -> [t] -> [TestTree]
|
||||||
|
maybeGroup mkTest groupName l
|
||||||
|
| null l = []
|
||||||
|
| otherwise = [testGroup groupName (concatMap (\(i, d) -> mkTest (show i) d) $ zip nbs l)]
|
||||||
|
where nbs :: [Int]
|
||||||
|
nbs = [0..]
|
||||||
|
|
||||||
is :: [Int]
|
is :: [Int]
|
||||||
is = [1..]
|
is = [1..]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user