|
@@ -0,0 +1,91 @@
|
|
|
+{-# LANGUAGE OverloadedStrings #-}
|
|
|
+
|
|
|
+module RoundTrips (tests) where
|
|
|
+
|
|
|
+import Distribution.TestSuite
|
|
|
+import Base (simpleTest)
|
|
|
+import Data.ByteString (ByteString)
|
|
|
+import qualified Data.ByteString.Lazy as LBS
|
|
|
+import qualified Data.ByteString.Lazy.Char8 as C8
|
|
|
+import qualified Data.ByteString.Char8 as SC8
|
|
|
+
|
|
|
+import Crypto.Error
|
|
|
+import Crypto.Chunked
|
|
|
+import Crypto.ChunkedAlgorithms
|
|
|
+
|
|
|
+tests :: IO [Test]
|
|
|
+tests = return [
|
|
|
+ simpleTest "Check MAC size" checkMacSize,
|
|
|
+ simpleTest "Good round trip" goodRoundTrip,
|
|
|
+ simpleTest "Auth error" authError
|
|
|
+ ]
|
|
|
+
|
|
|
+testKey :: ByteString
|
|
|
+testKey = SC8.pack "01234567890123456789012345678901"
|
|
|
+testNonce :: ByteString
|
|
|
+testNonce = SC8.pack "012345678901"
|
|
|
+testString :: LBS.ByteString
|
|
|
+testString = C8.pack $ unlines [
|
|
|
+ "ChaCha20 and Poly1305 for IETF Protocols",
|
|
|
+ "Abstract",
|
|
|
+ "This document defines the ChaCha20 stream cipher as well as the use",
|
|
|
+ "of the Poly1305 authenticator, both as stand-alone algorithms and as",
|
|
|
+ "a combined mode, or Authenticated Encryption with Associated Data",
|
|
|
+ "(AEAD) algorithm.",
|
|
|
+ "This document does not introduce any new crypto, but is meant to",
|
|
|
+ "serve as a stable reference and an implementation guide. It is a",
|
|
|
+ "product of the Crypto Forum Research Group (CFRG).",
|
|
|
+ "Status of This Memo",
|
|
|
+ "This document is not an Internet Standards Track specification; it is",
|
|
|
+ "published for informational purposes.",
|
|
|
+ "This document is a product of the Internet Research Task Force",
|
|
|
+ "(IRTF). The IRTF publishes the results of Internet-related research",
|
|
|
+ "and development activities. These results might not be suitable for",
|
|
|
+ "deployment. This RFC represents the consensus of the Crypto Forum",
|
|
|
+ "Research Group of the Internet Research Task Force (IRTF). Documents",
|
|
|
+ "approved for publication by the IRSG are not a candidate for any",
|
|
|
+ "level of Internet Standard; see Section 2 of RFC 5741.",
|
|
|
+ "Information about the current status of this document, any errata,",
|
|
|
+ "and how to provide feedback on it may be obtained at",
|
|
|
+ "http://www.rfc-editor.org/info/rfc7539."
|
|
|
+ ]
|
|
|
+
|
|
|
+checkMacSize :: IO Progress
|
|
|
+checkMacSize = do
|
|
|
+ let algo = chunkedChaChaPoly1305 32 testKey
|
|
|
+ (enc, fails1) = encrypt algo testNonce 0 testString
|
|
|
+ case sequence fails1 of
|
|
|
+ CryptoFailed e -> return . Finished . Fail $ "Crypto failed: " ++ show e
|
|
|
+ CryptoPassed _ -> let
|
|
|
+ nchunks = LBS.length testString `div` plainSize algo
|
|
|
+ modchunks = LBS.length testString `mod` plainSize algo
|
|
|
+ expsize = nchunks * encryptedSize algo + modchunks + (encryptedSize algo - plainSize algo)
|
|
|
+ in if expsize == LBS.length enc
|
|
|
+ then return . Finished $ Pass
|
|
|
+ else return . Finished . Fail $ "Sizes mismatch. Original size is " ++ show (LBS.length testString) ++
|
|
|
+ " encrypted text size is " ++ show (LBS.length enc) ++ " extimated size is " ++ show expsize
|
|
|
+
|
|
|
+goodRoundTrip :: IO Progress
|
|
|
+goodRoundTrip = do
|
|
|
+ let algo = chunkedChaChaPoly1305 32 testKey
|
|
|
+ (enc, fails1) = encrypt algo testNonce 0 testString
|
|
|
+ (dec, fails2) = decrypt algo testNonce 0 enc
|
|
|
+ case sequence fails1 >> sequence fails2 of
|
|
|
+ CryptoPassed _ -> if dec == testString
|
|
|
+ then return . Finished $ Pass
|
|
|
+ else return . Finished . Fail $ "Text differs: " ++ C8.unpack dec
|
|
|
+ CryptoFailed e -> return . Finished . Fail $ "Crypto failed: " ++ show e
|
|
|
+
|
|
|
+authError :: IO Progress
|
|
|
+authError = do
|
|
|
+ let algo = chunkedChaChaPoly1305 32 testKey
|
|
|
+ (enc, fails1) = encrypt algo testNonce 0 testString
|
|
|
+ case LBS.uncons enc of
|
|
|
+ Nothing -> return . Finished . Fail $ "Empty encrypted text!"
|
|
|
+ Just (t, tt) -> do
|
|
|
+ let enc' = LBS.cons (t+1) tt
|
|
|
+ (dec, fails2) = decrypt algo testNonce 0 enc'
|
|
|
+ case sequence fails1 >> sequence fails2 of
|
|
|
+ CryptoFailed CryptoError_MacKeyInvalid -> return . Finished $ Pass
|
|
|
+ CryptoFailed e -> return . Finished . Fail $ "Crypto failed: " ++ show e
|
|
|
+ CryptoPassed _ -> return . Finished . Fail $ "Got decrypted text: " ++ C8.unpack dec
|