├── notes ├── .gitignore └── roadmap.org ├── tests ├── Spec.hs ├── comparative │ ├── Main.hs │ ├── Digest │ │ ├── Sha256Spec.hs │ │ ├── Sha512Spec.hs │ │ └── Blake2bSpec.hs │ ├── Digest.hs │ ├── AuthEncrypt │ │ └── ChaCha20Poly1305Spec.hs │ ├── Compare.hs │ ├── Encrypt │ │ └── ChaCha20Spec.hs │ ├── AuthEncrypt.hs │ └── Encrypt.hs ├── prgquality.sh ├── entropyquality.sh ├── standard-test-vectors │ └── blake2 │ │ └── url ├── core │ └── Tests │ │ ├── Core.hs │ │ └── Core │ │ ├── Imports.hs │ │ ├── Utils.hs │ │ └── Instances.hs ├── auth │ ├── implementation │ │ └── Auth │ │ │ ├── Poly1305.hs │ │ │ └── Mac │ │ │ ├── Blake2b.hs │ │ │ └── Blake2s.hs │ ├── Implementation.hsig │ └── Tests │ │ └── Auth.hs ├── message-digest │ ├── Implementation.hsig │ └── Tests │ │ └── Digest.hs ├── Raaz │ ├── RandomSpec.hs │ ├── Core │ │ ├── MemorySpec.hs │ │ ├── ByteSourceSpec.hs │ │ ├── Util │ │ │ └── ByteStringSpec.hs │ │ ├── EncodeSpec.hs │ │ └── Types │ │ │ └── WordSpec.hs │ ├── Digest │ │ ├── Sha256Spec.hs │ │ └── Sha512Spec.hs │ ├── Cipher │ │ └── XChaCha20Spec.hs │ └── Mac │ │ └── Poly1305Spec.hs └── cipher │ └── Tests │ └── Cipher.hs ├── monocypher └── tests │ ├── Monocypher.hs │ └── Monocypher │ ├── Sha512Spec.hs │ └── Blake2bSpec.hs ├── Setup.lhs ├── .gitmodules ├── .gitignore ├── scripts ├── stack-freeze.sh ├── get-lh.sh └── run-lh.sh ├── implementation ├── cbits │ └── raaz │ │ ├── cipher │ │ ├── aes │ │ │ └── cportable.h │ │ ├── cportable │ │ │ ├── aes.h │ │ │ └── salsa20.h │ │ └── chacha20 │ │ │ ├── common.h │ │ │ └── cportable.c │ │ └── hash │ │ └── blake2 │ │ ├── blake2s │ │ └── constants.h │ │ ├── common.h │ │ └── blake2b │ │ └── constants.h ├── entropy │ ├── urandom │ │ └── Entropy.hs │ ├── arc4random │ │ └── Entropy.hs │ ├── getrandom │ │ └── Entropy.hsc │ └── windows │ │ └── Entropy.hsc ├── ChaCha20 │ ├── Random │ │ └── CPortable.hs │ ├── CHandWritten.hs │ └── CPortable.hs ├── Sha512 │ ├── CPortable.hs │ └── CHandWritten.hs ├── Sha256 │ ├── CPortable.hs │ └── CHandWritten.hs ├── Blake2s │ └── CHandWritten.hs ├── Blake2b │ ├── CHandWritten.hs │ └── CPortable.hs └── Poly1305 │ └── Memory.hs ├── CONTRIBUTORS ├── core ├── Raaz │ ├── Core │ │ ├── Constants.hs │ │ ├── Prelude.hs │ │ ├── DH.hs │ │ ├── Types │ │ │ ├── Internal.hs │ │ │ └── Copying.hs │ │ ├── KeyExchange.hs │ │ ├── CpuSupports.hs │ │ ├── Parse │ │ │ └── Unsafe.hs │ │ ├── Types.hs │ │ ├── Util │ │ │ └── ByteString.hs │ │ ├── Parse.hs │ │ └── Encode.hs │ ├── Core.hs │ ├── KeyExchange │ │ └── X25519 │ │ │ └── Internal.hs │ └── Primitive │ │ ├── AEAD │ │ └── Internal.hs │ │ ├── Poly1305 │ │ └── Internal.hs │ │ └── Keyed │ │ └── Internal.hs └── cbits │ └── raaz │ └── core │ ├── memory.c │ ├── cpusupports.c │ ├── endian.c │ └── endian.h ├── mans └── Makefile ├── .github └── workflows │ ├── checks.yml │ └── ci.yml ├── raaz ├── Raaz │ ├── V1.hs │ ├── V1 │ │ ├── Digest.hs │ │ ├── Auth.hs │ │ └── AuthEncrypt │ │ │ └── Unsafe.hs │ └── AuthEncrypt │ │ └── Unsafe.hs └── bin │ ├── Usage.hs │ ├── Main.hs │ └── Command │ ├── Info.hs │ └── Rand.hs ├── old-raaz └── Raaz │ └── Hash │ ├── Sha1 │ ├── Recommendation.hs │ ├── Implementation │ │ └── CPortable.hs │ └── Internal.hs │ └── Sha1.hs ├── indef ├── buffer │ └── Implementation.hsig ├── chacha20 │ ├── Implementation.hsig │ └── XChaCha20 │ │ └── Implementation.hs ├── keyed │ └── hash │ │ └── Implementation.hsig ├── Utils.hs └── Implementation.hsig ├── flake.nix ├── benchmarks ├── internal │ └── Benchmark │ │ ├── CSPRG.hs │ │ ├── Primitive.hs │ │ └── Types.hs └── Main.hs ├── api ├── aead │ ├── Auth │ │ └── Implementation.hsig │ └── Cipher │ │ └── Implementation.hsig ├── random │ ├── Internal.hs │ ├── Entropy.hsig │ └── Implementation.hsig ├── encrypt │ ├── Implementation.hsig │ └── Interface.hs ├── digest │ ├── Implementation.hsig │ └── Interface.hs └── auth │ ├── Implementation.hsig │ └── Interface.hs ├── liquid └── LiquidSpec.hs ├── LICENSE-BSD3 ├── flake.lock ├── Releasing.md └── README.md /notes/.gitignore: -------------------------------------------------------------------------------- 1 | *.tex 2 | -------------------------------------------------------------------------------- /tests/Spec.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -F -pgmF hspec-discover #-} 2 | -------------------------------------------------------------------------------- /tests/comparative/Main.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -F -pgmF hspec-discover #-} 2 | -------------------------------------------------------------------------------- /monocypher/tests/Monocypher.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -F -pgmF hspec-discover #-} 2 | -------------------------------------------------------------------------------- /tests/prgquality.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cabal new-exec raaz rand | dieharder -a -g 200 3 | -------------------------------------------------------------------------------- /tests/entropyquality.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cabal new-exec raaz entropy | dieharder -a -g 200 3 | -------------------------------------------------------------------------------- /Setup.lhs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env runhaskell 2 | > import Distribution.Simple 3 | > main = defaultMain 4 | -------------------------------------------------------------------------------- /tests/standard-test-vectors/blake2/url: -------------------------------------------------------------------------------- 1 | https://raw.githubusercontent.com/BLAKE2/BLAKE2/master/testvectors/blake2-kat.json -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "wiki"] 2 | path = wiki 3 | url = https://github.com/raaz-crypto/raaz.wiki.git 4 | [submodule "libverse"] 5 | path = libverse 6 | url = https://github.com/raaz-crypto/libverse.git 7 | -------------------------------------------------------------------------------- /tests/core/Tests/Core.hs: -------------------------------------------------------------------------------- 1 | -- Common stuff need by all test modules 2 | module Tests.Core (module E) where 3 | 4 | import Tests.Core.Imports as E 5 | import Tests.Core.Instances () 6 | import Tests.Core.Utils as E 7 | -------------------------------------------------------------------------------- /tests/auth/implementation/Auth/Poly1305.hs: -------------------------------------------------------------------------------- 1 | module Auth.Poly1305 ( module Tests.Core 2 | , module Poly1305.Implementation 3 | ) where 4 | 5 | import Poly1305.Implementation 6 | import Tests.Core 7 | -------------------------------------------------------------------------------- /tests/auth/implementation/Auth/Mac/Blake2b.hs: -------------------------------------------------------------------------------- 1 | module Auth.Mac.Blake2b ( module Blake2b.Mac.Implementation 2 | , module Tests.Core 3 | ) where 4 | import Blake2b.Mac.Implementation 5 | import Tests.Core 6 | -------------------------------------------------------------------------------- /tests/auth/implementation/Auth/Mac/Blake2s.hs: -------------------------------------------------------------------------------- 1 | module Auth.Mac.Blake2s ( module Blake2s.Mac.Implementation 2 | , module Tests.Core 3 | ) where 4 | import Blake2s.Mac.Implementation 5 | import Tests.Core 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.hi 3 | dist 4 | dist-newstyle 5 | dist-docs 6 | tags 7 | TAGS 8 | .cabal-sandbox 9 | .ghc.environment* 10 | cabal.project.local 11 | *test 12 | .hpc 13 | cabal.sandbox.config 14 | .stack-work 15 | .liquid 16 | *.s 17 | *.pdf 18 | mans/raaz.1.gz 19 | .hlint-* 20 | -------------------------------------------------------------------------------- /scripts/stack-freeze.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | STACKAGE_URL=https://www.stackage.org/"$1"/cabal.config 4 | TARGET=cabal.project.freeze 5 | if [ -n "$2" ] 6 | then 7 | TARGET="$2" 8 | fi 9 | 10 | rm -f cabal.config 11 | wget "$STACKAGE_URL" -c 12 | sed -n /raaz/!p < cabal.config > "$TARGET" 13 | -------------------------------------------------------------------------------- /tests/message-digest/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | 3 | -- This signature adds additional constraints on the primitive and its 4 | -- key so that we can give digest tests. 5 | signature Implementation where 6 | 7 | import Raaz.Core 8 | 9 | data Prim 10 | instance Show Prim 11 | -------------------------------------------------------------------------------- /scripts/get-lh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FOLDER="$HOME/liquidhaskell" 4 | 5 | rm -rf "$FOLDER" 6 | 7 | cd "$HOME" 8 | git clone --recursive --depth 1 git://github.com/ucsd-progsys/liquidhaskell.git 9 | 10 | cd "$FOLDER" 11 | 12 | cabal sandbox init 13 | cabal sandbox add-source ./liquid-fixpoint 14 | cabal install 15 | -------------------------------------------------------------------------------- /scripts/run-lh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | LIQUID="$HOME/liquidhaskell/.cabal-sandbox/bin/liquid" 5 | $LIQUID --version 6 | 7 | echo "-------------------------------------------------" 8 | 9 | 10 | "$LIQUID" `find raaz-core -name "*.hs" | grep -v Entropy` 11 | "$LIQUID"`find raaz-implementation -name "*.hs" | grep -v Entropy` 12 | -------------------------------------------------------------------------------- /implementation/cbits/raaz/cipher/aes/cportable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void raazAESCBCEncryptCPortable( 4 | Block *inp, int nBlocks, 5 | int nRounds, RMatrix *eKey, 6 | RMatrix iv); 7 | 8 | extern void raazAESCBCDecryptCPortable( 9 | Block *inp, int nBlocks, 10 | int nRounds, RMatrix *eKey, 11 | RMatrix iv); 12 | -------------------------------------------------------------------------------- /tests/comparative/Digest/Sha256Spec.hs: -------------------------------------------------------------------------------- 1 | module Digest.Sha256Spec where 2 | 3 | import Digest 4 | import qualified Digest.Sha256.CPortable as CP 5 | import qualified Digest.Sha256.CHandWritten as CH 6 | 7 | spec :: Spec 8 | spec = digestSpec[ (CP.name, CP.digest) 9 | , (CH.name, CH.digest) 10 | ] 11 | -------------------------------------------------------------------------------- /tests/comparative/Digest/Sha512Spec.hs: -------------------------------------------------------------------------------- 1 | module Digest.Sha512Spec where 2 | 3 | import Digest 4 | import qualified Digest.Sha512.CPortable as CP 5 | import qualified Digest.Sha512.CHandWritten as CH 6 | 7 | spec :: Spec 8 | spec = digestSpec [ (CP.name, CP.digest) 9 | , (CH.name, CH.digest) 10 | ] 11 | -------------------------------------------------------------------------------- /tests/comparative/Digest/Blake2bSpec.hs: -------------------------------------------------------------------------------- 1 | module Digest.Blake2bSpec where 2 | 3 | import Digest 4 | import qualified Digest.Blake2b.CPortable as CP 5 | import qualified Digest.Blake2b.CHandWritten as CH 6 | 7 | spec :: Spec 8 | spec = digestSpec [ (CP.name, CP.digest) 9 | , (CH.name, CH.digest) 10 | ] 11 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Code 2 | ---- 3 | 4 | Abhimanyu Jaju 5 | Gurpreet Singh Khanuja 6 | Harshit 7 | Herbert Valerio Riedel 8 | Jaro Reinders 9 | Piyush P Kurur 10 | Saksham Sharma 11 | Sarthak Jain 12 | Satvik Chauhan 13 | Soorya Narayan J. M. 14 | Tamar Christina (Mistuke) 15 | Vinit Kataria 16 | 17 | Debian packaging 18 | ---------------- 19 | 20 | Sean Whitton 21 | -------------------------------------------------------------------------------- /core/Raaz/Core/Constants.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_HADDOCK hide #-} 2 | -- | Some constants used by raaz. 3 | module Raaz.Core.Constants 4 | ( l1Cache 5 | ) where 6 | import Raaz.Core.Prelude 7 | import Raaz.Core.Types 8 | 9 | -- | Typical size of L1 cache. Used for selecting buffer size etc in crypto operations. 10 | l1Cache :: BYTES Int 11 | l1Cache = 32768 12 | -------------------------------------------------------------------------------- /mans/Makefile: -------------------------------------------------------------------------------- 1 | MAN_PAGES=raaz.1 # Which man pages to generate. 2 | MAN_PAGES_GZ= $(addsuffix .gz, ${MAN_PAGES}) 3 | MAN_SOURCES= $(addsuffix .md, ${MAN_PAGES}) 4 | 5 | .PHONY: all clean 6 | 7 | all: ${MAN_PAGES_GZ} 8 | clean: 9 | rm -f ${MAN_PAGES} ${MAN_PAGES_GZ} 10 | 11 | ${MAN_PAGES_GZ}:%.gz:% 12 | gzip -f $< 13 | ${MAN_PAGES}:%:%.md 14 | pandoc -s $< -t man -o $@ 15 | -------------------------------------------------------------------------------- /tests/comparative/Digest.hs: -------------------------------------------------------------------------------- 1 | module Digest( digestSpec 2 | , module Compare 3 | ) where 4 | import Compare 5 | 6 | digestSpec :: Eq a 7 | => [(String, ByteString -> a)] 8 | -> Spec 9 | digestSpec fs = prop mesg $ \ bs -> checkSame $ map (digestIt bs) fs 10 | where digestIt bs (nm,f) = (nm, f bs) 11 | mesg = message $ map fst fs 12 | -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: Checks 2 | on: [push, pull_request] 3 | jobs: 4 | checks: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Get the Repository 8 | uses: actions/checkout@v4 9 | 10 | - name: 'Trailing white spaces ?' 11 | uses: harupy/find-trailing-whitespace@master 12 | 13 | - name: 'Run HLint' 14 | uses: haskell-actions/hlint-scan@v1 15 | -------------------------------------------------------------------------------- /tests/auth/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | 3 | -- This signature adds additional constraints on the primitive and its 4 | -- key so that we can give authenticator tests. 5 | signature Implementation where 6 | 7 | import Raaz.Core 8 | import Test.QuickCheck.Arbitrary 9 | 10 | data Prim 11 | 12 | 13 | instance Show (Prim) 14 | instance Show (Key Prim) 15 | instance Arbitrary (Key Prim) 16 | -------------------------------------------------------------------------------- /implementation/cbits/raaz/hash/blake2/blake2s/constants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | const Word2s iv2s0 = 0x6a09e667UL; 6 | const Word2s iv2s1 = 0xbb67ae85UL; 7 | const Word2s iv2s2 = 0x3c6ef372UL; 8 | const Word2s iv2s3 = 0xa54ff53aUL; 9 | const Word2s iv2s4 = 0x510e527fUL; 10 | const Word2s iv2s5 = 0x9b05688cUL; 11 | const Word2s iv2s6 = 0x1f83d9abUL; 12 | const Word2s iv2s7 = 0x5be0cd19UL; 13 | -------------------------------------------------------------------------------- /tests/comparative/AuthEncrypt/ChaCha20Poly1305Spec.hs: -------------------------------------------------------------------------------- 1 | module AuthEncrypt.ChaCha20Poly1305Spec where 2 | 3 | import AuthEncrypt 4 | import qualified AuthEncrypt.ChaCha20Poly1305.CPortable as CP 5 | import qualified AuthEncrypt.ChaCha20Poly1305.CHandWritten as CH 6 | 7 | spec :: Spec 8 | spec = lockVsUnlock 9 | [ (CP.name, CP.unsafeLock), (CH.name, CH.unsafeLock) ] 10 | [ (CP.name, CP.unlock), (CH.name, CH.unlock) ] 11 | -------------------------------------------------------------------------------- /tests/Raaz/RandomSpec.hs: -------------------------------------------------------------------------------- 1 | module Raaz.RandomSpec where 2 | 3 | import Tests.Core 4 | import Raaz.Random 5 | 6 | spec :: Spec 7 | spec = it "system prg should return different words on distinct calls" 8 | $ compareWords `shouldReturn` False 9 | where r64 :: RandomState -> IO Word64 10 | r64 = random 11 | compareWords = withRandomState $ \ state -> (==) <$> r64 state <*> r64 state 12 | -------------------------------------------------------------------------------- /raaz/Raaz/V1.hs: -------------------------------------------------------------------------------- 1 | -- | The interface is the same as that of "Raaz" but the primitive 2 | -- selection corresponds to the version 1 of the raaz library. Use 3 | -- this module if you want compatibility with Version 1 of the 4 | -- library. 5 | -- 6 | -- For documentation refer the top-most module "Raaz". 7 | 8 | module Raaz.V1 ( module Raaz.V1.Digest 9 | , module Raaz.V1.Auth 10 | ) where 11 | 12 | import Raaz.V1.Digest 13 | import Raaz.V1.Auth 14 | -------------------------------------------------------------------------------- /implementation/cbits/raaz/hash/blake2/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define HASH_SIZE 8 7 | #define BLOCK_SIZE 16 8 | 9 | typedef uint64_t Word2b; /* basic unit for blake2b */ 10 | typedef uint32_t Word2s; /* basic unit for blake2s */ 11 | 12 | 13 | typedef Word2b Blake2b[HASH_SIZE]; 14 | typedef Word2b Block2b[BLOCK_SIZE]; 15 | 16 | typedef Word2s Blake2s[HASH_SIZE]; 17 | typedef Word2s Block2s[BLOCK_SIZE]; 18 | -------------------------------------------------------------------------------- /implementation/cbits/raaz/hash/blake2/blake2b/constants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | const Word2b iv2b0 = 0x6a09e667f3bcc908ULL; 6 | const Word2b iv2b1 = 0xbb67ae8584caa73bULL; 7 | const Word2b iv2b2 = 0x3c6ef372fe94f82bULL; 8 | const Word2b iv2b3 = 0xa54ff53a5f1d36f1ULL; 9 | const Word2b iv2b4 = 0x510e527fade682d1ULL; 10 | const Word2b iv2b5 = 0x9b05688c2b3e6c1fULL; 11 | const Word2b iv2b6 = 0x1f83d9abfb41bd6bULL; 12 | const Word2b iv2b7 = 0x5be0cd19137e2179ULL; 13 | -------------------------------------------------------------------------------- /tests/comparative/Compare.hs: -------------------------------------------------------------------------------- 1 | module Compare ( checkSame, message 2 | , module Tests.Core 3 | ) where 4 | import Tests.Core 5 | same :: Eq a => [a] -> Bool 6 | same [] = True 7 | same (x:xs) = all (==x) xs 8 | 9 | 10 | checkSame :: Eq a => [(b,a)] -> Bool 11 | checkSame = same . map snd 12 | 13 | message :: [String] -> String 14 | message xs = unwords $ oxfordComma $ "comparing" : xs 15 | where oxfordComma [x,y] = [x ++ ", and", y] 16 | oxfordComma ys = ys 17 | -------------------------------------------------------------------------------- /raaz/Raaz/V1/Digest.hs: -------------------------------------------------------------------------------- 1 | -- | The interface is the same as that of "Raaz.Digest" but the primitive 2 | -- selection corresponds to the version 1 of the raaz library. Use 3 | -- this module if you want compatibility with Version 1 of the 4 | -- library. 5 | -- 6 | -- For documentation refer to the module "Raaz.Digest". 7 | 8 | module Raaz.V1.Digest 9 | ( 10 | module Raaz.Digest.Blake2b 11 | , digestAlgorithm 12 | ) where 13 | 14 | import Raaz.Core 15 | import Raaz.Digest.Blake2b 16 | 17 | -- | Algorithm used for message digest 18 | digestAlgorithm :: String 19 | digestAlgorithm = primName 20 | -------------------------------------------------------------------------------- /raaz/Raaz/V1/Auth.hs: -------------------------------------------------------------------------------- 1 | -- | The interface is the same as that of "Raaz.Auth" but the 2 | -- primitive selection corresponds to the version 1 of the raaz 3 | -- library. Use this module if you want compatibility with Version 1 4 | -- of the library. 5 | -- 6 | -- For documentation refer the module "Raaz.Auth". 7 | 8 | module Raaz.V1.Auth ( module Raaz.Auth.Blake2b 9 | , authAlgorithm 10 | ) where 11 | import Raaz.Core 12 | import Raaz.Auth.Blake2b 13 | 14 | -- | The algorithm used for message authentication. 15 | authAlgorithm :: String 16 | authAlgorithm = primName 17 | -------------------------------------------------------------------------------- /tests/comparative/Encrypt/ChaCha20Spec.hs: -------------------------------------------------------------------------------- 1 | module Encrypt.ChaCha20Spec where 2 | 3 | import Encrypt 4 | import qualified Encrypt.ChaCha20.CPortable as CP 5 | import qualified Encrypt.ChaCha20.CHandWritten as CH 6 | 7 | spec :: Spec 8 | spec = do 9 | describe "encryption" $ encryptSpec [ (CP.name, CP.encrypt) 10 | , (CH.name, CH.encrypt) 11 | ] 12 | describe "decryption" $ decryptSpec [ (CP.name, CP.decrypt) 13 | , (CH.name, CH.decrypt) 14 | ] 15 | -------------------------------------------------------------------------------- /old-raaz/Raaz/Hash/Sha1/Recommendation.hs: -------------------------------------------------------------------------------- 1 | -- | This sets up the recommended implementation of Sha1. 2 | {-# OPTIONS_GHC -fno-warn-orphans #-} 3 | -- 4 | -- The orphan instance declaration separates the implementation and 5 | -- setting the recommended instances. Therefore, we ignore the warning. 6 | -- 7 | 8 | module Raaz.Hash.Sha1.Recommendation where 9 | 10 | import Raaz.Core 11 | import Raaz.Hash.Sha1.Internal 12 | import qualified Raaz.Hash.Sha1.Implementation.CPortable as CPortable 13 | 14 | -- | Recommended implementation for SHA1. 15 | instance Recommendation SHA1 where 16 | recommended _ = CPortable.implementation 17 | -------------------------------------------------------------------------------- /indef/buffer/Implementation.hsig: -------------------------------------------------------------------------------- 1 | -- | An implementation of a cryptographic primitive is a method to 2 | -- process data that is multiples of its block size. Fast 3 | -- implementations involve other details like the alignment 4 | -- restriction on the input buffer and all that. We package all this 5 | -- in the following signature. 6 | signature Implementation ( Prim, Internals 7 | , BufferPtr, BufferAlignment 8 | , additionalBlocks 9 | ) where 10 | 11 | import Raaz.Core 12 | data Prim 13 | data Internals 14 | instance Primitive Prim 15 | instance Memory Internals 16 | -------------------------------------------------------------------------------- /implementation/entropy/urandom/Entropy.hs: -------------------------------------------------------------------------------- 1 | -- | Entropy based on `/dev/urandom`. 2 | module Entropy( getEntropy, entropySource ) where 3 | 4 | import System.IO 5 | import Raaz.Core 6 | 7 | 8 | 9 | -- | The name of the source from which entropy is gathered. For 10 | -- information purposes only. 11 | entropySource :: String 12 | entropySource = "/dev/urandom(generic posix)" 13 | 14 | -- | Get random bytes from the system. Do not over use this function 15 | -- as it is meant to be used by a PRG. This function reads bytes from 16 | -- '/dev/urandom'. 17 | getEntropy :: BYTES Int -> Ptr Word8 -> IO (BYTES Int) 18 | getEntropy l ptr = withBinaryFile "/dev/urandom" ReadMode 19 | $ \ hand -> hFillBuf hand ptr l 20 | -------------------------------------------------------------------------------- /tests/comparative/AuthEncrypt.hs: -------------------------------------------------------------------------------- 1 | module AuthEncrypt (lockVsUnlock 2 | , module Compare 3 | ) where 4 | import Compare 5 | 6 | type LockFn k n a = k -> n -> ByteString -> a 7 | type UnlockFn k n a = k -> a -> Maybe ByteString 8 | 9 | 10 | lockVsUnlock :: ( Show k, Show n 11 | , Arbitrary k, Arbitrary n 12 | ) 13 | => [ (String, LockFn k n a) ] 14 | -> [ (String, UnlockFn k n a) ] 15 | -> Spec 16 | lockVsUnlock lfs ulfs = sequence_ [ lVsUL lnf ulnf | lnf <- lfs , ulnf <- ulfs ] 17 | where lVsUL (ln, lf) (uln, ulf) = let 18 | mesg = unwords ["lock using", ln, "unlock using", uln] 19 | in prop mesg $ \ k n bs -> ulf k (lf k n bs) `shouldBe` Just bs 20 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | 3 | description = "Development environment for raaz, a fast and type safe cryptographic library in haskell"; 4 | 5 | inputs = { 6 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 7 | flake-utils.url = "github:numtide/flake-utils"; 8 | }; 9 | 10 | outputs = { self, nixpkgs, flake-utils }: 11 | flake-utils.lib.eachDefaultSystem (system: 12 | let pkgs = nixpkgs.legacyPackages.${system}; 13 | hpkgs = pkgs.haskell.packages.ghcHEAD; 14 | in 15 | { 16 | devShell = pkgs.mkShell { 17 | buildInputs = [ pkgs.editorconfig-checker 18 | pkgs.zlib 19 | hpkgs.ghc 20 | ]; 21 | }; 22 | } 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /benchmarks/internal/Benchmark/CSPRG.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | {-# LANGUAGE MonoLocalBinds #-} 3 | module Benchmark.CSPRG where 4 | 5 | import Control.Monad 6 | import GHC.TypeLits 7 | 8 | import Raaz.Core 9 | import Benchmark.Types 10 | import Buffer 11 | import Implementation 12 | 13 | 14 | -- | Number of blocks. 15 | nblocks :: BlockCount Prim 16 | nblocks = atLeast nBytes 17 | 18 | allocAndRun :: (BufferPtr -> IO ()) -> IO () 19 | allocAndRun = allocaBuffer (nblocks <> additionalBlocks) 20 | 21 | bench :: KnownNat BufferAlignment => RaazBench 22 | bench = (primName, name, toBenchmarkable $ action . fromIntegral) 23 | where action count = allocAndRun $ doit count 24 | doit count ptr = withMemory $ \ mem -> replicateM_ count (randomBlocks ptr nblocks mem) 25 | -------------------------------------------------------------------------------- /benchmarks/internal/Benchmark/Primitive.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | {-# LANGUAGE MonoLocalBinds #-} 3 | module Benchmark.Primitive where 4 | 5 | import Control.Monad 6 | import GHC.TypeLits 7 | 8 | import Raaz.Core 9 | import Implementation 10 | import Benchmark.Types 11 | 12 | -- | Number of blocks. 13 | nblocks :: BlockCount Prim 14 | nblocks = atLeast nBytes 15 | 16 | allocAndRun :: (BufferPtr -> IO ()) -> IO () 17 | allocAndRun = allocaBuffer (nblocks <> additionalBlocks) 18 | 19 | bench :: KnownNat BufferAlignment => RaazBench 20 | bench = (primName, nm, toBenchmarkable $ action . fromIntegral) 21 | where action count = allocAndRun $ doit count 22 | nm = name 23 | doit count ptr = withMemory $ \ mem -> replicateM_ count (processBlocks ptr nblocks mem) 24 | -------------------------------------------------------------------------------- /raaz/bin/Usage.hs: -------------------------------------------------------------------------------- 1 | module Usage( usage, errorBailout ) where 2 | 3 | import Prelude 4 | import System.Console.GetOpt 5 | import System.IO 6 | import System.Exit 7 | 8 | -- | The usage message for the program. 9 | usage :: [OptDescr a] -- ^ options 10 | -> String -- ^ Header 11 | -> [String] -- ^ errors 12 | -> String 13 | usage options header errs 14 | | null errs = usageInfo header options 15 | | otherwise = "raaz: " ++ unlines errs ++ usageInfo header options 16 | 17 | 18 | 19 | -- | Bail out on error 20 | errorBailout :: [OptDescr a] -- ^ Options 21 | -> String -- ^ Header 22 | -> [String] -- ^ Errors 23 | -> IO b 24 | errorBailout opts str errs = do 25 | hPutStrLn stderr $ usage opts str errs 26 | exitFailure 27 | -------------------------------------------------------------------------------- /tests/core/Tests/Core/Imports.hs: -------------------------------------------------------------------------------- 1 | -- Common imports. 2 | module Tests.Core.Imports( module E ) where 3 | import Data.ByteString as E (ByteString, pack) 4 | import Data.ByteString.Char8 () -- import IsString instance for 5 | -- byte string. 6 | import Foreign.Storable as E (Storable, peek, poke) 7 | import Test.Hspec as E 8 | import Test.Hspec.QuickCheck as E 9 | import Test.QuickCheck as E 10 | import Test.QuickCheck.Monadic as E 11 | 12 | import Raaz.Core as E hiding ((===), Result, (.&.)) 13 | 14 | import Raaz.Primitive.Blake2.Internal as E 15 | import Raaz.Primitive.ChaCha20.Internal as E hiding ( Key ) 16 | import Raaz.Primitive.Poly1305.Internal as E hiding ( Key ) 17 | import Raaz.Primitive.Sha2.Internal as E 18 | 19 | 20 | -- import Raaz.Hash.Sha1 as E 21 | -------------------------------------------------------------------------------- /api/aead/Auth/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE KindSignatures #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE FlexibleInstances #-} 6 | {-# LANGUAGE TypeFamilies #-} 7 | 8 | -- | The implementation of the authenticator part of the construction. 9 | signature Auth.Implementation where 10 | 11 | import Raaz.Core 12 | 13 | data Prim 14 | data Internals 15 | 16 | instance Eq Prim -- We need ability to compare 17 | instance Equality Prim -- Timing safe comparison when part of a 18 | -- compound type 19 | instance Encodable Prim -- To serialise authentication tag. 20 | 21 | instance Memory Internals 22 | instance WriteAccessible Internals 23 | instance Extractable Internals Prim 24 | -------------------------------------------------------------------------------- /old-raaz/Raaz/Hash/Sha1/Implementation/CPortable.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | -- | The portable C-implementation of SHA1 3 | module Raaz.Hash.Sha1.Implementation.CPortable 4 | ( implementation 5 | ) where 6 | 7 | import Foreign.Ptr ( Ptr ) 8 | import Raaz.Core 9 | import Raaz.Hash.Internal 10 | import Raaz.Hash.Sha.Util 11 | import Raaz.Hash.Sha1.Internal 12 | 13 | -- | The portable C implementation of SHA1. 14 | implementation :: Implementation SHA1 15 | implementation = SomeHashI cPortable 16 | 17 | cPortable :: HashI SHA1 (HashMemory SHA1) 18 | cPortable = shaImplementation 19 | "sha1-cportable" 20 | "Sha1 Implementation using portable C and Haskell FFI" 21 | c_sha1_compress length64Write 22 | 23 | foreign import ccall unsafe 24 | "raaz/hash/sha1/portable.h raazHashSha1PortableCompress" 25 | c_sha1_compress :: Pointer -> Int -> Ptr SHA1 -> IO () 26 | -------------------------------------------------------------------------------- /core/Raaz/Core.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- 3 | -- Module : Raaz.Core 4 | -- Description : Core functions, data types and classes of the raaz package. 5 | -- Copyright : (c) Piyush P Kurur, 2019 6 | -- License : Apache-2.0 OR BSD-3-Clause 7 | -- Maintainer : Piyush P Kurur 8 | -- Stability : experimental 9 | -- 10 | 11 | module Raaz.Core 12 | ( module X 13 | , module Raaz.Core.Memory 14 | ) where 15 | 16 | import Raaz.Core.ByteSource as X 17 | import Raaz.Core.Constants as X 18 | import Raaz.Core.Encode as X 19 | import Raaz.Core.KeyExchange as X 20 | import Raaz.Core.Memory hiding ( Access ) 21 | import Raaz.Core.Memory ( Access ) 22 | import Raaz.Core.Prelude as X 23 | import Raaz.Core.Primitive as X 24 | import Raaz.Core.Transfer as X 25 | import Raaz.Core.Types as X 26 | import Raaz.Core.Util.ByteString as X 27 | 28 | {-# ANN module "HLint: ignore Use import/export shortcut" #-} 29 | -------------------------------------------------------------------------------- /implementation/entropy/arc4random/Entropy.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | -- | Entropy based on arc4random_buf (OpenBSD/NetBSD etc). 4 | module Entropy( getEntropy, entropySource ) where 5 | 6 | import Raaz.Core 7 | import Raaz.Core.Types.Internal 8 | 9 | -- | The name of the source from which entropy is gathered. For 10 | -- information purposes only. 11 | entropySource :: String 12 | entropySource = "arc4random_buf" 13 | 14 | -- | The arc4random function. 15 | foreign import ccall unsafe 16 | "arc4random_buf" 17 | c_arc4random :: Ptr Word8 -- Message 18 | -> BYTES Int -- number of bytes 19 | -> IO (BYTES Int) 20 | 21 | -- | Get random bytes from using the @arc4random@ on OpenBSD/NetBSD 22 | -- This is only used to seed the PRG and not intended for call by 23 | -- others. 24 | getEntropy :: BYTES Int -> Ptr Word8 -> IO (BYTES Int) 25 | getEntropy l ptr = c_arc4random ptr l 26 | -------------------------------------------------------------------------------- /core/Raaz/Core/Prelude.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | -- | 3 | -- 4 | -- Module : Raaz.Core.Prelude 5 | -- Copyright : (c) Piyush P Kurur, 2019 6 | -- License : Apache-2.0 OR BSD-3-Clause 7 | -- Maintainer : Piyush P Kurur 8 | -- Stability : experimental 9 | -- 10 | 11 | module Raaz.Core.Prelude ( module X 12 | , module Prelude 13 | ) where 14 | 15 | import Control.Applicative as X 16 | import Control.Monad as X 17 | import Data.Bits as X 18 | import Data.ByteString.Char8 () 19 | import Data.ByteString.Lazy.Char8 () 20 | import Data.Kind as X 21 | import Data.Maybe as X 22 | import Data.Proxy as X 23 | 24 | import Data.String as X 25 | import Data.Word as X 26 | import Prelude hiding (length, replicate, zipWith) 27 | import System.IO as X 28 | -------------------------------------------------------------------------------- /tests/comparative/Encrypt.hs: -------------------------------------------------------------------------------- 1 | module Encrypt( encryptSpec 2 | , decryptSpec 3 | , module Compare 4 | ) where 5 | import Compare 6 | 7 | encryptSpec :: ( Eq a 8 | , Show k, Show n 9 | , Arbitrary k , Arbitrary n 10 | ) 11 | => [(String, k -> n -> ByteString -> a)] 12 | -> Spec 13 | 14 | encryptSpec fs = prop mesg $ \ k n bs -> checkSame $ map (encryptIt k n bs) fs 15 | where encryptIt k n bs (nm,f) = (nm, f k n bs) 16 | mesg = message $ map fst fs 17 | 18 | 19 | decryptSpec :: ( Eq a 20 | , Show k, Show n 21 | , Arbitrary k , Arbitrary n 22 | ) 23 | => [(String, k -> n -> ByteString -> a)] 24 | -> Spec 25 | 26 | decryptSpec fs = prop mesg $ \ k n bs -> checkSame $ map (decryptIt k n bs) fs 27 | where decryptIt k n bs (nm,f) = (nm, f k n bs) 28 | mesg = message $ map fst fs 29 | -------------------------------------------------------------------------------- /api/random/Internal.hs: -------------------------------------------------------------------------------- 1 | -- | Some internal functions exposed by raaz mainly for testing 2 | -- purposes. The functions here are pretty low level and/or expose to 3 | -- much of the system details. If you find your self needing some of 4 | -- the functions here, it should be treated as a bug in raaz. Please 5 | -- file an issue. 6 | module Internal 7 | ( fillSystemEntropy 8 | ) where 9 | 10 | import Raaz.Core 11 | import Entropy 12 | 13 | -- | __WARNING__ Never use this function directly. Only exposed for 14 | -- testing the quality of system entropy. Fill the given input buffer 15 | -- with from the system entropy pool. This is provided only to test 16 | -- the quality of the system entropy function with systems like 17 | -- die-harder. The function is going to be less safe (due to the low 18 | -- level nature of the function) and slower (due to system call 19 | -- overheads). 20 | fillSystemEntropy :: LengthUnit l => l -> Ptr Word8 -> IO (BYTES Int) 21 | fillSystemEntropy = getEntropy . inBytes 22 | -------------------------------------------------------------------------------- /implementation/cbits/raaz/cipher/cportable/aes.h: -------------------------------------------------------------------------------- 1 | #ifndef __RAAZ_CIPHER_AES_H_ 2 | #define __RAAZ_CIPHER_AES_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | typedef uint8_t Word8; 9 | typedef uint32_t Word32; 10 | typedef uint64_t Word64; 11 | 12 | typedef enum {KEY128=0, KEY192=1, KEY256=2} KEY; 13 | 14 | extern void raazCipherAESExpand(Word32 *expandedKey, Word8 *key, Word8 k); 15 | extern void raazCipherAESBlockEncrypt(Word32 *eKey, Word8 *block, Word8 k); 16 | extern void raazCipherAESBlockDecrypt(Word32 *eKey, Word8 *block, Word8 k); 17 | extern void raazCipherAESECBEncrypt(Word32 *key, Word8 *input, Word32 nblocks, Word8 k); 18 | extern void raazCipherAESECBDecrypt(Word32 *key, Word8 *input, Word32 nblocks, Word8 k); 19 | extern void raazCipherAESCBCEncrypt(Word32 *key, Word8 *input, Word8 *iv, Word32 nblocks, KEY k); 20 | extern void raazCipherAESCBCDecrypt(Word32 *key, Word8 *input, Word8 *iv, Word32 nblocks, KEY k); 21 | extern void raazCipherAESCTREncrypt(Word32 *key, Word8 *input, Word8 *iv, Word32 len, KEY k); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /core/Raaz/Core/DH.hs: -------------------------------------------------------------------------------- 1 | -- | This module provides an abstract interface for Diffie Hellman Key Exchange. 2 | 3 | {-# LANGUAGE TypeFamilies #-} 4 | 5 | module Raaz.Core.DH 6 | ( DH(..) ) where 7 | 8 | -- | The DH (Diffie-Hellman) typeclass provides an interface for key 9 | -- exchanges. 'Secret' represents the secret generated by each party 10 | -- & known only to itself. 'PublicToken' represents the token 11 | -- generated from the 'Secret' which is sent to the other party. 12 | -- 'SharedSecret' represents the common secret generated by both 13 | -- parties from the respective public tokens. 'publicToken' takes the 14 | -- generator of the group and a secret and generates the public token. 15 | -- 'sharedSecret' takes the generator of the group, secret of one party 16 | -- and public token of the other party and generates the shared secret. 17 | class DH d where 18 | type Secret d :: * 19 | type PublicToken d :: * 20 | type SharedSecret d :: * 21 | 22 | publicToken :: d -> Secret d -> PublicToken d 23 | sharedSecret :: d -> Secret d -> PublicToken d -> SharedSecret d 24 | -------------------------------------------------------------------------------- /core/Raaz/KeyExchange/X25519/Internal.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 3 | {-# LANGUAGE FlexibleInstances #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE TypeFamilies #-} 6 | module Raaz.KeyExchange.X25519.Internal 7 | ( X25519(..) 8 | ) where 9 | 10 | import Foreign.Storable 11 | import Raaz.Core 12 | import Raaz.Core.KeyExchange () 13 | 14 | data X25519 = X25519 15 | 16 | type Word256 = Tuple 4 (LE Word64) 17 | 18 | instance KeyExchange X25519 where 19 | 20 | newtype Private X25519 = Private Word256 21 | deriving (Storable, EndianStore, Equality, Eq) 22 | 23 | newtype Exchange X25519 = Exchange Word256 24 | deriving (Storable, EndianStore, Equality, Eq) 25 | 26 | newtype Secret X25519 = Secret Word256 27 | deriving (Storable, EndianStore, Equality, Eq) 28 | 29 | 30 | instance Encodable (Private X25519) 31 | instance Encodable (Exchange X25519) 32 | instance Encodable (Secret X25519) 33 | 34 | instance Show (Private X25519) where 35 | show = showBase16 36 | 37 | instance Show (Exchange X25519) where 38 | show = showBase16 39 | 40 | instance Show (Secret X25519) where 41 | show = showBase16 42 | -------------------------------------------------------------------------------- /implementation/entropy/getrandom/Entropy.hsc: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | -- | Entropy based on the getrandom system call on Linux. 3 | module Entropy( getEntropy, entropySource ) where 4 | 5 | import Foreign.C ( CLong(..) ) 6 | 7 | import Raaz.Core.Prelude 8 | import Raaz.Core.Types 9 | import Raaz.Core.Types.Internal 10 | 11 | # include 12 | # include 13 | 14 | 15 | -- | The name of the source from which entropy is gathered. For 16 | -- information purposes only. 17 | entropySource :: String 18 | entropySource = "getrandom(linux)" 19 | 20 | -- | The getrandom system call. 21 | foreign import ccall unsafe 22 | "syscall" 23 | c_syscall :: CLong 24 | -> Ptr Word8 -- Message 25 | -> BYTES Int -- number of bytes to be read. 26 | -> Int -- flags 27 | -> IO (BYTES Int) 28 | 29 | sysGETRANDOM :: CLong 30 | sysGETRANDOM = #const SYS_getrandom 31 | 32 | -- | Get random bytes from using the @getrandom@ system call on 33 | -- linux. This is only used to seed the PRG and not intended for call 34 | -- by others. 35 | getEntropy :: BYTES Int -> Ptr Word8 -> IO (BYTES Int) 36 | getEntropy l ptr = c_syscall sysGETRANDOM ptr l 0 37 | -------------------------------------------------------------------------------- /monocypher/tests/Monocypher/Sha512Spec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | module Monocypher.Sha512Spec where 4 | 5 | 6 | import Data.ByteString.Internal (unsafeCreate) 7 | import Data.ByteString.Unsafe (unsafeUseAsCStringLen) 8 | import qualified Foreign.Storable as Storable 9 | import Foreign.Ptr 10 | import Foreign.C.Types 11 | import Foreign.C.String 12 | 13 | import Tests.Core 14 | import qualified Raaz.Digest.Sha512 as Sha512 15 | 16 | foreign import ccall unsafe 17 | crypto_sha512 :: Ptr Word8 -- hash 18 | -> Ptr CChar -- message 19 | -> CSize 20 | -> IO () 21 | 22 | sha512Size :: Int 23 | sha512Size = Storable.sizeOf (undefined :: Sha512) 24 | 25 | monocypher_sha512_io :: Ptr Word8 -> CStringLen -> IO () 26 | monocypher_sha512_io hshPtr (ptr, l) = crypto_sha512 hshPtr ptr (toEnum l) 27 | 28 | 29 | monocypher_sha512 :: ByteString -> Sha512 30 | monocypher_sha512 bs = unsafeFromByteString $ unsafeCreate sha512Size creator 31 | where creator ptr = unsafeUseAsCStringLen bs (monocypher_sha512_io ptr) 32 | 33 | spec :: Spec 34 | spec = prop "monocypher vs raaz sha512" $ 35 | \ x -> 36 | monocypher_sha512 x `shouldBe` Sha512.digest x 37 | -------------------------------------------------------------------------------- /monocypher/tests/Monocypher/Blake2bSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | module Monocypher.Blake2bSpec where 4 | 5 | 6 | import Data.ByteString.Internal (unsafeCreate) 7 | import Data.ByteString.Unsafe (unsafeUseAsCStringLen) 8 | import qualified Foreign.Storable as Storable 9 | import Foreign.Ptr 10 | import Foreign.C.Types 11 | import Foreign.C.String 12 | 13 | import Tests.Core 14 | import qualified Raaz.Digest.Blake2b as Blake2b 15 | 16 | foreign import ccall unsafe 17 | crypto_blake2b :: Ptr Word8 -- hash 18 | -> Ptr CChar -- message 19 | -> CSize 20 | -> IO () 21 | 22 | blake2bSize :: Int 23 | blake2bSize = Storable.sizeOf (undefined :: Blake2b) 24 | 25 | monocypher_blake2b_io :: Ptr Word8 -> CStringLen -> IO () 26 | monocypher_blake2b_io hshPtr (ptr, l) = crypto_blake2b hshPtr ptr (toEnum l) 27 | 28 | 29 | monocypher_blake2b :: ByteString -> Blake2b 30 | monocypher_blake2b bs = unsafeFromByteString $ unsafeCreate blake2bSize creator 31 | where creator ptr = unsafeUseAsCStringLen bs (monocypher_blake2b_io ptr) 32 | 33 | spec :: Spec 34 | spec = prop "monocypher vs raaz - blake2b" $ 35 | \ x -> 36 | monocypher_blake2b x `shouldBe` Blake2b.digest x 37 | -------------------------------------------------------------------------------- /tests/Raaz/Core/MemorySpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ScopedTypeVariables #-} 2 | module Raaz.Core.MemorySpec where 3 | import Tests.Core 4 | 5 | spec :: Spec 6 | spec = do describe "store and read" $ do 7 | prop "should return identical values when run securely" 8 | $ \ (x :: Word) -> withSecureMemory (storeAndRead x) `shouldReturn` x 9 | 10 | prop "should return identical values when run insecurely" 11 | $ \ (x :: Word) -> withMemory (storeAndRead x) `shouldReturn` x 12 | 13 | describe "store, copy, and read" $ do 14 | prop "should return identical values when run securely" 15 | $ \ (x :: Word) -> withSecureMemory (storeCopyRead x) `shouldReturn` x 16 | 17 | prop "should return identical values when run insecurely" 18 | $ \ (x :: Word) -> withMemory (storeCopyRead x) `shouldReturn` x 19 | 20 | where storeAndRead :: Word -> MemoryCell Word -> IO Word 21 | storeAndRead x mem = initialise x mem >> extract mem 22 | storeCopyRead :: Word -> (MemoryCell Word, MemoryCell Word) -> IO Word 23 | storeCopyRead x mem = let 24 | src = fst mem 25 | dst = snd mem 26 | in do initialise x src 27 | copyCell (destination dst) (source src) 28 | extract dst 29 | -------------------------------------------------------------------------------- /implementation/ChaCha20/Random/CPortable.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | module ChaCha20.Random.CPortable 3 | ( name, primName, description, RandomBufferSize, reseedAfter, randomBlocks 4 | , module ChaCha20.CPortable 5 | ) where 6 | 7 | import Raaz.Core 8 | import qualified ChaCha20.CPortable as Base 9 | import ChaCha20.CPortable (Prim, Internals, BufferAlignment, BufferPtr, additionalBlocks) 10 | import Raaz.Verse.ChaCha20.C.Portable 11 | 12 | name :: String 13 | name = "libverse-c" 14 | 15 | primName :: String 16 | primName = "chacha20-csprg" 17 | 18 | description :: String 19 | description = "ChaCha20 based CSPRG (machine endian version) written in C exposed by libverse." 20 | 21 | 22 | -------------------- CSPRG related stuff ------------------------------- 23 | -- | The number of blocks of the cipher that is generated in one go 24 | -- encoded as a type level nat. 25 | type RandomBufferSize = 16 26 | 27 | 28 | -- | How many blocks of the primitive to generated before re-seeding. 29 | reseedAfter :: BlockCount Prim 30 | reseedAfter = blocksOf (1024 * 1024 * 1024) (Proxy :: Proxy Prim) 31 | 32 | 33 | 34 | randomBlocks :: BufferPtr 35 | -> BlockCount Prim 36 | -> Internals 37 | -> IO () 38 | randomBlocks = Base.runBlockProcess verse_chacha20csprg_c_portable 39 | -------------------------------------------------------------------------------- /core/cbits/raaz/core/memory.c: -------------------------------------------------------------------------------- 1 | 2 | # ifdef PLATFORM_WINDOWS 3 | # include 4 | # include 5 | typedef BOOL WINAPI (*VirtualFunction)(LPVOID, SIZE_T); 6 | 7 | #else /* we assume posix system */ 8 | 9 | # include 10 | 11 | #endif 12 | 13 | /* Locks and Unlocks Memory */ 14 | int raazMemorylock(void* ptr, size_t size){ 15 | #ifdef PLATFORM_WINDOWS 16 | VirtualFunction func = 17 | (VirtualFunction)GetProcAddress(GetModuleHandle(TEXT("kernel32")), 18 | "VirtualLock"); 19 | return !func(ptr, size); 20 | #else 21 | return mlock(ptr,size); 22 | #endif 23 | 24 | } 25 | 26 | void raazMemoryunlock(void* ptr, size_t size){ 27 | #ifdef PLATFORM_WINDOWS 28 | VirtualFunction func = 29 | (VirtualFunction)GetProcAddress(GetModuleHandle (TEXT("kernel32")), 30 | "VirtualUnlock"); 31 | func(ptr, size); 32 | #else /* posix */ 33 | munlock(ptr,size); 34 | #endif 35 | } 36 | 37 | 38 | #include 39 | 40 | 41 | void raazWipeMemory(void * ptr, size_t size) 42 | { 43 | 44 | #ifdef HAVE_EXPLICIT_BZERO 45 | explicit_bzero(ptr,size); 46 | #elif HAVE_EXPLICIT_MEMSET 47 | explicit_memset(ptr,0,size); 48 | #elif HAVE_SECURE_ZERO_MEMORY 49 | SecureZeroMemory(ptr, size); 50 | #else 51 | #warning memset: The compiler might optimise it away. 52 | memset(ptr,0,size); 53 | #endif 54 | } 55 | -------------------------------------------------------------------------------- /core/cbits/raaz/core/cpusupports.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This module exposes runtime checks for cpu flags. Works only with GCC. 4 | 5 | */ 6 | 7 | 8 | # define GCC_VERSION (__GNUC__ * 10 + __GNUC_MINOR__) 9 | 10 | /* Check an x86_64 feature */ 11 | 12 | # ifdef ARCH_X86_64 13 | # define X86_64_SUPPORTS(x) { __builtin_cpu_init(); return __builtin_cpu_supports((x)); } 14 | # else 15 | # define X86_64_SUPPORTS(x) { return 0; } 16 | # endif 17 | 18 | # if GCC_VERSION >= 48 && !defined(__clang__) 19 | # pragma GCC push_options 20 | # pragma GCC optimize ("O0") 21 | 22 | int raaz_supports_sse() { X86_64_SUPPORTS("sse"); } 23 | int raaz_supports_sse2() { X86_64_SUPPORTS("sse2"); } 24 | int raaz_supports_sse3() { X86_64_SUPPORTS("sse3"); } 25 | int raaz_supports_sse4_1(){ X86_64_SUPPORTS("sse4.1"); } 26 | int raaz_supports_sse4_2(){ X86_64_SUPPORTS("sse4.2"); } 27 | int raaz_supports_avx() { X86_64_SUPPORTS("avx"); } 28 | int raaz_supports_avx2() { X86_64_SUPPORTS("avx2"); } 29 | 30 | # pragma GCC pop_options 31 | 32 | # else 33 | 34 | int raaz_supports_sse() { return 0;} 35 | int raaz_supports_sse2() { return 0;} 36 | int raaz_supports_sse3() { return 0;} 37 | int raaz_supports_sse4_1(){ return 0;} 38 | int raaz_supports_sse4_2(){ return 0;} 39 | int raaz_supports_avx() { return 0;} 40 | int raaz_supports_avx2() { return 0;} 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /implementation/cbits/raaz/cipher/cportable/salsa20.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Portable C implementation of Salsa20 Encryption. The implementation is 4 | part of the raaz cryptographic network library and is not meant to be 5 | used as a standalone aes implementation. 6 | 7 | Copyright (c) 2013, Satvik Chauhan 8 | 9 | All rights reserved. 10 | 11 | This software is distributed under the terms and conditions of the 12 | BSD3 license. See the accompanying file LICENSE for exact terms and 13 | condition. 14 | 15 | */ 16 | 17 | #ifndef __RAAZ_CIPHER_SALSA_H_ 18 | #define __RAAZ_CIPHER_SALSA_H_ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | typedef uint8_t Word8; 27 | typedef uint32_t Word32; 28 | typedef uint64_t Word64; 29 | 30 | extern void salsa20_20_word(Word32 out[16],Word32 in[16]); 31 | extern void salsa20_12_word(Word32 out[16],Word32 in[16]); 32 | extern void salsa20_8_word(Word32 out[16],Word32 in[16]); 33 | extern void expand128(Word32 iv[8],Word32 matrix[16]); 34 | extern void expand256(Word32 iv[12],Word32 matrix[16]); 35 | 36 | extern void salsa20_20(Word32 matrix[16], Word8 *input, Word32 bytes); 37 | extern void salsa20_12(Word32 matrix[16], Word8 *input, Word32 bytes); 38 | extern void salsa20_8(Word32 matrix[16], Word8 *input, Word32 bytes); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /liquid/LiquidSpec.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Language.Haskell.Liquid.Liquid 3 | import System.Exit 4 | import System.Directory 5 | import System.FilePath 6 | 7 | -- | Liquid haskell is run on these files/directors. If the given name 8 | -- is a directory we recurse on all .hs/.lhs files in that directory. 9 | toCheck :: [FilePath] 10 | toCheck = [ "Raaz/Core/Encode" 11 | , "Raaz/Core/Types/Tuple.hs" 12 | , "Raaz/Hash/Sha1" 13 | , "Raaz/Hash/Sha224" 14 | , "Raaz/Hash/Sha256" 15 | , "Raaz/Hash/Sha384" 16 | , "Raaz/Hash/Sha512" 17 | ] 18 | 19 | main :: IO () 20 | main = allHsFiles toCheck >>= liquid 21 | 22 | 23 | allHsFiles :: [FilePath] -> IO [FilePath] 24 | allHsFiles = fmap concat . mapM allHsFile 25 | 26 | allHsFile :: FilePath -> IO [FilePath] 27 | allHsFile fp = doesFileExist fp >>= handleFile 28 | 29 | where handleFile cond 30 | | cond && checkHs fp = return [fp] 31 | | cond = return [] 32 | | otherwise = doesDirectoryExist fp >>= handleDir 33 | 34 | handleDir cond 35 | | cond = recurse 36 | | otherwise = return [] 37 | 38 | recurse = listDirectory fp >>= allHsFiles . map (fp) 39 | 40 | checkHs fp = ext == ".hs" || ext == ".lhs" 41 | where ext = takeExtension fp 42 | -------------------------------------------------------------------------------- /tests/Raaz/Core/ByteSourceSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module Raaz.Core.ByteSourceSpec where 3 | 4 | import qualified Data.ByteString as B 5 | import System.IO 6 | import System.IO.Unsafe 7 | 8 | import Tests.Core 9 | 10 | 11 | readResult :: ByteSource src => BYTES Int -> src -> IO (FillResult src) 12 | readResult n src = allocaBuffer n $ fillBytes n src 13 | 14 | {-# NOINLINE readResultPure #-} 15 | readResultPure :: PureByteSource src => BYTES Int -> src -> FillResult src 16 | readResultPure n src = unsafePerformIO $ readResult n src 17 | 18 | devNullExpectation :: Expectation 19 | 20 | #ifdef HAVE_DEV_NULL 21 | devNullExpectation = withBinaryFile "/dev/null" ReadMode (readResult 0) `shouldReturn` (Exhausted 0) 22 | #else 23 | devNullExpectation = pendingWith "Non-posix system needs an equivalent of /dev/null" 24 | #endif 25 | 26 | 27 | spec :: Spec 28 | spec = do 29 | describe "/dev/null" $ 30 | it "should return Exhausted even for a read request of 0" devNullExpectation 31 | 32 | let genL :: [ByteString] -> Gen (BYTES Int) 33 | genL bs = fromIntegral <$> choose (0, sum $ map B.length bs) 34 | in describe "concatenated source" $ 35 | prop "reading from a list is equivalent to reading from concatenation" $ 36 | \ bs -> forAll (genL bs) $ \ n -> (B.concat <$> readResultPure n bs) == readResultPure n (B.concat bs) 37 | -------------------------------------------------------------------------------- /api/encrypt/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | {-# LANGUAGE MultiParamTypeClasses #-} 3 | {-# LANGUAGE FlexibleInstances #-} 4 | {-# LANGUAGE FlexibleContexts #-} 5 | {-# LANGUAGE TypeFamilies #-} 6 | 7 | -- | Implementation of stream ciphers. Since encryption/decryption is 8 | -- done by typically xoring the keystream witht he data, the have two 9 | -- property. 10 | -- 11 | -- 1. Using the same key stream can compromise the safety so typically these 12 | -- primitives take, apart from the key a nounce that needs to be distinct. 13 | -- It is the key nounce pair that should not be reused. 14 | -- 15 | -- 2. They usually can rewind/advace/skip input and perform 16 | -- encryption/decryption. 17 | -- 18 | 19 | signature Implementation where 20 | 21 | import Raaz.Core 22 | 23 | -- | The primitive 24 | data Prim 25 | 26 | -- | The internal memory used by the implementation. 27 | data Internals 28 | instance Memory Internals 29 | 30 | instance Initialisable Internals (Key Prim) 31 | instance Initialisable Internals (Nounce Prim) 32 | instance Initialisable Internals (BlockCount Prim) -- To restore/advance 33 | -- to a particular 34 | -- block in the stream 35 | 36 | instance Extractable Internals (BlockCount Prim) -- To query the position 37 | -------------------------------------------------------------------------------- /tests/Raaz/Digest/Sha256Spec.hs: -------------------------------------------------------------------------------- 1 | 2 | {-# OPTIONS_GHC -fno-warn-orphans #-} 3 | {-# LANGUAGE OverloadedStrings #-} 4 | {-# LANGUAGE ScopedTypeVariables #-} 5 | 6 | module Raaz.Digest.Sha256Spec where 7 | 8 | import Prelude hiding (replicate) 9 | 10 | import Tests.Core 11 | import Sha256.Digest 12 | 13 | spec :: Spec 14 | spec = do 15 | basicEndianSpecs (undefined :: Sha256) 16 | incrementalVsFull 17 | 18 | -- 19 | -- Some unit tests 20 | -- 21 | "" `digestsTo` "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" 22 | 23 | "abc" `digestsTo` "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" 24 | 25 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" `digestsTo` 26 | "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" 27 | 28 | "The quick brown fox jumps over the lazy dog" `digestsTo` 29 | "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592" 30 | 31 | "The quick brown fox jumps over the lazy cog" `digestsTo` 32 | "e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be" 33 | 34 | "The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog" `digestsTo` 35 | "86c55ba51d6b4aef51f4ae956077a0f661d0b876c5774fef3172c4f56092cbbd" 36 | -------------------------------------------------------------------------------- /api/aead/Cipher/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | {-# LANGUAGE MultiParamTypeClasses #-} 3 | {-# LANGUAGE FlexibleInstances #-} 4 | {-# LANGUAGE FlexibleContexts #-} 5 | {-# LANGUAGE TypeFamilies #-} 6 | 7 | -- | Implementation for the cipher part of the AEAD construction. It 8 | -- is assumed that the initialisation of the cipher `Internals` is 9 | -- done in the following order. 10 | -- 11 | -- 1. Initialise the key either using initialise or using the `WriteAccessable` interface 12 | -- 13 | -- 2. Initialise the nounce 14 | -- 15 | -- 3. Initialise the BlockCount 16 | -- 17 | -- In addition to serialise the corresponding locked data we would 18 | -- need Encodable instance for the nounce. 19 | 20 | signature Cipher.Implementation where 21 | 22 | import Raaz.Core 23 | 24 | -- | The primitive 25 | data Prim 26 | 27 | -- | The internal memory used by the implementation. 28 | data Internals 29 | instance Memory Internals 30 | 31 | instance Initialisable Internals (Key Prim) 32 | instance Encodable (Nounce Prim) 33 | 34 | -- | Write access to key is provided. 35 | instance WriteAccessible Internals 36 | instance Initialisable Internals (Nounce Prim) 37 | instance Initialisable Internals (BlockCount Prim) -- To restore/advance 38 | -- to a particular 39 | -- block in the stream 40 | -------------------------------------------------------------------------------- /core/Raaz/Primitive/AEAD/Internal.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | {-# LANGUAGE MultiParamTypeClasses #-} 3 | {-# LANGUAGE DataKinds #-} 4 | -- | 5 | -- 6 | -- Module : Raaz.Primitive.AEAD.Internal 7 | -- Description : Generic interface to authenticated encryption. 8 | -- Copyright : (c) Piyush P Kurur, 2019 9 | -- License : Apache-2.0 OR BSD-3-Clause 10 | -- Maintainer : Piyush P Kurur 11 | -- Stability : experimental 12 | 13 | module Raaz.Primitive.AEAD.Internal 14 | ( AEAD(..), unsafeAEAD 15 | ) where 16 | 17 | 18 | import Data.ByteString 19 | import Raaz.Core 20 | 21 | -- | An authenticated encrypted packet containing a payload of type 22 | -- @plain@ and additional authenticated data of type @aad@. 23 | data AEAD c t = AEAD 24 | { unsafeToNounce :: Nounce c 25 | -- ^ The nounce use to compute this packet. 26 | 27 | , unsafeToCipherText :: ByteString 28 | -- ^ The associated cipher text. 29 | 30 | , unsafeToAuthTag :: t 31 | -- ^ The associated authentication tag. 32 | 33 | } 34 | 35 | -- | Create an AEAD packet from the underlying authentication tag and 36 | -- cipher text. 37 | unsafeAEAD :: Nounce c 38 | -> ByteString 39 | -> t -- ^ the authentication tag 40 | -> AEAD c t 41 | unsafeAEAD = AEAD 42 | -------------------------------------------------------------------------------- /raaz/bin/Main.hs: -------------------------------------------------------------------------------- 1 | -- 2 | -- The main function that drives other commands. 3 | -- 4 | 5 | import Data.Version (showVersion) 6 | import Options.Applicative 7 | import Prelude 8 | import Raaz (version) 9 | 10 | import Command.Checksum 11 | import Command.Info 12 | import Command.Rand 13 | 14 | 15 | data Option = ShowVersion 16 | | RunCommand (IO ()) 17 | 18 | progOption :: Parser Option 19 | progOption = flag ShowVersion ShowVersion versionMods 20 | <|> RunCommand <$> rand 21 | <|> RunCommand <$> checksum 22 | <|> RunCommand <$> information 23 | 24 | where versionMods = mconcat [ short 'v' 25 | , long "version" 26 | , help "Print the version of the raaz library used" 27 | ] 28 | 29 | ---------------------- The main function and stuff ------------------------------ 30 | run :: Option -> IO () 31 | run ShowVersion = putStrLn $ "raaz version " ++ showVersion version 32 | run (RunCommand cmd) = cmd 33 | 34 | 35 | main :: IO () 36 | main = execParser opts >>= run 37 | where opts = info (helper <*> progOption) 38 | $ mconcat [ fullDesc 39 | , header "raaz - A command line interface to the raaz cryptographic library." 40 | , footer "Homepage: http://github.com/raaz-crypto" 41 | ] 42 | -------------------------------------------------------------------------------- /tests/message-digest/Tests/Digest.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | {-# LANGUAGE MonoLocalBinds #-} 3 | {-# LANGUAGE DataKinds #-} 4 | {-# LANGUAGE ScopedTypeVariables #-} 5 | -- Generic tests for hash. 6 | 7 | module Tests.Digest 8 | ( digestsTo 9 | , incrementalVsFull 10 | ) where 11 | 12 | import Implementation 13 | import Interface 14 | 15 | import Tests.Core 16 | 17 | 18 | 19 | digestsTo :: ByteString 20 | -> Prim 21 | -> Spec 22 | digestsTo str h = it msg (digest str `shouldBe` h) 23 | where msg = unwords [ "hashes" 24 | , shortened $ show str 25 | , "to" 26 | , shortened $ show h 27 | ] 28 | 29 | incrDigest :: ByteString 30 | -> IO Prim 31 | incrDigest bs = withMemory $ \ (cxt :: DigestCxt 1) -> 32 | do startDigest cxt 33 | updateDigest bs cxt 34 | finaliseDigest cxt 35 | 36 | incrDigestList :: [ByteString] 37 | -> IO Prim 38 | incrDigestList bsL = withMemory $ \ (cxt :: DigestCxt 1) -> 39 | do startDigest cxt 40 | mapM_ (`updateDigest` cxt) bsL 41 | finaliseDigest cxt 42 | 43 | incrementalVsFull :: Spec 44 | incrementalVsFull = describe "Incremental vs Full digest" $ do 45 | prop "for single source" $ 46 | \ bs -> incrDigest bs `shouldReturn` digest bs 47 | 48 | prop "for multiple source" $ 49 | \ bsL -> incrDigestList bsL `shouldReturn` digest bsL 50 | -------------------------------------------------------------------------------- /implementation/cbits/raaz/cipher/chacha20/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef uint32_t Word; 8 | typedef Word State[16]; 9 | typedef Word Block[16]; 10 | 11 | /* Implementation in accordance to RFC7539 12 | * https://tools.ietf.org/html/rfc7539 13 | * 14 | * Note that there is a difference in the rfc and the version 15 | * published by djb. In the rfc one uses 32-bit counter and 96-bit 16 | * nounce, whereas the published version of djb uses 64bit counter and 17 | * 64bit nounce. 18 | * 19 | * As a result the maximum data that should be encrypted with this 20 | * cipher (for a given key, iv pair). 21 | * 22 | * 2^32 blocks = 256 GB. 23 | * 24 | */ 25 | 26 | typedef uint32_t Counter; 27 | typedef Word IV[3]; 28 | typedef Word Key[8]; 29 | 30 | # define BLOCK_SIZE (sizeof(State)) 31 | 32 | #define C0 ((Word) 0x61707865) 33 | #define C1 ((Word) 0x3320646e) 34 | #define C2 ((Word) 0x79622d32) 35 | #define C3 ((Word) 0x6b206574) 36 | 37 | 38 | /* Vector types */ 39 | 40 | # ifdef HAVE_VECTOR_128 41 | /* Type of 128-bit SIMD instructions */ 42 | typedef Word Vec __attribute__ ((vector_size (16))); 43 | # endif 44 | 45 | # ifdef HAVE_VECTOR_256 46 | /* Type of 256-bit SIMD instructions */ 47 | typedef Word Vec2 __attribute__ ((vector_size (32))); 48 | # endif 49 | 50 | # ifdef HAVE_VECTOR_512 51 | /* Type of 512-bit SIMD instructions */ 52 | typedef Word Vec4 __attribute__ ((vector_size (64))); 53 | # endif 54 | -------------------------------------------------------------------------------- /core/Raaz/Core/Types/Internal.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_HADDOCK show-extensions #-} 2 | -- | 3 | -- 4 | -- Module : Raaz.Core.Types.Internal 5 | -- Copyright : (c) Piyush P Kurur, 2018 6 | -- License : Apache-2.0 OR BSD-3-Clause 7 | -- Maintainer : Piyush P Kurur 8 | -- Stability : experimental 9 | -- 10 | -- 11 | -- __WARNING:__ There is very little reason for importing this 12 | -- module even if you are a developer of raaz let alone a user. The one 13 | -- place where you enhance type safety by importing this module is where 14 | -- you define FFI calls --- consider this FFI call to memcpy 15 | -- 16 | -- > 17 | -- > foreign import ccall unsafe "string.h memcpy" c_memcpy 18 | -- > :: Dest Pointer -> Src Pointer -> BYTES Int -> IO Pointer 19 | -- 20 | -- instead of this 21 | -- 22 | -- > 23 | -- > foreign import ccall unsafe "string.h memcpy" c_memcpy 24 | -- > :: Pointer -> Pointer -> Int -> IO Pointer 25 | 26 | module Raaz.Core.Types.Internal 27 | ( module Raaz.Core.Primitive 28 | , module Raaz.Core.Types.Endian.Internal 29 | , module Raaz.Core.Types.Pointer.Internal 30 | , module Raaz.Core.Types.Copying 31 | , module Raaz.Core.Types.Tuple 32 | ) where 33 | 34 | import Raaz.Core.Primitive ( BlockCount (..) ) 35 | import Raaz.Core.Types.Endian.Internal ( LE(..), BE(..) ) 36 | 37 | import Raaz.Core.Types.Pointer.Internal 38 | ( AlignedPtr (..) 39 | , BYTES(..) 40 | ) 41 | 42 | import Raaz.Core.Types.Copying ( Src(..), Dest(..) ) 43 | import Raaz.Core.Types.Tuple 44 | -------------------------------------------------------------------------------- /api/digest/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE KindSignatures #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE FlexibleInstances #-} 6 | {-# LANGUAGE TypeFamilies #-} 7 | 8 | -- | This signature imposes additional constraints on the primitive to 9 | -- make it possible to use it as a message digest. Here is the list. 10 | -- 11 | -- 1. The `Prim` type captures the message digest and hence should be 12 | -- instances of `Eq`, so that we can compare messages by checking 13 | -- the digest, `Equality`, so that the equality comparison can be 14 | -- made timing safe when part of a compound data, and `Encodable` 15 | -- so that we can serialise the digest into a byte string. 16 | -- 17 | -- 2. To start the process of computing the message digest the 18 | -- `Internal` state of the implementation should use initialised by 19 | -- @()@. 20 | -- 21 | -- 3. At the end of the message, the digest, which recall is captured 22 | -- by the type `Prim` should be extracted from the internal state. 23 | -- 24 | 25 | signature Implementation where 26 | 27 | 28 | import Raaz.Core 29 | 30 | -- | The primitive. 31 | data Prim 32 | 33 | instance Eq Prim 34 | instance Equality Prim 35 | instance Encodable Prim 36 | 37 | -- | The internal memory used by the primitive. 38 | data Internals 39 | instance Memory Internals 40 | 41 | 42 | instance Initialisable Internals () 43 | instance Extractable Internals Prim 44 | -------------------------------------------------------------------------------- /api/auth/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE KindSignatures #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE FlexibleInstances #-} 6 | {-# LANGUAGE TypeFamilies #-} 7 | 8 | -- | This signature imposes additional constraints on the primitive to 9 | -- make it possible to use it as a message authenticator. Here is the list. 10 | -- 11 | -- 1. The `Prim` type captures the message authentication code and 12 | -- hence should be instances of `Eq`, so that we can compare 13 | -- messages by checking the digest, `Equality`, so that the 14 | -- equality comparison can be made timing safe when part of a 15 | -- compound data, and `Encodeable` so that we can serialise the 16 | -- authentication code to a byte string. 17 | -- 18 | -- 2. To start the process of computing the message authentication, 19 | -- the `Internal` state of the implementation should be initialised 20 | -- using the secret key. 21 | -- 22 | -- 3. At the end of the message, the authentication code, which recall 23 | -- is captured by the type `Prim` should be extractable from the 24 | -- internal state. 25 | -- 26 | 27 | signature Implementation where 28 | 29 | import Raaz.Core 30 | 31 | data Prim 32 | data Internals 33 | 34 | 35 | instance Equality Prim 36 | instance Eq Prim 37 | instance Encodable Prim 38 | 39 | instance Memory Internals 40 | instance Initialisable Internals (Key Prim) 41 | instance Extractable Internals Prim 42 | -------------------------------------------------------------------------------- /tests/auth/Tests/Auth.hs: -------------------------------------------------------------------------------- 1 | -- Generic tests for hash. 2 | {-# LANGUAGE FlexibleContexts #-} 3 | {-# LANGUAGE MonoLocalBinds #-} 4 | {-# LANGUAGE DataKinds #-} 5 | {-# LANGUAGE ScopedTypeVariables #-} 6 | 7 | module Tests.Auth 8 | ( authsTo 9 | , incrementalVsFull 10 | , auth 11 | ) where 12 | 13 | import Implementation 14 | import Interface 15 | import Tests.Core 16 | 17 | authsTo :: ByteString 18 | -> Prim 19 | -> Key Prim 20 | -> Spec 21 | authsTo str prim key = it msg (auth key str `shouldBe` prim) 22 | where msg = unwords [ "authenticates" 23 | , shortened $ show str 24 | , "to" 25 | , shortened $ show prim 26 | ] 27 | 28 | 29 | incrDigest :: Key Prim 30 | -> ByteString 31 | -> IO Prim 32 | incrDigest k bs = withMemory $ \ (cxt :: AuthCxt 1) -> 33 | do startAuth k cxt 34 | updateAuth bs cxt 35 | finaliseAuth cxt 36 | 37 | incrDigestList :: Key Prim 38 | -> [ByteString] 39 | -> IO Prim 40 | incrDigestList k bsL = withMemory $ \ (cxt :: AuthCxt 1) -> 41 | do startAuth k cxt 42 | mapM_ (`updateAuth` cxt) bsL 43 | finaliseAuth cxt 44 | 45 | incrementalVsFull :: Spec 46 | incrementalVsFull = describe "Incremental vs Full authenticator" $ do 47 | prop "for single source" $ 48 | \ k bs -> incrDigest k bs `shouldReturn` auth k bs 49 | 50 | prop "for multiple source" $ 51 | \ k bsL -> incrDigestList k bsL `shouldReturn` auth k bsL 52 | -------------------------------------------------------------------------------- /LICENSE-BSD3: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, Piyush P Kurur 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Piyush P Kurur nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /tests/Raaz/Core/Util/ByteStringSpec.hs: -------------------------------------------------------------------------------- 1 | module Raaz.Core.Util.ByteStringSpec where 2 | 3 | import Tests.Core 4 | import Prelude hiding (length, take) 5 | import Data.ByteString.Internal(createAndTrim) 6 | import qualified Data.ByteString as B 7 | import Foreign.Ptr 8 | 9 | import Raaz.Core as RC 10 | import Raaz.Core.Types.Internal (BYTES (..)) 11 | 12 | 13 | spec :: Spec 14 | spec = do context "unsafeCopyToPointer" $ 15 | it "creates the same copy at the input pointer" 16 | $ feed arbitrary $ \ bs -> (== bs) <$> clone bs 17 | 18 | let gen = do bs <- arbitrary 19 | l <- choose (0, B.length bs) 20 | return (bs, l) 21 | in context "unsafeNCopyToPointer" 22 | $ it "creates the same prefix of at the input pointer" 23 | $ feed gen $ \ (bs,n) -> (==) (B.take n bs) 24 | <$> clonePrefix (bs,n) 25 | 26 | context "createFrom" 27 | $ it "reads exactly the same bytes from the byte string pointer" 28 | $ feed arbitrary $ \ bs -> (==bs) <$> readFrom bs 29 | 30 | where clone bs = create (length bs) $ RC.unsafeCopyToPointer bs . castPtr 31 | clonePrefix (bs,n) 32 | = createAndTrim (B.length bs) 33 | $ \ cptr -> do RC.unsafeNCopyToPointer (BYTES n) bs 34 | $ castPtr cptr 35 | return n 36 | readFrom bs = RC.withByteString bs 37 | $ RC.createFrom (RC.length bs) 38 | -------------------------------------------------------------------------------- /benchmarks/Main.hs: -------------------------------------------------------------------------------- 1 | -- | This module benchmarks all block function and shows the 2 | 3 | import Control.Monad 4 | 5 | import Prelude 6 | import System.IO 7 | import Text.PrettyPrint 8 | 9 | import Benchmark.Types 10 | import qualified Benchmark.Blake2b.CPortable as Blake2bCP 11 | import qualified Benchmark.Blake2b.CHandWritten as Blake2bCHW 12 | 13 | import qualified Benchmark.Blake2s.CHandWritten as Blake2sCHW 14 | 15 | import qualified Benchmark.ChaCha20.CPortable as ChaCha20CP 16 | import qualified Benchmark.ChaCha20.CHandWritten as ChaCha20CHW 17 | 18 | import qualified Benchmark.Poly1305.CPortable as Poly1305CP 19 | 20 | import qualified Benchmark.Sha256.CPortable as Sha256CP 21 | import qualified Benchmark.Sha256.CHandWritten as Sha256CHW 22 | 23 | import qualified Benchmark.Sha512.CPortable as Sha512CP 24 | import qualified Benchmark.Sha512.CHandWritten as Sha512CHW 25 | 26 | import qualified Benchmark.CSPRG.CPortable as CSPRGCP 27 | 28 | 29 | main :: IO () 30 | main = do 31 | hSetEncoding stdout utf8 32 | putStrLn $ render header 33 | mapM_ printBench [ Blake2bCP.bench 34 | , Blake2bCHW.bench 35 | 36 | , Blake2sCHW.bench 37 | 38 | , Poly1305CP.bench 39 | 40 | , CSPRGCP.bench 41 | 42 | , ChaCha20CP.bench 43 | , ChaCha20CHW.bench 44 | 45 | , Sha256CP.bench 46 | , Sha256CHW.bench 47 | 48 | , Sha512CP.bench 49 | , Sha512CHW.bench 50 | ] 51 | 52 | where printBench = runRaazBench >=> pure . render >=> putStrLn 53 | -------------------------------------------------------------------------------- /tests/Raaz/Core/EncodeSpec.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fno-warn-orphans #-} 2 | {-# LANGUAGE ScopedTypeVariables #-} 3 | {-# LANGUAGE OverloadedStrings #-} 4 | module Raaz.Core.EncodeSpec where 5 | 6 | import Tests.Core 7 | import qualified Data.ByteString as B 8 | 9 | shouldBeAMultipleOf :: Int -> Int -> Bool 10 | shouldBeAMultipleOf m x = m `rem` x == 0 11 | 12 | shouldEncodeTo :: (Format fmt, Eq fmt) => ByteString -> fmt -> Spec 13 | shouldEncodeTo bs e = it msg $ encodeByteString bs `shouldBe` e 14 | where msg = show bs ++ " should encode to " ++ show e 15 | 16 | spec :: Spec 17 | spec = do 18 | describe "Base16" $ do 19 | prop "encoded string is always of even length" $ \ (x :: Base16) -> 20 | B.length (toByteString x) `shouldBeAMultipleOf` 2 21 | 22 | prop "unsafeFromByteString . toByteString = id" $ \ (x :: Base16) -> 23 | unsafeFromByteString (toByteString x) `shouldBe` x 24 | 25 | prop "correctly encodes a 64-bit big endian word." $ \ (w :: Word64) -> 26 | read ("0x" ++ showBase16 (bigEndian w)) == w 27 | 28 | 29 | describe "Base64" $ do 30 | prop "encoded string is always divisible by 4" $ \ (x :: Base64) -> 31 | B.length (toByteString x) `shouldBeAMultipleOf` 4 32 | 33 | prop "unsafeFromByteString . toByteString = id" $ \ (x :: Base16) -> 34 | unsafeFromByteString (toByteString x) `shouldBe` x 35 | 36 | describe "examples" $ do 37 | "pleasure." `shouldEncodeTo` ("cGxlYXN1cmUu" :: Base64) 38 | "leasure." `shouldEncodeTo` ("bGVhc3VyZS4=" :: Base64) 39 | "easure." `shouldEncodeTo` ("ZWFzdXJlLg==" :: Base64) 40 | "asure." `shouldEncodeTo` ("YXN1cmUu" :: Base64) 41 | "sure." `shouldEncodeTo` ("c3VyZS4=" :: Base64) 42 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1731533236, 9 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1739736696, 24 | "narHash": "sha256-zON2GNBkzsIyALlOCFiEBcIjI4w38GYOb+P+R4S8Jsw=", 25 | "owner": "NixOS", 26 | "repo": "nixpkgs", 27 | "rev": "d74a2335ac9c133d6bbec9fc98d91a77f1604c1f", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "NixOS", 32 | "ref": "nixos-unstable", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "flake-utils": "flake-utils", 40 | "nixpkgs": "nixpkgs" 41 | } 42 | }, 43 | "systems": { 44 | "locked": { 45 | "lastModified": 1681028828, 46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 47 | "owner": "nix-systems", 48 | "repo": "default", 49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "nix-systems", 54 | "repo": "default", 55 | "type": "github" 56 | } 57 | } 58 | }, 59 | "root": "root", 60 | "version": 7 61 | } 62 | -------------------------------------------------------------------------------- /tests/Raaz/Digest/Sha512Spec.hs: -------------------------------------------------------------------------------- 1 | 2 | {-# OPTIONS_GHC -fno-warn-orphans #-} 3 | {-# LANGUAGE OverloadedStrings #-} 4 | {-# LANGUAGE ScopedTypeVariables #-} 5 | 6 | module Raaz.Digest.Sha512Spec where 7 | 8 | import Prelude hiding (replicate) 9 | 10 | 11 | import Tests.Core 12 | import Sha512.Digest 13 | 14 | 15 | spec :: Spec 16 | spec = do 17 | basicEndianSpecs (undefined :: Sha512) 18 | incrementalVsFull 19 | 20 | -- 21 | -- Some unit tests 22 | -- 23 | "" `digestsTo` 24 | "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" 25 | 26 | "abc" `digestsTo` 27 | "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" 28 | 29 | "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" `digestsTo` 30 | "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" 31 | 32 | "The quick brown fox jumps over the lazy dog" `digestsTo` 33 | "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6" 34 | 35 | "The quick brown fox jumps over the lazy cog" `digestsTo` 36 | "3eeee1d0e11733ef152a6c29503b3ae20c4f1f3cda4cb26f1bc1a41f91c7fe4ab3bd86494049e201c4bd5155f31ecb7a3c8606843c4cc8dfcab7da11c8ae5045" 37 | 38 | "The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog" `digestsTo` 39 | "e489dcc2e8867d0bbeb0a35e6b94951a11affd7041ef39fa21719eb01800c29a2c3522924443939a7848fde58fb1dbd9698fece092c0c2b412c51a47602cfd38" 40 | -------------------------------------------------------------------------------- /implementation/Sha512/CPortable.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | 3 | -- | The portable C-implementation of Sha512. 4 | module Sha512.CPortable 5 | ( name, primName, description 6 | , Prim, Internals, BufferAlignment 7 | , BufferPtr 8 | , additionalBlocks 9 | , processBlocks 10 | , processLast 11 | ) where 12 | 13 | import Foreign.Ptr ( castPtr ) 14 | 15 | import Raaz.Core 16 | import Raaz.Core.Types.Internal 17 | 18 | import Raaz.Primitive.HashMemory 19 | import Raaz.Primitive.Sha2.Internal (Sha512, Sha512Mem, process512Last) 20 | 21 | import Raaz.Verse.Sha512.C.Portable 22 | 23 | 24 | name :: String 25 | name = "libverse-c" 26 | 27 | primName :: String 28 | primName = "sha512" 29 | 30 | description :: String 31 | description = "Sha512 Implementation in C exposed by libverse" 32 | 33 | type Prim = Sha512 34 | type Internals = Sha512Mem 35 | type BufferAlignment = 32 36 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 37 | 38 | additionalBlocks :: BlockCount Sha512 39 | additionalBlocks = blocksOf 1 Proxy 40 | 41 | compressBlocks :: BufferPtr 42 | -> BlockCount Sha512 43 | -> Internals 44 | -> IO () 45 | compressBlocks buf blks mem = let hPtr = castPtr $ hashCell128Pointer mem 46 | blkPtr = castPtr $ forgetAlignment buf 47 | wBlks = toEnum $ fromEnum blks 48 | in verse_sha512_c_portable blkPtr wBlks hPtr 49 | 50 | processBlocks :: BufferPtr 51 | -> BlockCount Sha512 52 | -> Internals 53 | -> IO () 54 | processBlocks buf blks mem = compressBlocks buf blks mem >> updateLength128 blks mem 55 | 56 | 57 | 58 | -- | Process the last bytes. 59 | processLast :: BufferPtr 60 | -> BYTES Int 61 | -> Internals 62 | -> IO () 63 | processLast = process512Last processBlocks 64 | -------------------------------------------------------------------------------- /old-raaz/Raaz/Hash/Sha1/Internal.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 4 | {-# LANGUAGE TypeFamilies #-} 5 | {-# LANGUAGE FlexibleInstances #-} 6 | 7 | {-# LANGUAGE MultiParamTypeClasses #-} 8 | {-# CFILES raaz/hash/sha1/portable.c #-} 9 | 10 | {-| 11 | 12 | This module exposes the `SHA1` hash constructor. You would hardly need 13 | to import the module directly as you would want to treat the `SHA1` 14 | type as an opaque type for type safety. This module is exported only 15 | for special uses like writing a test case or defining a binary 16 | instance etc. 17 | 18 | -} 19 | 20 | module Raaz.Hash.Sha1.Internal (SHA1(..)) where 21 | 22 | import Data.String 23 | import Data.Word 24 | import Foreign.Storable ( Storable(..) ) 25 | 26 | import Raaz.Core 27 | 28 | import Raaz.Hash.Internal 29 | 30 | -- | The cryptographic hash SHA1. 31 | newtype SHA1 = SHA1 (Tuple 5 (BE Word32)) 32 | deriving (Storable, EndianStore, Equality, Eq) 33 | 34 | instance Encodable SHA1 35 | 36 | instance IsString SHA1 where 37 | fromString = fromBase16 38 | 39 | instance Show SHA1 where 40 | show = showBase16 41 | 42 | instance Initialisable (HashMemory SHA1) () where 43 | initialise _ = initialise $ SHA1 $ unsafeFromList [ 0x67452301 44 | , 0xefcdab89 45 | , 0x98badcfe 46 | , 0x10325476 47 | , 0xc3d2e1f0 48 | ] 49 | 50 | 51 | instance Primitive SHA1 where 52 | type BlockSize SHA1 = 64 53 | type Implementation SHA1 = SomeHashI SHA1 54 | type Key SHA1 = () 55 | type Digest SHA1 = SHA1 56 | 57 | instance Hash SHA1 where 58 | additionalPadBlocks _ = toEnum 1 59 | -------------------------------------------------------------------------------- /implementation/Sha256/CPortable.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | 3 | -- | The portable C-implementation of Sha256. 4 | module Sha256.CPortable 5 | ( name, primName, description 6 | , Prim, Internals, BufferAlignment 7 | , BufferPtr 8 | , additionalBlocks 9 | , processBlocks 10 | , processLast 11 | ) where 12 | 13 | import Foreign.Ptr ( castPtr ) 14 | 15 | import Raaz.Core 16 | import Raaz.Core.Types.Internal 17 | 18 | import Raaz.Primitive.HashMemory 19 | import Raaz.Primitive.Sha2.Internal (Sha256, Sha256Mem, process256Last) 20 | 21 | import Raaz.Verse.Sha256.C.Portable 22 | 23 | name :: String 24 | name = "libverse-c" 25 | 26 | primName :: String 27 | primName = "sha256" 28 | 29 | description :: String 30 | description = "Sha256 Implementation in C exposed by libverse" 31 | 32 | type Prim = Sha256 33 | type Internals = Sha256Mem 34 | type BufferAlignment = 32 35 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 36 | 37 | additionalBlocks :: BlockCount Sha256 38 | additionalBlocks = blocksOf 1 Proxy 39 | 40 | -- | The compression algorithm. 41 | compressBlocks :: BufferPtr 42 | -> BlockCount Sha256 43 | -> Internals 44 | -> IO () 45 | compressBlocks buf blks mem = let hPtr = castPtr $ hashCellPointer mem 46 | blkPtr = castPtr $ forgetAlignment buf 47 | wBlks = toEnum $ fromEnum blks 48 | in verse_sha256_c_portable blkPtr wBlks hPtr 49 | 50 | 51 | processBlocks :: BufferPtr 52 | -> BlockCount Sha256 53 | -> Internals 54 | -> IO () 55 | processBlocks buf blks mem = compressBlocks buf blks mem >> updateLength blks mem 56 | 57 | -- | Process the last bytes. 58 | processLast :: BufferPtr 59 | -> BYTES Int 60 | -> Internals 61 | -> IO () 62 | processLast = process256Last processBlocks 63 | -------------------------------------------------------------------------------- /api/encrypt/Interface.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | 3 | -- | The interface for a stream cipher. For stream ciphers, both 4 | -- encrypt and decrypt are same. One of the advantage of stream cipher 5 | -- is that it allows rewinding/advancing the stream before encrypting 6 | -- and decryption. This interface also supports such 7 | -- rewinding/advancing. 8 | module Interface( Cipher 9 | , encrypt 10 | , decrypt 11 | , encryptAt 12 | , decryptAt 13 | , name 14 | , description 15 | ) where 16 | 17 | import Data.ByteString 18 | import System.IO.Unsafe ( unsafePerformIO ) 19 | 20 | import Raaz.Core 21 | import Implementation 22 | 23 | import qualified Utils as U 24 | 25 | type Cipher = Implementation.Prim 26 | 27 | -- | Encrypt using the cipher. 28 | encrypt :: Key Prim -- ^ The key for the stream cipher 29 | -> Nounce Prim -- ^ The nounce used by the stream cipher. 30 | -> ByteString -- ^ The bytestring to process 31 | -> ByteString 32 | encrypt key nounce = encryptAt key nounce mempty 33 | 34 | -- | Same as encrypt but first advances so many blocks. 35 | encryptAt :: Key Prim 36 | -> Nounce Prim 37 | -> BlockCount Prim 38 | -> ByteString 39 | -> ByteString 40 | encryptAt key nounce blk bs = unsafePerformIO $ withMemory $ \ mem -> do 41 | initialise key mem 42 | initialise nounce mem 43 | initialise blk mem 44 | U.transform bs mem 45 | 46 | -- | Same as decrypt but first advance so many blocks. 47 | decryptAt :: Key Prim 48 | -> Nounce Prim 49 | -> BlockCount Prim 50 | -> ByteString 51 | -> ByteString 52 | decryptAt = encryptAt 53 | 54 | -- | Decrypt using the cipher. Since we are concerned with stream 55 | -- ciphers both encrypt and decrypt are the same. 56 | decrypt :: Key Prim 57 | -> Nounce Prim 58 | -> ByteString 59 | -> ByteString 60 | decrypt = encrypt 61 | -------------------------------------------------------------------------------- /Releasing.md: -------------------------------------------------------------------------------- 1 | # Checklist for releasing. 2 | 3 | ## Pre-release checklist. 4 | 5 | Suppose that the release that one wants to do is version A.B.C. We 6 | assume that the current master has all the necessary changes except 7 | the release specific ones. The workflow is to start with a release 8 | branch which we will call release-A.B.C. 9 | 10 | * On the master branch edit the travis.yml to start building on the 11 | release-A.B.C even before creating it. This ensures all release 12 | specific changes that are pushed to the release-A.B.C branch will be 13 | built by travis. 14 | 15 | * Create a fresh branch titled release-A.B.C. 16 | 17 | * Go over the bug-tracker for bugs to be addressed for this release. 18 | mark them. 19 | 20 | * A pending change log entry should already be there for this entry. 21 | Please review it. 22 | 23 | * Hack and get the project to shape. 24 | 25 | * When ready merge to the master as a non-ff merge. 26 | 27 | ## Candidate release. 28 | 29 | Hackage supports candidate releases which we should be making use of. 30 | Here is a set of steps that can be done with a candidate release that 31 | can help in doing a high quality release 32 | 33 | 1. Make sure to trigger a documentation build for the candidate on 34 | hackage. This is currently not automated but would likely be the 35 | case. 36 | 37 | 2. The package build matrix is likely to be operational for candidate 38 | packages as well. This gives good package compatibility hints for 39 | high quality release. 40 | 41 | 3. Get down-stream packagers to make an experimental upload of the 42 | package into their CI system. Distributions like Debian often do 43 | have multi-arch builds and also add builds across other platforms 44 | like Hurd, kFreeBSD etc. Successful builds 45 | 46 | 47 | ## Post release 48 | 49 | * Upload the release on hackage. 50 | 51 | * Tag the release branch. Put the change log in the tag message. 52 | 53 | * Bump up the release version and also the version on the man page. 54 | 55 | * Create a pending entry for the next release in the Change log. 56 | -------------------------------------------------------------------------------- /implementation/Sha256/CHandWritten.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | {-# LANGUAGE DataKinds #-} 3 | 4 | -- | The portable C-implementation of Sha256. 5 | module Sha256.CHandWritten 6 | ( name, primName, description 7 | , Prim, Internals, BufferAlignment 8 | , BufferPtr 9 | , additionalBlocks 10 | , processBlocks 11 | , processLast 12 | ) where 13 | 14 | import Raaz.Core 15 | import Raaz.Core.Types.Internal 16 | import Raaz.Primitive.HashMemory 17 | import Raaz.Primitive.Sha2.Internal (Sha256, Sha256Mem, process256Last) 18 | 19 | name :: String 20 | name = "handwritten-c" 21 | 22 | primName :: String 23 | primName = "sha256" 24 | 25 | description :: String 26 | description = "Hand written Sha256 Implementation using portable C and Haskell FFI" 27 | 28 | type Prim = Sha256 29 | type Internals = Sha256Mem 30 | type BufferAlignment = 32 31 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 32 | 33 | additionalBlocks :: BlockCount Sha256 34 | additionalBlocks = blocksOf 1 Proxy 35 | 36 | ------------------------ The foreign function calls --------------------- 37 | 38 | foreign import ccall unsafe 39 | "raaz/hash/sha256/portable.h raazHashSha256PortableCompress" 40 | c_sha256_compress :: BufferPtr 41 | -> BlockCount Sha256 42 | -> Ptr Sha256 43 | -> IO () 44 | 45 | 46 | compressBlocks :: BufferPtr 47 | -> BlockCount Sha256 48 | -> Internals 49 | -> IO () 50 | compressBlocks buf blks = c_sha256_compress buf blks . hashCellPointer 51 | 52 | 53 | processBlocks :: BufferPtr 54 | -> BlockCount Sha256 55 | -> Internals 56 | -> IO () 57 | processBlocks buf blks mem = compressBlocks buf blks mem >> updateLength blks mem 58 | 59 | -- | Process the last bytes. 60 | processLast :: BufferPtr 61 | -> BYTES Int 62 | -> Internals 63 | -> IO () 64 | processLast = process256Last processBlocks 65 | -------------------------------------------------------------------------------- /implementation/Sha512/CHandWritten.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | {-# LANGUAGE DataKinds #-} 3 | 4 | -- | The portable C-implementation of Sha512. 5 | module Sha512.CHandWritten 6 | ( name, primName, description 7 | , Prim, Internals, BufferAlignment 8 | , BufferPtr 9 | , additionalBlocks 10 | , processBlocks 11 | , processLast 12 | ) where 13 | 14 | import Raaz.Core 15 | import Raaz.Core.Types.Internal 16 | import Raaz.Primitive.HashMemory 17 | import Raaz.Primitive.Sha2.Internal (Sha512, Sha512Mem, process512Last) 18 | 19 | name :: String 20 | name = "handwritten-c" 21 | 22 | primName :: String 23 | primName = "sha512" 24 | 25 | description :: String 26 | description = "Hand written Sha512 Implementation using portable C and Haskell FFI" 27 | 28 | type Prim = Sha512 29 | type Internals = Sha512Mem 30 | type BufferAlignment = 32 31 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 32 | 33 | additionalBlocks :: BlockCount Sha512 34 | additionalBlocks = blocksOf 1 Proxy 35 | 36 | ------------------------ The foreign function calls --------------------- 37 | 38 | foreign import ccall unsafe 39 | "raaz/hash/sha512/portable.h raazHashSha512PortableCompress" 40 | c_sha512_compress :: BufferPtr 41 | -> BlockCount Sha512 42 | -> Ptr Sha512 43 | -> IO () 44 | 45 | 46 | compressBlocks :: BufferPtr 47 | -> BlockCount Sha512 48 | -> Internals 49 | -> IO () 50 | compressBlocks buf blks = c_sha512_compress buf blks . hashCell128Pointer 51 | 52 | 53 | processBlocks :: BufferPtr 54 | -> BlockCount Sha512 55 | -> Internals 56 | -> IO () 57 | processBlocks buf blks mem = compressBlocks buf blks mem >> updateLength128 blks mem 58 | 59 | -- | Process the last bytes. 60 | processLast :: BufferPtr 61 | -> BYTES Int 62 | -> Internals 63 | -> IO () 64 | processLast = process512Last processBlocks 65 | -------------------------------------------------------------------------------- /implementation/entropy/windows/Entropy.hsc: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module Entropy( getEntropy, entropySource ) where 3 | 4 | #include 5 | #include 6 | 7 | ##if defined(i386_HOST_ARCH) 8 | ## define WINDOWS_CCONV stdcall 9 | ##elif defined(x86_64_HOST_ARCH) 10 | ## define WINDOWS_CCONV ccall 11 | ##else 12 | ## error Unknown mingw32 arch 13 | ##endif 14 | 15 | import Foreign.Ptr (Ptr(), nullPtr, castPtr) 16 | import Foreign.Storable (peek) 17 | import Foreign.C.String (CWString()) 18 | import Raaz.Core.Prelude 19 | import Raaz.Core 20 | import Raaz.Core.Types.Internal 21 | 22 | type HCRYPTPROV = Ptr () 23 | 24 | -- | The name of the source from which entropy is gathered. For 25 | -- information purposes only. 26 | entropySource :: String 27 | entropySource = "CryptGenRandom(windows)" 28 | 29 | foreign import WINDOWS_CCONV unsafe "Wincrypt.h CryptGenRandom" 30 | c_CryptGenRandom :: HCRYPTPROV -> Word32 -> Ptr Word8 -> IO Bool 31 | 32 | foreign import WINDOWS_CCONV unsafe "Wincrypt.h CryptAcquireContextW" 33 | c_CryptAcquireContext :: Ptr HCRYPTPROV -> CWString -> CWString 34 | -> Word32 -> Word32 -> IO Bool 35 | 36 | foreign import WINDOWS_CCONV unsafe "Wincrypt.h CryptReleaseContext" 37 | c_CryptReleaseContext :: HCRYPTPROV -> Word32 -> IO Bool 38 | 39 | -- | Get cryptographically random bytes from the system. 40 | getEntropy :: BYTES Int -> Ptr Word8 -> IO (BYTES Int) 41 | getEntropy l ptr = allocaBuffer ptrSize $ \ctx -> 42 | do let addr = castPtr ctx 43 | ctx_ok <- c_CryptAcquireContext addr nullPtr nullPtr 44 | (#const PROV_RSA_FULL) 45 | ((#const CRYPT_VERIFYCONTEXT) .|. (#const CRYPT_SILENT)) 46 | when (not ctx_ok) $ fail "Call to CryptAcquireContext failed." 47 | ctx' <- peek addr 48 | success <- c_CryptGenRandom ctx' (fromIntegral l) (castPtr ptr) 49 | _ <- c_CryptReleaseContext ctx' 0 50 | if success 51 | then return $ l 52 | else fail "Unable to generate entropy. Call to CryptGenRandom failed." 53 | where ptrSize = BYTES ((#size HCRYPTPROV) :: Int) 54 | -------------------------------------------------------------------------------- /raaz/Raaz/AuthEncrypt/Unsafe.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- Module : Raaz.AuthEncrypt.Unsafe 3 | -- Copyright : (c) Piyush P Kurur, 2016 4 | -- License : Apache-2.0 OR BSD-3-Clause 5 | -- Maintainer : Piyush P Kurur 6 | -- Stability : experimental 7 | -- 8 | module Raaz.AuthEncrypt.Unsafe 9 | ( -- * Explicit computation and taking apart 10 | -- $unsafe$ 11 | -- ** Specific variants 12 | -- $specific$ 13 | module Raaz.V1.AuthEncrypt.Unsafe 14 | ) where 15 | 16 | import Raaz.V1.AuthEncrypt.Unsafe 17 | 18 | -- $unsafe$ 19 | -- 20 | -- This module provides two class of unsafe functions: 21 | -- 22 | -- 1. Functions to compute AEAD tokens with explicit key and Nounce 23 | -- 24 | -- 2. Functions to take apart an AEAD token into their constituents, namely 25 | -- the nounce used, the cipher text, and the authentication tag. 26 | -- 27 | -- The former is to help interface with other libraries where as the 28 | -- latter allows us to serialise AEAD tokens. 29 | -- 30 | -- 31 | -- __WARNING:__ The security of the interface is compromised if 32 | -- 33 | -- 1. The key gets revealed to the attacker or 34 | -- 35 | -- 2. If the same key/nounce pair is used to lock two different 36 | -- messages. 37 | -- 38 | -- 3. Taking apart the AEAD token may compromises type safety. 39 | -- 40 | -- Nounces /need not/ be private and may be exposed to the 41 | -- attacker. In fact, in the safe version of these locking function, 42 | -- we pick the nounce at random (using the csprg) and pack it into the 43 | -- AEAD token. 44 | 45 | -- $specific$ 46 | -- 47 | -- For specific algorithms, the unsafe version is also available 48 | -- 49 | -- * Raaz.AuthEncrypt.Unsafe.ChaCha20Poly1305 50 | -- * Raaz.AuthEncrypt.Unsafe.XChaCha20Poly1305 51 | -- 52 | -- The former has a smaller nounce (96-bits) than the latter 53 | -- (192-bits) and hence there is a slight risk in using it with 54 | -- randomly generated nounces. It is however, slightly faster and is 55 | -- safe to use when there is frequent key resets as in the case of 56 | -- network protocols. As with other cases we recommend the use of the 57 | -- default interface instead of the specific one when ever possible. 58 | -------------------------------------------------------------------------------- /api/random/Entropy.hsig: -------------------------------------------------------------------------------- 1 | -- | Cryptographic pseudo-random generators need an entropy source 2 | -- using which its internal state is initialised at startup or after 3 | -- some pre-defined amount of random data is generated. This signature 4 | -- captures the interface for getting randomness from the entropy 5 | -- pool. The pseudo-random generator exposed from this component can 6 | -- work with any module that satisfies this signature. Be warned 7 | -- however that it is really not a good idea to plug in random (pun 8 | -- unintended) entropy sources. 9 | -- 10 | -- == Default entropy source 11 | -- 12 | -- The Entropy module exposed by the @raaz:implementation@ component 13 | -- is what is used by default by the raaz library. User level 14 | -- libraries have very little access to actual entropy sources and it 15 | -- is very difficult to ascertain the quality of the ones that we do 16 | -- have. Therefore, we believe it is better to rely on the operating 17 | -- system for the entropy needed for seeding. Given below is the list of our choice 18 | -- of entropy source. 19 | -- 20 | -- [OpenBSD/NetBSD:] The arc4random call. 21 | -- 22 | -- [Linux:] The @getrandom@ system call. For older (< 3.17) kernels 23 | -- lacking support for this call, you might need to compile raaz with 24 | -- the `linux-getrandom` disabled. 25 | -- 26 | -- [Other Posix:] Uses @\/dev\/urandom@ 27 | -- 28 | -- [Windows:] Support using CryptGenRandom from Wincrypt.h. 29 | -- 30 | -- Be warned that on some (older?) posix systems, the entropy can be 31 | -- quite low at certain epochs, like at the time of startup. Another 32 | -- situation when entropy gets compromised is when containers are 33 | -- replicated. Defending against these however are beyond the scope of 34 | -- raaz. 35 | 36 | signature Entropy where 37 | 38 | import Raaz.Core 39 | 40 | -- | The name of the source from which entropy is gathered. For 41 | -- information purposes only. Mainly for information purposes. 42 | entropySource :: String 43 | 44 | 45 | -- | Read the given amount of random bytes from the entropy pool. Do 46 | -- not over use this function as it is meant to be used just to seed a 47 | -- PRG. 48 | getEntropy :: BYTES Int -> Ptr Word8 -> IO (BYTES Int) 49 | -------------------------------------------------------------------------------- /indef/chacha20/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE KindSignatures #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE FlexibleInstances #-} 6 | {-# LANGUAGE TypeFamilies #-} 7 | {-# LANGUAGE CPP #-} 8 | 9 | -- | An implementation for chacha20 together with hchacha20 hash 10 | -- implementation. 11 | signature Implementation where 12 | 13 | 14 | import Raaz.Core 15 | import Raaz.Primitive.ChaCha20.Internal 16 | 17 | -- NOTE: 18 | -- 19 | -- With https://gitlab.haskell.org/ghc/ghc/issues/15138 and 20 | -- https://gitlab.haskell.org/ghc/ghc/issues/15379 fixed I (ppk) had 21 | -- expected that one can differ the assignment of Buffer 22 | -- alignment. While this is indeed the case for other implementations, 23 | -- for some reason it, does not seem to work for the Mac 24 | -- implementation, probably because of being an indirect constraint; 25 | -- Mac.Implementation -> Implementation but then is mixed as 26 | -- Implementation in the auth case. Therefore, I am setting an 27 | -- artificially large base number here. 28 | -- 29 | # if MIN_VERSION_base(100,100,0) 30 | -- # if MIN_VERSION_base(4,13,0) 31 | import GHC.TypeLits 32 | 33 | -- | The alignment requirements on the buffer. 34 | data BufferAlignment :: Nat 35 | instance KnownNat BufferAlignment 36 | 37 | # else 38 | -- | The alignment required for buffer (hack around bug 39 | -- https://ghc.haskell.org/trac/ghc/ticket/15138) 40 | type BufferAlignment = 32 41 | #endif 42 | 43 | -- | The primitive for which the implementation is given 44 | type Prim = ChaCha20 45 | 46 | -- | The Internal memory associated with the ChaCha20 implementation. 47 | data Internals 48 | instance Memory Internals 49 | 50 | instance Initialisable Internals (BlockCount ChaCha20) 51 | instance Extractable Internals (BlockCount ChaCha20) 52 | 53 | -- | The function that sets the internal state for the xchacha 54 | -- variant. 55 | xchacha20Setup :: Nounce XChaCha20 -> Internals -> IO () 56 | 57 | -- | Allows copying key from a Memory cell to internal. 58 | copyKey :: Dest Internals-> Src (MemoryCell (Key ChaCha20)) -> IO () 59 | -------------------------------------------------------------------------------- /indef/keyed/hash/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE ConstraintKinds #-} 3 | {-# LANGUAGE MultiParamTypeClasses #-} 4 | {-# LANGUAGE FlexibleInstances #-} 5 | {-# LANGUAGE TypeFamilies #-} 6 | {-# LANGUAGE CPP #-} 7 | -- | A keyed primitive is something that expects a key for it to 8 | -- function. Examples include, encryption, encrypted-authentication 9 | -- etc. This signature add additional constraints to an implementation 10 | -- to make it a keyed cryptographic primitive. 11 | signature Implementation 12 | ( Prim 13 | , Internals 14 | , BufferAlignment 15 | ) where 16 | 17 | 18 | import Foreign.Storable (Storable) 19 | import Raaz.Core 20 | import Raaz.Primitive.Keyed.Internal (KeyedHash) 21 | 22 | -- NOTE: 23 | -- 24 | -- (This issue does not seem to be applicable any more) 25 | -- 26 | -- With https://gitlab.haskell.org/ghc/ghc/issues/15138 and 27 | -- https://gitlab.haskell.org/ghc/ghc/issues/15379 fixed I (ppk) had 28 | -- expected that one can differ the assignment of Buffer 29 | -- alignment. While this is indeed the case for other implementations, 30 | -- for some reason it, does not seem to work for the Mac 31 | -- implementation, probably because of being an indirect constraint; 32 | -- Mac.Implementation -> Implementation but then is mixed as 33 | -- Implementation in the auth case. Therefore, I am setting an 34 | -- artificially large base number here. 35 | -- 36 | 37 | # if MIN_VERSION_base(4,13,0) 38 | import GHC.TypeLits 39 | 40 | -- | The alignment requirements on the buffer. 41 | data BufferAlignment :: Nat 42 | instance KnownNat BufferAlignment 43 | 44 | # else 45 | -- | The alignment required for buffer (hack around bug 46 | -- https://ghc.haskell.org/trac/ghc/ticket/15138) 47 | type BufferAlignment = 32 48 | #endif 49 | 50 | -- | The primitive for which the implementation is given 51 | data Prim 52 | instance Primitive Prim 53 | instance Storable Prim 54 | instance KeyedHash Prim 55 | 56 | 57 | -- | The internal memory used by the implementation. 58 | data Internals 59 | instance Memory Internals 60 | instance Initialisable Internals Prim 61 | instance Extractable Internals Prim 62 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: [ 'main' , 'master' , '0.3' ] 5 | pull_request: 6 | branches: [ 'main' , 'master' , '0.3' ] 7 | schedule: 8 | # Daily build. 9 | - cron: '42 8 * * *' 10 | 11 | jobs: 12 | build: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | os: [ubuntu-latest] 17 | ghc: 18 | # - '8.4' (Haddock failure) 19 | # - '8.6' (Haddock failure) 20 | - '8.8' 21 | - '8.10' 22 | - '9.0' 23 | - '9.2' 24 | - '9.4' 25 | - '9.6' 26 | - '9.8' 27 | - '9.10' 28 | - '9.12' 29 | - 'latest' 30 | 31 | include: 32 | - os: windows-latest 33 | ghc: 'latest' 34 | - os: macos-latest 35 | ghc: 'latest' 36 | 37 | steps: 38 | - name: 'Setup' 39 | uses: haskell-actions/setup@v2 40 | with: 41 | ghc-version: ${{ matrix.ghc }} 42 | cabal-version: '3.10' 43 | - name: Information 44 | run: | 45 | ghc --version 46 | cabal --version 47 | 48 | - name: Get the Repository 49 | uses: actions/checkout@v4 50 | 51 | - name: Submodules 52 | run: git submodule update --init libverse 53 | 54 | - name: Updating Cabal packages 55 | run: | 56 | cabal update 57 | 58 | - name: Build 59 | run: cabal build --minimize-conflict-set 60 | 61 | - name: Test 62 | run: cabal test 63 | 64 | # - name: Benchmark 65 | # run: cabal bench 66 | 67 | # - name: Haddock 68 | # run: cabal haddock 69 | 70 | - name: Check 71 | run: cabal check 72 | 73 | # Disable Install command. 74 | # - name: Install 75 | # run: cabal install 76 | 77 | - name: Build with tarball 78 | if: matrix.os == 'ubuntu-latest' 79 | run: | 80 | cabal sdist 81 | mkdir tarball-build 82 | mv dist-newstyle/sdist/*.tar.gz tarball-build 83 | cd tarball-build 84 | tar xzvf *.tar.gz --strip-components=1 85 | cabal build 86 | cabal test 87 | cabal check 88 | 89 | - name: Raaz information 90 | run: cabal run raaz -- info 91 | -------------------------------------------------------------------------------- /core/Raaz/Core/KeyExchange.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE TypeFamilies #-} 2 | module Raaz.Core.KeyExchange 3 | ( -- * Key exchange. 4 | -- $terminology$ 5 | KeyExchange(..) 6 | ) where 7 | 8 | import Raaz.Core.Prelude 9 | 10 | -- $terminology$ 11 | -- 12 | -- Consider a key exchange between two peers Alice and Bob. There are three 13 | -- important data that is used in the protocol. 14 | -- 15 | -- [Private Key:] Each peer generates a key that is know to only 16 | -- themselves. This could be a static key (i.e might be used 17 | -- multiple times) or a ephemeral key (key per session). 18 | -- 19 | -- [Exchange data:] The peer who holds the secret key `K` generates 20 | -- the corresponding exchange data `Eₖ` that is sent to the peer at 21 | -- the other end of the communication. The exchange data need not 22 | -- be a secret as typically it is exchanged via public channel. The 23 | -- mere knowledge of `Eₖ` will not give any information of the 24 | -- secret key `K` the adversary. 25 | -- 26 | -- [Shared Secret:] Consider two peers Alice and Bob with the 27 | -- respective private keys `Ka` and `Kb`. Let `Ea` and `Eb` be the 28 | -- respective exchange data, then both Alice and Bob can establish 29 | -- a shared `Sab` among themselves at their individual ends by 30 | -- knowing only their own private key and exchange data of the 31 | -- peer, i.e. Alice generates `Sab` from Ka (which is known 32 | -- to her) and Eb (which is sent to her by Bob) over the insecure 33 | -- channel. Similarly, Bob can generated `Sab` from knowing `Kb` 34 | -- and `Ea`. However, an adversary cannot generate `Sab` from 35 | -- merely knowing `Ea` and `Eb` which is the public communication 36 | -- between Alice and Bob. 37 | -- 38 | -- We have separate types for each of these data types. 39 | -- 40 | 41 | class KeyExchange kx where 42 | 43 | -- | The key private key associated with the exchange algorithm. 44 | data Private kx :: Type 45 | 46 | -- | The data that is to be exchanged between the peers for the 47 | -- establishment of the shared secret. 48 | data Exchange kx :: Type 49 | 50 | -- | The shared secret that is established between the peer at each 51 | -- end of the communication once each of the peer receives the 52 | -- exchange communication from the other end. 53 | data Secret kx :: Type 54 | -------------------------------------------------------------------------------- /tests/cipher/Tests/Cipher.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | {-# LANGUAGE MonoLocalBinds #-} 3 | module Tests.Cipher( transformsTo 4 | , keyStreamIs 5 | , zeros 6 | ) where 7 | import Raaz.Core 8 | import Prelude hiding (length) 9 | import Tests.Core.Imports 10 | import Tests.Core.Utils 11 | import Implementation 12 | import Interface 13 | 14 | transformsTo :: (Format fmt1, Format fmt2, Show (Nounce Prim), Show (Key Prim)) 15 | => fmt1 16 | -> fmt2 17 | -> (Key Prim, Nounce Prim, Int) 18 | -> Spec 19 | transformsTo inp expected (key,nounce,ctr) = it msg $ result `shouldBe` decodeFormat expected 20 | where result = encryptAt key nounce (blocksOf ctr Proxy) $ decodeFormat inp 21 | msg = unwords [ withKeyNounce key nounce ctr 22 | , "encrypts" 23 | , shortened $ show inp 24 | , "to" 25 | , shortened $ show expected 26 | ] 27 | 28 | withKeyNounce :: (Show (Key Prim), Show (Nounce Prim)) 29 | => Key Prim 30 | -> Nounce Prim 31 | -> Int 32 | -> String 33 | withKeyNounce key nounce ctr = unwords [ "with {" 34 | , "key:" ++ shortened (show key) 35 | , ", nounce:" ++ shortened (show nounce) 36 | , ", counter:" ++ show ctr 37 | , "}" 38 | ] 39 | 40 | keyStreamIs :: ( Show (Key Prim), Show (Nounce Prim), Format fmt) 41 | => fmt 42 | -> (Key Prim, Nounce Prim, Int) 43 | -> Spec 44 | keyStreamIs expected (key, nounce, ctr) = it msg $ result `shouldBe` decoded 45 | where decoded = decodeFormat expected 46 | result = encryptAt key nounce (blocksOf ctr Proxy) $ zeros $ Raaz.Core.length decoded 47 | msg = unwords [ withKeyNounce key nounce ctr 48 | , "key stream is" 49 | , shortened $ show expected 50 | ] 51 | 52 | zeros :: BYTES Int -> ByteString 53 | zeros = toByteString . writeZero 54 | where writeZero :: LengthUnit u => u -> WriteTo 55 | writeZero = writeBytes 0 56 | -------------------------------------------------------------------------------- /implementation/ChaCha20/CHandWritten.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | {-# LANGUAGE DataKinds #-} 3 | 4 | 5 | -- | The portable C-implementation of Blake2b. 6 | module ChaCha20.CHandWritten where 7 | 8 | import Raaz.Core 9 | import Raaz.Core.Types.Internal 10 | import Raaz.Primitive.ChaCha20.Internal 11 | 12 | 13 | name :: String 14 | name = "handwritten-c" 15 | 16 | primName :: String 17 | primName = "chacha20" 18 | 19 | description :: String 20 | description = "Hand written ChaCha20 Implementation using portable C" 21 | 22 | type Prim = ChaCha20 23 | type Internals = ChaCha20Mem 24 | type BufferAlignment = 32 25 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 26 | 27 | additionalBlocks :: BlockCount ChaCha20 28 | additionalBlocks = blocksOf 1 Proxy 29 | 30 | 31 | ------------------------ The foreign function calls --------------------- 32 | 33 | -- | Chacha20 block transformation. 34 | foreign import ccall unsafe 35 | "raaz/cipher/chacha20/cportable.h raazChaCha20Block" 36 | c_chacha20_block :: BufferPtr -- message 37 | -> BlockCount ChaCha20 -- number of blocks 38 | -> Ptr (Key ChaCha20) -- key 39 | -> Ptr (Nounce ChaCha20) -- iv 40 | -> Ptr (WordType ChaCha20) 41 | -> IO () 42 | 43 | processBlocks :: BufferPtr 44 | -> BlockCount Prim 45 | -> Internals 46 | -> IO () 47 | 48 | processBlocks buf blks mem = 49 | let keyPtr = keyCellPtr mem 50 | ivPtr = ivCellPtr mem 51 | counterPtr = counterCellPtr mem 52 | in c_chacha20_block buf blks keyPtr ivPtr counterPtr 53 | 54 | -- | Process the last bytes. 55 | processLast :: BufferPtr 56 | -> BYTES Int 57 | -> Internals 58 | -> IO () 59 | processLast buf = processBlocks buf . atLeast 60 | 61 | -- | The number of blocks of the cipher that is generated in one go 62 | -- encoded as a type level nat. 63 | type RandomBufferSize = 16 64 | 65 | 66 | -- | How many blocks of the primitive to generated before re-seeding. 67 | reseedAfter :: BlockCount Prim 68 | reseedAfter = blocksOf (1024 * 1024 * 1024) (Proxy :: Proxy Prim) 69 | 70 | randomBlocks :: BufferPtr 71 | -> BlockCount Prim 72 | -> Internals 73 | -> IO () 74 | 75 | randomBlocks = processBlocks 76 | -------------------------------------------------------------------------------- /core/Raaz/Core/Types/Copying.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_HADDOCK hide #-} 2 | -- | 3 | -- 4 | -- Module : Raaz.Core.Types.Copying 5 | -- Description : Avoid confusion between source and destination while copying. 6 | -- Copyright : (c) Piyush P Kurur, 2016 7 | -- License : Apache-2.0 OR BSD-3-Clause 8 | -- Maintainer : Piyush P Kurur 9 | -- Stability : experimental 10 | -- 11 | module Raaz.Core.Types.Copying 12 | ( Src(..), Dest(..), source, destination 13 | ) where 14 | 15 | import Raaz.Core.Prelude 16 | 17 | -- | The source of a copy operation. Besides the `source` smart 18 | -- constructor, the functor instance allows to transform the internal 19 | -- type using the `fmap` (e.g. given an @sptr :: Src (Ptr Word8)@ 20 | -- shift it by an offset). 21 | -- 22 | -- For FFI use: One can use this type directly in FFI interface by 23 | -- importing "Raaz.Core.Types.Internal" to get access to the 24 | -- constructor. 25 | newtype Src a = Src { unSrc :: a } 26 | 27 | -- | Smart constructor for `Src`. Copying functions 28 | source :: a -> Src a 29 | source = Src 30 | 31 | instance Functor Src where 32 | fmap f = Src . f . unSrc 33 | 34 | -- | The destination of a copy operation. Besides the `destination` 35 | -- smart constructor, the functor instance allows to transform the 36 | -- internal type using the `fmap` (e.g. given an @dptr :: Dest (Ptr 37 | -- Word8)@ shift it by an offset). 38 | -- 39 | -- For FFI use: One can use this type directly in FFI interface by 40 | -- importing "Raaz.Core.Types.Internal" to get access to the 41 | -- constructor. 42 | 43 | newtype Dest a = Dest { unDest :: a } 44 | 45 | -- | Smart constructor for `Dest`. 46 | destination :: a -> Dest a 47 | destination = Dest 48 | 49 | instance Functor Dest where 50 | fmap f = Dest . f . unDest 51 | 52 | -- DEVELOPERS NOTE: Why no applicative ? 53 | -- 54 | -- It might look like providing an applicative instance is a good idea 55 | -- for both source and destination; You could use `pure x` instead of 56 | -- saying `source x` or `destination x`. But therein lies the 57 | -- problem. The reason why we had the `Src` and `Dest` type was so 58 | -- that we do not have have problems in function likes `copy ptr1 59 | -- ptr2` (is ptr1 the source or is it the destination). If we give the 60 | -- option to use pure instead of the explicit `source` and 61 | -- `destination` combinators, we end up writing `copy (pure ptr1) 62 | -- (pure ptr2)` which does not give any more safety. 63 | -------------------------------------------------------------------------------- /core/Raaz/Core/CpuSupports.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | {-# OPTIONS_HADDOCK show-extensions #-} 3 | 4 | 5 | -- | 6 | -- 7 | -- Module : Raaz.Core.CpuSupports 8 | -- Copyright : (c) Piyush P Kurur, 2017 9 | -- License : Apache-2.0 OR BSD-3-Clause 10 | -- Maintainer : Piyush P Kurur 11 | -- Stability : experimental 12 | -- 13 | -- This module gives functions that check at runtime whether the 14 | -- underlying cpu supports given features. CPU features are 15 | -- architecture specific. However, functions from this module are 16 | -- guaranteed to be defined always -- they return `False` for 17 | -- incompatible architecture. For example, the flag `avx2` is relevant 18 | -- only for a an X86 architecture. So it is defined false, for say the 19 | -- ARM architecture. 20 | 21 | module Raaz.Core.CpuSupports 22 | ( sse, sse2, sse3 23 | , sse4_1, sse4_2 24 | , avx, avx2 25 | ) where 26 | 27 | import Foreign.C 28 | import Raaz.Core.Prelude 29 | 30 | foreign import ccall unsafe "raaz_supports_sse" 31 | c_sse :: IO CInt 32 | 33 | foreign import ccall unsafe "raaz_supports_sse2" 34 | c_sse2 :: IO CInt 35 | 36 | foreign import ccall unsafe "raaz_supports_sse3" 37 | c_sse3 :: IO CInt 38 | 39 | 40 | foreign import ccall unsafe "raaz_supports_sse4_1" 41 | c_sse4_1 :: IO CInt 42 | 43 | 44 | foreign import ccall unsafe "raaz_supports_sse4_2" 45 | c_sse4_2 :: IO CInt 46 | 47 | foreign import ccall unsafe "raaz_supports_avx" 48 | c_avx :: IO CInt 49 | 50 | foreign import ccall unsafe "raaz_supports_avx2" 51 | c_avx2 :: IO CInt 52 | 53 | 54 | {-# NOINLINE gccBuiltInToBool #-} 55 | 56 | gccBuiltInToBool :: IO CInt -> IO Bool 57 | gccBuiltInToBool = fmap (>0) 58 | 59 | -- | Check whether the cpu supports sse extension. 60 | sse :: IO Bool 61 | sse = gccBuiltInToBool c_sse 62 | 63 | -- | Check whether the cpu supports sse2 extension. 64 | sse2 :: IO Bool 65 | sse2 = gccBuiltInToBool c_sse2 66 | 67 | -- | Check whether the cpu supports sse3 extension. 68 | sse3 :: IO Bool 69 | sse3 = gccBuiltInToBool c_sse3 70 | 71 | -- | Check whether the cpu supports sse4_1 extension. 72 | sse4_1 :: IO Bool 73 | sse4_1 = gccBuiltInToBool c_sse4_1 74 | 75 | -- | Check whether the cpu supports sse-4.2 extension. 76 | sse4_2 :: IO Bool 77 | sse4_2 = gccBuiltInToBool c_sse4_2 78 | 79 | -- | Check whether the cpu supports avx extension. 80 | avx :: IO Bool 81 | avx = gccBuiltInToBool c_avx 82 | 83 | -- | Check whether the cpu supports avx2 extension. 84 | avx2 :: IO Bool 85 | avx2 = gccBuiltInToBool c_avx2 86 | -------------------------------------------------------------------------------- /tests/Raaz/Core/Types/WordSpec.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ScopedTypeVariables #-} 2 | module Raaz.Core.Types.WordSpec where 3 | 4 | import Tests.Core 5 | import Data.ByteString as B 6 | 7 | 8 | msbFirst :: (Bits a, Integral a) => B.ByteString -> a 9 | msbFirst = B.foldl (\ x b -> shiftL x 8 + fromIntegral b) 0 10 | lsbFirst :: (Bits a, Integral a) => B.ByteString -> a 11 | lsbFirst = B.foldr (\ b x -> shiftL x 8 + fromIntegral b) 0 12 | 13 | 14 | spec :: Spec 15 | spec = do 16 | 17 | describe "little and big endian encodings are opposites" $ do 18 | 19 | prop "for 32-bit quantities" $ \ (x :: Word32) -> 20 | toByteString (littleEndian x) `shouldBe` B.reverse (toByteString $ bigEndian x) 21 | 22 | prop "for 64-bit quantities" $ \ (x :: Word64) -> 23 | toByteString (littleEndian x) `shouldBe` B.reverse (toByteString $ bigEndian x) 24 | 25 | 26 | describe "32-bit little endian" $ do 27 | 28 | basicEndianSpecs (undefined :: LE Word32) 29 | 30 | prop "size of encodings of is 4 bytes" $ \ (w :: LE Word32) -> 31 | B.length (toByteString w) `shouldBe` 4 32 | 33 | prop "toByteString in lsb first order" $ \ (x :: LE Word32) -> 34 | lsbFirst (toByteString x) `shouldBe` x 35 | 36 | prop "unsafeFromByteString . toByteString = id" $ \ (x :: LE Word32) -> 37 | unsafeFromByteString (toByteString x) `shouldBe` x 38 | 39 | describe "64-bit little endian" $ do 40 | 41 | basicEndianSpecs (undefined :: LE Word64) 42 | 43 | prop "size of encodings of is 8 bytes" $ \ (w :: LE Word64) -> 44 | B.length (toByteString w) `shouldBe` 8 45 | 46 | prop "toByteString in lsb first order" $ \ (x :: LE Word64) -> 47 | lsbFirst (toByteString x) `shouldBe` x 48 | 49 | prop "unsafeFromByteString . toByteString = id" $ \ (x :: LE Word64) -> 50 | unsafeFromByteString (toByteString x) `shouldBe` x 51 | 52 | describe "32-bit big endian" $ do 53 | 54 | basicEndianSpecs (undefined :: BE Word32) 55 | 56 | prop "size of encodings of is 4 bytes" $ \ (w :: BE Word32) -> 57 | B.length (toByteString w) `shouldBe` 4 58 | 59 | prop "toByteString in lsb first order" $ \ (x :: BE Word32) -> 60 | msbFirst (toByteString x) `shouldBe` x 61 | 62 | prop "unsafeFromByteString . toByteString = id" $ \ (x :: BE Word32) -> 63 | unsafeFromByteString (toByteString x) `shouldBe` x 64 | 65 | describe "64-bit big endian" $ do 66 | 67 | basicEndianSpecs (undefined :: BE Word64) 68 | 69 | prop "size of encodings of is 8 bytes" $ \ (w :: BE Word64) -> 70 | B.length (toByteString w) `shouldBe` 8 71 | 72 | prop "toByteString in lsb first order" $ \ (x :: BE Word64) -> 73 | msbFirst (toByteString x) `shouldBe` x 74 | 75 | prop "unsafeFromByteString . toByteString = id" $ \ (x :: BE Word64) -> 76 | unsafeFromByteString (toByteString x) `shouldBe` x 77 | -------------------------------------------------------------------------------- /core/Raaz/Core/Parse/Unsafe.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- 3 | -- Module : Raaz.Core.Parse.Unsafe 4 | -- Copyright : (c) Piyush P Kurur, 2019 5 | -- License : Apache-2.0 OR BSD-3-Clause 6 | -- Maintainer : Piyush P Kurur 7 | -- Stability : experimental 8 | -- 9 | 10 | module Raaz.Core.Parse.Unsafe 11 | ( Parser, parseWidth 12 | , unsafeMakeParser 13 | , unsafeRunParser 14 | , unsafeParseVector, unsafeParseStorableVector 15 | ) where 16 | 17 | import Data.Vector.Generic (Vector, generateM) 18 | import Foreign.Storable (Storable, peekElemOff) 19 | import Raaz.Core.Prelude 20 | import Raaz.Core.MonoidalAction 21 | import Raaz.Core.Types.Endian 22 | import Raaz.Core.Types.Pointer 23 | 24 | 25 | type BytesMonoid = BYTES Int 26 | type ParseAction = FieldM IO (Ptr Word8) 27 | 28 | -- | An applicative parser type for reading data from a pointer. 29 | type Parser = TwistRF ParseAction BytesMonoid 30 | 31 | -- | Run the parser without checking the length constraints. 32 | unsafeRunParser :: Pointer ptr 33 | => Parser a 34 | -> ptr b 35 | -> IO a 36 | unsafeRunParser prsr = unsafeWithPointerCast $ runIt prsr 37 | where runIt = runFieldM . twistFunctorValue 38 | 39 | -- | Return the bytes that this parser will read. 40 | parseWidth :: Parser a -> BYTES Int 41 | parseWidth = twistMonoidValue 42 | 43 | -- | Make an parser out of its action and the length of the buffer 44 | -- that it acts on. 45 | unsafeMakeParser :: LengthUnit l => l -> (Ptr Word8 -> IO a) -> Parser a 46 | unsafeMakeParser l action = TwistRF (liftToFieldM action) $ inBytes l 47 | 48 | -- | Similar to @unsafeParseVector@ but assumes the elements are 49 | -- encoded in host endian 50 | unsafeParseStorableVector :: (Storable a, Vector v a) => Int -> Parser (v a) 51 | unsafeParseStorableVector n = pvec 52 | where pvec = unsafeMakeParser width $ \ cptr -> generateM n (getA cptr) 53 | width = fromIntegral n * sizeOf (thisProxy pvec) 54 | getA = peekElemOff . castPointer 55 | thisProxy :: Storable a => Parser (v a) -> Proxy a 56 | thisProxy _ = Proxy 57 | 58 | -- | Parse a vector of elements making sure the proper endian 59 | -- conversion is done. It does not check whether the length parameter 60 | -- is non-negative and hence is unsafe. Use it only if you can prove 61 | -- that the length parameter is non-negative. 62 | unsafeParseVector :: (EndianStore a, Vector v a) => Int -> Parser (v a) 63 | unsafeParseVector n = pvec 64 | where pvec = unsafeMakeParser width $ \ cptr -> generateM n (loadFromIndex (castPointer cptr)) 65 | width = fromIntegral n * sizeOf (thisProxy pvec) 66 | thisProxy :: Storable a => Parser (v a) -> Proxy a 67 | thisProxy _ = Proxy 68 | -------------------------------------------------------------------------------- /old-raaz/Raaz/Hash/Sha1.hs: -------------------------------------------------------------------------------- 1 | {-| 2 | 3 | This module exposes combinators to compute the SHA1 hash and the 4 | associated HMAC for some common types. 5 | 6 | 7 | -} 8 | module Raaz.Hash.Sha1 9 | {-# DEPRECATED "SHA1 is broken. This module is here only for transition." #-} 10 | ( 11 | -- * The broken SHA1 cryptographic hash. 12 | -- $sha1$ 13 | SHA1 14 | , sha1, sha1File, sha1Source 15 | -- * HMAC computation using SHA1 16 | , hmacSha1, hmacSha1File, hmacSha1Source 17 | ) where 18 | 19 | import qualified Data.ByteString as B 20 | import qualified Data.ByteString.Lazy as L 21 | 22 | import Raaz.Core 23 | 24 | import Raaz.Hash.Internal ( hashSource, hash, hashFile ) 25 | import Raaz.Hash.Internal.HMAC ( hmacSource, hmac, hmacFile, HMAC ) 26 | import Raaz.Hash.Sha1.Internal ( SHA1 ) 27 | import Raaz.Hash.Sha1.Recommendation() 28 | 29 | -- $sha1$ 30 | -- 31 | -- We already have a collision for SHA1: 32 | -- 33 | -- 34 | -- While it does not yet rule out SHA1 for some specific tasks, there 35 | -- is no reason for its continual usage. This module is present only 36 | -- to facilitate the transition to a better hash. Use it assuming no 37 | -- security guarantees. Raaz will not try to optimise the 38 | -- implementations given here and will remove this module at some 39 | -- point of time. So do not rely on this for your software. 40 | -- 41 | -- 42 | -- 43 | 44 | {-# DEPRECATED sha1, sha1File, sha1Source 45 | "SHA1 is broken. This functions are here only for transition." #-} 46 | -- | Compute the sha1 hash of an instance of `PureByteSource`. Use 47 | -- this for computing the sha1 hash of a strict or lazy byte string. 48 | sha1 :: PureByteSource src => src -> SHA1 49 | sha1 = hash 50 | 51 | 52 | {-# SPECIALIZE sha1 :: B.ByteString -> SHA1 #-} 53 | {-# SPECIALIZE sha1 :: L.ByteString -> SHA1 #-} 54 | 55 | 56 | -- | Compute the sha1 hash of a file. 57 | sha1File :: FilePath -> IO SHA1 58 | sha1File = hashFile 59 | 60 | -- | Compute the sha1 hash of a general byte source. 61 | sha1Source :: ByteSource src => src -> IO SHA1 62 | sha1Source = hashSource 63 | 64 | 65 | {-# DEPRECATED hmacSha1, hmacSha1File, hmacSha1Source 66 | "SHA1 is broken. This functions are here only for transition." #-} 67 | 68 | -- | Compute the message authentication code using hmac-sha1. 69 | hmacSha1 :: PureByteSource src => Key (HMAC SHA1) -> src -> HMAC SHA1 70 | hmacSha1 = hmac 71 | 72 | -- | Compute the message authentication code for a file. 73 | hmacSha1File :: Key (HMAC SHA1) -> FilePath -> IO (HMAC SHA1) 74 | hmacSha1File = hmacFile 75 | 76 | -- | Compute the message authetication code for a generic byte source. 77 | hmacSha1Source :: ByteSource src => Key (HMAC SHA1) -> src -> IO (HMAC SHA1) 78 | hmacSha1Source = hmacSource 79 | -------------------------------------------------------------------------------- /indef/Utils.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE MonoLocalBinds #-} 4 | {-# LANGUAGE CPP #-} 5 | 6 | -- | 7 | -- 8 | -- Module : Utils 9 | -- Description : A utility module for primitives. 10 | -- Copyright : (c) Piyush P Kurur, 2019 11 | -- License : Apache-2.0 OR BSD-3-Clause 12 | -- Maintainer : Piyush P Kurur 13 | -- Stability : experimental 14 | -- 15 | 16 | module Utils 17 | ( processByteSource 18 | , processBuffer 19 | , updateCxt 20 | , finaliseCxt 21 | , transform 22 | ) where 23 | 24 | import Data.ByteString as B 25 | import Data.ByteString.Internal as IB 26 | import GHC.TypeLits 27 | 28 | import Raaz.Core 29 | 30 | import Implementation 31 | import Buffer 32 | import Context 33 | 34 | -- Warning: Not to be exposed Internal function for allocation. 35 | allocaFor :: BlockCount Prim -> (BufferPtr -> IO a) -> IO a 36 | allocaFor blks = allocaBuffer totalSize 37 | where totalSize = blks `mappend` additionalBlocks 38 | 39 | -- | Process the complete byte source using the internals of the 40 | -- primitive. 41 | processByteSource :: ByteSource src => src -> Internals -> IO () 42 | processByteSource src imem 43 | = allocaFor blks $ 44 | \ ptr -> processChunks (processBlocks ptr blks imem) 45 | (\ sz -> processLast ptr sz imem) 46 | src ptr blks 47 | where blks = atLeast l1Cache :: BlockCount Prim 48 | 49 | -- | Process the contents of the given buffer using the processBlocks action. 50 | processBuffer :: KnownNat n 51 | => Buffer n 52 | -> Internals 53 | -> IO () 54 | processBuffer = withBufferPtr processBlocks 55 | 56 | -- | Update the context with the data from the source. This will process 57 | -- any complete blocks on the way so that 58 | updateCxt :: (KnownNat n, ByteSource src) 59 | => src 60 | -> Cxt n 61 | -> IO () 62 | updateCxt = unsafeUpdate processBlocks 63 | 64 | 65 | -- | Finalise the computation by making use of what ever data is left 66 | -- in the buffer. 67 | finaliseCxt :: KnownNat n 68 | => Cxt n 69 | -> IO () 70 | finaliseCxt = unsafeFinalise processLast 71 | 72 | -- | Transform the given bytestring. Hint: use this very rearely. 73 | transform :: ByteString -> Internals -> IO ByteString 74 | transform bs imem 75 | = allocaFor bufSz $ 76 | \ buf -> do unsafeCopyToPointer bs buf -- Copy the input to buffer. 77 | processLast buf strSz imem 78 | IB.create sbytes $ 79 | \ ptr -> Raaz.Core.memcpy (destination ptr) (source buf) strSz 80 | where strSz = Raaz.Core.length bs 81 | sbytes :: Int 82 | sbytes = fromEnum strSz 83 | -- 84 | -- Buffer size is at least the size of the input. 85 | -- 86 | bufSz = atLeast strSz 87 | -------------------------------------------------------------------------------- /core/cbits/raaz/core/endian.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * These are declared as macros because they will work for both 5 | * 32-bit as well as 64-bit cases. 6 | */ 7 | 8 | # define MASK(i) (0xFFULL << (8*(i))) /* mask to select the ith byte */ 9 | # define SEL(a,i) ((a) & MASK(i)) /* select the ith byte */ 10 | # define MOVL(a,i) ((a) << (8*(i))) /* shift the bytes i positions to the left */ 11 | # define MOVR(a,i) ((a) >> (8*(i))) /* shift the bytes i positions to the right */ 12 | # define SWAP(a,i,j) (MOVL(SEL(a,i),(j-i)) | MOVR(SEL(a,j), (j - i))) 13 | /* This function swaps the ith and jth bytes and sets other bytes to 0 */ 14 | 15 | 16 | 17 | # define TO32(x) ((uint32_t)(x)) 18 | # define TO64(x) ((uint64_t)(x)) 19 | 20 | # define B32(ptr,i) (TO32(ptr[i])) 21 | # define B64(ptr,i) (TO64(ptr[i])) 22 | 23 | /* Make a 32-bit quantity out of the 4 bytes given in MSB first order */ 24 | # define MK32(a,b,c,d) ( (a) << 24 | (b) << 16 | (c) << 8 | (d) ) 25 | 26 | /* Similar to MK32 but for 64-bit quantities */ 27 | # define MK64(a,b,c,d,e,f,g,h) \ 28 | ((a) << 56 | (b) << 48 | (c) << 40 | (d) << 32 | (e) << 24 | (f) << 16 | (g) << 8 | (h)) 29 | 30 | 31 | #ifdef __RAAZ_REQUIRE_PORTABLE_SWAP__ 32 | 33 | uint32_t raaz_bswap32(uint32_t a){ return (SWAP(a,0,3) | SWAP(a,1,2)); } 34 | uint64_t raaz_bswap64(uint64_t a){ return (SWAP(a,0,7) | SWAP(a,1,6) | SWAP(a,2,5) | SWAP(a,3,4)); } 35 | 36 | #endif 37 | 38 | 39 | #ifdef __RAAZ_REQUIRE_PORTABLE_ENDIAN__ 40 | 41 | uint32_t raaz_tobe32(uint32_t x) 42 | { 43 | uint8_t *ptr = (uint8_t *) &x; 44 | return MK32(B32(ptr,0), B32(ptr,1), B32(ptr,2), B32(ptr,3)); 45 | } 46 | 47 | 48 | uint32_t raaz_tole32(uint32_t x) 49 | { 50 | uint8_t *ptr = (uint8_t *) &x; 51 | return MK32(B32(ptr,3), B32(ptr,2), B32(ptr,1), B32(ptr,0)); 52 | 53 | } 54 | 55 | uint64_t raaz_tobe64(uint64_t x) 56 | { 57 | uint8_t *ptr = (uint8_t *) &x; 58 | return MK64(B64(ptr,0), B64(ptr,1), B64(ptr,2), B64(ptr,3), 59 | B64(ptr,4), B64(ptr,5), B64(ptr,6), B64(ptr,7)); 60 | } 61 | 62 | 63 | uint64_t raaz_tole64(uint64_t x) 64 | { 65 | uint8_t *ptr = (uint8_t *) &x; 66 | return MK64(B64(ptr,7), B64(ptr,6), B64(ptr,5), B64(ptr,4), 67 | B64(ptr,3), B64(ptr,2), B64(ptr,1), B64(ptr,0)); 68 | } 69 | 70 | #endif 71 | 72 | 73 | /* Finally we define the functions that are called by Haskell as FFI 74 | * routines for their endian store instances. These should not be 75 | * declared static inline. 76 | */ 77 | 78 | uint32_t raazSwap32(uint32_t a){ return raaz_bswap32(a);} 79 | uint64_t raazSwap64(uint64_t a){ return raaz_bswap64(a);} 80 | 81 | void raazSwap32Array(uint32_t *ptr, int n) 82 | { 83 | for(;n > 0; ++ptr, --n){*ptr = raaz_bswap32(*ptr);} 84 | } 85 | 86 | void raazSwap64Array(uint64_t *ptr, int n) 87 | { 88 | for(;n > 0; ++ptr, --n){*ptr = raaz_bswap64(*ptr);} 89 | } 90 | -------------------------------------------------------------------------------- /benchmarks/internal/Benchmark/Types.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RecordWildCards #-} 2 | 3 | module Benchmark.Types 4 | ( RaazBench 5 | , toBenchmarkable 6 | , nBytes 7 | , nRuns 8 | , runRaazBench 9 | , header 10 | ) where 11 | 12 | import Criterion.Measurement 13 | import Criterion.Measurement.Types hiding (measure) 14 | 15 | import Data.Int 16 | import Text.PrettyPrint 17 | 18 | import Raaz.Core 19 | 20 | -- | The total data processed in each benchmark. 21 | nBytes :: BYTES Int 22 | nBytes = 32 * 1024 23 | 24 | -- | How many times to run each benchmark 25 | nRuns :: Int64 26 | nRuns = 10000 27 | 28 | type RaazBench = (String, String, Benchmarkable) 29 | 30 | header :: Doc 31 | header = hsep $ punctuate comma $ map text 32 | [ "Primitive" 33 | , "Implementation" 34 | , "time" 35 | , "cycles" 36 | , "rate (bits/sec)" 37 | , "time/byte" 38 | , "cycles/byte" 39 | ] 40 | 41 | -- | Execute a benchmark and writeout the results. 42 | runRaazBench :: RaazBench -> IO Doc 43 | runRaazBench (prNm, nm, bm) = do 44 | (memt,_) <- measure bm nRuns 45 | return $ hsep $ punctuate comma $ text prNm : text nm : pprMeasured memt 46 | 47 | 48 | ------------------------ Helper functions ------------------------ 49 | 50 | 51 | pprMeasured :: Measured -> [Doc] 52 | pprMeasured Measured{..} = 53 | [ text (secs tm) -- time 54 | , text (humanise cy) -- cycles 55 | , text rt -- rate 56 | , text secB -- secs/byte 57 | , text (humanise cycB) -- cycles/byte 58 | ] 59 | where tm = measTime / fromIntegral nRuns 60 | cy = fromIntegral measCycles / fromIntegral nRuns 61 | bytes = fromIntegral nBytes 62 | secB = humanise (tm / bytes) ++ "s" 63 | cycB = cy / bytes 64 | rt = humanise $ 8 * bytes / tm 65 | 66 | 67 | -- | Humanise the output units. 68 | humanise :: Double -> String 69 | humanise u | u < 1 = goL 0 u 70 | | otherwise = goU 0 u 71 | where goL e x | x > 1 || e == -3 = restrictDecimals 2 x ++ unitPrefix e 72 | | otherwise = goL (e - 1) (x * 1000) 73 | 74 | goU e x | x < 100 || e == 5 = restrictDecimals 2 x ++ unitPrefix e 75 | | otherwise = goU (e + 1) (x / 1000) 76 | 77 | 78 | restrictDecimals :: Int -> Double -> String 79 | restrictDecimals n x = u ++ take (n+1) v 80 | where (u,v) = span (/= '.') $ show x 81 | 82 | 83 | -- | @Unit prefix n@ gives proper prefix every 10^{3n} exponent 84 | unitPrefix :: Int -> String 85 | unitPrefix ex 86 | | ex < -3 = error "exponent too small name" 87 | | ex == -3 = "n" 88 | | ex == -2 = "µ" 89 | | ex == -1 = "m" 90 | | ex == 0 = "" 91 | | ex == 1 = "K" 92 | | ex == 2 = "M" 93 | | ex == 3 = "G" 94 | | ex == 4 = "T" 95 | | ex == 5 = "P" 96 | | otherwise = error "exponent to large to name" 97 | -------------------------------------------------------------------------------- /tests/core/Tests/Core/Utils.hs: -------------------------------------------------------------------------------- 1 | module Tests.Core.Utils where 2 | 3 | import Raaz.Core.Types.Internal ( BYTES(..) ) 4 | 5 | import Tests.Core.Imports hiding (length, replicate) 6 | import Prelude (length, replicate) 7 | 8 | import Foreign.Ptr ( castPtr ) 9 | import Data.ByteString as B (concat) 10 | 11 | -- | Run a spec with a give key. 12 | with :: key -> (key -> Spec) -> Spec 13 | with key hmsto = hmsto key 14 | 15 | 16 | -- | Store and the load the given value. 17 | storeAndThenLoad :: EndianStore a 18 | => a -> IO a 19 | storeAndThenLoad a = allocaBuffer (sizeOf $ pure a) (runStoreLoad . castPtr) 20 | where runStoreLoad ptr = store ptr a >> load ptr 21 | 22 | 23 | allocCast :: BYTES Int -> (Ptr a -> IO c) -> IO c 24 | allocCast sz f = allocaBuffer sz $ f . castPtr 25 | 26 | storeAdjustAndPeek :: EndianStore a 27 | => a 28 | -> IO a 29 | storeAdjustAndPeek a 30 | = allocCast sz $ \ ptr -> do store ptr a 31 | adjustEndian ptr 1 32 | peek ptr 33 | where sz = sizeOf $ pure a 34 | 35 | pokeAdjustAndLoad :: EndianStore a 36 | => a 37 | -> IO a 38 | pokeAdjustAndLoad a 39 | = allocCast sz $ \ ptr -> do poke ptr a 40 | adjustEndian ptr 1 41 | load ptr 42 | where sz = sizeOf $ pure a 43 | 44 | 45 | 46 | basicEndianSpecs :: ( EndianStore a, Show a, Eq a, Arbitrary a) 47 | => a -> Spec 48 | basicEndianSpecs a = describe "Endian Checks" $ do 49 | prop "store followed by load returns original value" $ \ x -> 50 | storeAndThenLoad (x `asTypeOf` a) `shouldReturn` x 51 | 52 | prop "store, adjust followed by peek should return the original value" $ \ x -> 53 | storeAdjustAndPeek (x `asTypeOf` a) `shouldReturn` x 54 | 55 | prop "poke, adjust followed by load should return the original value" $ \ x -> 56 | pokeAdjustAndLoad (x `asTypeOf` a) `shouldReturn` x 57 | 58 | 59 | 60 | -- | Shorten a string to make it readable in tests. 61 | shortened :: String -> String 62 | shortened x | l <= 11 = paddedx 63 | | otherwise = prefix ++ "..." ++ suffix 64 | where l = length x 65 | prefix = take 4 x 66 | suffix = drop (l - 4) x 67 | paddedx = x ++ replicate (11 - l) ' ' 68 | 69 | -- | Generate bytestrings that are multiples of block size of a 70 | -- primitive. 71 | blocks :: Primitive prim => Proxy prim -> Gen ByteString 72 | blocks primProxy = B.concat <$> listOf singleBlock 73 | where singleBlock = pack <$> vector sz 74 | BYTES sz = inBytes $ blocksOf 1 primProxy 75 | 76 | 77 | -- | Run a property with a given generator. 78 | feed :: (Testable pr, Show a) => Gen a -> (a -> IO pr) -> Property 79 | feed gen pr = monadicIO $ pick gen >>= (run . pr) 80 | 81 | repeated :: Monoid m => m -> Int -> m 82 | repeated m n = mconcat $ replicate n m 83 | -------------------------------------------------------------------------------- /notes/roadmap.org: -------------------------------------------------------------------------------- 1 | #+STARTUP: indent 2 | 3 | * TODO Version 1.0 4 | 5 | We have been beating around the bush quit a bit. It is useful to 6 | consolidate the lessons learned and aim for version 1. 7 | 8 | ** Expectation for version 1.0 9 | When a user looks for a modern cryptographic library particularly for 10 | network applications some of the things that they require are 11 | 12 | *** Cryptographic hashing 13 | **** DONE SHA2 hashes 14 | **** DONE Blake2 hashes 15 | *** Cryptographically Secure Psedo-random generator (CSPRG) 16 | **** DONE Chacha20 based CSPRG. 17 | 18 | *** Digital signature scheme. 19 | **** TODO ED25519 20 | 21 | *** Diffie-Helman style key exchange. 22 | **** TODO EC25519 23 | 24 | *** Password hashing. 25 | **** TODO Argon 26 | 27 | *** Encrypted authenticated modes. 28 | The target is chacha20-poly1305. This means we need 29 | **** DONE Chacha20 30 | **** TODO Poly1305 31 | 32 | 33 | 34 | ** Actions Plan 35 | 36 | *** Disable primitives 37 | 38 | 39 | **** SHA1 hashing 40 | 41 | Collision has been found in sha1 and hence we are not very keen in 42 | supporting this hash. 43 | 44 | **** AES 45 | 46 | Implementation of AES without side channel leaks are difficult (but 47 | not impossible) and that too only for the CTR mode. There is not much 48 | point in supporting the CBC mode which is know to have a lot of tricky 49 | edge cases. 50 | 51 | *** Support only portable C implementations 52 | 53 | The C compiler is often able to give very high quality code. So we 54 | restrict the attention to portable C implementation as of now. 55 | 56 | * Experimental Backpack based design 57 | ** TODO Multiple implementation of primitives 58 | Raaz as a library believes in having multiple implementations of 59 | crypto primitives. It should be feasible for a user to select the 60 | implementation of her choice. 61 | 62 | *** Current solution 63 | 64 | Consider a primitive like cryptographic hashing. Each primitive had 65 | an associated type called =Implementation= which captures the 66 | implementation of the primitive. Also the library has a recommended 67 | implementation for each supported primitive. For hashing, there are 68 | two variants =hash= and =hash'= where the former uses the recommended 69 | version where as the latter takes as argument an implementation and 70 | uses it for computation. If a user is not happy with a given 71 | recommendation, then she needs to use the primed version. 72 | 73 | 74 | *** Backpack based solution 75 | 76 | An /implementation/ of a particular kind of primitives, i.e. say 77 | hashing, is specifying a bunch of functions of particular 78 | kind. Depending on the nature of the primitive, we define an 79 | implementation signature. 80 | 81 | Having such an implementation, we can provide an /interface/ to the 82 | user. Thus an /interface/ associated with a primitive depends on an 83 | implementation provided. 84 | 85 | *** Tasks 86 | - [ ] Separate out the core definitions. 87 | - [ ] Make implementation/interface signatures. 88 | - [ ] Hashes. 89 | - [ ] Ciphers 90 | -------------------------------------------------------------------------------- /tests/core/Tests/Core/Instances.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE FlexibleInstances #-} 4 | {-# OPTIONS_GHC -fno-warn-orphans #-} 5 | 6 | -- | Some common instances that are required by the test cases. 7 | module Tests.Core.Instances () where 8 | 9 | import Tests.Core.Imports 10 | 11 | import Raaz.Primitive.Poly1305.Internal as Poly1305 12 | import Raaz.Core.Types.Internal 13 | import Raaz.Primitive.Keyed.Internal as Keyed 14 | 15 | 16 | instance Arbitrary w => Arbitrary (LE w) where 17 | arbitrary = littleEndian <$> arbitrary 18 | 19 | instance Arbitrary w => Arbitrary (BE w) where 20 | arbitrary = bigEndian <$> arbitrary 21 | 22 | instance Arbitrary w => Arbitrary (BYTES w) where 23 | arbitrary = BYTES <$> arbitrary 24 | 25 | instance Arbitrary ByteString where 26 | arbitrary = pack <$> arbitrary 27 | 28 | 29 | --------------- Arbitrary instances for Hashes ---------------- 30 | 31 | instance Arbitrary Sha256 where 32 | arbitrary = genEncodable 33 | 34 | instance Arbitrary Sha512 where 35 | arbitrary = genEncodable 36 | 37 | instance Arbitrary Blake2b where 38 | arbitrary = genEncodable 39 | 40 | instance Arbitrary Blake2s where 41 | arbitrary = genEncodable 42 | 43 | ---------------- Parameter block for Blake ------------- 44 | 45 | ---------------- Arbitrary instaces of encoded data -------------- 46 | 47 | instance Arbitrary Base16 where 48 | arbitrary = encodeByteString . pack <$> listOf arbitrary 49 | 50 | instance Arbitrary Base64 where 51 | arbitrary = encodeByteString . pack <$> listOf arbitrary 52 | 53 | ------------------ For ChaCha20 types ------------------------- 54 | 55 | instance Arbitrary (Key ChaCha20) where 56 | arbitrary = genEncodable 57 | 58 | instance Arbitrary (Nounce ChaCha20) where 59 | arbitrary = genEncodable 60 | 61 | instance Arbitrary (BlockCount ChaCha20) where 62 | arbitrary = toEnum <$> arbitrary 63 | 64 | ------------------ For XChaCha20 types ------------------------- 65 | 66 | instance Arbitrary (Key XChaCha20) where 67 | arbitrary = genEncodable 68 | 69 | instance Arbitrary (Key (Keyed prim)) where 70 | arbitrary = Keyed.Key . pack <$> listOf1 arbitrary 71 | 72 | instance Arbitrary (Nounce XChaCha20) where 73 | arbitrary = genEncodable 74 | 75 | instance Arbitrary (BlockCount XChaCha20) where 76 | arbitrary = toEnum <$> arbitrary 77 | 78 | ------------------ Arbitrary instances for Poly1305 ------------- 79 | instance Arbitrary Poly1305.R where 80 | arbitrary = genEncodable 81 | 82 | instance Arbitrary Poly1305.S where 83 | arbitrary = genEncodable 84 | 85 | instance Arbitrary Poly1305.Poly1305 where 86 | arbitrary = genEncodable 87 | 88 | instance Arbitrary (Key Poly1305) where 89 | arbitrary = Poly1305.Key <$> arbitrary <*> arbitrary 90 | 91 | genEncodable :: (Encodable a, Storable a) => Gen a 92 | genEncodable = go undefined 93 | where go :: (Encodable a, Storable a) => a -> Gen a 94 | go x = unsafeFromByteString . pack <$> vector (fromEnum $ sizeOf $ pure x) 95 | -------------------------------------------------------------------------------- /implementation/Blake2s/CHandWritten.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | {-# LANGUAGE DataKinds #-} 3 | 4 | 5 | -- | The portable C-implementation of Blake2s. 6 | module Blake2s.CHandWritten where 7 | 8 | import Raaz.Core 9 | import Raaz.Core.Transfer.Unsafe 10 | import Raaz.Core.Types.Internal 11 | import Raaz.Primitive.HashMemory 12 | import Raaz.Primitive.Blake2.Internal 13 | 14 | 15 | name :: String 16 | name = "handwritten-c" 17 | 18 | primName :: String 19 | primName = "blake2s" 20 | 21 | description :: String 22 | description = "Hand written Blake2s Implementation using portable C and Haskell FFI" 23 | 24 | type Prim = Blake2s 25 | type Internals = Blake2sMem 26 | type BufferAlignment = 32 27 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 28 | 29 | additionalBlocks :: BlockCount Prim 30 | additionalBlocks = blocksOf 1 Proxy 31 | 32 | ------------------------- FFI For Blake2s ------------------------------------- 33 | 34 | 35 | foreign import ccall unsafe 36 | "raaz/hash/blake2/common.h raazHashBlake2sPortableBlockCompress" 37 | c_blake2s_compress :: BufferPtr 38 | -> BlockCount Blake2s 39 | -> BYTES Word64 40 | -> Ptr Prim 41 | -> IO () 42 | 43 | foreign import ccall unsafe 44 | "raaz/hash/blake2/common.h raazHashBlake2sPortableLastBlock" 45 | c_blake2s_last :: BlockPtr Prim 46 | -> BYTES Int 47 | -> BYTES Word64 48 | -> Word32 49 | -> Word32 50 | -> Ptr Prim 51 | -> IO () 52 | -- 53 | processBlocks :: BufferPtr 54 | -> BlockCount Prim 55 | -> Internals 56 | -> IO () 57 | 58 | processBlocks buf blks b2smem = 59 | let hshPtr = hashCellPointer b2smem 60 | in do l <- getLength b2smem 61 | c_blake2s_compress buf blks l hshPtr 62 | updateLength blks b2smem 63 | 64 | -- | Process the last bytes. 65 | processLast :: BufferPtr 66 | -> BYTES Int 67 | -> Internals 68 | -> IO () 69 | processLast buf nbytes b2smem = do 70 | unsafeTransfer padding $ forgetAlignment buf -- pad the message 71 | processBlocks buf nBlocks b2smem -- process all but the last block 72 | -- 73 | -- Handle the last block 74 | -- 75 | l <- getLength b2smem 76 | c_blake2s_last lastBlockPtr remBytes l f0 f1 hshPtr 77 | where hshPtr = hashCellPointer b2smem 78 | padding = blake2Pad (Proxy :: Proxy Prim) nbytes 79 | nBlocks = atMost (transferSize padding) `mappend` toEnum (-1) 80 | -- all but the last block 81 | remBytes = nbytes - inBytes nBlocks 82 | -- Actual bytes in the last block. 83 | lastBlockPtr = forgetAlignment buf `movePtr` nBlocks 84 | -- 85 | -- Finalisation FLAGS 86 | -- 87 | f0 = complement 0 88 | f1 = 0 89 | -------------------------------------------------------------------------------- /api/random/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE FlexibleInstances #-} 3 | {-# LANGUAGE MultiParamTypeClasses #-} 4 | {-# LANGUAGE TypeFamilies #-} 5 | 6 | -- | Cryptographically secure pseudo-random generator or CSPRG for 7 | -- short is typically implemented from a stream cipher by setting its 8 | -- internals from an entropy source and generating its key stream as 9 | -- the pseudo-random stream. This signature captures primitives that 10 | -- can be used in such a fashion. 11 | -- 12 | -- == Defaults 13 | -- 14 | -- The raaz:implementation package uses the ChaCha20 cipher to satisfy 15 | -- this implementation. 16 | 17 | signature Implementation ( Prim 18 | , name 19 | , primName 20 | , description 21 | , Internals 22 | , BufferAlignment 23 | , RandomBufferSize 24 | , reseedAfter 25 | , randomBlocks 26 | ) where 27 | 28 | import Raaz.Core 29 | 30 | -- | The primitive. 31 | data Prim 32 | instance Primitive Prim 33 | 34 | -- | The name of the implementation. 35 | name :: String 36 | 37 | -- | The name of the primitive used as the seed stretcher 38 | primName :: String 39 | 40 | -- | The description of the implementation. 41 | description :: String 42 | 43 | -- | The internal memory. It should be possible to initialise the 44 | -- contents of the internal memory from a buffer. After generating 45 | -- some pseudo-random bytes, we use this ability to achieve the /fast 46 | -- key erasure/ (). This 47 | -- design ensure that revealing the current state does not compromise 48 | -- the pseudo-random bytes generated in the past. 49 | data Internals 50 | instance Memory Internals 51 | instance WriteAccessible Internals 52 | 53 | -- | The alignment required for buffer (hack around bug 54 | -- https://ghc.haskell.org/trac/ghc/ticket/15138) 55 | type BufferAlignment = 32 56 | 57 | -- | The number of blocks of the cipher that is generated in one go 58 | -- encoded as a type level nat. 59 | type RandomBufferSize = 16 60 | 61 | 62 | -- | How many blocks of the primitive to generated before re-seeding. 63 | reseedAfter :: BlockCount Prim 64 | 65 | -- | Generate pseudo-random data in multiples of the blocks. The sole 66 | -- purpose of this function is to stretch a fixed size seed (the key 67 | -- of the cipher) to a cryptographically unpredictable stream of 68 | -- bytes. While, the key stream function of a cipher is a natural 69 | -- candidate actual implementations might differ for example, by 70 | -- ignoring the endian considerations. In particular, if deterministic 71 | -- generation of random bytes across architectures are what is 72 | -- desired, this function is not suitable. 73 | randomBlocks :: AlignedBlockPtr BufferAlignment Prim 74 | -> BlockCount Prim 75 | -> Internals 76 | -> IO () 77 | -------------------------------------------------------------------------------- /tests/Raaz/Cipher/XChaCha20Spec.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fno-warn-orphans #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | {-# LANGUAGE ScopedTypeVariables #-} 4 | {-# LANGUAGE DataKinds #-} 5 | 6 | module Raaz.Cipher.XChaCha20Spec where 7 | 8 | import Tests.Core 9 | import qualified XChaCha20.Implementation as XI 10 | import qualified ChaCha20.CPortable as CP 11 | import System.IO.Unsafe( unsafePerformIO ) 12 | 13 | 14 | unsafeRun :: Memory mem => (mem -> IO a) -> a 15 | unsafeRun = unsafePerformIO . withMemory 16 | 17 | setup :: Key ChaCha20 18 | -> Nounce XChaCha20 19 | -> (Key ChaCha20, Nounce ChaCha20) 20 | setup k n = unsafeRun setupMem 21 | where setupMem :: CP.Internals -> IO (Key ChaCha20, Nounce ChaCha20) 22 | setupMem mem = do initialise k mem 23 | CP.xchacha20Setup n mem 24 | (,) <$> extract (keyCell mem) 25 | <*> extract (ivCell mem) 26 | xinit :: Key XChaCha20 27 | -> Nounce XChaCha20 28 | -> (Key ChaCha20, Nounce ChaCha20) 29 | xinit k n = unsafeRun xinitMem 30 | where xinitMem :: XI.Internals -> IO (Key ChaCha20, Nounce ChaCha20) 31 | xinitMem mem = do initialise k mem 32 | initialise n mem 33 | (,) <$> extract (keyCell $ XI.chacha20Internals mem) 34 | <*> extract (ivCell $ XI.chacha20Internals mem) 35 | 36 | mesg :: (Show k, Show n, Show kp, Show iv) 37 | => k -> n -> kp -> iv -> String 38 | mesg k n kp iv = unwords ["for key:" 39 | , shortened $ show k 40 | , "and nounce:" 41 | , shortened $ show n 42 | , "the key should be" 43 | , shortened $ show kp 44 | , "and the internal nounce should be" 45 | , show iv 46 | ] 47 | 48 | setupSpec :: Key ChaCha20 -> Nounce XChaCha20 -> (Key ChaCha20, Nounce ChaCha20) -> Spec 49 | setupSpec k n (kp,iv) = it msg $ setup k n `shouldBe` (kp,iv) 50 | where msg = unwords ["setup:", mesg k n kp iv] 51 | 52 | xinitSpec :: Key XChaCha20 -> Nounce XChaCha20 -> (Key ChaCha20,Nounce ChaCha20) -> Spec 53 | xinitSpec k n (kp,iv) = it msg $ xinit k n `shouldBe` (kp,iv) 54 | where msg = unwords ["xinit:", mesg k n kp iv] 55 | 56 | spec :: Spec 57 | spec = do 58 | setupSpec 59 | "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f" 60 | "00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27:00:01:02:03:04:05:06:07" 61 | ("82413b42 27b27bfe d30e4250 8a877d73 a0f9e4d5 8a74a853 c12ec413 26d3ecdc", "00:00:00:00:00:01:02:03:04:05:06:07") 62 | 63 | xinitSpec 64 | "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f" 65 | "00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27:00:01:02:03:04:05:06:07" 66 | ("82413b42 27b27bfe d30e4250 8a877d73 a0f9e4d5 8a74a853 c12ec413 26d3ecdc", "00:00:00:00:00:01:02:03:04:05:06:07") 67 | -------------------------------------------------------------------------------- /raaz/Raaz/V1/AuthEncrypt/Unsafe.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- Module : Raaz.AuthEncrypt.Unsafe 3 | -- Copyright : (c) Piyush P Kurur, 2016 4 | -- License : Apache-2.0 OR BSD-3-Clause 5 | -- Maintainer : Piyush P Kurur 6 | -- Stability : experimental 7 | -- 8 | module Raaz.V1.AuthEncrypt.Unsafe 9 | ( Locked 10 | , unsafeLock, unsafeLockWith 11 | , Cipher, AuthTag 12 | , unsafeToNounce, unsafeToCipherText, unsafeToAuthTag 13 | , unsafeLocked 14 | ) where 15 | 16 | import Data.ByteString 17 | import Raaz.Core 18 | import qualified Raaz.AuthEncrypt.Unsafe.XChaCha20Poly1305 as AE 19 | import Raaz.AuthEncrypt.Unsafe.XChaCha20Poly1305 ( Locked, Cipher, AuthTag 20 | ) 21 | 22 | -- | Similar to `lockWith` but an explicit nounce is taken as 23 | -- input. Reusing the key-nounce pair will compromise the security and 24 | -- hence using this function is unsafe. The user needs to ensure the 25 | -- freshness of the key, nounce pair through some other means. 26 | -- 27 | -- Some protocols have a predefined way to pick nounces and this is 28 | -- the reason, we provide such an interface. If that is not a concern, 29 | -- we recommend the use of `lockWith` instead. 30 | unsafeLockWith :: ( Encodable plain, Encodable aad) 31 | => aad 32 | -> Key Cipher 33 | -> Nounce Cipher 34 | -> plain 35 | -> Locked 36 | unsafeLockWith = AE.unsafeLockWith 37 | 38 | -- | Locks a given message but needs an explicit nounce. Reusing the 39 | -- key-nounce pair will compromise the security and hence using this 40 | -- function is unsafe. The user needs to ensure the freshness of the 41 | -- key, nounce pair through some other means. 42 | -- 43 | -- Some protocols have a predefined way to pick nounces and this is 44 | -- the reason we provide such an interface. If that is not a concern, 45 | -- we recommend the use of `lock` instead. 46 | unsafeLock :: Encodable plain 47 | => Key Cipher -- ^ The key 48 | -> Nounce Cipher -- ^ The nounce 49 | -> plain -- ^ The object to be locked. 50 | -> Locked 51 | unsafeLock = AE.unsafeLock 52 | 53 | 54 | 55 | 56 | -- | Get the cipher text part of the Locked message. 57 | unsafeToCipherText :: Locked 58 | -> ByteString 59 | unsafeToCipherText = AE.unsafeToCipherText 60 | 61 | -- | Get the authentication token of the Locked message. 62 | unsafeToAuthTag :: Locked -> AE.AuthTag 63 | unsafeToAuthTag = AE.unsafeToAuthTag 64 | 65 | -- | Get the nounce used for authenticating the token. 66 | unsafeToNounce :: Locked -> Nounce Cipher 67 | unsafeToNounce = AE.unsafeToNounce 68 | 69 | -- | Construct the locked message out of the nounce, cipher text, and the 70 | -- authentication tag. 71 | unsafeLocked :: Nounce Cipher -- ^ The nounce used for locking this message 72 | -> ByteString -- ^ The cipher text 73 | -> AE.AuthTag -- ^ the Authentication tag 74 | -> Locked 75 | unsafeLocked = AE.unsafeLocked 76 | -------------------------------------------------------------------------------- /api/auth/Interface.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RecordWildCards #-} 2 | module Interface ( Auth 3 | , auth 4 | , authFile 5 | , authSource 6 | , AuthCxt 7 | , startAuth 8 | , updateAuth 9 | , finaliseAuth 10 | , name 11 | , primName 12 | , description 13 | ) where 14 | 15 | import GHC.TypeLits 16 | 17 | import qualified Data.ByteString as B 18 | import qualified Data.ByteString.Lazy as L 19 | import System.IO.Unsafe (unsafePerformIO) 20 | 21 | 22 | import Raaz.Core 23 | import qualified Implementation 24 | import Utils 25 | import Context 26 | 27 | type Auth = Implementation.Prim 28 | type AuthCxt = Cxt 29 | -- | Compute the authenticator of a pure byte source like, 30 | -- `B.ByteString`. 31 | auth :: PureByteSource src 32 | => Key Auth 33 | -> src -- ^ Message 34 | -> Auth 35 | auth key = unsafePerformIO . authSource key 36 | {-# INLINEABLE auth #-} 37 | {-# SPECIALIZE auth :: Key Auth -> B.ByteString -> Auth #-} 38 | {-# SPECIALIZE auth :: Key Auth -> L.ByteString -> Auth #-} 39 | 40 | -- | Compute the auth of file. 41 | authFile :: Key Auth 42 | -> FilePath -- ^ File to be authed 43 | -> IO Auth 44 | authFile key fileName = withBinaryFile fileName ReadMode $ authSource key 45 | {-# INLINEABLE authFile #-} 46 | 47 | 48 | -- | Compute the auth of an arbitrary byte source. 49 | authSource :: ByteSource src 50 | => Key Auth 51 | -> src 52 | -> IO Auth 53 | {-# SPECIALIZE authSource :: Key Auth -> B.ByteString -> IO Auth #-} 54 | {-# SPECIALIZE authSource :: Key Auth -> L.ByteString -> IO Auth #-} 55 | {-# SPECIALIZE authSource :: Key Auth -> Handle -> IO Auth #-} 56 | 57 | authSource key src = withMemory $ \ mem -> do 58 | initialise key mem 59 | processByteSource src mem 60 | extract mem 61 | 62 | -- | Prepare the context to (re)start a session of incremental 63 | -- processing. 64 | startAuth :: KnownNat n 65 | => Key Auth -- ^ The key to be used 66 | -> AuthCxt n 67 | -> IO () 68 | startAuth k cxt@Cxt{..} = do initialise k cxtInternals 69 | unsafeSetCxtEmpty cxt 70 | 71 | 72 | -- | Add some more data into the context, in this case the entirety of 73 | -- the byte source src. 74 | updateAuth :: (KnownNat n, ByteSource src) 75 | => src 76 | -> AuthCxt n 77 | -> IO () 78 | updateAuth = updateCxt 79 | 80 | -- | Finalise the context to get hold of the digest. 81 | finaliseAuth :: KnownNat n 82 | => AuthCxt n 83 | -> IO Auth 84 | finaliseAuth cxt@Cxt{..} = finaliseCxt cxt >> extract cxtInternals 85 | 86 | 87 | -- | Textual name of the authenticator implementation. 88 | name :: String 89 | name = Implementation.name 90 | 91 | -- | Textual name of the associated primitive. 92 | primName :: String 93 | primName = Implementation.primName 94 | 95 | -- | Description of the implementation 96 | description :: String 97 | description = Implementation.description 98 | -------------------------------------------------------------------------------- /core/Raaz/Primitive/Poly1305/Internal.hs: -------------------------------------------------------------------------------- 1 | 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 4 | {-# LANGUAGE TypeFamilies #-} 5 | 6 | -- | 7 | -- 8 | -- Module : Raaz.Primitive.Poly1305.Internal 9 | -- Description : Internals of the poly1305 message authenticator. 10 | -- Copyright : (c) Piyush P Kurur, 2019 11 | -- License : Apache-2.0 OR BSD-3-Clause 12 | -- Maintainer : Piyush P Kurur 13 | -- Stability : experimental 14 | -- 15 | 16 | module Raaz.Primitive.Poly1305.Internal 17 | ( -- * The Poly1305 MAC 18 | -- $poly1305$ 19 | Poly1305(..), R(..), S(..), WORD, Key(..) 20 | ) where 21 | 22 | import Foreign.Storable( Storable ) 23 | import Raaz.Core 24 | 25 | -- $poly1305$ 26 | -- 27 | -- This module exposes the types required to implement the the 28 | -- poly1305 message authenticator. The poly1305 is a function that 29 | -- takes two parameters `r` and `s` and for an input message `m` 30 | -- computes the function. 31 | -- 32 | -- Poly1305(m, r,s) = (M(r) mod 2^130 - 5) + s mod 2^128 33 | -- 34 | -- In the original publication, `r` is selected pseudo-randomly and 35 | -- `s` is generated by encrypting (using AES) a nonce `n` with a 36 | -- secret key k, i.e. r = random; s = AES(k,n). The secret that needs 37 | -- to be shared by the two parties is `r` and the key `k`. Actual 38 | -- protocols should never repeat the nonce `n` for otherwise there 39 | -- will be compromise in the security. The RFC7539 uses a variant 40 | -- that uses the chacha20 cipher instead of AES. 41 | -- 42 | -- As can be seen from the above discussion the actual mechanism for 43 | -- selecting the `r` and `s` differs depending on the 44 | -- situation. Hence, this module only provide the "raw" Poly1305 45 | -- implementation leaving out the details of the selection of `r` and 46 | -- `s` for some latter stage. Thus this module is not of direct use 47 | -- but is used by actual protocols to implement message 48 | -- authentication. 49 | 50 | -- | A Poly1305 word is a 128-bit numbers in little-endian. 51 | type WORD = Tuple 2 (LE Word64) 52 | 53 | -- | The datatype that captures the Poly1305 authenticator tag. 54 | newtype Poly1305 = Poly1305 WORD deriving (Storable, EndianStore, Equality, Eq) 55 | 56 | -- | The `r` component of the secret. 57 | newtype R = R WORD deriving (Storable, EndianStore, Equality, Eq) 58 | 59 | -- | The `s` component of the secret. 60 | newtype S = S WORD deriving (Storable, EndianStore, Equality, Eq) 61 | 62 | instance Encodable Poly1305 63 | instance Encodable R 64 | instance Encodable S 65 | 66 | instance IsString Poly1305 where 67 | fromString = fromBase16 68 | 69 | instance IsString R where 70 | fromString = fromBase16 71 | 72 | instance IsString S where 73 | fromString = fromBase16 74 | 75 | instance Show Poly1305 where 76 | show = showBase16 77 | 78 | instance Show R where 79 | show = showBase16 80 | 81 | instance Show S where 82 | show = showBase16 83 | 84 | instance Primitive Poly1305 where 85 | type WordType Poly1305 = Word8 86 | type WordsPerBlock Poly1305 = 16 87 | 88 | data instance Key Poly1305 = Key R S deriving Show 89 | -------------------------------------------------------------------------------- /core/Raaz/Core/Types.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- 3 | -- Module : Raaz.Core.Types 4 | -- Description : The core types of raaz 5 | -- Copyright : (c) Piyush P Kurur, 2019 6 | -- License : Apache-2.0 OR BSD-3-Clause 7 | -- Maintainer : Piyush P Kurur 8 | -- Stability : experimental 9 | -- 10 | 11 | module Raaz.Core.Types 12 | ( -- * Overview. 13 | -- $overview$ 14 | module Raaz.Core.Primitive 15 | , module Raaz.Core.Types.Equality 16 | , module Raaz.Core.Types.Endian 17 | , module Raaz.Core.Types.Pointer 18 | , module Raaz.Core.Types.Tuple 19 | , module Raaz.Core.Types.Copying 20 | ) where 21 | 22 | import Raaz.Core.Types.Equality 23 | 24 | import Raaz.Core.Primitive ( BlockCount ) 25 | 26 | import Raaz.Core.Types.Endian 27 | import Raaz.Core.Types.Pointer 28 | 29 | import Raaz.Core.Types.Tuple hiding ( map ) 30 | import Raaz.Core.Types.Copying( Src, Dest, source, destination) 31 | 32 | 33 | -- $overview$ 34 | -- 35 | -- __WARNING:__ If you are just a user of this library, it is unlikely 36 | -- that you will need to import this module. It is only required if 37 | -- you are a developer and want to define a new cryptographic data 38 | -- type. 39 | -- 40 | -- A lot of cryptographic code is low level and involves quite a bit 41 | -- of boilerplate and are therefore fertile grounds for bugs. This 42 | -- module describes types specific to raaz that are designed to catch 43 | -- bugs in such low level code. The three principles that we follow 44 | -- in the design are: 45 | -- 46 | -- 1. Define distinct types for semantically different objects. For 47 | -- example, distinguish between buffer length/pointer offset in 48 | -- bytes versus other units (see `LengthUnit`) or make endian aware 49 | -- variants of standard word types (see `BE` and `LE`) etc. 50 | -- 51 | -- 2. Make sure that the low level functions are sensitive to these 52 | -- types. For example, the function `sizeOf` exposed here returns 53 | -- @`BYTES` `Int`@ instead of just `Int` and functions like 54 | -- `allocaBuffer` are generic enough to work with any length units. 55 | -- 56 | -- 3. Provide obvious instances for some basic type and have and 57 | -- idiom/design pattern to build such interfaces for user defined 58 | -- types. For example, we have a very specific way to build timing 59 | -- safe equality functions for arbitrary types. Most of the time, 60 | -- in our case it just amounts to handling product types. 61 | -- 62 | -- == Role of Monoids. 63 | -- 64 | -- Monoids play an important role in facilitating the top down 65 | -- approach to type safety that we mentioned above. Some types 66 | -- described here have a natural monoid semantics. For example, when 67 | -- dealing with pointer offsets and buffer sizes, we use type safe 68 | -- length units like `BYTES`. These length units are instances of 69 | -- monoids where the underlying operation is addition. On the other 70 | -- hand, when it comes to pointer alignment which is captured by the 71 | -- type `Alignment`, the monoid operation is taking the lowest common 72 | -- multiple. 73 | -- 74 | {-# ANN module "HLint: ignore Use import/export shortcut" #-} 75 | -------------------------------------------------------------------------------- /implementation/Blake2b/CHandWritten.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | {-# LANGUAGE DataKinds #-} 3 | 4 | 5 | -- | The portable C-implementation of Blake2b. 6 | module Blake2b.CHandWritten where 7 | 8 | import Raaz.Core 9 | import Raaz.Core.Transfer.Unsafe 10 | import Raaz.Core.Types.Internal 11 | import Raaz.Primitive.HashMemory 12 | import Raaz.Primitive.Blake2.Internal 13 | 14 | 15 | name :: String 16 | name = "handwritten-c" 17 | 18 | primName :: String 19 | primName = "blake2b" 20 | 21 | description :: String 22 | description = "Hand written Blake2b Implementation in portable C" 23 | 24 | type Prim = Blake2b 25 | type Internals = Blake2bMem 26 | type BufferAlignment = 32 27 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 28 | 29 | additionalBlocks :: BlockCount Blake2b 30 | additionalBlocks = blocksOf 1 Proxy 31 | 32 | 33 | ------------------------ The foreign function calls --------------------- 34 | 35 | foreign import ccall unsafe 36 | "raaz/hash/blake2/common.h raazHashBlake2bPortableBlockCompress" 37 | c_blake2b_compress :: BufferPtr 38 | -> BlockCount Prim 39 | -> Ptr (BYTES Word64) 40 | -> Ptr (BYTES Word64) 41 | -> Ptr Blake2b 42 | -> IO () 43 | 44 | foreign import ccall unsafe 45 | "raaz/hash/blake2/common.h raazHashBlake2bPortableLastBlock" 46 | c_blake2b_last :: BlockPtr Prim 47 | -> BYTES Int 48 | -> BYTES Word64 49 | -> BYTES Word64 50 | -> Word64 51 | -> Word64 52 | -> Ptr Blake2b 53 | -> IO () 54 | 55 | -- 56 | processBlocks :: BufferPtr 57 | -> BlockCount Blake2b 58 | -> Blake2bMem 59 | -> IO () 60 | 61 | processBlocks buf blks b2bmem = 62 | let uPtr = uLengthCellPointer b2bmem 63 | lPtr = lLengthCellPointer b2bmem 64 | hshPtr = hashCell128Pointer b2bmem 65 | in c_blake2b_compress buf blks uPtr lPtr hshPtr 66 | 67 | -- | Process the last bytes. 68 | processLast :: BufferPtr 69 | -> BYTES Int 70 | -> Blake2bMem 71 | -> IO () 72 | processLast buf nbytes b2bmem = do 73 | unsafeTransfer padding buf -- pad the message 74 | processBlocks buf nBlocks b2bmem -- process all but the last block 75 | -- 76 | -- Handle the last block 77 | -- 78 | let 79 | hshPtr = hashCell128Pointer b2bmem 80 | in do u <- getULength b2bmem 81 | l <- getLLength b2bmem 82 | c_blake2b_last lastBlockPtr remBytes u l f0 f1 hshPtr 83 | 84 | where padding = blake2Pad (Proxy :: Proxy Blake2b) nbytes 85 | nBlocks = atMost (transferSize padding) `mappend` toEnum (-1) 86 | -- all but the last block 87 | remBytes = nbytes - inBytes nBlocks 88 | -- Actual bytes in the last block. 89 | lastBlockPtr = forgetAlignment buf `movePtr` nBlocks 90 | -- 91 | -- Finalisation FLAGS 92 | -- 93 | f0 = complement 0 94 | f1 = 0 95 | -------------------------------------------------------------------------------- /indef/chacha20/XChaCha20/Implementation.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | {-# LANGUAGE MultiParamTypeClasses #-} 3 | 4 | module XChaCha20.Implementation where 5 | 6 | import Raaz.Core 7 | import Raaz.Primitive.ChaCha20.Internal 8 | 9 | 10 | import qualified Implementation as Base 11 | 12 | -- | Name of the implementation 13 | name :: String 14 | name = Base.name 15 | 16 | -- | Then name of the primitive. 17 | primName :: String 18 | primName = "xchacha20" 19 | 20 | -- | A description of what this implementation is about. 21 | description :: String 22 | description = Base.description ++ " This is the XChaCha variant." 23 | 24 | -- | The underlying cryptographic primitive is the XChaCha20 cipher. 25 | type Prim = XChaCha20 26 | 27 | -- | The internal memory used by XChaCha20 implementation. It consists 28 | -- of a copy of the key and the internals of the associated chaca20 29 | -- implementation. 30 | data Internals = XChaCha20Mem 31 | { copyOfKey :: MemoryCell (Key ChaCha20) 32 | , chacha20Internals :: Base.Internals 33 | } 34 | 35 | type BufferAlignment = Base.BufferAlignment 36 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 37 | 38 | instance Memory Internals where 39 | memoryAlloc = XChaCha20Mem <$> memoryAlloc <*> memoryAlloc 40 | unsafeToPointer = unsafeToPointer . copyOfKey 41 | 42 | 43 | instance Initialisable Internals (Key XChaCha20) where 44 | initialise xkey = initialise xkey . copyOfKey 45 | 46 | instance WriteAccessible Internals where 47 | writeAccess = writeAccess . copyOfKey 48 | afterWriteAdjustment = afterWriteAdjustment . copyOfKey 49 | 50 | instance Initialisable Internals (Nounce XChaCha20) where 51 | initialise xnounce imem = do 52 | let dest = destination $ chacha20Internals imem 53 | src = source $ copyOfKey imem 54 | in Base.copyKey dest src 55 | Base.xchacha20Setup xnounce $ chacha20Internals imem 56 | 57 | instance Initialisable Internals (BlockCount XChaCha20) where 58 | initialise bcount = initialise bcountP . chacha20Internals 59 | where bcountP :: BlockCount ChaCha20 60 | bcountP = toEnum $ fromEnum bcount 61 | 62 | instance Extractable Internals (BlockCount XChaCha20) where 63 | extract = fmap coerce . extract . chacha20Internals 64 | where coerce :: BlockCount ChaCha20 -> BlockCount XChaCha20 65 | coerce = toEnum . fromEnum 66 | 67 | additionalBlocks :: BlockCount XChaCha20 68 | additionalBlocks = coerce Base.additionalBlocks 69 | where coerce :: BlockCount Base.Prim -> BlockCount XChaCha20 70 | coerce = toEnum . fromEnum 71 | 72 | 73 | processBlocks :: BufferPtr 74 | -> BlockCount Prim 75 | -> Internals 76 | -> IO () 77 | processBlocks buf bcount = 78 | Base.processBlocks (castPointer buf) (coerce bcount) . chacha20Internals 79 | where coerce :: BlockCount XChaCha20 -> BlockCount Base.Prim 80 | coerce = toEnum . fromEnum 81 | 82 | -- | Process the last bytes. 83 | processLast :: BufferPtr 84 | -> BYTES Int 85 | -> Internals 86 | -> IO () 87 | processLast buf nbytes = Base.processLast (castPointer buf) nbytes . chacha20Internals 88 | -------------------------------------------------------------------------------- /core/Raaz/Primitive/Keyed/Internal.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 2 | {-# LANGUAGE TypeFamilies #-} 3 | {-# LANGUAGE FlexibleInstances #-} 4 | 5 | -- | 6 | -- 7 | -- Module : Raaz.Primitive.Keyed.Internal 8 | -- Description : Keyed hashing primitives. 9 | -- Copyright : (c) Piyush P Kurur, 2019 10 | -- License : Apache-2.0 OR BSD-3-Clause 11 | -- Maintainer : Piyush P Kurur 12 | -- Stability : experimental 13 | -- 14 | 15 | module Raaz.Primitive.Keyed.Internal 16 | ( -- * Keyed Hashing. 17 | -- $keyedhash$ 18 | -- 19 | Keyed(..), KeyedHash(..), Key(..), unsafeToKeyed, unsafeToPrim 20 | ) where 21 | 22 | import Data.ByteString as BS 23 | import Foreign.Storable ( Storable ) 24 | 25 | import Raaz.Core 26 | 27 | -- $keyedhash$ 28 | -- 29 | -- The keyed version of a cryptographic hash. Certain hashes like 30 | -- blake2 can be used for message authentication where the message is 31 | -- essentially appended to the key and hashed. This module is meant to 32 | -- handle such keyed primitives. Note that this naive message 33 | -- authentication is vulnerable to length extension attack when 34 | -- combined with a Merkel-Damgrad like hash like the sha2 family of 35 | -- hashes; they require a more complicated HMAC construction. 36 | 37 | -- | Class of primitives, typically cryptographic hashes, that when 38 | -- used as a keyed hash gives a safe MAC. 39 | class KeyedHash prim where 40 | -- The initialisation used by the hash can depend on the length of 41 | -- the key used. 42 | hashInit :: BYTES Int -> prim 43 | 44 | -- | The message authentication code associated with the hashes. 45 | newtype Keyed prim = Keyed prim 46 | deriving (Eq, Equality, Storable, EndianStore, Encodable) 47 | 48 | instance IsString prim => IsString (Keyed prim) where 49 | fromString = unsafeToKeyed . fromString 50 | 51 | instance Show prim => Show (Keyed prim) where 52 | show = show . unsafeToPrim 53 | 54 | instance Primitive prim => Primitive (Keyed prim) where 55 | type WordType (Keyed prim) = WordType prim 56 | type WordsPerBlock (Keyed prim) = WordsPerBlock prim 57 | 58 | --------------- Key used by the keyed prim ----------------------------- 59 | 60 | newtype instance Key (Keyed prim) = Key ByteString 61 | 62 | instance IsString (Key (Keyed prim)) where 63 | fromString = Key . fromBase16 64 | 65 | instance Show (Key (Keyed prim)) where 66 | show (Key hkey) = showBase16 hkey 67 | 68 | instance Encodable (Key (Keyed prim)) where 69 | toByteString (Key bs) = bs 70 | fromByteString = Just . Key 71 | unsafeFromByteString = Key 72 | 73 | -- | Converts a Keyed value to the corresponding hash value. This 74 | -- function violates the principle that semantically distinct values 75 | -- should be of distinct types and hence should be considered unsafe 76 | unsafeToPrim :: Keyed prim -> prim 77 | unsafeToPrim (Keyed p) = p 78 | 79 | 80 | -- | Converts the hash value to the corresponding @`Keyed`@ 81 | -- value. This function violates the principle that semantically 82 | -- distinct values should be of distinct types and hence should be 83 | -- considered unsafe. 84 | unsafeToKeyed :: prim -> Keyed prim 85 | unsafeToKeyed = Keyed 86 | -------------------------------------------------------------------------------- /api/digest/Interface.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RecordWildCards #-} 2 | -- | 3 | -- 4 | -- Module : digest-api: Interface 5 | -- Description : Generic interface to message digest. 6 | -- Copyright : (c) Piyush P Kurur, 2019 7 | -- License : Apache-2.0 OR BSD-3-Clause 8 | -- Maintainer : Piyush P Kurur 9 | -- Stability : experimental 10 | -- 11 | module Interface ( Digest 12 | , digest 13 | , digestFile 14 | , digestSource 15 | , DigestCxt 16 | , startDigest 17 | , updateDigest 18 | , finaliseDigest 19 | , name 20 | , primName 21 | , description 22 | ) where 23 | 24 | import GHC.TypeLits 25 | 26 | import qualified Data.ByteString as B 27 | import qualified Data.ByteString.Lazy as L 28 | import System.IO.Unsafe (unsafePerformIO) 29 | 30 | 31 | import Raaz.Core 32 | import qualified Implementation 33 | import Utils 34 | import Context 35 | 36 | type Digest = Implementation.Prim 37 | type DigestCxt = Cxt 38 | -- | Compute the digest of a pure byte source like, `B.ByteString`. 39 | digest :: PureByteSource src 40 | => src -- ^ Message 41 | -> Digest 42 | digest = unsafePerformIO . digestSource 43 | {-# INLINEABLE digest #-} 44 | {-# SPECIALIZE digest :: B.ByteString -> Digest #-} 45 | {-# SPECIALIZE digest :: L.ByteString -> Digest #-} 46 | 47 | -- | Compute the digest of file. 48 | digestFile :: FilePath -- ^ File to be digested 49 | -> IO Digest 50 | digestFile fileName = withBinaryFile fileName ReadMode digestSource 51 | {-# INLINEABLE digestFile #-} 52 | 53 | -- | Compute the digest of an arbitrary byte source. 54 | digestSource :: ByteSource src 55 | => src 56 | -> IO Digest 57 | {-# SPECIALIZE digestSource :: B.ByteString -> IO Digest #-} 58 | {-# SPECIALIZE digestSource :: L.ByteString -> IO Digest #-} 59 | {-# SPECIALIZE digestSource :: Handle -> IO Digest #-} 60 | 61 | digestSource src = withMemory $ \ mem -> do 62 | initialise () mem 63 | processByteSource src mem 64 | extract mem 65 | 66 | -- | Textual name of the digest implementation. 67 | name :: String 68 | name = Implementation.name 69 | 70 | -- | Textual name of the primitive 71 | primName :: String 72 | primName = Implementation.primName 73 | 74 | -- | Description of the implementation 75 | description :: String 76 | description = Implementation.description 77 | 78 | -- | Prepare the context to (re)start a session of incremental 79 | -- processing. 80 | startDigest :: KnownNat n => Cxt n -> IO () 81 | startDigest cxt@Cxt{..} = do initialise () cxtInternals 82 | unsafeSetCxtEmpty cxt 83 | 84 | 85 | -- | Add some more data into the context, in this case the entirety of 86 | -- the byte source src. 87 | updateDigest :: (KnownNat n, ByteSource src) 88 | => src 89 | -> Cxt n 90 | -> IO () 91 | updateDigest = updateCxt 92 | 93 | -- | Finalise the context to get hold of the digest. 94 | finaliseDigest :: KnownNat n 95 | => Cxt n 96 | -> IO Digest 97 | finaliseDigest cxt@Cxt{..} = finaliseCxt cxt >> extract cxtInternals 98 | -------------------------------------------------------------------------------- /implementation/Poly1305/Memory.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE MultiParamTypeClasses #-} 3 | {-# LANGUAGE FlexibleInstances #-} 4 | -- | This module implements memory elements used for Poly1305 5 | -- implementations. 6 | module Poly1305.Memory 7 | ( Mem(..) 8 | , Element 9 | , elementToInteger 10 | , rKeyPtr 11 | , sKeyPtr 12 | , accumPtr 13 | ) where 14 | 15 | import qualified Data.Vector.Unboxed as V 16 | import Foreign.Ptr ( castPtr ) 17 | import Raaz.Core 18 | import qualified Raaz.Core.Types.Internal as TI 19 | import Raaz.Primitive.Poly1305.Internal 20 | 21 | import Raaz.Verse.Poly1305.C.Portable (verse_poly1305_c_portable_clamp) 22 | 23 | -- | An element in the finite field GF(2¹³⁰ - 5) requires 130 bits 24 | -- which is stored as three 64-bit word where the last word has only 25 | -- 2-bits. 26 | type Element = Tuple 3 Word64 27 | 28 | 29 | -- | Convert the element to an integer. 30 | elementToInteger :: Element -> Integer 31 | elementToInteger = V.foldr fld 0 . unsafeToVector 32 | where fld :: Word64 -> Integer -> Integer 33 | fld w i = toInteger w + i `shiftL` 32 34 | 35 | 36 | -- | The memory associated with Poly1305 stores the 37 | data Mem = Mem { accCell :: MemoryCell Element 38 | , rCell :: MemoryCell R 39 | , sCell :: MemoryCell S 40 | } 41 | 42 | -- | Clearing the accumulator. 43 | clearAcc :: Mem -> IO () 44 | clearAcc = initialise zero . accCell 45 | where zero :: Element 46 | zero = unsafeFromList [0,0,0] 47 | 48 | instance Memory Mem where 49 | memoryAlloc = Mem <$> memoryAlloc <*> memoryAlloc <*> memoryAlloc 50 | unsafeToPointer = unsafeToPointer . accCell 51 | 52 | 53 | -- | Get the pointer to the array holding the key fragment r. 54 | rKeyPtr :: Mem -> Ptr (Tuple 2 Word64) 55 | rKeyPtr = castPtr . unsafeGetCellPointer . rCell 56 | 57 | -- | Get the pointer to the array holding the key fragment s. 58 | sKeyPtr :: Mem -> Ptr (Tuple 2 Word64) 59 | sKeyPtr = castPtr . unsafeGetCellPointer . sCell 60 | 61 | -- | Get the pointer to the accumulator array. 62 | accumPtr :: Mem -> Ptr Element 63 | accumPtr = castPtr . unsafeGetCellPointer . accCell 64 | 65 | -- | The clamping function on pointer 66 | clampPtr :: Ptr (Tuple 2 Word64) -> IO () 67 | clampPtr = flip verse_poly1305_c_portable_clamp 1 68 | 69 | -- | The clamping operation 70 | clamp :: Mem -> IO () 71 | clamp = clampPtr . rKeyPtr 72 | 73 | instance Initialisable Mem (Key Poly1305) where 74 | initialise (Key r s) mem = do clearAcc mem 75 | initialise r $ rCell mem 76 | initialise s $ sCell mem 77 | clamp mem 78 | 79 | instance Extractable Mem Poly1305 where 80 | extract = fmap toPoly1305 . extract . accCell 81 | where toPoly1305 = Poly1305 . TI.map littleEndian . project 82 | project :: Tuple 3 Word64 -> Tuple 2 Word64 83 | project = initial 84 | 85 | instance WriteAccessible Mem where 86 | writeAccess mem = writeAccess (rCell mem) ++ writeAccess (sCell mem) 87 | afterWriteAdjustment mem = do 88 | clearAcc mem 89 | afterWriteAdjustment $ rCell mem 90 | afterWriteAdjustment $ sCell mem 91 | clamp mem 92 | -------------------------------------------------------------------------------- /implementation/Blake2b/CPortable.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | 3 | -- | The portable C-implementation of Blake2b. 4 | module Blake2b.CPortable where 5 | 6 | 7 | import Foreign.Ptr ( castPtr ) 8 | 9 | import Raaz.Core 10 | import Raaz.Core.Transfer.Unsafe 11 | import Raaz.Core.Types.Internal 12 | import Raaz.Primitive.HashMemory 13 | import Raaz.Primitive.Blake2.Internal 14 | import Raaz.Verse.Blake2b.C.Portable 15 | 16 | name :: String 17 | name = "libverse-c" 18 | 19 | primName :: String 20 | primName = "blake2b" 21 | 22 | description :: String 23 | description = "Blake2b Implementation in C exposed by libverse" 24 | 25 | type Prim = Blake2b 26 | type Internals = Blake2bMem 27 | type BufferAlignment = 32 28 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 29 | 30 | additionalBlocks :: BlockCount Blake2b 31 | additionalBlocks = blocksOf 1 Proxy 32 | 33 | 34 | processBlocks :: BufferPtr 35 | -> BlockCount Blake2b 36 | -> Blake2bMem 37 | -> IO () 38 | 39 | processBlocks buf blks b2bmem = 40 | let uPtr = castPtr $ uLengthCellPointer b2bmem 41 | lPtr = castPtr $ lLengthCellPointer b2bmem 42 | hshPtr = castPtr $ hashCell128Pointer b2bmem 43 | -- 44 | -- Type coersions to the appropriate type. 45 | -- 46 | wblks = toEnum $ fromEnum blks 47 | blkPtr = castPtr $ forgetAlignment buf 48 | in verse_blake2b_c_portable_iter blkPtr wblks uPtr lPtr hshPtr 49 | 50 | 51 | -- | Process the last bytes. The last block of the message (whether it 52 | -- is padded or not) should necessarily be processed by the 53 | -- processLast function as one needs to set the finalisation flag for 54 | -- it. 55 | -- 56 | -- Let us consider two cases. 57 | -- 58 | -- 1. The message is empty. In which case the padding is 1-block 59 | -- size. This needs to be processed as the last block 60 | -- 61 | -- 2. If the message is non-empty then the padded message is the least 62 | -- multiple @n@ of block size that is greater than or equal to the 63 | -- input and hence is at least 1 block in size. Therefore, we 64 | -- should be compressing a total @n-1@ blocks using the block 65 | -- compression function at the last block using the finalisation 66 | -- flags. 67 | -- 68 | processLast :: BufferPtr 69 | -> BYTES Int 70 | -> Blake2bMem 71 | -> IO () 72 | processLast buf nbytes b2bmem = do 73 | unsafeTransfer padding $ forgetAlignment buf -- pad the message 74 | processBlocks buf nBlocks b2bmem -- process all but the last block 75 | -- 76 | -- Handle the last block 77 | -- 78 | BYTES u <- getULength b2bmem 79 | BYTES l <- getLLength b2bmem 80 | let hshPtr = castPtr $ hashCell128Pointer b2bmem 81 | in verse_blake2b_c_portable_last lastBlockPtr remBytes u l f0 f1 hshPtr 82 | 83 | where padding = blake2Pad (Proxy :: Proxy Blake2b) nbytes 84 | nBlocks = atMost (transferSize padding) `mappend` toEnum (-1) 85 | -- all but the last block 86 | remBytes = toEnum $ fromEnum $ nbytes - inBytes nBlocks 87 | -- Actual bytes in the last block. 88 | lastBlockPtr = castPtr (forgetAlignment buf `movePtr` nBlocks) 89 | -- 90 | -- Finalisation FLAGS 91 | -- 92 | f0 = complement 0 93 | f1 = 0 94 | -------------------------------------------------------------------------------- /implementation/ChaCha20/CPortable.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | 3 | -- | The portable C-implementation of Blake2b. 4 | module ChaCha20.CPortable where 5 | 6 | import Foreign.Ptr ( castPtr ) 7 | import qualified Data.Vector.Unboxed as V 8 | 9 | import Raaz.Core 10 | import Raaz.Core.Types.Internal 11 | import Raaz.Primitive.ChaCha20.Internal 12 | import Raaz.Verse.ChaCha20.C.Portable 13 | 14 | name :: String 15 | name = "libverse-c" 16 | 17 | primName :: String 18 | primName = "chacha20" 19 | 20 | description :: String 21 | description = "ChaCha20 Implementation in C exposed by libverse" 22 | 23 | type Prim = ChaCha20 24 | type Internals = ChaCha20Mem 25 | type BufferAlignment = 32 26 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 27 | 28 | additionalBlocks :: BlockCount ChaCha20 29 | additionalBlocks = blocksOf 1 Proxy 30 | 31 | processBlocks :: BufferPtr 32 | -> BlockCount Prim 33 | -> Internals 34 | -> IO () 35 | 36 | processBlocks = runBlockProcess verse_chacha20_c_portable 37 | 38 | 39 | -- | Process the last bytes. 40 | processLast :: BufferPtr 41 | -> BYTES Int 42 | -> Internals 43 | -> IO () 44 | processLast buf = processBlocks buf . atLeast 45 | 46 | 47 | -- | The xchacha20Setup does the following to the internal state 48 | -- 49 | -- 1. Replaces the key stored in the keyCell using the hchacah20 hashing function 50 | -- 51 | -- 2. Initialises the ivcell with the last two words in the xiv value. 52 | -- 53 | -- As a result the internal state is ready to start encrypting using 54 | -- the xchacha20 variant. 55 | -- 56 | xchacha20Setup :: Nounce XChaCha20 -> Internals -> IO () 57 | xchacha20Setup (XNounce tup) mem = do 58 | verse_hchacha20_c_portable keyPtr h0 h1 h2 h3 59 | -- In the above step, the key gets replaced by the subkey obtained 60 | -- from the hchacha20 hash. Note that verse_hchacha expects a 61 | -- Word32 for h0 .. , h3 and hence the match LE h0 ... LE h3 in the 62 | -- where clause below. 63 | initialise iv $ ivCell mem 64 | -- The associated chacha 20 iv is just the rest of the words from 65 | -- the XChacha20 IV. When building the iv we need them as LE Word32 66 | -- and hence we do a simple h4, h4 match below. 67 | where keyPtr = castPtr $ keyCellPtr mem 68 | [LE h0,LE h1,LE h2, LE h3, h4, h5] = V.toList $ unsafeToVector tup 69 | iv = Nounce $ unsafeFromList [0, h4, h5] :: Nounce ChaCha20 70 | 71 | 72 | -- | Copy the key from the memory cell chacha20Mem. 73 | copyKey :: Dest ChaCha20Mem -> Src (MemoryCell (Key ChaCha20)) -> IO () 74 | copyKey = copyCell . fmap keyCell 75 | 76 | -------------- Helper function for running an iterator ----------- 77 | runBlockProcess :: ( Ptr buf -> 78 | Word64 -> 79 | Ptr a -> 80 | Ptr b -> 81 | Ptr c -> 82 | IO () 83 | ) 84 | -> BufferPtr 85 | -> BlockCount Prim 86 | -> Internals 87 | -> IO () 88 | runBlockProcess func buf blks mem = 89 | let keyPtr = castPtr $ keyCellPtr mem 90 | ivPtr = castPtr $ ivCellPtr mem 91 | counterPtr = castPtr $ counterCellPtr mem 92 | blkPtr = castPtr $ forgetAlignment buf 93 | wBlks = toEnum $ fromEnum blks 94 | in func blkPtr wBlks keyPtr ivPtr counterPtr 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Raaz: A secure cryptographic library 2 | ==================================== 3 | 4 | [![Apache-2.0 OR BSD-3-Clause][shields-license]](#legal) 5 | [![][ci-build]][github-actions] 6 | [![][ci-checks]][github-actions] 7 | [![Hackage][hackage-badge]][hackage] 8 | [![Hackage Dependencies][hackage-deps-badge]][hackage-deps] 9 | 10 | Raaz is a cryptographic library in Haskell that provide a high level 11 | and safe access to a lot of cryptographic operations. The library can 12 | be used for standalone cryptographic applications as well as for 13 | implementing other network protocols. Some of the features that are 14 | unique to raaz are the following 15 | 16 | 1. Pervasive use of types for better safety. 17 | 2. Default choice of primitives and implementations are safe. 18 | 3. Mechanism to have multiple implementations for any given 19 | cryptographic primitives. An advanced user who has an in-depth 20 | knowledge of the platform should be able to plugin the desired 21 | implementation. 22 | 4. Strong emphasis on API design with thorough documentation. 23 | 24 | Building 25 | -------- 26 | 27 | The recommended way to install raaz is through `cabal-install` version 28 | 3.0 or above. We also need a version of GHC that supports backpack 29 | (for details on which version of GHC is supported, refer to our 30 | [CI-builds][github-actions]). 31 | 32 | cabal build 33 | cabal test 34 | cabal install 35 | 36 | Online documentation 37 | -------------------- 38 | 39 | - [Latest release][doc-latest] 40 | - [Release candidate][doc-candidate] 41 | 42 | About the name 43 | -------------- 44 | 45 | The word `Raaz` (राज़) stands for secret in Hindi. 46 | 47 | 48 | Legal 49 | ----- 50 | 51 | Copyright 2012 Piyush P Kurur 52 | 53 | The library is licensed under 54 | 55 | * Apache License, Version 2.0 56 | 57 | * BSD 3-Clause license 58 | 59 | 60 | You may not use this software except in compliance with one of the 61 | above Licenses (*at your option*). 62 | 63 | SPDX-License-Identifier: (Apache-2.0 OR BSD-3-Clause) 64 | 65 | Unless required by applicable law or agreed to in writing, software 66 | distributed under these Licenses is distributed on an "AS IS" BASIS, 67 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 68 | implied. For the exact terms and conditions see the accompanying 69 | LICENSE file. 70 | 71 | 72 | [wiki]: "Raaz Wiki" 73 | [repo]: "Raaz on github" 74 | [blake2]: "Blake2 hash function" 75 | [emailgroups]: "Raaz on Google groups" 76 | [hackage]: 77 | [hackage-badge]: 78 | [hackage-deps-badge]: 79 | [hackage-deps]: 80 | [shields-license]: 81 | [ci-build]: "Building source" 82 | [ci-checks]: "Source code checks" 83 | [github-actions]: "Github actions" 84 | [doc-latest]: 85 | [doc-candidate]: 86 | -------------------------------------------------------------------------------- /indef/Implementation.hsig: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ConstraintKinds #-} 2 | {-# LANGUAGE DataKinds #-} 3 | {-# LANGUAGE KindSignatures #-} 4 | {-# LANGUAGE MultiParamTypeClasses #-} 5 | {-# LANGUAGE FlexibleInstances #-} 6 | {-# LANGUAGE TypeFamilies #-} 7 | {-# LANGUAGE CPP #-} 8 | 9 | -- | 10 | -- 11 | -- Module : indef:Implementation 12 | -- Copyright : (c) Piyush P Kurur, 2019 13 | -- License : Apache-2.0 OR BSD-3-Clause 14 | -- Maintainer : Piyush P Kurur 15 | -- Stability : experimental 16 | -- 17 | -- Implementation of a low level cryptographic bulk primitive, like a 18 | -- cryptographic hash or a cipher, essentially consists of of two 19 | -- functions. 20 | -- 21 | -- [@`processBlocks`@:] Processes multiple blocks of data till we have 22 | -- the last chuck of data which may not end at a block boundary in which 23 | -- case switch to 24 | -- 25 | -- [@`processLast`@:] Completes processing the input. 26 | -- 27 | -- Any padding or special processing that is required at the end has 28 | -- to be handled by `processLast`. 29 | -- 30 | -- Besides these, fast implementations involve other details like the 31 | -- alignment restriction on the input buffer, additional space 32 | -- required at the end of the buffer for padding etc. This signature 33 | -- captures all such details. 34 | -- 35 | 36 | signature Implementation where 37 | 38 | import Raaz.Core 39 | 40 | # if MIN_VERSION_base(4,13,0) 41 | 42 | import GHC.TypeLits 43 | 44 | # endif 45 | 46 | -- | Name of the implementation. 47 | name :: String 48 | 49 | -- | Name of the primitive 50 | primName :: String 51 | 52 | -- | Description of the implementation. 53 | description :: String 54 | 55 | -- | The primitive for which the implementation is given 56 | data Prim 57 | 58 | -- | The internal memory used by the implementation. 59 | data Internals 60 | 61 | instance Primitive Prim 62 | instance Memory Internals 63 | 64 | 65 | # if MIN_VERSION_base(4,13,0) 66 | 67 | -- | The alignment requirements on the buffer. 68 | data BufferAlignment :: Nat 69 | instance KnownNat BufferAlignment 70 | 71 | # else 72 | -- | The alignment required for buffer (hack around bug 73 | -- https://ghc.haskell.org/trac/ghc/ticket/15138) 74 | type BufferAlignment = 32 75 | #endif 76 | 77 | -- | The pointer type associated with the buffer used by the 78 | -- implementation. 79 | type BufferPtr = AlignedBlockPtr BufferAlignment Prim 80 | 81 | -- | The additional space other than the payload that required in the 82 | -- buffer for processing the data. There are multiple reasons for 83 | -- having this additional space. The most important case is for 84 | -- handling padding when processing the last block. Some fast 85 | -- implementations, particularly those which use SIMD instructions, 86 | -- handle data that is often a multiple of the block size. In such 87 | -- cases, it make sense to have additional blocks in such cases to 88 | -- make the overall implementation simple. 89 | additionalBlocks :: BlockCount Prim 90 | 91 | -- | The function that process bytes in multiples of the block size of 92 | -- the primitive. 93 | processBlocks :: BufferPtr 94 | -> BlockCount Prim 95 | -> Internals 96 | -> IO () 97 | 98 | -- | Process the last bytes of the stream. 99 | processLast :: BufferPtr 100 | -> BYTES Int 101 | -> Internals 102 | -> IO () 103 | -------------------------------------------------------------------------------- /implementation/cbits/raaz/cipher/chacha20/cportable.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | /* The main chacha20 block transform for a complete block of data. 4 | * 5 | * Maximum bytes that should be encoded is 2^32 * 64 = 256GB. The 6 | * counter repeats after that. 7 | * 8 | */ 9 | 10 | 11 | 12 | /* Warnings all macros are unprotected use with care */ 13 | 14 | # define R(x,i) ((x << i) | (x >> (32 - i))) 15 | 16 | # define QROUND(a,b,c,d) \ 17 | { \ 18 | a += b; d ^= a; d = R(d,16); \ 19 | c += d; b ^= c; b = R(b,12); \ 20 | a += b; d ^= a; d = R(d,8); \ 21 | c += d; b ^= c; b = R(b,7); \ 22 | } \ 23 | 24 | 25 | 26 | # define ROUND \ 27 | { \ 28 | QROUND(x0, x4, x8, x12); \ 29 | QROUND(x1, x5, x9, x13); \ 30 | QROUND(x2, x6, x10, x14); \ 31 | QROUND(x3, x7, x11, x15); \ 32 | QROUND(x0, x5, x10, x15); \ 33 | QROUND(x1, x6, x11, x12); \ 34 | QROUND(x2, x7, x8, x13); \ 35 | QROUND(x3, x4, x9, x14); \ 36 | } 37 | 38 | 39 | # define XOR(i,a) (*msg)[i] ^= raaz_tole32(a) 40 | # define EMIT(i,a) (*msg)[i] = a 41 | 42 | /* 43 | 44 | Some function for debugging. 45 | 46 | # define PR(i) printf("%8x ", x##i) 47 | # define PRM(i) printf("%8x ", (*msg)[i]) 48 | # define NEWLINE printf("\n") 49 | # define PRINTSTATE \ 50 | { \ 51 | PR(0); PR(1); PR(2); PR(3); NEWLINE; \ 52 | PR(4); PR(5); PR(6); PR(7); NEWLINE; \ 53 | PR(8); PR(9); PR(10); PR(11); NEWLINE; \ 54 | PR(12); PR(13); PR(14); PR(15); NEWLINE; \ 55 | } 56 | 57 | # define PRINTMESG \ 58 | { \ 59 | PRM(0); PRM(1); PRM(2); PRM(3); NEWLINE; \ 60 | PRM(4); PRM(5); PRM(6); PRM(7); NEWLINE; \ 61 | PRM(8); PRM(9); PRM(10); PRM(11); NEWLINE; \ 62 | PRM(12); PRM(13); PRM(14); PRM(15); NEWLINE; \ 63 | } 64 | 65 | */ 66 | 67 | 68 | 69 | # pragma GCC optimize "tree-vectorize" 70 | 71 | void raazChaCha20Block(Block * msg, int nblocks, const Key key, const IV iv, Counter *ctr) 72 | { 73 | register Word x0, x1, x2, x3; 74 | register Word x4, x5, x6, x7; 75 | register Word x8, x9, x10, x11; 76 | register Word x12, x13, x14, x15; 77 | register Word valCtr; /* value of the ctr */ 78 | 79 | valCtr = *ctr; 80 | while( nblocks > 0){ 81 | 82 | 83 | x0 = C0 ; x1 = C1 ; x2 = C2 ; x3 = C3 ; 84 | x4 = key[0] ; x5 = key[1] ; x6 = key[2] ; x7 = key[3] ; 85 | x8 = key[4] ; x9 = key[5] ; x10 = key[6] ; x11 = key[7] ; 86 | x12 = valCtr ; x13 = iv[0] ; x14 = iv[1] ; x15 = iv[2] ; 87 | 88 | 89 | ROUND; /* 0,1 */ 90 | ROUND; /* 2,3 */ 91 | ROUND; /* 4,5 */ 92 | ROUND; /* 6,7 */ 93 | ROUND; /* 8,9 */ 94 | ROUND; /* 10,11 */ 95 | ROUND; /* 12,13 */ 96 | ROUND; /* 14,15 */ 97 | ROUND; /* 16,17 */ 98 | ROUND; /* 18,19 */ 99 | 100 | 101 | 102 | x0 += C0 ; x1 += C1 ; x2 += C2 ; x3 += C3 ; 103 | x4 += key[0] ; x5 += key[1] ; x6 += key[2] ; x7 += key[3] ; 104 | x8 += key[4] ; x9 += key[5] ; x10 += key[6] ; x11 += key[7] ; 105 | x12 += valCtr ; x13 += iv[0] ; x14 += iv[1] ; x15 += iv[2] ; 106 | 107 | 108 | XOR(0,x0) ; XOR(1, x1) ; XOR(2, x2) ; XOR(3, x3) ; 109 | XOR(4,x4) ; XOR(5, x5) ; XOR(6, x6) ; XOR(7, x7) ; 110 | XOR(8,x8) ; XOR(9, x9) ; XOR(10, x10) ; XOR(11, x11) ; 111 | XOR(12,x12) ; XOR(13,x13); XOR(14, x14) ; XOR(15, x15) ; 112 | 113 | 114 | ++ valCtr; 115 | --nblocks; ++msg; /* move to the next block */ 116 | } 117 | *ctr = valCtr; /* increment counter */ 118 | return; 119 | } 120 | -------------------------------------------------------------------------------- /raaz/bin/Command/Info.hs: -------------------------------------------------------------------------------- 1 | module Command.Info where 2 | 3 | import Data.Version (showVersion) 4 | import Options.Applicative 5 | import Prelude 6 | import Raaz 7 | import qualified Raaz.Core.CpuSupports as CpuSupports 8 | import qualified Raaz.Auth.Blake2b 9 | import qualified Raaz.Auth.Blake2s 10 | import qualified Raaz.Digest.Blake2b 11 | import qualified Raaz.Digest.Blake2s 12 | import qualified Raaz.Digest.Sha512 13 | import qualified Raaz.Digest.Sha256 14 | 15 | 16 | 17 | information :: Parser (IO ()) 18 | 19 | information = subparser $ mconcat [ commandGroup "Information" 20 | , metavar "INFORMATION" 21 | , infoCmd 22 | ] 23 | 24 | where infoCmd = command "info" $ info (helper <*> opts) 25 | $ mconcat [ fullDesc 26 | , header "raaz info - Print the library information" 27 | , progDesc "prints information about raaz library." 28 | ] 29 | 30 | opts = pure $ sequence_ [ field "Library Version" $ showVersion version 31 | , algorithmInfo 32 | , implementationInfo 33 | , cpuCapabilities 34 | ] 35 | 36 | 37 | 38 | field :: String -> String -> IO () 39 | field title v = putStrLn $ title ++ ": " ++ v 40 | section :: String -> [String] -> IO () 41 | section title lns = do 42 | putStrLn $ title ++ ":" 43 | mapM_ indent lns 44 | where indent = putStrLn . (++) " " 45 | 46 | algorithmInfo :: IO () 47 | algorithmInfo = section "Algorithm Selection" $ map unwords 48 | [ [ "digest:", digestAlgorithm] 49 | , [ "message authentication:", authAlgorithm] 50 | , [ "authenticated encryption:", authEncryptAlgorithm] 51 | , [ "entropy:" , entropySource] 52 | , [ "csprg:", csprgName] 53 | ] 54 | 55 | implementationInfo :: IO () 56 | implementationInfo = section "Implementation Info" $ map unwords 57 | 58 | [ [ "auth (blake2b):", Raaz.Auth.Blake2b.name] 59 | , [ "auth (blake2s):", Raaz.Auth.Blake2s.name] 60 | , [ "blake2b:", Raaz.Digest.Blake2b.name ] 61 | , [ "blake2s:", Raaz.Digest.Blake2s.name ] 62 | , [ "sha512:", Raaz.Digest.Sha512.name ] 63 | , [ "sha256:", Raaz.Digest.Sha256.name ] 64 | , [ "csprg:", csprgImpl ] 65 | ] 66 | 67 | 68 | cpuCapabilities :: IO () 69 | cpuCapabilities = do sse <- CpuSupports.sse 70 | sse2 <- CpuSupports.sse2 71 | sse3 <- CpuSupports.sse3 72 | sse4_1 <- CpuSupports.sse4_1 73 | sse4_2 <- CpuSupports.sse4_2 74 | avx <- CpuSupports.avx 75 | avx2 <- CpuSupports.avx2 76 | let caps = [ (sse, "sse") 77 | , (sse2, "sse2") 78 | , (sse3, "sse3") 79 | , (sse4_1, "sse4.1") 80 | , (sse4_2, "sse4.2") 81 | , (avx, "avx") 82 | , (avx2, "avx2") 83 | ] 84 | w = maximum $ map (length . snd) caps 85 | pad x = x ++ replicate (w - length x + 3) ' ' 86 | display (True, c) = unwords [pad c, "- supported"] 87 | display (_,c) = unwords [pad c, "- cannot detect"] 88 | in section "CPU capabilities" $ map display caps 89 | -------------------------------------------------------------------------------- /raaz/bin/Command/Rand.hs: -------------------------------------------------------------------------------- 1 | -- This command spits out never ending stream of cryptographically 2 | -- secure bytes. Apart from replacing Yo-Yo Honey Singh (`raaz rand > 3 | -- /dev/audio), it is used to test the quality of the randomnes 4 | -- produced. 5 | 6 | module Command.Rand ( rand ) where 7 | 8 | 9 | import Options.Applicative 10 | import Raaz.Core 11 | import Raaz.Random 12 | import Raaz.Random.Internal 13 | 14 | 15 | -- So much bytes generated in one go before writing to stdout. 16 | 17 | bufSize :: BYTES Int 18 | bufSize = 32 * 1024 19 | 20 | 21 | rand :: Parser (IO ()) 22 | rand = subparser $ mconcat [ commandGroup "Randomness" 23 | , metavar "RANDOMNESS" 24 | , randCmd 25 | , entropyCmd 26 | ] 27 | 28 | 29 | 30 | randCmd :: Mod CommandFields (IO ()) 31 | randCmd = command "rand" 32 | $ info (helper <*> randOpts) 33 | $ mconcat [ fullDesc 34 | , header "raaz rand - Cryptographically secure pseudo random bytes." 35 | , progDesc "output cryptographically secure pseudo random bytes." 36 | ] 37 | where randOpts = opts infiniteRand finiteRand 38 | 39 | entropyCmd :: Mod CommandFields (IO ()) 40 | entropyCmd = command "entropy" 41 | $ info (helper <*> entropyOpts) 42 | $ mconcat [ fullDesc 43 | , header "raaz entropy - System entropy." 44 | , progDesc "emit data from the system entropy pool." 45 | ] 46 | where entropyOpts = opts infiniteEntropy finiteEntropy 47 | 48 | opts :: (Ptr Word8 -> IO ()) 49 | -> (BYTES Int -> Ptr Word8 -> IO ()) 50 | -> Parser (IO ()) 51 | opts inf fin = nRandomBytes . toEnum <$> argument auto (metavar "NUMBER_OF_BYTES") 52 | <|> pure infinteBytes 53 | where nRandomBytes n = withBuffer (fin n) 54 | infinteBytes = withBuffer inf 55 | withBuffer = allocaBuffer bufSize 56 | 57 | 58 | 59 | ------------- Rand functions ---------------------------------------------- 60 | 61 | emitRand :: BYTES Int 62 | -> Ptr Word8 63 | -> RandomState 64 | -> IO () 65 | emitRand m ptr rstate = do 66 | fillRandomBytes m (destination ptr) rstate 67 | hPutBuf stdout ptr $ fromIntegral m 68 | 69 | infiniteRand :: Ptr Word8 70 | -> IO () 71 | infiniteRand buf = withRandomState goForEver 72 | where goForEver rstate = go 73 | where go = emitRand bufSize buf rstate >> go 74 | 75 | finiteRand :: BYTES Int 76 | -> Ptr Word8 77 | -> IO () 78 | finiteRand n buf = withRandomState goFinite 79 | where goFinite rstate = go n 80 | where go m | m >= bufSize = do emitRand bufSize buf rstate ; go (m - bufSize) 81 | | otherwise = emitRand m buf rstate 82 | 83 | 84 | 85 | ----------------- Entropy functions ------------------------------------------ 86 | 87 | emitEntropy :: BYTES Int 88 | -> Ptr Word8 89 | -> IO () 90 | emitEntropy m ptr = do 91 | void $ fillSystemEntropy m ptr 92 | hPutBuf stdout ptr $ fromIntegral m 93 | 94 | 95 | infiniteEntropy :: Ptr Word8 96 | -> IO () 97 | infiniteEntropy buf = go 98 | where go = emitEntropy bufSize buf >> go 99 | 100 | finiteEntropy:: BYTES Int 101 | -> Ptr Word8 102 | -> IO () 103 | finiteEntropy n buf = go n 104 | where go m | m >= bufSize = do emitEntropy bufSize buf ; go (m - bufSize) 105 | | otherwise = emitEntropy m buf 106 | -------------------------------------------------------------------------------- /core/Raaz/Core/Util/ByteString.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- 3 | -- Module : Raaz.Core.Util.ByteString 4 | -- Copyright : (c) Piyush P Kurur, 2019 5 | -- License : Apache-2.0 OR BSD-3-Clause 6 | -- Maintainer : Piyush P Kurur 7 | -- Stability : experimental 8 | -- 9 | 10 | {-# LANGUAGE FlexibleContexts #-} 11 | module Raaz.Core.Util.ByteString 12 | ( length, replicate 13 | , create, createFrom 14 | , withByteString 15 | , unsafeCopyToPointer 16 | , unsafeNCopyToPointer 17 | ) where 18 | 19 | import Prelude hiding (length, replicate) 20 | import qualified Data.ByteString as B 21 | import Data.ByteString (ByteString) 22 | import qualified Data.ByteString.Internal as BI 23 | import Data.Word 24 | import Foreign.ForeignPtr (withForeignPtr) 25 | import Foreign.Ptr (castPtr, plusPtr) 26 | 27 | import Raaz.Core.Types.Pointer 28 | import Raaz.Core.Types.Pointer.Internal 29 | import Raaz.Core.Types.Copying 30 | 31 | -- | A typesafe length for Bytestring 32 | length :: ByteString -> BYTES Int 33 | length = BYTES . B.length 34 | 35 | -- | A type safe version of replicate 36 | replicate :: LengthUnit l => l -> Word8 -> ByteString 37 | replicate l = B.replicate sz 38 | where BYTES sz = inBytes l 39 | 40 | -- | Copy the bytestring to the crypto buffer. This operation leads to 41 | -- undefined behaviour if the crypto pointer points to an area smaller 42 | -- than the size of the byte string. 43 | unsafeCopyToPointer :: Pointer ptr 44 | => ByteString -- ^ The source. 45 | -> ptr a -- ^ The destination. 46 | -> IO () 47 | unsafeCopyToPointer bs cptr = withForeignPtr fptr $ 48 | \ p -> memcpy (destination cptr) (source $ p `plusPtr` offset) (BYTES n) 49 | where (fptr, offset,n) = BI.toForeignPtr bs 50 | 51 | 52 | -- | Similar to `unsafeCopyToPointer` but takes an additional input 53 | -- @n@ which is the number of bytes (expressed in type safe length 54 | -- units) to transfer. This operation leads to undefined behaviour if 55 | -- either the bytestring is shorter than @n@ or the crypto pointer 56 | -- points to an area smaller than @n@. 57 | unsafeNCopyToPointer :: LengthUnit n 58 | => n -- ^ length of data to be copied 59 | -> ByteString -- ^ The source byte string 60 | -> Ptr a -- ^ The buffer 61 | -> IO () 62 | unsafeNCopyToPointer n bs cptr = withForeignPtr fptr $ 63 | \ p -> memcpy (destination cptr) (source $ p `plusPtr` offset) n 64 | where (fptr, offset,_) = BI.toForeignPtr bs 65 | 66 | -- | Works directly on the pointer associated with the 67 | -- `ByteString`. This function should only read and not modify the 68 | -- contents of the pointer. 69 | withByteString :: ByteString -> (Ptr something -> IO a) -> IO a 70 | withByteString bs f = withForeignPtr fptr (f . flip plusPtr off) 71 | where (fptr, off, _) = BI.toForeignPtr bs 72 | 73 | -- | The action @create l act@ creates a length @l@ bytestring where 74 | -- the contents are filled using the the @act@ to fill the buffer. 75 | create :: LengthUnit l => l -> (Ptr a -> IO ()) -> IO ByteString 76 | create l act = myCreate (act . castPtr) 77 | where myCreate = BI.create $ fromIntegral $ inBytes l 78 | 79 | -- | The IO action @createFrom n cptr@ creates a bytestring by copying 80 | -- @n@ bytes from the pointer @cptr@. 81 | createFrom :: LengthUnit l => l -> Ptr a -> IO ByteString 82 | createFrom l cptr = create l filler 83 | where filler dptr = memcpy (destination dptr) (source cptr) l 84 | 85 | ---------------------- Hexadecimal encoding. ----------------------------------- 86 | -------------------------------------------------------------------------------- /core/Raaz/Core/Parse.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- 3 | -- Module : Raaz.Core.Parse 4 | -- Description : Applicative parsing from buffers. 5 | -- Copyright : (c) Piyush P Kurur, 2019 6 | -- License : Apache-2.0 OR BSD-3-Clause 7 | -- Maintainer : Piyush P Kurur 8 | -- Stability : experimental 9 | -- 10 | 11 | module Raaz.Core.Parse 12 | ( Parser, parseWidth, parseError, runParser 13 | , parse, parseStorable 14 | , parseVector, parseStorableVector 15 | , parseByteString 16 | , skip 17 | ) where 18 | 19 | import Data.ByteString (ByteString) 20 | import Data.Vector.Generic (Vector) 21 | import Foreign.Storable (Storable, peek) 22 | import System.IO.Unsafe (unsafePerformIO) 23 | 24 | import Raaz.Core.Parse.Unsafe 25 | import Raaz.Core.Prelude 26 | import Raaz.Core.Types.Endian 27 | import Raaz.Core.Types.Pointer 28 | import Raaz.Core.Util.ByteString (createFrom, length, withByteString) 29 | 30 | -- | Skip over some data. 31 | skip :: LengthUnit u => u -> Parser () 32 | skip = flip unsafeMakeParser doNothing 33 | where doNothing = const $ return () 34 | 35 | -- | A parser that fails with a given error message. 36 | parseError :: String -> Parser a 37 | parseError msg = unsafeMakeParser (0 :: BYTES Int) $ \ _ -> fail msg 38 | 39 | -- | Runs a parser on a byte string. It returns `Nothing` if the byte string is smaller than 40 | -- what the parser would consume. 41 | runParser :: Parser a -> ByteString -> Maybe a 42 | runParser pr bs 43 | | length bs < parseWidth pr = Nothing 44 | | otherwise = Just $ unsafePerformIO $ withByteString bs $ unsafeRunParser pr 45 | 46 | -- | The primary purpose of this function is to satisfy type checkers. 47 | parserToProxy :: Parser a -> Proxy a 48 | parserToProxy _ = Proxy 49 | 50 | -- | Parses a value which is an instance of Storable. Beware that this 51 | -- parser expects that the value is stored in machine endian. Mostly 52 | -- it is useful in defining the `peek` function in a complicated 53 | -- `Storable` instance. 54 | parseStorable :: Storable a => Parser a 55 | parseStorable = pa 56 | where pa = unsafeMakeParser (sizeOf $ parserToProxy pa) (peek . castPointer) 57 | 58 | -- | Parse a crypto value. Endian safety is take into account 59 | -- here. This is what you would need when you parse packets from an 60 | -- external source. You can also use this to define the `load` 61 | -- function in a complicated `EndianStore` instance. 62 | parse :: EndianStore a => Parser a 63 | parse = pa 64 | where pa = unsafeMakeParser (sizeOf $ parserToProxy pa) (load . castPointer) 65 | 66 | -- | Parses a strict bytestring of a given length. 67 | parseByteString :: LengthUnit l => l -> Parser ByteString 68 | parseByteString l = unsafeMakeParser l $ createFrom l 69 | 70 | -- | Similar to `parseVector` but parses according to the host 71 | -- endian. This function is essentially used to define storable 72 | -- instances of complicated data. It is unlikely to be of use when 73 | -- parsing externally serialised data as one would want to keep track 74 | -- of the endianness of the data. 75 | parseStorableVector :: (Storable a, Vector v a) => Int -> Parser (v a) 76 | parseStorableVector n | n < 0 = parseError $ "parseStorableVector on " ++ show n 77 | | otherwise = unsafeParseStorableVector n 78 | 79 | -- | Parses a vector of elements. It takes care of the correct endian 80 | -- conversion. This is the function to use while parsing external 81 | -- data. 82 | parseVector :: (EndianStore a, Vector v a) => Int -> Parser (v a) 83 | parseVector n | n < 0 = parseError $ "parseVector on " ++ show n 84 | | otherwise = unsafeParseVector n 85 | -------------------------------------------------------------------------------- /core/cbits/raaz/core/endian.h: -------------------------------------------------------------------------------- 1 | # pragma once 2 | # include 3 | 4 | /* This header file does the following 5 | 6 | 1. Declarations of raazSwap* and RaazSwap*Array functions that are the 7 | C functions for call from Haskell. 8 | 9 | 2. Endian conversion functions that are used by implementations of 10 | primitives. 11 | 12 | Note that on the Haskell side endian conversion happens by calling the 13 | swap if required and we do not need the endian functions 14 | here. Therefore, they are declared as static inline whenever possible. 15 | 16 | 17 | We first define functions for byte swapping falling back to portable C 18 | implementation (indicated by defining __RAAZ_REQUIRE_PORTABLE_SWAP__) 19 | available in raaz/core/endian.c. The C-ffi stub functions make use of 20 | these functions. The endian conversions functions also use them if we 21 | can detect the byte order. Otherwise they too have a portable c 22 | implementation (indicated by defining 23 | __RAAZ_REQUIRE_PORTABLE_ENDIAN__) 24 | 25 | */ 26 | 27 | /* 28 | * Byte swapping. Use platform specific ones when we know it. 29 | */ 30 | 31 | #ifdef PLATFORM_OSX 32 | # include /* For PLATFORM OSX */ 33 | 34 | static inline uint32_t raaz_bswap32(uint32_t x){ return OSSwapInt32(x); } 35 | static inline uint64_t raaz_bswap64(uint64_t x){ return OSSwapInt64(x); } 36 | 37 | #elif defined(PLATFORM_WINDOWS) 38 | # include 39 | static inline uint32_t raaz_bswap32(uint32_t x){ return _byteswap_ulong(x); } 40 | static inline uint64_t raaz_bswap64(uint64_t x){ return _byteswap_uint64(x); } 41 | 42 | #elif defined(PLATFORM_OPENBSD) 43 | # include 44 | static inline uint32_t raaz_bswap32(uint32_t x){ return swap32(x); } 45 | static inline uint64_t raaz_bswap64(uint64_t x){ return swap64(x); } 46 | 47 | #elif defined(PLATFORM_LINUX) /* All other platforms */ 48 | # include 49 | static inline uint32_t raaz_bswap32(uint32_t x){ return bswap_32(x); } 50 | static inline uint64_t raaz_bswap64(uint64_t x){ return bswap_64(x); } 51 | #else 52 | /* We do not have platform specific byte swap */ 53 | # define __RAAZ_REQUIRE_PORTABLE_SWAP__ 54 | 55 | extern uint32_t raaz_bswap32(uint32_t x); 56 | extern uint64_t raaz_bswap64(uint64_t x); 57 | 58 | #endif 59 | 60 | 61 | #ifdef __GNUC__ 62 | 63 | /* For GNUC compiler use byte order checks to define efficient endian 64 | * conversion */ 65 | 66 | # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 67 | 68 | static inline uint32_t raaz_tobe32(uint32_t x){ return raaz_bswap32(x); } 69 | static inline uint64_t raaz_tobe64(uint64_t x){ return raaz_bswap64(x); } 70 | 71 | static inline uint32_t raaz_tole32(uint32_t x){ return x; } 72 | static inline uint64_t raaz_tole64(uint64_t x){ return x; } 73 | 74 | # else 75 | static inline uint32_t raaz_tobe32(uint32_t x){ return x; } 76 | static inline uint64_t raaz_tobe64(uint64_t x){ return x; } 77 | 78 | static inline uint32_t raaz_tole32(uint32_t x){ return raaz_bswap32(x); } 79 | static inline uint64_t raaz_tole64(uint64_t x){ return raaz_bswap64(x); } 80 | 81 | # endif /* Byte order */ 82 | 83 | #else /* Not __GNUC__ use portable implementations */ 84 | # define __RAAZ_REQUIRE_PORTABLE_ENDIAN__ 85 | 86 | extern uint32_t raaz_tobe32(uint32_t x); 87 | extern uint64_t raaz_tobe64(uint64_t x); 88 | extern uint32_t raaz_tole32(uint32_t x); 89 | extern uint64_t raaz_tole64(uint64_t x); 90 | 91 | #endif 92 | 93 | /* These are the C functions that are exported for FFI calls to 94 | * Haskell. Their definitions are available in endian.c 95 | */ 96 | 97 | extern uint32_t raazSwap32 (uint32_t a); 98 | extern uint64_t raazSwap64 (uint64_t a); 99 | extern void raazSwap32Array (uint32_t *ptr, int n); 100 | extern void raazSwap64Array (uint64_t *ptr, int n); 101 | -------------------------------------------------------------------------------- /core/Raaz/Core/Encode.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- 3 | -- Module : Raaz.Core.Encode 4 | -- Description : Encoding and decoding values to formats. 5 | -- Copyright : (c) Piyush P Kurur, 2015 6 | -- License : Apache-2.0 OR BSD-3-Clause 7 | -- Maintainer : Piyush P Kurur 8 | -- Stability : experimental 9 | -- 10 | module Raaz.Core.Encode 11 | ( -- * Encoding of binary data. 12 | -- $encodable$ 13 | Encodable(..) 14 | , Format(..) 15 | , encode, decode, translate, unsafeDecode 16 | -- ** The base 16 encoding format 17 | , Base16 18 | , fromBase16, showBase16 19 | -- ** Other binary formats. 20 | , Base64 21 | ) where 22 | 23 | import Raaz.Core.Prelude 24 | import Raaz.Core.Encode.Internal 25 | import Raaz.Core.Encode.Base16 26 | import Raaz.Core.Encode.Base64 27 | 28 | -- $encodable$ 29 | -- 30 | -- Often one wants to represent cryptographic hashes, secret keys or 31 | -- just binary data into various enocoding formats like base64, 32 | -- hexadecimal etc. This module gives a generic interface for all such 33 | -- operations. There are two main classes that capture the essence of 34 | -- encoding. 35 | -- 36 | -- [`Format`:] The class of all types that are encoding formats to binary 37 | -- data. They are all instances of `Show` and `Data.String.IsString` for 38 | -- ease of printing and inclusion in source code. 39 | -- 40 | -- [`Encodable`:] The class of all types that can be encoded /into/ binary. 41 | -- 42 | -- The combinators `encode` and `decode` allows encoding any instance of `Encodable` to 43 | -- any of the instances of `Format`. 44 | -- 45 | -- == Sample code that makes use of Base16 encoding. 46 | -- 47 | -- > theAnswer :: LE Word64 48 | -- > theAnswer = 42 49 | -- > 50 | -- > main = do putStr "The answer to life, universe and everything is:" 51 | -- > print answserInBase16 52 | -- > where answerInBase16 :: Base16 53 | -- > answerInBase16 = encode theAnswer 54 | -- > 55 | -- > checkAnswer :: Base16 -> Bool 56 | -- > checkAnswer = maybe False (==theAnswer) . decode 57 | -- > 58 | -- > checkAnswerBS :: ByteString -> Bool 59 | -- > checkAnswerBS = checkAnswer . fromString 60 | -- 61 | -- In the above example, @`LE` Word64@, which captures 64-bit unsigned 62 | -- integers is an instance of Encode (but not Word64). The encode 63 | -- combinator then converts in into the type Base16 that is an 64 | -- instance of `Format`. The print then uses the `Show` instance of 65 | -- Base16 to print it as a sequence of hexadecimal 66 | -- characters. Similarly the decode combinator in @checkAnswer@ 67 | -- decodes a base16 before comparing with the answer. 68 | -- 69 | -- == Liberal @IsString@ instances 70 | -- 71 | -- Certain ascii printable formats like Base16 and Base64 have a more 72 | -- liberal `IsString` instance: they typically allow the use of spaces 73 | -- and newline in the input to the `fromString` function . This allows 74 | -- a more readable representation of these types when using the 75 | -- @OverloadedStrings@ extension. See the documentation of the 76 | -- corresponding instance declarations to see what characters are 77 | -- ignored. However, all `Show` instance of formats are strict in the 78 | -- sense that they do not produce any such extraneous characters. 79 | 80 | -- | Encode in a given format. 81 | encode :: (Encodable a, Format fmt) => a -> fmt 82 | encode = encodeByteString . toByteString 83 | 84 | -- | Decode from a given format. It results in Nothing if there is a 85 | -- parse error. 86 | decode :: (Format fmt, Encodable a) => fmt -> Maybe a 87 | decode = fromByteString . decodeFormat 88 | 89 | -- | The unsafe version of `decode`. 90 | unsafeDecode :: (Format fmt, Encodable a) => fmt -> a 91 | unsafeDecode = unsafeFromByteString . decodeFormat 92 | 93 | -- | Translate from one format to another. 94 | translate :: (Format fmt1, Format fmt2) => fmt1 -> fmt2 95 | translate = encodeByteString . decodeFormat 96 | -------------------------------------------------------------------------------- /tests/Raaz/Mac/Poly1305Spec.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fno-warn-orphans #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | {-# LANGUAGE ScopedTypeVariables #-} 4 | {-# LANGUAGE DataKinds #-} 5 | 6 | module Raaz.Mac.Poly1305Spec where 7 | 8 | import qualified Data.Vector.Unboxed as V 9 | import Data.Vector.Unboxed ( (!) ) 10 | import Tests.Core 11 | import Poly1305.Auth 12 | import Raaz.Random 13 | import qualified Data.ByteString as BS 14 | 15 | import Raaz.Primitive.Poly1305.Internal 16 | 17 | randomClamping :: Spec 18 | randomClamping = it "randomly generated R values should be clamped" 19 | $ checkClamped `shouldReturn` True 20 | where randR :: RandomState -> IO R 21 | randR = random 22 | checkClamped = withRandomState (fmap isClamped . randR) 23 | 24 | 25 | -- | Check whether the given value of r is clamped. 26 | isClamped :: R -> Bool 27 | isClamped = isClampedStr . toByteString 28 | where top4Clear w = w < 16 29 | bot2Clear w = w `mod` 4 == 0 30 | isClampedStr bs = check top4Clear [3,7,11,15] && check bot2Clear [4,8,12] 31 | where check pr = all (pr . BS.index bs) 32 | 33 | spec :: Spec 34 | spec = do 35 | describe "Poly1305" $ 36 | basicEndianSpecs (undefined :: Poly1305) 37 | describe "R" $ do 38 | basicEndianSpecs (undefined :: R) 39 | randomClamping 40 | 41 | describe "S" $ 42 | basicEndianSpecs (undefined :: S) 43 | 44 | incrementalVsFull 45 | 46 | with (Key "85:d6:be:78:57:55:6d:33:7f:44:52:fe:42:d5:06:a8" 47 | "01:03:80:8a:fb:0d:b2:fd:4a:bf:f6:af:41:49:f5:1b" 48 | ) 49 | $ ( "Cryptographic Forum Research Group" :: ByteString) 50 | `authsTo` ("a8:06:1d:c1:30:51:36:c6:c2:2b:8b:af:0c:01:27:a9" :: Poly1305) 51 | 52 | describe "vs Integer based implementation" $ do 53 | prop "should be identical" $ 54 | \ k str -> auth k str `shouldBe` poly1305 k str 55 | 56 | ------------------------------------------------------------------------------- 57 | -- Poly1305 using the Integer Type 58 | -- 59 | -- WARNING: only to be used for testing, it is slow and unsafe. 60 | -- 61 | 62 | -- ^ The prime 2^130 - 5 63 | prime :: Integer 64 | prime = bit 130 - 5 65 | 66 | fromWORD :: WORD -> Integer 67 | fromWORD w128 = b0 + shiftL b1 64 68 | where vec = unsafeToVector w128 69 | b0 = fromIntegral (vec ! 0) 70 | b1 = fromIntegral (vec ! 1) 71 | 72 | toWORD :: Integer -> WORD 73 | toWORD i = unsafeFromVector $ V.fromList [b0 , b1] 74 | where b0 = fromIntegral i 75 | b1 = fromIntegral (shiftR i 64) 76 | 77 | fromR :: R -> Integer 78 | fromR (R r) = foldl clearBit v $ 79 | [ 28, 29, 30, 31 ] ++ [32, 33] ++ 80 | [ 60, 61, 62, 63 ] ++ [64, 65] ++ 81 | [ 92, 93, 94, 95 ] ++ [96, 97] ++ 82 | [ 124, 125, 126, 127] 83 | where v = fromWORD r 84 | 85 | 86 | fromS :: S -> Integer 87 | fromS (S s) = fromWORD s 88 | 89 | toPoly1305 :: Integer -> Poly1305 90 | toPoly1305 = Poly1305 . toWORD 91 | 92 | -- | Split the message byte string to integers 93 | chunks :: ByteString -> [Integer] 94 | chunks = map toI . chunkBS 95 | where chunkBS bs 96 | | BS.null bs = [] 97 | | otherwise = let (start, rest) = BS.splitAt 16 bs 98 | in start : chunkBS rest 99 | 100 | addByte :: Word8 -> Integer -> Integer 101 | addByte w8 i = shiftL i 8 + fromIntegral w8 102 | toI = BS.foldr addByte 1 103 | 104 | eval :: R -> [Integer] -> Integer 105 | eval r = foldl fl 0 106 | where rI = fromR r 107 | fl acc msg = ((acc + msg) * rI) `rem` prime 108 | 109 | 110 | poly1305 :: Key Poly1305 -> ByteString -> Poly1305 111 | poly1305 (Key r s) bs = toPoly1305 $ eval r message + sI 112 | where message = chunks bs 113 | sI = fromS s 114 | --------------------------------------------------------------------------------