botan-low-0.0.2.0: test/Botan/Low/MACSpec.hs
module Main where
import Test.Prelude
import Botan.Bindings.MAC
import Botan.Low.MAC
import Botan.Low.RNG
-- NOTE: Full testing of all algorithms will require botan ADT types instead
-- of names, to be able to query for acceptable key and nonce parameters
-- nonceMACs :: [(MACName, Maybe Int)]
-- nonceMACs = concat
-- [ [ "CMAC(" <> bc <> ")" | bc <- allBlockCiphers ]
-- , [ "GMAC(" <> bc <> ")" | bc <- allBlockCiphers ]
-- , [ "CBC-MAC(" <> bc <> ")" | bc <- allBlockCiphers ]
-- ]
-- macs :: [(MACName, Maybe Int)]
-- macs = concat
-- [ nonceMACs
-- , [ "HMAC(" <> h <> ")" | h <- hashes ]
-- , [ "Poly1305", "SipHash(2,4)", "X9.19-MAC" ]
-- ]
macs :: [MACName]
macs = fmap fst macsAndNonceSzs
macsAndNonceSzs :: [(MACName, Int)]
macsAndNonceSzs =
[ ("CMAC(AES-256)", 0)
, ("GMAC(AES-256)", 16)
-- , ("CBC-MAC(AES-256)", 16) -- Not supported
, ("HMAC(SHA-3)", 0)
, ("Poly1305", 0)
, ("SipHash(2,4)", 0)
, ("X9.19-MAC", 0)
]
message :: ByteString
message = "Fee fi fo fum! I smell the blood of an Englishman!"
main :: IO ()
main = hspec $ testSuite macsAndNonceSzs (chars . fst) $ \ (h,nonceSz) -> do
it "can initialize a mac context" $ do
ctx <- macInit h
pass
it "has a name" $ do
ctx <- macInit h
name <- macName ctx
pass
it "has an output length" $ do
ctx <- macInit h
olen <- macOutputLength ctx
pass
-- it "can copy the internal state" $ do
-- ctx <- macInit h
-- -- TODO: Populate with state and actually prove
-- ctx' <- macCopyState ctx
-- pass
it "has a key spec" $ do
ctx <- macInit h
(_,_,_) <- macGetKeyspec ctx
pass
it "can set the key" $ do
ctx <- macInit h
(_,mx,_) <- macGetKeyspec ctx
k <- systemRNGGet mx
macSetKey ctx k
pass
-- it "has a nonce spec" $ do
it "can set the nonce" $ do
if nonceSz > 0
then do
ctx <- macInit h
(_,mx,_) <- macGetKeyspec ctx
k <- systemRNGGet mx
macSetKey ctx k
n <- systemRNGGet nonceSz
macSetNonce ctx n
else pass
it "can clear all internal state" $ do
ctx <- macInit h
(_,mx,_) <- macGetKeyspec ctx
k <- systemRNGGet mx
macSetKey ctx k
if nonceSz > 0
then do
n <- systemRNGGet nonceSz
macSetNonce ctx n
else pass
-- TODO: Populate with state and actually prove
macClear ctx
pass
it "can update the internal state with a single message block" $ do
ctx <- macInit h
(_,mx,_) <- macGetKeyspec ctx
k <- systemRNGGet mx
macSetKey ctx k
if nonceSz > 0
then do
n <- systemRNGGet nonceSz
macSetNonce ctx n
else pass
macUpdate ctx message
pass
it "can update the internal state with multiple message blocks" $ do
ctx <- macInit h
(_,mx,_) <- macGetKeyspec ctx
k <- systemRNGGet mx
macSetKey ctx k
if nonceSz > 0
then do
n <- systemRNGGet nonceSz
macSetNonce ctx n
else pass
forM_ (splitBlocks 4 message) $ macUpdate ctx
pass
it "can finalize a digest" $ do
ctx <- macInit h
(_,mx,_) <- macGetKeyspec ctx
k <- systemRNGGet mx
macSetKey ctx k
if nonceSz > 0
then do
n <- systemRNGGet nonceSz
macSetNonce ctx n
else pass
macUpdate ctx message
d <- macFinal ctx
pass