module Botan.Low.HOTP
(
HOTP(..)
, HOTPHashName(..)
, HOTPCounter(..)
, HOTPCode(..)
, withHOTP
, hotpInit
, hotpDestroy
, hotpGenerate
, hotpCheck
, pattern HOTP_SHA1
, pattern HOTP_SHA256
, pattern HOTP_SHA512
, hotpHashes
) where
import qualified Data.ByteString as ByteString
import Botan.Bindings.HOTP
import Botan.Low.Hash
import Botan.Low.Error
import Botan.Low.Make
import Botan.Low.Prelude
import Botan.Low.Remake
newtype HOTP = MkHOTP { HOTP -> ForeignPtr BotanHOTPStruct
getHOTPForeignPtr :: ForeignPtr BotanHOTPStruct }
newHOTP :: BotanHOTP -> IO HOTP
withHOTP :: HOTP -> (BotanHOTP -> IO a) -> IO a
hotpDestroy :: HOTP -> IO ()
createHOTP :: (Ptr BotanHOTP -> IO CInt) -> IO HOTP
(BotanHOTP -> IO HOTP
newHOTP, HOTP -> (BotanHOTP -> IO a) -> IO a
withHOTP, HOTP -> IO ()
hotpDestroy, (Ptr BotanHOTP -> IO CInt) -> IO HOTP
createHOTP, (Ptr BotanHOTP -> Ptr CSize -> IO CInt) -> IO [HOTP]
_)
= (Ptr BotanHOTPStruct -> BotanHOTP)
-> (BotanHOTP -> Ptr BotanHOTPStruct)
-> (ForeignPtr BotanHOTPStruct -> HOTP)
-> (HOTP -> ForeignPtr BotanHOTPStruct)
-> FinalizerPtr BotanHOTPStruct
-> (BotanHOTP -> IO HOTP, HOTP -> (BotanHOTP -> IO a) -> IO a,
HOTP -> IO (), (Ptr BotanHOTP -> IO CInt) -> IO HOTP,
(Ptr BotanHOTP -> Ptr CSize -> IO CInt) -> IO [HOTP])
forall botan struct object a.
Storable botan =>
(Ptr struct -> botan)
-> (botan -> Ptr struct)
-> (ForeignPtr struct -> object)
-> (object -> ForeignPtr struct)
-> FinalizerPtr struct
-> (botan -> IO object, object -> (botan -> IO a) -> IO a,
object -> IO (), (Ptr botan -> IO CInt) -> IO object,
(Ptr botan -> Ptr CSize -> IO CInt) -> IO [object])
mkBindings
Ptr BotanHOTPStruct -> BotanHOTP
MkBotanHOTP BotanHOTP -> Ptr BotanHOTPStruct
runBotanHOTP
ForeignPtr BotanHOTPStruct -> HOTP
MkHOTP HOTP -> ForeignPtr BotanHOTPStruct
getHOTPForeignPtr
FinalizerPtr BotanHOTPStruct
botan_hotp_destroy
type HOTPHashName = HashName
pattern HOTP_SHA1
, HOTP_SHA256
, HOTP_SHA512
:: HOTPHashName
pattern $mHOTP_SHA1 :: forall {r}. HOTPHashName -> ((# #) -> r) -> ((# #) -> r) -> r
$bHOTP_SHA1 :: HOTPHashName
HOTP_SHA1 = SHA1
pattern $mHOTP_SHA256 :: forall {r}. HOTPHashName -> ((# #) -> r) -> ((# #) -> r) -> r
$bHOTP_SHA256 :: HOTPHashName
HOTP_SHA256 = SHA256
pattern $mHOTP_SHA512 :: forall {r}. HOTPHashName -> ((# #) -> r) -> ((# #) -> r) -> r
$bHOTP_SHA512 :: HOTPHashName
HOTP_SHA512 = SHA512
hotpHashes :: [HOTPHashName]
hotpHashes =
[ HOTPHashName
HOTP_SHA1
, HOTPHashName
HOTP_SHA256
, HOTPHashName
HOTP_SHA512
]
type HOTPCounter = Word64
type HOTPCode = Word32
hotpInit
:: ByteString
-> HashName
-> Int
-> IO HOTP
hotpInit :: HOTPHashName -> HOTPHashName -> Int -> IO HOTP
hotpInit HOTPHashName
key HOTPHashName
algo Int
digits = HOTPHashName -> (Ptr Word8 -> CSize -> IO HOTP) -> IO HOTP
forall byte a. HOTPHashName -> (Ptr byte -> CSize -> IO a) -> IO a
asBytesLen HOTPHashName
key ((Ptr Word8 -> CSize -> IO HOTP) -> IO HOTP)
-> (Ptr Word8 -> CSize -> IO HOTP) -> IO HOTP
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
keyPtr CSize
keyLen -> do
HOTPHashName -> (Ptr CChar -> IO HOTP) -> IO HOTP
forall a. HOTPHashName -> (Ptr CChar -> IO a) -> IO a
asCString HOTPHashName
algo ((Ptr CChar -> IO HOTP) -> IO HOTP)
-> (Ptr CChar -> IO HOTP) -> IO HOTP
forall a b. (a -> b) -> a -> b
$ \ Ptr CChar
algoPtr -> do
(Ptr BotanHOTP -> IO CInt) -> IO HOTP
createHOTP ((Ptr BotanHOTP -> IO CInt) -> IO HOTP)
-> (Ptr BotanHOTP -> IO CInt) -> IO HOTP
forall a b. (a -> b) -> a -> b
$ \ Ptr BotanHOTP
out -> Ptr BotanHOTP
-> ConstPtr Word8 -> CSize -> ConstPtr CChar -> CSize -> IO CInt
botan_hotp_init
Ptr BotanHOTP
out
(Ptr Word8 -> ConstPtr Word8
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr Word8
keyPtr)
CSize
keyLen
(Ptr CChar -> ConstPtr CChar
forall a. Ptr a -> ConstPtr a
ConstPtr Ptr CChar
algoPtr)
(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
digits)
withHOTPInit :: ByteString -> ByteString -> Int -> (HOTP -> IO a) -> IO a
withHOTPInit :: forall a.
HOTPHashName -> HOTPHashName -> Int -> (HOTP -> IO a) -> IO a
withHOTPInit = (HOTPHashName -> HOTPHashName -> Int -> IO HOTP)
-> (HOTP -> IO ())
-> HOTPHashName
-> HOTPHashName
-> Int
-> (HOTP -> IO a)
-> IO a
forall x y z t a.
(x -> y -> z -> IO t)
-> (t -> IO ()) -> x -> y -> z -> (t -> IO a) -> IO a
mkWithTemp3 HOTPHashName -> HOTPHashName -> Int -> IO HOTP
hotpInit HOTP -> IO ()
hotpDestroy
hotpGenerate
:: HOTP
-> HOTPCounter
-> IO HOTPCode
hotpGenerate :: HOTP -> Word64 -> IO Word32
hotpGenerate HOTP
hotp Word64
counter = HOTP -> (BotanHOTP -> IO Word32) -> IO Word32
forall a. HOTP -> (BotanHOTP -> IO a) -> IO a
withHOTP HOTP
hotp ((BotanHOTP -> IO Word32) -> IO Word32)
-> (BotanHOTP -> IO Word32) -> IO Word32
forall a b. (a -> b) -> a -> b
$ \ BotanHOTP
hotpPtr -> do
(Ptr Word32 -> IO Word32) -> IO Word32
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Word32 -> IO Word32) -> IO Word32)
-> (Ptr Word32 -> IO Word32) -> IO Word32
forall a b. (a -> b) -> a -> b
$ \ Ptr Word32
outPtr -> do
HasCallStack => IO CInt -> IO CInt
IO CInt -> IO CInt
throwBotanIfNegative (IO CInt -> IO CInt) -> IO CInt -> IO CInt
forall a b. (a -> b) -> a -> b
$ BotanHOTP -> Ptr Word32 -> Word64 -> IO CInt
botan_hotp_generate BotanHOTP
hotpPtr Ptr Word32
outPtr Word64
counter
Ptr Word32 -> IO Word32
forall a. Storable a => Ptr a -> IO a
peek Ptr Word32
outPtr
hotpCheck
:: HOTP
-> HOTPCode
-> HOTPCounter
-> Int
-> IO (Bool, HOTPCounter)
hotpCheck :: HOTP -> Word32 -> Word64 -> Int -> IO (Bool, Word64)
hotpCheck HOTP
hotp Word32
code Word64
counter Int
resync = HOTP -> (BotanHOTP -> IO (Bool, Word64)) -> IO (Bool, Word64)
forall a. HOTP -> (BotanHOTP -> IO a) -> IO a
withHOTP HOTP
hotp ((BotanHOTP -> IO (Bool, Word64)) -> IO (Bool, Word64))
-> (BotanHOTP -> IO (Bool, Word64)) -> IO (Bool, Word64)
forall a b. (a -> b) -> a -> b
$ \ BotanHOTP
hotpPtr -> do
(Ptr Word64 -> IO (Bool, Word64)) -> IO (Bool, Word64)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Word64 -> IO (Bool, Word64)) -> IO (Bool, Word64))
-> (Ptr Word64 -> IO (Bool, Word64)) -> IO (Bool, Word64)
forall a b. (a -> b) -> a -> b
$ \ Ptr Word64
outPtr -> do
Bool
valid <- HasCallStack => IO CInt -> IO Bool
IO CInt -> IO Bool
throwBotanCatchingSuccess (IO CInt -> IO Bool) -> IO CInt -> IO Bool
forall a b. (a -> b) -> a -> b
$ BotanHOTP -> Ptr Word64 -> Word32 -> Word64 -> CSize -> IO CInt
botan_hotp_check BotanHOTP
hotpPtr Ptr Word64
outPtr Word32
code Word64
counter (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
resync)
Word64
nextCounter <- Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek Ptr Word64
outPtr
(Bool, Word64) -> IO (Bool, Word64)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
valid, Word64
nextCounter)