module Botan.HOTP where

import qualified Data.ByteString as ByteString

import qualified Botan.Low.HOTP as Low

import Botan.Hash

import Botan.Prelude

-- TODO: Package the ctx with counter?
-- Low HOTPCtx does not mutate, so it should
--  be copyable.

type MutableHOTP = Low.HOTP

data HOTP
    = HOTP_SHA1
    | HOTP_SHA256
    | HOTP_SHA512

hotpHash :: HOTP -> Hash
hotpHash :: HOTP -> Hash
hotpHash HOTP
HOTP_SHA1 = Hash
SHA1
hotpHash HOTP
HOTP_SHA256 = Hash
SHA256
hotpHash HOTP
HOTP_SHA512 = Hash
SHA512

hotpAlgo :: HOTP -> Low.HOTPHashName
hotpAlgo :: HOTP -> HOTPHashName
hotpAlgo = Hash -> HOTPHashName
hashName (Hash -> HOTPHashName) -> (HOTP -> Hash) -> HOTP -> HOTPHashName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HOTP -> Hash
hotpHash

type HOTPKey = ByteString

-- TODO: Bring in MVar to capture everything
data HOTPCtx
    = HOTPCtx
    { HOTPCtx -> HOTP
hotpCtx       :: Low.HOTP
    , HOTPCtx -> HOTPCounter
hotpCounter   :: Low.HOTPCounter
    , HOTPCtx -> Int
hotpResync    :: Int
    }

data HOTPLength
    = Short
    | Long

hotpLength :: HOTPLength -> Int
hotpLength :: HOTPLength -> Int
hotpLength HOTPLength
Short = Int
6
hotpLength HOTPLength
Long = Int
8

newHOTP :: HOTP -> HOTPLength -> Int -> ByteString -> IO HOTPCtx
newHOTP :: HOTP -> HOTPLength -> Int -> HOTPHashName -> IO HOTPCtx
newHOTP HOTP
hotp HOTPLength
len Int
resync HOTPHashName
key = do
    HOTP
ctx <- HOTPHashName -> HOTPHashName -> Int -> IO HOTP
Low.hotpInit HOTPHashName
key (HOTP -> HOTPHashName
hotpAlgo HOTP
hotp) (HOTPLength -> Int
hotpLength HOTPLength
len)
    HOTPCtx -> IO HOTPCtx
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (HOTPCtx -> IO HOTPCtx) -> HOTPCtx -> IO HOTPCtx
forall a b. (a -> b) -> a -> b
$ HOTPCtx
        { hotpCtx :: HOTP
hotpCtx = HOTP
ctx
        , hotpCounter :: HOTPCounter
hotpCounter = HOTPCounter
0
        , hotpResync :: Int
hotpResync = Int
resync
        }

hotpGenerate :: HOTPCtx -> IO Low.HOTPCode
hotpGenerate :: HOTPCtx -> IO HOTPCode
hotpGenerate = HOTPCtx -> IO HOTPCode
forall a. HasCallStack => a
undefined

hotpCheck :: HOTPCtx -> Low.HOTPCode -> IO Bool
hotpCheck :: HOTPCtx -> HOTPCode -> IO Bool
hotpCheck = HOTPCtx -> HOTPCode -> IO Bool
forall a. HasCallStack => a
undefined


-- NOTE: Digits should be 6-8
hotpCtxInit :: ByteString -> ByteString -> Int -> IO HOTPCtx
hotpCtxInit :: HOTPHashName -> HOTPHashName -> Int -> IO HOTPCtx
hotpCtxInit HOTPHashName
key HOTPHashName
algo Int
digits = IO HOTPCtx
forall a. HasCallStack => a
undefined

hotpCtxGenerate :: HOTPCtx -> Low.HOTPCounter -> (Low.HOTPCode, HOTPCtx)
hotpCtxGenerate :: HOTPCtx -> HOTPCounter -> (HOTPCode, HOTPCtx)
hotpCtxGenerate HOTPCtx
hotp HOTPCounter
counter = (HOTPCode, HOTPCtx)
forall a. HasCallStack => a
undefined

-- NOTE:
--      "Returns a pair of (is_valid,next_counter_to_use). If the OTP is
--      invalid then always returns (false,starting_counter), since the
--      last successful authentication counter has not changed. "
-- NOTE: "Depending on the environment a resync_range of 3 to 10 might be appropriate."
hotpCtxCheck :: HOTPCtx -> Low.HOTPCode -> Low.HOTPCounter -> Int -> (Bool, Low.HOTPCounter)
hotpCtxCheck :: HOTPCtx -> HOTPCode -> HOTPCounter -> Int -> (Bool, HOTPCounter)
hotpCtxCheck HOTPCtx
hotp HOTPCode
code HOTPCounter
counter Int
resync = (Bool, HOTPCounter)
forall a. HasCallStack => a
undefined