module Crypto.Threefish.UBI where
import Data.Word
import Data.Bits
import Crypto.Threefish.Common
data BlockType
= Key
| Config
| Personalization
| PublicKey
| KeyIdentifier
| Nonce
| Message
| Output
type2w64 :: BlockType -> Word64
type2w64 Key = 0
type2w64 Config = 4
type2w64 Personalization = 8
type2w64 PublicKey = 12
type2w64 KeyIdentifier = 16
type2w64 Nonce = 20
type2w64 Message = 48
type2w64 Output = 63
type2int :: BlockType -> Int
type2int Key = 0
type2int Config = 4
type2int Personalization = 8
type2int PublicKey = 12
type2int KeyIdentifier = 16
type2int Nonce = 20
type2int Message = 48
type2int Output = 63
newTweak :: BlockType -> Tweak
newTweak t = setType t $ setFirst True $ Tweak 0 0
setType :: BlockType -> Tweak -> Tweak
setType t (Tweak lo hi) =
Tweak lo ((type2w64 t `shiftL` 56) .|. (hi .&. zeroType))
where
zeroType = complement (63 `shiftL` 56)
setFirst :: Bool -> Tweak -> Tweak
setFirst set (Tweak lo hi) = Tweak lo ((if set then setBit else clearBit) hi 62)
setLast :: Bool -> Tweak -> Tweak
setLast set (Tweak lo hi) = Tweak lo ((if set then setBit else clearBit) hi 63)
addBytes :: Word64 -> Tweak -> Tweak
addBytes bs (Tweak lo hi) = Tweak (lo + bs) hi
configTweak :: Tweak
configTweak = setFirst True $ setLast True $ newTweak Config