packages feed

cacophony-0.4.0: benchmarks/bench.hs

{-# LANGUAGE OverloadedStrings, RankNTypes, ScopedTypeVariables #-}
module Main where

import Control.DeepSeq   (($!!))
import Control.Exception (handle)
import Criterion.Main
import Data.Proxy

import Crypto.Noise.Cipher
import Crypto.Noise.Cipher.ChaChaPoly1305
import Crypto.Noise.Curve
import Crypto.Noise.Curve.Curve25519
import Crypto.Noise.Handshake
import Crypto.Noise.Hash
import Crypto.Noise.Hash.SHA256
import Crypto.Noise.Types

import HandshakeStates
import Instances()

data HandshakeType c d h =
    NoiseNN
  | NoiseKN
  | NoiseNK
  | NoiseKK
  | NoiseNE
  | NoiseKE
  | NoiseNX
  | NoiseKXi
  | NoiseXN
  | NoiseIN
  | NoiseXK
  | NoiseIK
  | NoiseXE
  | NoiseIE
  | NoiseXX
  | NoiseIX
  | NoiseN
  | NoiseK
  | NoiseX

is25519 :: KeyPair Curve25519
is25519 = curveBytesToPair . bsToSB' $ "I\f\232\218A\210\230\147\FS\222\167\v}l\243!\168.\ESC\t\SYN\"\169\179A`\DC28\211\169tC"

rs25519 :: KeyPair Curve25519
rs25519 = curveBytesToPair . bsToSB' $ "\ETB\157\&7\DC2\252\NUL\148\172\148\133\218\207\&8\221y\144\209\168FX\224Ser_\178|\153.\FSg&"

re25519 :: KeyPair Curve25519
re25519 = curveBytesToPair . bsToSB' $ "<\231\151\151\180\217\146\DLEI}\160N\163iKc\162\210Y\168R\213\206&gm\169r\SUB[\\'"

mkHandshakes :: forall c d h proxy. (Cipher c, Curve d, Hash h)
             => HandshakeKeys d
             -> HandshakeKeys d
             -> proxy (c, h)
             -> [Benchmark]
mkHandshakes ihks rhks _ =
  let nni, nnr, kni, knr, nki, nkr, kki, kkr, nei, ner, kei, ker, nxi, nxr,
        kxi, kxr, xni, xnr, ini, inr, xki, xkr, iki, ikr, xei, xer, iei, ier,
        xxi, xxr, ixi, ixr, ni, nr, ki, kr, xi, xr :: HandshakeState c d h
      nni = noiseNNIHS ihks
      nnr = noiseNNRHS rhks
      kni = noiseKNIHS ihks
      knr = noiseKNRHS rhks
      nki = noiseNKIHS ihks
      nkr = noiseNKRHS rhks
      kki = noiseKKIHS ihks
      kkr = noiseKKRHS rhks
      nei = noiseNEIHS ihks
      ner = noiseNERHS rhks
      kei = noiseKEIHS ihks
      ker = noiseKERHS rhks
      nxi = noiseNXIHS ihks
      nxr = noiseNXRHS rhks
      kxi = noiseKXIHS ihks
      kxr = noiseKXRHS rhks
      xni = noiseXNIHS ihks
      xnr = noiseXNRHS rhks
      ini = noiseINIHS ihks
      inr = noiseINRHS rhks
      xki = noiseXKIHS ihks
      xkr = noiseXKRHS rhks
      iki = noiseIKIHS ihks
      ikr = noiseIKRHS rhks
      xei = noiseXEIHS ihks
      xer = noiseXERHS rhks
      iei = noiseIEIHS ihks
      ier = noiseIERHS rhks
      xxi = noiseXXIHS ihks
      xxr = noiseXXRHS rhks
      ixi = noiseIXIHS ihks
      ixr = noiseIXRHS rhks
      ni  = noiseNIHS  ihks
      nr  = noiseNRHS  rhks
      ki  = noiseKIHS  ihks
      kr  = noiseKRHS  rhks
      xi  = noiseXIHS  ihks
      xr  = noiseXRHS  rhks in

   [ bench "NoisePSK_NN" $ whnfIO (twoMessage   nni nnr)
   , bench "NoisePSK_KN" $ whnfIO (twoMessage   kni knr)
   , bench "NoisePSK_NK" $ whnfIO (twoMessage   nki nkr)
   , bench "NoisePSK_KK" $ whnfIO (twoMessage   kki kkr)
   , bench "NoisePSK_NE" $ whnfIO (twoMessage   nei ner)
   , bench "NoisePSK_KE" $ whnfIO (twoMessage   kei ker)
   , bench "NoisePSK_NX" $ whnfIO (twoMessage   nxi nxr)
   , bench "NoisePSK_KX" $ whnfIO (twoMessage   kxi kxr)
   , bench "NoisePSK_XN" $ whnfIO (threeMessage xni xnr)
   , bench "NoisePSK_IN" $ whnfIO (twoMessage   ini inr)
   , bench "NoisePSK_XK" $ whnfIO (threeMessage xki xkr)
   , bench "NoisePSK_IK" $ whnfIO (twoMessage   iki ikr)
   , bench "NoisePSK_XE" $ whnfIO (threeMessage xei xer)
   , bench "NoisePSK_IE" $ whnfIO (twoMessage   iei ier)
   , bench "NoisePSK_XX" $ whnfIO (threeMessage xxi xxr)
   , bench "NoisePSK_IX" $ whnfIO (twoMessage   ixi ixr)
   , bench "NoisePSK_N"  $ whnfIO (oneMessage   ni  nr )
   , bench "NoisePSK_K"  $ whnfIO (oneMessage   ki  kr )
   , bench "NoisePSK_X"  $ whnfIO (oneMessage   xi  xr )
   ]

oneMessage :: (Cipher c, Curve d, Hash h)
           => HandshakeState c d h
           -> HandshakeState c d h
           -> IO Plaintext
oneMessage ihs rhs = handle (\(_ :: NoiseException) -> return "") $ do
  (aliceToBob1, csAlice1, _) <- writeMessageFinal ihs ""
  let (_, csBob1, _) = readMessageFinal rhs aliceToBob1
      x = decrypt csBob1 . encrypt csAlice1 $ ""

  return $!! x

  where
      encrypt cs p  = fst $ encryptPayload p  cs
      decrypt cs ct = fst $ decryptPayload ct cs

twoMessage :: (Cipher c, Curve d, Hash h)
           => HandshakeState c d h
           -> HandshakeState c d h
           -> IO (Plaintext, Plaintext)
twoMessage ihs rhs = handle (\(_ :: NoiseException) -> return ("", "")) $ do
  (aliceToBob1, ihs') <- writeMessage ihs ""
  let (_, rhs') = readMessage rhs aliceToBob1

  (bobToAlice1, csBob1, csBob2) <- writeMessageFinal rhs' ""
  let (_, csAlice1, csAlice2) = readMessageFinal ihs' bobToAlice1
      x = decrypt csBob1 . encrypt csAlice1 $ ""
      y = decrypt csAlice2 . encrypt csBob2 $ ""

  return $!! (x, y)

  where
      encrypt cs p  = fst $ encryptPayload p  cs
      decrypt cs ct = fst $ decryptPayload ct cs

threeMessage :: (Cipher c, Curve d, Hash h)
             => HandshakeState c d h
             -> HandshakeState c d h
             -> IO (Plaintext, Plaintext)
threeMessage ihs rhs = handle (\(_ :: NoiseException) -> return ("", "")) $ do
  (aliceToBob1, ihs') <- writeMessage ihs ""
  let (_, rhs') = readMessage rhs aliceToBob1

  (bobToAlice1, rhs'') <- writeMessage rhs' ""
  let (_, ihs'') = readMessage ihs' bobToAlice1

  (aliceToBob2, csAlice1, csAlice2) <- writeMessageFinal ihs'' ""
  let (_, csBob1, csBob2) = readMessageFinal rhs'' aliceToBob2
      x = decrypt csBob1 . encrypt csAlice1 $ ""
      y = decrypt csAlice2 . encrypt csBob2 $ ""

  return $!! (x, y)

  where
      encrypt cs p  = fst $ encryptPayload p  cs
      decrypt cs ct = fst $ decryptPayload ct cs

main :: IO ()
main =
  let p    = Just "cacophony"
      p'   = Just "not cacophony"
      hks  = HandshakeKeys p  is25519 rs25519 re25519
      hks' = HandshakeKeys p' is25519 rs25519 re25519 in
  defaultMain
  [ bgroup "Curve25519-ChaChaPoly1305-SHA256"
    [ bgroup "with valid PSK"
      (mkHandshakes hks hks (Proxy :: Proxy (ChaChaPoly1305, SHA256)))
    , bgroup "with invalid PSK"
      (mkHandshakes hks hks' (Proxy :: Proxy (ChaChaPoly1305, SHA256)))
    ]
  ]