Compare commits
136 Commits
cryptonite
...
uni2work
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f78fca2504 | ||
|
|
d163f69512 | ||
|
|
9401b4e3fd | ||
|
|
b96ec42d3e | ||
|
|
7dfaf914e6 | ||
|
|
aca61fa1b6 | ||
|
|
20b194fc97 | ||
|
|
cca5d72bf1 | ||
|
|
495eca0bb5 | ||
|
|
309abe378d | ||
|
|
f4f92b702c | ||
|
|
93f50b49b7 | ||
|
|
a8d1d401bc | ||
|
|
b3db979ca0 | ||
|
|
71a630edaf | ||
|
|
365c8978a2 | ||
|
|
8698c9fd94 | ||
|
|
e9c9c770d3 | ||
|
|
9961606e5b | ||
|
|
4b4a641970 | ||
|
|
a6fbe0ed4c | ||
|
|
b6981a4ea5 | ||
|
|
cf89276b5c | ||
|
|
f449a54eb2 | ||
|
|
95b247e5eb | ||
|
|
955f94b784 | ||
|
|
d0ead79fed | ||
|
|
b29dc159fb | ||
|
|
10dc63c51f | ||
|
|
18ae7a7b40 | ||
|
|
fa19117dfe | ||
|
|
d49408156e | ||
|
|
81cc351800 | ||
|
|
9eadf707c4 | ||
|
|
72544ea9aa | ||
|
|
63d427ee77 | ||
|
|
c8199872e7 | ||
|
|
e67d8fb223 | ||
|
|
caec601cd1 | ||
|
|
ba3ab1f0cd | ||
|
|
0254f16e83 | ||
|
|
cf9631dd7f | ||
|
|
c123752de4 | ||
|
|
edbd9e09fb | ||
|
|
dfc9fb9fb2 | ||
|
|
5f657fda2e | ||
|
|
f64efafbad | ||
|
|
17336857c5 | ||
|
|
775855994c | ||
|
|
5d63ef7c4f | ||
|
|
f84f7e3009 | ||
|
|
0cf0d076ab | ||
|
|
f5706959a4 | ||
|
|
dae01d056d | ||
|
|
a1072948ca | ||
|
|
d8a39637f5 | ||
|
|
64f097788e | ||
|
|
b9e1e75a10 | ||
|
|
e56308f9d0 | ||
|
|
981b97a132 | ||
|
|
2e0a60f7f7 | ||
|
|
b01f610aa2 | ||
|
|
ef880291e3 | ||
|
|
977c72cac9 | ||
|
|
1cb2cd2f12 | ||
|
|
436b9abc13 | ||
|
|
6f932998ad | ||
|
|
bd84c75f3e | ||
|
|
6f70986cb1 | ||
|
|
633879f801 | ||
|
|
6075b698e1 | ||
|
|
4b9584dbe4 | ||
|
|
4b8a8229cf | ||
|
|
43a9967b1d | ||
|
|
86470d5563 | ||
|
|
d2df760e34 | ||
|
|
be517c9273 | ||
|
|
2579d1e7aa | ||
|
|
44a1651d26 | ||
|
|
b08ce5e3ae | ||
|
|
f9a6a35ce3 | ||
|
|
f291bd08ef | ||
|
|
b5d9b6cba5 | ||
|
|
7f1c2980e2 | ||
|
|
7ac3060873 | ||
|
|
1f6ed5711c | ||
|
|
17879cbecd | ||
|
|
9e0dbb3231 | ||
|
|
0a1aa3517c | ||
|
|
18c6e37ef1 | ||
|
|
95ebd3996f | ||
|
|
78684bc62b | ||
|
|
99820c742d | ||
|
|
b9a8a6b83d | ||
|
|
15327ecd4f | ||
|
|
8f75165f8b | ||
|
|
977e75f478 | ||
|
|
19b7ab375a | ||
|
|
ce35a1e07d | ||
|
|
6f2a59e470 | ||
|
|
db8d47a76c | ||
|
|
bdf1a7a133 | ||
|
|
e0b201b5e7 | ||
|
|
2e92639679 | ||
|
|
68c93ccbb1 | ||
|
|
e8b8a199e8 | ||
|
|
2433893730 | ||
|
|
096e2ec0bd | ||
|
|
65643a3bea | ||
|
|
3ae08ed509 | ||
|
|
29f0fd1b7a | ||
|
|
73719cbe88 | ||
|
|
908f979d44 | ||
|
|
0075b57f90 | ||
|
|
262252a5c4 | ||
|
|
f2fa7836cb | ||
|
|
4ca77b8cf5 | ||
|
|
fc07a8b931 | ||
|
|
0d32f9b833 | ||
|
|
7e6aeaa8da | ||
|
|
00221a494c | ||
|
|
a0ad444ec1 | ||
|
|
3e4ce8d2ed | ||
|
|
a64a058153 | ||
|
|
d3a60abf28 | ||
|
|
7ca1f2e4d6 | ||
|
|
71184beb15 | ||
|
|
cdd0821eee | ||
|
|
53a1bf7ebf | ||
|
|
91c87deae1 | ||
|
|
f121d1b8d1 | ||
|
|
2cf3b75636 | ||
|
|
4df2a95276 | ||
|
|
5b39ae3e48 | ||
|
|
c8a4e48e0c | ||
|
|
f55636bd43 |
29
.appveyor.yml
Normal file
29
.appveyor.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# ~*~ auto-generated by haskell-ci with config : 4fdddfa41dd039e198b8d125a70471f7dd140fa01001d99126af56fb31429ece ~*~
|
||||||
|
|
||||||
|
version: "{build}"
|
||||||
|
clone_folder: C:\project
|
||||||
|
build: off
|
||||||
|
cache:
|
||||||
|
- "C:\\SR -> .appveyor.yml"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
global:
|
||||||
|
STACK_ROOT: "C:\\SR"
|
||||||
|
matrix:
|
||||||
|
- { BUILD: "ghc-8.6", STACKCMD: "stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps", STACKCFG: "{ resolver: lts-14.27, packages: [ '.' ], extra-deps: [], flags: {} }", STACKURL: "https://www.stackage.org/stack/windows-x86_64" }
|
||||||
|
- { BUILD: "ghc-8.8", STACKCMD: "stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps", STACKCFG: "{ resolver: lts-15.1, packages: [ '.' ], extra-deps: [], flags: {} }", STACKURL: "https://www.stackage.org/stack/windows-x86_64" }
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
|
install:
|
||||||
|
- set PATH=C:\Program Files\Git\mingw64\bin;%PATH%
|
||||||
|
- curl -ostack.zip -L %STACKURL%
|
||||||
|
- 7z x stack.zip stack.exe
|
||||||
|
- refreshenv
|
||||||
|
test_script:
|
||||||
|
- echo %STACKCFG% > stack.yaml
|
||||||
|
- stack setup > nul
|
||||||
|
- echo "" | %STACKCMD%
|
||||||
|
|
||||||
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -12,3 +12,4 @@ benchs/Hash
|
|||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
.cabal-sandbox/
|
.cabal-sandbox/
|
||||||
cabal.sandbox.config
|
cabal.sandbox.config
|
||||||
|
stack.yaml.lock
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
compiler: ghc-8.0 lts-9.21
|
compiler: ghc-8.0 lts-9.21
|
||||||
compiler: ghc-8.2 lts-11.22
|
compiler: ghc-8.2 lts-11.22
|
||||||
compiler: ghc-8.4 lts-12.26
|
compiler: ghc-8.4 lts-12.26
|
||||||
compiler: ghc-8.6 lts-13.21
|
compiler: ghc-8.6 lts-14.27
|
||||||
|
compiler: ghc-8.8 lts-15.1
|
||||||
|
|
||||||
# options
|
# options
|
||||||
# option: alias x=y z=v
|
# option: alias x=y z=v
|
||||||
@ -10,11 +11,11 @@ option: gaugedeps extradep=gauge-0.2.1
|
|||||||
option: basementmin extradep=basement-0.0.8 extradep=memory-0.14.18
|
option: basementmin extradep=basement-0.0.8 extradep=memory-0.14.18
|
||||||
|
|
||||||
# builds
|
# builds
|
||||||
build: ghc-8.2 basementmin
|
|
||||||
build: ghc-8.0 basementmin gaugedeps
|
build: ghc-8.0 basementmin gaugedeps
|
||||||
build: ghc-8.0 basementmin gaugedeps os=osx
|
build: ghc-8.2 basementmin
|
||||||
build: ghc-8.4
|
build: ghc-8.4
|
||||||
build: ghc-8.6
|
build: ghc-8.6 os=linux,osx,windows
|
||||||
|
build: ghc-8.8 os=linux,windows
|
||||||
|
|
||||||
# packages
|
# packages
|
||||||
package: '.'
|
package: '.'
|
||||||
|
|||||||
3
.hlint.yaml
Normal file
3
.hlint.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- arguments: [ --cpp-define=ARCH_X86_64
|
||||||
|
]
|
||||||
|
- ignore: { name: Use camelCase }
|
||||||
53
.travis.yml
53
.travis.yml
@ -1,7 +1,4 @@
|
|||||||
# ~*~ auto-generated by haskell-ci with config : cb76551db808ad3472d36865246ef3849351a6c78535dd987bd37bc95bfd47c0 ~*~
|
# ~*~ auto-generated by haskell-ci with config : 4fdddfa41dd039e198b8d125a70471f7dd140fa01001d99126af56fb31429ece ~*~
|
||||||
|
|
||||||
# Use new container infrastructure to enable caching
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
# Caching so the next build will be fast too.
|
# Caching so the next build will be fast too.
|
||||||
cache:
|
cache:
|
||||||
@ -10,28 +7,32 @@ cache:
|
|||||||
- $HOME/.stack
|
- $HOME/.stack
|
||||||
- $HOME/.local
|
- $HOME/.local
|
||||||
|
|
||||||
matrix:
|
language: generic
|
||||||
|
os: linux
|
||||||
|
|
||||||
|
jobs:
|
||||||
include:
|
include:
|
||||||
- { env: BUILD=stack RESOLVER=ghc-8.2, compiler: ghc-8.2, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=stack RESOLVER=ghc-8.0, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
- { env: BUILD=stack RESOLVER=ghc-8.0, compiler: ghc-8.0, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=stack RESOLVER=ghc-8.2, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
- { env: BUILD=stack RESOLVER=ghc-8.0, compiler: ghc-8.0, language: generic, addons: { apt: { packages: [ libgmp-dev ] } }, os: osx }
|
- { env: BUILD=stack RESOLVER=ghc-8.4, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
- { env: BUILD=stack RESOLVER=ghc-8.4, compiler: ghc-8.4, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=stack RESOLVER=ghc-8.6, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
- { env: BUILD=stack RESOLVER=ghc-8.6, compiler: ghc-8.6, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=stack RESOLVER=ghc-8.6, addons: { apt: { packages: [ libgmp-dev ] } }, os: osx }
|
||||||
- { env: BUILD=hlint, compiler: hlint, language: generic }
|
- { env: BUILD=stack RESOLVER=ghc-8.8, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
- { env: BUILD=weeder, compiler: weeder, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=hlint }
|
||||||
|
- { env: BUILD=weeder, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- { env: BUILD=hlint, compiler: hlint, language: generic }
|
- { env: BUILD=hlint }
|
||||||
- { env: BUILD=weeder, compiler: weeder, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=weeder, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- export PATH=$HOME/.local/bin::$HOME/.cabal/bin:$PATH
|
- export PATH=$HOME/.local/bin:$HOME/.cabal/bin:$PATH
|
||||||
- mkdir -p ~/.local/bin
|
- mkdir -p ~/.local/bin
|
||||||
- |
|
- |
|
||||||
case "$BUILD" in
|
case "$BUILD" in
|
||||||
stack|weeder)
|
stack|weeder)
|
||||||
if [ `uname` = "Darwin" ]
|
if [ `uname` = "Darwin" ]
|
||||||
then
|
then
|
||||||
travis_retry curl --insecure -L https://www.stackage.org/stack/osx-x86_64 | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin
|
travis_retry curl -L https://www.stackage.org/stack/osx-x86_64 | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin
|
||||||
else
|
else
|
||||||
travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
|
travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
|
||||||
fi
|
fi
|
||||||
@ -48,24 +49,24 @@ script:
|
|||||||
stack)
|
stack)
|
||||||
# create the build stack.yaml
|
# create the build stack.yaml
|
||||||
case "$RESOLVER" in
|
case "$RESOLVER" in
|
||||||
|
ghc-8.0)
|
||||||
|
echo "{ resolver: lts-9.21, packages: [ '.' ], extra-deps: [ basement-0.0.8, memory-0.14.18, gauge-0.2.1 ], flags: {} }" > stack.yaml
|
||||||
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
|
;;
|
||||||
ghc-8.2)
|
ghc-8.2)
|
||||||
echo "{ resolver: lts-11.22, packages: [ '.' ], extra-deps: [ basement-0.0.8, memory-0.14.18 ], flags: {} }" > stack.yaml
|
echo "{ resolver: lts-11.22, packages: [ '.' ], extra-deps: [ basement-0.0.8, memory-0.14.18 ], flags: {} }" > stack.yaml
|
||||||
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
;;
|
;;
|
||||||
ghc-8.0)
|
|
||||||
echo "{ resolver: lts-9.21, packages: [ '.' ], extra-deps: [ basement-0.0.8, memory-0.14.18, gauge-0.2.1 ], flags: {} }" > stack.yaml
|
|
||||||
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
|
||||||
;;
|
|
||||||
ghc-8.0)
|
|
||||||
echo "{ resolver: lts-9.21, packages: [ '.' ], extra-deps: [ basement-0.0.8, memory-0.14.18, gauge-0.2.1 ], flags: {} }" > stack.yaml
|
|
||||||
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
|
||||||
;;
|
|
||||||
ghc-8.4)
|
ghc-8.4)
|
||||||
echo "{ resolver: lts-12.26, packages: [ '.' ], extra-deps: [], flags: {} }" > stack.yaml
|
echo "{ resolver: lts-12.26, packages: [ '.' ], extra-deps: [], flags: {} }" > stack.yaml
|
||||||
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
;;
|
;;
|
||||||
ghc-8.6)
|
ghc-8.6)
|
||||||
echo "{ resolver: lts-13.21, packages: [ '.' ], extra-deps: [], flags: {} }" > stack.yaml
|
echo "{ resolver: lts-14.27, packages: [ '.' ], extra-deps: [], flags: {} }" > stack.yaml
|
||||||
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
|
;;
|
||||||
|
ghc-8.8)
|
||||||
|
echo "{ resolver: lts-15.1, packages: [ '.' ], extra-deps: [], flags: {} }" > stack.yaml
|
||||||
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -74,7 +75,7 @@ script:
|
|||||||
curl -sL https://raw.github.com/ndmitchell/hlint/master/misc/travis.sh | sh -s . --cpp-define=__GLASGOW_HASKELL__=800 --cpp-define=x86_64_HOST_ARCH=1 --cpp-define=mingw32_HOST_OS=1
|
curl -sL https://raw.github.com/ndmitchell/hlint/master/misc/travis.sh | sh -s . --cpp-define=__GLASGOW_HASKELL__=800 --cpp-define=x86_64_HOST_ARCH=1 --cpp-define=mingw32_HOST_OS=1
|
||||||
;;
|
;;
|
||||||
weeder)
|
weeder)
|
||||||
stack --no-terminal build --install-ghc
|
stack --no-terminal build --install-ghc --ghc-options="-ddump-to-file -ddump-hi" --test --no-run-tests --bench --no-run-benchmarks
|
||||||
curl -sL https://raw.github.com/ndmitchell/weeder/master/misc/travis.sh | sh -s .
|
curl -sL https://raw.github.com/ndmitchell/weeder/master/misc/travis.sh | sh -s .
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
27
CHANGELOG.md
27
CHANGELOG.md
@ -1,3 +1,30 @@
|
|||||||
|
## 0.30
|
||||||
|
|
||||||
|
* Fix some C symbol blake2b prefix to be cryptonite_ prefix (fix mixing with other C library)
|
||||||
|
* add hmac-lazy
|
||||||
|
* Fix compilation with GHC 9.2
|
||||||
|
* Drop support for GHC8.0, GHC8.2, GHC8.4, GHC8.6
|
||||||
|
|
||||||
|
## 0.29
|
||||||
|
|
||||||
|
* advance compilation with gmp breakage due to change upstream
|
||||||
|
* Add native EdDSA support
|
||||||
|
|
||||||
|
## 0.28
|
||||||
|
|
||||||
|
* Add hash constant time capability
|
||||||
|
* Prevent possible overflow during hashing by hashing in 4GB chunks
|
||||||
|
|
||||||
|
## 0.27
|
||||||
|
|
||||||
|
* Optimise AES GCM and CCM
|
||||||
|
* Optimise P256R1 implementation
|
||||||
|
* Various AES-NI building improvements
|
||||||
|
* Add better ECDSA support
|
||||||
|
* Add XSalsa derive
|
||||||
|
* Implement square roots for ECC binary curve
|
||||||
|
* Various tests and benchmarks
|
||||||
|
|
||||||
## 0.26
|
## 0.26
|
||||||
|
|
||||||
* Add Rabin cryptosystem (and variants)
|
* Add Rabin cryptosystem (and variants)
|
||||||
|
|||||||
@ -37,6 +37,9 @@ module Crypto.Cipher.AES.Primitive
|
|||||||
, decryptCTR
|
, decryptCTR
|
||||||
, decryptXTS
|
, decryptXTS
|
||||||
|
|
||||||
|
-- * CTR with 32-bit wrapping
|
||||||
|
, combineC32
|
||||||
|
|
||||||
-- * Incremental GCM
|
-- * Incremental GCM
|
||||||
, gcmMode
|
, gcmMode
|
||||||
, gcmInit
|
, gcmInit
|
||||||
@ -128,7 +131,7 @@ newtype AESCCM = AESCCM ScrubbedBytes
|
|||||||
deriving (NFData)
|
deriving (NFData)
|
||||||
|
|
||||||
sizeGCM :: Int
|
sizeGCM :: Int
|
||||||
sizeGCM = 80
|
sizeGCM = 320
|
||||||
|
|
||||||
sizeOCB :: Int
|
sizeOCB :: Int
|
||||||
sizeOCB = 160
|
sizeOCB = 160
|
||||||
@ -317,6 +320,21 @@ decryptXTS :: ByteArray ba
|
|||||||
-> ba -- ^ output decrypted
|
-> ba -- ^ output decrypted
|
||||||
decryptXTS = doXTS c_aes_decrypt_xts
|
decryptXTS = doXTS c_aes_decrypt_xts
|
||||||
|
|
||||||
|
-- | encrypt/decrypt using Counter mode (32-bit wrapping used in AES-GCM-SIV)
|
||||||
|
{-# NOINLINE combineC32 #-}
|
||||||
|
combineC32 :: ByteArray ba
|
||||||
|
=> AES -- ^ AES Context
|
||||||
|
-> IV AES -- ^ initial vector of AES block size (usually representing a 128 bit integer)
|
||||||
|
-> ba -- ^ plaintext input
|
||||||
|
-> ba -- ^ ciphertext output
|
||||||
|
combineC32 ctx iv input
|
||||||
|
| len <= 0 = B.empty
|
||||||
|
| B.length iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ show (B.length iv)
|
||||||
|
| otherwise = B.allocAndFreeze len doEncrypt
|
||||||
|
where doEncrypt o = withKeyAndIV ctx iv $ \k v -> withByteArray input $ \i ->
|
||||||
|
c_aes_encrypt_c32 (castPtr o) k v i (fromIntegral len)
|
||||||
|
len = B.length input
|
||||||
|
|
||||||
{-# INLINE doECB #-}
|
{-# INLINE doECB #-}
|
||||||
doECB :: ByteArray ba
|
doECB :: ByteArray ba
|
||||||
=> (Ptr b -> Ptr AES -> CString -> CUInt -> IO ())
|
=> (Ptr b -> Ptr AES -> CString -> CUInt -> IO ())
|
||||||
@ -578,6 +596,9 @@ foreign import ccall unsafe "cryptonite_aes.h cryptonite_aes_gen_ctr_cont"
|
|||||||
foreign import ccall "cryptonite_aes.h cryptonite_aes_encrypt_ctr"
|
foreign import ccall "cryptonite_aes.h cryptonite_aes_encrypt_ctr"
|
||||||
c_aes_encrypt_ctr :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
|
c_aes_encrypt_ctr :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_aes.h cryptonite_aes_encrypt_c32"
|
||||||
|
c_aes_encrypt_c32 :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_aes.h cryptonite_aes_gcm_init"
|
foreign import ccall "cryptonite_aes.h cryptonite_aes_gcm_init"
|
||||||
c_aes_gcm_init :: Ptr AESGCM -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
|
c_aes_gcm_init :: Ptr AESGCM -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
|
||||||
|
|
||||||
|
|||||||
193
Crypto/Cipher/AESGCMSIV.hs
Normal file
193
Crypto/Cipher/AESGCMSIV.hs
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
-- |
|
||||||
|
-- Module : Crypto.Cipher.AESGCMSIV
|
||||||
|
-- License : BSD-style
|
||||||
|
-- Maintainer : Olivier Chéron <olivier.cheron@gmail.com>
|
||||||
|
-- Stability : experimental
|
||||||
|
-- Portability : unknown
|
||||||
|
--
|
||||||
|
-- Implementation of AES-GCM-SIV, an AEAD scheme with nonce misuse resistance
|
||||||
|
-- defined in <https://tools.ietf.org/html/rfc8452 RFC 8452>.
|
||||||
|
--
|
||||||
|
-- To achieve the nonce misuse-resistance property, encryption requires two
|
||||||
|
-- passes on the plaintext, hence no streaming API is provided. This AEAD
|
||||||
|
-- operates on complete inputs held in memory. For simplicity, the
|
||||||
|
-- implementation of decryption uses a similar pattern, with performance
|
||||||
|
-- penalty compared to an implementation which is able to merge both passes.
|
||||||
|
--
|
||||||
|
-- The specification allows inputs up to 2^36 bytes but this implementation
|
||||||
|
-- requires AAD and plaintext/ciphertext to be both smaller than 2^32 bytes.
|
||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
module Crypto.Cipher.AESGCMSIV
|
||||||
|
( Nonce
|
||||||
|
, nonce
|
||||||
|
, generateNonce
|
||||||
|
, encrypt
|
||||||
|
, decrypt
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Bits
|
||||||
|
import Data.Word
|
||||||
|
|
||||||
|
import Foreign.C.Types
|
||||||
|
import Foreign.C.String
|
||||||
|
import Foreign.Ptr (Ptr, plusPtr)
|
||||||
|
import Foreign.Storable (peekElemOff, poke, pokeElemOff)
|
||||||
|
|
||||||
|
import Data.ByteArray
|
||||||
|
import qualified Data.ByteArray as B
|
||||||
|
import Data.Memory.Endian (toLE)
|
||||||
|
import Data.Memory.PtrMethods (memXor)
|
||||||
|
|
||||||
|
import Crypto.Cipher.AES.Primitive
|
||||||
|
import Crypto.Cipher.Types
|
||||||
|
import Crypto.Error
|
||||||
|
import Crypto.Internal.Compat (unsafeDoIO)
|
||||||
|
import Crypto.Random
|
||||||
|
|
||||||
|
|
||||||
|
-- 12-byte nonces
|
||||||
|
|
||||||
|
-- | Nonce value for AES-GCM-SIV, always 12 bytes.
|
||||||
|
newtype Nonce = Nonce Bytes deriving (Show, Eq, ByteArrayAccess)
|
||||||
|
|
||||||
|
-- | Nonce smart constructor. Accepts only 12-byte inputs.
|
||||||
|
nonce :: ByteArrayAccess iv => iv -> CryptoFailable Nonce
|
||||||
|
nonce iv
|
||||||
|
| B.length iv == 12 = CryptoPassed (Nonce $ B.convert iv)
|
||||||
|
| otherwise = CryptoFailed CryptoError_IvSizeInvalid
|
||||||
|
|
||||||
|
-- | Generate a random nonce for use with AES-GCM-SIV.
|
||||||
|
generateNonce :: MonadRandom m => m Nonce
|
||||||
|
generateNonce = Nonce <$> getRandomBytes 12
|
||||||
|
|
||||||
|
|
||||||
|
-- POLYVAL (mutable context)
|
||||||
|
|
||||||
|
newtype Polyval = Polyval Bytes
|
||||||
|
|
||||||
|
polyvalInit :: ScrubbedBytes -> IO Polyval
|
||||||
|
polyvalInit h = Polyval <$> doInit
|
||||||
|
where doInit = B.alloc 272 $ \pctx -> B.withByteArray h $ \ph ->
|
||||||
|
c_aes_polyval_init pctx ph
|
||||||
|
|
||||||
|
polyvalUpdate :: ByteArrayAccess ba => Polyval -> ba -> IO ()
|
||||||
|
polyvalUpdate (Polyval ctx) bs = B.withByteArray ctx $ \pctx ->
|
||||||
|
B.withByteArray bs $ \pbs -> c_aes_polyval_update pctx pbs sz
|
||||||
|
where sz = fromIntegral (B.length bs)
|
||||||
|
|
||||||
|
polyvalFinalize :: Polyval -> IO ScrubbedBytes
|
||||||
|
polyvalFinalize (Polyval ctx) = B.alloc 16 $ \dst ->
|
||||||
|
B.withByteArray ctx $ \pctx -> c_aes_polyval_finalize pctx dst
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_aes.h cryptonite_aes_polyval_init"
|
||||||
|
c_aes_polyval_init :: Ptr Polyval -> CString -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_aes.h cryptonite_aes_polyval_update"
|
||||||
|
c_aes_polyval_update :: Ptr Polyval -> CString -> CUInt -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_aes.h cryptonite_aes_polyval_finalize"
|
||||||
|
c_aes_polyval_finalize :: Ptr Polyval -> CString -> IO ()
|
||||||
|
|
||||||
|
|
||||||
|
-- Key Generation
|
||||||
|
|
||||||
|
le32iv :: Word32 -> Nonce -> Bytes
|
||||||
|
le32iv n (Nonce iv) = B.allocAndFreeze 16 $ \ptr -> do
|
||||||
|
poke ptr (toLE n)
|
||||||
|
copyByteArrayToPtr iv (ptr `plusPtr` 4)
|
||||||
|
|
||||||
|
deriveKeys :: BlockCipher128 aes => aes -> Nonce -> (ScrubbedBytes, AES)
|
||||||
|
deriveKeys aes iv =
|
||||||
|
case cipherKeySize aes of
|
||||||
|
KeySizeFixed sz | sz `mod` 8 == 0 ->
|
||||||
|
let mak = buildKey [0 .. 1]
|
||||||
|
key = buildKey [2 .. fromIntegral (sz `div` 8) + 1]
|
||||||
|
mek = throwCryptoError (cipherInit key)
|
||||||
|
in (mak, mek)
|
||||||
|
_ -> error "AESGCMSIV: invalid cipher"
|
||||||
|
where
|
||||||
|
idx n = ecbEncrypt aes (le32iv n iv) `takeView` 8
|
||||||
|
buildKey = B.concat . map idx
|
||||||
|
|
||||||
|
|
||||||
|
-- Encryption and decryption
|
||||||
|
|
||||||
|
lengthInvalid :: ByteArrayAccess ba => ba -> Bool
|
||||||
|
lengthInvalid bs
|
||||||
|
| finiteBitSize len > 32 = len >= 1 `unsafeShiftL` 32
|
||||||
|
| otherwise = False
|
||||||
|
where len = B.length bs
|
||||||
|
|
||||||
|
-- | AEAD encryption with the specified key and nonce. The key must be given
|
||||||
|
-- as an initialized 'Crypto.Cipher.AES.AES128' or 'Crypto.Cipher.AES.AES256'
|
||||||
|
-- cipher.
|
||||||
|
--
|
||||||
|
-- Lengths of additional data and plaintext must be less than 2^32 bytes,
|
||||||
|
-- otherwise an exception is thrown.
|
||||||
|
encrypt :: (BlockCipher128 aes, ByteArrayAccess aad, ByteArray ba)
|
||||||
|
=> aes -> Nonce -> aad -> ba -> (AuthTag, ba)
|
||||||
|
encrypt aes iv aad plaintext
|
||||||
|
| lengthInvalid aad = error "AESGCMSIV: aad is too large"
|
||||||
|
| lengthInvalid plaintext = error "AESGCMSIV: plaintext is too large"
|
||||||
|
| otherwise = (AuthTag tag, ciphertext)
|
||||||
|
where
|
||||||
|
(mak, mek) = deriveKeys aes iv
|
||||||
|
ss = getSs mak aad plaintext
|
||||||
|
tag = buildTag mek ss iv
|
||||||
|
ciphertext = combineC32 mek (transformTag tag) plaintext
|
||||||
|
|
||||||
|
-- | AEAD decryption with the specified key and nonce. The key must be given
|
||||||
|
-- as an initialized 'Crypto.Cipher.AES.AES128' or 'Crypto.Cipher.AES.AES256'
|
||||||
|
-- cipher.
|
||||||
|
--
|
||||||
|
-- Lengths of additional data and ciphertext must be less than 2^32 bytes,
|
||||||
|
-- otherwise an exception is thrown.
|
||||||
|
decrypt :: (BlockCipher128 aes, ByteArrayAccess aad, ByteArray ba)
|
||||||
|
=> aes -> Nonce -> aad -> ba -> AuthTag -> Maybe ba
|
||||||
|
decrypt aes iv aad ciphertext (AuthTag tag)
|
||||||
|
| lengthInvalid aad = error "AESGCMSIV: aad is too large"
|
||||||
|
| lengthInvalid ciphertext = error "AESGCMSIV: ciphertext is too large"
|
||||||
|
| tag `constEq` buildTag mek ss iv = Just plaintext
|
||||||
|
| otherwise = Nothing
|
||||||
|
where
|
||||||
|
(mak, mek) = deriveKeys aes iv
|
||||||
|
ss = getSs mak aad plaintext
|
||||||
|
plaintext = combineC32 mek (transformTag tag) ciphertext
|
||||||
|
|
||||||
|
-- Calculate S_s = POLYVAL(mak, X_1, X_2, ...).
|
||||||
|
getSs :: (ByteArrayAccess aad, ByteArrayAccess ba)
|
||||||
|
=> ScrubbedBytes -> aad -> ba -> ScrubbedBytes
|
||||||
|
getSs mak aad plaintext = unsafeDoIO $ do
|
||||||
|
ctx <- polyvalInit mak
|
||||||
|
polyvalUpdate ctx aad
|
||||||
|
polyvalUpdate ctx plaintext
|
||||||
|
polyvalUpdate ctx (lb :: Bytes) -- the "length block"
|
||||||
|
polyvalFinalize ctx
|
||||||
|
where
|
||||||
|
lb = B.allocAndFreeze 16 $ \ptr -> do
|
||||||
|
pokeElemOff ptr 0 (toLE64 $ B.length aad)
|
||||||
|
pokeElemOff ptr 1 (toLE64 $ B.length plaintext)
|
||||||
|
toLE64 x = toLE (fromIntegral x * 8 :: Word64)
|
||||||
|
|
||||||
|
-- XOR the first 12 bytes of S_s with the nonce and clear the most significant
|
||||||
|
-- bit of the last byte.
|
||||||
|
tagInput :: ScrubbedBytes -> Nonce -> Bytes
|
||||||
|
tagInput ss (Nonce iv) =
|
||||||
|
B.copyAndFreeze ss $ \ptr ->
|
||||||
|
B.withByteArray iv $ \ivPtr -> do
|
||||||
|
memXor ptr ptr ivPtr 12
|
||||||
|
b <- peekElemOff ptr 15
|
||||||
|
pokeElemOff ptr 15 (b .&. (0x7f :: Word8))
|
||||||
|
|
||||||
|
-- Encrypt the result with AES using the message-encryption key to produce the
|
||||||
|
-- tag.
|
||||||
|
buildTag :: BlockCipher128 aes => aes -> ScrubbedBytes -> Nonce -> Bytes
|
||||||
|
buildTag mek ss iv = ecbEncrypt mek (tagInput ss iv)
|
||||||
|
|
||||||
|
-- The initial counter block is the tag with the most significant bit of the
|
||||||
|
-- last byte set to one.
|
||||||
|
transformTag :: Bytes -> IV AES
|
||||||
|
transformTag tag = toIV $ B.copyAndFreeze tag $ \ptr ->
|
||||||
|
peekElemOff ptr 15 >>= pokeElemOff ptr 15 . (.|. (0x80 :: Word8))
|
||||||
|
where toIV bs = let Just iv = makeIV (bs :: Bytes) in iv
|
||||||
@ -41,9 +41,9 @@ initialize :: (ByteArrayAccess key, ByteArrayAccess nonce)
|
|||||||
-> nonce -- ^ the nonce (64 or 96 bits)
|
-> nonce -- ^ the nonce (64 or 96 bits)
|
||||||
-> State -- ^ the initial ChaCha state
|
-> State -- ^ the initial ChaCha state
|
||||||
initialize nbRounds key nonce
|
initialize nbRounds key nonce
|
||||||
| not (kLen `elem` [16,32]) = error "ChaCha: key length should be 128 or 256 bits"
|
| kLen `notElem` [16,32] = error "ChaCha: key length should be 128 or 256 bits"
|
||||||
| not (nonceLen `elem` [8,12]) = error "ChaCha: nonce length should be 64 or 96 bits"
|
| nonceLen `notElem` [8,12] = error "ChaCha: nonce length should be 64 or 96 bits"
|
||||||
| not (nbRounds `elem` [8,12,20]) = error "ChaCha: rounds should be 8, 12 or 20"
|
| nbRounds `notElem` [8,12,20] = error "ChaCha: rounds should be 8, 12 or 20"
|
||||||
| otherwise = unsafeDoIO $ do
|
| otherwise = unsafeDoIO $ do
|
||||||
stPtr <- B.alloc 132 $ \stPtr ->
|
stPtr <- B.alloc 132 $ \stPtr ->
|
||||||
B.withByteArray nonce $ \noncePtr ->
|
B.withByteArray nonce $ \noncePtr ->
|
||||||
|
|||||||
@ -30,6 +30,11 @@ import Crypto.Internal.Compat
|
|||||||
import Crypto.Internal.Imports
|
import Crypto.Internal.Imports
|
||||||
|
|
||||||
-- | The encryption state for RC4
|
-- | The encryption state for RC4
|
||||||
|
--
|
||||||
|
-- This type is an instance of 'ByteArrayAccess' for debugging purpose. Internal
|
||||||
|
-- layout is architecture dependent, may contain uninitialized data fragments,
|
||||||
|
-- and change in future versions. The bytearray should not be used as input to
|
||||||
|
-- cryptographic algorithms.
|
||||||
newtype State = State ScrubbedBytes
|
newtype State = State ScrubbedBytes
|
||||||
deriving (ByteArrayAccess,NFData)
|
deriving (ByteArrayAccess,NFData)
|
||||||
|
|
||||||
|
|||||||
@ -33,9 +33,9 @@ initialize :: (ByteArrayAccess key, ByteArrayAccess nonce)
|
|||||||
-> nonce -- ^ the nonce (64 or 96 bits)
|
-> nonce -- ^ the nonce (64 or 96 bits)
|
||||||
-> State -- ^ the initial Salsa state
|
-> State -- ^ the initial Salsa state
|
||||||
initialize nbRounds key nonce
|
initialize nbRounds key nonce
|
||||||
| not (kLen `elem` [16,32]) = error "Salsa: key length should be 128 or 256 bits"
|
| kLen `notElem` [16,32] = error "Salsa: key length should be 128 or 256 bits"
|
||||||
| not (nonceLen `elem` [8,12]) = error "Salsa: nonce length should be 64 or 96 bits"
|
| nonceLen `notElem` [8,12] = error "Salsa: nonce length should be 64 or 96 bits"
|
||||||
| not (nbRounds `elem` [8,12,20]) = error "Salsa: rounds should be 8, 12 or 20"
|
| nbRounds `notElem` [8,12,20] = error "Salsa: rounds should be 8, 12 or 20"
|
||||||
| otherwise = unsafeDoIO $ do
|
| otherwise = unsafeDoIO $ do
|
||||||
stPtr <- B.alloc 132 $ \stPtr ->
|
stPtr <- B.alloc 132 $ \stPtr ->
|
||||||
B.withByteArray nonce $ \noncePtr ->
|
B.withByteArray nonce $ \noncePtr ->
|
||||||
|
|||||||
@ -27,24 +27,24 @@ data AEADModeImpl st = AEADModeImpl
|
|||||||
-- | Authenticated Encryption with Associated Data algorithms
|
-- | Authenticated Encryption with Associated Data algorithms
|
||||||
data AEAD cipher = forall st . AEAD
|
data AEAD cipher = forall st . AEAD
|
||||||
{ aeadModeImpl :: AEADModeImpl st
|
{ aeadModeImpl :: AEADModeImpl st
|
||||||
, aeadState :: st
|
, aeadState :: !st
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Append some header information to an AEAD context
|
-- | Append some header information to an AEAD context
|
||||||
aeadAppendHeader :: ByteArrayAccess aad => AEAD cipher -> aad -> AEAD cipher
|
aeadAppendHeader :: ByteArrayAccess aad => AEAD cipher -> aad -> AEAD cipher
|
||||||
aeadAppendHeader (AEAD impl st) aad = AEAD impl $ (aeadImplAppendHeader impl) st aad
|
aeadAppendHeader (AEAD impl st) aad = AEAD impl $ aeadImplAppendHeader impl st aad
|
||||||
|
|
||||||
-- | Encrypt some data and update the AEAD context
|
-- | Encrypt some data and update the AEAD context
|
||||||
aeadEncrypt :: ByteArray ba => AEAD cipher -> ba -> (ba, AEAD cipher)
|
aeadEncrypt :: ByteArray ba => AEAD cipher -> ba -> (ba, AEAD cipher)
|
||||||
aeadEncrypt (AEAD impl st) ba = second (AEAD impl) $ (aeadImplEncrypt impl) st ba
|
aeadEncrypt (AEAD impl st) ba = second (AEAD impl) $ aeadImplEncrypt impl st ba
|
||||||
|
|
||||||
-- | Decrypt some data and update the AEAD context
|
-- | Decrypt some data and update the AEAD context
|
||||||
aeadDecrypt :: ByteArray ba => AEAD cipher -> ba -> (ba, AEAD cipher)
|
aeadDecrypt :: ByteArray ba => AEAD cipher -> ba -> (ba, AEAD cipher)
|
||||||
aeadDecrypt (AEAD impl st) ba = second (AEAD impl) $ (aeadImplDecrypt impl) st ba
|
aeadDecrypt (AEAD impl st) ba = second (AEAD impl) $ aeadImplDecrypt impl st ba
|
||||||
|
|
||||||
-- | Finalize the AEAD context and return the authentication tag
|
-- | Finalize the AEAD context and return the authentication tag
|
||||||
aeadFinalize :: AEAD cipher -> Int -> AuthTag
|
aeadFinalize :: AEAD cipher -> Int -> AuthTag
|
||||||
aeadFinalize (AEAD impl st) n = (aeadImplFinalize impl) st n
|
aeadFinalize (AEAD impl st) = aeadImplFinalize impl st
|
||||||
|
|
||||||
-- | Simple AEAD encryption
|
-- | Simple AEAD encryption
|
||||||
aeadSimpleEncrypt :: (ByteArrayAccess aad, ByteArray ba)
|
aeadSimpleEncrypt :: (ByteArrayAccess aad, ByteArray ba)
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
{-# LANGUAGE ForeignFunctionInterface #-}
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
module Crypto.Cipher.XSalsa
|
module Crypto.Cipher.XSalsa
|
||||||
( initialize
|
( initialize
|
||||||
|
, derive
|
||||||
, combine
|
, combine
|
||||||
, generate
|
, generate
|
||||||
, State
|
, State
|
||||||
@ -34,7 +35,7 @@ initialize :: (ByteArrayAccess key, ByteArrayAccess nonce)
|
|||||||
initialize nbRounds key nonce
|
initialize nbRounds key nonce
|
||||||
| kLen /= 32 = error "XSalsa: key length should be 256 bits"
|
| kLen /= 32 = error "XSalsa: key length should be 256 bits"
|
||||||
| nonceLen /= 24 = error "XSalsa: nonce length should be 192 bits"
|
| nonceLen /= 24 = error "XSalsa: nonce length should be 192 bits"
|
||||||
| not (nbRounds `elem` [8,12,20]) = error "XSalsa: rounds should be 8, 12 or 20"
|
| nbRounds `notElem` [8,12,20] = error "XSalsa: rounds should be 8, 12 or 20"
|
||||||
| otherwise = unsafeDoIO $ do
|
| otherwise = unsafeDoIO $ do
|
||||||
stPtr <- B.alloc 132 $ \stPtr ->
|
stPtr <- B.alloc 132 $ \stPtr ->
|
||||||
B.withByteArray nonce $ \noncePtr ->
|
B.withByteArray nonce $ \noncePtr ->
|
||||||
@ -44,5 +45,31 @@ initialize nbRounds key nonce
|
|||||||
where kLen = B.length key
|
where kLen = B.length key
|
||||||
nonceLen = B.length nonce
|
nonceLen = B.length nonce
|
||||||
|
|
||||||
|
-- | Use an already initialized context and new nonce material to derive another
|
||||||
|
-- XSalsa context.
|
||||||
|
--
|
||||||
|
-- This allows a multi-level cascade where a first key @k1@ and nonce @n1@ is
|
||||||
|
-- used to get @HState(k1,n1)@, and this value is then used as key @k2@ to build
|
||||||
|
-- @XSalsa(k2,n2)@. Function 'initialize' is to be called with the first 192
|
||||||
|
-- bits of @n1|n2@, and the call to @derive@ should add the remaining 128 bits.
|
||||||
|
--
|
||||||
|
-- The output context always uses the same number of rounds as the input
|
||||||
|
-- context.
|
||||||
|
derive :: ByteArrayAccess nonce
|
||||||
|
=> State -- ^ base XSalsa state
|
||||||
|
-> nonce -- ^ the remainder nonce (128 bits)
|
||||||
|
-> State -- ^ the new XSalsa state
|
||||||
|
derive (State stPtr') nonce
|
||||||
|
| nonceLen /= 16 = error "XSalsa: nonce length should be 128 bits"
|
||||||
|
| otherwise = unsafeDoIO $ do
|
||||||
|
stPtr <- B.copy stPtr' $ \stPtr ->
|
||||||
|
B.withByteArray nonce $ \noncePtr ->
|
||||||
|
ccryptonite_xsalsa_derive stPtr nonceLen noncePtr
|
||||||
|
return $ State stPtr
|
||||||
|
where nonceLen = B.length nonce
|
||||||
|
|
||||||
foreign import ccall "cryptonite_xsalsa_init"
|
foreign import ccall "cryptonite_xsalsa_init"
|
||||||
ccryptonite_xsalsa_init :: Ptr State -> Int -> Int -> Ptr Word8 -> Int -> Ptr Word8 -> IO ()
|
ccryptonite_xsalsa_init :: Ptr State -> Int -> Int -> Ptr Word8 -> Int -> Ptr Word8 -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_xsalsa_derive"
|
||||||
|
ccryptonite_xsalsa_derive :: Ptr State -> Int -> Ptr Word8 -> IO ()
|
||||||
|
|||||||
@ -44,7 +44,7 @@ compute' g = MP . foldl' (step $ g) (B.replicate bsz 0) . chunks . pad (ZERO bsz
|
|||||||
where
|
where
|
||||||
(hd, tl) = B.splitAt bsz msg
|
(hd, tl) = B.splitAt bsz msg
|
||||||
|
|
||||||
-- | Compute Miyaguchi-Preneel one way compress using the infered block cipher.
|
-- | Compute Miyaguchi-Preneel one way compress using the inferred block cipher.
|
||||||
-- Only safe when KEY-SIZE equals to BLOCK-SIZE.
|
-- Only safe when KEY-SIZE equals to BLOCK-SIZE.
|
||||||
--
|
--
|
||||||
-- Simple usage /mp' msg :: MiyaguchiPreneel AES128/
|
-- Simple usage /mp' msg :: MiyaguchiPreneel AES128/
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
-- Portability : unknown
|
-- Portability : unknown
|
||||||
--
|
--
|
||||||
-- Various cryptographic padding commonly used for block ciphers
|
-- Various cryptographic padding commonly used for block ciphers
|
||||||
-- or assymetric systems.
|
-- or asymmetric systems.
|
||||||
--
|
--
|
||||||
module Crypto.Data.Padding
|
module Crypto.Data.Padding
|
||||||
( Format(..)
|
( Format(..)
|
||||||
|
|||||||
135
Crypto/ECC.hs
135
Crypto/ECC.hs
@ -8,6 +8,7 @@
|
|||||||
-- Elliptic Curve Cryptography
|
-- Elliptic Curve Cryptography
|
||||||
--
|
--
|
||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
@ -21,6 +22,7 @@ module Crypto.ECC
|
|||||||
, EllipticCurve(..)
|
, EllipticCurve(..)
|
||||||
, EllipticCurveDH(..)
|
, EllipticCurveDH(..)
|
||||||
, EllipticCurveArith(..)
|
, EllipticCurveArith(..)
|
||||||
|
, EllipticCurveBasepointArith(..)
|
||||||
, KeyPair(..)
|
, KeyPair(..)
|
||||||
, SharedSecret(..)
|
, SharedSecret(..)
|
||||||
) where
|
) where
|
||||||
@ -34,7 +36,9 @@ import Crypto.Error
|
|||||||
import Crypto.Internal.Imports
|
import Crypto.Internal.Imports
|
||||||
import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes)
|
import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes)
|
||||||
import qualified Crypto.Internal.ByteArray as B
|
import qualified Crypto.Internal.ByteArray as B
|
||||||
|
import Crypto.Number.Basic (numBits)
|
||||||
import Crypto.Number.Serialize (i2ospOf_, os2ip)
|
import Crypto.Number.Serialize (i2ospOf_, os2ip)
|
||||||
|
import qualified Crypto.Number.Serialize.LE as LE
|
||||||
import qualified Crypto.PubKey.Curve25519 as X25519
|
import qualified Crypto.PubKey.Curve25519 as X25519
|
||||||
import qualified Crypto.PubKey.Curve448 as X448
|
import qualified Crypto.PubKey.Curve448 as X448
|
||||||
import Data.ByteArray (convert)
|
import Data.ByteArray (convert)
|
||||||
@ -98,7 +102,7 @@ class EllipticCurve curve => EllipticCurveDH curve where
|
|||||||
-- value or an exception.
|
-- value or an exception.
|
||||||
ecdh :: proxy curve -> Scalar curve -> Point curve -> CryptoFailable SharedSecret
|
ecdh :: proxy curve -> Scalar curve -> Point curve -> CryptoFailable SharedSecret
|
||||||
|
|
||||||
class EllipticCurve curve => EllipticCurveArith curve where
|
class (EllipticCurve curve, Eq (Point curve)) => EllipticCurveArith curve where
|
||||||
-- | Add points on a curve
|
-- | Add points on a curve
|
||||||
pointAdd :: proxy curve -> Point curve -> Point curve -> Point curve
|
pointAdd :: proxy curve -> Point curve -> Point curve -> Point curve
|
||||||
|
|
||||||
@ -111,6 +115,35 @@ class EllipticCurve curve => EllipticCurveArith curve where
|
|||||||
-- -- | Scalar Inverse
|
-- -- | Scalar Inverse
|
||||||
-- scalarInverse :: Scalar curve -> Scalar curve
|
-- scalarInverse :: Scalar curve -> Scalar curve
|
||||||
|
|
||||||
|
class (EllipticCurveArith curve, Eq (Scalar curve)) => EllipticCurveBasepointArith curve where
|
||||||
|
-- | Get the curve order size in bits
|
||||||
|
curveOrderBits :: proxy curve -> Int
|
||||||
|
|
||||||
|
-- | Multiply a scalar with the curve base point
|
||||||
|
pointBaseSmul :: proxy curve -> Scalar curve -> Point curve
|
||||||
|
|
||||||
|
-- | Multiply the point @p@ with @s2@ and add a lifted to curve value @s1@
|
||||||
|
pointsSmulVarTime :: proxy curve -> Scalar curve -> Scalar curve -> Point curve -> Point curve
|
||||||
|
pointsSmulVarTime prx s1 s2 p = pointAdd prx (pointBaseSmul prx s1) (pointSmul prx s2 p)
|
||||||
|
|
||||||
|
-- | Encode an elliptic curve scalar into big-endian form
|
||||||
|
encodeScalar :: ByteArray bs => proxy curve -> Scalar curve -> bs
|
||||||
|
|
||||||
|
-- | Try to decode the big-endian form of an elliptic curve scalar
|
||||||
|
decodeScalar :: ByteArray bs => proxy curve -> bs -> CryptoFailable (Scalar curve)
|
||||||
|
|
||||||
|
-- | Convert an elliptic curve scalar to an integer
|
||||||
|
scalarToInteger :: proxy curve -> Scalar curve -> Integer
|
||||||
|
|
||||||
|
-- | Try to create an elliptic curve scalar from an integer
|
||||||
|
scalarFromInteger :: proxy curve -> Integer -> CryptoFailable (Scalar curve)
|
||||||
|
|
||||||
|
-- | Add two scalars and reduce modulo the curve order
|
||||||
|
scalarAdd :: proxy curve -> Scalar curve -> Scalar curve -> Scalar curve
|
||||||
|
|
||||||
|
-- | Multiply two scalars and reduce modulo the curve order
|
||||||
|
scalarMul :: proxy curve -> Scalar curve -> Scalar curve -> Scalar curve
|
||||||
|
|
||||||
-- | P256 Curve
|
-- | P256 Curve
|
||||||
--
|
--
|
||||||
-- also known as P256
|
-- also known as P256
|
||||||
@ -133,11 +166,11 @@ instance EllipticCurve Curve_P256R1 where
|
|||||||
uncompressed = B.singleton 4
|
uncompressed = B.singleton 4
|
||||||
xy = P256.pointToBinary p
|
xy = P256.pointToBinary p
|
||||||
decodePoint _ mxy = case B.uncons mxy of
|
decodePoint _ mxy = case B.uncons mxy of
|
||||||
Nothing -> CryptoFailed $ CryptoError_PointSizeInvalid
|
Nothing -> CryptoFailed CryptoError_PointSizeInvalid
|
||||||
Just (m,xy)
|
Just (m,xy)
|
||||||
-- uncompressed
|
-- uncompressed
|
||||||
| m == 4 -> P256.pointFromBinary xy
|
| m == 4 -> P256.pointFromBinary xy
|
||||||
| otherwise -> CryptoFailed $ CryptoError_PointFormatInvalid
|
| otherwise -> CryptoFailed CryptoError_PointFormatInvalid
|
||||||
|
|
||||||
instance EllipticCurveArith Curve_P256R1 where
|
instance EllipticCurveArith Curve_P256R1 where
|
||||||
pointAdd _ a b = P256.pointAdd a b
|
pointAdd _ a b = P256.pointAdd a b
|
||||||
@ -148,6 +181,17 @@ instance EllipticCurveDH Curve_P256R1 where
|
|||||||
ecdhRaw _ s p = SharedSecret $ P256.pointDh s p
|
ecdhRaw _ s p = SharedSecret $ P256.pointDh s p
|
||||||
ecdh prx s p = checkNonZeroDH (ecdhRaw prx s p)
|
ecdh prx s p = checkNonZeroDH (ecdhRaw prx s p)
|
||||||
|
|
||||||
|
instance EllipticCurveBasepointArith Curve_P256R1 where
|
||||||
|
curveOrderBits _ = 256
|
||||||
|
pointBaseSmul _ = P256.toPoint
|
||||||
|
pointsSmulVarTime _ = P256.pointsMulVarTime
|
||||||
|
encodeScalar _ = P256.scalarToBinary
|
||||||
|
decodeScalar _ = P256.scalarFromBinary
|
||||||
|
scalarToInteger _ = P256.scalarToInteger
|
||||||
|
scalarFromInteger _ = P256.scalarFromInteger
|
||||||
|
scalarAdd _ = P256.scalarAdd
|
||||||
|
scalarMul _ = P256.scalarMul
|
||||||
|
|
||||||
data Curve_P384R1 = Curve_P384R1
|
data Curve_P384R1 = Curve_P384R1
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
|
|
||||||
@ -171,6 +215,17 @@ instance EllipticCurveDH Curve_P384R1 where
|
|||||||
where
|
where
|
||||||
prx = Proxy :: Proxy Simple.SEC_p384r1
|
prx = Proxy :: Proxy Simple.SEC_p384r1
|
||||||
|
|
||||||
|
instance EllipticCurveBasepointArith Curve_P384R1 where
|
||||||
|
curveOrderBits _ = 384
|
||||||
|
pointBaseSmul _ = Simple.pointBaseMul
|
||||||
|
pointsSmulVarTime _ = ecPointsMulVarTime
|
||||||
|
encodeScalar _ = ecScalarToBinary
|
||||||
|
decodeScalar _ = ecScalarFromBinary
|
||||||
|
scalarToInteger _ = ecScalarToInteger
|
||||||
|
scalarFromInteger _ = ecScalarFromInteger
|
||||||
|
scalarAdd _ = ecScalarAdd
|
||||||
|
scalarMul _ = ecScalarMul
|
||||||
|
|
||||||
data Curve_P521R1 = Curve_P521R1
|
data Curve_P521R1 = Curve_P521R1
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
|
|
||||||
@ -194,6 +249,17 @@ instance EllipticCurveDH Curve_P521R1 where
|
|||||||
where
|
where
|
||||||
prx = Proxy :: Proxy Simple.SEC_p521r1
|
prx = Proxy :: Proxy Simple.SEC_p521r1
|
||||||
|
|
||||||
|
instance EllipticCurveBasepointArith Curve_P521R1 where
|
||||||
|
curveOrderBits _ = 521
|
||||||
|
pointBaseSmul _ = Simple.pointBaseMul
|
||||||
|
pointsSmulVarTime _ = ecPointsMulVarTime
|
||||||
|
encodeScalar _ = ecScalarToBinary
|
||||||
|
decodeScalar _ = ecScalarFromBinary
|
||||||
|
scalarToInteger _ = ecScalarToInteger
|
||||||
|
scalarFromInteger _ = ecScalarFromInteger
|
||||||
|
scalarAdd _ = ecScalarAdd
|
||||||
|
scalarMul _ = ecScalarMul
|
||||||
|
|
||||||
data Curve_X25519 = Curve_X25519
|
data Curve_X25519 = Curve_X25519
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
|
|
||||||
@ -250,6 +316,22 @@ instance EllipticCurveArith Curve_Edwards25519 where
|
|||||||
pointNegate _ p = Edwards25519.pointNegate p
|
pointNegate _ p = Edwards25519.pointNegate p
|
||||||
pointSmul _ s p = Edwards25519.pointMul s p
|
pointSmul _ s p = Edwards25519.pointMul s p
|
||||||
|
|
||||||
|
instance EllipticCurveBasepointArith Curve_Edwards25519 where
|
||||||
|
curveOrderBits _ = 253
|
||||||
|
pointBaseSmul _ = Edwards25519.toPoint
|
||||||
|
pointsSmulVarTime _ = Edwards25519.pointsMulVarTime
|
||||||
|
encodeScalar _ = B.reverse . Edwards25519.scalarEncode
|
||||||
|
decodeScalar _ bs
|
||||||
|
| B.length bs == 32 = Edwards25519.scalarDecodeLong (B.reverse bs)
|
||||||
|
| otherwise = CryptoFailed CryptoError_SecretKeySizeInvalid
|
||||||
|
scalarToInteger _ s = LE.os2ip (Edwards25519.scalarEncode s :: B.Bytes)
|
||||||
|
scalarFromInteger _ i =
|
||||||
|
case LE.i2ospOf 32 i of
|
||||||
|
Nothing -> CryptoFailed CryptoError_SecretKeySizeInvalid
|
||||||
|
Just bs -> Edwards25519.scalarDecodeLong (bs :: B.Bytes)
|
||||||
|
scalarAdd _ = Edwards25519.scalarAdd
|
||||||
|
scalarMul _ = Edwards25519.scalarMul
|
||||||
|
|
||||||
checkNonZeroDH :: SharedSecret -> CryptoFailable SharedSecret
|
checkNonZeroDH :: SharedSecret -> CryptoFailable SharedSecret
|
||||||
checkNonZeroDH s@(SharedSecret b)
|
checkNonZeroDH s@(SharedSecret b)
|
||||||
| B.constAllZero b = CryptoFailed CryptoError_ScalarMultiplicationInvalid
|
| B.constAllZero b = CryptoFailed CryptoError_ScalarMultiplicationInvalid
|
||||||
@ -271,7 +353,7 @@ encodeECPoint (Simple.Point x y) = B.concat [uncompressed,xb,yb]
|
|||||||
|
|
||||||
decodeECPoint :: (Simple.Curve curve, ByteArray bs) => bs -> CryptoFailable (Simple.Point curve)
|
decodeECPoint :: (Simple.Curve curve, ByteArray bs) => bs -> CryptoFailable (Simple.Point curve)
|
||||||
decodeECPoint mxy = case B.uncons mxy of
|
decodeECPoint mxy = case B.uncons mxy of
|
||||||
Nothing -> CryptoFailed $ CryptoError_PointSizeInvalid
|
Nothing -> CryptoFailed CryptoError_PointSizeInvalid
|
||||||
Just (m,xy)
|
Just (m,xy)
|
||||||
-- uncompressed
|
-- uncompressed
|
||||||
| m == 4 ->
|
| m == 4 ->
|
||||||
@ -280,4 +362,47 @@ decodeECPoint mxy = case B.uncons mxy of
|
|||||||
x = os2ip xb
|
x = os2ip xb
|
||||||
y = os2ip yb
|
y = os2ip yb
|
||||||
in Simple.pointFromIntegers (x,y)
|
in Simple.pointFromIntegers (x,y)
|
||||||
| otherwise -> CryptoFailed $ CryptoError_PointFormatInvalid
|
| otherwise -> CryptoFailed CryptoError_PointFormatInvalid
|
||||||
|
|
||||||
|
ecPointsMulVarTime :: forall curve . Simple.Curve curve
|
||||||
|
=> Simple.Scalar curve
|
||||||
|
-> Simple.Scalar curve -> Simple.Point curve
|
||||||
|
-> Simple.Point curve
|
||||||
|
ecPointsMulVarTime n1 = Simple.pointAddTwoMuls n1 g
|
||||||
|
where g = Simple.curveEccG $ Simple.curveParameters (Proxy :: Proxy curve)
|
||||||
|
|
||||||
|
ecScalarFromBinary :: forall curve bs . (Simple.Curve curve, ByteArrayAccess bs)
|
||||||
|
=> bs -> CryptoFailable (Simple.Scalar curve)
|
||||||
|
ecScalarFromBinary ba
|
||||||
|
| B.length ba /= size = CryptoFailed CryptoError_SecretKeySizeInvalid
|
||||||
|
| otherwise = CryptoPassed (Simple.Scalar $ os2ip ba)
|
||||||
|
where size = ecCurveOrderBytes (Proxy :: Proxy curve)
|
||||||
|
|
||||||
|
ecScalarToBinary :: forall curve bs . (Simple.Curve curve, ByteArray bs)
|
||||||
|
=> Simple.Scalar curve -> bs
|
||||||
|
ecScalarToBinary (Simple.Scalar s) = i2ospOf_ size s
|
||||||
|
where size = ecCurveOrderBytes (Proxy :: Proxy curve)
|
||||||
|
|
||||||
|
ecScalarFromInteger :: forall curve . Simple.Curve curve
|
||||||
|
=> Integer -> CryptoFailable (Simple.Scalar curve)
|
||||||
|
ecScalarFromInteger s
|
||||||
|
| numBits s > nb = CryptoFailed CryptoError_SecretKeySizeInvalid
|
||||||
|
| otherwise = CryptoPassed (Simple.Scalar s)
|
||||||
|
where nb = 8 * ecCurveOrderBytes (Proxy :: Proxy curve)
|
||||||
|
|
||||||
|
ecScalarToInteger :: Simple.Scalar curve -> Integer
|
||||||
|
ecScalarToInteger (Simple.Scalar s) = s
|
||||||
|
|
||||||
|
ecCurveOrderBytes :: Simple.Curve c => proxy c -> Int
|
||||||
|
ecCurveOrderBytes prx = (numBits n + 7) `div` 8
|
||||||
|
where n = Simple.curveEccN $ Simple.curveParameters prx
|
||||||
|
|
||||||
|
ecScalarAdd :: forall curve . Simple.Curve curve
|
||||||
|
=> Simple.Scalar curve -> Simple.Scalar curve -> Simple.Scalar curve
|
||||||
|
ecScalarAdd (Simple.Scalar a) (Simple.Scalar b) = Simple.Scalar ((a + b) `mod` n)
|
||||||
|
where n = Simple.curveEccN $ Simple.curveParameters (Proxy :: Proxy curve)
|
||||||
|
|
||||||
|
ecScalarMul :: forall curve . Simple.Curve curve
|
||||||
|
=> Simple.Scalar curve -> Simple.Scalar curve -> Simple.Scalar curve
|
||||||
|
ecScalarMul (Simple.Scalar a) (Simple.Scalar b) = Simple.Scalar ((a * b) `mod` n)
|
||||||
|
where n = Simple.curveEccN $ Simple.curveParameters (Proxy :: Proxy curve)
|
||||||
|
|||||||
@ -283,45 +283,45 @@ pointsMulVarTime (Scalar s1) (Scalar s2) (Point p) =
|
|||||||
withByteArray p $ \pp ->
|
withByteArray p $ \pp ->
|
||||||
ed25519_base_double_scalarmul_vartime out ps1 pp ps2
|
ed25519_base_double_scalarmul_vartime out ps1 pp ps2
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_scalar_eq"
|
foreign import ccall unsafe "cryptonite_ed25519_scalar_eq"
|
||||||
ed25519_scalar_eq :: Ptr Scalar
|
ed25519_scalar_eq :: Ptr Scalar
|
||||||
-> Ptr Scalar
|
-> Ptr Scalar
|
||||||
-> IO CInt
|
-> IO CInt
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_scalar_encode"
|
foreign import ccall unsafe "cryptonite_ed25519_scalar_encode"
|
||||||
ed25519_scalar_encode :: Ptr Word8
|
ed25519_scalar_encode :: Ptr Word8
|
||||||
-> Ptr Scalar
|
-> Ptr Scalar
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_scalar_decode_long"
|
foreign import ccall unsafe "cryptonite_ed25519_scalar_decode_long"
|
||||||
ed25519_scalar_decode_long :: Ptr Scalar
|
ed25519_scalar_decode_long :: Ptr Scalar
|
||||||
-> Ptr Word8
|
-> Ptr Word8
|
||||||
-> CSize
|
-> CSize
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_scalar_add"
|
foreign import ccall unsafe "cryptonite_ed25519_scalar_add"
|
||||||
ed25519_scalar_add :: Ptr Scalar -- sum
|
ed25519_scalar_add :: Ptr Scalar -- sum
|
||||||
-> Ptr Scalar -- a
|
-> Ptr Scalar -- a
|
||||||
-> Ptr Scalar -- b
|
-> Ptr Scalar -- b
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_scalar_mul"
|
foreign import ccall unsafe "cryptonite_ed25519_scalar_mul"
|
||||||
ed25519_scalar_mul :: Ptr Scalar -- out
|
ed25519_scalar_mul :: Ptr Scalar -- out
|
||||||
-> Ptr Scalar -- a
|
-> Ptr Scalar -- a
|
||||||
-> Ptr Scalar -- b
|
-> Ptr Scalar -- b
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_encode"
|
foreign import ccall unsafe "cryptonite_ed25519_point_encode"
|
||||||
ed25519_point_encode :: Ptr Word8
|
ed25519_point_encode :: Ptr Word8
|
||||||
-> Ptr Point
|
-> Ptr Point
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_decode_vartime"
|
foreign import ccall unsafe "cryptonite_ed25519_point_decode_vartime"
|
||||||
ed25519_point_decode_vartime :: Ptr Point
|
ed25519_point_decode_vartime :: Ptr Point
|
||||||
-> Ptr Word8
|
-> Ptr Word8
|
||||||
-> IO CInt
|
-> IO CInt
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_eq"
|
foreign import ccall unsafe "cryptonite_ed25519_point_eq"
|
||||||
ed25519_point_eq :: Ptr Point
|
ed25519_point_eq :: Ptr Point
|
||||||
-> Ptr Point
|
-> Ptr Point
|
||||||
-> IO CInt
|
-> IO CInt
|
||||||
@ -330,23 +330,23 @@ foreign import ccall "cryptonite_ed25519_point_has_prime_order"
|
|||||||
ed25519_point_has_prime_order :: Ptr Point
|
ed25519_point_has_prime_order :: Ptr Point
|
||||||
-> IO CInt
|
-> IO CInt
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_negate"
|
foreign import ccall unsafe "cryptonite_ed25519_point_negate"
|
||||||
ed25519_point_negate :: Ptr Point -- minus_a
|
ed25519_point_negate :: Ptr Point -- minus_a
|
||||||
-> Ptr Point -- a
|
-> Ptr Point -- a
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_add"
|
foreign import ccall unsafe "cryptonite_ed25519_point_add"
|
||||||
ed25519_point_add :: Ptr Point -- sum
|
ed25519_point_add :: Ptr Point -- sum
|
||||||
-> Ptr Point -- a
|
-> Ptr Point -- a
|
||||||
-> Ptr Point -- b
|
-> Ptr Point -- b
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_double"
|
foreign import ccall unsafe "cryptonite_ed25519_point_double"
|
||||||
ed25519_point_double :: Ptr Point -- two_a
|
ed25519_point_double :: Ptr Point -- two_a
|
||||||
-> Ptr Point -- a
|
-> Ptr Point -- a
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
foreign import ccall "cryptonite_ed25519_point_mul_by_cofactor"
|
foreign import ccall unsafe "cryptonite_ed25519_point_mul_by_cofactor"
|
||||||
ed25519_point_mul_by_cofactor :: Ptr Point -- eight_a
|
ed25519_point_mul_by_cofactor :: Ptr Point -- eight_a
|
||||||
-> Ptr Point -- a
|
-> Ptr Point -- a
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|||||||
@ -28,15 +28,20 @@ module Crypto.Hash
|
|||||||
-- * Hash methods parametrized by algorithm
|
-- * Hash methods parametrized by algorithm
|
||||||
, hashInitWith
|
, hashInitWith
|
||||||
, hashWith
|
, hashWith
|
||||||
|
, hashPrefixWith
|
||||||
-- * Hash methods
|
-- * Hash methods
|
||||||
, hashInit
|
, hashInit
|
||||||
, hashUpdates
|
, hashUpdates
|
||||||
, hashUpdate
|
, hashUpdate
|
||||||
, hashFinalize
|
, hashFinalize
|
||||||
|
, hashFinalizePrefix
|
||||||
, hashBlockSize
|
, hashBlockSize
|
||||||
, hashDigestSize
|
, hashDigestSize
|
||||||
, hash
|
, hash
|
||||||
|
, hashPrefix
|
||||||
, hashlazy
|
, hashlazy
|
||||||
|
, hashPutContext
|
||||||
|
, hashGetContext
|
||||||
-- * Hash algorithms
|
-- * Hash algorithms
|
||||||
, module Crypto.Hash.Algorithms
|
, module Crypto.Hash.Algorithms
|
||||||
) where
|
) where
|
||||||
@ -47,16 +52,21 @@ import Basement.Block.Mutable (copyFromPtr, new)
|
|||||||
import Crypto.Internal.Compat (unsafeDoIO)
|
import Crypto.Internal.Compat (unsafeDoIO)
|
||||||
import Crypto.Hash.Types
|
import Crypto.Hash.Types
|
||||||
import Crypto.Hash.Algorithms
|
import Crypto.Hash.Algorithms
|
||||||
import Foreign.Ptr (Ptr)
|
import Foreign.Ptr (Ptr, plusPtr)
|
||||||
import Crypto.Internal.ByteArray (ByteArrayAccess)
|
import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray)
|
||||||
import qualified Crypto.Internal.ByteArray as B
|
import qualified Crypto.Internal.ByteArray as B
|
||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
import Data.Word (Word8)
|
import Data.Word (Word8)
|
||||||
|
import Data.Int (Int32)
|
||||||
|
|
||||||
-- | Hash a strict bytestring into a digest.
|
-- | Hash a strict bytestring into a digest.
|
||||||
hash :: (ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a
|
hash :: (ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a
|
||||||
hash bs = hashFinalize $ hashUpdate hashInit bs
|
hash bs = hashFinalize $ hashUpdate hashInit bs
|
||||||
|
|
||||||
|
-- | Hash the first N bytes of a bytestring, with code path independent from N.
|
||||||
|
hashPrefix :: (ByteArrayAccess ba, HashAlgorithmPrefix a) => ba -> Int -> Digest a
|
||||||
|
hashPrefix = hashFinalizePrefix hashInit
|
||||||
|
|
||||||
-- | Hash a lazy bytestring into a digest.
|
-- | Hash a lazy bytestring into a digest.
|
||||||
hashlazy :: HashAlgorithm a => L.ByteString -> Digest a
|
hashlazy :: HashAlgorithm a => L.ByteString -> Digest a
|
||||||
hashlazy lbs = hashFinalize $ hashUpdates hashInit (L.toChunks lbs)
|
hashlazy lbs = hashFinalize $ hashUpdates hashInit (L.toChunks lbs)
|
||||||
@ -81,9 +91,17 @@ hashUpdates :: forall a ba . (HashAlgorithm a, ByteArrayAccess ba)
|
|||||||
hashUpdates c l
|
hashUpdates c l
|
||||||
| null ls = c
|
| null ls = c
|
||||||
| otherwise = Context $ B.copyAndFreeze c $ \(ctx :: Ptr (Context a)) ->
|
| otherwise = Context $ B.copyAndFreeze c $ \(ctx :: Ptr (Context a)) ->
|
||||||
mapM_ (\b -> B.withByteArray b $ \d -> hashInternalUpdate ctx d (fromIntegral $ B.length b)) ls
|
mapM_ (\b -> B.withByteArray b (processBlocks ctx (B.length b))) ls
|
||||||
where
|
where
|
||||||
ls = filter (not . B.null) l
|
ls = filter (not . B.null) l
|
||||||
|
-- process the data in 2GB chunks to fit in uint32_t and Int on 32 bit systems
|
||||||
|
processBlocks ctx bytesLeft dataPtr
|
||||||
|
| bytesLeft == 0 = return ()
|
||||||
|
| otherwise = do
|
||||||
|
hashInternalUpdate ctx dataPtr (fromIntegral actuallyProcessed)
|
||||||
|
processBlocks ctx (bytesLeft - actuallyProcessed) (dataPtr `plusPtr` actuallyProcessed)
|
||||||
|
where
|
||||||
|
actuallyProcessed = min bytesLeft (fromIntegral (maxBound :: Int32))
|
||||||
|
|
||||||
-- | Finalize a context and return a digest.
|
-- | Finalize a context and return a digest.
|
||||||
hashFinalize :: forall a . HashAlgorithm a
|
hashFinalize :: forall a . HashAlgorithm a
|
||||||
@ -94,6 +112,24 @@ hashFinalize !c =
|
|||||||
((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (Context a)) -> hashInternalFinalize ctx dig
|
((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (Context a)) -> hashInternalFinalize ctx dig
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
|
-- | Update the context with the first N bytes of a bytestring and return the
|
||||||
|
-- digest. The code path is independent from N but much slower than a normal
|
||||||
|
-- 'hashUpdate'. The function can be called for the last bytes of a message, in
|
||||||
|
-- order to exclude a variable padding, without leaking the padding length. The
|
||||||
|
-- begining of the message, never impacted by the padding, should preferably go
|
||||||
|
-- through 'hashUpdate' for better performance.
|
||||||
|
hashFinalizePrefix :: forall a ba . (HashAlgorithmPrefix a, ByteArrayAccess ba)
|
||||||
|
=> Context a
|
||||||
|
-> ba
|
||||||
|
-> Int
|
||||||
|
-> Digest a
|
||||||
|
hashFinalizePrefix !c b len =
|
||||||
|
Digest $ B.allocAndFreeze (hashDigestSize (undefined :: a)) $ \(dig :: Ptr (Digest a)) -> do
|
||||||
|
((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (Context a)) ->
|
||||||
|
B.withByteArray b $ \d ->
|
||||||
|
hashInternalFinalizePrefix ctx d (fromIntegral $ B.length b) (fromIntegral len) dig
|
||||||
|
return ()
|
||||||
|
|
||||||
-- | Initialize a new context for a specified hash algorithm
|
-- | Initialize a new context for a specified hash algorithm
|
||||||
hashInitWith :: HashAlgorithm alg => alg -> Context alg
|
hashInitWith :: HashAlgorithm alg => alg -> Context alg
|
||||||
hashInitWith _ = hashInit
|
hashInitWith _ = hashInit
|
||||||
@ -102,6 +138,10 @@ hashInitWith _ = hashInit
|
|||||||
hashWith :: (ByteArrayAccess ba, HashAlgorithm alg) => alg -> ba -> Digest alg
|
hashWith :: (ByteArrayAccess ba, HashAlgorithm alg) => alg -> ba -> Digest alg
|
||||||
hashWith _ = hash
|
hashWith _ = hash
|
||||||
|
|
||||||
|
-- | Run the 'hashPrefix' function but takes an explicit hash algorithm parameter
|
||||||
|
hashPrefixWith :: (ByteArrayAccess ba, HashAlgorithmPrefix alg) => alg -> ba -> Int -> Digest alg
|
||||||
|
hashPrefixWith _ = hashPrefix
|
||||||
|
|
||||||
-- | Try to transform a bytearray into a Digest of specific algorithm.
|
-- | Try to transform a bytearray into a Digest of specific algorithm.
|
||||||
--
|
--
|
||||||
-- If the digest is not the right size for the algorithm specified, then
|
-- If the digest is not the right size for the algorithm specified, then
|
||||||
@ -121,3 +161,16 @@ digestFromByteString = from undefined
|
|||||||
unsafeFreeze muArray
|
unsafeFreeze muArray
|
||||||
where
|
where
|
||||||
count = CountOf (B.length ba)
|
count = CountOf (B.length ba)
|
||||||
|
|
||||||
|
hashPutContext :: forall a ba. (HashAlgorithmResumable a, ByteArray ba) => Context a -> ba
|
||||||
|
hashPutContext !c = B.allocAndFreeze (hashInternalContextSize (undefined :: a)) $ \(ptr :: Ptr Word8) ->
|
||||||
|
B.withByteArray c $ \(ctx :: Ptr (Context a)) -> hashInternalPutContextBE ctx ptr
|
||||||
|
|
||||||
|
hashGetContext :: forall a ba. (HashAlgorithmResumable a, ByteArrayAccess ba) => ba -> Maybe (Context a)
|
||||||
|
hashGetContext = from undefined
|
||||||
|
where
|
||||||
|
from :: a -> ba -> Maybe (Context a)
|
||||||
|
from alg bs
|
||||||
|
| B.length bs == (hashInternalContextSize alg) = Just $ Context $ B.allocAndFreeze (B.length bs) $ \(ctx :: Ptr (Context a)) ->
|
||||||
|
B.withByteArray bs $ \ptr -> hashInternalGetContextBE ptr ctx
|
||||||
|
| otherwise = Nothing
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
--
|
--
|
||||||
module Crypto.Hash.Algorithms
|
module Crypto.Hash.Algorithms
|
||||||
( HashAlgorithm
|
( HashAlgorithm
|
||||||
|
, HashAlgorithmPrefix
|
||||||
|
, HashAlgorithmResumable
|
||||||
-- * Hash algorithms
|
-- * Hash algorithms
|
||||||
, Blake2s_160(..)
|
, Blake2s_160(..)
|
||||||
, Blake2s_224(..)
|
, Blake2s_224(..)
|
||||||
@ -54,7 +56,7 @@ module Crypto.Hash.Algorithms
|
|||||||
, Whirlpool(..)
|
, Whirlpool(..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Crypto.Hash.Types (HashAlgorithm)
|
import Crypto.Hash.Types (HashAlgorithm, HashAlgorithmPrefix, HashAlgorithmResumable)
|
||||||
import Crypto.Hash.Blake2s
|
import Crypto.Hash.Blake2s
|
||||||
import Crypto.Hash.Blake2sp
|
import Crypto.Hash.Blake2sp
|
||||||
import Crypto.Hash.Blake2b
|
import Crypto.Hash.Blake2b
|
||||||
|
|||||||
@ -24,6 +24,11 @@ import qualified Crypto.Internal.ByteArray as B
|
|||||||
import Foreign.Ptr
|
import Foreign.Ptr
|
||||||
|
|
||||||
-- | A Mutable hash context
|
-- | A Mutable hash context
|
||||||
|
--
|
||||||
|
-- This type is an instance of 'B.ByteArrayAccess' for debugging purpose.
|
||||||
|
-- Internal layout is architecture dependent, may contain uninitialized data
|
||||||
|
-- fragments, and change in future versions. The bytearray should not be used
|
||||||
|
-- as input to cryptographic algorithms.
|
||||||
newtype MutableContext a = MutableContext B.Bytes
|
newtype MutableContext a = MutableContext B.Bytes
|
||||||
deriving (B.ByteArrayAccess)
|
deriving (B.ByteArrayAccess)
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,10 @@ instance HashAlgorithm Keccak_224 where
|
|||||||
hashInternalUpdate = c_keccak_update
|
hashInternalUpdate = c_keccak_update
|
||||||
hashInternalFinalize p = c_keccak_finalize p 224
|
hashInternalFinalize p = c_keccak_finalize p 224
|
||||||
|
|
||||||
|
instance HashAlgorithmResumable Keccak_224 where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
-- | Keccak (256 bits) cryptographic hash algorithm
|
-- | Keccak (256 bits) cryptographic hash algorithm
|
||||||
data Keccak_256 = Keccak_256
|
data Keccak_256 = Keccak_256
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
@ -52,6 +56,10 @@ instance HashAlgorithm Keccak_256 where
|
|||||||
hashInternalUpdate = c_keccak_update
|
hashInternalUpdate = c_keccak_update
|
||||||
hashInternalFinalize p = c_keccak_finalize p 256
|
hashInternalFinalize p = c_keccak_finalize p 256
|
||||||
|
|
||||||
|
instance HashAlgorithmResumable Keccak_256 where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
-- | Keccak (384 bits) cryptographic hash algorithm
|
-- | Keccak (384 bits) cryptographic hash algorithm
|
||||||
data Keccak_384 = Keccak_384
|
data Keccak_384 = Keccak_384
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
@ -67,6 +75,10 @@ instance HashAlgorithm Keccak_384 where
|
|||||||
hashInternalUpdate = c_keccak_update
|
hashInternalUpdate = c_keccak_update
|
||||||
hashInternalFinalize p = c_keccak_finalize p 384
|
hashInternalFinalize p = c_keccak_finalize p 384
|
||||||
|
|
||||||
|
instance HashAlgorithmResumable Keccak_384 where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
-- | Keccak (512 bits) cryptographic hash algorithm
|
-- | Keccak (512 bits) cryptographic hash algorithm
|
||||||
data Keccak_512 = Keccak_512
|
data Keccak_512 = Keccak_512
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
@ -82,6 +94,10 @@ instance HashAlgorithm Keccak_512 where
|
|||||||
hashInternalUpdate = c_keccak_update
|
hashInternalUpdate = c_keccak_update
|
||||||
hashInternalFinalize p = c_keccak_finalize p 512
|
hashInternalFinalize p = c_keccak_finalize p 512
|
||||||
|
|
||||||
|
instance HashAlgorithmResumable Keccak_512 where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_keccak_init"
|
foreign import ccall unsafe "cryptonite_keccak_init"
|
||||||
c_keccak_init :: Ptr (Context a) -> Word32 -> IO ()
|
c_keccak_init :: Ptr (Context a) -> Word32 -> IO ()
|
||||||
@ -91,3 +107,9 @@ foreign import ccall "cryptonite_keccak_update"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_keccak_finalize"
|
foreign import ccall unsafe "cryptonite_keccak_finalize"
|
||||||
c_keccak_finalize :: Ptr (Context a) -> Word32 -> Ptr (Digest a) -> IO ()
|
c_keccak_finalize :: Ptr (Context a) -> Word32 -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_sha3_ctx_to_be"
|
||||||
|
c_sha3_ctx_to_be :: Ptr (Context a) -> Ptr Word8 -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_sha3_be_to_ctx"
|
||||||
|
c_sha3_be_to_ctx :: Ptr Word8 -> Ptr (Context a) -> IO ()
|
||||||
|
|||||||
@ -34,6 +34,9 @@ instance HashAlgorithm MD5 where
|
|||||||
hashInternalUpdate = c_md5_update
|
hashInternalUpdate = c_md5_update
|
||||||
hashInternalFinalize = c_md5_finalize
|
hashInternalFinalize = c_md5_finalize
|
||||||
|
|
||||||
|
instance HashAlgorithmPrefix MD5 where
|
||||||
|
hashInternalFinalizePrefix = c_md5_finalize_prefix
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_md5_init"
|
foreign import ccall unsafe "cryptonite_md5_init"
|
||||||
c_md5_init :: Ptr (Context a)-> IO ()
|
c_md5_init :: Ptr (Context a)-> IO ()
|
||||||
|
|
||||||
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_md5_update"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_md5_finalize"
|
foreign import ccall unsafe "cryptonite_md5_finalize"
|
||||||
c_md5_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
c_md5_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_md5_finalize_prefix"
|
||||||
|
c_md5_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO ()
|
||||||
|
|||||||
@ -34,6 +34,9 @@ instance HashAlgorithm SHA1 where
|
|||||||
hashInternalUpdate = c_sha1_update
|
hashInternalUpdate = c_sha1_update
|
||||||
hashInternalFinalize = c_sha1_finalize
|
hashInternalFinalize = c_sha1_finalize
|
||||||
|
|
||||||
|
instance HashAlgorithmPrefix SHA1 where
|
||||||
|
hashInternalFinalizePrefix = c_sha1_finalize_prefix
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha1_init"
|
foreign import ccall unsafe "cryptonite_sha1_init"
|
||||||
c_sha1_init :: Ptr (Context a)-> IO ()
|
c_sha1_init :: Ptr (Context a)-> IO ()
|
||||||
|
|
||||||
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha1_update"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha1_finalize"
|
foreign import ccall unsafe "cryptonite_sha1_finalize"
|
||||||
c_sha1_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
c_sha1_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_sha1_finalize_prefix"
|
||||||
|
c_sha1_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO ()
|
||||||
|
|||||||
@ -34,6 +34,9 @@ instance HashAlgorithm SHA224 where
|
|||||||
hashInternalUpdate = c_sha224_update
|
hashInternalUpdate = c_sha224_update
|
||||||
hashInternalFinalize = c_sha224_finalize
|
hashInternalFinalize = c_sha224_finalize
|
||||||
|
|
||||||
|
instance HashAlgorithmPrefix SHA224 where
|
||||||
|
hashInternalFinalizePrefix = c_sha224_finalize_prefix
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha224_init"
|
foreign import ccall unsafe "cryptonite_sha224_init"
|
||||||
c_sha224_init :: Ptr (Context a)-> IO ()
|
c_sha224_init :: Ptr (Context a)-> IO ()
|
||||||
|
|
||||||
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha224_update"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha224_finalize"
|
foreign import ccall unsafe "cryptonite_sha224_finalize"
|
||||||
c_sha224_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
c_sha224_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_sha224_finalize_prefix"
|
||||||
|
c_sha224_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO ()
|
||||||
|
|||||||
@ -34,6 +34,9 @@ instance HashAlgorithm SHA256 where
|
|||||||
hashInternalUpdate = c_sha256_update
|
hashInternalUpdate = c_sha256_update
|
||||||
hashInternalFinalize = c_sha256_finalize
|
hashInternalFinalize = c_sha256_finalize
|
||||||
|
|
||||||
|
instance HashAlgorithmPrefix SHA256 where
|
||||||
|
hashInternalFinalizePrefix = c_sha256_finalize_prefix
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha256_init"
|
foreign import ccall unsafe "cryptonite_sha256_init"
|
||||||
c_sha256_init :: Ptr (Context a)-> IO ()
|
c_sha256_init :: Ptr (Context a)-> IO ()
|
||||||
|
|
||||||
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha256_update"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha256_finalize"
|
foreign import ccall unsafe "cryptonite_sha256_finalize"
|
||||||
c_sha256_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
c_sha256_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_sha256_finalize_prefix"
|
||||||
|
c_sha256_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO ()
|
||||||
|
|||||||
@ -37,6 +37,10 @@ instance HashAlgorithm SHA3_224 where
|
|||||||
hashInternalUpdate = c_sha3_update
|
hashInternalUpdate = c_sha3_update
|
||||||
hashInternalFinalize p = c_sha3_finalize p 224
|
hashInternalFinalize p = c_sha3_finalize p 224
|
||||||
|
|
||||||
|
instance HashAlgorithmResumable SHA3_224 where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
-- | SHA3 (256 bits) cryptographic hash algorithm
|
-- | SHA3 (256 bits) cryptographic hash algorithm
|
||||||
data SHA3_256 = SHA3_256
|
data SHA3_256 = SHA3_256
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
@ -52,6 +56,10 @@ instance HashAlgorithm SHA3_256 where
|
|||||||
hashInternalUpdate = c_sha3_update
|
hashInternalUpdate = c_sha3_update
|
||||||
hashInternalFinalize p = c_sha3_finalize p 256
|
hashInternalFinalize p = c_sha3_finalize p 256
|
||||||
|
|
||||||
|
instance HashAlgorithmResumable SHA3_256 where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
-- | SHA3 (384 bits) cryptographic hash algorithm
|
-- | SHA3 (384 bits) cryptographic hash algorithm
|
||||||
data SHA3_384 = SHA3_384
|
data SHA3_384 = SHA3_384
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
@ -67,6 +75,10 @@ instance HashAlgorithm SHA3_384 where
|
|||||||
hashInternalUpdate = c_sha3_update
|
hashInternalUpdate = c_sha3_update
|
||||||
hashInternalFinalize p = c_sha3_finalize p 384
|
hashInternalFinalize p = c_sha3_finalize p 384
|
||||||
|
|
||||||
|
instance HashAlgorithmResumable SHA3_384 where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
-- | SHA3 (512 bits) cryptographic hash algorithm
|
-- | SHA3 (512 bits) cryptographic hash algorithm
|
||||||
data SHA3_512 = SHA3_512
|
data SHA3_512 = SHA3_512
|
||||||
deriving (Show,Data)
|
deriving (Show,Data)
|
||||||
@ -82,6 +94,10 @@ instance HashAlgorithm SHA3_512 where
|
|||||||
hashInternalUpdate = c_sha3_update
|
hashInternalUpdate = c_sha3_update
|
||||||
hashInternalFinalize p = c_sha3_finalize p 512
|
hashInternalFinalize p = c_sha3_finalize p 512
|
||||||
|
|
||||||
|
instance HashAlgorithmResumable SHA3_512 where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha3_init"
|
foreign import ccall unsafe "cryptonite_sha3_init"
|
||||||
c_sha3_init :: Ptr (Context a) -> Word32 -> IO ()
|
c_sha3_init :: Ptr (Context a) -> Word32 -> IO ()
|
||||||
@ -91,3 +107,9 @@ foreign import ccall "cryptonite_sha3_update"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha3_finalize"
|
foreign import ccall unsafe "cryptonite_sha3_finalize"
|
||||||
c_sha3_finalize :: Ptr (Context a) -> Word32 -> Ptr (Digest a) -> IO ()
|
c_sha3_finalize :: Ptr (Context a) -> Word32 -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_sha3_ctx_to_be"
|
||||||
|
c_sha3_ctx_to_be :: Ptr (Context a) -> Ptr Word8 -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_sha3_be_to_ctx"
|
||||||
|
c_sha3_be_to_ctx :: Ptr Word8 -> Ptr (Context a) -> IO ()
|
||||||
|
|||||||
@ -34,6 +34,9 @@ instance HashAlgorithm SHA384 where
|
|||||||
hashInternalUpdate = c_sha384_update
|
hashInternalUpdate = c_sha384_update
|
||||||
hashInternalFinalize = c_sha384_finalize
|
hashInternalFinalize = c_sha384_finalize
|
||||||
|
|
||||||
|
instance HashAlgorithmPrefix SHA384 where
|
||||||
|
hashInternalFinalizePrefix = c_sha384_finalize_prefix
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha384_init"
|
foreign import ccall unsafe "cryptonite_sha384_init"
|
||||||
c_sha384_init :: Ptr (Context a)-> IO ()
|
c_sha384_init :: Ptr (Context a)-> IO ()
|
||||||
|
|
||||||
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha384_update"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha384_finalize"
|
foreign import ccall unsafe "cryptonite_sha384_finalize"
|
||||||
c_sha384_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
c_sha384_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_sha384_finalize_prefix"
|
||||||
|
c_sha384_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO ()
|
||||||
|
|||||||
@ -34,6 +34,9 @@ instance HashAlgorithm SHA512 where
|
|||||||
hashInternalUpdate = c_sha512_update
|
hashInternalUpdate = c_sha512_update
|
||||||
hashInternalFinalize = c_sha512_finalize
|
hashInternalFinalize = c_sha512_finalize
|
||||||
|
|
||||||
|
instance HashAlgorithmPrefix SHA512 where
|
||||||
|
hashInternalFinalizePrefix = c_sha512_finalize_prefix
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha512_init"
|
foreign import ccall unsafe "cryptonite_sha512_init"
|
||||||
c_sha512_init :: Ptr (Context a)-> IO ()
|
c_sha512_init :: Ptr (Context a)-> IO ()
|
||||||
|
|
||||||
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha512_update"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha512_finalize"
|
foreign import ccall unsafe "cryptonite_sha512_finalize"
|
||||||
c_sha512_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
c_sha512_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall "cryptonite_sha512_finalize_prefix"
|
||||||
|
c_sha512_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO ()
|
||||||
|
|||||||
@ -62,6 +62,10 @@ instance KnownNat bitlen => HashSHAKE (SHAKE128 bitlen) where
|
|||||||
cshakeInternalFinalize = cshakeFinalizeOutput (Proxy :: Proxy bitlen)
|
cshakeInternalFinalize = cshakeFinalizeOutput (Proxy :: Proxy bitlen)
|
||||||
cshakeOutputLength _ = integralNatVal (Proxy :: Proxy bitlen)
|
cshakeOutputLength _ = integralNatVal (Proxy :: Proxy bitlen)
|
||||||
|
|
||||||
|
instance KnownNat bitlen => HashAlgorithmResumable (SHAKE128 bitlen) where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
-- | SHAKE256 (256 bits) extendable output function. Supports an arbitrary
|
-- | SHAKE256 (256 bits) extendable output function. Supports an arbitrary
|
||||||
-- digest size, to be specified as a type parameter of kind 'Nat'.
|
-- digest size, to be specified as a type parameter of kind 'Nat'.
|
||||||
--
|
--
|
||||||
@ -86,6 +90,10 @@ instance KnownNat bitlen => HashSHAKE (SHAKE256 bitlen) where
|
|||||||
cshakeInternalFinalize = cshakeFinalizeOutput (Proxy :: Proxy bitlen)
|
cshakeInternalFinalize = cshakeFinalizeOutput (Proxy :: Proxy bitlen)
|
||||||
cshakeOutputLength _ = integralNatVal (Proxy :: Proxy bitlen)
|
cshakeOutputLength _ = integralNatVal (Proxy :: Proxy bitlen)
|
||||||
|
|
||||||
|
instance KnownNat bitlen => HashAlgorithmResumable (SHAKE256 bitlen) where
|
||||||
|
hashInternalPutContextBE = c_sha3_ctx_to_be
|
||||||
|
hashInternalGetContextBE = c_sha3_be_to_ctx
|
||||||
|
|
||||||
shakeFinalizeOutput :: KnownNat bitlen
|
shakeFinalizeOutput :: KnownNat bitlen
|
||||||
=> proxy bitlen
|
=> proxy bitlen
|
||||||
-> Ptr (Context a)
|
-> Ptr (Context a)
|
||||||
@ -129,3 +137,9 @@ foreign import ccall unsafe "cryptonite_sha3_finalize_cshake"
|
|||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha3_output"
|
foreign import ccall unsafe "cryptonite_sha3_output"
|
||||||
c_sha3_output :: Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()
|
c_sha3_output :: Ptr (Context a) -> Ptr (Digest a) -> Word32 -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_sha3_ctx_to_be"
|
||||||
|
c_sha3_ctx_to_be :: Ptr (Context a) -> Ptr Word8 -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_sha3_be_to_ctx"
|
||||||
|
c_sha3_be_to_ctx :: Ptr Word8 -> Ptr (Context a) -> IO ()
|
||||||
|
|||||||
@ -14,6 +14,8 @@
|
|||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
module Crypto.Hash.Types
|
module Crypto.Hash.Types
|
||||||
( HashAlgorithm(..)
|
( HashAlgorithm(..)
|
||||||
|
, HashAlgorithmPrefix(..)
|
||||||
|
, HashAlgorithmResumable(..)
|
||||||
, Context(..)
|
, Context(..)
|
||||||
, Digest(..)
|
, Digest(..)
|
||||||
) where
|
) where
|
||||||
@ -59,12 +61,31 @@ class HashAlgorithm a where
|
|||||||
-- | Finalize the context and set the digest raw memory to the right value
|
-- | Finalize the context and set the digest raw memory to the right value
|
||||||
hashInternalFinalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
hashInternalFinalize :: Ptr (Context a) -> Ptr (Digest a) -> IO ()
|
||||||
|
|
||||||
|
-- | Hashing algorithms with a constant-time implementation.
|
||||||
|
class HashAlgorithm a => HashAlgorithmPrefix a where
|
||||||
|
-- | Update the context with the first N bytes of a buffer and finalize this
|
||||||
|
-- context. The code path executed is independent from N and depends only
|
||||||
|
-- on the complete buffer length.
|
||||||
|
hashInternalFinalizePrefix :: Ptr (Context a)
|
||||||
|
-> Ptr Word8 -> Word32
|
||||||
|
-> Word32
|
||||||
|
-> Ptr (Digest a)
|
||||||
|
-> IO ()
|
||||||
|
class HashAlgorithm a => HashAlgorithmResumable a where
|
||||||
|
hashInternalPutContextBE :: Ptr (Context a) -> Ptr Word8 -> IO ()
|
||||||
|
hashInternalGetContextBE :: Ptr Word8 -> Ptr (Context a) -> IO ()
|
||||||
|
|
||||||
{-
|
{-
|
||||||
hashContextGetAlgorithm :: HashAlgorithm a => Context a -> a
|
hashContextGetAlgorithm :: HashAlgorithm a => Context a -> a
|
||||||
hashContextGetAlgorithm = undefined
|
hashContextGetAlgorithm = undefined
|
||||||
-}
|
-}
|
||||||
|
|
||||||
-- | Represent a context for a given hash algorithm.
|
-- | Represent a context for a given hash algorithm.
|
||||||
|
--
|
||||||
|
-- This type is an instance of 'ByteArrayAccess' for debugging purpose. Internal
|
||||||
|
-- layout is architecture dependent, may contain uninitialized data fragments,
|
||||||
|
-- and change in future versions. The bytearray should not be used as input to
|
||||||
|
-- cryptographic algorithms.
|
||||||
newtype Context a = Context Bytes
|
newtype Context a = Context Bytes
|
||||||
deriving (ByteArrayAccess,NFData)
|
deriving (ByteArrayAccess,NFData)
|
||||||
|
|
||||||
|
|||||||
53
Crypto/Internal/Builder.hs
Normal file
53
Crypto/Internal/Builder.hs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
-- |
|
||||||
|
-- Module : Crypto.Internal.Builder
|
||||||
|
-- License : BSD-style
|
||||||
|
-- Maintainer : Olivier Chéron <olivier.cheron@gmail.com>
|
||||||
|
-- Stability : stable
|
||||||
|
-- Portability : Good
|
||||||
|
--
|
||||||
|
-- Delaying and merging ByteArray allocations. This is similar to module
|
||||||
|
-- "Data.ByteArray.Pack" except the total length is computed automatically based
|
||||||
|
-- on what is appended.
|
||||||
|
--
|
||||||
|
{-# LANGUAGE BangPatterns #-}
|
||||||
|
module Crypto.Internal.Builder
|
||||||
|
( Builder
|
||||||
|
, buildAndFreeze
|
||||||
|
, builderLength
|
||||||
|
, byte
|
||||||
|
, bytes
|
||||||
|
, zero
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.ByteArray (ByteArray, ByteArrayAccess)
|
||||||
|
import qualified Data.ByteArray as B
|
||||||
|
import Data.Memory.PtrMethods (memSet)
|
||||||
|
|
||||||
|
import Foreign.Ptr (Ptr, plusPtr)
|
||||||
|
import Foreign.Storable (poke)
|
||||||
|
|
||||||
|
import Crypto.Internal.Imports hiding (empty)
|
||||||
|
|
||||||
|
data Builder = Builder !Int (Ptr Word8 -> IO ()) -- size and initializer
|
||||||
|
|
||||||
|
instance Semigroup Builder where
|
||||||
|
(Builder s1 f1) <> (Builder s2 f2) = Builder (s1 + s2) f
|
||||||
|
where f p = f1 p >> f2 (p `plusPtr` s1)
|
||||||
|
|
||||||
|
builderLength :: Builder -> Int
|
||||||
|
builderLength (Builder s _) = s
|
||||||
|
|
||||||
|
buildAndFreeze :: ByteArray ba => Builder -> ba
|
||||||
|
buildAndFreeze (Builder s f) = B.allocAndFreeze s f
|
||||||
|
|
||||||
|
byte :: Word8 -> Builder
|
||||||
|
byte !b = Builder 1 (`poke` b)
|
||||||
|
|
||||||
|
bytes :: ByteArrayAccess ba => ba -> Builder
|
||||||
|
bytes bs = Builder (B.length bs) (B.copyByteArrayToPtr bs)
|
||||||
|
|
||||||
|
zero :: Int -> Builder
|
||||||
|
zero s = if s > 0 then Builder s (\p -> memSet p 0 s) else empty
|
||||||
|
|
||||||
|
empty :: Builder
|
||||||
|
empty = Builder 0 (const $ return ())
|
||||||
@ -23,15 +23,21 @@ module Crypto.Internal.CompatPrim
|
|||||||
, convert4To32
|
, convert4To32
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import GHC.Prim
|
|
||||||
#if !defined(ARCH_IS_LITTLE_ENDIAN) && !defined(ARCH_IS_BIG_ENDIAN)
|
#if !defined(ARCH_IS_LITTLE_ENDIAN) && !defined(ARCH_IS_BIG_ENDIAN)
|
||||||
import Data.Memory.Endian (getSystemEndianness, Endianness(..))
|
import Data.Memory.Endian (getSystemEndianness, Endianness(..))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __GLASGOW_HASKELL__ >= 902
|
||||||
|
import GHC.Prim
|
||||||
|
#else
|
||||||
|
import GHC.Prim hiding (Word32#)
|
||||||
|
type Word32# = Word#
|
||||||
|
#endif
|
||||||
|
|
||||||
-- | Byteswap Word# to or from Big Endian
|
-- | Byteswap Word# to or from Big Endian
|
||||||
--
|
--
|
||||||
-- On a big endian machine, this function is a nop.
|
-- On a big endian machine, this function is a nop.
|
||||||
be32Prim :: Word# -> Word#
|
be32Prim :: Word32# -> Word32#
|
||||||
#ifdef ARCH_IS_LITTLE_ENDIAN
|
#ifdef ARCH_IS_LITTLE_ENDIAN
|
||||||
be32Prim = byteswap32Prim
|
be32Prim = byteswap32Prim
|
||||||
#elif defined(ARCH_IS_BIG_ENDIAN)
|
#elif defined(ARCH_IS_BIG_ENDIAN)
|
||||||
@ -43,7 +49,7 @@ be32Prim w = if getSystemEndianness == LittleEndian then byteswap32Prim w else w
|
|||||||
-- | Byteswap Word# to or from Little Endian
|
-- | Byteswap Word# to or from Little Endian
|
||||||
--
|
--
|
||||||
-- On a little endian machine, this function is a nop.
|
-- On a little endian machine, this function is a nop.
|
||||||
le32Prim :: Word# -> Word#
|
le32Prim :: Word32# -> Word32#
|
||||||
#ifdef ARCH_IS_LITTLE_ENDIAN
|
#ifdef ARCH_IS_LITTLE_ENDIAN
|
||||||
le32Prim w = w
|
le32Prim w = w
|
||||||
#elif defined(ARCH_IS_BIG_ENDIAN)
|
#elif defined(ARCH_IS_BIG_ENDIAN)
|
||||||
@ -54,16 +60,11 @@ le32Prim w = if getSystemEndianness == LittleEndian then w else byteswap32Prim w
|
|||||||
|
|
||||||
-- | Simple compatibility for byteswap the lower 32 bits of a Word#
|
-- | Simple compatibility for byteswap the lower 32 bits of a Word#
|
||||||
-- at the primitive level
|
-- at the primitive level
|
||||||
byteswap32Prim :: Word# -> Word#
|
byteswap32Prim :: Word32# -> Word32#
|
||||||
#if __GLASGOW_HASKELL__ >= 708
|
#if __GLASGOW_HASKELL__ >= 902
|
||||||
byteswap32Prim w = byteSwap32# w
|
byteswap32Prim w = wordToWord32# (byteSwap32# (word32ToWord# w))
|
||||||
#else
|
#else
|
||||||
byteswap32Prim w =
|
byteswap32Prim w = byteSwap32# w
|
||||||
let !a = uncheckedShiftL# w 24#
|
|
||||||
!b = and# (uncheckedShiftL# w 8#) 0x00ff0000##
|
|
||||||
!c = and# (uncheckedShiftRL# w 8#) 0x0000ff00##
|
|
||||||
!d = and# (uncheckedShiftRL# w 24#) 0x000000ff##
|
|
||||||
in or# a (or# b (or# c d))
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
-- | Combine 4 word8 [a,b,c,d] to a word32 representing [a,b,c,d]
|
-- | Combine 4 word8 [a,b,c,d] to a word32 representing [a,b,c,d]
|
||||||
|
|||||||
@ -5,11 +5,15 @@
|
|||||||
-- Stability : experimental
|
-- Stability : experimental
|
||||||
-- Portability : unknown
|
-- Portability : unknown
|
||||||
--
|
--
|
||||||
|
{-# LANGUAGE CPP #-}
|
||||||
module Crypto.Internal.Imports
|
module Crypto.Internal.Imports
|
||||||
( module X
|
( module X
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.Word as X
|
import Data.Word as X
|
||||||
|
#if !(MIN_VERSION_base(4,11,0))
|
||||||
|
import Data.Semigroup as X (Semigroup(..))
|
||||||
|
#endif
|
||||||
import Control.Applicative as X
|
import Control.Applicative as X
|
||||||
import Control.Monad as X (forM, forM_, void)
|
import Control.Monad as X (forM, forM_, void)
|
||||||
import Control.Arrow as X (first, second)
|
import Control.Arrow as X (first, second)
|
||||||
|
|||||||
@ -94,7 +94,7 @@ bxor = B.xor
|
|||||||
|
|
||||||
|
|
||||||
cipherIPT :: BlockCipher k => k -> [Word8]
|
cipherIPT :: BlockCipher k => k -> [Word8]
|
||||||
cipherIPT = expandIPT . blockSize where
|
cipherIPT = expandIPT . blockSize
|
||||||
|
|
||||||
-- Data type which represents the smallest irreducibule binary polynomial
|
-- Data type which represents the smallest irreducibule binary polynomial
|
||||||
-- against specified degree.
|
-- against specified degree.
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
module Crypto.MAC.HMAC
|
module Crypto.MAC.HMAC
|
||||||
( hmac
|
( hmac
|
||||||
|
, hmacLazy
|
||||||
, HMAC(..)
|
, HMAC(..)
|
||||||
-- * Incremental
|
-- * Incremental
|
||||||
, Context(..)
|
, Context(..)
|
||||||
@ -28,6 +29,7 @@ import Crypto.Internal.ByteArray (ScrubbedBytes, ByteArrayAccess)
|
|||||||
import qualified Crypto.Internal.ByteArray as B
|
import qualified Crypto.Internal.ByteArray as B
|
||||||
import Data.Memory.PtrMethods
|
import Data.Memory.PtrMethods
|
||||||
import Crypto.Internal.Compat
|
import Crypto.Internal.Compat
|
||||||
|
import qualified Data.ByteString.Lazy as L
|
||||||
|
|
||||||
-- | Represent an HMAC that is a phantom type with the hash used to produce the mac.
|
-- | Represent an HMAC that is a phantom type with the hash used to produce the mac.
|
||||||
--
|
--
|
||||||
@ -39,13 +41,20 @@ newtype HMAC a = HMAC { hmacGetDigest :: Digest a }
|
|||||||
instance Eq (HMAC a) where
|
instance Eq (HMAC a) where
|
||||||
(HMAC b1) == (HMAC b2) = B.constEq b1 b2
|
(HMAC b1) == (HMAC b2) = B.constEq b1 b2
|
||||||
|
|
||||||
-- | compute a MAC using the supplied hashing function
|
-- | Compute a MAC using the supplied hashing function
|
||||||
hmac :: (ByteArrayAccess key, ByteArrayAccess message, HashAlgorithm a)
|
hmac :: (ByteArrayAccess key, ByteArrayAccess message, HashAlgorithm a)
|
||||||
=> key -- ^ Secret key
|
=> key -- ^ Secret key
|
||||||
-> message -- ^ Message to MAC
|
-> message -- ^ Message to MAC
|
||||||
-> HMAC a
|
-> HMAC a
|
||||||
hmac secret msg = finalize $ updates (initialize secret) [msg]
|
hmac secret msg = finalize $ updates (initialize secret) [msg]
|
||||||
|
|
||||||
|
-- | Compute a MAC using the supplied hashing function, for a lazy input
|
||||||
|
hmacLazy :: (ByteArrayAccess key, HashAlgorithm a)
|
||||||
|
=> key -- ^ Secret key
|
||||||
|
-> L.ByteString -- ^ Message to MAC
|
||||||
|
-> HMAC a
|
||||||
|
hmacLazy secret msg = finalize $ updates (initialize secret) (L.toChunks msg)
|
||||||
|
|
||||||
-- | Represent an ongoing HMAC state, that can be appended with 'update'
|
-- | Represent an ongoing HMAC state, that can be appended with 'update'
|
||||||
-- and finalize to an HMAC with 'hmacFinalize'
|
-- and finalize to an HMAC with 'hmacFinalize'
|
||||||
data Context hashalg = Context !(Hash.Context hashalg) !(Hash.Context hashalg)
|
data Context hashalg = Context !(Hash.Context hashalg) !(Hash.Context hashalg)
|
||||||
|
|||||||
@ -27,13 +27,12 @@ import qualified Crypto.Hash as H
|
|||||||
import Crypto.Hash.SHAKE (HashSHAKE(..))
|
import Crypto.Hash.SHAKE (HashSHAKE(..))
|
||||||
import Crypto.Hash.Types (HashAlgorithm(..), Digest(..))
|
import Crypto.Hash.Types (HashAlgorithm(..), Digest(..))
|
||||||
import qualified Crypto.Hash.Types as H
|
import qualified Crypto.Hash.Types as H
|
||||||
import Foreign.Ptr (Ptr, plusPtr)
|
import Crypto.Internal.Builder
|
||||||
import Foreign.Storable (poke)
|
import Crypto.Internal.Imports
|
||||||
|
import Foreign.Ptr (Ptr)
|
||||||
import Data.Bits (shiftR)
|
import Data.Bits (shiftR)
|
||||||
import Data.ByteArray (ByteArray, ByteArrayAccess)
|
import Data.ByteArray (ByteArrayAccess)
|
||||||
import qualified Data.ByteArray as B
|
import qualified Data.ByteArray as B
|
||||||
import Data.Word (Word8)
|
|
||||||
import Data.Memory.PtrMethods (memSet)
|
|
||||||
|
|
||||||
|
|
||||||
-- cSHAKE
|
-- cSHAKE
|
||||||
@ -47,8 +46,8 @@ cshakeInit n s p = H.Context $ B.allocAndFreeze c $ \(ptr :: Ptr (H.Context a))
|
|||||||
where
|
where
|
||||||
c = hashInternalContextSize (undefined :: a)
|
c = hashInternalContextSize (undefined :: a)
|
||||||
w = hashBlockSize (undefined :: a)
|
w = hashBlockSize (undefined :: a)
|
||||||
x = encodeString n <+> encodeString s
|
x = encodeString n <> encodeString s
|
||||||
b = builderAllocAndFreeze (bytepad x w) :: B.Bytes
|
b = buildAndFreeze (bytepad x w) :: B.Bytes
|
||||||
|
|
||||||
cshakeUpdate :: (HashSHAKE a, ByteArrayAccess ba)
|
cshakeUpdate :: (HashSHAKE a, ByteArrayAccess ba)
|
||||||
=> H.Context a -> ba -> H.Context a
|
=> H.Context a -> ba -> H.Context a
|
||||||
@ -77,7 +76,7 @@ cshakeFinalize !c s =
|
|||||||
-- The Eq instance is constant time. No Show instance is provided, to avoid
|
-- The Eq instance is constant time. No Show instance is provided, to avoid
|
||||||
-- printing by mistake.
|
-- printing by mistake.
|
||||||
newtype KMAC a = KMAC { kmacGetDigest :: Digest a }
|
newtype KMAC a = KMAC { kmacGetDigest :: Digest a }
|
||||||
deriving ByteArrayAccess
|
deriving (ByteArrayAccess,NFData)
|
||||||
|
|
||||||
instance Eq (KMAC a) where
|
instance Eq (KMAC a) where
|
||||||
(KMAC b1) == (KMAC b2) = B.constEq b1 b2
|
(KMAC b1) == (KMAC b2) = B.constEq b1 b2
|
||||||
@ -99,7 +98,7 @@ initialize str key = Context $ cshakeInit n str p
|
|||||||
where
|
where
|
||||||
n = B.pack [75,77,65,67] :: B.Bytes -- "KMAC"
|
n = B.pack [75,77,65,67] :: B.Bytes -- "KMAC"
|
||||||
w = hashBlockSize (undefined :: a)
|
w = hashBlockSize (undefined :: a)
|
||||||
p = builderAllocAndFreeze (bytepad (encodeString key) w) :: B.ScrubbedBytes
|
p = buildAndFreeze (bytepad (encodeString key) w) :: B.ScrubbedBytes
|
||||||
|
|
||||||
-- | Incrementally update a KMAC context.
|
-- | Incrementally update a KMAC context.
|
||||||
update :: (HashSHAKE a, ByteArrayAccess ba) => Context a -> ba -> Context a
|
update :: (HashSHAKE a, ByteArrayAccess ba) => Context a -> ba -> Context a
|
||||||
@ -114,56 +113,32 @@ finalize :: forall a . HashSHAKE a => Context a -> KMAC a
|
|||||||
finalize (Context ctx) = KMAC $ cshakeFinalize ctx suffix
|
finalize (Context ctx) = KMAC $ cshakeFinalize ctx suffix
|
||||||
where
|
where
|
||||||
l = cshakeOutputLength (undefined :: a)
|
l = cshakeOutputLength (undefined :: a)
|
||||||
suffix = builderAllocAndFreeze (rightEncode l) :: B.Bytes
|
suffix = buildAndFreeze (rightEncode l) :: B.Bytes
|
||||||
|
|
||||||
|
|
||||||
-- Utilities
|
-- Utilities
|
||||||
|
|
||||||
bytepad :: Builder -> Int -> Builder
|
bytepad :: Builder -> Int -> Builder
|
||||||
bytepad x w = prefix <+> x <+> zero padLen
|
bytepad x w = prefix <> x <> zero padLen
|
||||||
where
|
where
|
||||||
prefix = leftEncode w
|
prefix = leftEncode w
|
||||||
padLen = (w - builderLength prefix - builderLength x) `mod` w
|
padLen = (w - builderLength prefix - builderLength x) `mod` w
|
||||||
|
|
||||||
encodeString :: ByteArrayAccess bin => bin -> Builder
|
encodeString :: ByteArrayAccess bin => bin -> Builder
|
||||||
encodeString s = leftEncode (8 * B.length s) <+> bytes s
|
encodeString s = leftEncode (8 * B.length s) <> bytes s
|
||||||
|
|
||||||
leftEncode :: Int -> Builder
|
leftEncode :: Int -> Builder
|
||||||
leftEncode x = byte len <+> digits
|
leftEncode x = byte len <> digits
|
||||||
where
|
where
|
||||||
digits = i2osp x
|
digits = i2osp x
|
||||||
len = fromIntegral (builderLength digits)
|
len = fromIntegral (builderLength digits)
|
||||||
|
|
||||||
rightEncode :: Int -> Builder
|
rightEncode :: Int -> Builder
|
||||||
rightEncode x = digits <+> byte len
|
rightEncode x = digits <> byte len
|
||||||
where
|
where
|
||||||
digits = i2osp x
|
digits = i2osp x
|
||||||
len = fromIntegral (builderLength digits)
|
len = fromIntegral (builderLength digits)
|
||||||
|
|
||||||
i2osp :: Int -> Builder
|
i2osp :: Int -> Builder
|
||||||
i2osp i | i >= 256 = i2osp (shiftR i 8) <+> byte (fromIntegral i)
|
i2osp i | i >= 256 = i2osp (shiftR i 8) <> byte (fromIntegral i)
|
||||||
| otherwise = byte (fromIntegral i)
|
| otherwise = byte (fromIntegral i)
|
||||||
|
|
||||||
|
|
||||||
-- Delaying and merging ByteArray allocations
|
|
||||||
|
|
||||||
data Builder = Builder !Int (Ptr Word8 -> IO ()) -- size and initializer
|
|
||||||
|
|
||||||
(<+>) :: Builder -> Builder -> Builder
|
|
||||||
(Builder s1 f1) <+> (Builder s2 f2) = Builder (s1 + s2) f
|
|
||||||
where f p = f1 p >> f2 (p `plusPtr` s1)
|
|
||||||
|
|
||||||
builderLength :: Builder -> Int
|
|
||||||
builderLength (Builder s _) = s
|
|
||||||
|
|
||||||
builderAllocAndFreeze :: ByteArray ba => Builder -> ba
|
|
||||||
builderAllocAndFreeze (Builder s f) = B.allocAndFreeze s f
|
|
||||||
|
|
||||||
byte :: Word8 -> Builder
|
|
||||||
byte !b = Builder 1 (`poke` b)
|
|
||||||
|
|
||||||
bytes :: ByteArrayAccess ba => ba -> Builder
|
|
||||||
bytes bs = Builder (B.length bs) (B.copyByteArrayToPtr bs)
|
|
||||||
|
|
||||||
zero :: Int -> Builder
|
|
||||||
zero s = Builder s (\p -> memSet p 0 s)
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ import Crypto.Internal.DeepSeq
|
|||||||
import Crypto.Error
|
import Crypto.Error
|
||||||
|
|
||||||
-- | Poly1305 State
|
-- | Poly1305 State
|
||||||
|
--
|
||||||
|
-- This type is an instance of 'ByteArrayAccess' for debugging purpose. Internal
|
||||||
|
-- layout is architecture dependent, may contain uninitialized data fragments,
|
||||||
|
-- and change in future versions. The bytearray should not be used as input to
|
||||||
|
-- cryptographic algorithms.
|
||||||
newtype State = State ScrubbedBytes
|
newtype State = State ScrubbedBytes
|
||||||
deriving (ByteArrayAccess)
|
deriving (ByteArrayAccess)
|
||||||
|
|
||||||
|
|||||||
@ -72,7 +72,9 @@ gmpLog2 _ = GmpUnsupported
|
|||||||
-- | Compute the power modulus using extra security to remain constant
|
-- | Compute the power modulus using extra security to remain constant
|
||||||
-- time wise through GMP
|
-- time wise through GMP
|
||||||
gmpPowModSecInteger :: Integer -> Integer -> Integer -> GmpSupported Integer
|
gmpPowModSecInteger :: Integer -> Integer -> Integer -> GmpSupported Integer
|
||||||
#if MIN_VERSION_integer_gmp(1,0,2)
|
#if MIN_VERSION_integer_gmp(1,1,0)
|
||||||
|
gmpPowModSecInteger _ _ _ = GmpUnsupported
|
||||||
|
#elif MIN_VERSION_integer_gmp(1,0,2)
|
||||||
gmpPowModSecInteger b e m = GmpSupported (powModSecInteger b e m)
|
gmpPowModSecInteger b e m = GmpSupported (powModSecInteger b e m)
|
||||||
#elif MIN_VERSION_integer_gmp(1,0,0)
|
#elif MIN_VERSION_integer_gmp(1,0,0)
|
||||||
gmpPowModSecInteger _ _ _ = GmpUnsupported
|
gmpPowModSecInteger _ _ _ = GmpUnsupported
|
||||||
@ -103,7 +105,9 @@ gmpInverse _ _ = GmpUnsupported
|
|||||||
|
|
||||||
-- | Get the next prime from a specific value through GMP
|
-- | Get the next prime from a specific value through GMP
|
||||||
gmpNextPrime :: Integer -> GmpSupported Integer
|
gmpNextPrime :: Integer -> GmpSupported Integer
|
||||||
#if MIN_VERSION_integer_gmp(0,5,1)
|
#if MIN_VERSION_integer_gmp(1,1,0)
|
||||||
|
gmpNextPrime _ = GmpUnsupported
|
||||||
|
#elif MIN_VERSION_integer_gmp(0,5,1)
|
||||||
gmpNextPrime n = GmpSupported (nextPrimeInteger n)
|
gmpNextPrime n = GmpSupported (nextPrimeInteger n)
|
||||||
#else
|
#else
|
||||||
gmpNextPrime _ = GmpUnsupported
|
gmpNextPrime _ = GmpUnsupported
|
||||||
@ -111,7 +115,9 @@ gmpNextPrime _ = GmpUnsupported
|
|||||||
|
|
||||||
-- | Test if a number is prime using Miller Rabin
|
-- | Test if a number is prime using Miller Rabin
|
||||||
gmpTestPrimeMillerRabin :: Int -> Integer -> GmpSupported Bool
|
gmpTestPrimeMillerRabin :: Int -> Integer -> GmpSupported Bool
|
||||||
#if MIN_VERSION_integer_gmp(0,5,1)
|
#if MIN_VERSION_integer_gmp(1,1,0)
|
||||||
|
gmpTestPrimeMillerRabin _ _ = GmpUnsupported
|
||||||
|
#elif MIN_VERSION_integer_gmp(0,5,1)
|
||||||
gmpTestPrimeMillerRabin (I# tries) !n = GmpSupported $
|
gmpTestPrimeMillerRabin (I# tries) !n = GmpSupported $
|
||||||
case testPrimeInteger n tries of
|
case testPrimeInteger n tries of
|
||||||
0# -> False
|
0# -> False
|
||||||
|
|||||||
@ -16,7 +16,9 @@ module Crypto.Number.F2m
|
|||||||
, mulF2m
|
, mulF2m
|
||||||
, squareF2m'
|
, squareF2m'
|
||||||
, squareF2m
|
, squareF2m
|
||||||
|
, powF2m
|
||||||
, modF2m
|
, modF2m
|
||||||
|
, sqrtF2m
|
||||||
, invF2m
|
, invF2m
|
||||||
, divF2m
|
, divF2m
|
||||||
) where
|
) where
|
||||||
@ -66,8 +68,8 @@ mulF2m :: BinaryPolynomial -- ^ Modulus
|
|||||||
mulF2m fx n1 n2
|
mulF2m fx n1 n2
|
||||||
| fx < 0
|
| fx < 0
|
||||||
|| n1 < 0
|
|| n1 < 0
|
||||||
|| n2 < 0 = error "mulF2m: negative number represent no binary binary polynomial"
|
|| n2 < 0 = error "mulF2m: negative number represent no binary polynomial"
|
||||||
| fx == 0 = error "modF2m: cannot multiply modulo zero polynomial"
|
| fx == 0 = error "mulF2m: cannot multiply modulo zero polynomial"
|
||||||
| otherwise = modF2m fx $ go (if n2 `mod` 2 == 1 then n1 else 0) (log2 n2)
|
| otherwise = modF2m fx $ go (if n2 `mod` 2 == 1 then n1 else 0) (log2 n2)
|
||||||
where
|
where
|
||||||
go n s | s == 0 = n
|
go n s | s == 0 = n
|
||||||
@ -96,10 +98,37 @@ squareF2m fx = modF2m fx . squareF2m'
|
|||||||
squareF2m' :: Integer
|
squareF2m' :: Integer
|
||||||
-> Integer
|
-> Integer
|
||||||
squareF2m' n
|
squareF2m' n
|
||||||
| n < 0 = error "mulF2m: negative number represent no binary binary polynomial"
|
| n < 0 = error "mulF2m: negative number represent no binary polynomial"
|
||||||
| otherwise = foldl' (\acc s -> if testBit n s then setBit acc (2 * s) else acc) 0 [0 .. log2 n]
|
| otherwise = foldl' (\acc s -> if testBit n s then setBit acc (2 * s) else acc) 0 [0 .. log2 n]
|
||||||
{-# INLINE squareF2m' #-}
|
{-# INLINE squareF2m' #-}
|
||||||
|
|
||||||
|
-- | Exponentiation in F₂m by computing @a^b mod fx@.
|
||||||
|
--
|
||||||
|
-- This implements an exponentiation by squaring based solution. It inherits the
|
||||||
|
-- same restrictions as 'squareF2m'. Negative exponents are disallowed.
|
||||||
|
powF2m :: BinaryPolynomial -- ^Modulus
|
||||||
|
-> Integer -- ^a
|
||||||
|
-> Integer -- ^b
|
||||||
|
-> Integer
|
||||||
|
powF2m fx a b
|
||||||
|
| b < 0 = error "powF2m: negative exponents disallowed"
|
||||||
|
| b == 0 = if fx > 1 then 1 else 0
|
||||||
|
| even b = squareF2m fx x
|
||||||
|
| otherwise = mulF2m fx a (squareF2m' x)
|
||||||
|
where x = powF2m fx a (b `div` 2)
|
||||||
|
|
||||||
|
-- | Square rooot in F₂m.
|
||||||
|
--
|
||||||
|
-- We exploit the fact that @a^(2^m) = a@, or in particular, @a^(2^m - 1) = 1@
|
||||||
|
-- from a classical result by Lagrange. Thus the square root is simply @a^(2^(m
|
||||||
|
-- - 1))@.
|
||||||
|
sqrtF2m :: BinaryPolynomial -- ^Modulus
|
||||||
|
-> Integer -- ^a
|
||||||
|
-> Integer
|
||||||
|
sqrtF2m fx a = go (log2 fx - 1) a
|
||||||
|
where go 0 x = x
|
||||||
|
go n x = go (n - 1) (squareF2m fx x)
|
||||||
|
|
||||||
-- | Extended GCD algorithm for polynomials. For @a@ and @b@ returns @(g, u, v)@ such that @a * u + b * v == g@.
|
-- | Extended GCD algorithm for polynomials. For @a@ and @b@ returns @(g, u, v)@ such that @a * u + b * v == g@.
|
||||||
--
|
--
|
||||||
-- Reference: https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#B.C3.A9zout.27s_identity_and_extended_GCD_algorithm
|
-- Reference: https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#B.C3.A9zout.27s_identity_and_extended_GCD_algorithm
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
{-# LANGUAGE BangPatterns #-}
|
{-# LANGUAGE BangPatterns #-}
|
||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
|
||||||
-- |
|
-- |
|
||||||
-- Module : Crypto.Number.ModArithmetic
|
-- Module : Crypto.Number.ModArithmetic
|
||||||
-- License : BSD-style
|
-- License : BSD-style
|
||||||
@ -15,7 +14,10 @@ module Crypto.Number.ModArithmetic
|
|||||||
-- * Inverse computing
|
-- * Inverse computing
|
||||||
, inverse
|
, inverse
|
||||||
, inverseCoprimes
|
, inverseCoprimes
|
||||||
|
, inverseFermat
|
||||||
|
-- * Squares
|
||||||
, jacobi
|
, jacobi
|
||||||
|
, squareRoot
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Exception (throw, Exception)
|
import Control.Exception (throw, Exception)
|
||||||
@ -56,7 +58,7 @@ expSafe b e m
|
|||||||
-- hiding parameters.
|
-- hiding parameters.
|
||||||
--
|
--
|
||||||
-- Use this function when all the parameters are public,
|
-- Use this function when all the parameters are public,
|
||||||
-- otherwise 'expSafe' should be prefered.
|
-- otherwise 'expSafe' should be preferred.
|
||||||
expFast :: Integer -- ^ base
|
expFast :: Integer -- ^ base
|
||||||
-> Integer -- ^ exponent
|
-> Integer -- ^ exponent
|
||||||
-> Integer -- ^ modulo
|
-> Integer -- ^ modulo
|
||||||
@ -70,7 +72,7 @@ exponentiation b e m
|
|||||||
| b == 1 = b
|
| b == 1 = b
|
||||||
| e == 0 = 1
|
| e == 0 = 1
|
||||||
| e == 1 = b `mod` m
|
| e == 1 = b `mod` m
|
||||||
| even e = let p = (exponentiation b (e `div` 2) m) `mod` m
|
| even e = let p = exponentiation b (e `div` 2) m `mod` m
|
||||||
in (p^(2::Integer)) `mod` m
|
in (p^(2::Integer)) `mod` m
|
||||||
| otherwise = (b * exponentiation b (e-1) m) `mod` m
|
| otherwise = (b * exponentiation b (e-1) m) `mod` m
|
||||||
|
|
||||||
@ -97,17 +99,17 @@ inverseCoprimes g m =
|
|||||||
|
|
||||||
-- | Computes the Jacobi symbol (a/n).
|
-- | Computes the Jacobi symbol (a/n).
|
||||||
-- 0 ≤ a < n; n ≥ 3 and odd.
|
-- 0 ≤ a < n; n ≥ 3 and odd.
|
||||||
--
|
--
|
||||||
-- The Legendre and Jacobi symbols are indistinguishable exactly when the
|
-- The Legendre and Jacobi symbols are indistinguishable exactly when the
|
||||||
-- lower argument is an odd prime, in which case they have the same value.
|
-- lower argument is an odd prime, in which case they have the same value.
|
||||||
--
|
--
|
||||||
-- See algorithm 2.149 in "Handbook of Applied Cryptography" by Alfred J. Menezes et al.
|
-- See algorithm 2.149 in "Handbook of Applied Cryptography" by Alfred J. Menezes et al.
|
||||||
jacobi :: Integer -> Integer -> Maybe Integer
|
jacobi :: Integer -> Integer -> Maybe Integer
|
||||||
jacobi a n
|
jacobi a n
|
||||||
| n < 3 || even n = Nothing
|
| n < 3 || even n = Nothing
|
||||||
| a == 0 || a == 1 = Just a
|
| a == 0 || a == 1 = Just a
|
||||||
| n <= a = jacobi (a `mod` n) n
|
| n <= a = jacobi (a `mod` n) n
|
||||||
| a < 0 =
|
| a < 0 =
|
||||||
let b = if n `mod` 4 == 1 then 1 else -1
|
let b = if n `mod` 4 == 1 then 1 else -1
|
||||||
in fmap (*b) (jacobi (-a) n)
|
in fmap (*b) (jacobi (-a) n)
|
||||||
| otherwise =
|
| otherwise =
|
||||||
@ -120,3 +122,96 @@ jacobi a n
|
|||||||
n1 = n `mod` a1
|
n1 = n `mod` a1
|
||||||
in if a1 == 1 then Just s
|
in if a1 == 1 then Just s
|
||||||
else fmap (*s) (jacobi n1 a1)
|
else fmap (*s) (jacobi n1 a1)
|
||||||
|
|
||||||
|
-- | Modular inverse using Fermat's little theorem. This works only when
|
||||||
|
-- the modulus is prime but avoids side channels like in 'expSafe'.
|
||||||
|
inverseFermat :: Integer -> Integer -> Integer
|
||||||
|
inverseFermat g p = expSafe g (p - 2) p
|
||||||
|
|
||||||
|
-- | Raised when the assumption about the modulus is invalid.
|
||||||
|
data ModulusAssertionError = ModulusAssertionError
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
|
instance Exception ModulusAssertionError
|
||||||
|
|
||||||
|
-- | Modular square root of @g@ modulo a prime @p@.
|
||||||
|
--
|
||||||
|
-- If the modulus is found not to be prime, the function will raise a
|
||||||
|
-- 'ModulusAssertionError'.
|
||||||
|
--
|
||||||
|
-- This implementation is variable time and should be used with public
|
||||||
|
-- parameters only.
|
||||||
|
squareRoot :: Integer -> Integer -> Maybe Integer
|
||||||
|
squareRoot p
|
||||||
|
| p < 2 = throw ModulusAssertionError
|
||||||
|
| otherwise =
|
||||||
|
case p `divMod` 8 of
|
||||||
|
(v, 3) -> method1 (2 * v + 1)
|
||||||
|
(v, 7) -> method1 (2 * v + 2)
|
||||||
|
(u, 5) -> method2 u
|
||||||
|
(_, 1) -> tonelliShanks p
|
||||||
|
(0, 2) -> \a -> Just (if even a then 0 else 1)
|
||||||
|
_ -> throw ModulusAssertionError
|
||||||
|
|
||||||
|
where
|
||||||
|
x `eqMod` y = (x - y) `mod` p == 0
|
||||||
|
|
||||||
|
validate g y | (y * y) `eqMod` g = Just y
|
||||||
|
| otherwise = Nothing
|
||||||
|
|
||||||
|
-- p == 4u + 3 and u' == u + 1
|
||||||
|
method1 u' g =
|
||||||
|
let y = expFast g u' p
|
||||||
|
in validate g y
|
||||||
|
|
||||||
|
-- p == 8u + 5
|
||||||
|
method2 u g =
|
||||||
|
let gamma = expFast (2 * g) u p
|
||||||
|
g_gamma = g * gamma
|
||||||
|
i = (2 * g_gamma * gamma) `mod` p
|
||||||
|
y = (g_gamma * (i - 1)) `mod` p
|
||||||
|
in validate g y
|
||||||
|
|
||||||
|
tonelliShanks :: Integer -> Integer -> Maybe Integer
|
||||||
|
tonelliShanks p a
|
||||||
|
| aa == 0 = Just 0
|
||||||
|
| otherwise =
|
||||||
|
case expFast aa p2 p of
|
||||||
|
b | b == p1 -> Nothing
|
||||||
|
| b == 1 -> Just $ go (expFast aa ((s + 1) `div` 2) p)
|
||||||
|
(expFast aa s p)
|
||||||
|
(expFast n s p)
|
||||||
|
e
|
||||||
|
| otherwise -> throw ModulusAssertionError
|
||||||
|
where
|
||||||
|
aa = a `mod` p
|
||||||
|
p1 = p - 1
|
||||||
|
p2 = p1 `div` 2
|
||||||
|
n = findN 2
|
||||||
|
|
||||||
|
x `mul` y = (x * y) `mod` p
|
||||||
|
|
||||||
|
pow2m 0 x = x
|
||||||
|
pow2m i x = pow2m (i - 1) (x `mul` x)
|
||||||
|
|
||||||
|
(e, s) = asPowerOf2AndOdd p1
|
||||||
|
|
||||||
|
-- find a quadratic non-residue
|
||||||
|
findN i
|
||||||
|
| expFast i p2 p == p1 = i
|
||||||
|
| otherwise = findN (i + 1)
|
||||||
|
|
||||||
|
-- find m such that b^(2^m) == 1 (mod p)
|
||||||
|
findM b i
|
||||||
|
| b == 1 = i
|
||||||
|
| otherwise = findM (b `mul` b) (i + 1)
|
||||||
|
|
||||||
|
go !x b g !r
|
||||||
|
| b == 1 = x
|
||||||
|
| otherwise =
|
||||||
|
let r' = findM b 0
|
||||||
|
z = pow2m (r - r' - 1) g
|
||||||
|
x' = x `mul` z
|
||||||
|
b' = b `mul` g'
|
||||||
|
g' = z `mul` z
|
||||||
|
in go x' b' g' r'
|
||||||
|
|||||||
@ -127,7 +127,7 @@ primalityTestMillerRabin tries !n =
|
|||||||
factorise :: Integer -> Integer -> (Integer, Integer)
|
factorise :: Integer -> Integer -> (Integer, Integer)
|
||||||
factorise !si !vi
|
factorise !si !vi
|
||||||
| vi `testBit` 0 = (si, vi)
|
| vi `testBit` 0 = (si, vi)
|
||||||
| otherwise = factorise (si+1) (vi `shiftR` 1) -- probably faster to not shift v continously, but just once.
|
| otherwise = factorise (si+1) (vi `shiftR` 1) -- probably faster to not shift v continuously, but just once.
|
||||||
expmod = expSafe
|
expmod = expSafe
|
||||||
|
|
||||||
-- when iteration reach zero, we have a probable prime
|
-- when iteration reach zero, we have a probable prime
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
-- P256 support
|
-- P256 support
|
||||||
--
|
--
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
{-# LANGUAGE BangPatterns #-}
|
|
||||||
{-# LANGUAGE EmptyDataDecls #-}
|
{-# LANGUAGE EmptyDataDecls #-}
|
||||||
{-# OPTIONS_GHC -fno-warn-unused-binds #-}
|
{-# OPTIONS_GHC -fno-warn-unused-binds #-}
|
||||||
module Crypto.PubKey.ECC.P256
|
module Crypto.PubKey.ECC.P256
|
||||||
@ -22,7 +21,9 @@ module Crypto.PubKey.ECC.P256
|
|||||||
, pointDh
|
, pointDh
|
||||||
, pointsMulVarTime
|
, pointsMulVarTime
|
||||||
, pointIsValid
|
, pointIsValid
|
||||||
|
, pointIsAtInfinity
|
||||||
, toPoint
|
, toPoint
|
||||||
|
, pointX
|
||||||
, pointToIntegers
|
, pointToIntegers
|
||||||
, pointFromIntegers
|
, pointFromIntegers
|
||||||
, pointToBinary
|
, pointToBinary
|
||||||
@ -31,10 +32,13 @@ module Crypto.PubKey.ECC.P256
|
|||||||
-- * Scalar arithmetic
|
-- * Scalar arithmetic
|
||||||
, scalarGenerate
|
, scalarGenerate
|
||||||
, scalarZero
|
, scalarZero
|
||||||
|
, scalarN
|
||||||
, scalarIsZero
|
, scalarIsZero
|
||||||
, scalarAdd
|
, scalarAdd
|
||||||
, scalarSub
|
, scalarSub
|
||||||
|
, scalarMul
|
||||||
, scalarInv
|
, scalarInv
|
||||||
|
, scalarInvSafe
|
||||||
, scalarCmp
|
, scalarCmp
|
||||||
, scalarFromBinary
|
, scalarFromBinary
|
||||||
, scalarToBinary
|
, scalarToBinary
|
||||||
@ -76,6 +80,9 @@ data P256Scalar
|
|||||||
data P256Y
|
data P256Y
|
||||||
data P256X
|
data P256X
|
||||||
|
|
||||||
|
order :: Integer
|
||||||
|
order = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- Point methods
|
-- Point methods
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
@ -109,7 +116,7 @@ pointAdd a b = withNewPoint $ \dx dy ->
|
|||||||
-- | Negate a point
|
-- | Negate a point
|
||||||
pointNegate :: Point -> Point
|
pointNegate :: Point -> Point
|
||||||
pointNegate a = withNewPoint $ \dx dy ->
|
pointNegate a = withNewPoint $ \dx dy ->
|
||||||
withPoint a $ \ax ay -> do
|
withPoint a $ \ax ay ->
|
||||||
ccryptonite_p256e_point_negate ax ay dx dy
|
ccryptonite_p256e_point_negate ax ay dx dy
|
||||||
|
|
||||||
-- | Multiply a point by a scalar
|
-- | Multiply a point by a scalar
|
||||||
@ -117,16 +124,16 @@ pointNegate a = withNewPoint $ \dx dy ->
|
|||||||
-- warning: variable time
|
-- warning: variable time
|
||||||
pointMul :: Scalar -> Point -> Point
|
pointMul :: Scalar -> Point -> Point
|
||||||
pointMul scalar p = withNewPoint $ \dx dy ->
|
pointMul scalar p = withNewPoint $ \dx dy ->
|
||||||
withScalar scalar $ \n -> withPoint p $ \px py -> withScalarZero $ \nzero ->
|
withScalar scalar $ \n -> withPoint p $ \px py ->
|
||||||
ccryptonite_p256_points_mul_vartime nzero n px py dx dy
|
ccryptonite_p256e_point_mul n px py dx dy
|
||||||
|
|
||||||
-- | Similar to 'pointMul', serializing the x coordinate as binary.
|
-- | Similar to 'pointMul', serializing the x coordinate as binary.
|
||||||
-- When scalar is multiple of point order the result is all zero.
|
-- When scalar is multiple of point order the result is all zero.
|
||||||
pointDh :: ByteArray binary => Scalar -> Point -> binary
|
pointDh :: ByteArray binary => Scalar -> Point -> binary
|
||||||
pointDh scalar p =
|
pointDh scalar p =
|
||||||
B.unsafeCreate scalarSize $ \dst -> withTempPoint $ \dx dy -> do
|
B.unsafeCreate scalarSize $ \dst -> withTempPoint $ \dx dy -> do
|
||||||
withScalar scalar $ \n -> withPoint p $ \px py -> withScalarZero $ \nzero ->
|
withScalar scalar $ \n -> withPoint p $ \px py ->
|
||||||
ccryptonite_p256_points_mul_vartime nzero n px py dx dy
|
ccryptonite_p256e_point_mul n px py dx dy
|
||||||
ccryptonite_p256_to_bin (castPtr dx) dst
|
ccryptonite_p256_to_bin (castPtr dx) dst
|
||||||
|
|
||||||
-- | multiply the point @p with @n2 and add a lifted to curve value @n1
|
-- | multiply the point @p with @n2 and add a lifted to curve value @n1
|
||||||
@ -145,6 +152,19 @@ pointIsValid p = unsafeDoIO $ withPoint p $ \px py -> do
|
|||||||
r <- ccryptonite_p256_is_valid_point px py
|
r <- ccryptonite_p256_is_valid_point px py
|
||||||
return (r /= 0)
|
return (r /= 0)
|
||||||
|
|
||||||
|
-- | Check if a 'Point' is the point at infinity
|
||||||
|
pointIsAtInfinity :: Point -> Bool
|
||||||
|
pointIsAtInfinity (Point b) = constAllZero b
|
||||||
|
|
||||||
|
-- | Return the x coordinate as a 'Scalar' if the point is not at infinity
|
||||||
|
pointX :: Point -> Maybe Scalar
|
||||||
|
pointX p
|
||||||
|
| pointIsAtInfinity p = Nothing
|
||||||
|
| otherwise = Just $
|
||||||
|
withNewScalarFreeze $ \d ->
|
||||||
|
withPoint p $ \px _ ->
|
||||||
|
ccryptonite_p256_mod ccryptonite_SECP256r1_n (castPtr px) (castPtr d)
|
||||||
|
|
||||||
-- | Convert a point to (x,y) Integers
|
-- | Convert a point to (x,y) Integers
|
||||||
pointToIntegers :: Point -> (Integer, Integer)
|
pointToIntegers :: Point -> (Integer, Integer)
|
||||||
pointToIntegers p = unsafeDoIO $ withPoint p $ \px py ->
|
pointToIntegers p = unsafeDoIO $ withPoint p $ \px py ->
|
||||||
@ -187,12 +207,12 @@ pointFromBinary ba = unsafePointFromBinary ba >>= validatePoint
|
|||||||
validatePoint :: Point -> CryptoFailable Point
|
validatePoint :: Point -> CryptoFailable Point
|
||||||
validatePoint p
|
validatePoint p
|
||||||
| pointIsValid p = CryptoPassed p
|
| pointIsValid p = CryptoPassed p
|
||||||
| otherwise = CryptoFailed $ CryptoError_PointCoordinatesInvalid
|
| otherwise = CryptoFailed CryptoError_PointCoordinatesInvalid
|
||||||
|
|
||||||
-- | Convert from binary to a point, possibly invalid
|
-- | Convert from binary to a point, possibly invalid
|
||||||
unsafePointFromBinary :: ByteArrayAccess ba => ba -> CryptoFailable Point
|
unsafePointFromBinary :: ByteArrayAccess ba => ba -> CryptoFailable Point
|
||||||
unsafePointFromBinary ba
|
unsafePointFromBinary ba
|
||||||
| B.length ba /= pointSize = CryptoFailed $ CryptoError_PublicKeySizeInvalid
|
| B.length ba /= pointSize = CryptoFailed CryptoError_PublicKeySizeInvalid
|
||||||
| otherwise =
|
| otherwise =
|
||||||
CryptoPassed $ withNewPoint $ \px py -> B.withByteArray ba $ \src -> do
|
CryptoPassed $ withNewPoint $ \px py -> B.withByteArray ba $ \src -> do
|
||||||
ccryptonite_p256_from_bin src (castPtr px)
|
ccryptonite_p256_from_bin src (castPtr px)
|
||||||
@ -215,6 +235,10 @@ scalarGenerate = unwrap . scalarFromBinary . witness <$> getRandomBytes 32
|
|||||||
scalarZero :: Scalar
|
scalarZero :: Scalar
|
||||||
scalarZero = withNewScalarFreeze $ \d -> ccryptonite_p256_init d
|
scalarZero = withNewScalarFreeze $ \d -> ccryptonite_p256_init d
|
||||||
|
|
||||||
|
-- | The scalar representing the curve order
|
||||||
|
scalarN :: Scalar
|
||||||
|
scalarN = throwCryptoError (scalarFromInteger order)
|
||||||
|
|
||||||
-- | Check if the scalar is 0
|
-- | Check if the scalar is 0
|
||||||
scalarIsZero :: Scalar -> Bool
|
scalarIsZero :: Scalar -> Bool
|
||||||
scalarIsZero s = unsafeDoIO $ withScalar s $ \d -> do
|
scalarIsZero s = unsafeDoIO $ withScalar s $ \d -> do
|
||||||
@ -237,6 +261,14 @@ scalarSub a b =
|
|||||||
withNewScalarFreeze $ \d -> withScalar a $ \pa -> withScalar b $ \pb ->
|
withNewScalarFreeze $ \d -> withScalar a $ \pa -> withScalar b $ \pb ->
|
||||||
ccryptonite_p256e_modsub ccryptonite_SECP256r1_n pa pb d
|
ccryptonite_p256e_modsub ccryptonite_SECP256r1_n pa pb d
|
||||||
|
|
||||||
|
-- | Perform multiplication between two scalars
|
||||||
|
--
|
||||||
|
-- > a * b
|
||||||
|
scalarMul :: Scalar -> Scalar -> Scalar
|
||||||
|
scalarMul a b =
|
||||||
|
withNewScalarFreeze $ \d -> withScalar a $ \pa -> withScalar b $ \pb ->
|
||||||
|
ccryptonite_p256_modmul ccryptonite_SECP256r1_n pa 0 pb d
|
||||||
|
|
||||||
-- | Give the inverse of the scalar
|
-- | Give the inverse of the scalar
|
||||||
--
|
--
|
||||||
-- > 1 / a
|
-- > 1 / a
|
||||||
@ -247,6 +279,14 @@ scalarInv a =
|
|||||||
withNewScalarFreeze $ \b -> withScalar a $ \pa ->
|
withNewScalarFreeze $ \b -> withScalar a $ \pa ->
|
||||||
ccryptonite_p256_modinv_vartime ccryptonite_SECP256r1_n pa b
|
ccryptonite_p256_modinv_vartime ccryptonite_SECP256r1_n pa b
|
||||||
|
|
||||||
|
-- | Give the inverse of the scalar using safe exponentiation
|
||||||
|
--
|
||||||
|
-- > 1 / a
|
||||||
|
scalarInvSafe :: Scalar -> Scalar
|
||||||
|
scalarInvSafe a =
|
||||||
|
withNewScalarFreeze $ \b -> withScalar a $ \pa ->
|
||||||
|
ccryptonite_p256e_scalar_invert pa b
|
||||||
|
|
||||||
-- | Compare 2 Scalar
|
-- | Compare 2 Scalar
|
||||||
scalarCmp :: Scalar -> Scalar -> Ordering
|
scalarCmp :: Scalar -> Scalar -> Ordering
|
||||||
scalarCmp a b = unsafeDoIO $
|
scalarCmp a b = unsafeDoIO $
|
||||||
@ -257,7 +297,7 @@ scalarCmp a b = unsafeDoIO $
|
|||||||
-- | convert a scalar from binary
|
-- | convert a scalar from binary
|
||||||
scalarFromBinary :: ByteArrayAccess ba => ba -> CryptoFailable Scalar
|
scalarFromBinary :: ByteArrayAccess ba => ba -> CryptoFailable Scalar
|
||||||
scalarFromBinary ba
|
scalarFromBinary ba
|
||||||
| B.length ba /= scalarSize = CryptoFailed $ CryptoError_SecretKeySizeInvalid
|
| B.length ba /= scalarSize = CryptoFailed CryptoError_SecretKeySizeInvalid
|
||||||
| otherwise =
|
| otherwise =
|
||||||
CryptoPassed $ withNewScalarFreeze $ \p -> B.withByteArray ba $ \b ->
|
CryptoPassed $ withNewScalarFreeze $ \p -> B.withByteArray ba $ \b ->
|
||||||
ccryptonite_p256_from_bin b p
|
ccryptonite_p256_from_bin b p
|
||||||
@ -298,18 +338,9 @@ withNewScalarFreeze f = Scalar $ B.allocAndFreeze scalarSize f
|
|||||||
withTempPoint :: (Ptr P256X -> Ptr P256Y -> IO a) -> IO a
|
withTempPoint :: (Ptr P256X -> Ptr P256Y -> IO a) -> IO a
|
||||||
withTempPoint f = allocTempScrubbed pointSize (\p -> let px = castPtr p in f px (pxToPy px))
|
withTempPoint f = allocTempScrubbed pointSize (\p -> let px = castPtr p in f px (pxToPy px))
|
||||||
|
|
||||||
withTempScalar :: (Ptr P256Scalar -> IO a) -> IO a
|
|
||||||
withTempScalar f = allocTempScrubbed scalarSize (f . castPtr)
|
|
||||||
|
|
||||||
withScalar :: Scalar -> (Ptr P256Scalar -> IO a) -> IO a
|
withScalar :: Scalar -> (Ptr P256Scalar -> IO a) -> IO a
|
||||||
withScalar (Scalar d) f = B.withByteArray d f
|
withScalar (Scalar d) f = B.withByteArray d f
|
||||||
|
|
||||||
withScalarZero :: (Ptr P256Scalar -> IO a) -> IO a
|
|
||||||
withScalarZero f =
|
|
||||||
withTempScalar $ \d -> do
|
|
||||||
ccryptonite_p256_init d
|
|
||||||
f d
|
|
||||||
|
|
||||||
allocTemp :: Int -> (Ptr Word8 -> IO a) -> IO a
|
allocTemp :: Int -> (Ptr Word8 -> IO a) -> IO a
|
||||||
allocTemp n f = ignoreSnd <$> B.allocRet n f
|
allocTemp n f = ignoreSnd <$> B.allocRet n f
|
||||||
where
|
where
|
||||||
@ -350,6 +381,8 @@ foreign import ccall "cryptonite_p256_mod"
|
|||||||
ccryptonite_p256_mod :: Ptr P256Scalar -> Ptr P256Scalar -> Ptr P256Scalar -> IO ()
|
ccryptonite_p256_mod :: Ptr P256Scalar -> Ptr P256Scalar -> Ptr P256Scalar -> IO ()
|
||||||
foreign import ccall "cryptonite_p256_modmul"
|
foreign import ccall "cryptonite_p256_modmul"
|
||||||
ccryptonite_p256_modmul :: Ptr P256Scalar -> Ptr P256Scalar -> P256Digit -> Ptr P256Scalar -> Ptr P256Scalar -> IO ()
|
ccryptonite_p256_modmul :: Ptr P256Scalar -> Ptr P256Scalar -> P256Digit -> Ptr P256Scalar -> Ptr P256Scalar -> IO ()
|
||||||
|
foreign import ccall "cryptonite_p256e_scalar_invert"
|
||||||
|
ccryptonite_p256e_scalar_invert :: Ptr P256Scalar -> Ptr P256Scalar -> IO ()
|
||||||
--foreign import ccall "cryptonite_p256_modinv"
|
--foreign import ccall "cryptonite_p256_modinv"
|
||||||
-- ccryptonite_p256_modinv :: Ptr P256Scalar -> Ptr P256Scalar -> Ptr P256Scalar -> IO ()
|
-- ccryptonite_p256_modinv :: Ptr P256Scalar -> Ptr P256Scalar -> Ptr P256Scalar -> IO ()
|
||||||
foreign import ccall "cryptonite_p256_modinv_vartime"
|
foreign import ccall "cryptonite_p256_modinv_vartime"
|
||||||
@ -370,6 +403,13 @@ foreign import ccall "cryptonite_p256e_point_negate"
|
|||||||
-> Ptr P256X -> Ptr P256Y
|
-> Ptr P256X -> Ptr P256Y
|
||||||
-> IO ()
|
-> IO ()
|
||||||
|
|
||||||
|
-- compute (out_x,out_y) = n * (in_x,in_y)
|
||||||
|
foreign import ccall "cryptonite_p256e_point_mul"
|
||||||
|
ccryptonite_p256e_point_mul :: Ptr P256Scalar -- n
|
||||||
|
-> Ptr P256X -> Ptr P256Y -- in_{x,y}
|
||||||
|
-> Ptr P256X -> Ptr P256Y -- out_{x,y}
|
||||||
|
-> IO ()
|
||||||
|
|
||||||
-- compute (out_x,out,y) = n1 * G + n2 * (in_x,in_y)
|
-- compute (out_x,out,y) = n1 * G + n2 * (in_x,in_y)
|
||||||
foreign import ccall "cryptonite_p256_points_mul_vartime"
|
foreign import ccall "cryptonite_p256_points_mul_vartime"
|
||||||
ccryptonite_p256_points_mul_vartime :: Ptr P256Scalar -- n1
|
ccryptonite_p256_points_mul_vartime :: Ptr P256Scalar -- n1
|
||||||
|
|||||||
272
Crypto/PubKey/ECDSA.hs
Normal file
272
Crypto/PubKey/ECDSA.hs
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
-- |
|
||||||
|
-- Module : Crypto.PubKey.ECDSA
|
||||||
|
-- License : BSD-style
|
||||||
|
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
|
||||||
|
-- Stability : experimental
|
||||||
|
-- Portability : unknown
|
||||||
|
--
|
||||||
|
-- Elliptic Curve Digital Signature Algorithm, with the parameterized
|
||||||
|
-- curve implementations provided by module "Crypto.ECC".
|
||||||
|
--
|
||||||
|
-- Public/private key pairs can be generated using
|
||||||
|
-- 'curveGenerateKeyPair' or decoded from binary.
|
||||||
|
--
|
||||||
|
-- /WARNING:/ Only curve P-256 has constant-time implementation.
|
||||||
|
-- Signature operations with P-384 and P-521 may leak the private key.
|
||||||
|
--
|
||||||
|
-- Signature verification should be safe for all curves.
|
||||||
|
{-# LANGUAGE BangPatterns #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
{-# LANGUAGE StandaloneDeriving #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
module Crypto.PubKey.ECDSA
|
||||||
|
( EllipticCurveECDSA (..)
|
||||||
|
-- * Public keys
|
||||||
|
, PublicKey
|
||||||
|
, encodePublic
|
||||||
|
, decodePublic
|
||||||
|
, toPublic
|
||||||
|
-- * Private keys
|
||||||
|
, PrivateKey
|
||||||
|
, encodePrivate
|
||||||
|
, decodePrivate
|
||||||
|
-- * Signatures
|
||||||
|
, Signature(..)
|
||||||
|
, signatureFromIntegers
|
||||||
|
, signatureToIntegers
|
||||||
|
-- * Generation and verification
|
||||||
|
, signWith
|
||||||
|
, signDigestWith
|
||||||
|
, sign
|
||||||
|
, signDigest
|
||||||
|
, verify
|
||||||
|
, verifyDigest
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
|
||||||
|
import Crypto.ECC
|
||||||
|
import qualified Crypto.ECC.Simple.Types as Simple
|
||||||
|
import Crypto.Error
|
||||||
|
import Crypto.Hash
|
||||||
|
import Crypto.Hash.Types
|
||||||
|
import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess)
|
||||||
|
import Crypto.Internal.Imports
|
||||||
|
import Crypto.Number.ModArithmetic (inverseFermat)
|
||||||
|
import qualified Crypto.PubKey.ECC.P256 as P256
|
||||||
|
import Crypto.Random.Types
|
||||||
|
|
||||||
|
import Data.Bits
|
||||||
|
import qualified Data.ByteArray as B
|
||||||
|
import Data.Data
|
||||||
|
|
||||||
|
import Foreign.Ptr (Ptr)
|
||||||
|
import Foreign.Storable (peekByteOff, pokeByteOff)
|
||||||
|
|
||||||
|
-- | Represent a ECDSA signature namely R and S.
|
||||||
|
data Signature curve = Signature
|
||||||
|
{ sign_r :: Scalar curve -- ^ ECDSA r
|
||||||
|
, sign_s :: Scalar curve -- ^ ECDSA s
|
||||||
|
}
|
||||||
|
|
||||||
|
deriving instance Eq (Scalar curve) => Eq (Signature curve)
|
||||||
|
deriving instance Show (Scalar curve) => Show (Signature curve)
|
||||||
|
|
||||||
|
instance NFData (Scalar curve) => NFData (Signature curve) where
|
||||||
|
rnf (Signature r s) = rnf r `seq` rnf s `seq` ()
|
||||||
|
|
||||||
|
-- | ECDSA Public Key.
|
||||||
|
type PublicKey curve = Point curve
|
||||||
|
|
||||||
|
-- | ECDSA Private Key.
|
||||||
|
type PrivateKey curve = Scalar curve
|
||||||
|
|
||||||
|
-- | Elliptic curves with ECDSA capabilities.
|
||||||
|
class EllipticCurveBasepointArith curve => EllipticCurveECDSA curve where
|
||||||
|
-- | Is a scalar in the accepted range for ECDSA
|
||||||
|
scalarIsValid :: proxy curve -> Scalar curve -> Bool
|
||||||
|
|
||||||
|
-- | Test whether the scalar is zero
|
||||||
|
scalarIsZero :: proxy curve -> Scalar curve -> Bool
|
||||||
|
scalarIsZero prx s = s == throwCryptoError (scalarFromInteger prx 0)
|
||||||
|
|
||||||
|
-- | Scalar inversion modulo the curve order
|
||||||
|
scalarInv :: proxy curve -> Scalar curve -> Maybe (Scalar curve)
|
||||||
|
|
||||||
|
-- | Return the point X coordinate as a scalar
|
||||||
|
pointX :: proxy curve -> Point curve -> Maybe (Scalar curve)
|
||||||
|
|
||||||
|
instance EllipticCurveECDSA Curve_P256R1 where
|
||||||
|
scalarIsValid _ s = not (P256.scalarIsZero s)
|
||||||
|
&& P256.scalarCmp s P256.scalarN == LT
|
||||||
|
|
||||||
|
scalarIsZero _ = P256.scalarIsZero
|
||||||
|
|
||||||
|
scalarInv _ s = let inv = P256.scalarInvSafe s
|
||||||
|
in if P256.scalarIsZero inv then Nothing else Just inv
|
||||||
|
|
||||||
|
pointX _ = P256.pointX
|
||||||
|
|
||||||
|
instance EllipticCurveECDSA Curve_P384R1 where
|
||||||
|
scalarIsValid _ = ecScalarIsValid (Proxy :: Proxy Simple.SEC_p384r1)
|
||||||
|
|
||||||
|
scalarIsZero _ = ecScalarIsZero
|
||||||
|
|
||||||
|
scalarInv _ = ecScalarInv (Proxy :: Proxy Simple.SEC_p384r1)
|
||||||
|
|
||||||
|
pointX _ = ecPointX (Proxy :: Proxy Simple.SEC_p384r1)
|
||||||
|
|
||||||
|
instance EllipticCurveECDSA Curve_P521R1 where
|
||||||
|
scalarIsValid _ = ecScalarIsValid (Proxy :: Proxy Simple.SEC_p521r1)
|
||||||
|
|
||||||
|
scalarIsZero _ = ecScalarIsZero
|
||||||
|
|
||||||
|
scalarInv _ = ecScalarInv (Proxy :: Proxy Simple.SEC_p521r1)
|
||||||
|
|
||||||
|
pointX _ = ecPointX (Proxy :: Proxy Simple.SEC_p521r1)
|
||||||
|
|
||||||
|
|
||||||
|
-- | Create a signature from integers (R, S).
|
||||||
|
signatureFromIntegers :: EllipticCurveECDSA curve
|
||||||
|
=> proxy curve -> (Integer, Integer) -> CryptoFailable (Signature curve)
|
||||||
|
signatureFromIntegers prx (r, s) =
|
||||||
|
liftA2 Signature (scalarFromInteger prx r) (scalarFromInteger prx s)
|
||||||
|
|
||||||
|
-- | Get integers (R, S) from a signature.
|
||||||
|
--
|
||||||
|
-- The values can then be used to encode the signature to binary with
|
||||||
|
-- ASN.1.
|
||||||
|
signatureToIntegers :: EllipticCurveECDSA curve
|
||||||
|
=> proxy curve -> Signature curve -> (Integer, Integer)
|
||||||
|
signatureToIntegers prx sig =
|
||||||
|
(scalarToInteger prx $ sign_r sig, scalarToInteger prx $ sign_s sig)
|
||||||
|
|
||||||
|
-- | Encode a public key into binary form, i.e. the uncompressed encoding
|
||||||
|
-- referenced from <https://tools.ietf.org/html/rfc5480 RFC 5480> section 2.2.
|
||||||
|
encodePublic :: (EllipticCurve curve, ByteArray bs)
|
||||||
|
=> proxy curve -> PublicKey curve -> bs
|
||||||
|
encodePublic = encodePoint
|
||||||
|
|
||||||
|
-- | Try to decode the binary form of a public key.
|
||||||
|
decodePublic :: (EllipticCurve curve, ByteArray bs)
|
||||||
|
=> proxy curve -> bs -> CryptoFailable (PublicKey curve)
|
||||||
|
decodePublic = decodePoint
|
||||||
|
|
||||||
|
-- | Encode a private key into binary form, i.e. the @privateKey@ field
|
||||||
|
-- described in <https://tools.ietf.org/html/rfc5915 RFC 5915>.
|
||||||
|
encodePrivate :: (EllipticCurveECDSA curve, ByteArray bs)
|
||||||
|
=> proxy curve -> PrivateKey curve -> bs
|
||||||
|
encodePrivate = encodeScalar
|
||||||
|
|
||||||
|
-- | Try to decode the binary form of a private key.
|
||||||
|
decodePrivate :: (EllipticCurveECDSA curve, ByteArray bs)
|
||||||
|
=> proxy curve -> bs -> CryptoFailable (PrivateKey curve)
|
||||||
|
decodePrivate = decodeScalar
|
||||||
|
|
||||||
|
-- | Create a public key from a private key.
|
||||||
|
toPublic :: EllipticCurveECDSA curve
|
||||||
|
=> proxy curve -> PrivateKey curve -> PublicKey curve
|
||||||
|
toPublic = pointBaseSmul
|
||||||
|
|
||||||
|
-- | Sign digest using the private key and an explicit k scalar.
|
||||||
|
signDigestWith :: (EllipticCurveECDSA curve, HashAlgorithm hash)
|
||||||
|
=> proxy curve -> Scalar curve -> PrivateKey curve -> Digest hash -> Maybe (Signature curve)
|
||||||
|
signDigestWith prx k d digest = do
|
||||||
|
let z = tHashDigest prx digest
|
||||||
|
point = pointBaseSmul prx k
|
||||||
|
r <- pointX prx point
|
||||||
|
kInv <- scalarInv prx k
|
||||||
|
let s = scalarMul prx kInv (scalarAdd prx z (scalarMul prx r d))
|
||||||
|
when (scalarIsZero prx r || scalarIsZero prx s) Nothing
|
||||||
|
return $ Signature r s
|
||||||
|
|
||||||
|
-- | Sign message using the private key and an explicit k scalar.
|
||||||
|
signWith :: (EllipticCurveECDSA curve, ByteArrayAccess msg, HashAlgorithm hash)
|
||||||
|
=> proxy curve -> Scalar curve -> PrivateKey curve -> hash -> msg -> Maybe (Signature curve)
|
||||||
|
signWith prx k d hashAlg msg = signDigestWith prx k d (hashWith hashAlg msg)
|
||||||
|
|
||||||
|
-- | Sign a digest using hash and private key.
|
||||||
|
signDigest :: (EllipticCurveECDSA curve, MonadRandom m, HashAlgorithm hash)
|
||||||
|
=> proxy curve -> PrivateKey curve -> Digest hash -> m (Signature curve)
|
||||||
|
signDigest prx pk digest = do
|
||||||
|
k <- curveGenerateScalar prx
|
||||||
|
case signDigestWith prx k pk digest of
|
||||||
|
Nothing -> signDigest prx pk digest
|
||||||
|
Just sig -> return sig
|
||||||
|
|
||||||
|
-- | Sign a message using hash and private key.
|
||||||
|
sign :: (EllipticCurveECDSA curve, MonadRandom m, ByteArrayAccess msg, HashAlgorithm hash)
|
||||||
|
=> proxy curve -> PrivateKey curve -> hash -> msg -> m (Signature curve)
|
||||||
|
sign prx pk hashAlg msg = signDigest prx pk (hashWith hashAlg msg)
|
||||||
|
|
||||||
|
-- | Verify a digest using hash and public key.
|
||||||
|
verifyDigest :: (EllipticCurveECDSA curve, HashAlgorithm hash)
|
||||||
|
=> proxy curve -> PublicKey curve -> Signature curve -> Digest hash -> Bool
|
||||||
|
verifyDigest prx q (Signature r s) digest
|
||||||
|
| not (scalarIsValid prx r) = False
|
||||||
|
| not (scalarIsValid prx s) = False
|
||||||
|
| otherwise = maybe False (r ==) $ do
|
||||||
|
w <- scalarInv prx s
|
||||||
|
let z = tHashDigest prx digest
|
||||||
|
u1 = scalarMul prx z w
|
||||||
|
u2 = scalarMul prx r w
|
||||||
|
x = pointsSmulVarTime prx u1 u2 q
|
||||||
|
pointX prx x
|
||||||
|
-- Note: precondition q /= PointO is not tested because we assume
|
||||||
|
-- point decoding never decodes point at infinity.
|
||||||
|
|
||||||
|
-- | Verify a signature using hash and public key.
|
||||||
|
verify :: (EllipticCurveECDSA curve, ByteArrayAccess msg, HashAlgorithm hash)
|
||||||
|
=> proxy curve -> hash -> PublicKey curve -> Signature curve -> msg -> Bool
|
||||||
|
verify prx hashAlg q sig msg = verifyDigest prx q sig (hashWith hashAlg msg)
|
||||||
|
|
||||||
|
-- | Truncate a digest based on curve order size.
|
||||||
|
tHashDigest :: (EllipticCurveECDSA curve, HashAlgorithm hash)
|
||||||
|
=> proxy curve -> Digest hash -> Scalar curve
|
||||||
|
tHashDigest prx (Digest digest) = throwCryptoError $ decodeScalar prx encoded
|
||||||
|
where m = curveOrderBits prx
|
||||||
|
d = m - B.length digest * 8
|
||||||
|
(n, r) = m `divMod` 8
|
||||||
|
n' = if r > 0 then succ n else n
|
||||||
|
|
||||||
|
encoded
|
||||||
|
| d > 0 = B.zero (n' - B.length digest) `B.append` digest
|
||||||
|
| d == 0 = digest
|
||||||
|
| r == 0 = B.take n digest
|
||||||
|
| otherwise = shiftBytes digest
|
||||||
|
|
||||||
|
shiftBytes bs = B.allocAndFreeze n' $ \dst ->
|
||||||
|
B.withByteArray bs $ \src -> go dst src 0 0
|
||||||
|
|
||||||
|
go :: Ptr Word8 -> Ptr Word8 -> Word8 -> Int -> IO ()
|
||||||
|
go dst src !a i
|
||||||
|
| i >= n' = return ()
|
||||||
|
| otherwise = do
|
||||||
|
b <- peekByteOff src i
|
||||||
|
pokeByteOff dst i (unsafeShiftR b (8 - r) .|. unsafeShiftL a r)
|
||||||
|
go dst src b (succ i)
|
||||||
|
|
||||||
|
|
||||||
|
ecScalarIsValid :: Simple.Curve c => proxy c -> Simple.Scalar c -> Bool
|
||||||
|
ecScalarIsValid prx (Simple.Scalar s) = s > 0 && s < n
|
||||||
|
where n = Simple.curveEccN $ Simple.curveParameters prx
|
||||||
|
|
||||||
|
ecScalarIsZero :: forall curve . Simple.Curve curve
|
||||||
|
=> Simple.Scalar curve -> Bool
|
||||||
|
ecScalarIsZero (Simple.Scalar a) = a == 0
|
||||||
|
|
||||||
|
ecScalarInv :: Simple.Curve c
|
||||||
|
=> proxy c -> Simple.Scalar c -> Maybe (Simple.Scalar c)
|
||||||
|
ecScalarInv prx (Simple.Scalar s)
|
||||||
|
| i == 0 = Nothing
|
||||||
|
| otherwise = Just $ Simple.Scalar i
|
||||||
|
where n = Simple.curveEccN $ Simple.curveParameters prx
|
||||||
|
i = inverseFermat s n
|
||||||
|
|
||||||
|
ecPointX :: Simple.Curve c
|
||||||
|
=> proxy c -> Simple.Point c -> Maybe (Simple.Scalar c)
|
||||||
|
ecPointX _ Simple.PointO = Nothing
|
||||||
|
ecPointX prx (Simple.Point x _) = Just (Simple.Scalar $ x `mod` n)
|
||||||
|
where n = Simple.curveEccN $ Simple.curveParameters prx
|
||||||
390
Crypto/PubKey/EdDSA.hs
Normal file
390
Crypto/PubKey/EdDSA.hs
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
-- |
|
||||||
|
-- Module : Crypto.PubKey.EdDSA
|
||||||
|
-- License : BSD-style
|
||||||
|
-- Maintainer : Olivier Chéron <olivier.cheron@gmail.com>
|
||||||
|
-- Stability : experimental
|
||||||
|
-- Portability : unknown
|
||||||
|
--
|
||||||
|
-- EdDSA signature generation and verification, implemented in Haskell and
|
||||||
|
-- parameterized with elliptic curve and hash algorithm. Only edwards25519 is
|
||||||
|
-- supported at the moment.
|
||||||
|
--
|
||||||
|
-- The module provides \"context\" and \"prehash\" variants defined in
|
||||||
|
-- <https://tools.ietf.org/html/rfc8032 RFC 8032>.
|
||||||
|
--
|
||||||
|
-- This implementation is most useful when wanting to customize the hash
|
||||||
|
-- algorithm. See module "Crypto.PubKey.Ed25519" for faster Ed25519 with
|
||||||
|
-- SHA-512.
|
||||||
|
--
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
module Crypto.PubKey.EdDSA
|
||||||
|
( SecretKey
|
||||||
|
, PublicKey
|
||||||
|
, Signature
|
||||||
|
-- * Curves with EdDSA implementation
|
||||||
|
, EllipticCurveEdDSA(CurveDigestSize)
|
||||||
|
, publicKeySize
|
||||||
|
, secretKeySize
|
||||||
|
, signatureSize
|
||||||
|
-- * Smart constructors
|
||||||
|
, signature
|
||||||
|
, publicKey
|
||||||
|
, secretKey
|
||||||
|
-- * Methods
|
||||||
|
, toPublic
|
||||||
|
, sign
|
||||||
|
, signCtx
|
||||||
|
, signPh
|
||||||
|
, verify
|
||||||
|
, verifyCtx
|
||||||
|
, verifyPh
|
||||||
|
, generateSecretKey
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Bits
|
||||||
|
import Data.ByteArray (ByteArray, ByteArrayAccess, Bytes, ScrubbedBytes, View)
|
||||||
|
import qualified Data.ByteArray as B
|
||||||
|
import Data.ByteString (ByteString)
|
||||||
|
import Data.Proxy
|
||||||
|
|
||||||
|
import Crypto.ECC
|
||||||
|
import qualified Crypto.ECC.Edwards25519 as Edwards25519
|
||||||
|
import Crypto.Error
|
||||||
|
import Crypto.Hash (Digest)
|
||||||
|
import Crypto.Hash.IO
|
||||||
|
import Crypto.Random
|
||||||
|
|
||||||
|
import GHC.TypeLits (KnownNat, Nat)
|
||||||
|
|
||||||
|
import Crypto.Internal.Builder
|
||||||
|
import Crypto.Internal.Compat
|
||||||
|
import Crypto.Internal.Imports
|
||||||
|
import Crypto.Internal.Nat (integralNatVal)
|
||||||
|
|
||||||
|
import Foreign.Storable
|
||||||
|
|
||||||
|
|
||||||
|
-- API
|
||||||
|
|
||||||
|
-- | An EdDSA Secret key
|
||||||
|
newtype SecretKey curve = SecretKey ScrubbedBytes
|
||||||
|
deriving (Show,Eq,ByteArrayAccess,NFData)
|
||||||
|
|
||||||
|
-- | An EdDSA public key
|
||||||
|
newtype PublicKey curve hash = PublicKey Bytes
|
||||||
|
deriving (Show,Eq,ByteArrayAccess,NFData)
|
||||||
|
|
||||||
|
-- | An EdDSA signature
|
||||||
|
newtype Signature curve hash = Signature Bytes
|
||||||
|
deriving (Show,Eq,ByteArrayAccess,NFData)
|
||||||
|
|
||||||
|
-- | Elliptic curves with an implementation of EdDSA
|
||||||
|
class ( EllipticCurveBasepointArith curve
|
||||||
|
, KnownNat (CurveDigestSize curve)
|
||||||
|
) => EllipticCurveEdDSA curve where
|
||||||
|
|
||||||
|
-- | Size of the digest for this curve (in bytes)
|
||||||
|
type CurveDigestSize curve :: Nat
|
||||||
|
|
||||||
|
-- | Size of secret keys for this curve (in bytes)
|
||||||
|
secretKeySize :: proxy curve -> Int
|
||||||
|
|
||||||
|
-- hash with specified parameters
|
||||||
|
hashWithDom :: (HashAlgorithm hash, ByteArrayAccess ctx, ByteArrayAccess msg)
|
||||||
|
=> proxy curve -> hash -> Bool -> ctx -> Builder -> msg -> Bytes
|
||||||
|
|
||||||
|
-- conversion between scalar, point and public key
|
||||||
|
pointPublic :: proxy curve -> Point curve -> PublicKey curve hash
|
||||||
|
publicPoint :: proxy curve -> PublicKey curve hash -> CryptoFailable (Point curve)
|
||||||
|
encodeScalarLE :: ByteArray bs => proxy curve -> Scalar curve -> bs
|
||||||
|
decodeScalarLE :: ByteArrayAccess bs => proxy curve -> bs -> CryptoFailable (Scalar curve)
|
||||||
|
|
||||||
|
-- how to use bits in a secret key
|
||||||
|
scheduleSecret :: ( HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
)
|
||||||
|
=> proxy curve
|
||||||
|
-> hash
|
||||||
|
-> SecretKey curve
|
||||||
|
-> (Scalar curve, View Bytes)
|
||||||
|
|
||||||
|
-- | Size of public keys for this curve (in bytes)
|
||||||
|
publicKeySize :: EllipticCurveEdDSA curve => proxy curve -> Int
|
||||||
|
publicKeySize prx = signatureSize prx `div` 2
|
||||||
|
|
||||||
|
-- | Size of signatures for this curve (in bytes)
|
||||||
|
signatureSize :: forall proxy curve . EllipticCurveEdDSA curve
|
||||||
|
=> proxy curve -> Int
|
||||||
|
signatureSize _ = integralNatVal (Proxy :: Proxy (CurveDigestSize curve))
|
||||||
|
|
||||||
|
|
||||||
|
-- Constructors
|
||||||
|
|
||||||
|
-- | Try to build a public key from a bytearray
|
||||||
|
publicKey :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ba
|
||||||
|
)
|
||||||
|
=> proxy curve -> hash -> ba -> CryptoFailable (PublicKey curve hash)
|
||||||
|
publicKey prx _ bs
|
||||||
|
| B.length bs == publicKeySize prx =
|
||||||
|
CryptoPassed (PublicKey $ B.convert bs)
|
||||||
|
| otherwise =
|
||||||
|
CryptoFailed CryptoError_PublicKeySizeInvalid
|
||||||
|
|
||||||
|
-- | Try to build a secret key from a bytearray
|
||||||
|
secretKey :: (EllipticCurveEdDSA curve, ByteArrayAccess ba)
|
||||||
|
=> proxy curve -> ba -> CryptoFailable (SecretKey curve)
|
||||||
|
secretKey prx bs
|
||||||
|
| B.length bs == secretKeySize prx =
|
||||||
|
CryptoPassed (SecretKey $ B.convert bs)
|
||||||
|
| otherwise =
|
||||||
|
CryptoFailed CryptoError_SecretKeyStructureInvalid
|
||||||
|
|
||||||
|
-- | Try to build a signature from a bytearray
|
||||||
|
signature :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ba
|
||||||
|
)
|
||||||
|
=> proxy curve -> hash -> ba -> CryptoFailable (Signature curve hash)
|
||||||
|
signature prx _ bs
|
||||||
|
| B.length bs == signatureSize prx =
|
||||||
|
CryptoPassed (Signature $ B.convert bs)
|
||||||
|
| otherwise =
|
||||||
|
CryptoFailed CryptoError_SecretKeyStructureInvalid
|
||||||
|
|
||||||
|
|
||||||
|
-- Conversions
|
||||||
|
|
||||||
|
-- | Generate a secret key
|
||||||
|
generateSecretKey :: (EllipticCurveEdDSA curve, MonadRandom m)
|
||||||
|
=> proxy curve -> m (SecretKey curve)
|
||||||
|
generateSecretKey prx = SecretKey <$> getRandomBytes (secretKeySize prx)
|
||||||
|
|
||||||
|
-- | Create a public key from a secret key
|
||||||
|
toPublic :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
)
|
||||||
|
=> proxy curve -> hash -> SecretKey curve -> PublicKey curve hash
|
||||||
|
toPublic prx alg priv =
|
||||||
|
let p = pointBaseSmul prx (secretScalar prx alg priv)
|
||||||
|
in pointPublic prx p
|
||||||
|
|
||||||
|
secretScalar :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
)
|
||||||
|
=> proxy curve -> hash -> SecretKey curve -> Scalar curve
|
||||||
|
secretScalar prx alg priv = fst (scheduleSecret prx alg priv)
|
||||||
|
|
||||||
|
|
||||||
|
-- EdDSA signature generation & verification
|
||||||
|
|
||||||
|
-- | Sign a message using the key pair
|
||||||
|
sign :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess msg
|
||||||
|
)
|
||||||
|
=> proxy curve -> SecretKey curve -> PublicKey curve hash -> msg -> Signature curve hash
|
||||||
|
sign prx = signCtx prx emptyCtx
|
||||||
|
|
||||||
|
-- | Verify a message
|
||||||
|
verify :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess msg
|
||||||
|
)
|
||||||
|
=> proxy curve -> PublicKey curve hash -> msg -> Signature curve hash -> Bool
|
||||||
|
verify prx = verifyCtx prx emptyCtx
|
||||||
|
|
||||||
|
-- | Sign a message using the key pair under context @ctx@
|
||||||
|
signCtx :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ctx
|
||||||
|
, ByteArrayAccess msg
|
||||||
|
)
|
||||||
|
=> proxy curve -> ctx -> SecretKey curve -> PublicKey curve hash -> msg -> Signature curve hash
|
||||||
|
signCtx prx = signPhCtx prx False
|
||||||
|
|
||||||
|
-- | Verify a message under context @ctx@
|
||||||
|
verifyCtx :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ctx
|
||||||
|
, ByteArrayAccess msg
|
||||||
|
)
|
||||||
|
=> proxy curve -> ctx -> PublicKey curve hash -> msg -> Signature curve hash -> Bool
|
||||||
|
verifyCtx prx = verifyPhCtx prx False
|
||||||
|
|
||||||
|
-- | Sign a prehashed message using the key pair under context @ctx@
|
||||||
|
signPh :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ctx
|
||||||
|
)
|
||||||
|
=> proxy curve -> ctx -> SecretKey curve -> PublicKey curve hash -> Digest prehash -> Signature curve hash
|
||||||
|
signPh prx = signPhCtx prx True
|
||||||
|
|
||||||
|
-- | Verify a prehashed message under context @ctx@
|
||||||
|
verifyPh :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ctx
|
||||||
|
)
|
||||||
|
=> proxy curve -> ctx -> PublicKey curve hash -> Digest prehash -> Signature curve hash -> Bool
|
||||||
|
verifyPh prx = verifyPhCtx prx True
|
||||||
|
|
||||||
|
signPhCtx :: forall proxy curve hash ctx msg .
|
||||||
|
( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ctx
|
||||||
|
, ByteArrayAccess msg
|
||||||
|
)
|
||||||
|
=> proxy curve -> Bool -> ctx -> SecretKey curve -> PublicKey curve hash -> msg -> Signature curve hash
|
||||||
|
signPhCtx prx ph ctx priv pub msg =
|
||||||
|
let alg = undefined :: hash
|
||||||
|
(s, prefix) = scheduleSecret prx alg priv
|
||||||
|
digR = hashWithDom prx alg ph ctx (bytes prefix) msg
|
||||||
|
r = decodeScalarNoErr prx digR
|
||||||
|
pR = pointBaseSmul prx r
|
||||||
|
bsR = encodePoint prx pR
|
||||||
|
sK = getK prx ph ctx pub bsR msg
|
||||||
|
sS = scalarAdd prx r (scalarMul prx sK s)
|
||||||
|
in encodeSignature prx (bsR, pR, sS)
|
||||||
|
|
||||||
|
verifyPhCtx :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ctx
|
||||||
|
, ByteArrayAccess msg
|
||||||
|
)
|
||||||
|
=> proxy curve -> Bool -> ctx -> PublicKey curve hash -> msg -> Signature curve hash -> Bool
|
||||||
|
verifyPhCtx prx ph ctx pub msg sig =
|
||||||
|
case doVerify of
|
||||||
|
CryptoPassed verified -> verified
|
||||||
|
CryptoFailed _ -> False
|
||||||
|
where
|
||||||
|
doVerify = do
|
||||||
|
(bsR, pR, sS) <- decodeSignature prx sig
|
||||||
|
nPub <- pointNegate prx `fmap` publicPoint prx pub
|
||||||
|
let sK = getK prx ph ctx pub bsR msg
|
||||||
|
pR' = pointsSmulVarTime prx sS sK nPub
|
||||||
|
return (pR == pR')
|
||||||
|
|
||||||
|
emptyCtx :: Bytes
|
||||||
|
emptyCtx = B.empty
|
||||||
|
|
||||||
|
getK :: forall proxy curve hash ctx msg .
|
||||||
|
( EllipticCurveEdDSA curve
|
||||||
|
, HashAlgorithm hash
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
, ByteArrayAccess ctx
|
||||||
|
, ByteArrayAccess msg
|
||||||
|
)
|
||||||
|
=> proxy curve -> Bool -> ctx -> PublicKey curve hash -> Bytes -> msg -> Scalar curve
|
||||||
|
getK prx ph ctx (PublicKey pub) bsR msg =
|
||||||
|
let alg = undefined :: hash
|
||||||
|
digK = hashWithDom prx alg ph ctx (bytes bsR <> bytes pub) msg
|
||||||
|
in decodeScalarNoErr prx digK
|
||||||
|
|
||||||
|
encodeSignature :: EllipticCurveEdDSA curve
|
||||||
|
=> proxy curve
|
||||||
|
-> (Bytes, Point curve, Scalar curve)
|
||||||
|
-> Signature curve hash
|
||||||
|
encodeSignature prx (bsR, _, sS) = Signature $ buildAndFreeze $
|
||||||
|
bytes bsR <> bytes bsS <> zero len0
|
||||||
|
where
|
||||||
|
bsS = encodeScalarLE prx sS :: Bytes
|
||||||
|
len0 = signatureSize prx - B.length bsR - B.length bsS
|
||||||
|
|
||||||
|
decodeSignature :: ( EllipticCurveEdDSA curve
|
||||||
|
, HashDigestSize hash ~ CurveDigestSize curve
|
||||||
|
)
|
||||||
|
=> proxy curve
|
||||||
|
-> Signature curve hash
|
||||||
|
-> CryptoFailable (Bytes, Point curve, Scalar curve)
|
||||||
|
decodeSignature prx (Signature bs) = do
|
||||||
|
let (bsR, bsS) = B.splitAt (publicKeySize prx) bs
|
||||||
|
pR <- decodePoint prx bsR
|
||||||
|
sS <- decodeScalarLE prx bsS
|
||||||
|
return (bsR, pR, sS)
|
||||||
|
|
||||||
|
-- implementations are supposed to decode any scalar up to the size of the digest
|
||||||
|
decodeScalarNoErr :: (EllipticCurveEdDSA curve, ByteArrayAccess bs)
|
||||||
|
=> proxy curve -> bs -> Scalar curve
|
||||||
|
decodeScalarNoErr prx = unwrap "decodeScalarNoErr" . decodeScalarLE prx
|
||||||
|
|
||||||
|
unwrap :: String -> CryptoFailable a -> a
|
||||||
|
unwrap name (CryptoFailed _) = error (name ++ ": assumption failed")
|
||||||
|
unwrap _ (CryptoPassed x) = x
|
||||||
|
|
||||||
|
|
||||||
|
-- Ed25519 implementation
|
||||||
|
|
||||||
|
instance EllipticCurveEdDSA Curve_Edwards25519 where
|
||||||
|
type CurveDigestSize Curve_Edwards25519 = 64
|
||||||
|
secretKeySize _ = 32
|
||||||
|
|
||||||
|
hashWithDom _ alg ph ctx bss
|
||||||
|
| not ph && B.null ctx = digestDomMsg alg bss
|
||||||
|
| otherwise = digestDomMsg alg (dom <> bss)
|
||||||
|
where dom = bytes ("SigEd25519 no Ed25519 collisions" :: ByteString) <>
|
||||||
|
byte (if ph then 1 else 0) <>
|
||||||
|
byte (fromIntegral $ B.length ctx) <>
|
||||||
|
bytes ctx
|
||||||
|
|
||||||
|
pointPublic _ = PublicKey . Edwards25519.pointEncode
|
||||||
|
publicPoint _ = Edwards25519.pointDecode
|
||||||
|
encodeScalarLE _ = Edwards25519.scalarEncode
|
||||||
|
decodeScalarLE _ = Edwards25519.scalarDecodeLong
|
||||||
|
|
||||||
|
scheduleSecret prx alg priv =
|
||||||
|
(decodeScalarNoErr prx clamped, B.dropView hashed 32)
|
||||||
|
where
|
||||||
|
hashed = digest alg $ \update -> update priv
|
||||||
|
|
||||||
|
clamped :: Bytes
|
||||||
|
clamped = B.copyAndFreeze (B.takeView hashed 32) $ \p -> do
|
||||||
|
b0 <- peekElemOff p 0 :: IO Word8
|
||||||
|
b31 <- peekElemOff p 31 :: IO Word8
|
||||||
|
pokeElemOff p 31 ((b31 .&. 0x7F) .|. 0x40)
|
||||||
|
pokeElemOff p 0 (b0 .&. 0xF8)
|
||||||
|
|
||||||
|
|
||||||
|
{-
|
||||||
|
Optimize hashing by limiting the number of roundtrips between Haskell and C.
|
||||||
|
Hash "update" functions do not use unsafe FFI call, so better concanetate
|
||||||
|
small fragments together and call the update function once.
|
||||||
|
|
||||||
|
Using the IO hash interface avoids context buffer copies.
|
||||||
|
|
||||||
|
Data type Digest is not used directly but converted to Bytes early. Any use of
|
||||||
|
withByteArray on the unpinned Digest backend would require copy through a
|
||||||
|
pinned trampoline.
|
||||||
|
-}
|
||||||
|
|
||||||
|
digestDomMsg :: (HashAlgorithm alg, ByteArrayAccess msg)
|
||||||
|
=> alg -> Builder -> msg -> Bytes
|
||||||
|
digestDomMsg alg bss bs = digest alg $ \update ->
|
||||||
|
update (buildAndFreeze bss :: Bytes) >> update bs
|
||||||
|
|
||||||
|
digest :: HashAlgorithm alg
|
||||||
|
=> alg
|
||||||
|
-> ((forall bs . ByteArrayAccess bs => bs -> IO ()) -> IO ())
|
||||||
|
-> Bytes
|
||||||
|
digest alg fn = B.convert $ unsafeDoIO $ do
|
||||||
|
mc <- hashMutableInitWith alg
|
||||||
|
fn (hashMutableUpdate mc)
|
||||||
|
hashMutableFinalize mc
|
||||||
@ -80,6 +80,13 @@ drgNewSeed (Seed seed) = initialize seed
|
|||||||
--
|
--
|
||||||
-- It can also be used in other contexts provided the input
|
-- It can also be used in other contexts provided the input
|
||||||
-- has been properly randomly generated.
|
-- has been properly randomly generated.
|
||||||
|
--
|
||||||
|
-- Note that the @Arbitrary@ instance provided by QuickCheck for 'Word64' does
|
||||||
|
-- not have a uniform distribution. It is often better to use instead
|
||||||
|
-- @arbitraryBoundedRandom@.
|
||||||
|
--
|
||||||
|
-- System endianness impacts how the tuple is interpreted and therefore changes
|
||||||
|
-- the resulting DRG.
|
||||||
drgNewTest :: (Word64, Word64, Word64, Word64, Word64) -> ChaChaDRG
|
drgNewTest :: (Word64, Word64, Word64, Word64, Word64) -> ChaChaDRG
|
||||||
drgNewTest = initializeWords
|
drgNewTest = initializeWords
|
||||||
|
|
||||||
|
|||||||
@ -25,10 +25,9 @@ replenish :: Int -> [EntropyBackend] -> Ptr Word8 -> IO ()
|
|||||||
replenish _ [] _ = fail "cryptonite: random: cannot get any source of entropy on this system"
|
replenish _ [] _ = fail "cryptonite: random: cannot get any source of entropy on this system"
|
||||||
replenish poolSize backends ptr = loop 0 backends ptr poolSize
|
replenish poolSize backends ptr = loop 0 backends ptr poolSize
|
||||||
where loop :: Int -> [EntropyBackend] -> Ptr Word8 -> Int -> IO ()
|
where loop :: Int -> [EntropyBackend] -> Ptr Word8 -> Int -> IO ()
|
||||||
loop retry [] p n | n == 0 = return ()
|
loop _ _ _ 0 = return ()
|
||||||
| retry == 3 = error "cryptonite: random: cannot fully replenish"
|
loop retry [] p n | retry == 3 = error "cryptonite: random: cannot fully replenish"
|
||||||
| otherwise = loop (retry+1) backends p n
|
| otherwise = loop (retry+1) backends p n
|
||||||
loop _ (_:_) _ 0 = return ()
|
|
||||||
loop retry (b:bs) p n = do
|
loop retry (b:bs) p n = do
|
||||||
r <- gatherBackend b p n
|
r <- gatherBackend b p n
|
||||||
loop retry bs (p `plusPtr` r) (n - r)
|
loop retry bs (p `plusPtr` r) (n - r)
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import Crypto.Random.Entropy
|
|||||||
import Crypto.Internal.ByteArray
|
import Crypto.Internal.ByteArray
|
||||||
|
|
||||||
-- | A monad constraint that allows to generate random bytes
|
-- | A monad constraint that allows to generate random bytes
|
||||||
class (Functor m, Monad m) => MonadRandom m where
|
class Monad m => MonadRandom m where
|
||||||
getRandomBytes :: ByteArray byteArray => Int -> m byteArray
|
getRandomBytes :: ByteArray byteArray => Int -> m byteArray
|
||||||
|
|
||||||
-- | A Deterministic Random Generator (DRG) class
|
-- | A Deterministic Random Generator (DRG) class
|
||||||
|
|||||||
64
Crypto/System/CPU.hs
Normal file
64
Crypto/System/CPU.hs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
-- |
|
||||||
|
-- Module : Crypto.System.CPU
|
||||||
|
-- License : BSD-style
|
||||||
|
-- Maintainer : Olivier Chéron <olivier.cheron@gmail.com>
|
||||||
|
-- Stability : experimental
|
||||||
|
-- Portability : unknown
|
||||||
|
--
|
||||||
|
-- Gives information about cryptonite runtime environment.
|
||||||
|
--
|
||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
module Crypto.System.CPU
|
||||||
|
( ProcessorOption (..)
|
||||||
|
, processorOptions
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Data
|
||||||
|
import Data.List (findIndices)
|
||||||
|
#ifdef SUPPORT_RDRAND
|
||||||
|
import Data.Maybe (isJust)
|
||||||
|
#endif
|
||||||
|
import Data.Word (Word8)
|
||||||
|
import Foreign.Ptr
|
||||||
|
import Foreign.Storable
|
||||||
|
|
||||||
|
import Crypto.Internal.Compat
|
||||||
|
|
||||||
|
#ifdef SUPPORT_RDRAND
|
||||||
|
import Crypto.Random.Entropy.RDRand
|
||||||
|
import Crypto.Random.Entropy.Source
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-- | CPU options impacting cryptography implementation and library performance.
|
||||||
|
data ProcessorOption
|
||||||
|
= AESNI -- ^ Support for AES instructions, with flag @support_aesni@
|
||||||
|
| PCLMUL -- ^ Support for CLMUL instructions, with flag @support_pclmuldq@
|
||||||
|
| RDRAND -- ^ Support for RDRAND instruction, with flag @support_rdrand@
|
||||||
|
deriving (Show,Eq,Enum,Data)
|
||||||
|
|
||||||
|
-- | Options which have been enabled at compile time and are supported by the
|
||||||
|
-- current CPU.
|
||||||
|
processorOptions :: [ProcessorOption]
|
||||||
|
processorOptions = unsafeDoIO $ do
|
||||||
|
p <- cryptonite_aes_cpu_init
|
||||||
|
options <- traverse (getOption p) aesOptions
|
||||||
|
rdrand <- hasRDRand
|
||||||
|
return (decodeOptions options ++ [ RDRAND | rdrand ])
|
||||||
|
where
|
||||||
|
aesOptions = [ AESNI .. PCLMUL ]
|
||||||
|
getOption p = peekElemOff p . fromEnum
|
||||||
|
decodeOptions = map toEnum . findIndices (> 0)
|
||||||
|
{-# NOINLINE processorOptions #-}
|
||||||
|
|
||||||
|
hasRDRand :: IO Bool
|
||||||
|
#ifdef SUPPORT_RDRAND
|
||||||
|
hasRDRand = fmap isJust getRDRand
|
||||||
|
where getRDRand = entropyOpen :: IO (Maybe RDRand)
|
||||||
|
#else
|
||||||
|
hasRDRand = return False
|
||||||
|
#endif
|
||||||
|
|
||||||
|
foreign import ccall unsafe "cryptonite_aes_cpu_init"
|
||||||
|
cryptonite_aes_cpu_init :: IO (Ptr Word8)
|
||||||
@ -8,6 +8,9 @@ module Crypto.Tutorial
|
|||||||
|
|
||||||
-- * Symmetric block ciphers
|
-- * Symmetric block ciphers
|
||||||
-- $symmetric_block_ciphers
|
-- $symmetric_block_ciphers
|
||||||
|
|
||||||
|
-- * Combining primitives
|
||||||
|
-- $combining_primitives
|
||||||
) where
|
) where
|
||||||
|
|
||||||
-- $api_design
|
-- $api_design
|
||||||
@ -147,3 +150,46 @@ module Crypto.Tutorial
|
|||||||
-- > putStrLn $ "Original Message: " ++ show msg
|
-- > putStrLn $ "Original Message: " ++ show msg
|
||||||
-- > putStrLn $ "Message after encryption: " ++ show eMsg
|
-- > putStrLn $ "Message after encryption: " ++ show eMsg
|
||||||
-- > putStrLn $ "Message after decryption: " ++ show dMsg
|
-- > putStrLn $ "Message after decryption: " ++ show dMsg
|
||||||
|
|
||||||
|
-- $combining_primitives
|
||||||
|
--
|
||||||
|
-- This example shows how to use Curve25519, XSalsa and Poly1305 primitives to
|
||||||
|
-- emulate NaCl's @crypto_box@ construct.
|
||||||
|
--
|
||||||
|
-- > import qualified Data.ByteArray as BA
|
||||||
|
-- > import Data.ByteString (ByteString)
|
||||||
|
-- > import qualified Data.ByteString as B
|
||||||
|
-- >
|
||||||
|
-- > import qualified Crypto.Cipher.XSalsa as XSalsa
|
||||||
|
-- > import qualified Crypto.MAC.Poly1305 as Poly1305
|
||||||
|
-- > import qualified Crypto.PubKey.Curve25519 as X25519
|
||||||
|
-- >
|
||||||
|
-- > -- | Build a @crypto_box@ packet encrypting the specified content with a
|
||||||
|
-- > -- 192-bit nonce, receiver public key and sender private key.
|
||||||
|
-- > crypto_box content nonce pk sk = BA.convert tag `B.append` c
|
||||||
|
-- > where
|
||||||
|
-- > zero = B.replicate 16 0
|
||||||
|
-- > shared = X25519.dh pk sk
|
||||||
|
-- > (iv0, iv1) = B.splitAt 8 nonce
|
||||||
|
-- > state0 = XSalsa.initialize 20 shared (zero `B.append` iv0)
|
||||||
|
-- > state1 = XSalsa.derive state0 iv1
|
||||||
|
-- > (rs, state2) = XSalsa.generate state1 32
|
||||||
|
-- > (c, _) = XSalsa.combine state2 content
|
||||||
|
-- > tag = Poly1305.auth (rs :: ByteString) c
|
||||||
|
-- >
|
||||||
|
-- > -- | Try to open a @crypto_box@ packet and recover the content using the
|
||||||
|
-- > -- 192-bit nonce, sender public key and receiver private key.
|
||||||
|
-- > crypto_box_open packet nonce pk sk
|
||||||
|
-- > | B.length packet < 16 = Nothing
|
||||||
|
-- > | BA.constEq tag' tag = Just content
|
||||||
|
-- > | otherwise = Nothing
|
||||||
|
-- > where
|
||||||
|
-- > (tag', c) = B.splitAt 16 packet
|
||||||
|
-- > zero = B.replicate 16 0
|
||||||
|
-- > shared = X25519.dh pk sk
|
||||||
|
-- > (iv0, iv1) = B.splitAt 8 nonce
|
||||||
|
-- > state0 = XSalsa.initialize 20 shared (zero `B.append` iv0)
|
||||||
|
-- > state1 = XSalsa.derive state0 iv1
|
||||||
|
-- > (rs, state2) = XSalsa.generate state1 32
|
||||||
|
-- > (content, _) = XSalsa.combine state2 c
|
||||||
|
-- > tag = Poly1305.auth (rs :: ByteString) c
|
||||||
|
|||||||
2
QA.hs
2
QA.hs
@ -47,7 +47,9 @@ perModuleAllowedExtensions =
|
|||||||
, ("Crypto/Cipher/DES/Primitive.hs", [FlexibleInstances])
|
, ("Crypto/Cipher/DES/Primitive.hs", [FlexibleInstances])
|
||||||
, ("Crypto/Cipher/Twofish/Primitive.hs", [MagicHash])
|
, ("Crypto/Cipher/Twofish/Primitive.hs", [MagicHash])
|
||||||
, ("Crypto/PubKey/Curve25519.hs", [MagicHash])
|
, ("Crypto/PubKey/Curve25519.hs", [MagicHash])
|
||||||
|
, ("Crypto/PubKey/ECDSA.hs", [FlexibleContexts,StandaloneDeriving,UndecidableInstances])
|
||||||
, ("Crypto/Number/Compat.hs", [UnboxedTuples,MagicHash,CPP])
|
, ("Crypto/Number/Compat.hs", [UnboxedTuples,MagicHash,CPP])
|
||||||
|
, ("Crypto/System/CPU.hs", [CPP])
|
||||||
]
|
]
|
||||||
|
|
||||||
disallowedModules =
|
disallowedModules =
|
||||||
|
|||||||
11
README.md
11
README.md
@ -52,6 +52,10 @@ On OSX <= 10.7, the system compiler doesn't understand the '-maes' option, and
|
|||||||
with the lack of autodetection feature builtin in .cabal file, it is left on
|
with the lack of autodetection feature builtin in .cabal file, it is left on
|
||||||
the user to disable the aesni. See the [Disabling AESNI] section
|
the user to disable the aesni. See the [Disabling AESNI] section
|
||||||
|
|
||||||
|
On CentOS 7 the default C compiler includes intrinsic header files incompatible
|
||||||
|
with per-function target options. Solutions are to use GCC >= 4.9 or disable
|
||||||
|
flag *use_target_attributes* (see flag configuration examples below).
|
||||||
|
|
||||||
Disabling AESNI
|
Disabling AESNI
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
@ -72,6 +76,13 @@ or as part of an installation:
|
|||||||
|
|
||||||
For help with cabal flags, see: [stackoverflow : is there a way to define flags for cabal](http://stackoverflow.com/questions/23523869/is-there-any-way-to-define-flags-for-cabal-dependencies)
|
For help with cabal flags, see: [stackoverflow : is there a way to define flags for cabal](http://stackoverflow.com/questions/23523869/is-there-any-way-to-define-flags-for-cabal-dependencies)
|
||||||
|
|
||||||
|
Enabling PCLMULDQ
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
When the C toolchain supports it, enabling flag *support_pclmuldq* can bring
|
||||||
|
additional security and performance for AES GCM. A CPU with the necessary
|
||||||
|
instruction set will use an alternate implementation selected at runtime.
|
||||||
|
|
||||||
Links
|
Links
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|||||||
124
benchs/Bench.hs
124
benchs/Bench.hs
@ -1,11 +1,13 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE ExistentialQuantification #-}
|
{-# LANGUAGE ExistentialQuantification #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import Gauge.Main
|
import Gauge.Main
|
||||||
|
|
||||||
import Crypto.Cipher.AES
|
import Crypto.Cipher.AES
|
||||||
|
import qualified Crypto.Cipher.AESGCMSIV as AESGCMSIV
|
||||||
import Crypto.Cipher.Blowfish
|
import Crypto.Cipher.Blowfish
|
||||||
import Crypto.Cipher.CAST5
|
import Crypto.Cipher.CAST5
|
||||||
import qualified Crypto.Cipher.ChaChaPoly1305 as CP
|
import qualified Crypto.Cipher.ChaChaPoly1305 as CP
|
||||||
@ -22,12 +24,17 @@ import Crypto.Number.Generate
|
|||||||
import qualified Crypto.PubKey.DH as DH
|
import qualified Crypto.PubKey.DH as DH
|
||||||
import qualified Crypto.PubKey.ECC.Types as ECC
|
import qualified Crypto.PubKey.ECC.Types as ECC
|
||||||
import qualified Crypto.PubKey.ECC.Prim as ECC
|
import qualified Crypto.PubKey.ECC.Prim as ECC
|
||||||
|
import qualified Crypto.PubKey.ECDSA as ECDSA
|
||||||
|
import qualified Crypto.PubKey.Ed25519 as Ed25519
|
||||||
|
import qualified Crypto.PubKey.EdDSA as EdDSA
|
||||||
import Crypto.Random
|
import Crypto.Random
|
||||||
|
|
||||||
import Control.DeepSeq (NFData)
|
import Control.DeepSeq (NFData)
|
||||||
import Data.ByteArray (ByteArray, Bytes)
|
import Data.ByteArray (ByteArray, Bytes)
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
|
|
||||||
|
import qualified Crypto.PubKey.ECC.P256 as P256
|
||||||
|
|
||||||
import Number.F2m
|
import Number.F2m
|
||||||
|
|
||||||
data HashAlg = forall alg . HashAlgorithm alg => HashAlg alg
|
data HashAlg = forall alg . HashAlgorithm alg => HashAlg alg
|
||||||
@ -123,7 +130,7 @@ benchBlockCipher =
|
|||||||
[ bgroup "ECB" benchECB
|
[ bgroup "ECB" benchECB
|
||||||
, bgroup "CBC" benchCBC
|
, bgroup "CBC" benchCBC
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
benchECB =
|
benchECB =
|
||||||
[ bench "DES-input=1024" $ nf (run (undefined :: DES) cipherInit key8) input1024
|
[ bench "DES-input=1024" $ nf (run (undefined :: DES) cipherInit key8) input1024
|
||||||
, bench "Blowfish128-input=1024" $ nf (run (undefined :: Blowfish128) cipherInit key16) input1024
|
, bench "Blowfish128-input=1024" $ nf (run (undefined :: Blowfish128) cipherInit key16) input1024
|
||||||
@ -165,6 +172,7 @@ benchAE =
|
|||||||
[ bench "ChaChaPoly1305" $ nf (cp key32) (input64, input1024)
|
[ bench "ChaChaPoly1305" $ nf (cp key32) (input64, input1024)
|
||||||
, bench "AES-GCM" $ nf (gcm key32) (input64, input1024)
|
, bench "AES-GCM" $ nf (gcm key32) (input64, input1024)
|
||||||
, bench "AES-CCM" $ nf (ccm key32) (input64, input1024)
|
, bench "AES-CCM" $ nf (ccm key32) (input64, input1024)
|
||||||
|
, bench "AES-GCM-SIV" $ nf (gcmsiv key32) (input64, input1024)
|
||||||
]
|
]
|
||||||
where cp k (ini, plain) =
|
where cp k (ini, plain) =
|
||||||
let iniState = throwCryptoError $ CP.initialize k (throwCryptoError $ CP.nonce12 nonce12)
|
let iniState = throwCryptoError $ CP.initialize k (throwCryptoError $ CP.nonce12 nonce12)
|
||||||
@ -184,6 +192,11 @@ benchAE =
|
|||||||
state = throwCryptoError $ aeadInit mode ctx nonce12
|
state = throwCryptoError $ aeadInit mode ctx nonce12
|
||||||
in aeadSimpleEncrypt state ini plain 16
|
in aeadSimpleEncrypt state ini plain 16
|
||||||
|
|
||||||
|
gcmsiv k (ini, plain) =
|
||||||
|
let ctx = throwCryptoError (cipherInit k) :: AES256
|
||||||
|
iv = throwCryptoError (AESGCMSIV.nonce nonce12)
|
||||||
|
in AESGCMSIV.encrypt ctx iv ini plain
|
||||||
|
|
||||||
input64 = B.replicate 64 0
|
input64 = B.replicate 64 0
|
||||||
input1024 = B.replicate 1024 0
|
input1024 = B.replicate 1024 0
|
||||||
|
|
||||||
@ -195,20 +208,42 @@ benchAE =
|
|||||||
benchECC =
|
benchECC =
|
||||||
[ bench "pointAddTwoMuls-baseline" $ nf run_b (n1, p1, n2, p2)
|
[ bench "pointAddTwoMuls-baseline" $ nf run_b (n1, p1, n2, p2)
|
||||||
, bench "pointAddTwoMuls-optimized" $ nf run_o (n1, p1, n2, p2)
|
, bench "pointAddTwoMuls-optimized" $ nf run_o (n1, p1, n2, p2)
|
||||||
|
, bench "pointAdd-ECC" $ nf run_c (p1, p2)
|
||||||
|
, bench "pointMul-ECC" $ nf run_d (n1, p2)
|
||||||
]
|
]
|
||||||
where run_b (n, p, k, q) = ECC.pointAdd c (ECC.pointMul c n p)
|
where run_b (n, p, k, q) = ECC.pointAdd c (ECC.pointMul c n p)
|
||||||
(ECC.pointMul c k q)
|
(ECC.pointMul c k q)
|
||||||
|
|
||||||
run_o (n, p, k, q) = ECC.pointAddTwoMuls c n p k q
|
run_o (n, p, k, q) = ECC.pointAddTwoMuls c n p k q
|
||||||
|
run_c (p, q) = ECC.pointAdd c p q
|
||||||
|
run_d (n, p) = ECC.pointMul c n p
|
||||||
|
|
||||||
c = ECC.getCurveByName ECC.SEC_p256r1
|
c = ECC.getCurveByName ECC.SEC_p256r1
|
||||||
r1 = 7
|
p1 = ECC.pointBaseMul c n1
|
||||||
r2 = 11
|
p2 = ECC.pointBaseMul c n2
|
||||||
p1 = ECC.pointBaseMul c r1
|
|
||||||
p2 = ECC.pointBaseMul c r2
|
|
||||||
n1 = 0x2ba9daf2363b2819e69b34a39cf496c2458a9b2a21505ea9e7b7cbca42dc7435
|
n1 = 0x2ba9daf2363b2819e69b34a39cf496c2458a9b2a21505ea9e7b7cbca42dc7435
|
||||||
n2 = 0xf054a7f60d10b8c2cf847ee90e9e029f8b0e971b09ca5f55c4d49921a11fadc1
|
n2 = 0xf054a7f60d10b8c2cf847ee90e9e029f8b0e971b09ca5f55c4d49921a11fadc1
|
||||||
|
|
||||||
|
benchP256 =
|
||||||
|
[ bench "pointAddTwoMuls-P256" $ nf run_p (n1, p1, n2, p2)
|
||||||
|
, bench "pointAdd-P256" $ nf run_q (p1, p2)
|
||||||
|
, bench "pointMul-P256" $ nf run_t (n1, p1)
|
||||||
|
]
|
||||||
|
where run_p (n, p, k, q) = P256.pointAdd (P256.pointMul n p) (P256.pointMul k q)
|
||||||
|
run_q (p, q) = P256.pointAdd p q
|
||||||
|
run_t (n, p) = P256.pointMul n p
|
||||||
|
|
||||||
|
xS = 0xde2444bebc8d36e682edd27e0f271508617519b3221a8fa0b77cab3989da97c9
|
||||||
|
yS = 0xc093ae7ff36e5380fc01a5aad1e66659702de80f53cec576b6350b243042a256
|
||||||
|
xT = 0x55a8b00f8da1d44e62f6b3b25316212e39540dc861c89575bb8cf92e35e0986b
|
||||||
|
yT = 0x5421c3209c2d6c704835d82ac4c3dd90f61a8a52598b9e7ab656e9d8c8b24316
|
||||||
|
p1 = P256.pointFromIntegers (xS, yS)
|
||||||
|
p2 = P256.pointFromIntegers (xT, yT)
|
||||||
|
n1 = throwCryptoError $ P256.scalarFromInteger 0x2ba9daf2363b2819e69b34a39cf496c2458a9b2a21505ea9e7b7cbca42dc7435
|
||||||
|
n2 = throwCryptoError $ P256.scalarFromInteger 0xf054a7f60d10b8c2cf847ee90e9e029f8b0e971b09ca5f55c4d49921a11fadc1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
benchFFDH = map doFFDHBench primes
|
benchFFDH = map doFFDHBench primes
|
||||||
where
|
where
|
||||||
doFFDHBench (e, p) =
|
doFFDHBench (e, p) =
|
||||||
@ -255,6 +290,82 @@ benchECDH = map doECDHBench curves
|
|||||||
, ("X448", CurveDH Curve_X448)
|
, ("X448", CurveDH Curve_X448)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
data CurveHashECDSA =
|
||||||
|
forall curve hashAlg . (ECDSA.EllipticCurveECDSA curve,
|
||||||
|
NFData (Scalar curve),
|
||||||
|
NFData (Point curve),
|
||||||
|
HashAlgorithm hashAlg) => CurveHashECDSA curve hashAlg
|
||||||
|
|
||||||
|
benchECDSA = map doECDSABench curveHashes
|
||||||
|
where
|
||||||
|
doECDSABench (name, CurveHashECDSA c hashAlg) =
|
||||||
|
let proxy = Just c -- using Maybe as Proxy
|
||||||
|
in bgroup name
|
||||||
|
[ env (signGenerate proxy) $ bench "sign" . nfIO . signRun proxy hashAlg
|
||||||
|
, env (verifyGenerate proxy hashAlg) $ bench "verify" . nf (verifyRun proxy hashAlg)
|
||||||
|
]
|
||||||
|
|
||||||
|
signGenerate proxy = do
|
||||||
|
m <- tenKB
|
||||||
|
s <- curveGenerateScalar proxy
|
||||||
|
return (s, m)
|
||||||
|
|
||||||
|
signRun proxy hashAlg (priv, msg) = ECDSA.sign proxy priv hashAlg msg
|
||||||
|
|
||||||
|
verifyGenerate proxy hashAlg = do
|
||||||
|
m <- tenKB
|
||||||
|
KeyPair p s <- curveGenerateKeyPair proxy
|
||||||
|
sig <- ECDSA.sign proxy s hashAlg m
|
||||||
|
return (p, sig, m)
|
||||||
|
|
||||||
|
verifyRun proxy hashAlg (pub, sig, msg) = ECDSA.verify proxy hashAlg pub sig msg
|
||||||
|
|
||||||
|
tenKB :: IO Bytes
|
||||||
|
tenKB = getRandomBytes 10240
|
||||||
|
|
||||||
|
curveHashes = [ ("secp256r1_sha256", CurveHashECDSA Curve_P256R1 SHA256)
|
||||||
|
, ("secp384r1_sha384", CurveHashECDSA Curve_P384R1 SHA384)
|
||||||
|
, ("secp521r1_sha512", CurveHashECDSA Curve_P521R1 SHA512)
|
||||||
|
]
|
||||||
|
|
||||||
|
benchEdDSA =
|
||||||
|
[ bgroup "EdDSA-Ed25519" benchGenEd25519
|
||||||
|
, bgroup "Ed25519" benchEd25519
|
||||||
|
]
|
||||||
|
where
|
||||||
|
benchGen prx alg =
|
||||||
|
[ bench "sign" $ perBatchEnv (genEnv prx alg) (run_gen_sign prx)
|
||||||
|
, bench "verify" $ perBatchEnv (genEnv prx alg) (run_gen_verify prx)
|
||||||
|
]
|
||||||
|
|
||||||
|
benchGenEd25519 = benchGen (Just Curve_Edwards25519) SHA512
|
||||||
|
benchEd25519 =
|
||||||
|
[ bench "sign" $ perBatchEnv ed25519Env run_ed25519_sign
|
||||||
|
, bench "verify" $ perBatchEnv ed25519Env run_ed25519_verify
|
||||||
|
]
|
||||||
|
|
||||||
|
msg = B.empty -- empty message = worst-case scenario showing API overhead
|
||||||
|
|
||||||
|
genEnv prx alg _ = do
|
||||||
|
sec <- EdDSA.generateSecretKey prx
|
||||||
|
let pub = EdDSA.toPublic prx alg sec
|
||||||
|
sig = EdDSA.sign prx sec pub msg
|
||||||
|
return (sec, pub, sig)
|
||||||
|
|
||||||
|
run_gen_sign prx (sec, pub, _) = return (EdDSA.sign prx sec pub msg)
|
||||||
|
|
||||||
|
run_gen_verify prx (_, pub, sig) = return (EdDSA.verify prx pub msg sig)
|
||||||
|
|
||||||
|
ed25519Env _ = do
|
||||||
|
sec <- Ed25519.generateSecretKey
|
||||||
|
let pub = Ed25519.toPublic sec
|
||||||
|
sig = Ed25519.sign sec pub msg
|
||||||
|
return (sec, pub, sig)
|
||||||
|
|
||||||
|
run_ed25519_sign (sec, pub, _) = return (Ed25519.sign sec pub msg)
|
||||||
|
|
||||||
|
run_ed25519_verify (_, pub, sig) = return (Ed25519.verify pub msg sig)
|
||||||
|
|
||||||
main = defaultMain
|
main = defaultMain
|
||||||
[ bgroup "hash" benchHash
|
[ bgroup "hash" benchHash
|
||||||
, bgroup "block-cipher" benchBlockCipher
|
, bgroup "block-cipher" benchBlockCipher
|
||||||
@ -262,9 +373,12 @@ main = defaultMain
|
|||||||
, bgroup "pbkdf2" benchPBKDF2
|
, bgroup "pbkdf2" benchPBKDF2
|
||||||
, bgroup "bcrypt" benchBCrypt
|
, bgroup "bcrypt" benchBCrypt
|
||||||
, bgroup "ECC" benchECC
|
, bgroup "ECC" benchECC
|
||||||
|
, bgroup "P256" benchP256
|
||||||
, bgroup "DH"
|
, bgroup "DH"
|
||||||
[ bgroup "FFDH" benchFFDH
|
[ bgroup "FFDH" benchFFDH
|
||||||
, bgroup "ECDH" benchECDH
|
, bgroup "ECDH" benchECDH
|
||||||
]
|
]
|
||||||
|
, bgroup "ECDSA" benchECDSA
|
||||||
|
, bgroup "EdDSA" benchEdDSA
|
||||||
, bgroup "F2m" benchF2m
|
, bgroup "F2m" benchF2m
|
||||||
]
|
]
|
||||||
|
|||||||
@ -108,6 +108,13 @@ static inline void block128_vxor(block128 *d, const block128 *s1, const block128
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void block128_byte_reverse(block128 *a)
|
||||||
|
{
|
||||||
|
uint64_t s0 = a->q[0], s1 = a->q[1];
|
||||||
|
a->q[0] = bitfn_swap64(s1);
|
||||||
|
a->q[1] = bitfn_swap64(s0);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void block128_inc_be(block128 *b)
|
static inline void block128_inc_be(block128 *b)
|
||||||
{
|
{
|
||||||
uint64_t v = be64_to_cpu(b->q[1]);
|
uint64_t v = be64_to_cpu(b->q[1]);
|
||||||
@ -118,6 +125,16 @@ static inline void block128_inc_be(block128 *b)
|
|||||||
b->q[1] = cpu_to_be64(v);
|
b->q[1] = cpu_to_be64(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void block128_inc32_be(block128 *b)
|
||||||
|
{
|
||||||
|
b->d[3] = cpu_to_be32(be32_to_cpu(b->d[3]) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void block128_inc32_le(block128 *b)
|
||||||
|
{
|
||||||
|
b->d[0] = cpu_to_le32(le32_to_cpu(b->d[0]) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef IMPL_DEBUG
|
#ifdef IMPL_DEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
static inline void block128_print(block128 *b)
|
static inline void block128_print(block128 *b)
|
||||||
|
|||||||
128
cbits/aes/gf.c
128
cbits/aes/gf.c
@ -34,33 +34,6 @@
|
|||||||
#include <aes/gf.h>
|
#include <aes/gf.h>
|
||||||
#include <aes/x86ni.h>
|
#include <aes/x86ni.h>
|
||||||
|
|
||||||
/* this is a really inefficient way to GF multiply.
|
|
||||||
* the alternative without hw accel is building small tables
|
|
||||||
* to speed up the multiplication.
|
|
||||||
* TODO: optimise with tables
|
|
||||||
*/
|
|
||||||
void cryptonite_aes_generic_gf_mul(block128 *a, block128 *b)
|
|
||||||
{
|
|
||||||
uint64_t a0, a1, v0, v1;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
a0 = a1 = 0;
|
|
||||||
v0 = cpu_to_be64(a->q[0]);
|
|
||||||
v1 = cpu_to_be64(a->q[1]);
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
|
||||||
for (j = 0x80; j != 0; j >>= 1) {
|
|
||||||
uint8_t x = b->b[i] & j;
|
|
||||||
a0 ^= x ? v0 : 0;
|
|
||||||
a1 ^= x ? v1 : 0;
|
|
||||||
x = (uint8_t) v1 & 1;
|
|
||||||
v1 = (v1 >> 1) | (v0 << 63);
|
|
||||||
v0 = (v0 >> 1) ^ (x ? (0xe1ULL << 56) : 0);
|
|
||||||
}
|
|
||||||
a->q[0] = cpu_to_be64(a0);
|
|
||||||
a->q[1] = cpu_to_be64(a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* inplace GFMUL for xts mode */
|
/* inplace GFMUL for xts mode */
|
||||||
void cryptonite_aes_generic_gf_mulx(block128 *a)
|
void cryptonite_aes_generic_gf_mulx(block128 *a)
|
||||||
{
|
{
|
||||||
@ -70,3 +43,104 @@ void cryptonite_aes_generic_gf_mulx(block128 *a)
|
|||||||
a->q[0] = cpu_to_le64(le64_to_cpu(a->q[0]) << 1) ^ r;
|
a->q[0] = cpu_to_le64(le64_to_cpu(a->q[0]) << 1) ^ r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GF multiplication with Shoup's method and 4-bit table.
|
||||||
|
*
|
||||||
|
* We precompute the products of H with all 4-bit polynomials and store them in
|
||||||
|
* a 'table_4bit' array. To avoid unnecessary byte swapping, the 16 blocks are
|
||||||
|
* written to the table with qwords already converted to CPU order. Table
|
||||||
|
* indices use the reflected bit ordering, i.e. polynomials X^0, X^1, X^2, X^3
|
||||||
|
* map to bit positions 3, 2, 1, 0 respectively.
|
||||||
|
*
|
||||||
|
* To multiply an arbitrary block with H, the input block is decomposed in 4-bit
|
||||||
|
* segments. We get the final result after 32 table lookups and additions, one
|
||||||
|
* for each segment, interleaving multiplication by P(X)=X^4.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* convert block128 qwords between BE and CPU order */
|
||||||
|
static inline void block128_cpu_swap_be(block128 *a, const block128 *b)
|
||||||
|
{
|
||||||
|
a->q[1] = cpu_to_be64(b->q[1]);
|
||||||
|
a->q[0] = cpu_to_be64(b->q[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* multiplication by P(X)=X, assuming qwords already in CPU order */
|
||||||
|
static inline void cpu_gf_mulx(block128 *a, const block128 *b)
|
||||||
|
{
|
||||||
|
uint64_t v0 = b->q[0];
|
||||||
|
uint64_t v1 = b->q[1];
|
||||||
|
a->q[1] = v1 >> 1 | v0 << 63;
|
||||||
|
a->q[0] = v0 >> 1 ^ ((0-(v1 & 1)) & 0xe100000000000000ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint64_t r4_0[] =
|
||||||
|
{ 0x0000000000000000ULL, 0x1c20000000000000ULL
|
||||||
|
, 0x3840000000000000ULL, 0x2460000000000000ULL
|
||||||
|
, 0x7080000000000000ULL, 0x6ca0000000000000ULL
|
||||||
|
, 0x48c0000000000000ULL, 0x54e0000000000000ULL
|
||||||
|
, 0xe100000000000000ULL, 0xfd20000000000000ULL
|
||||||
|
, 0xd940000000000000ULL, 0xc560000000000000ULL
|
||||||
|
, 0x9180000000000000ULL, 0x8da0000000000000ULL
|
||||||
|
, 0xa9c0000000000000ULL, 0xb5e0000000000000ULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* multiplication by P(X)=X^4, assuming qwords already in CPU order */
|
||||||
|
static inline void cpu_gf_mulx4(block128 *a, const block128 *b)
|
||||||
|
{
|
||||||
|
uint64_t v0 = b->q[0];
|
||||||
|
uint64_t v1 = b->q[1];
|
||||||
|
a->q[1] = v1 >> 4 | v0 << 60;
|
||||||
|
a->q[0] = v0 >> 4 ^ r4_0[v1 & 0xf];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize the 4-bit table given H */
|
||||||
|
void cryptonite_aes_generic_hinit(table_4bit htable, const block128 *h)
|
||||||
|
{
|
||||||
|
block128 v, *p;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
/* multiplication by 0 is 0 */
|
||||||
|
block128_zero(&htable[0]);
|
||||||
|
|
||||||
|
/* at index 8=2^3 we have H.X^0 = H */
|
||||||
|
i = 8;
|
||||||
|
block128_cpu_swap_be(&htable[i], h); /* in CPU order */
|
||||||
|
p = &htable[i];
|
||||||
|
|
||||||
|
/* for other powers of 2, repeat multiplication by P(X)=X */
|
||||||
|
for (i = 4; i > 0; i >>= 1)
|
||||||
|
{
|
||||||
|
cpu_gf_mulx(&htable[i], p);
|
||||||
|
p = &htable[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remaining elements are linear combinations */
|
||||||
|
for (i = 2; i < 16; i <<= 1) {
|
||||||
|
p = &htable[i];
|
||||||
|
v = *p;
|
||||||
|
for (j = 1; j < i; j++) {
|
||||||
|
p[j] = v;
|
||||||
|
block128_xor_aligned(&p[j], &htable[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* multiply a block with H */
|
||||||
|
void cryptonite_aes_generic_gf_mul(block128 *a, const table_4bit htable)
|
||||||
|
{
|
||||||
|
block128 b;
|
||||||
|
int i;
|
||||||
|
block128_zero(&b);
|
||||||
|
for (i = 15; i >= 0; i--)
|
||||||
|
{
|
||||||
|
uint8_t v = a->b[i];
|
||||||
|
block128_xor_aligned(&b, &htable[v & 0xf]); /* high bits (reflected) */
|
||||||
|
cpu_gf_mulx4(&b, &b);
|
||||||
|
block128_xor_aligned(&b, &htable[v >> 4]); /* low bits (reflected) */
|
||||||
|
if (i > 0)
|
||||||
|
cpu_gf_mulx4(&b, &b);
|
||||||
|
else
|
||||||
|
block128_cpu_swap_be(a, &b); /* restore BE order when done */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -32,7 +32,11 @@
|
|||||||
|
|
||||||
#include "aes/block128.h"
|
#include "aes/block128.h"
|
||||||
|
|
||||||
void cryptonite_aes_generic_gf_mul(block128 *a, block128 *b);
|
typedef block128 table_4bit[16];
|
||||||
|
|
||||||
void cryptonite_aes_generic_gf_mulx(block128 *a);
|
void cryptonite_aes_generic_gf_mulx(block128 *a);
|
||||||
|
|
||||||
|
void cryptonite_aes_generic_hinit(table_4bit htable, const block128 *h);
|
||||||
|
void cryptonite_aes_generic_gf_mul(block128 *a, const table_4bit htable);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -46,6 +46,7 @@
|
|||||||
/* old GCC version doesn't cope with the shuffle parameters, that can take 2 values (0xff and 0xaa)
|
/* old GCC version doesn't cope with the shuffle parameters, that can take 2 values (0xff and 0xaa)
|
||||||
* in our case, passed as argument despite being a immediate 8 bits constant anyway.
|
* in our case, passed as argument despite being a immediate 8 bits constant anyway.
|
||||||
* un-factorise aes_128_key_expansion into 2 version that have the shuffle parameter explicitly set */
|
* un-factorise aes_128_key_expansion into 2 version that have the shuffle parameter explicitly set */
|
||||||
|
TARGET_AESNI
|
||||||
static __m128i aes_128_key_expansion_ff(__m128i key, __m128i keygened)
|
static __m128i aes_128_key_expansion_ff(__m128i key, __m128i keygened)
|
||||||
{
|
{
|
||||||
keygened = _mm_shuffle_epi32(keygened, 0xff);
|
keygened = _mm_shuffle_epi32(keygened, 0xff);
|
||||||
@ -55,6 +56,7 @@ static __m128i aes_128_key_expansion_ff(__m128i key, __m128i keygened)
|
|||||||
return _mm_xor_si128(key, keygened);
|
return _mm_xor_si128(key, keygened);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
static __m128i aes_128_key_expansion_aa(__m128i key, __m128i keygened)
|
static __m128i aes_128_key_expansion_aa(__m128i key, __m128i keygened)
|
||||||
{
|
{
|
||||||
keygened = _mm_shuffle_epi32(keygened, 0xaa);
|
keygened = _mm_shuffle_epi32(keygened, 0xaa);
|
||||||
@ -64,6 +66,7 @@ static __m128i aes_128_key_expansion_aa(__m128i key, __m128i keygened)
|
|||||||
return _mm_xor_si128(key, keygened);
|
return _mm_xor_si128(key, keygened);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void cryptonite_aesni_init(aes_key *key, uint8_t *ikey, uint8_t size)
|
void cryptonite_aesni_init(aes_key *key, uint8_t *ikey, uint8_t size)
|
||||||
{
|
{
|
||||||
__m128i k[28];
|
__m128i k[28];
|
||||||
@ -145,6 +148,7 @@ void cryptonite_aesni_init(aes_key *key, uint8_t *ikey, uint8_t size)
|
|||||||
/* TO OPTIMISE: use pcmulqdq... or some faster code.
|
/* TO OPTIMISE: use pcmulqdq... or some faster code.
|
||||||
* this is the lamest way of doing it, but i'm out of time.
|
* this is the lamest way of doing it, but i'm out of time.
|
||||||
* this is basically a copy of gf_mulx in gf.c */
|
* this is basically a copy of gf_mulx in gf.c */
|
||||||
|
TARGET_AESNI
|
||||||
static __m128i gfmulx(__m128i v)
|
static __m128i gfmulx(__m128i v)
|
||||||
{
|
{
|
||||||
uint64_t v_[2] ALIGNMENT(16);
|
uint64_t v_[2] ALIGNMENT(16);
|
||||||
@ -158,33 +162,34 @@ static __m128i gfmulx(__m128i v)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __m128i gfmul_generic(__m128i tag, __m128i h)
|
TARGET_AESNI
|
||||||
|
static __m128i gfmul_generic(__m128i tag, const table_4bit htable)
|
||||||
{
|
{
|
||||||
aes_block _t, _h;
|
aes_block _t ALIGNMENT(16);
|
||||||
_mm_store_si128((__m128i *) &_t, tag);
|
_mm_store_si128((__m128i *) &_t, tag);
|
||||||
_mm_store_si128((__m128i *) &_h, h);
|
cryptonite_aes_generic_gf_mul(&_t, htable);
|
||||||
cryptonite_aes_generic_gf_mul(&_t, &_h);
|
|
||||||
tag = _mm_load_si128((__m128i *) &_t);
|
tag = _mm_load_si128((__m128i *) &_t);
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_PCLMUL
|
#ifdef WITH_PCLMUL
|
||||||
|
|
||||||
__m128i (*gfmul_branch_ptr)(__m128i a, __m128i b) = gfmul_generic;
|
__m128i (*gfmul_branch_ptr)(__m128i a, const table_4bit t) = gfmul_generic;
|
||||||
#define gfmul(a,b) ((*gfmul_branch_ptr)(a,b))
|
#define gfmul(a,t) ((*gfmul_branch_ptr)(a,t))
|
||||||
|
|
||||||
/* See Intel carry-less-multiplication-instruction-in-gcm-mode-paper.pdf
|
/* See Intel carry-less-multiplication-instruction-in-gcm-mode-paper.pdf
|
||||||
*
|
*
|
||||||
* Adapted from figure 5, with additional byte swapping so that interface
|
* Adapted from figure 5, with additional byte swapping so that interface
|
||||||
* is simimar to cryptonite_aes_generic_gf_mul.
|
* is simimar to cryptonite_aes_generic_gf_mul.
|
||||||
*/
|
*/
|
||||||
static __m128i gfmul_pclmuldq(__m128i a, __m128i b)
|
TARGET_AESNI_PCLMUL
|
||||||
|
static __m128i gfmul_pclmuldq(__m128i a, const table_4bit htable)
|
||||||
{
|
{
|
||||||
__m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
|
__m128i b, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
|
||||||
__m128i bswap_mask = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
|
__m128i bswap_mask = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
|
||||||
|
|
||||||
a = _mm_shuffle_epi8(a, bswap_mask);
|
a = _mm_shuffle_epi8(a, bswap_mask);
|
||||||
b = _mm_shuffle_epi8(b, bswap_mask);
|
b = _mm_loadu_si128((__m128i *) htable);
|
||||||
|
|
||||||
tmp3 = _mm_clmulepi64_si128(a, b, 0x00);
|
tmp3 = _mm_clmulepi64_si128(a, b, 0x00);
|
||||||
tmp4 = _mm_clmulepi64_si128(a, b, 0x10);
|
tmp4 = _mm_clmulepi64_si128(a, b, 0x10);
|
||||||
@ -231,28 +236,39 @@ static __m128i gfmul_pclmuldq(__m128i a, __m128i b)
|
|||||||
return _mm_shuffle_epi8(tmp6, bswap_mask);
|
return _mm_shuffle_epi8(tmp6, bswap_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_aesni_gf_mul(block128 *a, block128 *b)
|
void cryptonite_aesni_hinit_pclmul(table_4bit htable, const block128 *h)
|
||||||
{
|
{
|
||||||
__m128i _a, _b, _c;
|
/* When pclmul is active we don't need to fill the table. Instead we just
|
||||||
_a = _mm_loadu_si128((__m128i *) a);
|
* store H at index 0. It is written in reverse order, so function
|
||||||
_b = _mm_loadu_si128((__m128i *) b);
|
* gfmul_pclmuldq will not byte-swap this value.
|
||||||
_c = gfmul_pclmuldq(_a, _b);
|
*/
|
||||||
_mm_storeu_si128((__m128i *) a, _c);
|
htable->q[0] = bitfn_swap64(h->q[1]);
|
||||||
|
htable->q[1] = bitfn_swap64(h->q[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_aesni_init_pclmul()
|
TARGET_AESNI_PCLMUL
|
||||||
|
void cryptonite_aesni_gf_mul_pclmul(block128 *a, const table_4bit htable)
|
||||||
|
{
|
||||||
|
__m128i _a, _b;
|
||||||
|
_a = _mm_loadu_si128((__m128i *) a);
|
||||||
|
_b = gfmul_pclmuldq(_a, htable);
|
||||||
|
_mm_storeu_si128((__m128i *) a, _b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonite_aesni_init_pclmul(void)
|
||||||
{
|
{
|
||||||
gfmul_branch_ptr = gfmul_pclmuldq;
|
gfmul_branch_ptr = gfmul_pclmuldq;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define gfmul(a,b) (gfmul_generic(a,b))
|
#define gfmul(a,t) (gfmul_generic(a,t))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline __m128i ghash_add(__m128i tag, __m128i h, __m128i m)
|
TARGET_AESNI
|
||||||
|
static inline __m128i ghash_add(__m128i tag, const table_4bit htable, __m128i m)
|
||||||
{
|
{
|
||||||
tag = _mm_xor_si128(tag, m);
|
tag = _mm_xor_si128(tag, m);
|
||||||
return gfmul(tag, h);
|
return gfmul(tag, htable);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PRELOAD_ENC_KEYS128(k) \
|
#define PRELOAD_ENC_KEYS128(k) \
|
||||||
|
|||||||
@ -40,7 +40,16 @@
|
|||||||
#include <cryptonite_aes.h>
|
#include <cryptonite_aes.h>
|
||||||
#include <aes/block128.h>
|
#include <aes/block128.h>
|
||||||
|
|
||||||
|
#ifdef WITH_TARGET_ATTRIBUTES
|
||||||
|
#define TARGET_AESNI __attribute__((target("ssse3,aes")))
|
||||||
|
#define TARGET_AESNI_PCLMUL __attribute__((target("sse4.1,aes,pclmul")))
|
||||||
|
#else
|
||||||
|
#define TARGET_AESNI
|
||||||
|
#define TARGET_AESNI_PCLMUL
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef IMPL_DEBUG
|
#ifdef IMPL_DEBUG
|
||||||
|
TARGET_AESNI
|
||||||
static void block128_sse_print(__m128i m)
|
static void block128_sse_print(__m128i m)
|
||||||
{
|
{
|
||||||
block128 b;
|
block128 b;
|
||||||
@ -64,6 +73,8 @@ void cryptonite_aesni_decrypt_cbc128(aes_block *out, aes_key *key, aes_block *_i
|
|||||||
void cryptonite_aesni_decrypt_cbc256(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks);
|
void cryptonite_aesni_decrypt_cbc256(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks);
|
||||||
void cryptonite_aesni_encrypt_ctr128(uint8_t *out, aes_key *key, aes_block *_iv, uint8_t *in, uint32_t length);
|
void cryptonite_aesni_encrypt_ctr128(uint8_t *out, aes_key *key, aes_block *_iv, uint8_t *in, uint32_t length);
|
||||||
void cryptonite_aesni_encrypt_ctr256(uint8_t *out, aes_key *key, aes_block *_iv, uint8_t *in, uint32_t length);
|
void cryptonite_aesni_encrypt_ctr256(uint8_t *out, aes_key *key, aes_block *_iv, uint8_t *in, uint32_t length);
|
||||||
|
void cryptonite_aesni_encrypt_c32_128(uint8_t *out, aes_key *key, aes_block *_iv, uint8_t *in, uint32_t length);
|
||||||
|
void cryptonite_aesni_encrypt_c32_256(uint8_t *out, aes_key *key, aes_block *_iv, uint8_t *in, uint32_t length);
|
||||||
void cryptonite_aesni_encrypt_xts128(aes_block *out, aes_key *key1, aes_key *key2,
|
void cryptonite_aesni_encrypt_xts128(aes_block *out, aes_key *key1, aes_key *key2,
|
||||||
aes_block *_tweak, uint32_t spoint, aes_block *in, uint32_t blocks);
|
aes_block *_tweak, uint32_t spoint, aes_block *in, uint32_t blocks);
|
||||||
void cryptonite_aesni_encrypt_xts256(aes_block *out, aes_key *key1, aes_key *key2,
|
void cryptonite_aesni_encrypt_xts256(aes_block *out, aes_key *key1, aes_key *key2,
|
||||||
@ -73,8 +84,9 @@ void cryptonite_aesni_gcm_encrypt128(uint8_t *out, aes_gcm *gcm, aes_key *key, u
|
|||||||
void cryptonite_aesni_gcm_encrypt256(uint8_t *out, aes_gcm *gcm, aes_key *key, uint8_t *in, uint32_t length);
|
void cryptonite_aesni_gcm_encrypt256(uint8_t *out, aes_gcm *gcm, aes_key *key, uint8_t *in, uint32_t length);
|
||||||
|
|
||||||
#ifdef WITH_PCLMUL
|
#ifdef WITH_PCLMUL
|
||||||
void cryptonite_aesni_init_pclmul();
|
void cryptonite_aesni_init_pclmul(void);
|
||||||
void cryptonite_aesni_gf_mul(block128 *a, block128 *b);
|
void cryptonite_aesni_hinit_pclmul(table_4bit htable, const block128 *h);
|
||||||
|
void cryptonite_aesni_gf_mul_pclmul(block128 *a, const table_4bit htable);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_encrypt_block)(aes_block *out, aes_key *key, aes_block *in)
|
void SIZED(cryptonite_aesni_encrypt_block)(aes_block *out, aes_key *key, aes_block *in)
|
||||||
{
|
{
|
||||||
__m128i *k = (__m128i *) key->data;
|
__m128i *k = (__m128i *) key->data;
|
||||||
@ -37,6 +38,7 @@ void SIZED(cryptonite_aesni_encrypt_block)(aes_block *out, aes_key *key, aes_blo
|
|||||||
_mm_storeu_si128((__m128i *) out, m);
|
_mm_storeu_si128((__m128i *) out, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_decrypt_block)(aes_block *out, aes_key *key, aes_block *in)
|
void SIZED(cryptonite_aesni_decrypt_block)(aes_block *out, aes_key *key, aes_block *in)
|
||||||
{
|
{
|
||||||
__m128i *k = (__m128i *) key->data;
|
__m128i *k = (__m128i *) key->data;
|
||||||
@ -46,6 +48,7 @@ void SIZED(cryptonite_aesni_decrypt_block)(aes_block *out, aes_key *key, aes_blo
|
|||||||
_mm_storeu_si128((__m128i *) out, m);
|
_mm_storeu_si128((__m128i *) out, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_encrypt_ecb)(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks)
|
void SIZED(cryptonite_aesni_encrypt_ecb)(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks)
|
||||||
{
|
{
|
||||||
__m128i *k = (__m128i *) key->data;
|
__m128i *k = (__m128i *) key->data;
|
||||||
@ -58,6 +61,7 @@ void SIZED(cryptonite_aesni_encrypt_ecb)(aes_block *out, aes_key *key, aes_block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_decrypt_ecb)(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks)
|
void SIZED(cryptonite_aesni_decrypt_ecb)(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks)
|
||||||
{
|
{
|
||||||
__m128i *k = (__m128i *) key->data;
|
__m128i *k = (__m128i *) key->data;
|
||||||
@ -71,6 +75,7 @@ void SIZED(cryptonite_aesni_decrypt_ecb)(aes_block *out, aes_key *key, aes_block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_encrypt_cbc)(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks)
|
void SIZED(cryptonite_aesni_encrypt_cbc)(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks)
|
||||||
{
|
{
|
||||||
__m128i *k = (__m128i *) key->data;
|
__m128i *k = (__m128i *) key->data;
|
||||||
@ -87,6 +92,7 @@ void SIZED(cryptonite_aesni_encrypt_cbc)(aes_block *out, aes_key *key, aes_block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_decrypt_cbc)(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks)
|
void SIZED(cryptonite_aesni_decrypt_cbc)(aes_block *out, aes_key *key, aes_block *_iv, aes_block *in, uint32_t blocks)
|
||||||
{
|
{
|
||||||
__m128i *k = (__m128i *) key->data;
|
__m128i *k = (__m128i *) key->data;
|
||||||
@ -106,6 +112,7 @@ void SIZED(cryptonite_aesni_decrypt_cbc)(aes_block *out, aes_key *key, aes_block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_encrypt_ctr)(uint8_t *output, aes_key *key, aes_block *_iv, uint8_t *input, uint32_t len)
|
void SIZED(cryptonite_aesni_encrypt_ctr)(uint8_t *output, aes_key *key, aes_block *_iv, uint8_t *input, uint32_t len)
|
||||||
{
|
{
|
||||||
__m128i *k = (__m128i *) key->data;
|
__m128i *k = (__m128i *) key->data;
|
||||||
@ -151,6 +158,49 @@ void SIZED(cryptonite_aesni_encrypt_ctr)(uint8_t *output, aes_key *key, aes_bloc
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
|
void SIZED(cryptonite_aesni_encrypt_c32_)(uint8_t *output, aes_key *key, aes_block *_iv, uint8_t *input, uint32_t len)
|
||||||
|
{
|
||||||
|
__m128i *k = (__m128i *) key->data;
|
||||||
|
__m128i one = _mm_set_epi32(0,0,0,1);
|
||||||
|
uint32_t nb_blocks = len / 16;
|
||||||
|
uint32_t part_block_len = len % 16;
|
||||||
|
|
||||||
|
/* get the IV */
|
||||||
|
__m128i iv = _mm_loadu_si128((__m128i *) _iv);
|
||||||
|
|
||||||
|
PRELOAD_ENC(k);
|
||||||
|
|
||||||
|
for (; nb_blocks-- > 0; output += 16, input += 16) {
|
||||||
|
/* encrypt the iv and and xor it the input block */
|
||||||
|
__m128i tmp = iv;
|
||||||
|
DO_ENC_BLOCK(tmp);
|
||||||
|
__m128i m = _mm_loadu_si128((__m128i *) input);
|
||||||
|
m = _mm_xor_si128(m, tmp);
|
||||||
|
|
||||||
|
_mm_storeu_si128((__m128i *) output, m);
|
||||||
|
/* iv += 1 */
|
||||||
|
iv = _mm_add_epi32(iv, one);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part_block_len != 0) {
|
||||||
|
aes_block block;
|
||||||
|
memset(&block.b, 0, 16);
|
||||||
|
memcpy(&block.b, input, part_block_len);
|
||||||
|
|
||||||
|
__m128i m = _mm_loadu_si128((__m128i *) &block);
|
||||||
|
__m128i tmp = iv;
|
||||||
|
|
||||||
|
DO_ENC_BLOCK(tmp);
|
||||||
|
m = _mm_xor_si128(m, tmp);
|
||||||
|
_mm_storeu_si128((__m128i *) &block.b, m);
|
||||||
|
memcpy(output, &block.b, part_block_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_encrypt_xts)(aes_block *out, aes_key *key1, aes_key *key2,
|
void SIZED(cryptonite_aesni_encrypt_xts)(aes_block *out, aes_key *key1, aes_key *key2,
|
||||||
aes_block *_tweak, uint32_t spoint, aes_block *in, uint32_t blocks)
|
aes_block *_tweak, uint32_t spoint, aes_block *in, uint32_t blocks)
|
||||||
{
|
{
|
||||||
@ -181,6 +231,7 @@ void SIZED(cryptonite_aesni_encrypt_xts)(aes_block *out, aes_key *key1, aes_key
|
|||||||
} while (0);
|
} while (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET_AESNI
|
||||||
void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length)
|
void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length)
|
||||||
{
|
{
|
||||||
__m128i *k = (__m128i *) key->data;
|
__m128i *k = (__m128i *) key->data;
|
||||||
@ -191,7 +242,6 @@ void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key
|
|||||||
|
|
||||||
gcm->length_input += length;
|
gcm->length_input += length;
|
||||||
|
|
||||||
__m128i h = _mm_loadu_si128((__m128i *) &gcm->h);
|
|
||||||
__m128i tag = _mm_loadu_si128((__m128i *) &gcm->tag);
|
__m128i tag = _mm_loadu_si128((__m128i *) &gcm->tag);
|
||||||
__m128i iv = _mm_loadu_si128((__m128i *) &gcm->civ);
|
__m128i iv = _mm_loadu_si128((__m128i *) &gcm->civ);
|
||||||
iv = _mm_shuffle_epi8(iv, bswap_mask);
|
iv = _mm_shuffle_epi8(iv, bswap_mask);
|
||||||
@ -200,7 +250,7 @@ void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key
|
|||||||
|
|
||||||
for (; nb_blocks-- > 0; output += 16, input += 16) {
|
for (; nb_blocks-- > 0; output += 16, input += 16) {
|
||||||
/* iv += 1 */
|
/* iv += 1 */
|
||||||
iv = _mm_add_epi64(iv, one);
|
iv = _mm_add_epi32(iv, one);
|
||||||
|
|
||||||
/* put back iv in big endian, encrypt it,
|
/* put back iv in big endian, encrypt it,
|
||||||
* and xor it to input */
|
* and xor it to input */
|
||||||
@ -209,7 +259,7 @@ void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key
|
|||||||
__m128i m = _mm_loadu_si128((__m128i *) input);
|
__m128i m = _mm_loadu_si128((__m128i *) input);
|
||||||
m = _mm_xor_si128(m, tmp);
|
m = _mm_xor_si128(m, tmp);
|
||||||
|
|
||||||
tag = ghash_add(tag, h, m);
|
tag = ghash_add(tag, gcm->htable, m);
|
||||||
|
|
||||||
/* store it out */
|
/* store it out */
|
||||||
_mm_storeu_si128((__m128i *) output, m);
|
_mm_storeu_si128((__m128i *) output, m);
|
||||||
@ -240,7 +290,7 @@ void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key
|
|||||||
block128_copy_bytes(&block, input, part_block_len);
|
block128_copy_bytes(&block, input, part_block_len);
|
||||||
|
|
||||||
/* iv += 1 */
|
/* iv += 1 */
|
||||||
iv = _mm_add_epi64(iv, one);
|
iv = _mm_add_epi32(iv, one);
|
||||||
|
|
||||||
/* put back iv in big endian mode, encrypt it and xor it with input */
|
/* put back iv in big endian mode, encrypt it and xor it with input */
|
||||||
__m128i tmp = _mm_shuffle_epi8(iv, bswap_mask);
|
__m128i tmp = _mm_shuffle_epi8(iv, bswap_mask);
|
||||||
@ -250,7 +300,7 @@ void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key
|
|||||||
m = _mm_xor_si128(m, tmp);
|
m = _mm_xor_si128(m, tmp);
|
||||||
m = _mm_shuffle_epi8(m, mask);
|
m = _mm_shuffle_epi8(m, mask);
|
||||||
|
|
||||||
tag = ghash_add(tag, h, m);
|
tag = ghash_add(tag, gcm->htable, m);
|
||||||
|
|
||||||
/* make output */
|
/* make output */
|
||||||
_mm_storeu_si128((__m128i *) &block.b, m);
|
_mm_storeu_si128((__m128i *) &block.b, m);
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
* Copyright 2015
|
* Copyright 2015
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||||
*
|
*
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||||
* these licenses can be found at:
|
* these licenses can be found at:
|
||||||
*
|
*
|
||||||
@ -83,25 +83,25 @@ static int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen)
|
|||||||
} while ((void)0, 0)
|
} while ((void)0, 0)
|
||||||
|
|
||||||
if (outlen <= BLAKE2B_OUTBYTES) {
|
if (outlen <= BLAKE2B_OUTBYTES) {
|
||||||
TRY(blake2b_init(&blake_state, outlen));
|
TRY(_cryptonite_blake2b_init(&blake_state, outlen));
|
||||||
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
|
TRY(_cryptonite_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
|
||||||
TRY(blake2b_update(&blake_state, in, inlen));
|
TRY(_cryptonite_blake2b_update(&blake_state, in, inlen));
|
||||||
TRY(blake2b_final(&blake_state, out, outlen));
|
TRY(_cryptonite_blake2b_final(&blake_state, out, outlen));
|
||||||
} else {
|
} else {
|
||||||
uint32_t toproduce;
|
uint32_t toproduce;
|
||||||
uint8_t out_buffer[BLAKE2B_OUTBYTES];
|
uint8_t out_buffer[BLAKE2B_OUTBYTES];
|
||||||
uint8_t in_buffer[BLAKE2B_OUTBYTES];
|
uint8_t in_buffer[BLAKE2B_OUTBYTES];
|
||||||
TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
|
TRY(_cryptonite_blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
|
||||||
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
|
TRY(_cryptonite_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
|
||||||
TRY(blake2b_update(&blake_state, in, inlen));
|
TRY(_cryptonite_blake2b_update(&blake_state, in, inlen));
|
||||||
TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
|
TRY(_cryptonite_blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
|
||||||
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
|
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
|
||||||
out += BLAKE2B_OUTBYTES / 2;
|
out += BLAKE2B_OUTBYTES / 2;
|
||||||
toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
|
toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
|
||||||
|
|
||||||
while (toproduce > BLAKE2B_OUTBYTES) {
|
while (toproduce > BLAKE2B_OUTBYTES) {
|
||||||
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
|
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
|
||||||
TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
|
TRY(_cryptonite_blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
|
||||||
BLAKE2B_OUTBYTES, NULL, 0));
|
BLAKE2B_OUTBYTES, NULL, 0));
|
||||||
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
|
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
|
||||||
out += BLAKE2B_OUTBYTES / 2;
|
out += BLAKE2B_OUTBYTES / 2;
|
||||||
@ -109,7 +109,7 @@ static int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
|
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
|
||||||
TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
|
TRY(_cryptonite_blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
|
||||||
0));
|
0));
|
||||||
memcpy(out, out_buffer, toproduce);
|
memcpy(out, out_buffer, toproduce);
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ static void store_block(void *output, const block *src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***************Memory functions*****************/
|
/***************Memory functions*****************/
|
||||||
static
|
static
|
||||||
int allocate_memory(const argon2_context *context, uint8_t **memory,
|
int allocate_memory(const argon2_context *context, uint8_t **memory,
|
||||||
size_t num, size_t size) {
|
size_t num, size_t size) {
|
||||||
size_t memory_size = num*size;
|
size_t memory_size = num*size;
|
||||||
@ -175,7 +175,7 @@ int allocate_memory(const argon2_context *context, uint8_t **memory,
|
|||||||
|
|
||||||
return ARGON2_OK;
|
return ARGON2_OK;
|
||||||
}
|
}
|
||||||
static
|
static
|
||||||
void free_memory(const argon2_context *context, uint8_t *memory,
|
void free_memory(const argon2_context *context, uint8_t *memory,
|
||||||
size_t num, size_t size) {
|
size_t num, size_t size) {
|
||||||
size_t memory_size = num*size;
|
size_t memory_size = num*size;
|
||||||
@ -425,7 +425,7 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ARGON2_NO_THREADS */
|
#endif /* ARGON2_NO_THREADS */
|
||||||
static
|
static
|
||||||
int fill_memory_blocks(argon2_instance_t *instance) {
|
int fill_memory_blocks(argon2_instance_t *instance) {
|
||||||
if (instance == NULL || instance->lanes == 0) {
|
if (instance == NULL || instance->lanes == 0) {
|
||||||
return ARGON2_INCORRECT_PARAMETER;
|
return ARGON2_INCORRECT_PARAMETER;
|
||||||
@ -437,7 +437,7 @@ int fill_memory_blocks(argon2_instance_t *instance) {
|
|||||||
fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance);
|
fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static
|
static
|
||||||
int validate_inputs(const argon2_context *context) {
|
int validate_inputs(const argon2_context *context) {
|
||||||
if (NULL == context) {
|
if (NULL == context) {
|
||||||
return ARGON2_INCORRECT_PARAMETER;
|
return ARGON2_INCORRECT_PARAMETER;
|
||||||
@ -564,7 +564,7 @@ int validate_inputs(const argon2_context *context) {
|
|||||||
|
|
||||||
return ARGON2_OK;
|
return ARGON2_OK;
|
||||||
}
|
}
|
||||||
static
|
static
|
||||||
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
|
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
/* Make the first and second block in each lane as G(H0||i||0) or
|
/* Make the first and second block in each lane as G(H0||i||0) or
|
||||||
@ -587,7 +587,7 @@ void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
|
|||||||
}
|
}
|
||||||
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
static
|
static
|
||||||
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
||||||
argon2_type type) {
|
argon2_type type) {
|
||||||
blake2b_state BlakeHash;
|
blake2b_state BlakeHash;
|
||||||
@ -597,31 +597,31 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
|
_cryptonite_blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
|
||||||
|
|
||||||
store32(&value, context->lanes);
|
store32(&value, context->lanes);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
store32(&value, context->outlen);
|
store32(&value, context->outlen);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
store32(&value, context->m_cost);
|
store32(&value, context->m_cost);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
store32(&value, context->t_cost);
|
store32(&value, context->t_cost);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
store32(&value, context->version);
|
store32(&value, context->version);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
store32(&value, (uint32_t)type);
|
store32(&value, (uint32_t)type);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
store32(&value, context->pwdlen);
|
store32(&value, context->pwdlen);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
if (context->pwd != NULL) {
|
if (context->pwd != NULL) {
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
|
||||||
context->pwdlen);
|
context->pwdlen);
|
||||||
|
|
||||||
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
|
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
|
||||||
@ -631,18 +631,18 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
store32(&value, context->saltlen);
|
store32(&value, context->saltlen);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
if (context->salt != NULL) {
|
if (context->salt != NULL) {
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
|
||||||
context->saltlen);
|
context->saltlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
store32(&value, context->secretlen);
|
store32(&value, context->secretlen);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
if (context->secret != NULL) {
|
if (context->secret != NULL) {
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
|
||||||
context->secretlen);
|
context->secretlen);
|
||||||
|
|
||||||
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
|
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
|
||||||
@ -652,16 +652,16 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
store32(&value, context->adlen);
|
store32(&value, context->adlen);
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||||
|
|
||||||
if (context->ad != NULL) {
|
if (context->ad != NULL) {
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
|
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
|
||||||
context->adlen);
|
context->adlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
|
_cryptonite_blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
|
||||||
}
|
}
|
||||||
static
|
static
|
||||||
int initialize(argon2_instance_t *instance, argon2_context *context) {
|
int initialize(argon2_instance_t *instance, argon2_context *context) {
|
||||||
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
|
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
|
||||||
int result = ARGON2_OK;
|
int result = ARGON2_OK;
|
||||||
|
|||||||
@ -142,51 +142,51 @@ extern "C" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Streaming API */
|
/* Streaming API */
|
||||||
int blake2s_init( blake2s_state *S, size_t outlen );
|
int _cryptonite_blake2s_init( blake2s_state *S, size_t outlen );
|
||||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
|
int _cryptonite_blake2s_init_param( blake2s_state *S, const blake2s_param *P );
|
||||||
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2s_update( blake2s_state *S, const void *in, size_t inlen );
|
||||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
|
int _cryptonite_blake2s_final( blake2s_state *S, void *out, size_t outlen );
|
||||||
|
|
||||||
int blake2b_init( blake2b_state *S, size_t outlen );
|
int _cryptonite_blake2b_init( blake2b_state *S, size_t outlen );
|
||||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
int _cryptonite_blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
||||||
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2b_update( blake2b_state *S, const void *in, size_t inlen );
|
||||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
|
int _cryptonite_blake2b_final( blake2b_state *S, void *out, size_t outlen );
|
||||||
|
|
||||||
int blake2sp_init( blake2sp_state *S, size_t outlen );
|
int _cryptonite_blake2sp_init( blake2sp_state *S, size_t outlen );
|
||||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
|
||||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
|
int _cryptonite_blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
|
||||||
|
|
||||||
int blake2bp_init( blake2bp_state *S, size_t outlen );
|
int _cryptonite_blake2bp_init( blake2bp_state *S, size_t outlen );
|
||||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
|
||||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
|
int _cryptonite_blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
|
||||||
|
|
||||||
/* Variable output length API */
|
/* Variable output length API */
|
||||||
int blake2xs_init( blake2xs_state *S, const size_t outlen );
|
int _cryptonite_blake2xs_init( blake2xs_state *S, const size_t outlen );
|
||||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
|
||||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
|
int _cryptonite_blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
|
||||||
|
|
||||||
int blake2xb_init( blake2xb_state *S, const size_t outlen );
|
int _cryptonite_blake2xb_init( blake2xb_state *S, const size_t outlen );
|
||||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
|
||||||
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
|
int _cryptonite_blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
|
||||||
|
|
||||||
/* Simple API */
|
/* Simple API */
|
||||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
|
|
||||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
|
|
||||||
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
|
|
||||||
/* This is simply an alias for blake2b */
|
/* This is simply an alias for blake2b */
|
||||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,7 +78,7 @@ static void blake2b_init0( blake2b_state *S )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* init xors IV with input parameter block */
|
/* init xors IV with input parameter block */
|
||||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
int _cryptonite_blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
||||||
{
|
{
|
||||||
const uint8_t *p = ( const uint8_t * )( P );
|
const uint8_t *p = ( const uint8_t * )( P );
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -95,7 +95,7 @@ int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int blake2b_init( blake2b_state *S, size_t outlen )
|
int _cryptonite_blake2b_init( blake2b_state *S, size_t outlen )
|
||||||
{
|
{
|
||||||
blake2b_param P[1];
|
blake2b_param P[1];
|
||||||
|
|
||||||
@ -113,11 +113,11 @@ int blake2b_init( blake2b_state *S, size_t outlen )
|
|||||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
return blake2b_init_param( S, P );
|
return _cryptonite_blake2b_init_param( S, P );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
blake2b_param P[1];
|
blake2b_param P[1];
|
||||||
|
|
||||||
@ -138,13 +138,13 @@ int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t k
|
|||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
|
|
||||||
if( blake2b_init_param( S, P ) < 0 ) return -1;
|
if( _cryptonite_blake2b_init_param( S, P ) < 0 ) return -1;
|
||||||
|
|
||||||
{
|
{
|
||||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
||||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -218,7 +218,7 @@ static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOC
|
|||||||
#undef G
|
#undef G
|
||||||
#undef ROUND
|
#undef ROUND
|
||||||
|
|
||||||
int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
int _cryptonite_blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
||||||
{
|
{
|
||||||
const unsigned char * in = (const unsigned char *)pin;
|
const unsigned char * in = (const unsigned char *)pin;
|
||||||
if( inlen > 0 )
|
if( inlen > 0 )
|
||||||
@ -245,7 +245,7 @@ int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
int _cryptonite_blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
||||||
{
|
{
|
||||||
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -270,7 +270,7 @@ int blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* inlen, at least, should be uint64_t. Others can be size_t. */
|
/* inlen, at least, should be uint64_t. Others can be size_t. */
|
||||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
int _cryptonite_blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
blake2b_state S[1];
|
blake2b_state S[1];
|
||||||
|
|
||||||
@ -287,26 +287,26 @@ int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
|
|
||||||
if( keylen > 0 )
|
if( keylen > 0 )
|
||||||
{
|
{
|
||||||
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
if( _cryptonite_blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( blake2b_init( S, outlen ) < 0 ) return -1;
|
if( _cryptonite_blake2b_init( S, outlen ) < 0 ) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b_update( S, ( const uint8_t * )in, inlen );
|
_cryptonite_blake2b_update( S, ( const uint8_t * )in, inlen );
|
||||||
blake2b_final( S, out, outlen );
|
_cryptonite_blake2b_final( S, out, outlen );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
|
int _cryptonite_blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
|
||||||
return blake2b(out, outlen, in, inlen, key, keylen);
|
return _cryptonite_blake2b(out, outlen, in, inlen, key, keylen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SUPERCOP)
|
#if defined(SUPERCOP)
|
||||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||||
{
|
{
|
||||||
return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
|
return _cryptonite_blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -329,9 +329,9 @@ int main( void )
|
|||||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||||
blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
|
_cryptonite_blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
|
||||||
|
|
||||||
if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
|
if( 0 != memcmp( hash, _cryptonite_blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
|
||||||
{
|
{
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -346,25 +346,25 @@ int main( void )
|
|||||||
size_t mlen = i;
|
size_t mlen = i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2b_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2b_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
if ( (err = _cryptonite_blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
|
if (0 != memcmp(hash, _cryptonite_blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
*/
|
*/
|
||||||
static int blake2bp_init_leaf_param( blake2b_state *S, const blake2b_param *P )
|
static int blake2bp_init_leaf_param( blake2b_state *S, const blake2b_param *P )
|
||||||
{
|
{
|
||||||
int err = blake2b_init_param(S, P);
|
int err = _cryptonite_blake2b_init_param(S, P);
|
||||||
S->outlen = P->inner_length;
|
S->outlen = P->inner_length;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -74,11 +74,11 @@ static int blake2bp_init_root( blake2b_state *S, size_t outlen, size_t keylen )
|
|||||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
return blake2b_init_param( S, P );
|
return _cryptonite_blake2b_init_param( S, P );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2bp_init( blake2bp_state *S, size_t outlen )
|
int _cryptonite_blake2bp_init( blake2bp_state *S, size_t outlen )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ int blake2bp_init( blake2bp_state *S, size_t outlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t
|
|||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );
|
||||||
|
|
||||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
int _cryptonite_blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
||||||
{
|
{
|
||||||
const unsigned char * in = (const unsigned char *)pin;
|
const unsigned char * in = (const unsigned char *)pin;
|
||||||
size_t left = S->buflen;
|
size_t left = S->buflen;
|
||||||
@ -145,7 +145,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
|||||||
memcpy( S->buf + left, in, fill );
|
memcpy( S->buf + left, in, fill );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
|
||||||
|
|
||||||
in += fill;
|
in += fill;
|
||||||
inlen -= fill;
|
inlen -= fill;
|
||||||
@ -168,7 +168,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
|||||||
|
|
||||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
||||||
{
|
{
|
||||||
blake2b_update( S->S[i], in__, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S->S[i], in__, BLAKE2B_BLOCKBYTES );
|
||||||
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
|
int _cryptonite_blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
|
||||||
{
|
{
|
||||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -201,19 +201,19 @@ int blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
|
|||||||
|
|
||||||
if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES;
|
if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES;
|
||||||
|
|
||||||
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left );
|
_cryptonite_blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left );
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );
|
_cryptonite_blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );
|
_cryptonite_blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );
|
||||||
|
|
||||||
return blake2b_final( S->R, out, S->outlen );
|
return _cryptonite_blake2b_final( S->R, out, S->outlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
int _cryptonite_blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
||||||
blake2b_state S[PARALLELISM_DEGREE][1];
|
blake2b_state S[PARALLELISM_DEGREE][1];
|
||||||
@ -243,7 +243,7 @@ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );
|
||||||
|
|
||||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
@ -264,7 +264,7 @@ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
|
|
||||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
||||||
{
|
{
|
||||||
blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
|
||||||
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||||
}
|
}
|
||||||
@ -273,10 +273,10 @@ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
{
|
{
|
||||||
const size_t left = inlen__ - i * BLAKE2B_BLOCKBYTES;
|
const size_t left = inlen__ - i * BLAKE2B_BLOCKBYTES;
|
||||||
const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;
|
const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;
|
||||||
blake2b_update( S[i], in__, len );
|
_cryptonite_blake2b_update( S[i], in__, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b_final( S[i], hash[i], BLAKE2B_OUTBYTES );
|
_cryptonite_blake2b_final( S[i], hash[i], BLAKE2B_OUTBYTES );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( blake2bp_init_root( FS, outlen, keylen ) < 0 )
|
if( blake2bp_init_root( FS, outlen, keylen ) < 0 )
|
||||||
@ -285,9 +285,9 @@ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
FS->last_node = 1; /* Mark as last node */
|
FS->last_node = 1; /* Mark as last node */
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );
|
_cryptonite_blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );
|
||||||
|
|
||||||
return blake2b_final( FS, out, outlen );;
|
return _cryptonite_blake2b_final( FS, out, outlen );;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BLAKE2BP_SELFTEST)
|
#if defined(BLAKE2BP_SELFTEST)
|
||||||
@ -326,21 +326,21 @@ int main( void )
|
|||||||
size_t mlen = i;
|
size_t mlen = i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2bp_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2bp_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2bp_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2bp_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2bp_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2bp_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
if ( (err = _cryptonite_blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -73,7 +73,7 @@ static void blake2s_init0( blake2s_state *S )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* init2 xors IV with input parameter block */
|
/* init2 xors IV with input parameter block */
|
||||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
int _cryptonite_blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
||||||
{
|
{
|
||||||
const unsigned char *p = ( const unsigned char * )( P );
|
const unsigned char *p = ( const unsigned char * )( P );
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -90,7 +90,7 @@ int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
|||||||
|
|
||||||
|
|
||||||
/* Sequential blake2s initialization */
|
/* Sequential blake2s initialization */
|
||||||
int blake2s_init( blake2s_state *S, size_t outlen )
|
int _cryptonite_blake2s_init( blake2s_state *S, size_t outlen )
|
||||||
{
|
{
|
||||||
blake2s_param P[1];
|
blake2s_param P[1];
|
||||||
|
|
||||||
@ -109,10 +109,10 @@ int blake2s_init( blake2s_state *S, size_t outlen )
|
|||||||
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
|
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
|
||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
return blake2s_init_param( S, P );
|
return _cryptonite_blake2s_init_param( S, P );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
blake2s_param P[1];
|
blake2s_param P[1];
|
||||||
|
|
||||||
@ -133,13 +133,13 @@ int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t k
|
|||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
|
|
||||||
if( blake2s_init_param( S, P ) < 0 ) return -1;
|
if( _cryptonite_blake2s_init_param( S, P ) < 0 ) return -1;
|
||||||
|
|
||||||
{
|
{
|
||||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
|
||||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -211,7 +211,7 @@ static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBY
|
|||||||
#undef G
|
#undef G
|
||||||
#undef ROUND
|
#undef ROUND
|
||||||
|
|
||||||
int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
|
int _cryptonite_blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
|
||||||
{
|
{
|
||||||
const unsigned char * in = (const unsigned char *)pin;
|
const unsigned char * in = (const unsigned char *)pin;
|
||||||
if( inlen > 0 )
|
if( inlen > 0 )
|
||||||
@ -238,7 +238,7 @@ int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen )
|
int _cryptonite_blake2s_final( blake2s_state *S, void *out, size_t outlen )
|
||||||
{
|
{
|
||||||
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
|
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -262,7 +262,7 @@ int blake2s_final( blake2s_state *S, void *out, size_t outlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
int _cryptonite_blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
blake2s_state S[1];
|
blake2s_state S[1];
|
||||||
|
|
||||||
@ -279,22 +279,22 @@ int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
|
|
||||||
if( keylen > 0 )
|
if( keylen > 0 )
|
||||||
{
|
{
|
||||||
if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
if( _cryptonite_blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( blake2s_init( S, outlen ) < 0 ) return -1;
|
if( _cryptonite_blake2s_init( S, outlen ) < 0 ) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2s_update( S, ( const uint8_t * )in, inlen );
|
_cryptonite_blake2s_update( S, ( const uint8_t * )in, inlen );
|
||||||
blake2s_final( S, out, outlen );
|
_cryptonite_blake2s_final( S, out, outlen );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SUPERCOP)
|
#if defined(SUPERCOP)
|
||||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||||
{
|
{
|
||||||
return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
|
return _cryptonite_blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ int main( void )
|
|||||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||||
blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
_cryptonite_blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
||||||
|
|
||||||
if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
||||||
{
|
{
|
||||||
@ -334,21 +334,21 @@ int main( void )
|
|||||||
size_t mlen = i;
|
size_t mlen = i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2s_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2s_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2s_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2s_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
if ( (err = _cryptonite_blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
*/
|
*/
|
||||||
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
|
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
|
||||||
{
|
{
|
||||||
int err = blake2s_init_param(S, P);
|
int err = _cryptonite_blake2s_init_param(S, P);
|
||||||
S->outlen = P->inner_length;
|
S->outlen = P->inner_length;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -71,11 +71,11 @@ static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
|
|||||||
P->inner_length = BLAKE2S_OUTBYTES;
|
P->inner_length = BLAKE2S_OUTBYTES;
|
||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
return blake2s_init_param( S, P );
|
return _cryptonite_blake2s_init_param( S, P );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2sp_init( blake2sp_state *S, size_t outlen )
|
int _cryptonite_blake2sp_init( blake2sp_state *S, size_t outlen )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ int blake2sp_init( blake2sp_state *S, size_t outlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t
|
|||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
|
||||||
|
|
||||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
int _cryptonite_blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
||||||
{
|
{
|
||||||
const unsigned char * in = (const unsigned char *)pin;
|
const unsigned char * in = (const unsigned char *)pin;
|
||||||
size_t left = S->buflen;
|
size_t left = S->buflen;
|
||||||
@ -142,7 +142,7 @@ int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
|||||||
memcpy( S->buf + left, in, fill );
|
memcpy( S->buf + left, in, fill );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
||||||
|
|
||||||
in += fill;
|
in += fill;
|
||||||
inlen -= fill;
|
inlen -= fill;
|
||||||
@ -164,7 +164,7 @@ int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
|||||||
|
|
||||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||||
{
|
{
|
||||||
blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
|
||||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
}
|
}
|
||||||
@ -181,7 +181,7 @@ int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
|
int _cryptonite_blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
|
||||||
{
|
{
|
||||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -198,20 +198,20 @@ int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
|
|||||||
|
|
||||||
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
||||||
|
|
||||||
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
_cryptonite_blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
|
_cryptonite_blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
|
_cryptonite_blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
|
||||||
|
|
||||||
return blake2s_final( S->R, out, S->outlen );
|
return _cryptonite_blake2s_final( S->R, out, S->outlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
int _cryptonite_blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||||
blake2s_state S[PARALLELISM_DEGREE][1];
|
blake2s_state S[PARALLELISM_DEGREE][1];
|
||||||
@ -241,7 +241,7 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
|
||||||
|
|
||||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
@ -262,7 +262,7 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
|
|
||||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||||
{
|
{
|
||||||
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
|
||||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
}
|
}
|
||||||
@ -271,10 +271,10 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
{
|
{
|
||||||
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
|
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
|
||||||
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
|
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
|
||||||
blake2s_update( S[i], in__, len );
|
_cryptonite_blake2s_update( S[i], in__, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
|
_cryptonite_blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
|
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
|
||||||
@ -283,9 +283,9 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
FS->last_node = 1;
|
FS->last_node = 1;
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
|
_cryptonite_blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
|
||||||
|
|
||||||
return blake2s_final( FS, out, outlen );
|
return _cryptonite_blake2s_final( FS, out, outlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -309,7 +309,7 @@ int main( void )
|
|||||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||||
blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
_cryptonite_blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
||||||
|
|
||||||
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
||||||
{
|
{
|
||||||
@ -326,21 +326,21 @@ int main( void )
|
|||||||
size_t mlen = i;
|
size_t mlen = i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2sp_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2sp_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
if ( (err = _cryptonite_blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,11 +23,11 @@
|
|||||||
#include "blake2.h"
|
#include "blake2.h"
|
||||||
#include "blake2-impl.h"
|
#include "blake2-impl.h"
|
||||||
|
|
||||||
int blake2xb_init( blake2xb_state *S, const size_t outlen ) {
|
int _cryptonite_blake2xb_init( blake2xb_state *S, const size_t outlen ) {
|
||||||
return blake2xb_init_key(S, outlen, NULL, 0);
|
return _cryptonite_blake2xb_init_key(S, outlen, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen)
|
int _cryptonite_blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen)
|
||||||
{
|
{
|
||||||
if ( outlen == 0 || outlen > 0xFFFFFFFFUL ) {
|
if ( outlen == 0 || outlen > 0xFFFFFFFFUL ) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -55,7 +55,7 @@ int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key,
|
|||||||
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
||||||
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
||||||
|
|
||||||
if( blake2b_init_param( S->S, S->P ) < 0 ) {
|
if( _cryptonite_blake2b_init_param( S->S, S->P ) < 0 ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,17 +63,17 @@ int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key,
|
|||||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||||
memset(block, 0, BLAKE2B_BLOCKBYTES);
|
memset(block, 0, BLAKE2B_BLOCKBYTES);
|
||||||
memcpy(block, key, keylen);
|
memcpy(block, key, keylen);
|
||||||
blake2b_update(S->S, block, BLAKE2B_BLOCKBYTES);
|
_cryptonite_blake2b_update(S->S, block, BLAKE2B_BLOCKBYTES);
|
||||||
secure_zero_memory(block, BLAKE2B_BLOCKBYTES);
|
secure_zero_memory(block, BLAKE2B_BLOCKBYTES);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
|
int _cryptonite_blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
|
||||||
return blake2b_update( S->S, in, inlen );
|
return _cryptonite_blake2b_update( S->S, in, inlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
int _cryptonite_blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
||||||
|
|
||||||
blake2b_state C[1];
|
blake2b_state C[1];
|
||||||
blake2b_param P[1];
|
blake2b_param P[1];
|
||||||
@ -98,7 +98,7 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Finalize the root hash */
|
/* Finalize the root hash */
|
||||||
if (blake2b_final(S->S, root, BLAKE2B_OUTBYTES) < 0) {
|
if (_cryptonite_blake2b_final(S->S, root, BLAKE2B_OUTBYTES) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,10 +117,10 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
|||||||
/* Initialize state */
|
/* Initialize state */
|
||||||
P->digest_length = block_size;
|
P->digest_length = block_size;
|
||||||
store32(&P->node_offset, i);
|
store32(&P->node_offset, i);
|
||||||
blake2b_init_param(C, P);
|
_cryptonite_blake2b_init_param(C, P);
|
||||||
/* Process key if needed */
|
/* Process key if needed */
|
||||||
blake2b_update(C, root, BLAKE2B_OUTBYTES);
|
_cryptonite_blake2b_update(C, root, BLAKE2B_OUTBYTES);
|
||||||
if (blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
|
if (_cryptonite_blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
outlen -= block_size;
|
outlen -= block_size;
|
||||||
@ -133,7 +133,7 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
int _cryptonite_blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
||||||
{
|
{
|
||||||
blake2xb_state S[1];
|
blake2xb_state S[1];
|
||||||
|
|
||||||
@ -154,15 +154,15 @@ int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Initialize the root block structure */
|
/* Initialize the root block structure */
|
||||||
if (blake2xb_init_key(S, outlen, key, keylen) < 0) {
|
if (_cryptonite_blake2xb_init_key(S, outlen, key, keylen) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Absorb the input message */
|
/* Absorb the input message */
|
||||||
blake2xb_update(S, in, inlen);
|
_cryptonite_blake2xb_update(S, in, inlen);
|
||||||
|
|
||||||
/* Compute the root node of the tree and the final hash using the counter construction */
|
/* Compute the root node of the tree and the final hash using the counter construction */
|
||||||
return blake2xb_final(S, out, outlen);
|
return _cryptonite_blake2xb_final(S, out, outlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BLAKE2XB_SELFTEST)
|
#if defined(BLAKE2XB_SELFTEST)
|
||||||
@ -189,7 +189,7 @@ int main( void )
|
|||||||
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
||||||
if( blake2xb( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2B_KEYBYTES ) < 0 ) {
|
if( _cryptonite_blake2xb( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2B_KEYBYTES ) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,21 +208,21 @@ int main( void )
|
|||||||
size_t mlen = BLAKE2_KAT_LENGTH;
|
size_t mlen = BLAKE2_KAT_LENGTH;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2xb_init_key(&S, outlen, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2xb_init_key(&S, outlen, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2xb_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2xb_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2xb_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2xb_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2xb_final(&S, hash, outlen)) < 0) {
|
if ( (err = _cryptonite_blake2xb_final(&S, hash, outlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,11 +23,11 @@
|
|||||||
#include "blake2.h"
|
#include "blake2.h"
|
||||||
#include "blake2-impl.h"
|
#include "blake2-impl.h"
|
||||||
|
|
||||||
int blake2xs_init( blake2xs_state *S, const size_t outlen ) {
|
int _cryptonite_blake2xs_init( blake2xs_state *S, const size_t outlen ) {
|
||||||
return blake2xs_init_key(S, outlen, NULL, 0);
|
return _cryptonite_blake2xs_init_key(S, outlen, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
if ( outlen == 0 || outlen > 0xFFFFUL ) {
|
if ( outlen == 0 || outlen > 0xFFFFUL ) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -54,7 +54,7 @@ int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key,
|
|||||||
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
||||||
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
||||||
|
|
||||||
if( blake2s_init_param( S->S, S->P ) < 0 ) {
|
if( _cryptonite_blake2s_init_param( S->S, S->P ) < 0 ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,17 +62,17 @@ int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key,
|
|||||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||||
memset(block, 0, BLAKE2S_BLOCKBYTES);
|
memset(block, 0, BLAKE2S_BLOCKBYTES);
|
||||||
memcpy(block, key, keylen);
|
memcpy(block, key, keylen);
|
||||||
blake2s_update(S->S, block, BLAKE2S_BLOCKBYTES);
|
_cryptonite_blake2s_update(S->S, block, BLAKE2S_BLOCKBYTES);
|
||||||
secure_zero_memory(block, BLAKE2S_BLOCKBYTES);
|
secure_zero_memory(block, BLAKE2S_BLOCKBYTES);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
|
int _cryptonite_blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
|
||||||
return blake2s_update( S->S, in, inlen );
|
return _cryptonite_blake2s_update( S->S, in, inlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
int _cryptonite_blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
||||||
|
|
||||||
blake2s_state C[1];
|
blake2s_state C[1];
|
||||||
blake2s_param P[1];
|
blake2s_param P[1];
|
||||||
@ -97,7 +97,7 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Finalize the root hash */
|
/* Finalize the root hash */
|
||||||
if (blake2s_final(S->S, root, BLAKE2S_OUTBYTES) < 0) {
|
if (_cryptonite_blake2s_final(S->S, root, BLAKE2S_OUTBYTES) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,10 +116,10 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
|||||||
/* Initialize state */
|
/* Initialize state */
|
||||||
P->digest_length = block_size;
|
P->digest_length = block_size;
|
||||||
store32(&P->node_offset, i);
|
store32(&P->node_offset, i);
|
||||||
blake2s_init_param(C, P);
|
_cryptonite_blake2s_init_param(C, P);
|
||||||
/* Process key if needed */
|
/* Process key if needed */
|
||||||
blake2s_update(C, root, BLAKE2S_OUTBYTES);
|
_cryptonite_blake2s_update(C, root, BLAKE2S_OUTBYTES);
|
||||||
if (blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
|
if (_cryptonite_blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
outlen -= block_size;
|
outlen -= block_size;
|
||||||
@ -131,7 +131,7 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
int _cryptonite_blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
||||||
{
|
{
|
||||||
blake2xs_state S[1];
|
blake2xs_state S[1];
|
||||||
|
|
||||||
@ -152,15 +152,15 @@ int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Initialize the root block structure */
|
/* Initialize the root block structure */
|
||||||
if (blake2xs_init_key(S, outlen, key, keylen) < 0) {
|
if (_cryptonite_blake2xs_init_key(S, outlen, key, keylen) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Absorb the input message */
|
/* Absorb the input message */
|
||||||
blake2xs_update(S, in, inlen);
|
_cryptonite_blake2xs_update(S, in, inlen);
|
||||||
|
|
||||||
/* Compute the root node of the tree and the final hash using the counter construction */
|
/* Compute the root node of the tree and the final hash using the counter construction */
|
||||||
return blake2xs_final(S, out, outlen);
|
return _cryptonite_blake2xs_final(S, out, outlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BLAKE2XS_SELFTEST)
|
#if defined(BLAKE2XS_SELFTEST)
|
||||||
@ -187,7 +187,7 @@ int main( void )
|
|||||||
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
||||||
if( blake2xs( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2S_KEYBYTES ) < 0 ) {
|
if( _cryptonite_blake2xs( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2S_KEYBYTES ) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,21 +206,21 @@ int main( void )
|
|||||||
size_t mlen = BLAKE2_KAT_LENGTH;
|
size_t mlen = BLAKE2_KAT_LENGTH;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2xs_init_key(&S, outlen, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2xs_init_key(&S, outlen, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2xs_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2xs_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2xs_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2xs_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2xs_final(&S, hash, outlen)) < 0) {
|
if ( (err = _cryptonite_blake2xs_final(&S, hash, outlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -142,51 +142,51 @@ extern "C" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Streaming API */
|
/* Streaming API */
|
||||||
int blake2s_init( blake2s_state *S, size_t outlen );
|
int _cryptonite_blake2s_init( blake2s_state *S, size_t outlen );
|
||||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
|
int _cryptonite_blake2s_init_param( blake2s_state *S, const blake2s_param *P );
|
||||||
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2s_update( blake2s_state *S, const void *in, size_t inlen );
|
||||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
|
int _cryptonite_blake2s_final( blake2s_state *S, void *out, size_t outlen );
|
||||||
|
|
||||||
int blake2b_init( blake2b_state *S, size_t outlen );
|
int _cryptonite_blake2b_init( blake2b_state *S, size_t outlen );
|
||||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
int _cryptonite_blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
||||||
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2b_update( blake2b_state *S, const void *in, size_t inlen );
|
||||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
|
int _cryptonite_blake2b_final( blake2b_state *S, void *out, size_t outlen );
|
||||||
|
|
||||||
int blake2sp_init( blake2sp_state *S, size_t outlen );
|
int _cryptonite_blake2sp_init( blake2sp_state *S, size_t outlen );
|
||||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
|
||||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
|
int _cryptonite_blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
|
||||||
|
|
||||||
int blake2bp_init( blake2bp_state *S, size_t outlen );
|
int _cryptonite_blake2bp_init( blake2bp_state *S, size_t outlen );
|
||||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
|
||||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
|
int _cryptonite_blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
|
||||||
|
|
||||||
/* Variable output length API */
|
/* Variable output length API */
|
||||||
int blake2xs_init( blake2xs_state *S, const size_t outlen );
|
int _cryptonite_blake2xs_init( blake2xs_state *S, const size_t outlen );
|
||||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
|
||||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
|
int _cryptonite_blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
|
||||||
|
|
||||||
int blake2xb_init( blake2xb_state *S, const size_t outlen );
|
int _cryptonite_blake2xb_init( blake2xb_state *S, const size_t outlen );
|
||||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
|
int _cryptonite_blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
|
int _cryptonite_blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
|
||||||
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
|
int _cryptonite_blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
|
||||||
|
|
||||||
/* Simple API */
|
/* Simple API */
|
||||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
|
|
||||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
|
|
||||||
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
|
|
||||||
/* This is simply an alias for blake2b */
|
/* This is simply an alias for blake2b */
|
||||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
int _cryptonite_blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,7 +74,7 @@ static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* init xors IV with input parameter block */
|
/* init xors IV with input parameter block */
|
||||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
int _cryptonite_blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
/*blake2b_init0( S ); */
|
/*blake2b_init0( S ); */
|
||||||
@ -92,7 +92,7 @@ int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
|||||||
|
|
||||||
|
|
||||||
/* Some sort of default parameter block initialization, for sequential blake2b */
|
/* Some sort of default parameter block initialization, for sequential blake2b */
|
||||||
int blake2b_init( blake2b_state *S, size_t outlen )
|
int _cryptonite_blake2b_init( blake2b_state *S, size_t outlen )
|
||||||
{
|
{
|
||||||
blake2b_param P[1];
|
blake2b_param P[1];
|
||||||
|
|
||||||
@ -111,10 +111,10 @@ int blake2b_init( blake2b_state *S, size_t outlen )
|
|||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
|
|
||||||
return blake2b_init_param( S, P );
|
return _cryptonite_blake2b_init_param( S, P );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
blake2b_param P[1];
|
blake2b_param P[1];
|
||||||
|
|
||||||
@ -135,14 +135,14 @@ int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t k
|
|||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
|
|
||||||
if( blake2b_init_param( S, P ) < 0 )
|
if( _cryptonite_blake2b_init_param( S, P ) < 0 )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
||||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -218,7 +218,7 @@ static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOC
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
int _cryptonite_blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
||||||
{
|
{
|
||||||
const unsigned char * in = (const unsigned char *)pin;
|
const unsigned char * in = (const unsigned char *)pin;
|
||||||
if( inlen > 0 )
|
if( inlen > 0 )
|
||||||
@ -246,7 +246,7 @@ int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
int _cryptonite_blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
||||||
{
|
{
|
||||||
if( out == NULL || outlen < S->outlen )
|
if( out == NULL || outlen < S->outlen )
|
||||||
return -1;
|
return -1;
|
||||||
@ -264,7 +264,7 @@ int blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
int _cryptonite_blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
blake2b_state S[1];
|
blake2b_state S[1];
|
||||||
|
|
||||||
@ -281,26 +281,26 @@ int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
|
|
||||||
if( keylen )
|
if( keylen )
|
||||||
{
|
{
|
||||||
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
if( _cryptonite_blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( blake2b_init( S, outlen ) < 0 ) return -1;
|
if( _cryptonite_blake2b_init( S, outlen ) < 0 ) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b_update( S, ( const uint8_t * )in, inlen );
|
_cryptonite_blake2b_update( S, ( const uint8_t * )in, inlen );
|
||||||
blake2b_final( S, out, outlen );
|
_cryptonite_blake2b_final( S, out, outlen );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
|
int _cryptonite_blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
|
||||||
return blake2b(out, outlen, in, inlen, key, keylen);
|
return _cryptonite_blake2b(out, outlen, in, inlen, key, keylen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SUPERCOP)
|
#if defined(SUPERCOP)
|
||||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||||
{
|
{
|
||||||
return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
|
return _cryptonite_blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -340,21 +340,21 @@ int main( void )
|
|||||||
size_t mlen = i;
|
size_t mlen = i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2b_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2b_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
if ( (err = _cryptonite_blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
*/
|
*/
|
||||||
static int blake2bp_init_leaf_param( blake2b_state *S, const blake2b_param *P )
|
static int blake2bp_init_leaf_param( blake2b_state *S, const blake2b_param *P )
|
||||||
{
|
{
|
||||||
int err = blake2b_init_param(S, P);
|
int err = _cryptonite_blake2b_init_param(S, P);
|
||||||
S->outlen = P->inner_length;
|
S->outlen = P->inner_length;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -74,11 +74,11 @@ static int blake2bp_init_root( blake2b_state *S, size_t outlen, size_t keylen )
|
|||||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
return blake2b_init_param( S, P );
|
return _cryptonite_blake2b_init_param( S, P );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2bp_init( blake2bp_state *S, size_t outlen )
|
int _cryptonite_blake2bp_init( blake2bp_state *S, size_t outlen )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
|
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
|
||||||
@ -98,7 +98,7 @@ int blake2bp_init( blake2bp_state *S, size_t outlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t
|
|||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );
|
||||||
|
|
||||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
int _cryptonite_blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
||||||
{
|
{
|
||||||
const unsigned char * in = (const unsigned char *)pin;
|
const unsigned char * in = (const unsigned char *)pin;
|
||||||
size_t left = S->buflen;
|
size_t left = S->buflen;
|
||||||
@ -144,7 +144,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
|||||||
memcpy( S->buf + left, in, fill );
|
memcpy( S->buf + left, in, fill );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
|
||||||
|
|
||||||
in += fill;
|
in += fill;
|
||||||
inlen -= fill;
|
inlen -= fill;
|
||||||
@ -167,7 +167,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
|||||||
|
|
||||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
||||||
{
|
{
|
||||||
blake2b_update( S->S[i], in__, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S->S[i], in__, BLAKE2B_BLOCKBYTES );
|
||||||
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
|
int _cryptonite_blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
|
||||||
{
|
{
|
||||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -202,19 +202,19 @@ int blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
|
|||||||
|
|
||||||
if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES;
|
if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES;
|
||||||
|
|
||||||
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left );
|
_cryptonite_blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left );
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );
|
_cryptonite_blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );
|
_cryptonite_blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );
|
||||||
|
|
||||||
return blake2b_final( S->R, out, S->outlen );
|
return _cryptonite_blake2b_final( S->R, out, S->outlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
int _cryptonite_blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
||||||
blake2b_state S[PARALLELISM_DEGREE][1];
|
blake2b_state S[PARALLELISM_DEGREE][1];
|
||||||
@ -244,7 +244,7 @@ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );
|
||||||
|
|
||||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
@ -265,7 +265,7 @@ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
|
|
||||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
||||||
{
|
{
|
||||||
blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
|
_cryptonite_blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
|
||||||
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||||
}
|
}
|
||||||
@ -274,10 +274,10 @@ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
{
|
{
|
||||||
const size_t left = inlen__ - i * BLAKE2B_BLOCKBYTES;
|
const size_t left = inlen__ - i * BLAKE2B_BLOCKBYTES;
|
||||||
const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;
|
const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;
|
||||||
blake2b_update( S[i], in__, len );
|
_cryptonite_blake2b_update( S[i], in__, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b_final( S[i], hash[i], BLAKE2B_OUTBYTES );
|
_cryptonite_blake2b_final( S[i], hash[i], BLAKE2B_OUTBYTES );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( blake2bp_init_root( FS, outlen, keylen ) < 0 )
|
if( blake2bp_init_root( FS, outlen, keylen ) < 0 )
|
||||||
@ -286,9 +286,9 @@ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
FS->last_node = 1; /* Mark as last node */
|
FS->last_node = 1; /* Mark as last node */
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );
|
_cryptonite_blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );
|
||||||
|
|
||||||
return blake2b_final( FS, out, outlen );
|
return _cryptonite_blake2b_final( FS, out, outlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ int main( void )
|
|||||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||||
blake2bp( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
|
_cryptonite_blake2bp( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
|
||||||
|
|
||||||
if( 0 != memcmp( hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES ) )
|
if( 0 != memcmp( hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES ) )
|
||||||
{
|
{
|
||||||
@ -328,21 +328,21 @@ int main( void )
|
|||||||
size_t mlen = i;
|
size_t mlen = i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2bp_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2bp_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2bp_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2bp_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2bp_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2bp_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
if ( (err = _cryptonite_blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -72,7 +72,7 @@ static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* init2 xors IV with input parameter block */
|
/* init2 xors IV with input parameter block */
|
||||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
int _cryptonite_blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
/*blake2s_init0( S ); */
|
/*blake2s_init0( S ); */
|
||||||
@ -90,7 +90,7 @@ int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
|||||||
|
|
||||||
|
|
||||||
/* Some sort of default parameter block initialization, for sequential blake2s */
|
/* Some sort of default parameter block initialization, for sequential blake2s */
|
||||||
int blake2s_init( blake2s_state *S, size_t outlen )
|
int _cryptonite_blake2s_init( blake2s_state *S, size_t outlen )
|
||||||
{
|
{
|
||||||
blake2s_param P[1];
|
blake2s_param P[1];
|
||||||
|
|
||||||
@ -110,11 +110,11 @@ int blake2s_init( blake2s_state *S, size_t outlen )
|
|||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
|
|
||||||
return blake2s_init_param( S, P );
|
return _cryptonite_blake2s_init_param( S, P );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
blake2s_param P[1];
|
blake2s_param P[1];
|
||||||
|
|
||||||
@ -136,14 +136,14 @@ int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t k
|
|||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
|
|
||||||
if( blake2s_init_param( S, P ) < 0 )
|
if( _cryptonite_blake2s_init_param( S, P ) < 0 )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
{
|
{
|
||||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
|
||||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -206,7 +206,7 @@ static void blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOC
|
|||||||
STOREU( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row2, row4 ) ) );
|
STOREU( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row2, row4 ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
|
int _cryptonite_blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
|
||||||
{
|
{
|
||||||
const unsigned char * in = (const unsigned char *)pin;
|
const unsigned char * in = (const unsigned char *)pin;
|
||||||
if( inlen > 0 )
|
if( inlen > 0 )
|
||||||
@ -233,7 +233,7 @@ int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen )
|
int _cryptonite_blake2s_final( blake2s_state *S, void *out, size_t outlen )
|
||||||
{
|
{
|
||||||
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
|
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -275,15 +275,15 @@ int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
|
|
||||||
if( keylen > 0 )
|
if( keylen > 0 )
|
||||||
{
|
{
|
||||||
if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
if( _cryptonite_blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( blake2s_init( S, outlen ) < 0 ) return -1;
|
if( _cryptonite_blake2s_init( S, outlen ) < 0 ) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2s_update( S, ( const uint8_t * )in, inlen );
|
_cryptonite_blake2s_update( S, ( const uint8_t * )in, inlen );
|
||||||
blake2s_final( S, out, outlen );
|
_cryptonite_blake2s_final( S, out, outlen );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,21 +330,21 @@ int main( void )
|
|||||||
size_t mlen = i;
|
size_t mlen = i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2s_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2s_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2s_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2s_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
if ( (err = _cryptonite_blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
*/
|
*/
|
||||||
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
|
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
|
||||||
{
|
{
|
||||||
int err = blake2s_init_param(S, P);
|
int err = _cryptonite_blake2s_init_param(S, P);
|
||||||
S->outlen = P->inner_length;
|
S->outlen = P->inner_length;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -71,11 +71,11 @@ static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
|
|||||||
P->inner_length = BLAKE2S_OUTBYTES;
|
P->inner_length = BLAKE2S_OUTBYTES;
|
||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
memset( P->salt, 0, sizeof( P->salt ) );
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
memset( P->personal, 0, sizeof( P->personal ) );
|
||||||
return blake2s_init_param( S, P );
|
return _cryptonite_blake2s_init_param( S, P );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2sp_init( blake2sp_state *S, size_t outlen )
|
int _cryptonite_blake2sp_init( blake2sp_state *S, size_t outlen )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ int blake2sp_init( blake2sp_state *S, size_t outlen )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t
|
|||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
|
||||||
|
|
||||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
int _cryptonite_blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
||||||
{
|
{
|
||||||
const unsigned char * in = (const unsigned char *)pin;
|
const unsigned char * in = (const unsigned char *)pin;
|
||||||
size_t left = S->buflen;
|
size_t left = S->buflen;
|
||||||
@ -142,7 +142,7 @@ int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
|||||||
memcpy( S->buf + left, in, fill );
|
memcpy( S->buf + left, in, fill );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
||||||
|
|
||||||
in += fill;
|
in += fill;
|
||||||
inlen -= fill;
|
inlen -= fill;
|
||||||
@ -165,7 +165,7 @@ int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
|||||||
|
|
||||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||||
{
|
{
|
||||||
blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
|
||||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
|
int _cryptonite_blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
|
||||||
{
|
{
|
||||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -199,20 +199,20 @@ int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
|
|||||||
|
|
||||||
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
||||||
|
|
||||||
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
_cryptonite_blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
|
_cryptonite_blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
|
_cryptonite_blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
|
||||||
|
|
||||||
return blake2s_final( S->R, out, S->outlen );
|
return _cryptonite_blake2s_final( S->R, out, S->outlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
int _cryptonite_blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||||
blake2s_state S[PARALLELISM_DEGREE][1];
|
blake2s_state S[PARALLELISM_DEGREE][1];
|
||||||
@ -242,7 +242,7 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
memcpy( block, key, keylen );
|
memcpy( block, key, keylen );
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
|
||||||
|
|
||||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
|
|
||||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||||
{
|
{
|
||||||
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
|
_cryptonite_blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
|
||||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||||
}
|
}
|
||||||
@ -272,10 +272,10 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
{
|
{
|
||||||
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
|
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
|
||||||
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
|
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
|
||||||
blake2s_update( S[i], in__, len );
|
_cryptonite_blake2s_update( S[i], in__, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
|
_cryptonite_blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
|
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
|
||||||
@ -284,9 +284,9 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
FS->last_node = 1;
|
FS->last_node = 1;
|
||||||
|
|
||||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||||
blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
|
_cryptonite_blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
|
||||||
|
|
||||||
return blake2s_final( FS, out, outlen );
|
return _cryptonite_blake2s_final( FS, out, outlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BLAKE2SP_SELFTEST)
|
#if defined(BLAKE2SP_SELFTEST)
|
||||||
@ -308,7 +308,7 @@ int main( void )
|
|||||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||||
blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
_cryptonite_blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
||||||
|
|
||||||
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
||||||
{
|
{
|
||||||
@ -325,21 +325,21 @@ int main( void )
|
|||||||
size_t mlen = i;
|
size_t mlen = i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2sp_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2sp_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
if ( (err = _cryptonite_blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,11 +23,11 @@
|
|||||||
#include "blake2.h"
|
#include "blake2.h"
|
||||||
#include "blake2-impl.h"
|
#include "blake2-impl.h"
|
||||||
|
|
||||||
int blake2xb_init( blake2xb_state *S, const size_t outlen ) {
|
int _cryptonite_blake2xb_init( blake2xb_state *S, const size_t outlen ) {
|
||||||
return blake2xb_init_key(S, outlen, NULL, 0);
|
return _cryptonite_blake2xb_init_key(S, outlen, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen)
|
int _cryptonite_blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen)
|
||||||
{
|
{
|
||||||
if ( outlen == 0 || outlen > 0xFFFFFFFFUL ) {
|
if ( outlen == 0 || outlen > 0xFFFFFFFFUL ) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -55,7 +55,7 @@ int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key,
|
|||||||
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
||||||
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
||||||
|
|
||||||
if( blake2b_init_param( S->S, S->P ) < 0 ) {
|
if( _cryptonite_blake2b_init_param( S->S, S->P ) < 0 ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,17 +63,17 @@ int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key,
|
|||||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||||
memset(block, 0, BLAKE2B_BLOCKBYTES);
|
memset(block, 0, BLAKE2B_BLOCKBYTES);
|
||||||
memcpy(block, key, keylen);
|
memcpy(block, key, keylen);
|
||||||
blake2b_update(S->S, block, BLAKE2B_BLOCKBYTES);
|
_cryptonite_blake2b_update(S->S, block, BLAKE2B_BLOCKBYTES);
|
||||||
secure_zero_memory(block, BLAKE2B_BLOCKBYTES);
|
secure_zero_memory(block, BLAKE2B_BLOCKBYTES);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
|
int _cryptonite_blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
|
||||||
return blake2b_update( S->S, in, inlen );
|
return _cryptonite_blake2b_update( S->S, in, inlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
int _cryptonite_blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
||||||
|
|
||||||
blake2b_state C[1];
|
blake2b_state C[1];
|
||||||
blake2b_param P[1];
|
blake2b_param P[1];
|
||||||
@ -98,7 +98,7 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Finalize the root hash */
|
/* Finalize the root hash */
|
||||||
if (blake2b_final(S->S, root, BLAKE2B_OUTBYTES) < 0) {
|
if (_cryptonite_blake2b_final(S->S, root, BLAKE2B_OUTBYTES) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,10 +117,10 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
|||||||
/* Initialize state */
|
/* Initialize state */
|
||||||
P->digest_length = block_size;
|
P->digest_length = block_size;
|
||||||
store32(&P->node_offset, i);
|
store32(&P->node_offset, i);
|
||||||
blake2b_init_param(C, P);
|
_cryptonite_blake2b_init_param(C, P);
|
||||||
/* Process key if needed */
|
/* Process key if needed */
|
||||||
blake2b_update(C, root, BLAKE2B_OUTBYTES);
|
_cryptonite_blake2b_update(C, root, BLAKE2B_OUTBYTES);
|
||||||
if (blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
|
if (_cryptonite_blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
outlen -= block_size;
|
outlen -= block_size;
|
||||||
@ -133,7 +133,7 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
int _cryptonite_blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
||||||
{
|
{
|
||||||
blake2xb_state S[1];
|
blake2xb_state S[1];
|
||||||
|
|
||||||
@ -154,15 +154,15 @@ int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Initialize the root block structure */
|
/* Initialize the root block structure */
|
||||||
if (blake2xb_init_key(S, outlen, key, keylen) < 0) {
|
if (_cryptonite_blake2xb_init_key(S, outlen, key, keylen) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Absorb the input message */
|
/* Absorb the input message */
|
||||||
blake2xb_update(S, in, inlen);
|
_cryptonite_blake2xb_update(S, in, inlen);
|
||||||
|
|
||||||
/* Compute the root node of the tree and the final hash using the counter construction */
|
/* Compute the root node of the tree and the final hash using the counter construction */
|
||||||
return blake2xb_final(S, out, outlen);
|
return _cryptonite_blake2xb_final(S, out, outlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BLAKE2XB_SELFTEST)
|
#if defined(BLAKE2XB_SELFTEST)
|
||||||
@ -189,7 +189,7 @@ int main( void )
|
|||||||
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
||||||
if( blake2xb( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2B_KEYBYTES ) < 0 ) {
|
if( _cryptonite_blake2xb( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2B_KEYBYTES ) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,21 +208,21 @@ int main( void )
|
|||||||
size_t mlen = BLAKE2_KAT_LENGTH;
|
size_t mlen = BLAKE2_KAT_LENGTH;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2xb_init_key(&S, outlen, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2xb_init_key(&S, outlen, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2xb_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2xb_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2xb_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2xb_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2xb_final(&S, hash, outlen)) < 0) {
|
if ( (err = _cryptonite_blake2xb_final(&S, hash, outlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,11 +23,11 @@
|
|||||||
#include "blake2.h"
|
#include "blake2.h"
|
||||||
#include "blake2-impl.h"
|
#include "blake2-impl.h"
|
||||||
|
|
||||||
int blake2xs_init( blake2xs_state *S, const size_t outlen ) {
|
int _cryptonite_blake2xs_init( blake2xs_state *S, const size_t outlen ) {
|
||||||
return blake2xs_init_key(S, outlen, NULL, 0);
|
return _cryptonite_blake2xs_init_key(S, outlen, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen )
|
int _cryptonite_blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen )
|
||||||
{
|
{
|
||||||
if ( outlen == 0 || outlen > 0xFFFFUL ) {
|
if ( outlen == 0 || outlen > 0xFFFFUL ) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -54,7 +54,7 @@ int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key,
|
|||||||
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
||||||
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
||||||
|
|
||||||
if( blake2s_init_param( S->S, S->P ) < 0 ) {
|
if( _cryptonite_blake2s_init_param( S->S, S->P ) < 0 ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,17 +62,17 @@ int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key,
|
|||||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||||
memset(block, 0, BLAKE2S_BLOCKBYTES);
|
memset(block, 0, BLAKE2S_BLOCKBYTES);
|
||||||
memcpy(block, key, keylen);
|
memcpy(block, key, keylen);
|
||||||
blake2s_update(S->S, block, BLAKE2S_BLOCKBYTES);
|
_cryptonite_blake2s_update(S->S, block, BLAKE2S_BLOCKBYTES);
|
||||||
secure_zero_memory(block, BLAKE2S_BLOCKBYTES);
|
secure_zero_memory(block, BLAKE2S_BLOCKBYTES);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
|
int _cryptonite_blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
|
||||||
return blake2s_update( S->S, in, inlen );
|
return _cryptonite_blake2s_update( S->S, in, inlen );
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
int _cryptonite_blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
||||||
|
|
||||||
blake2s_state C[1];
|
blake2s_state C[1];
|
||||||
blake2s_param P[1];
|
blake2s_param P[1];
|
||||||
@ -97,7 +97,7 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Finalize the root hash */
|
/* Finalize the root hash */
|
||||||
if (blake2s_final(S->S, root, BLAKE2S_OUTBYTES) < 0) {
|
if (_cryptonite_blake2s_final(S->S, root, BLAKE2S_OUTBYTES) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,10 +116,10 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
|||||||
/* Initialize state */
|
/* Initialize state */
|
||||||
P->digest_length = block_size;
|
P->digest_length = block_size;
|
||||||
store32(&P->node_offset, i);
|
store32(&P->node_offset, i);
|
||||||
blake2s_init_param(C, P);
|
_cryptonite_blake2s_init_param(C, P);
|
||||||
/* Process key if needed */
|
/* Process key if needed */
|
||||||
blake2s_update(C, root, BLAKE2S_OUTBYTES);
|
_cryptonite_blake2s_update(C, root, BLAKE2S_OUTBYTES);
|
||||||
if (blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
|
if (_cryptonite_blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
outlen -= block_size;
|
outlen -= block_size;
|
||||||
@ -131,7 +131,7 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
int _cryptonite_blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
||||||
{
|
{
|
||||||
blake2xs_state S[1];
|
blake2xs_state S[1];
|
||||||
|
|
||||||
@ -152,15 +152,15 @@ int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Initialize the root block structure */
|
/* Initialize the root block structure */
|
||||||
if (blake2xs_init_key(S, outlen, key, keylen) < 0) {
|
if (_cryptonite_blake2xs_init_key(S, outlen, key, keylen) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Absorb the input message */
|
/* Absorb the input message */
|
||||||
blake2xs_update(S, in, inlen);
|
_cryptonite_blake2xs_update(S, in, inlen);
|
||||||
|
|
||||||
/* Compute the root node of the tree and the final hash using the counter construction */
|
/* Compute the root node of the tree and the final hash using the counter construction */
|
||||||
return blake2xs_final(S, out, outlen);
|
return _cryptonite_blake2xs_final(S, out, outlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BLAKE2XS_SELFTEST)
|
#if defined(BLAKE2XS_SELFTEST)
|
||||||
@ -187,7 +187,7 @@ int main( void )
|
|||||||
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
||||||
{
|
{
|
||||||
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
||||||
if( blake2xs( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2S_KEYBYTES ) < 0 ) {
|
if( _cryptonite_blake2xs( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2S_KEYBYTES ) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,21 +206,21 @@ int main( void )
|
|||||||
size_t mlen = BLAKE2_KAT_LENGTH;
|
size_t mlen = BLAKE2_KAT_LENGTH;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if( (err = blake2xs_init_key(&S, outlen, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
if( (err = _cryptonite_blake2xs_init_key(&S, outlen, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mlen >= step) {
|
while (mlen >= step) {
|
||||||
if ( (err = blake2xs_update(&S, p, step)) < 0 ) {
|
if ( (err = _cryptonite_blake2xs_update(&S, p, step)) < 0 ) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mlen -= step;
|
mlen -= step;
|
||||||
p += step;
|
p += step;
|
||||||
}
|
}
|
||||||
if ( (err = blake2xs_update(&S, p, mlen)) < 0) {
|
if ( (err = _cryptonite_blake2xs_update(&S, p, mlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ( (err = blake2xs_final(&S, hash, outlen)) < 0) {
|
if ( (err = _cryptonite_blake2xs_final(&S, hash, outlen)) < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,7 @@ void cryptonite_aes_generic_decrypt_ecb(aes_block *output, aes_key *key, aes_blo
|
|||||||
void cryptonite_aes_generic_encrypt_cbc(aes_block *output, aes_key *key, aes_block *iv, aes_block *input, uint32_t nb_blocks);
|
void cryptonite_aes_generic_encrypt_cbc(aes_block *output, aes_key *key, aes_block *iv, aes_block *input, uint32_t nb_blocks);
|
||||||
void cryptonite_aes_generic_decrypt_cbc(aes_block *output, aes_key *key, aes_block *iv, aes_block *input, uint32_t nb_blocks);
|
void cryptonite_aes_generic_decrypt_cbc(aes_block *output, aes_key *key, aes_block *iv, aes_block *input, uint32_t nb_blocks);
|
||||||
void cryptonite_aes_generic_encrypt_ctr(uint8_t *output, aes_key *key, aes_block *iv, uint8_t *input, uint32_t length);
|
void cryptonite_aes_generic_encrypt_ctr(uint8_t *output, aes_key *key, aes_block *iv, uint8_t *input, uint32_t length);
|
||||||
|
void cryptonite_aes_generic_encrypt_c32(uint8_t *output, aes_key *key, aes_block *iv, uint8_t *input, uint32_t length);
|
||||||
void cryptonite_aes_generic_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,
|
void cryptonite_aes_generic_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,
|
||||||
uint32_t spoint, aes_block *input, uint32_t nb_blocks);
|
uint32_t spoint, aes_block *input, uint32_t nb_blocks);
|
||||||
void cryptonite_aes_generic_decrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,
|
void cryptonite_aes_generic_decrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,
|
||||||
@ -69,6 +70,8 @@ enum {
|
|||||||
DECRYPT_CBC_128, DECRYPT_CBC_192, DECRYPT_CBC_256,
|
DECRYPT_CBC_128, DECRYPT_CBC_192, DECRYPT_CBC_256,
|
||||||
/* ctr */
|
/* ctr */
|
||||||
ENCRYPT_CTR_128, ENCRYPT_CTR_192, ENCRYPT_CTR_256,
|
ENCRYPT_CTR_128, ENCRYPT_CTR_192, ENCRYPT_CTR_256,
|
||||||
|
/* ctr with 32-bit wrapping */
|
||||||
|
ENCRYPT_C32_128, ENCRYPT_C32_192, ENCRYPT_C32_256,
|
||||||
/* xts */
|
/* xts */
|
||||||
ENCRYPT_XTS_128, ENCRYPT_XTS_192, ENCRYPT_XTS_256,
|
ENCRYPT_XTS_128, ENCRYPT_XTS_192, ENCRYPT_XTS_256,
|
||||||
DECRYPT_XTS_128, DECRYPT_XTS_192, DECRYPT_XTS_256,
|
DECRYPT_XTS_128, DECRYPT_XTS_192, DECRYPT_XTS_256,
|
||||||
@ -82,7 +85,7 @@ enum {
|
|||||||
ENCRYPT_CCM_128, ENCRYPT_CCM_192, ENCRYPT_CCM_256,
|
ENCRYPT_CCM_128, ENCRYPT_CCM_192, ENCRYPT_CCM_256,
|
||||||
DECRYPT_CCM_128, DECRYPT_CCM_192, DECRYPT_CCM_256,
|
DECRYPT_CCM_128, DECRYPT_CCM_192, DECRYPT_CCM_256,
|
||||||
/* ghash */
|
/* ghash */
|
||||||
GHASH_GF_MUL,
|
GHASH_HINIT, GHASH_GF_MUL,
|
||||||
};
|
};
|
||||||
|
|
||||||
void *cryptonite_aes_branch_table[] = {
|
void *cryptonite_aes_branch_table[] = {
|
||||||
@ -115,6 +118,10 @@ void *cryptonite_aes_branch_table[] = {
|
|||||||
[ENCRYPT_CTR_128] = cryptonite_aes_generic_encrypt_ctr,
|
[ENCRYPT_CTR_128] = cryptonite_aes_generic_encrypt_ctr,
|
||||||
[ENCRYPT_CTR_192] = cryptonite_aes_generic_encrypt_ctr,
|
[ENCRYPT_CTR_192] = cryptonite_aes_generic_encrypt_ctr,
|
||||||
[ENCRYPT_CTR_256] = cryptonite_aes_generic_encrypt_ctr,
|
[ENCRYPT_CTR_256] = cryptonite_aes_generic_encrypt_ctr,
|
||||||
|
/* CTR with 32-bit wrapping */
|
||||||
|
[ENCRYPT_C32_128] = cryptonite_aes_generic_encrypt_c32,
|
||||||
|
[ENCRYPT_C32_192] = cryptonite_aes_generic_encrypt_c32,
|
||||||
|
[ENCRYPT_C32_256] = cryptonite_aes_generic_encrypt_c32,
|
||||||
/* XTS */
|
/* XTS */
|
||||||
[ENCRYPT_XTS_128] = cryptonite_aes_generic_encrypt_xts,
|
[ENCRYPT_XTS_128] = cryptonite_aes_generic_encrypt_xts,
|
||||||
[ENCRYPT_XTS_192] = cryptonite_aes_generic_encrypt_xts,
|
[ENCRYPT_XTS_192] = cryptonite_aes_generic_encrypt_xts,
|
||||||
@ -144,6 +151,7 @@ void *cryptonite_aes_branch_table[] = {
|
|||||||
[DECRYPT_CCM_192] = cryptonite_aes_generic_ccm_decrypt,
|
[DECRYPT_CCM_192] = cryptonite_aes_generic_ccm_decrypt,
|
||||||
[DECRYPT_CCM_256] = cryptonite_aes_generic_ccm_decrypt,
|
[DECRYPT_CCM_256] = cryptonite_aes_generic_ccm_decrypt,
|
||||||
/* GHASH */
|
/* GHASH */
|
||||||
|
[GHASH_HINIT] = cryptonite_aes_generic_hinit,
|
||||||
[GHASH_GF_MUL] = cryptonite_aes_generic_gf_mul,
|
[GHASH_GF_MUL] = cryptonite_aes_generic_gf_mul,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -156,7 +164,8 @@ typedef void (*gcm_crypt_f)(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t
|
|||||||
typedef void (*ocb_crypt_f)(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length);
|
typedef void (*ocb_crypt_f)(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length);
|
||||||
typedef void (*ccm_crypt_f)(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length);
|
typedef void (*ccm_crypt_f)(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length);
|
||||||
typedef void (*block_f)(aes_block *output, aes_key *key, aes_block *input);
|
typedef void (*block_f)(aes_block *output, aes_key *key, aes_block *input);
|
||||||
typedef void (*gf_mul_f)(aes_block *a, aes_block *b);
|
typedef void (*hinit_f)(table_4bit htable, const block128 *h);
|
||||||
|
typedef void (*gf_mul_f)(block128 *a, const table_4bit htable);
|
||||||
|
|
||||||
#ifdef WITH_AESNI
|
#ifdef WITH_AESNI
|
||||||
#define GET_INIT(strength) \
|
#define GET_INIT(strength) \
|
||||||
@ -171,6 +180,8 @@ typedef void (*gf_mul_f)(aes_block *a, aes_block *b);
|
|||||||
((cbc_f) (cryptonite_aes_branch_table[DECRYPT_CBC_128 + strength]))
|
((cbc_f) (cryptonite_aes_branch_table[DECRYPT_CBC_128 + strength]))
|
||||||
#define GET_CTR_ENCRYPT(strength) \
|
#define GET_CTR_ENCRYPT(strength) \
|
||||||
((ctr_f) (cryptonite_aes_branch_table[ENCRYPT_CTR_128 + strength]))
|
((ctr_f) (cryptonite_aes_branch_table[ENCRYPT_CTR_128 + strength]))
|
||||||
|
#define GET_C32_ENCRYPT(strength) \
|
||||||
|
((ctr_f) (cryptonite_aes_branch_table[ENCRYPT_C32_128 + strength]))
|
||||||
#define GET_XTS_ENCRYPT(strength) \
|
#define GET_XTS_ENCRYPT(strength) \
|
||||||
((xts_f) (cryptonite_aes_branch_table[ENCRYPT_XTS_128 + strength]))
|
((xts_f) (cryptonite_aes_branch_table[ENCRYPT_XTS_128 + strength]))
|
||||||
#define GET_XTS_DECRYPT(strength) \
|
#define GET_XTS_DECRYPT(strength) \
|
||||||
@ -191,8 +202,10 @@ typedef void (*gf_mul_f)(aes_block *a, aes_block *b);
|
|||||||
(((block_f) (cryptonite_aes_branch_table[ENCRYPT_BLOCK_128 + k->strength]))(o,k,i))
|
(((block_f) (cryptonite_aes_branch_table[ENCRYPT_BLOCK_128 + k->strength]))(o,k,i))
|
||||||
#define cryptonite_aes_decrypt_block(o,k,i) \
|
#define cryptonite_aes_decrypt_block(o,k,i) \
|
||||||
(((block_f) (cryptonite_aes_branch_table[DECRYPT_BLOCK_128 + k->strength]))(o,k,i))
|
(((block_f) (cryptonite_aes_branch_table[DECRYPT_BLOCK_128 + k->strength]))(o,k,i))
|
||||||
#define cryptonite_gf_mul(a,b) \
|
#define cryptonite_hinit(t,h) \
|
||||||
(((gf_mul_f) (cryptonite_aes_branch_table[GHASH_GF_MUL]))(a,b))
|
(((hinit_f) (cryptonite_aes_branch_table[GHASH_HINIT]))(t,h))
|
||||||
|
#define cryptonite_gf_mul(a,t) \
|
||||||
|
(((gf_mul_f) (cryptonite_aes_branch_table[GHASH_GF_MUL]))(a,t))
|
||||||
#else
|
#else
|
||||||
#define GET_INIT(strenght) cryptonite_aes_generic_init
|
#define GET_INIT(strenght) cryptonite_aes_generic_init
|
||||||
#define GET_ECB_ENCRYPT(strength) cryptonite_aes_generic_encrypt_ecb
|
#define GET_ECB_ENCRYPT(strength) cryptonite_aes_generic_encrypt_ecb
|
||||||
@ -200,6 +213,7 @@ typedef void (*gf_mul_f)(aes_block *a, aes_block *b);
|
|||||||
#define GET_CBC_ENCRYPT(strength) cryptonite_aes_generic_encrypt_cbc
|
#define GET_CBC_ENCRYPT(strength) cryptonite_aes_generic_encrypt_cbc
|
||||||
#define GET_CBC_DECRYPT(strength) cryptonite_aes_generic_decrypt_cbc
|
#define GET_CBC_DECRYPT(strength) cryptonite_aes_generic_decrypt_cbc
|
||||||
#define GET_CTR_ENCRYPT(strength) cryptonite_aes_generic_encrypt_ctr
|
#define GET_CTR_ENCRYPT(strength) cryptonite_aes_generic_encrypt_ctr
|
||||||
|
#define GET_C32_ENCRYPT(strength) cryptonite_aes_generic_encrypt_c32
|
||||||
#define GET_XTS_ENCRYPT(strength) cryptonite_aes_generic_encrypt_xts
|
#define GET_XTS_ENCRYPT(strength) cryptonite_aes_generic_encrypt_xts
|
||||||
#define GET_XTS_DECRYPT(strength) cryptonite_aes_generic_decrypt_xts
|
#define GET_XTS_DECRYPT(strength) cryptonite_aes_generic_decrypt_xts
|
||||||
#define GET_GCM_ENCRYPT(strength) cryptonite_aes_generic_gcm_encrypt
|
#define GET_GCM_ENCRYPT(strength) cryptonite_aes_generic_gcm_encrypt
|
||||||
@ -210,14 +224,23 @@ typedef void (*gf_mul_f)(aes_block *a, aes_block *b);
|
|||||||
#define GET_CCM_DECRYPT(strength) cryptonite_aes_generic_ccm_decrypt
|
#define GET_CCM_DECRYPT(strength) cryptonite_aes_generic_ccm_decrypt
|
||||||
#define cryptonite_aes_encrypt_block(o,k,i) cryptonite_aes_generic_encrypt_block(o,k,i)
|
#define cryptonite_aes_encrypt_block(o,k,i) cryptonite_aes_generic_encrypt_block(o,k,i)
|
||||||
#define cryptonite_aes_decrypt_block(o,k,i) cryptonite_aes_generic_decrypt_block(o,k,i)
|
#define cryptonite_aes_decrypt_block(o,k,i) cryptonite_aes_generic_decrypt_block(o,k,i)
|
||||||
#define cryptonite_gf_mul(a,b) cryptonite_aes_generic_gf_mul(a,b)
|
#define cryptonite_hinit(t,h) cryptonite_aes_generic_hinit(t,h)
|
||||||
|
#define cryptonite_gf_mul(a,t) cryptonite_aes_generic_gf_mul(a,t)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CPU_AESNI 0
|
||||||
|
#define CPU_PCLMUL 1
|
||||||
|
#define CPU_OPTION_COUNT 2
|
||||||
|
|
||||||
|
static uint8_t cryptonite_aes_cpu_options[CPU_OPTION_COUNT] = {};
|
||||||
|
|
||||||
#if defined(ARCH_X86) && defined(WITH_AESNI)
|
#if defined(ARCH_X86) && defined(WITH_AESNI)
|
||||||
static void initialize_table_ni(int aesni, int pclmul)
|
static void initialize_table_ni(int aesni, int pclmul)
|
||||||
{
|
{
|
||||||
if (!aesni)
|
if (!aesni)
|
||||||
return;
|
return;
|
||||||
|
cryptonite_aes_cpu_options[CPU_AESNI] = 1;
|
||||||
|
|
||||||
cryptonite_aes_branch_table[INIT_128] = cryptonite_aesni_init;
|
cryptonite_aes_branch_table[INIT_128] = cryptonite_aesni_init;
|
||||||
cryptonite_aes_branch_table[INIT_256] = cryptonite_aesni_init;
|
cryptonite_aes_branch_table[INIT_256] = cryptonite_aesni_init;
|
||||||
|
|
||||||
@ -238,6 +261,9 @@ static void initialize_table_ni(int aesni, int pclmul)
|
|||||||
/* CTR */
|
/* CTR */
|
||||||
cryptonite_aes_branch_table[ENCRYPT_CTR_128] = cryptonite_aesni_encrypt_ctr128;
|
cryptonite_aes_branch_table[ENCRYPT_CTR_128] = cryptonite_aesni_encrypt_ctr128;
|
||||||
cryptonite_aes_branch_table[ENCRYPT_CTR_256] = cryptonite_aesni_encrypt_ctr256;
|
cryptonite_aes_branch_table[ENCRYPT_CTR_256] = cryptonite_aesni_encrypt_ctr256;
|
||||||
|
/* CTR with 32-bit wrapping */
|
||||||
|
cryptonite_aes_branch_table[ENCRYPT_C32_128] = cryptonite_aesni_encrypt_c32_128;
|
||||||
|
cryptonite_aes_branch_table[ENCRYPT_C32_256] = cryptonite_aesni_encrypt_c32_256;
|
||||||
/* XTS */
|
/* XTS */
|
||||||
cryptonite_aes_branch_table[ENCRYPT_XTS_128] = cryptonite_aesni_encrypt_xts128;
|
cryptonite_aes_branch_table[ENCRYPT_XTS_128] = cryptonite_aesni_encrypt_xts128;
|
||||||
cryptonite_aes_branch_table[ENCRYPT_XTS_256] = cryptonite_aesni_encrypt_xts256;
|
cryptonite_aes_branch_table[ENCRYPT_XTS_256] = cryptonite_aesni_encrypt_xts256;
|
||||||
@ -252,13 +278,24 @@ static void initialize_table_ni(int aesni, int pclmul)
|
|||||||
#ifdef WITH_PCLMUL
|
#ifdef WITH_PCLMUL
|
||||||
if (!pclmul)
|
if (!pclmul)
|
||||||
return;
|
return;
|
||||||
|
cryptonite_aes_cpu_options[CPU_PCLMUL] = 1;
|
||||||
|
|
||||||
/* GHASH */
|
/* GHASH */
|
||||||
cryptonite_aes_branch_table[GHASH_GF_MUL] = cryptonite_aesni_gf_mul;
|
cryptonite_aes_branch_table[GHASH_HINIT] = cryptonite_aesni_hinit_pclmul,
|
||||||
|
cryptonite_aes_branch_table[GHASH_GF_MUL] = cryptonite_aesni_gf_mul_pclmul,
|
||||||
cryptonite_aesni_init_pclmul();
|
cryptonite_aesni_init_pclmul();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint8_t *cryptonite_aes_cpu_init(void)
|
||||||
|
{
|
||||||
|
#if defined(ARCH_X86) && defined(WITH_AESNI)
|
||||||
|
cryptonite_aesni_initialize_hw(initialize_table_ni);
|
||||||
|
#endif
|
||||||
|
return cryptonite_aes_cpu_options;
|
||||||
|
}
|
||||||
|
|
||||||
void cryptonite_aes_initkey(aes_key *key, uint8_t *origkey, uint8_t size)
|
void cryptonite_aes_initkey(aes_key *key, uint8_t *origkey, uint8_t size)
|
||||||
{
|
{
|
||||||
switch (size) {
|
switch (size) {
|
||||||
@ -266,9 +303,7 @@ void cryptonite_aes_initkey(aes_key *key, uint8_t *origkey, uint8_t size)
|
|||||||
case 24: key->nbr = 12; key->strength = 1; break;
|
case 24: key->nbr = 12; key->strength = 1; break;
|
||||||
case 32: key->nbr = 14; key->strength = 2; break;
|
case 32: key->nbr = 14; key->strength = 2; break;
|
||||||
}
|
}
|
||||||
#if defined(ARCH_X86) && defined(WITH_AESNI)
|
cryptonite_aes_cpu_init();
|
||||||
cryptonite_aesni_initialize_hw(initialize_table_ni);
|
|
||||||
#endif
|
|
||||||
init_f _init = GET_INIT(key->strength);
|
init_f _init = GET_INIT(key->strength);
|
||||||
_init(key, origkey, size);
|
_init(key, origkey, size);
|
||||||
}
|
}
|
||||||
@ -330,6 +365,12 @@ void cryptonite_aes_encrypt_ctr(uint8_t *output, aes_key *key, aes_block *iv, ui
|
|||||||
e(output, key, iv, input, len);
|
e(output, key, iv, input, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cryptonite_aes_encrypt_c32(uint8_t *output, aes_key *key, aes_block *iv, uint8_t *input, uint32_t len)
|
||||||
|
{
|
||||||
|
ctr_f e = GET_C32_ENCRYPT(key->strength);
|
||||||
|
e(output, key, iv, input, len);
|
||||||
|
}
|
||||||
|
|
||||||
void cryptonite_aes_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,
|
void cryptonite_aes_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,
|
||||||
uint32_t spoint, aes_block *input, uint32_t nb_blocks)
|
uint32_t spoint, aes_block *input, uint32_t nb_blocks)
|
||||||
{
|
{
|
||||||
@ -382,20 +423,22 @@ void cryptonite_aes_ocb_decrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uin
|
|||||||
static void gcm_ghash_add(aes_gcm *gcm, block128 *b)
|
static void gcm_ghash_add(aes_gcm *gcm, block128 *b)
|
||||||
{
|
{
|
||||||
block128_xor(&gcm->tag, b);
|
block128_xor(&gcm->tag, b);
|
||||||
cryptonite_gf_mul(&gcm->tag, &gcm->h);
|
cryptonite_gf_mul(&gcm->tag, gcm->htable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_aes_gcm_init(aes_gcm *gcm, aes_key *key, uint8_t *iv, uint32_t len)
|
void cryptonite_aes_gcm_init(aes_gcm *gcm, aes_key *key, uint8_t *iv, uint32_t len)
|
||||||
{
|
{
|
||||||
|
block128 h;
|
||||||
gcm->length_aad = 0;
|
gcm->length_aad = 0;
|
||||||
gcm->length_input = 0;
|
gcm->length_input = 0;
|
||||||
|
|
||||||
block128_zero(&gcm->h);
|
block128_zero(&h);
|
||||||
block128_zero(&gcm->tag);
|
block128_zero(&gcm->tag);
|
||||||
block128_zero(&gcm->iv);
|
block128_zero(&gcm->iv);
|
||||||
|
|
||||||
/* prepare H : encrypt_K(0^128) */
|
/* prepare H : encrypt_K(0^128) */
|
||||||
cryptonite_aes_encrypt_block(&gcm->h, key, &gcm->h);
|
cryptonite_aes_encrypt_block(&h, key, &h);
|
||||||
|
cryptonite_hinit(gcm->htable, &h);
|
||||||
|
|
||||||
if (len == 12) {
|
if (len == 12) {
|
||||||
block128_copy_bytes(&gcm->iv, iv, 12);
|
block128_copy_bytes(&gcm->iv, iv, 12);
|
||||||
@ -405,15 +448,15 @@ void cryptonite_aes_gcm_init(aes_gcm *gcm, aes_key *key, uint8_t *iv, uint32_t l
|
|||||||
int i;
|
int i;
|
||||||
for (; len >= 16; len -= 16, iv += 16) {
|
for (; len >= 16; len -= 16, iv += 16) {
|
||||||
block128_xor(&gcm->iv, (block128 *) iv);
|
block128_xor(&gcm->iv, (block128 *) iv);
|
||||||
cryptonite_gf_mul(&gcm->iv, &gcm->h);
|
cryptonite_gf_mul(&gcm->iv, gcm->htable);
|
||||||
}
|
}
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
block128_xor_bytes(&gcm->iv, iv, len);
|
block128_xor_bytes(&gcm->iv, iv, len);
|
||||||
cryptonite_gf_mul(&gcm->iv, &gcm->h);
|
cryptonite_gf_mul(&gcm->iv, gcm->htable);
|
||||||
}
|
}
|
||||||
for (i = 15; origlen; --i, origlen >>= 8)
|
for (i = 15; origlen; --i, origlen >>= 8)
|
||||||
gcm->iv.b[i] ^= (uint8_t) origlen;
|
gcm->iv.b[i] ^= (uint8_t) origlen;
|
||||||
cryptonite_gf_mul(&gcm->iv, &gcm->h);
|
cryptonite_gf_mul(&gcm->iv, gcm->htable);
|
||||||
}
|
}
|
||||||
|
|
||||||
block128_copy_aligned(&gcm->civ, &gcm->iv);
|
block128_copy_aligned(&gcm->civ, &gcm->iv);
|
||||||
@ -507,7 +550,7 @@ static void ccm_encode_ctr(block128* out, aes_ccm* ccm, unsigned int cnt)
|
|||||||
static void ccm_cbcmac_add(aes_ccm* ccm, aes_key* key, block128* bi)
|
static void ccm_cbcmac_add(aes_ccm* ccm, aes_key* key, block128* bi)
|
||||||
{
|
{
|
||||||
block128_xor_aligned(&ccm->xi, bi);
|
block128_xor_aligned(&ccm->xi, bi);
|
||||||
cryptonite_aes_generic_encrypt_block(&ccm->xi, key, &ccm->xi);
|
cryptonite_aes_encrypt_block(&ccm->xi, key, &ccm->xi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* even though it is possible to support message size as large as 2^64, we support up to 2^32 only */
|
/* even though it is possible to support message size as large as 2^64, we support up to 2^32 only */
|
||||||
@ -765,6 +808,30 @@ void cryptonite_aes_generic_encrypt_ctr(uint8_t *output, aes_key *key, aes_block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cryptonite_aes_generic_encrypt_c32(uint8_t *output, aes_key *key, aes_block *iv, uint8_t *input, uint32_t len)
|
||||||
|
{
|
||||||
|
aes_block block, o;
|
||||||
|
uint32_t nb_blocks = len / 16;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* preload IV in block */
|
||||||
|
block128_copy(&block, iv);
|
||||||
|
|
||||||
|
for ( ; nb_blocks-- > 0; block128_inc32_le(&block), output += 16, input += 16) {
|
||||||
|
cryptonite_aes_encrypt_block(&o, key, &block);
|
||||||
|
block128_vxor((block128 *) output, &o, (block128 *) input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len % 16) != 0) {
|
||||||
|
cryptonite_aes_encrypt_block(&o, key, &block);
|
||||||
|
for (i = 0; i < (len % 16); i++) {
|
||||||
|
*output = ((uint8_t *) &o)[i] ^ *input;
|
||||||
|
output++;
|
||||||
|
input++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cryptonite_aes_generic_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,
|
void cryptonite_aes_generic_encrypt_xts(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit,
|
||||||
uint32_t spoint, aes_block *input, uint32_t nb_blocks)
|
uint32_t spoint, aes_block *input, uint32_t nb_blocks)
|
||||||
{
|
{
|
||||||
@ -811,7 +878,7 @@ void cryptonite_aes_generic_gcm_encrypt(uint8_t *output, aes_gcm *gcm, aes_key *
|
|||||||
|
|
||||||
gcm->length_input += length;
|
gcm->length_input += length;
|
||||||
for (; length >= 16; input += 16, output += 16, length -= 16) {
|
for (; length >= 16; input += 16, output += 16, length -= 16) {
|
||||||
block128_inc_be(&gcm->civ);
|
block128_inc32_be(&gcm->civ);
|
||||||
|
|
||||||
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
|
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
|
||||||
block128_xor(&out, (block128 *) input);
|
block128_xor(&out, (block128 *) input);
|
||||||
@ -822,7 +889,7 @@ void cryptonite_aes_generic_gcm_encrypt(uint8_t *output, aes_gcm *gcm, aes_key *
|
|||||||
aes_block tmp;
|
aes_block tmp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
block128_inc_be(&gcm->civ);
|
block128_inc32_be(&gcm->civ);
|
||||||
/* create e(civ) in out */
|
/* create e(civ) in out */
|
||||||
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
|
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
|
||||||
/* initialize a tmp as input and xor it to e(civ) */
|
/* initialize a tmp as input and xor it to e(civ) */
|
||||||
@ -844,7 +911,7 @@ void cryptonite_aes_generic_gcm_decrypt(uint8_t *output, aes_gcm *gcm, aes_key *
|
|||||||
|
|
||||||
gcm->length_input += length;
|
gcm->length_input += length;
|
||||||
for (; length >= 16; input += 16, output += 16, length -= 16) {
|
for (; length >= 16; input += 16, output += 16, length -= 16) {
|
||||||
block128_inc_be(&gcm->civ);
|
block128_inc32_be(&gcm->civ);
|
||||||
|
|
||||||
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
|
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
|
||||||
gcm_ghash_add(gcm, (block128 *) input);
|
gcm_ghash_add(gcm, (block128 *) input);
|
||||||
@ -855,7 +922,7 @@ void cryptonite_aes_generic_gcm_decrypt(uint8_t *output, aes_gcm *gcm, aes_key *
|
|||||||
aes_block tmp;
|
aes_block tmp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
block128_inc_be(&gcm->civ);
|
block128_inc32_be(&gcm->civ);
|
||||||
|
|
||||||
block128_zero(&tmp);
|
block128_zero(&tmp);
|
||||||
block128_copy_bytes(&tmp, input, length);
|
block128_copy_bytes(&tmp, input, length);
|
||||||
@ -988,3 +1055,55 @@ void cryptonite_aes_generic_ocb_decrypt(uint8_t *output, aes_ocb *ocb, aes_key *
|
|||||||
{
|
{
|
||||||
ocb_generic_crypt(output, ocb, key, input, length, 0);
|
ocb_generic_crypt(output, ocb, key, input, length, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void gf_mulx_rev(block128 *a, const block128 *h)
|
||||||
|
{
|
||||||
|
uint64_t v1 = cpu_to_le64(h->q[0]);
|
||||||
|
uint64_t v0 = cpu_to_le64(h->q[1]);
|
||||||
|
a->q[1] = cpu_to_be64(v1 >> 1 | v0 << 63);
|
||||||
|
a->q[0] = cpu_to_be64(v0 >> 1 ^ ((0-(v1 & 1)) & 0xe100000000000000ULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonite_aes_polyval_init(aes_polyval *ctx, const aes_block *h)
|
||||||
|
{
|
||||||
|
aes_block r;
|
||||||
|
|
||||||
|
/* ByteReverse(S_0) = 0 */
|
||||||
|
block128_zero(&ctx->s);
|
||||||
|
|
||||||
|
/* ByteReverse(H) * x */
|
||||||
|
gf_mulx_rev(&r, h);
|
||||||
|
cryptonite_hinit(ctx->htable, &r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonite_aes_polyval_update(aes_polyval *ctx, const uint8_t *input, uint32_t length)
|
||||||
|
{
|
||||||
|
aes_block r;
|
||||||
|
const uint8_t *p;
|
||||||
|
uint32_t sz;
|
||||||
|
|
||||||
|
/* This automatically pads with zeros if input is not a multiple of the
|
||||||
|
block size. */
|
||||||
|
for (p = input; length > 0; p += 16, length -= sz)
|
||||||
|
{
|
||||||
|
sz = length < 16 ? length : 16;
|
||||||
|
|
||||||
|
/* ByteReverse(X_j) */
|
||||||
|
block128_zero(&r);
|
||||||
|
memcpy(&r, p, sz);
|
||||||
|
block128_byte_reverse(&r);
|
||||||
|
|
||||||
|
/* ByteReverse(S_{j-1}) + ByteReverse(X_j) */
|
||||||
|
block128_xor_aligned(&ctx->s, &r);
|
||||||
|
|
||||||
|
/* ByteReverse(S_j) */
|
||||||
|
cryptonite_gf_mul(&ctx->s, ctx->htable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonite_aes_polyval_finalize(aes_polyval *ctx, aes_block *dst)
|
||||||
|
{
|
||||||
|
/* S_s */
|
||||||
|
block128_copy_aligned(dst, &ctx->s);
|
||||||
|
block128_byte_reverse(dst);
|
||||||
|
}
|
||||||
|
|||||||
@ -45,10 +45,10 @@ typedef struct {
|
|||||||
uint8_t data[16*14*2];
|
uint8_t data[16*14*2];
|
||||||
} aes_key;
|
} aes_key;
|
||||||
|
|
||||||
/* size = 4*16+2*8= 80 */
|
/* size = 19*16+2*8= 320 */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
aes_block tag;
|
aes_block tag;
|
||||||
aes_block h;
|
aes_block htable[16];
|
||||||
aes_block iv;
|
aes_block iv;
|
||||||
aes_block civ;
|
aes_block civ;
|
||||||
uint64_t length_aad;
|
uint64_t length_aad;
|
||||||
@ -77,6 +77,12 @@ typedef struct {
|
|||||||
block128 li[4];
|
block128 li[4];
|
||||||
} aes_ocb;
|
} aes_ocb;
|
||||||
|
|
||||||
|
/* size = 17*16= 272 */
|
||||||
|
typedef struct {
|
||||||
|
aes_block htable[16];
|
||||||
|
aes_block s;
|
||||||
|
} aes_polyval;
|
||||||
|
|
||||||
/* in bytes: either 16,24,32 */
|
/* in bytes: either 16,24,32 */
|
||||||
void cryptonite_aes_initkey(aes_key *ctx, uint8_t *key, uint8_t size);
|
void cryptonite_aes_initkey(aes_key *ctx, uint8_t *key, uint8_t size);
|
||||||
|
|
||||||
@ -115,4 +121,10 @@ void cryptonite_aes_ccm_encrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uin
|
|||||||
void cryptonite_aes_ccm_decrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length);
|
void cryptonite_aes_ccm_decrypt(uint8_t *output, aes_ccm *ccm, aes_key *key, uint8_t *input, uint32_t length);
|
||||||
void cryptonite_aes_ccm_finish(uint8_t *tag, aes_ccm *ccm, aes_key *key);
|
void cryptonite_aes_ccm_finish(uint8_t *tag, aes_ccm *ccm, aes_key *key);
|
||||||
|
|
||||||
|
uint8_t *cryptonite_aes_cpu_init(void);
|
||||||
|
|
||||||
|
void cryptonite_aes_polyval_init(aes_polyval *ctx, const aes_block *h);
|
||||||
|
void cryptonite_aes_polyval_update(aes_polyval *ctx, const uint8_t *input, uint32_t length);
|
||||||
|
void cryptonite_aes_polyval_finalize(aes_polyval *ctx, aes_block *dst);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -44,11 +44,21 @@ static inline void store_le32_aligned(uint8_t *dst, const uint32_t v)
|
|||||||
*((uint32_t *) dst) = cpu_to_le32(v);
|
*((uint32_t *) dst) = cpu_to_le32(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void xor_le32_aligned(uint8_t *dst, const uint32_t v)
|
||||||
|
{
|
||||||
|
*((uint32_t *) dst) ^= cpu_to_le32(v);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void store_be32_aligned(uint8_t *dst, const uint32_t v)
|
static inline void store_be32_aligned(uint8_t *dst, const uint32_t v)
|
||||||
{
|
{
|
||||||
*((uint32_t *) dst) = cpu_to_be32(v);
|
*((uint32_t *) dst) = cpu_to_be32(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void xor_be32_aligned(uint8_t *dst, const uint32_t v)
|
||||||
|
{
|
||||||
|
*((uint32_t *) dst) ^= cpu_to_be32(v);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void store_le64_aligned(uint8_t *dst, const uint64_t v)
|
static inline void store_le64_aligned(uint8_t *dst, const uint64_t v)
|
||||||
{
|
{
|
||||||
*((uint64_t *) dst) = cpu_to_le64(v);
|
*((uint64_t *) dst) = cpu_to_le64(v);
|
||||||
@ -59,6 +69,11 @@ static inline void store_be64_aligned(uint8_t *dst, const uint64_t v)
|
|||||||
*((uint64_t *) dst) = cpu_to_be64(v);
|
*((uint64_t *) dst) = cpu_to_be64(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void xor_be64_aligned(uint8_t *dst, const uint64_t v)
|
||||||
|
{
|
||||||
|
*((uint64_t *) dst) ^= cpu_to_be64(v);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef UNALIGNED_ACCESS_OK
|
#ifdef UNALIGNED_ACCESS_OK
|
||||||
#define load_le32(a) load_le32_aligned(a)
|
#define load_le32(a) load_le32_aligned(a)
|
||||||
#else
|
#else
|
||||||
@ -70,20 +85,30 @@ static inline uint32_t load_le32(const uint8_t *p)
|
|||||||
|
|
||||||
#ifdef UNALIGNED_ACCESS_OK
|
#ifdef UNALIGNED_ACCESS_OK
|
||||||
#define store_le32(a, b) store_le32_aligned(a, b)
|
#define store_le32(a, b) store_le32_aligned(a, b)
|
||||||
|
#define xor_le32(a, b) xor_le32_aligned(a, b)
|
||||||
#else
|
#else
|
||||||
static inline void store_le32(uint8_t *dst, const uint32_t v)
|
static inline void store_le32(uint8_t *dst, const uint32_t v)
|
||||||
{
|
{
|
||||||
dst[0] = v; dst[1] = v >> 8; dst[2] = v >> 16; dst[3] = v >> 24;
|
dst[0] = v; dst[1] = v >> 8; dst[2] = v >> 16; dst[3] = v >> 24;
|
||||||
}
|
}
|
||||||
|
static inline void xor_le32(uint8_t *dst, const uint32_t v)
|
||||||
|
{
|
||||||
|
dst[0] ^= v; dst[1] ^= v >> 8; dst[2] ^= v >> 16; dst[3] ^= v >> 24;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef UNALIGNED_ACCESS_OK
|
#ifdef UNALIGNED_ACCESS_OK
|
||||||
#define store_be32(a, b) store_be32_aligned(a, b)
|
#define store_be32(a, b) store_be32_aligned(a, b)
|
||||||
|
#define xor_be32(a, b) xor_be32_aligned(a, b)
|
||||||
#else
|
#else
|
||||||
static inline void store_be32(uint8_t *dst, const uint32_t v)
|
static inline void store_be32(uint8_t *dst, const uint32_t v)
|
||||||
{
|
{
|
||||||
dst[3] = v; dst[2] = v >> 8; dst[1] = v >> 16; dst[0] = v >> 24;
|
dst[3] = v; dst[2] = v >> 8; dst[1] = v >> 16; dst[0] = v >> 24;
|
||||||
}
|
}
|
||||||
|
static inline void xor_be32(uint8_t *dst, const uint32_t v)
|
||||||
|
{
|
||||||
|
dst[3] ^= v; dst[2] ^= v >> 8; dst[1] ^= v >> 16; dst[0] ^= v >> 24;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef UNALIGNED_ACCESS_OK
|
#ifdef UNALIGNED_ACCESS_OK
|
||||||
@ -98,12 +123,18 @@ static inline void store_le64(uint8_t *dst, const uint64_t v)
|
|||||||
|
|
||||||
#ifdef UNALIGNED_ACCESS_OK
|
#ifdef UNALIGNED_ACCESS_OK
|
||||||
#define store_be64(a, b) store_be64_aligned(a, b)
|
#define store_be64(a, b) store_be64_aligned(a, b)
|
||||||
|
#define xor_be64(a, b) xor_be64_aligned(a, b)
|
||||||
#else
|
#else
|
||||||
static inline void store_be64(uint8_t *dst, const uint64_t v)
|
static inline void store_be64(uint8_t *dst, const uint64_t v)
|
||||||
{
|
{
|
||||||
dst[7] = v ; dst[6] = v >> 8 ; dst[5] = v >> 16; dst[4] = v >> 24;
|
dst[7] = v ; dst[6] = v >> 8 ; dst[5] = v >> 16; dst[4] = v >> 24;
|
||||||
dst[3] = v >> 32; dst[2] = v >> 40; dst[1] = v >> 48; dst[0] = v >> 56;
|
dst[3] = v >> 32; dst[2] = v >> 40; dst[1] = v >> 48; dst[0] = v >> 56;
|
||||||
}
|
}
|
||||||
|
static inline void xor_be64(uint8_t *dst, const uint64_t v)
|
||||||
|
{
|
||||||
|
dst[7] ^= v ; dst[6] ^= v >> 8 ; dst[5] ^= v >> 16; dst[4] ^= v >> 24;
|
||||||
|
dst[3] ^= v >> 32; dst[2] ^= v >> 40; dst[1] ^= v >> 48; dst[0] ^= v >> 56;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
void cryptonite_blake2b_init(blake2b_ctx *ctx, uint32_t hashlen)
|
void cryptonite_blake2b_init(blake2b_ctx *ctx, uint32_t hashlen)
|
||||||
{
|
{
|
||||||
blake2b_init(ctx, hashlen / 8);
|
_cryptonite_blake2b_init(ctx, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_blake2b_update(blake2b_ctx *ctx, const uint8_t *data, uint32_t len)
|
void cryptonite_blake2b_update(blake2b_ctx *ctx, const uint8_t *data, uint32_t len)
|
||||||
{
|
{
|
||||||
blake2b_update(ctx, data, len);
|
_cryptonite_blake2b_update(ctx, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_blake2b_finalize(blake2b_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
void cryptonite_blake2b_finalize(blake2b_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
||||||
{
|
{
|
||||||
blake2b_final(ctx, out, hashlen / 8);
|
_cryptonite_blake2b_final(ctx, out, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
void cryptonite_blake2bp_init(blake2bp_ctx *ctx, uint32_t hashlen)
|
void cryptonite_blake2bp_init(blake2bp_ctx *ctx, uint32_t hashlen)
|
||||||
{
|
{
|
||||||
blake2bp_init(ctx, hashlen / 8);
|
_cryptonite_blake2bp_init(ctx, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_blake2bp_update(blake2bp_ctx *ctx, const uint8_t *data, uint32_t len)
|
void cryptonite_blake2bp_update(blake2bp_ctx *ctx, const uint8_t *data, uint32_t len)
|
||||||
{
|
{
|
||||||
blake2bp_update(ctx, data, len);
|
_cryptonite_blake2bp_update(ctx, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_blake2bp_finalize(blake2bp_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
void cryptonite_blake2bp_finalize(blake2bp_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
||||||
{
|
{
|
||||||
blake2bp_final(ctx, out, hashlen / 8);
|
_cryptonite_blake2bp_final(ctx, out, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
void cryptonite_blake2s_init(blake2s_ctx *ctx, uint32_t hashlen)
|
void cryptonite_blake2s_init(blake2s_ctx *ctx, uint32_t hashlen)
|
||||||
{
|
{
|
||||||
blake2s_init(ctx, hashlen / 8);
|
_cryptonite_blake2s_init(ctx, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_blake2s_update(blake2s_ctx *ctx, const uint8_t *data, uint32_t len)
|
void cryptonite_blake2s_update(blake2s_ctx *ctx, const uint8_t *data, uint32_t len)
|
||||||
{
|
{
|
||||||
blake2s_update(ctx, data, len);
|
_cryptonite_blake2s_update(ctx, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_blake2s_finalize(blake2s_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
void cryptonite_blake2s_finalize(blake2s_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
||||||
{
|
{
|
||||||
blake2s_final(ctx, out, hashlen / 8);
|
_cryptonite_blake2s_final(ctx, out, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
void cryptonite_blake2sp_init(blake2sp_ctx *ctx, uint32_t hashlen)
|
void cryptonite_blake2sp_init(blake2sp_ctx *ctx, uint32_t hashlen)
|
||||||
{
|
{
|
||||||
blake2sp_init(ctx, hashlen / 8);
|
_cryptonite_blake2sp_init(ctx, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_blake2sp_update(blake2sp_ctx *ctx, const uint8_t *data, uint32_t len)
|
void cryptonite_blake2sp_update(blake2sp_ctx *ctx, const uint8_t *data, uint32_t len)
|
||||||
{
|
{
|
||||||
blake2sp_update(ctx, data, len);
|
_cryptonite_blake2sp_update(ctx, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cryptonite_blake2sp_finalize(blake2sp_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
void cryptonite_blake2sp_finalize(blake2sp_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
||||||
{
|
{
|
||||||
blake2sp_final(ctx, out, hashlen / 8);
|
_cryptonite_blake2sp_final(ctx, out, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,7 +98,6 @@ void cryptonite_chacha_init_core(cryptonite_chacha_state *st,
|
|||||||
uint32_t ivlen, const uint8_t *iv)
|
uint32_t ivlen, const uint8_t *iv)
|
||||||
{
|
{
|
||||||
const uint8_t *constants = (keylen == 32) ? sigma : tau;
|
const uint8_t *constants = (keylen == 32) ? sigma : tau;
|
||||||
int i;
|
|
||||||
|
|
||||||
ASSERT_ALIGNMENT(constants, 4);
|
ASSERT_ALIGNMENT(constants, 4);
|
||||||
|
|
||||||
|
|||||||
90
cbits/cryptonite_hash_prefix.c
Normal file
90
cbits/cryptonite_hash_prefix.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Olivier Chéron <olivier.cheron@gmail.com>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cryptonite_hash_prefix.h>
|
||||||
|
|
||||||
|
void CRYPTONITE_HASHED(finalize_prefix)(struct HASHED_LOWER(ctx) *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out)
|
||||||
|
{
|
||||||
|
uint64_t bits[HASHED(BITS_ELEMS)];
|
||||||
|
uint8_t *p = (uint8_t *) &bits;
|
||||||
|
uint32_t index, padidx, padlen, pos, out_mask;
|
||||||
|
static const uint32_t cut_off = HASHED(BLOCK_SIZE) - sizeof(bits);
|
||||||
|
|
||||||
|
/* Make sure n <= len */
|
||||||
|
n += (len - n) & constant_time_lt(len, n);
|
||||||
|
|
||||||
|
/* Initial index, based on current context state */
|
||||||
|
index = CRYPTONITE_HASHED(get_index)(ctx);
|
||||||
|
|
||||||
|
/* Final size after n bytes */
|
||||||
|
CRYPTONITE_HASHED(incr_sz)(ctx, bits, n);
|
||||||
|
|
||||||
|
/* Padding index and length */
|
||||||
|
padidx = CRYPTONITE_HASHED(get_index)(ctx);
|
||||||
|
padlen = HASHED(BLOCK_SIZE) + cut_off - padidx;
|
||||||
|
padlen -= HASHED(BLOCK_SIZE) & constant_time_lt(padidx, cut_off);
|
||||||
|
|
||||||
|
/* Initialize buffers because we will XOR into them */
|
||||||
|
memset(ctx->buf + index, 0, HASHED(BLOCK_SIZE) - index);
|
||||||
|
memset(out, 0, HASHED(DIGEST_SIZE));
|
||||||
|
pos = 0;
|
||||||
|
|
||||||
|
/* Iterate based on the full buffer length, regardless of n, and include
|
||||||
|
* the maximum overhead with padding and size bytes
|
||||||
|
*/
|
||||||
|
while (pos < len + HASHED(BLOCK_SIZE) + sizeof(bits)) {
|
||||||
|
uint8_t b;
|
||||||
|
|
||||||
|
/* Take as many bytes from the input buffer as possible */
|
||||||
|
if (pos < len)
|
||||||
|
b = *(data++) & (uint8_t) constant_time_lt(pos, n);
|
||||||
|
else
|
||||||
|
b = 0;
|
||||||
|
|
||||||
|
/* First padding byte */
|
||||||
|
b |= 0x80 & (uint8_t) constant_time_eq(pos, n);
|
||||||
|
|
||||||
|
/* Size bytes are always at the end of a block */
|
||||||
|
if (index >= cut_off)
|
||||||
|
b |= p[index - cut_off] & (uint8_t) constant_time_ge(pos, n + padlen);
|
||||||
|
|
||||||
|
/* Store this byte into the buffer */
|
||||||
|
ctx->buf[index++] ^= b;
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
/* Process a full block, at a boundary which is independent from n */
|
||||||
|
if (index >= HASHED(BLOCK_SIZE)) {
|
||||||
|
index = 0;
|
||||||
|
HASHED_LOWER(do_chunk)(ctx, (void *) ctx->buf);
|
||||||
|
memset(ctx->buf, 0, HASHED(BLOCK_SIZE));
|
||||||
|
|
||||||
|
/* Try to store the result: this is a no-op except when we reach the
|
||||||
|
* actual size based on n, more iterations may continue after that
|
||||||
|
* when len is really larger
|
||||||
|
*/
|
||||||
|
out_mask = constant_time_eq(pos, n + padlen + sizeof(bits));
|
||||||
|
CRYPTONITE_HASHED(select_digest)(ctx, out, out_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
cbits/cryptonite_hash_prefix.h
Normal file
65
cbits/cryptonite_hash_prefix.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Olivier Chéron <olivier.cheron@gmail.com>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CRYPTONITE_HASH_PREFIX_H
|
||||||
|
#define CRYPTONITE_HASH_PREFIX_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
static inline uint32_t constant_time_msb(uint32_t a)
|
||||||
|
{
|
||||||
|
return 0 - (a >> 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t constant_time_lt(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t constant_time_ge(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return ~constant_time_lt(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t constant_time_is_zero(uint32_t a)
|
||||||
|
{
|
||||||
|
return constant_time_msb(~a & (a - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t constant_time_eq(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return constant_time_is_zero(a ^ b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t constant_time_msb_64(uint64_t a)
|
||||||
|
{
|
||||||
|
return 0 - (a >> 63);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b)
|
||||||
|
{
|
||||||
|
return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -185,3 +185,30 @@ void cryptonite_md5_finalize(struct md5_ctx *ctx, uint8_t *out)
|
|||||||
store_le32(out+ 8, ctx->h[2]);
|
store_le32(out+ 8, ctx->h[2]);
|
||||||
store_le32(out+12, ctx->h[3]);
|
store_le32(out+12, ctx->h[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HASHED(m) MD5_##m
|
||||||
|
#define HASHED_LOWER(m) md5_##m
|
||||||
|
#define CRYPTONITE_HASHED(m) cryptonite_md5_##m
|
||||||
|
#define MD5_BLOCK_SIZE 64
|
||||||
|
#define MD5_BITS_ELEMS 1
|
||||||
|
|
||||||
|
static inline uint32_t cryptonite_md5_get_index(const struct md5_ctx *ctx)
|
||||||
|
{
|
||||||
|
return (uint32_t) (ctx->sz & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cryptonite_md5_incr_sz(struct md5_ctx *ctx, uint64_t *bits, uint32_t n)
|
||||||
|
{
|
||||||
|
ctx->sz += n;
|
||||||
|
*bits = cpu_to_le64(ctx->sz << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cryptonite_md5_select_digest(const struct md5_ctx *ctx, uint8_t *out, uint32_t out_mask)
|
||||||
|
{
|
||||||
|
xor_le32(out , ctx->h[0] & out_mask);
|
||||||
|
xor_le32(out+ 4, ctx->h[1] & out_mask);
|
||||||
|
xor_le32(out+ 8, ctx->h[2] & out_mask);
|
||||||
|
xor_le32(out+12, ctx->h[3] & out_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <cryptonite_hash_prefix.c>
|
||||||
|
|||||||
@ -39,5 +39,6 @@ struct md5_ctx
|
|||||||
void cryptonite_md5_init(struct md5_ctx *ctx);
|
void cryptonite_md5_init(struct md5_ctx *ctx);
|
||||||
void cryptonite_md5_update(struct md5_ctx *ctx, const uint8_t *data, uint32_t len);
|
void cryptonite_md5_update(struct md5_ctx *ctx, const uint8_t *data, uint32_t len);
|
||||||
void cryptonite_md5_finalize(struct md5_ctx *ctx, uint8_t *out);
|
void cryptonite_md5_finalize(struct md5_ctx *ctx, uint8_t *out);
|
||||||
|
void cryptonite_md5_finalize_prefix(struct md5_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -91,7 +91,7 @@ static inline int cryptonite_rdrand_step(RDRAND_T *buffer)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Returns the number of bytes succesfully generated */
|
/* Returns the number of bytes successfully generated */
|
||||||
int cryptonite_get_rand_bytes(uint8_t *buffer, size_t len)
|
int cryptonite_get_rand_bytes(uint8_t *buffer, size_t len)
|
||||||
{
|
{
|
||||||
RDRAND_T tmp;
|
RDRAND_T tmp;
|
||||||
|
|||||||
@ -120,7 +120,6 @@ void cryptonite_salsa_init_core(cryptonite_salsa_state *st,
|
|||||||
uint32_t ivlen, const uint8_t *iv)
|
uint32_t ivlen, const uint8_t *iv)
|
||||||
{
|
{
|
||||||
const uint8_t *constants = (keylen == 32) ? sigma : tau;
|
const uint8_t *constants = (keylen == 32) ? sigma : tau;
|
||||||
int i;
|
|
||||||
|
|
||||||
st->d[0] = load_le32_aligned(constants + 0);
|
st->d[0] = load_le32_aligned(constants + 0);
|
||||||
st->d[5] = load_le32_aligned(constants + 4);
|
st->d[5] = load_le32_aligned(constants + 4);
|
||||||
|
|||||||
@ -216,3 +216,31 @@ void cryptonite_sha1_finalize(struct sha1_ctx *ctx, uint8_t *out)
|
|||||||
store_be32(out+12, ctx->h[3]);
|
store_be32(out+12, ctx->h[3]);
|
||||||
store_be32(out+16, ctx->h[4]);
|
store_be32(out+16, ctx->h[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HASHED(m) SHA1_##m
|
||||||
|
#define HASHED_LOWER(m) sha1_##m
|
||||||
|
#define CRYPTONITE_HASHED(m) cryptonite_sha1_##m
|
||||||
|
#define SHA1_BLOCK_SIZE 64
|
||||||
|
#define SHA1_BITS_ELEMS 1
|
||||||
|
|
||||||
|
static inline uint32_t cryptonite_sha1_get_index(const struct sha1_ctx *ctx)
|
||||||
|
{
|
||||||
|
return (uint32_t) (ctx->sz & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cryptonite_sha1_incr_sz(struct sha1_ctx *ctx, uint64_t *bits, uint32_t n)
|
||||||
|
{
|
||||||
|
ctx->sz += n;
|
||||||
|
*bits = cpu_to_be64(ctx->sz << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cryptonite_sha1_select_digest(const struct sha1_ctx *ctx, uint8_t *out, uint32_t out_mask)
|
||||||
|
{
|
||||||
|
xor_be32(out , ctx->h[0] & out_mask);
|
||||||
|
xor_be32(out+ 4, ctx->h[1] & out_mask);
|
||||||
|
xor_be32(out+ 8, ctx->h[2] & out_mask);
|
||||||
|
xor_be32(out+12, ctx->h[3] & out_mask);
|
||||||
|
xor_be32(out+16, ctx->h[4] & out_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <cryptonite_hash_prefix.c>
|
||||||
|
|||||||
@ -41,5 +41,6 @@ struct sha1_ctx
|
|||||||
void cryptonite_sha1_init(struct sha1_ctx *ctx);
|
void cryptonite_sha1_init(struct sha1_ctx *ctx);
|
||||||
void cryptonite_sha1_update(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len);
|
void cryptonite_sha1_update(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len);
|
||||||
void cryptonite_sha1_finalize(struct sha1_ctx *ctx, uint8_t *out);
|
void cryptonite_sha1_finalize(struct sha1_ctx *ctx, uint8_t *out);
|
||||||
|
void cryptonite_sha1_finalize_prefix(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -161,6 +161,14 @@ void cryptonite_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out)
|
|||||||
memcpy(out, intermediate, SHA224_DIGEST_SIZE);
|
memcpy(out, intermediate, SHA224_DIGEST_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cryptonite_sha224_finalize_prefix(struct sha224_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out)
|
||||||
|
{
|
||||||
|
uint8_t intermediate[SHA256_DIGEST_SIZE];
|
||||||
|
|
||||||
|
cryptonite_sha256_finalize_prefix(ctx, data, len, n, intermediate);
|
||||||
|
memcpy(out, intermediate, SHA224_DIGEST_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out)
|
void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out)
|
||||||
{
|
{
|
||||||
static uint8_t padding[64] = { 0x80, };
|
static uint8_t padding[64] = { 0x80, };
|
||||||
@ -182,3 +190,29 @@ void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out)
|
|||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
store_be32(out+4*i, ctx->h[i]);
|
store_be32(out+4*i, ctx->h[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HASHED(m) SHA256_##m
|
||||||
|
#define HASHED_LOWER(m) sha256_##m
|
||||||
|
#define CRYPTONITE_HASHED(m) cryptonite_sha256_##m
|
||||||
|
#define SHA256_BLOCK_SIZE 64
|
||||||
|
#define SHA256_BITS_ELEMS 1
|
||||||
|
|
||||||
|
static inline uint32_t cryptonite_sha256_get_index(const struct sha256_ctx *ctx)
|
||||||
|
{
|
||||||
|
return (uint32_t) (ctx->sz & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cryptonite_sha256_incr_sz(struct sha256_ctx *ctx, uint64_t *bits, uint32_t n)
|
||||||
|
{
|
||||||
|
ctx->sz += n;
|
||||||
|
*bits = cpu_to_be64(ctx->sz << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cryptonite_sha256_select_digest(const struct sha256_ctx *ctx, uint8_t *out, uint32_t out_mask)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
xor_be32(out+4*i, ctx->h[i] & out_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <cryptonite_hash_prefix.c>
|
||||||
|
|||||||
@ -47,9 +47,11 @@ struct sha256_ctx
|
|||||||
void cryptonite_sha224_init(struct sha224_ctx *ctx);
|
void cryptonite_sha224_init(struct sha224_ctx *ctx);
|
||||||
void cryptonite_sha224_update(struct sha224_ctx *ctx, const uint8_t *data, uint32_t len);
|
void cryptonite_sha224_update(struct sha224_ctx *ctx, const uint8_t *data, uint32_t len);
|
||||||
void cryptonite_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out);
|
void cryptonite_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out);
|
||||||
|
void cryptonite_sha224_finalize_prefix(struct sha224_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out);
|
||||||
|
|
||||||
void cryptonite_sha256_init(struct sha256_ctx *ctx);
|
void cryptonite_sha256_init(struct sha256_ctx *ctx);
|
||||||
void cryptonite_sha256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len);
|
void cryptonite_sha256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len);
|
||||||
void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out);
|
void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out);
|
||||||
|
void cryptonite_sha256_finalize_prefix(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -121,14 +121,14 @@ void cryptonite_sha3_update(struct sha3_ctx *ctx, const uint8_t *data, uint32_t
|
|||||||
to_fill = ctx->bufsz - ctx->bufindex;
|
to_fill = ctx->bufsz - ctx->bufindex;
|
||||||
|
|
||||||
if (ctx->bufindex == ctx->bufsz) {
|
if (ctx->bufindex == ctx->bufsz) {
|
||||||
sha3_do_chunk(ctx->state, (uint64_t *) ctx->buf, ctx->bufsz / 8);
|
sha3_do_chunk(ctx->state, ctx->bufwords, ctx->bufsz / 8);
|
||||||
ctx->bufindex = 0;
|
ctx->bufindex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process partial buffer if there's enough data to make a block */
|
/* process partial buffer if there's enough data to make a block */
|
||||||
if (ctx->bufindex && len >= to_fill) {
|
if (ctx->bufindex && len >= to_fill) {
|
||||||
memcpy(ctx->buf + ctx->bufindex, data, to_fill);
|
memcpy(ctx->buf + ctx->bufindex, data, to_fill);
|
||||||
sha3_do_chunk(ctx->state, (uint64_t *) ctx->buf, ctx->bufsz / 8);
|
sha3_do_chunk(ctx->state, ctx->bufwords, ctx->bufsz / 8);
|
||||||
len -= to_fill;
|
len -= to_fill;
|
||||||
data += to_fill;
|
data += to_fill;
|
||||||
ctx->bufindex = 0;
|
ctx->bufindex = 0;
|
||||||
@ -159,7 +159,7 @@ void cryptonite_sha3_finalize_with_pad_byte(struct sha3_ctx *ctx, uint8_t pad_by
|
|||||||
{
|
{
|
||||||
/* process full buffer if needed */
|
/* process full buffer if needed */
|
||||||
if (ctx->bufindex == ctx->bufsz) {
|
if (ctx->bufindex == ctx->bufsz) {
|
||||||
sha3_do_chunk(ctx->state, (uint64_t *) ctx->buf, ctx->bufsz / 8);
|
sha3_do_chunk(ctx->state, ctx->bufwords, ctx->bufsz / 8);
|
||||||
ctx->bufindex = 0;
|
ctx->bufindex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ void cryptonite_sha3_finalize_with_pad_byte(struct sha3_ctx *ctx, uint8_t pad_by
|
|||||||
ctx->buf[ctx->bufsz - 1] |= 0x80;
|
ctx->buf[ctx->bufsz - 1] |= 0x80;
|
||||||
|
|
||||||
/* process */
|
/* process */
|
||||||
sha3_do_chunk(ctx->state, (uint64_t *) ctx->buf, ctx->bufsz / 8);
|
sha3_do_chunk(ctx->state, ctx->bufwords, ctx->bufsz / 8);
|
||||||
ctx->bufindex = 0;
|
ctx->bufindex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,3 +250,31 @@ void cryptonite_keccak_finalize(struct sha3_ctx *ctx, uint32_t hashlen, uint8_t
|
|||||||
cryptonite_sha3_finalize_with_pad_byte(ctx, 1);
|
cryptonite_sha3_finalize_with_pad_byte(ctx, 1);
|
||||||
cryptonite_sha3_output(ctx, out, hashlen / 8);
|
cryptonite_sha3_output(ctx, out, hashlen / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cryptonite_sha3_ctx_to_be(struct sha3_ctx *ctx, uint8_t *out)
|
||||||
|
{
|
||||||
|
void *ptr = out;
|
||||||
|
const uint32_t bufindex_be = cpu_to_be32(ctx->bufindex);
|
||||||
|
memcpy(ptr, &bufindex_be, sizeof(uint32_t));
|
||||||
|
ptr += sizeof(uint32_t);
|
||||||
|
const uint32_t bufsz_be = cpu_to_be32(ctx->bufsz);
|
||||||
|
memcpy(ptr, &bufsz_be, sizeof(uint32_t));
|
||||||
|
ptr += sizeof(uint32_t);
|
||||||
|
cpu_to_be64_array((uint64_t *) ptr, ctx->state, 25);
|
||||||
|
ptr += 25 * sizeof(uint64_t);
|
||||||
|
cpu_to_be64_array((uint64_t *) ptr, ctx->bufwords, ctx->bufsz / sizeof(uint64_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonite_sha3_be_to_ctx(uint8_t *in, struct sha3_ctx *ctx)
|
||||||
|
{
|
||||||
|
const uint32_t bufindex_cpu = be32_to_cpu(* (uint32_t *) in);
|
||||||
|
memcpy(&ctx->bufindex, &bufindex_cpu, sizeof(uint32_t));
|
||||||
|
in += sizeof(uint32_t);
|
||||||
|
const uint32_t bufsz_cpu = be32_to_cpu(* (uint32_t *) in);
|
||||||
|
memcpy(&ctx->bufsz, &bufsz_cpu, sizeof(uint32_t));
|
||||||
|
in += sizeof(uint32_t);
|
||||||
|
be64_to_cpu_array(ctx->state, (uint64_t *) in, 25);
|
||||||
|
in += 25 * sizeof(uint64_t);
|
||||||
|
be64_to_cpu_array(ctx->bufwords, (uint64_t *) in, ctx->bufsz / sizeof(uint64_t));
|
||||||
|
}
|
||||||
|
|||||||
@ -29,9 +29,12 @@
|
|||||||
struct sha3_ctx
|
struct sha3_ctx
|
||||||
{
|
{
|
||||||
uint32_t bufindex;
|
uint32_t bufindex;
|
||||||
uint32_t bufsz;
|
uint32_t bufsz; /* size of buf, i.e. in bytes */
|
||||||
uint64_t state[25];
|
uint64_t state[25];
|
||||||
uint8_t buf[0]; /* maximum SHAKE128 is 168 bytes, otherwise buffer can be decreased */
|
union { /* maximum SHAKE128 is 168 bytes, otherwise buffer can be decreased */
|
||||||
|
uint8_t buf[0];
|
||||||
|
uint64_t bufwords[0];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SHA3_CTX_SIZE sizeof(struct sha3_ctx)
|
#define SHA3_CTX_SIZE sizeof(struct sha3_ctx)
|
||||||
@ -64,4 +67,7 @@ void cryptonite_keccak_init(struct sha3_ctx *ctx, uint32_t hashlen);
|
|||||||
void cryptonite_keccak_update(struct sha3_ctx *ctx, uint8_t *data, uint32_t len);
|
void cryptonite_keccak_update(struct sha3_ctx *ctx, uint8_t *data, uint32_t len);
|
||||||
void cryptonite_keccak_finalize(struct sha3_ctx *ctx, uint32_t hashlen, uint8_t *out);
|
void cryptonite_keccak_finalize(struct sha3_ctx *ctx, uint32_t hashlen, uint8_t *out);
|
||||||
|
|
||||||
|
void cryptonite_sha3_ctx_to_be(struct sha3_ctx *ctx, uint8_t *out);
|
||||||
|
void cryptonite_sha3_be_to_ctx(uint8_t *in, struct sha3_ctx *ctx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -180,6 +180,14 @@ void cryptonite_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out)
|
|||||||
memcpy(out, intermediate, SHA384_DIGEST_SIZE);
|
memcpy(out, intermediate, SHA384_DIGEST_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cryptonite_sha384_finalize_prefix(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out)
|
||||||
|
{
|
||||||
|
uint8_t intermediate[SHA512_DIGEST_SIZE];
|
||||||
|
|
||||||
|
cryptonite_sha512_finalize_prefix(ctx, data, len, n, intermediate);
|
||||||
|
memcpy(out, intermediate, SHA384_DIGEST_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out)
|
void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out)
|
||||||
{
|
{
|
||||||
static uint8_t padding[128] = { 0x80, };
|
static uint8_t padding[128] = { 0x80, };
|
||||||
@ -203,6 +211,38 @@ void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out)
|
|||||||
store_be64(out+8*i, ctx->h[i]);
|
store_be64(out+8*i, ctx->h[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HASHED(m) SHA512_##m
|
||||||
|
#define HASHED_LOWER(m) sha512_##m
|
||||||
|
#define CRYPTONITE_HASHED(m) cryptonite_sha512_##m
|
||||||
|
#define SHA512_BLOCK_SIZE 128
|
||||||
|
#define SHA512_BITS_ELEMS 2
|
||||||
|
|
||||||
|
#include <cryptonite_hash_prefix.h>
|
||||||
|
|
||||||
|
static inline uint32_t cryptonite_sha512_get_index(const struct sha512_ctx *ctx)
|
||||||
|
{
|
||||||
|
return (uint32_t) (ctx->sz[0] & 0x7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cryptonite_sha512_incr_sz(struct sha512_ctx *ctx, uint64_t *bits, uint32_t n)
|
||||||
|
{
|
||||||
|
ctx->sz[0] += n;
|
||||||
|
ctx->sz[1] += 1 & constant_time_lt_64(ctx->sz[0], n);
|
||||||
|
bits[0] = cpu_to_be64((ctx->sz[1] << 3 | ctx->sz[0] >> 61));
|
||||||
|
bits[1] = cpu_to_be64((ctx->sz[0] << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cryptonite_sha512_select_digest(const struct sha512_ctx *ctx, uint8_t *out, uint32_t out_mask)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint64_t out_mask_64 = out_mask;
|
||||||
|
out_mask_64 |= out_mask_64 << 32;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
xor_be64(out+8*i, ctx->h[i] & out_mask_64);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <cryptonite_hash_prefix.c>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen)
|
void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen)
|
||||||
|
|||||||
@ -46,10 +46,12 @@ struct sha512_ctx
|
|||||||
void cryptonite_sha384_init(struct sha384_ctx *ctx);
|
void cryptonite_sha384_init(struct sha384_ctx *ctx);
|
||||||
void cryptonite_sha384_update(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len);
|
void cryptonite_sha384_update(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len);
|
||||||
void cryptonite_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out);
|
void cryptonite_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out);
|
||||||
|
void cryptonite_sha384_finalize_prefix(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out);
|
||||||
|
|
||||||
void cryptonite_sha512_init(struct sha512_ctx *ctx);
|
void cryptonite_sha512_init(struct sha512_ctx *ctx);
|
||||||
void cryptonite_sha512_update(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len);
|
void cryptonite_sha512_update(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len);
|
||||||
void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out);
|
void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out);
|
||||||
|
void cryptonite_sha512_finalize_prefix(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out);
|
||||||
|
|
||||||
/* only multiples of 8 are supported as valid t values */
|
/* only multiples of 8 are supported as valid t values */
|
||||||
void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen);
|
void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen);
|
||||||
|
|||||||
@ -167,7 +167,6 @@ void cryptonite_skein256_update(struct skein256_ctx *ctx, const uint8_t *data, u
|
|||||||
void cryptonite_skein256_finalize(struct skein256_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
void cryptonite_skein256_finalize(struct skein256_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
||||||
{
|
{
|
||||||
uint32_t outsize;
|
uint32_t outsize;
|
||||||
uint64_t *p = (uint64_t *) out;
|
|
||||||
uint64_t x[4];
|
uint64_t x[4];
|
||||||
int i, j, n;
|
int i, j, n;
|
||||||
|
|
||||||
|
|||||||
@ -185,7 +185,6 @@ void cryptonite_skein512_update(struct skein512_ctx *ctx, const uint8_t *data, u
|
|||||||
void cryptonite_skein512_finalize(struct skein512_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
void cryptonite_skein512_finalize(struct skein512_ctx *ctx, uint32_t hashlen, uint8_t *out)
|
||||||
{
|
{
|
||||||
uint32_t outsize;
|
uint32_t outsize;
|
||||||
uint64_t *p = (uint64_t *) out;
|
|
||||||
uint64_t x[8];
|
uint64_t x[8];
|
||||||
int i, j, n;
|
int i, j, n;
|
||||||
|
|
||||||
|
|||||||
@ -777,7 +777,6 @@ static void processBuffer(whirlpool_ctx * const ctx)
|
|||||||
uint64_t K[8]; /* the round key */
|
uint64_t K[8]; /* the round key */
|
||||||
uint64_t block[8]; /* mu(buffer) */
|
uint64_t block[8]; /* mu(buffer) */
|
||||||
uint64_t state[8]; /* the cipher state */
|
uint64_t state[8]; /* the cipher state */
|
||||||
uint64_t L[8];
|
|
||||||
uint8_t *buffer = ctx->buffer;
|
uint8_t *buffer = ctx->buffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -47,13 +47,27 @@ void cryptonite_xsalsa_init(cryptonite_salsa_context *ctx, uint8_t nb_rounds,
|
|||||||
(x6, x7, x8, x9) is the first 128 bits of a 192-bit nonce
|
(x6, x7, x8, x9) is the first 128 bits of a 192-bit nonce
|
||||||
*/
|
*/
|
||||||
cryptonite_salsa_init_core(&ctx->st, keylen, key, 8, iv);
|
cryptonite_salsa_init_core(&ctx->st, keylen, key, 8, iv);
|
||||||
ctx->st.d[ 8] = load_le32(iv + 8);
|
|
||||||
ctx->st.d[ 9] = load_le32(iv + 12);
|
/* Continue initialization in a separate function that may also
|
||||||
|
be called independently */
|
||||||
|
cryptonite_xsalsa_derive(ctx, ivlen - 8, iv + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cryptonite_xsalsa_derive(cryptonite_salsa_context *ctx,
|
||||||
|
uint32_t ivlen, const uint8_t *iv)
|
||||||
|
{
|
||||||
|
/* Finish creating initial 512-bit input block:
|
||||||
|
(x6, x7, x8, x9) is the first 128 bits of a 192-bit nonce
|
||||||
|
|
||||||
|
Except iv has been shifted by 64 bits so there are now only 128 bits ahead.
|
||||||
|
*/
|
||||||
|
ctx->st.d[ 8] += load_le32(iv + 0);
|
||||||
|
ctx->st.d[ 9] += load_le32(iv + 4);
|
||||||
|
|
||||||
/* Compute (z0, z1, . . . , z15) = doubleround ^(r/2) (x0, x1, . . . , x15) */
|
/* Compute (z0, z1, . . . , z15) = doubleround ^(r/2) (x0, x1, . . . , x15) */
|
||||||
block hSalsa;
|
block hSalsa;
|
||||||
memset(&hSalsa, 0, sizeof(block));
|
memset(&hSalsa, 0, sizeof(block));
|
||||||
cryptonite_salsa_core_xor(nb_rounds, &hSalsa, &ctx->st);
|
cryptonite_salsa_core_xor(ctx->nb_rounds, &hSalsa, &ctx->st);
|
||||||
|
|
||||||
/* Build a new 512-bit input block (x′0, x′1, . . . , x′15):
|
/* Build a new 512-bit input block (x′0, x′1, . . . , x′15):
|
||||||
(x′0, x′5, x′10, x′15) is the Salsa20 constant
|
(x′0, x′5, x′10, x′15) is the Salsa20 constant
|
||||||
@ -69,8 +83,8 @@ void cryptonite_xsalsa_init(cryptonite_salsa_context *ctx, uint8_t nb_rounds,
|
|||||||
ctx->st.d[12] = hSalsa.d[ 7] - ctx->st.d[ 7];
|
ctx->st.d[12] = hSalsa.d[ 7] - ctx->st.d[ 7];
|
||||||
ctx->st.d[13] = hSalsa.d[ 8] - ctx->st.d[ 8];
|
ctx->st.d[13] = hSalsa.d[ 8] - ctx->st.d[ 8];
|
||||||
ctx->st.d[14] = hSalsa.d[ 9] - ctx->st.d[ 9];
|
ctx->st.d[14] = hSalsa.d[ 9] - ctx->st.d[ 9];
|
||||||
ctx->st.d[ 6] = load_le32(iv + 16);
|
ctx->st.d[ 6] = load_le32(iv + 8);
|
||||||
ctx->st.d[ 7] = load_le32(iv + 20);
|
ctx->st.d[ 7] = load_le32(iv + 12);
|
||||||
ctx->st.d[ 8] = 0;
|
ctx->st.d[ 8] = 0;
|
||||||
ctx->st.d[ 9] = 0;
|
ctx->st.d[ 9] = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user