Compare commits

...

136 Commits

Author SHA1 Message Date
Sarah Vaupel
f78fca2504 Merge branch 'master' into uni2work 2024-01-09 02:48:31 +01:00
Vincent Hanquez
d163f69512
Merge pull request #371 from Vlix/patch-1
Small refactor
2022-10-03 08:11:46 +08:00
Felix Paulusma
9401b4e3fd
Small refactor
The same parameter was matched on twice, so why not just do it once?
2022-10-03 01:01:30 +02:00
Vincent Hanquez
b96ec42d3e
Merge pull request #348 from robx/fix-segfault
Fix alignment in gfmul_generic (closes #334)
2022-05-02 12:31:16 +08:00
Vincent Hanquez
7dfaf914e6
release 0.30 2022-03-13 20:54:14 +08:00
Vincent Hanquez
aca61fa1b6
update stackage 2022-03-13 20:49:31 +08:00
Vincent Hanquez
20b194fc97
fix byteswap32 to work on Word32# instead of Word# (with compat for ghc < 9.2) 2022-03-13 20:49:11 +08:00
Vincent Hanquez
cca5d72bf1
Merge pull request #359 from iquerejeta/build-issue
Include prefix to missing functions
2022-02-23 10:10:20 +08:00
iquerejeta
495eca0bb5
include prefix to missing functions 2022-02-17 11:43:52 +00:00
Vincent Hanquez
309abe378d
missing symbols renaming 2021-10-28 20:27:17 +08:00
iquerejeta
f4f92b702c
recapitalised constant 2021-10-28 10:57:03 +02:00
iquerejeta
93f50b49b7 ref folder changes, and minor sse 2021-09-15 12:28:06 +01:00
iquerejeta
a8d1d401bc linker complaints 2021-09-13 15:11:27 +01:00
Robert Vollmert
b3db979ca0 Fix alignment in gfmul_generic (closes #334)
This fixes a test-suite segfault on Darwin with -O0. Before this change:

$ cabal run -O0 test-cryptonite -- -p AE1
Segmentation fault: 11

with

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   test-cryptonite               	0x0000000108f7f61f gfmul_generic + 47
1   test-cryptonite               	0x0000000108f76f17 ghash_add + 71
2   test-cryptonite               	0x0000000108f743b4 cryptonite_aesni_gcm_encrypt128 + 2244
3   test-cryptonite               	0x0000000108f97f20 cryptonite_aes_gcm_encrypt + 96
4   test-cryptonite               	0x0000000108eeadf5 Lc8Pq_info + 197
2021-09-10 17:50:05 +02:00
Gregor Kleen
71a630edaf resumable hashing 2021-06-23 12:29:34 +02:00
Gregor Kleen
365c8978a2 build support 2021-06-23 12:29:12 +02:00
Vincent Hanquez
8698c9fd94
Merge pull request #221 from Porges/hmac-lazy
Add `hmacLazy` for lazy `ByteString`s
2021-06-03 08:01:10 +08:00
George Pollard
e9c9c770d3
Update HMAC.hs 2021-06-03 08:34:34 +12:00
George Pollard
9961606e5b
Merge branch 'master' into hmac-lazy 2021-06-03 08:33:55 +12:00
Vincent Hanquez
4b4a641970
cryptonite-0.29 2021-05-08 23:00:34 +08:00
Vincent Hanquez
a6fbe0ed4c
fix miscompilation with ghc9 2021-05-08 22:57:36 +08:00
Vincent Hanquez
b6981a4ea5
latest integer-gmp breaks advance GMP functions again (...) 2021-05-08 22:57:26 +08:00
Vincent Hanquez
cf89276b5c
Merge pull request #312 from ocheron/eddsa-gen
Generic EdDSA implementation
2021-04-14 23:17:34 +08:00
Vincent Hanquez
f449a54eb2
Merge pull request #345 from hamishmack/hkm/32bit-fix
Fix for 32 bit platforms
2021-04-14 23:08:10 +08:00
Hamish Mackenzie
95b247e5eb
Fix for 32 bit platforms
The use of `(fromIntegral (maxBound :: Word32))` causes problems.  It is used to make an `Int` and 32 bit systems it winds up being -1.
2021-04-14 17:16:15 +12:00
Vincent Hanquez
955f94b784
release 0.28 2021-01-27 10:48:00 +08:00
Vincent Hanquez
d0ead79fed
Merge pull request #331 from chpatrick/hash-4gb
Hash data in 4GB chunks to avoid uint32_t overflow.
2020-08-08 09:24:47 +08:00
Patrick Chilton
b29dc159fb Hash data in 4GB chunks to avoid uint32_t overflow. 2020-08-07 21:36:19 +02:00
Olivier Chéron
10dc63c51f Merge pull request #328 from ocheron/aead-thunks
Avoid thunk leak with AEAD state
2020-07-20 19:06:59 +02:00
Olivier Chéron
18ae7a7b40 Remove redundant brackets 2020-07-19 15:45:49 +02:00
Olivier Chéron
fa19117dfe Avoid thunk leak with AEAD state 2020-07-19 15:44:10 +02:00
Olivier Chéron
d49408156e Warn about instances exposing internals 2020-07-05 09:20:29 +02:00
Olivier Chéron
81cc351800 Note about drgNewTest and endianness 2020-07-05 09:20:29 +02:00
Olivier Chéron
9eadf707c4 Merge pull request #325 from ocheron/hash-ct
Hashing independent from input length
2020-07-05 08:46:38 +02:00
Olivier Chéron
72544ea9aa Removed extra semicolon 2020-07-02 19:35:06 +02:00
Olivier Chéron
63d427ee77 Add note about other package flags 2020-06-28 08:49:28 +02:00
Olivier Chéron
c8199872e7 Test HashAlgorithmPrefix API 2020-06-26 07:16:49 +02:00
Olivier Chéron
e67d8fb223 Generate HashAlgorithmPrefix instances 2020-06-26 07:16:41 +02:00
Olivier Chéron
caec601cd1 Add finalize_prefix functions 2020-06-26 07:16:30 +02:00
Olivier Chéron
ba3ab1f0cd Add HashAlgorithmPrefix API 2020-06-26 07:16:18 +02:00
Vincent Hanquez
0254f16e83
release 0.27 2020-06-21 12:07:25 +08:00
Olivier Chéron
cf9631dd7f Merge pull request #322 from incertia/square-root-f2m
implement square roots in f2m
2020-06-14 09:16:16 +02:00
Olivier Chéron
c123752de4 Use isNothing 2020-06-13 09:24:47 +02:00
Olivier Chéron
edbd9e09fb Test properties of powF2m 2020-06-12 19:06:58 +02:00
Olivier Chéron
dfc9fb9fb2 Fix powF2m when exponent is not a power of 2
Integer multiplication cannot be used because it includes carry
propagation.  This needs to use carry-less mulF2m instead.
2020-06-12 19:01:52 +02:00
Olivier Chéron
5f657fda2e Remove powF2m'
We keep only the function providing the base service, negative
exponents can be still computed with invF2m.
2020-06-12 18:54:37 +02:00
Will Song
f64efafbad update sqrtF2m 2020-06-08 10:16:42 -05:00
Will Song
17336857c5 implement square roots in f2m 2020-06-01 20:56:42 -05:00
Olivier Chéron
775855994c Use notElem 2020-03-15 15:44:35 +01:00
Olivier Chéron
5d63ef7c4f Merge pull request #316 from ocheron/target-attrs
AESNI and PCLMUL as per-function attributes
2020-03-15 15:43:27 +01:00
Olivier Chéron
f84f7e3009 Enable flag by default 2020-03-15 15:39:56 +01:00
Olivier Chéron
0cf0d076ab Add flag use_target_attributes 2020-03-14 08:44:44 +01:00
Olivier Chéron
f5706959a4 AES-NI and PCLMUL with per-function target compiler options 2020-03-14 08:43:44 +01:00
Olivier Chéron
dae01d056d AES-NI with per-file target compiler options 2020-03-14 08:09:12 +01:00
Olivier Chéron
a1072948ca Avoid error "Unknown mingw32 arch" with hlint 2020-03-14 08:07:35 +01:00
Olivier Chéron
d8a39637f5 Ignore hint "Use camelCase" globally 2020-03-14 07:39:06 +01:00
Olivier Chéron
64f097788e Merge pull request #315 from ocheron/i386-sse
Fix support_sse on i386 architecture
2020-03-14 07:36:30 +01:00
Olivier Chéron
b9e1e75a10 Fix support_sse on i386 architecture
On i386 compilation failed with support_sse enabled and support_aesni
disabled.  This enables the minimum required instruction set, guarded
with an architecture condition.
2020-03-11 19:15:32 +01:00
Olivier Chéron
e56308f9d0 Fix ignored allow_failures and weeder build in Travis CI
Used haskell-ci commit cbf9d90 from PR vincenthz/haskell-ci#5 to
regenerate the files.
2020-03-08 18:34:59 +01:00
Olivier Chéron
981b97a132 Protect against negative argument 2020-02-24 06:54:23 +01:00
Olivier Chéron
2e0a60f7f7 Use Semigroup API 2020-02-24 06:54:23 +01:00
Olivier Chéron
b01f610aa2 Add and use Builder module
Avoids intermediate allocations and conversions when concatenating
byte arrays of different types.
2020-02-24 06:54:23 +01:00
Olivier Chéron
ef880291e3 Add EdDSA 'ctx' and 'ph' variants 2020-02-24 06:54:23 +01:00
Olivier Chéron
977c72cac9 Test EdDSA with both SHA-2 and BLAKE2 2020-02-24 06:54:23 +01:00
Olivier Chéron
1cb2cd2f12 Ability to select the hash algorithm 2020-02-24 06:54:23 +01:00
Olivier Chéron
436b9abc13 Benchmark EdDSA implementations 2020-02-24 06:54:23 +01:00
Olivier Chéron
6f932998ad Fast hashing for EdDSA 2020-02-24 06:54:23 +01:00
Olivier Chéron
bd84c75f3e Use unsafe FFI calls
Changed Edwards primitives to unsafe when overhead of FFI call is
approximately 5% or more of total execution time.
2020-02-24 06:54:23 +01:00
Olivier Chéron
6f70986cb1 Avoid signature padding when not required 2020-02-24 06:54:23 +01:00
Olivier Chéron
633879f801 Avoid repeated point encoding 2020-02-24 06:54:23 +01:00
Olivier Chéron
6075b698e1 Generic EdDSA implementation 2020-02-24 06:54:23 +01:00
Olivier Chéron
4b9584dbe4 Use lts-15 in CI and bump versions 2020-02-24 06:53:19 +01:00
Olivier Chéron
4b8a8229cf Remove redundant where 2020-02-24 06:53:03 +01:00
Olivier Chéron
43a9967b1d Remove redundant superclass in MonadRandom
Reported by @frasertweedale
2020-02-16 19:49:49 +01:00
Olivier Chéron
86470d5563 Use conventional declaration order 2020-02-10 06:43:26 +01:00
Olivier Chéron
d2df760e34 Use zipWith 2020-02-10 06:43:26 +01:00
Vincent Hanquez
be517c9273
Merge pull request #307 from ocheron/p256-b64
Add 64-bit implementation for P256
2020-01-21 10:33:56 +08:00
Olivier Chéron
2579d1e7aa Use smaller value in felem_diff 2020-01-14 21:11:51 +01:00
Olivier Chéron
44a1651d26 Remove NULL checks in inner loop 2020-01-12 18:33:32 +01:00
Olivier Chéron
b08ce5e3ae Add 64-bit implementation for p256 2020-01-12 18:33:32 +01:00
Olivier Chéron
f9a6a35ce3 Prepare 64-bit implementation for p256 2020-01-12 18:33:32 +01:00
Olivier Chéron
f291bd08ef Move p256 felem code 2020-01-12 18:33:32 +01:00
Olivier Chéron
b5d9b6cba5 Add AppVeyor file 2020-01-12 18:21:17 +01:00
Olivier Chéron
7f1c2980e2 Merge pull request #305 from ocheron/p256-point-mul
Better P256.pointMul performance
2020-01-12 18:20:17 +01:00
Olivier Chéron
7ac3060873 Better P256.pointMul performance
Use dedicated function to avoid multiplying the basepoint with 0.
2020-01-06 18:49:12 +01:00
Olivier Chéron
1f6ed5711c Warn about non-uniform distribution with QuickCheck 2020-01-04 10:58:22 +01:00
Olivier Chéron
17879cbecd Merge pull request #303 from ocheron/square-root
Modular square root
2020-01-04 10:55:48 +01:00
Olivier Chéron
9e0dbb3231 Modular square root 2019-12-07 08:35:14 +01:00
Olivier Chéron
0a1aa3517c Fix warnings and whitespace 2019-12-03 21:06:17 +01:00
Olivier Chéron
18c6e37ef1 Merge pull request #300 from ocheron/tc-ecdsa
ECDSA with a type class
2019-12-01 08:47:33 +01:00
Olivier Chéron
95ebd3996f Merge pull request #301 from bwignall/typo
Fix typos
2019-12-01 08:45:37 +01:00
Brian Wignall
78684bc62b Fix typos 2019-11-30 18:22:26 -05:00
Olivier Chéron
99820c742d Truncate the digest without Integer conversion 2019-11-11 17:46:16 +01:00
Olivier Chéron
b9a8a6b83d ECDSA with digest 2019-11-11 17:46:16 +01:00
Olivier Chéron
15327ecd4f ECDSA with a type class 2019-11-11 17:46:16 +01:00
Olivier Chéron
8f75165f8b Time-constant P256 scalar inversion 2019-11-11 17:46:16 +01:00
Olivier Chéron
977e75f478 Add P256 functions to implement ECDSA 2019-11-11 17:46:16 +01:00
Olivier Chéron
19b7ab375a Time-constant modular inverse 2019-11-11 17:46:16 +01:00
Olivier Chéron
ce35a1e07d Merge pull request #299 from ocheron/ecc-scalar-ext
Extended ECC type class
2019-11-11 17:45:18 +01:00
Olivier Chéron
6f2a59e470 Apply hlint suggestions 2019-10-05 08:34:12 +02:00
Olivier Chéron
db8d47a76c ECC arithmetic in prime-order subgroup
A type-class extension packs together additional functions related to
a chosen basepoint as well as scalar serialization and arithmetic
modulo the subgroup order.
2019-10-05 08:34:12 +02:00
Olivier Chéron
bdf1a7a133 Require point equality in EllipticCurveArith
This is an incompatible API change but is very useful to test
properties and algorithms derived from the primitives.  An ECC
instance sufficiently advanced to have math primitives should
implement equality too.
2019-10-05 08:34:12 +02:00
Olivier Chéron
e0b201b5e7 Test P256.pointMul 2019-10-05 08:34:12 +02:00
Olivier Chéron
2e92639679 Add P256.scalarMul 2019-10-05 08:34:12 +02:00
Olivier Chéron
68c93ccbb1 Add GHC 8.8.1 to CI and bump versions 2019-10-05 08:23:45 +02:00
Olivier Chéron
e8b8a199e8 Merge pull request #293 from ocheron/xsalsa-derive
Add XSalsa.derive
2019-09-14 08:53:43 +02:00
Olivier Chéron
2433893730 Test XSalsa.derive
Adds a test case taken from NaCl paper, but without the parts related
to Curve25519 and Poly1305 because we want to test only XSalsa here.
2019-09-14 08:35:43 +02:00
Olivier Chéron
096e2ec0bd Add XSalsa.derive and example
This function adds one more HSalsa key derivation to an XSalsa context
that has previously been initialized.  It allows multi-level cascades
like the 2-level done by NaCl crypto_box.
2019-09-09 19:32:24 +02:00
Olivier Chéron
65643a3bea Merge pull request #292 from ocheron/aes-gcm-siv
AES-GCM-SIV
2019-09-08 09:49:35 +02:00
Olivier Chéron
3ae08ed509 Add API to generate a random nonce
This AEAD scheme is compatible with choosing the nonce randomly.
2019-08-25 16:38:08 +02:00
Olivier Chéron
29f0fd1b7a Test AES-GCM-SIV
Includes the test vectors from RFC 8452 and QuickCheck properties with
encryption-decryption round trip.
2019-08-25 16:38:03 +02:00
Olivier Chéron
73719cbe88 Add AES-GCM-SIV to AEAD benchmarks 2019-08-25 16:38:03 +02:00
Olivier Chéron
908f979d44 Add AES-GCM-SIV 2019-08-25 16:38:01 +02:00
Olivier Chéron
0075b57f90 Add internal AES CTR variant with 32-bit counter
This variant of CTR mode is used by AES-GCM-SIV.  The counter is in
little-endian format and uses the first four bytes of the IV only.
2019-08-25 08:55:49 +02:00
Olivier Chéron
262252a5c4 Merge pull request #291 from ocheron/p256-point-add
Faster P256.pointAdd
2019-08-25 08:51:58 +02:00
Olivier Chéron
f2fa7836cb Merge pull request #290 from ocheron/gcm-wrapping
Fix counter wrapping in AES GCM
2019-08-25 08:51:03 +02:00
Olivier Chéron
4ca77b8cf5 Faster P256.pointAdd
Convert to projective coordinates without expansive calls to function
'scalar_mult'.
2019-08-21 09:32:53 +02:00
Olivier Chéron
fc07a8b931 Fix counter wrapping in AES GCM
The generic and AESNI implementations used different conventions
regarding counter wrapping in GCM.  The generic code was based on
function block128_inc_be, for which the counter is a 128-bit value.
Whereas the AESNI code used intrinsic function _mm_add_epi64, and
therefore wrapping at 2^64.

In NIST.SP.800-38d the GCM specification mandates to use incrementing
function inc32, wrapping after 2^32 blocks.  This commit changes both
generic and AESNI implementations to align to the specification and
adds a test vector specially crafted to start encryption with IV block
0xfffffffffffffffffffffffffffffffe.
2019-08-20 10:34:40 +02:00
Olivier Chéron
0d32f9b833 Remove unused variables 2019-08-12 21:11:01 +02:00
Olivier Chéron
7e6aeaa8da Add Crypto.System.CPU to QA 2019-08-12 21:10:47 +02:00
Olivier Chéron
00221a494c Ignore stack.yaml.lock 2019-07-28 08:46:18 +02:00
Olivier Chéron
a0ad444ec1 Merge pull request #288 from 3for/P256-bench
bench for P256.pointAdd and P256.pointMul
2019-07-28 08:42:21 +02:00
Olivier Chéron
3e4ce8d2ed Merge pull request #287 from tom-audm/master
Fix typo ("strive" -> "strives")
2019-07-28 08:38:28 +02:00
root
a64a058153 warning remove and benchF2m okay 2019-07-23 11:14:09 +08:00
root
d3a60abf28 warning remove 2019-07-23 10:57:33 +08:00
root
7ca1f2e4d6 bench for P256.pointAdd and P256.pointMul 2019-07-15 10:47:58 +08:00
tom-audm
71184beb15 Fix typo ("strive" -> "strives") 2019-07-11 16:36:27 -04:00
Olivier Chéron
cdd0821eee Merge pull request #281 from ocheron/cpu-options
Add module Crypto.System.CPU
2019-06-23 09:05:13 +02:00
Olivier Chéron
53a1bf7ebf Report info about runtime environment in the test suite 2019-06-15 09:28:02 +02:00
Olivier Chéron
91c87deae1 Add Crypto.System.CPU 2019-06-15 09:28:02 +02:00
Olivier Chéron
f121d1b8d1 Merge pull request #280 from ocheron/gcm-small-table
More optimizations for AES GCM and CCM
2019-06-15 09:27:48 +02:00
Olivier Chéron
2cf3b75636 AES CCM: use AESNI in CBC-MAC computation when possible 2019-06-06 06:48:22 +02:00
Olivier Chéron
4df2a95276 AES GCM: use Shoup's method with 4-bit table 2019-06-06 06:48:16 +02:00
Olivier Chéron
5b39ae3e48 Add missing void and const 2019-05-26 11:50:07 +02:00
Olivier Chéron
c8a4e48e0c Remove unused variables 2019-05-26 11:50:07 +02:00
George Pollard
f55636bd43 Add hmacLazy for lazy ByteStrings
Modeled off `hashLazy`.
2018-03-06 18:05:02 +13:00
144 changed files with 6057 additions and 1542 deletions

29
.appveyor.yml Normal file
View 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
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ benchs/Hash
*.sublime-workspace
.cabal-sandbox/
cabal.sandbox.config
stack.yaml.lock

View File

@ -2,7 +2,8 @@
compiler: ghc-8.0 lts-9.21
compiler: ghc-8.2 lts-11.22
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
# 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
# builds
build: ghc-8.2 basementmin
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.6
build: ghc-8.6 os=linux,osx,windows
build: ghc-8.8 os=linux,windows
# packages
package: '.'

3
.hlint.yaml Normal file
View File

@ -0,0 +1,3 @@
- arguments: [ --cpp-define=ARCH_X86_64
]
- ignore: { name: Use camelCase }

View File

@ -1,7 +1,4 @@
# ~*~ auto-generated by haskell-ci with config : cb76551db808ad3472d36865246ef3849351a6c78535dd987bd37bc95bfd47c0 ~*~
# Use new container infrastructure to enable caching
sudo: false
# ~*~ auto-generated by haskell-ci with config : 4fdddfa41dd039e198b8d125a70471f7dd140fa01001d99126af56fb31429ece ~*~
# Caching so the next build will be fast too.
cache:
@ -10,28 +7,32 @@ cache:
- $HOME/.stack
- $HOME/.local
matrix:
language: generic
os: linux
jobs:
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, compiler: ghc-8.0, language: generic, 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, compiler: ghc-8.4, language: generic, 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=hlint, compiler: hlint, language: generic }
- { env: BUILD=weeder, compiler: weeder, 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.2, addons: { apt: { packages: [ libgmp-dev ] } } }
- { env: BUILD=stack RESOLVER=ghc-8.4, addons: { apt: { packages: [ libgmp-dev ] } } }
- { env: BUILD=stack RESOLVER=ghc-8.6, addons: { apt: { packages: [ libgmp-dev ] } } }
- { env: BUILD=stack RESOLVER=ghc-8.6, addons: { apt: { packages: [ libgmp-dev ] } }, os: osx }
- { env: BUILD=stack RESOLVER=ghc-8.8, addons: { apt: { packages: [ libgmp-dev ] } } }
- { env: BUILD=hlint }
- { env: BUILD=weeder, addons: { apt: { packages: [ libgmp-dev ] } } }
allow_failures:
- { env: BUILD=hlint, compiler: hlint, language: generic }
- { env: BUILD=weeder, compiler: weeder, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
- { env: BUILD=hlint }
- { env: BUILD=weeder, addons: { apt: { packages: [ libgmp-dev ] } } }
install:
- export PATH=$HOME/.local/bin::$HOME/.cabal/bin:$PATH
- export PATH=$HOME/.local/bin:$HOME/.cabal/bin:$PATH
- mkdir -p ~/.local/bin
- |
case "$BUILD" in
stack|weeder)
if [ `uname` = "Darwin" ]
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
travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
fi
@ -48,24 +49,24 @@ script:
stack)
# create the build stack.yaml
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)
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
;;
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)
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
;;
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
;;
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
;;
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 .
;;
esac

View File

@ -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
* Add Rabin cryptosystem (and variants)

View File

@ -37,6 +37,9 @@ module Crypto.Cipher.AES.Primitive
, decryptCTR
, decryptXTS
-- * CTR with 32-bit wrapping
, combineC32
-- * Incremental GCM
, gcmMode
, gcmInit
@ -128,7 +131,7 @@ newtype AESCCM = AESCCM ScrubbedBytes
deriving (NFData)
sizeGCM :: Int
sizeGCM = 80
sizeGCM = 320
sizeOCB :: Int
sizeOCB = 160
@ -317,6 +320,21 @@ decryptXTS :: ByteArray ba
-> ba -- ^ output decrypted
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 #-}
doECB :: ByteArray ba
=> (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"
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"
c_aes_gcm_init :: Ptr AESGCM -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()

193
Crypto/Cipher/AESGCMSIV.hs Normal file
View 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

View File

@ -41,9 +41,9 @@ initialize :: (ByteArrayAccess key, ByteArrayAccess nonce)
-> nonce -- ^ the nonce (64 or 96 bits)
-> State -- ^ the initial ChaCha state
initialize nbRounds key nonce
| not (kLen `elem` [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"
| not (nbRounds `elem` [8,12,20]) = error "ChaCha: rounds should be 8, 12 or 20"
| kLen `notElem` [16,32] = error "ChaCha: key length should be 128 or 256 bits"
| nonceLen `notElem` [8,12] = error "ChaCha: nonce length should be 64 or 96 bits"
| nbRounds `notElem` [8,12,20] = error "ChaCha: rounds should be 8, 12 or 20"
| otherwise = unsafeDoIO $ do
stPtr <- B.alloc 132 $ \stPtr ->
B.withByteArray nonce $ \noncePtr ->

View File

@ -30,6 +30,11 @@ import Crypto.Internal.Compat
import Crypto.Internal.Imports
-- | 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
deriving (ByteArrayAccess,NFData)

View File

@ -33,9 +33,9 @@ initialize :: (ByteArrayAccess key, ByteArrayAccess nonce)
-> nonce -- ^ the nonce (64 or 96 bits)
-> State -- ^ the initial Salsa state
initialize nbRounds key nonce
| not (kLen `elem` [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"
| not (nbRounds `elem` [8,12,20]) = error "Salsa: rounds should be 8, 12 or 20"
| kLen `notElem` [16,32] = error "Salsa: key length should be 128 or 256 bits"
| nonceLen `notElem` [8,12] = error "Salsa: nonce length should be 64 or 96 bits"
| nbRounds `notElem` [8,12,20] = error "Salsa: rounds should be 8, 12 or 20"
| otherwise = unsafeDoIO $ do
stPtr <- B.alloc 132 $ \stPtr ->
B.withByteArray nonce $ \noncePtr ->

View File

@ -27,24 +27,24 @@ data AEADModeImpl st = AEADModeImpl
-- | Authenticated Encryption with Associated Data algorithms
data AEAD cipher = forall st . AEAD
{ aeadModeImpl :: AEADModeImpl st
, aeadState :: st
, aeadState :: !st
}
-- | Append some header information to an AEAD context
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
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
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
aeadFinalize :: AEAD cipher -> Int -> AuthTag
aeadFinalize (AEAD impl st) n = (aeadImplFinalize impl) st n
aeadFinalize (AEAD impl st) = aeadImplFinalize impl st
-- | Simple AEAD encryption
aeadSimpleEncrypt :: (ByteArrayAccess aad, ByteArray ba)

View File

@ -12,6 +12,7 @@
{-# LANGUAGE ForeignFunctionInterface #-}
module Crypto.Cipher.XSalsa
( initialize
, derive
, combine
, generate
, State
@ -34,7 +35,7 @@ initialize :: (ByteArrayAccess key, ByteArrayAccess nonce)
initialize nbRounds key nonce
| kLen /= 32 = error "XSalsa: key length should be 256 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
stPtr <- B.alloc 132 $ \stPtr ->
B.withByteArray nonce $ \noncePtr ->
@ -44,5 +45,31 @@ initialize nbRounds key nonce
where kLen = B.length key
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"
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 ()

View File

@ -44,7 +44,7 @@ compute' g = MP . foldl' (step $ g) (B.replicate bsz 0) . chunks . pad (ZERO bsz
where
(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.
--
-- Simple usage /mp' msg :: MiyaguchiPreneel AES128/

View File

@ -6,7 +6,7 @@
-- Portability : unknown
--
-- Various cryptographic padding commonly used for block ciphers
-- or assymetric systems.
-- or asymmetric systems.
--
module Crypto.Data.Padding
( Format(..)

View File

@ -8,6 +8,7 @@
-- Elliptic Curve Cryptography
--
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
@ -21,6 +22,7 @@ module Crypto.ECC
, EllipticCurve(..)
, EllipticCurveDH(..)
, EllipticCurveArith(..)
, EllipticCurveBasepointArith(..)
, KeyPair(..)
, SharedSecret(..)
) where
@ -34,7 +36,9 @@ import Crypto.Error
import Crypto.Internal.Imports
import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Number.Basic (numBits)
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.Curve448 as X448
import Data.ByteArray (convert)
@ -98,7 +102,7 @@ class EllipticCurve curve => EllipticCurveDH curve where
-- value or an exception.
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
pointAdd :: proxy curve -> Point curve -> Point curve -> Point curve
@ -111,6 +115,35 @@ class EllipticCurve curve => EllipticCurveArith curve where
-- -- | Scalar Inverse
-- 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
--
-- also known as P256
@ -133,11 +166,11 @@ instance EllipticCurve Curve_P256R1 where
uncompressed = B.singleton 4
xy = P256.pointToBinary p
decodePoint _ mxy = case B.uncons mxy of
Nothing -> CryptoFailed $ CryptoError_PointSizeInvalid
Nothing -> CryptoFailed CryptoError_PointSizeInvalid
Just (m,xy)
-- uncompressed
| m == 4 -> P256.pointFromBinary xy
| otherwise -> CryptoFailed $ CryptoError_PointFormatInvalid
| otherwise -> CryptoFailed CryptoError_PointFormatInvalid
instance EllipticCurveArith Curve_P256R1 where
pointAdd _ a b = P256.pointAdd a b
@ -148,6 +181,17 @@ instance EllipticCurveDH Curve_P256R1 where
ecdhRaw _ s p = SharedSecret $ P256.pointDh 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
deriving (Show,Data)
@ -171,6 +215,17 @@ instance EllipticCurveDH Curve_P384R1 where
where
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
deriving (Show,Data)
@ -194,6 +249,17 @@ instance EllipticCurveDH Curve_P521R1 where
where
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
deriving (Show,Data)
@ -250,6 +316,22 @@ instance EllipticCurveArith Curve_Edwards25519 where
pointNegate _ p = Edwards25519.pointNegate 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 s@(SharedSecret b)
| 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 mxy = case B.uncons mxy of
Nothing -> CryptoFailed $ CryptoError_PointSizeInvalid
Nothing -> CryptoFailed CryptoError_PointSizeInvalid
Just (m,xy)
-- uncompressed
| m == 4 ->
@ -280,4 +362,47 @@ decodeECPoint mxy = case B.uncons mxy of
x = os2ip xb
y = os2ip yb
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)

View File

@ -283,45 +283,45 @@ pointsMulVarTime (Scalar s1) (Scalar s2) (Point p) =
withByteArray p $ \pp ->
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
-> Ptr Scalar
-> IO CInt
foreign import ccall "cryptonite_ed25519_scalar_encode"
foreign import ccall unsafe "cryptonite_ed25519_scalar_encode"
ed25519_scalar_encode :: Ptr Word8
-> Ptr Scalar
-> IO ()
foreign import ccall "cryptonite_ed25519_scalar_decode_long"
foreign import ccall unsafe "cryptonite_ed25519_scalar_decode_long"
ed25519_scalar_decode_long :: Ptr Scalar
-> Ptr Word8
-> CSize
-> IO ()
foreign import ccall "cryptonite_ed25519_scalar_add"
foreign import ccall unsafe "cryptonite_ed25519_scalar_add"
ed25519_scalar_add :: Ptr Scalar -- sum
-> Ptr Scalar -- a
-> Ptr Scalar -- b
-> IO ()
foreign import ccall "cryptonite_ed25519_scalar_mul"
foreign import ccall unsafe "cryptonite_ed25519_scalar_mul"
ed25519_scalar_mul :: Ptr Scalar -- out
-> Ptr Scalar -- a
-> Ptr Scalar -- b
-> IO ()
foreign import ccall "cryptonite_ed25519_point_encode"
foreign import ccall unsafe "cryptonite_ed25519_point_encode"
ed25519_point_encode :: Ptr Word8
-> Ptr Point
-> IO ()
foreign import ccall "cryptonite_ed25519_point_decode_vartime"
foreign import ccall unsafe "cryptonite_ed25519_point_decode_vartime"
ed25519_point_decode_vartime :: Ptr Point
-> Ptr Word8
-> IO CInt
foreign import ccall "cryptonite_ed25519_point_eq"
foreign import ccall unsafe "cryptonite_ed25519_point_eq"
ed25519_point_eq :: Ptr Point
-> Ptr Point
-> IO CInt
@ -330,23 +330,23 @@ foreign import ccall "cryptonite_ed25519_point_has_prime_order"
ed25519_point_has_prime_order :: Ptr Point
-> IO CInt
foreign import ccall "cryptonite_ed25519_point_negate"
foreign import ccall unsafe "cryptonite_ed25519_point_negate"
ed25519_point_negate :: Ptr Point -- minus_a
-> Ptr Point -- a
-> IO ()
foreign import ccall "cryptonite_ed25519_point_add"
foreign import ccall unsafe "cryptonite_ed25519_point_add"
ed25519_point_add :: Ptr Point -- sum
-> Ptr Point -- a
-> Ptr Point -- b
-> IO ()
foreign import ccall "cryptonite_ed25519_point_double"
foreign import ccall unsafe "cryptonite_ed25519_point_double"
ed25519_point_double :: Ptr Point -- two_a
-> Ptr Point -- a
-> 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
-> Ptr Point -- a
-> IO ()

View File

@ -28,15 +28,20 @@ module Crypto.Hash
-- * Hash methods parametrized by algorithm
, hashInitWith
, hashWith
, hashPrefixWith
-- * Hash methods
, hashInit
, hashUpdates
, hashUpdate
, hashFinalize
, hashFinalizePrefix
, hashBlockSize
, hashDigestSize
, hash
, hashPrefix
, hashlazy
, hashPutContext
, hashGetContext
-- * Hash algorithms
, module Crypto.Hash.Algorithms
) where
@ -47,16 +52,21 @@ import Basement.Block.Mutable (copyFromPtr, new)
import Crypto.Internal.Compat (unsafeDoIO)
import Crypto.Hash.Types
import Crypto.Hash.Algorithms
import Foreign.Ptr (Ptr)
import Crypto.Internal.ByteArray (ByteArrayAccess)
import Foreign.Ptr (Ptr, plusPtr)
import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray)
import qualified Crypto.Internal.ByteArray as B
import qualified Data.ByteString.Lazy as L
import Data.Word (Word8)
import Data.Int (Int32)
-- | Hash a strict bytestring into a digest.
hash :: (ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a
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.
hashlazy :: HashAlgorithm a => L.ByteString -> Digest a
hashlazy lbs = hashFinalize $ hashUpdates hashInit (L.toChunks lbs)
@ -81,9 +91,17 @@ hashUpdates :: forall a ba . (HashAlgorithm a, ByteArrayAccess ba)
hashUpdates c l
| null ls = c
| 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
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.
hashFinalize :: forall a . HashAlgorithm a
@ -94,6 +112,24 @@ hashFinalize !c =
((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (Context a)) -> hashInternalFinalize ctx dig
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
hashInitWith :: HashAlgorithm alg => alg -> Context alg
hashInitWith _ = hashInit
@ -102,6 +138,10 @@ hashInitWith _ = hashInit
hashWith :: (ByteArrayAccess ba, HashAlgorithm alg) => alg -> ba -> Digest alg
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.
--
-- If the digest is not the right size for the algorithm specified, then
@ -121,3 +161,16 @@ digestFromByteString = from undefined
unsafeFreeze muArray
where
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

View File

@ -9,6 +9,8 @@
--
module Crypto.Hash.Algorithms
( HashAlgorithm
, HashAlgorithmPrefix
, HashAlgorithmResumable
-- * Hash algorithms
, Blake2s_160(..)
, Blake2s_224(..)
@ -54,7 +56,7 @@ module Crypto.Hash.Algorithms
, Whirlpool(..)
) where
import Crypto.Hash.Types (HashAlgorithm)
import Crypto.Hash.Types (HashAlgorithm, HashAlgorithmPrefix, HashAlgorithmResumable)
import Crypto.Hash.Blake2s
import Crypto.Hash.Blake2sp
import Crypto.Hash.Blake2b

View File

@ -24,6 +24,11 @@ import qualified Crypto.Internal.ByteArray as B
import Foreign.Ptr
-- | 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
deriving (B.ByteArrayAccess)

View File

@ -37,6 +37,10 @@ instance HashAlgorithm Keccak_224 where
hashInternalUpdate = c_keccak_update
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
data Keccak_256 = Keccak_256
deriving (Show,Data)
@ -52,6 +56,10 @@ instance HashAlgorithm Keccak_256 where
hashInternalUpdate = c_keccak_update
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
data Keccak_384 = Keccak_384
deriving (Show,Data)
@ -67,6 +75,10 @@ instance HashAlgorithm Keccak_384 where
hashInternalUpdate = c_keccak_update
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
data Keccak_512 = Keccak_512
deriving (Show,Data)
@ -82,6 +94,10 @@ instance HashAlgorithm Keccak_512 where
hashInternalUpdate = c_keccak_update
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"
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"
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 ()

View File

@ -34,6 +34,9 @@ instance HashAlgorithm MD5 where
hashInternalUpdate = c_md5_update
hashInternalFinalize = c_md5_finalize
instance HashAlgorithmPrefix MD5 where
hashInternalFinalizePrefix = c_md5_finalize_prefix
foreign import ccall unsafe "cryptonite_md5_init"
c_md5_init :: Ptr (Context a)-> IO ()
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_md5_update"
foreign import ccall unsafe "cryptonite_md5_finalize"
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 ()

View File

@ -34,6 +34,9 @@ instance HashAlgorithm SHA1 where
hashInternalUpdate = c_sha1_update
hashInternalFinalize = c_sha1_finalize
instance HashAlgorithmPrefix SHA1 where
hashInternalFinalizePrefix = c_sha1_finalize_prefix
foreign import ccall unsafe "cryptonite_sha1_init"
c_sha1_init :: Ptr (Context a)-> IO ()
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha1_update"
foreign import ccall unsafe "cryptonite_sha1_finalize"
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 ()

View File

@ -34,6 +34,9 @@ instance HashAlgorithm SHA224 where
hashInternalUpdate = c_sha224_update
hashInternalFinalize = c_sha224_finalize
instance HashAlgorithmPrefix SHA224 where
hashInternalFinalizePrefix = c_sha224_finalize_prefix
foreign import ccall unsafe "cryptonite_sha224_init"
c_sha224_init :: Ptr (Context a)-> IO ()
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha224_update"
foreign import ccall unsafe "cryptonite_sha224_finalize"
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 ()

View File

@ -34,6 +34,9 @@ instance HashAlgorithm SHA256 where
hashInternalUpdate = c_sha256_update
hashInternalFinalize = c_sha256_finalize
instance HashAlgorithmPrefix SHA256 where
hashInternalFinalizePrefix = c_sha256_finalize_prefix
foreign import ccall unsafe "cryptonite_sha256_init"
c_sha256_init :: Ptr (Context a)-> IO ()
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha256_update"
foreign import ccall unsafe "cryptonite_sha256_finalize"
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 ()

View File

@ -37,6 +37,10 @@ instance HashAlgorithm SHA3_224 where
hashInternalUpdate = c_sha3_update
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
data SHA3_256 = SHA3_256
deriving (Show,Data)
@ -52,6 +56,10 @@ instance HashAlgorithm SHA3_256 where
hashInternalUpdate = c_sha3_update
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
data SHA3_384 = SHA3_384
deriving (Show,Data)
@ -67,6 +75,10 @@ instance HashAlgorithm SHA3_384 where
hashInternalUpdate = c_sha3_update
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
data SHA3_512 = SHA3_512
deriving (Show,Data)
@ -82,6 +94,10 @@ instance HashAlgorithm SHA3_512 where
hashInternalUpdate = c_sha3_update
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"
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"
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 ()

View File

@ -34,6 +34,9 @@ instance HashAlgorithm SHA384 where
hashInternalUpdate = c_sha384_update
hashInternalFinalize = c_sha384_finalize
instance HashAlgorithmPrefix SHA384 where
hashInternalFinalizePrefix = c_sha384_finalize_prefix
foreign import ccall unsafe "cryptonite_sha384_init"
c_sha384_init :: Ptr (Context a)-> IO ()
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha384_update"
foreign import ccall unsafe "cryptonite_sha384_finalize"
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 ()

View File

@ -34,6 +34,9 @@ instance HashAlgorithm SHA512 where
hashInternalUpdate = c_sha512_update
hashInternalFinalize = c_sha512_finalize
instance HashAlgorithmPrefix SHA512 where
hashInternalFinalizePrefix = c_sha512_finalize_prefix
foreign import ccall unsafe "cryptonite_sha512_init"
c_sha512_init :: Ptr (Context a)-> IO ()
@ -42,3 +45,6 @@ foreign import ccall "cryptonite_sha512_update"
foreign import ccall unsafe "cryptonite_sha512_finalize"
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 ()

View File

@ -62,6 +62,10 @@ instance KnownNat bitlen => HashSHAKE (SHAKE128 bitlen) where
cshakeInternalFinalize = cshakeFinalizeOutput (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
-- 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)
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
=> proxy bitlen
-> Ptr (Context a)
@ -129,3 +137,9 @@ foreign import ccall unsafe "cryptonite_sha3_finalize_cshake"
foreign import ccall unsafe "cryptonite_sha3_output"
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 ()

View File

@ -14,6 +14,8 @@
{-# LANGUAGE TypeFamilies #-}
module Crypto.Hash.Types
( HashAlgorithm(..)
, HashAlgorithmPrefix(..)
, HashAlgorithmResumable(..)
, Context(..)
, Digest(..)
) where
@ -59,12 +61,31 @@ class HashAlgorithm a where
-- | Finalize the context and set the digest raw memory to the right value
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 = undefined
-}
-- | 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
deriving (ByteArrayAccess,NFData)

View 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 ())

View File

@ -23,15 +23,21 @@ module Crypto.Internal.CompatPrim
, convert4To32
) where
import GHC.Prim
#if !defined(ARCH_IS_LITTLE_ENDIAN) && !defined(ARCH_IS_BIG_ENDIAN)
import Data.Memory.Endian (getSystemEndianness, Endianness(..))
#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
--
-- On a big endian machine, this function is a nop.
be32Prim :: Word# -> Word#
be32Prim :: Word32# -> Word32#
#ifdef ARCH_IS_LITTLE_ENDIAN
be32Prim = byteswap32Prim
#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
--
-- On a little endian machine, this function is a nop.
le32Prim :: Word# -> Word#
le32Prim :: Word32# -> Word32#
#ifdef ARCH_IS_LITTLE_ENDIAN
le32Prim w = w
#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#
-- at the primitive level
byteswap32Prim :: Word# -> Word#
#if __GLASGOW_HASKELL__ >= 708
byteswap32Prim w = byteSwap32# w
byteswap32Prim :: Word32# -> Word32#
#if __GLASGOW_HASKELL__ >= 902
byteswap32Prim w = wordToWord32# (byteSwap32# (word32ToWord# w))
#else
byteswap32Prim 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))
byteswap32Prim w = byteSwap32# w
#endif
-- | Combine 4 word8 [a,b,c,d] to a word32 representing [a,b,c,d]

View File

@ -5,11 +5,15 @@
-- Stability : experimental
-- Portability : unknown
--
{-# LANGUAGE CPP #-}
module Crypto.Internal.Imports
( module X
) where
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.Monad as X (forM, forM_, void)
import Control.Arrow as X (first, second)

View File

@ -94,7 +94,7 @@ bxor = B.xor
cipherIPT :: BlockCipher k => k -> [Word8]
cipherIPT = expandIPT . blockSize where
cipherIPT = expandIPT . blockSize
-- Data type which represents the smallest irreducibule binary polynomial
-- against specified degree.

View File

@ -12,6 +12,7 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Crypto.MAC.HMAC
( hmac
, hmacLazy
, HMAC(..)
-- * Incremental
, Context(..)
@ -28,6 +29,7 @@ import Crypto.Internal.ByteArray (ScrubbedBytes, ByteArrayAccess)
import qualified Crypto.Internal.ByteArray as B
import Data.Memory.PtrMethods
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.
--
@ -39,13 +41,20 @@ newtype HMAC a = HMAC { hmacGetDigest :: Digest a }
instance Eq (HMAC a) where
(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)
=> key -- ^ Secret key
-> message -- ^ Message to MAC
-> HMAC a
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'
-- and finalize to an HMAC with 'hmacFinalize'
data Context hashalg = Context !(Hash.Context hashalg) !(Hash.Context hashalg)

View File

@ -27,13 +27,12 @@ import qualified Crypto.Hash as H
import Crypto.Hash.SHAKE (HashSHAKE(..))
import Crypto.Hash.Types (HashAlgorithm(..), Digest(..))
import qualified Crypto.Hash.Types as H
import Foreign.Ptr (Ptr, plusPtr)
import Foreign.Storable (poke)
import Crypto.Internal.Builder
import Crypto.Internal.Imports
import Foreign.Ptr (Ptr)
import Data.Bits (shiftR)
import Data.ByteArray (ByteArray, ByteArrayAccess)
import Data.ByteArray (ByteArrayAccess)
import qualified Data.ByteArray as B
import Data.Word (Word8)
import Data.Memory.PtrMethods (memSet)
-- cSHAKE
@ -47,8 +46,8 @@ cshakeInit n s p = H.Context $ B.allocAndFreeze c $ \(ptr :: Ptr (H.Context a))
where
c = hashInternalContextSize (undefined :: a)
w = hashBlockSize (undefined :: a)
x = encodeString n <+> encodeString s
b = builderAllocAndFreeze (bytepad x w) :: B.Bytes
x = encodeString n <> encodeString s
b = buildAndFreeze (bytepad x w) :: B.Bytes
cshakeUpdate :: (HashSHAKE a, ByteArrayAccess ba)
=> 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
-- printing by mistake.
newtype KMAC a = KMAC { kmacGetDigest :: Digest a }
deriving ByteArrayAccess
deriving (ByteArrayAccess,NFData)
instance Eq (KMAC a) where
(KMAC b1) == (KMAC b2) = B.constEq b1 b2
@ -99,7 +98,7 @@ initialize str key = Context $ cshakeInit n str p
where
n = B.pack [75,77,65,67] :: B.Bytes -- "KMAC"
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.
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
where
l = cshakeOutputLength (undefined :: a)
suffix = builderAllocAndFreeze (rightEncode l) :: B.Bytes
suffix = buildAndFreeze (rightEncode l) :: B.Bytes
-- Utilities
bytepad :: Builder -> Int -> Builder
bytepad x w = prefix <+> x <+> zero padLen
bytepad x w = prefix <> x <> zero padLen
where
prefix = leftEncode w
padLen = (w - builderLength prefix - builderLength x) `mod` w
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 x = byte len <+> digits
leftEncode x = byte len <> digits
where
digits = i2osp x
len = fromIntegral (builderLength digits)
rightEncode :: Int -> Builder
rightEncode x = digits <+> byte len
rightEncode x = digits <> byte len
where
digits = i2osp x
len = fromIntegral (builderLength digits)
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)
-- 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)

View File

@ -33,6 +33,11 @@ import Crypto.Internal.DeepSeq
import Crypto.Error
-- | 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
deriving (ByteArrayAccess)

View File

@ -72,7 +72,9 @@ gmpLog2 _ = GmpUnsupported
-- | Compute the power modulus using extra security to remain constant
-- time wise through GMP
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)
#elif MIN_VERSION_integer_gmp(1,0,0)
gmpPowModSecInteger _ _ _ = GmpUnsupported
@ -103,7 +105,9 @@ gmpInverse _ _ = GmpUnsupported
-- | Get the next prime from a specific value through GMP
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)
#else
gmpNextPrime _ = GmpUnsupported
@ -111,7 +115,9 @@ gmpNextPrime _ = GmpUnsupported
-- | Test if a number is prime using Miller Rabin
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 $
case testPrimeInteger n tries of
0# -> False

View File

@ -16,7 +16,9 @@ module Crypto.Number.F2m
, mulF2m
, squareF2m'
, squareF2m
, powF2m
, modF2m
, sqrtF2m
, invF2m
, divF2m
) where
@ -66,8 +68,8 @@ mulF2m :: BinaryPolynomial -- ^ Modulus
mulF2m fx n1 n2
| fx < 0
|| n1 < 0
|| n2 < 0 = error "mulF2m: negative number represent no binary binary polynomial"
| fx == 0 = error "modF2m: cannot multiply modulo zero polynomial"
|| n2 < 0 = error "mulF2m: negative number represent no binary 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)
where
go n s | s == 0 = n
@ -96,10 +98,37 @@ squareF2m fx = modF2m fx . squareF2m'
squareF2m' :: Integer
-> Integer
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]
{-# 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@.
--
-- Reference: https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#B.C3.A9zout.27s_identity_and_extended_GCD_algorithm

View File

@ -1,5 +1,4 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveDataTypeable #-}
-- |
-- Module : Crypto.Number.ModArithmetic
-- License : BSD-style
@ -15,7 +14,10 @@ module Crypto.Number.ModArithmetic
-- * Inverse computing
, inverse
, inverseCoprimes
, inverseFermat
-- * Squares
, jacobi
, squareRoot
) where
import Control.Exception (throw, Exception)
@ -56,7 +58,7 @@ expSafe b e m
-- hiding parameters.
--
-- Use this function when all the parameters are public,
-- otherwise 'expSafe' should be prefered.
-- otherwise 'expSafe' should be preferred.
expFast :: Integer -- ^ base
-> Integer -- ^ exponent
-> Integer -- ^ modulo
@ -70,7 +72,7 @@ exponentiation b e m
| b == 1 = b
| e == 0 = 1
| 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
| otherwise = (b * exponentiation b (e-1) m) `mod` m
@ -120,3 +122,96 @@ jacobi a n
n1 = n `mod` a1
in if a1 == 1 then Just s
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'

View File

@ -127,7 +127,7 @@ primalityTestMillerRabin tries !n =
factorise :: Integer -> Integer -> (Integer, Integer)
factorise !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
-- when iteration reach zero, we have a probable prime

View File

@ -8,7 +8,6 @@
-- P256 support
--
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# OPTIONS_GHC -fno-warn-unused-binds #-}
module Crypto.PubKey.ECC.P256
@ -22,7 +21,9 @@ module Crypto.PubKey.ECC.P256
, pointDh
, pointsMulVarTime
, pointIsValid
, pointIsAtInfinity
, toPoint
, pointX
, pointToIntegers
, pointFromIntegers
, pointToBinary
@ -31,10 +32,13 @@ module Crypto.PubKey.ECC.P256
-- * Scalar arithmetic
, scalarGenerate
, scalarZero
, scalarN
, scalarIsZero
, scalarAdd
, scalarSub
, scalarMul
, scalarInv
, scalarInvSafe
, scalarCmp
, scalarFromBinary
, scalarToBinary
@ -76,6 +80,9 @@ data P256Scalar
data P256Y
data P256X
order :: Integer
order = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
------------------------------------------------------------------------
-- Point methods
------------------------------------------------------------------------
@ -109,7 +116,7 @@ pointAdd a b = withNewPoint $ \dx dy ->
-- | Negate a point
pointNegate :: Point -> Point
pointNegate a = withNewPoint $ \dx dy ->
withPoint a $ \ax ay -> do
withPoint a $ \ax ay ->
ccryptonite_p256e_point_negate ax ay dx dy
-- | Multiply a point by a scalar
@ -117,16 +124,16 @@ pointNegate a = withNewPoint $ \dx dy ->
-- warning: variable time
pointMul :: Scalar -> Point -> Point
pointMul scalar p = withNewPoint $ \dx dy ->
withScalar scalar $ \n -> withPoint p $ \px py -> withScalarZero $ \nzero ->
ccryptonite_p256_points_mul_vartime nzero n px py dx dy
withScalar scalar $ \n -> withPoint p $ \px py ->
ccryptonite_p256e_point_mul n px py dx dy
-- | Similar to 'pointMul', serializing the x coordinate as binary.
-- When scalar is multiple of point order the result is all zero.
pointDh :: ByteArray binary => Scalar -> Point -> binary
pointDh scalar p =
B.unsafeCreate scalarSize $ \dst -> withTempPoint $ \dx dy -> do
withScalar scalar $ \n -> withPoint p $ \px py -> withScalarZero $ \nzero ->
ccryptonite_p256_points_mul_vartime nzero n px py dx dy
withScalar scalar $ \n -> withPoint p $ \px py ->
ccryptonite_p256e_point_mul n px py dx dy
ccryptonite_p256_to_bin (castPtr dx) dst
-- | 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
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
pointToIntegers :: Point -> (Integer, Integer)
pointToIntegers p = unsafeDoIO $ withPoint p $ \px py ->
@ -187,12 +207,12 @@ pointFromBinary ba = unsafePointFromBinary ba >>= validatePoint
validatePoint :: Point -> CryptoFailable Point
validatePoint p
| pointIsValid p = CryptoPassed p
| otherwise = CryptoFailed $ CryptoError_PointCoordinatesInvalid
| otherwise = CryptoFailed CryptoError_PointCoordinatesInvalid
-- | Convert from binary to a point, possibly invalid
unsafePointFromBinary :: ByteArrayAccess ba => ba -> CryptoFailable Point
unsafePointFromBinary ba
| B.length ba /= pointSize = CryptoFailed $ CryptoError_PublicKeySizeInvalid
| B.length ba /= pointSize = CryptoFailed CryptoError_PublicKeySizeInvalid
| otherwise =
CryptoPassed $ withNewPoint $ \px py -> B.withByteArray ba $ \src -> do
ccryptonite_p256_from_bin src (castPtr px)
@ -215,6 +235,10 @@ scalarGenerate = unwrap . scalarFromBinary . witness <$> getRandomBytes 32
scalarZero :: Scalar
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
scalarIsZero :: Scalar -> Bool
scalarIsZero s = unsafeDoIO $ withScalar s $ \d -> do
@ -237,6 +261,14 @@ scalarSub a b =
withNewScalarFreeze $ \d -> withScalar a $ \pa -> withScalar b $ \pb ->
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
--
-- > 1 / a
@ -247,6 +279,14 @@ scalarInv a =
withNewScalarFreeze $ \b -> withScalar a $ \pa ->
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
scalarCmp :: Scalar -> Scalar -> Ordering
scalarCmp a b = unsafeDoIO $
@ -257,7 +297,7 @@ scalarCmp a b = unsafeDoIO $
-- | convert a scalar from binary
scalarFromBinary :: ByteArrayAccess ba => ba -> CryptoFailable Scalar
scalarFromBinary ba
| B.length ba /= scalarSize = CryptoFailed $ CryptoError_SecretKeySizeInvalid
| B.length ba /= scalarSize = CryptoFailed CryptoError_SecretKeySizeInvalid
| otherwise =
CryptoPassed $ withNewScalarFreeze $ \p -> B.withByteArray ba $ \b ->
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 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 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 n f = ignoreSnd <$> B.allocRet n f
where
@ -350,6 +381,8 @@ foreign import ccall "cryptonite_p256_mod"
ccryptonite_p256_mod :: Ptr P256Scalar -> Ptr P256Scalar -> Ptr P256Scalar -> IO ()
foreign import ccall "cryptonite_p256_modmul"
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"
-- ccryptonite_p256_modinv :: Ptr P256Scalar -> Ptr P256Scalar -> Ptr P256Scalar -> IO ()
foreign import ccall "cryptonite_p256_modinv_vartime"
@ -370,6 +403,13 @@ foreign import ccall "cryptonite_p256e_point_negate"
-> Ptr P256X -> Ptr P256Y
-> 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)
foreign import ccall "cryptonite_p256_points_mul_vartime"
ccryptonite_p256_points_mul_vartime :: Ptr P256Scalar -- n1

272
Crypto/PubKey/ECDSA.hs Normal file
View 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
View 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

View File

@ -80,6 +80,13 @@ drgNewSeed (Seed seed) = initialize seed
--
-- It can also be used in other contexts provided the input
-- 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 = initializeWords

View File

@ -25,10 +25,9 @@ replenish :: Int -> [EntropyBackend] -> Ptr Word8 -> IO ()
replenish _ [] _ = fail "cryptonite: random: cannot get any source of entropy on this system"
replenish poolSize backends ptr = loop 0 backends ptr poolSize
where loop :: Int -> [EntropyBackend] -> Ptr Word8 -> Int -> IO ()
loop retry [] p n | n == 0 = return ()
| retry == 3 = error "cryptonite: random: cannot fully replenish"
loop _ _ _ 0 = return ()
loop retry [] p n | retry == 3 = error "cryptonite: random: cannot fully replenish"
| otherwise = loop (retry+1) backends p n
loop _ (_:_) _ 0 = return ()
loop retry (b:bs) p n = do
r <- gatherBackend b p n
loop retry bs (p `plusPtr` r) (n - r)

View File

@ -17,7 +17,7 @@ import Crypto.Random.Entropy
import Crypto.Internal.ByteArray
-- | 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
-- | A Deterministic Random Generator (DRG) class

64
Crypto/System/CPU.hs Normal file
View 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)

View File

@ -8,6 +8,9 @@ module Crypto.Tutorial
-- * Symmetric block ciphers
-- $symmetric_block_ciphers
-- * Combining primitives
-- $combining_primitives
) where
-- $api_design
@ -147,3 +150,46 @@ module Crypto.Tutorial
-- > putStrLn $ "Original Message: " ++ show msg
-- > putStrLn $ "Message after encryption: " ++ show eMsg
-- > 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
View File

@ -47,7 +47,9 @@ perModuleAllowedExtensions =
, ("Crypto/Cipher/DES/Primitive.hs", [FlexibleInstances])
, ("Crypto/Cipher/Twofish/Primitive.hs", [MagicHash])
, ("Crypto/PubKey/Curve25519.hs", [MagicHash])
, ("Crypto/PubKey/ECDSA.hs", [FlexibleContexts,StandaloneDeriving,UndecidableInstances])
, ("Crypto/Number/Compat.hs", [UnboxedTuples,MagicHash,CPP])
, ("Crypto/System/CPU.hs", [CPP])
]
disallowedModules =

View File

@ -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
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
---------------
@ -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)
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
-----

View File

@ -1,11 +1,13 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
module Main where
import Gauge.Main
import Crypto.Cipher.AES
import qualified Crypto.Cipher.AESGCMSIV as AESGCMSIV
import Crypto.Cipher.Blowfish
import Crypto.Cipher.CAST5
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.ECC.Types 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 Control.DeepSeq (NFData)
import Data.ByteArray (ByteArray, Bytes)
import qualified Data.ByteString as B
import qualified Crypto.PubKey.ECC.P256 as P256
import Number.F2m
data HashAlg = forall alg . HashAlgorithm alg => HashAlg alg
@ -165,6 +172,7 @@ benchAE =
[ bench "ChaChaPoly1305" $ nf (cp key32) (input64, input1024)
, bench "AES-GCM" $ nf (gcm 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) =
let iniState = throwCryptoError $ CP.initialize k (throwCryptoError $ CP.nonce12 nonce12)
@ -184,6 +192,11 @@ benchAE =
state = throwCryptoError $ aeadInit mode ctx nonce12
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
input1024 = B.replicate 1024 0
@ -195,20 +208,42 @@ benchAE =
benchECC =
[ bench "pointAddTwoMuls-baseline" $ nf run_b (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)
(ECC.pointMul c 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
r1 = 7
r2 = 11
p1 = ECC.pointBaseMul c r1
p2 = ECC.pointBaseMul c r2
p1 = ECC.pointBaseMul c n1
p2 = ECC.pointBaseMul c n2
n1 = 0x2ba9daf2363b2819e69b34a39cf496c2458a9b2a21505ea9e7b7cbca42dc7435
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
where
doFFDHBench (e, p) =
@ -255,6 +290,82 @@ benchECDH = map doECDHBench curves
, ("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
[ bgroup "hash" benchHash
, bgroup "block-cipher" benchBlockCipher
@ -262,9 +373,12 @@ main = defaultMain
, bgroup "pbkdf2" benchPBKDF2
, bgroup "bcrypt" benchBCrypt
, bgroup "ECC" benchECC
, bgroup "P256" benchP256
, bgroup "DH"
[ bgroup "FFDH" benchFFDH
, bgroup "ECDH" benchECDH
]
, bgroup "ECDSA" benchECDSA
, bgroup "EdDSA" benchEdDSA
, bgroup "F2m" benchF2m
]

View File

@ -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)
{
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);
}
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
#include <stdio.h>
static inline void block128_print(block128 *b)

View File

@ -34,33 +34,6 @@
#include <aes/gf.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 */
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;
}
/*
* 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 */
}
}

View File

@ -32,7 +32,11 @@
#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_hinit(table_4bit htable, const block128 *h);
void cryptonite_aes_generic_gf_mul(block128 *a, const table_4bit htable);
#endif

View File

@ -46,6 +46,7 @@
/* 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.
* 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)
{
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);
}
TARGET_AESNI
static __m128i aes_128_key_expansion_aa(__m128i key, __m128i keygened)
{
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);
}
TARGET_AESNI
void cryptonite_aesni_init(aes_key *key, uint8_t *ikey, uint8_t size)
{
__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.
* 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 */
TARGET_AESNI
static __m128i gfmulx(__m128i v)
{
uint64_t v_[2] ALIGNMENT(16);
@ -158,33 +162,34 @@ static __m128i gfmulx(__m128i 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 *) &_h, h);
cryptonite_aes_generic_gf_mul(&_t, &_h);
cryptonite_aes_generic_gf_mul(&_t, htable);
tag = _mm_load_si128((__m128i *) &_t);
return tag;
}
#ifdef WITH_PCLMUL
__m128i (*gfmul_branch_ptr)(__m128i a, __m128i b) = gfmul_generic;
#define gfmul(a,b) ((*gfmul_branch_ptr)(a,b))
__m128i (*gfmul_branch_ptr)(__m128i a, const table_4bit t) = gfmul_generic;
#define gfmul(a,t) ((*gfmul_branch_ptr)(a,t))
/* See Intel carry-less-multiplication-instruction-in-gcm-mode-paper.pdf
*
* Adapted from figure 5, with additional byte swapping so that interface
* 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);
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);
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);
}
void cryptonite_aesni_gf_mul(block128 *a, block128 *b)
void cryptonite_aesni_hinit_pclmul(table_4bit htable, const block128 *h)
{
__m128i _a, _b, _c;
_a = _mm_loadu_si128((__m128i *) a);
_b = _mm_loadu_si128((__m128i *) b);
_c = gfmul_pclmuldq(_a, _b);
_mm_storeu_si128((__m128i *) a, _c);
/* When pclmul is active we don't need to fill the table. Instead we just
* store H at index 0. It is written in reverse order, so function
* gfmul_pclmuldq will not byte-swap this value.
*/
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;
}
#else
#define gfmul(a,b) (gfmul_generic(a,b))
#define gfmul(a,t) (gfmul_generic(a,t))
#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);
return gfmul(tag, h);
return gfmul(tag, htable);
}
#define PRELOAD_ENC_KEYS128(k) \

View File

@ -40,7 +40,16 @@
#include <cryptonite_aes.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
TARGET_AESNI
static void block128_sse_print(__m128i m)
{
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_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_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,
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,
@ -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);
#ifdef WITH_PCLMUL
void cryptonite_aesni_init_pclmul();
void cryptonite_aesni_gf_mul(block128 *a, block128 *b);
void cryptonite_aesni_init_pclmul(void);
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

View File

@ -28,6 +28,7 @@
* SUCH DAMAGE.
*/
TARGET_AESNI
void SIZED(cryptonite_aesni_encrypt_block)(aes_block *out, aes_key *key, aes_block *in)
{
__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);
}
TARGET_AESNI
void SIZED(cryptonite_aesni_decrypt_block)(aes_block *out, aes_key *key, aes_block *in)
{
__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);
}
TARGET_AESNI
void SIZED(cryptonite_aesni_encrypt_ecb)(aes_block *out, aes_key *key, aes_block *in, uint32_t blocks)
{
__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)
{
__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)
{
__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)
{
__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)
{
__m128i *k = (__m128i *) key->data;
@ -151,6 +158,49 @@ void SIZED(cryptonite_aesni_encrypt_ctr)(uint8_t *output, aes_key *key, aes_bloc
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,
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);
}
TARGET_AESNI
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;
@ -191,7 +242,6 @@ void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key
gcm->length_input += length;
__m128i h = _mm_loadu_si128((__m128i *) &gcm->h);
__m128i tag = _mm_loadu_si128((__m128i *) &gcm->tag);
__m128i iv = _mm_loadu_si128((__m128i *) &gcm->civ);
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) {
/* iv += 1 */
iv = _mm_add_epi64(iv, one);
iv = _mm_add_epi32(iv, one);
/* put back iv in big endian, encrypt it,
* 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);
m = _mm_xor_si128(m, tmp);
tag = ghash_add(tag, h, m);
tag = ghash_add(tag, gcm->htable, m);
/* store it out */
_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);
/* 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 */
__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_shuffle_epi8(m, mask);
tag = ghash_add(tag, h, m);
tag = ghash_add(tag, gcm->htable, m);
/* make output */
_mm_storeu_si128((__m128i *) &block.b, m);

View File

@ -83,25 +83,25 @@ static int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen)
} while ((void)0, 0)
if (outlen <= BLAKE2B_OUTBYTES) {
TRY(blake2b_init(&blake_state, outlen));
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(blake2b_update(&blake_state, in, inlen));
TRY(blake2b_final(&blake_state, out, outlen));
TRY(_cryptonite_blake2b_init(&blake_state, outlen));
TRY(_cryptonite_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(_cryptonite_blake2b_update(&blake_state, in, inlen));
TRY(_cryptonite_blake2b_final(&blake_state, out, outlen));
} else {
uint32_t toproduce;
uint8_t out_buffer[BLAKE2B_OUTBYTES];
uint8_t in_buffer[BLAKE2B_OUTBYTES];
TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(blake2b_update(&blake_state, in, inlen));
TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
TRY(_cryptonite_blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
TRY(_cryptonite_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(_cryptonite_blake2b_update(&blake_state, in, inlen));
TRY(_cryptonite_blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
while (toproduce > 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));
memcpy(out, out_buffer, 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);
TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
TRY(_cryptonite_blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
0));
memcpy(out, out_buffer, toproduce);
}
@ -597,31 +597,31 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
return;
}
blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
_cryptonite_blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
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);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
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);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
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);
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
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) {
blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
context->pwdlen);
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
@ -631,18 +631,18 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
}
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) {
blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
context->saltlen);
}
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) {
blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
context->secretlen);
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
@ -652,14 +652,14 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
}
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) {
blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
_cryptonite_blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
context->adlen);
}
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
_cryptonite_blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
}
static
int initialize(argon2_instance_t *instance, argon2_context *context) {

View File

@ -142,51 +142,51 @@ extern "C" {
};
/* Streaming API */
int 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 blake2s_init_param( blake2s_state *S, const blake2s_param *P );
int 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_init( blake2s_state *S, size_t outlen );
int _cryptonite_blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2s_init_param( blake2s_state *S, const blake2s_param *P );
int _cryptonite_blake2s_update( blake2s_state *S, const void *in, size_t inlen );
int _cryptonite_blake2s_final( blake2s_state *S, void *out, size_t outlen );
int 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 blake2b_init_param( blake2b_state *S, const blake2b_param *P );
int 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_init( blake2b_state *S, size_t outlen );
int _cryptonite_blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2b_init_param( blake2b_state *S, const blake2b_param *P );
int _cryptonite_blake2b_update( blake2b_state *S, const void *in, size_t inlen );
int _cryptonite_blake2b_final( blake2b_state *S, void *out, size_t outlen );
int 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 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_init( blake2sp_state *S, size_t outlen );
int _cryptonite_blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
int _cryptonite_blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
int 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 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_init( blake2bp_state *S, size_t outlen );
int _cryptonite_blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
int _cryptonite_blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
/* Variable output length API */
int 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 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_init( blake2xs_state *S, const size_t outlen );
int _cryptonite_blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
int _cryptonite_blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
int 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 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_init( blake2xb_state *S, const size_t outlen );
int _cryptonite_blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
int _cryptonite_blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
/* Simple API */
int 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_blake2s( 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 blake2bp( 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 _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 blake2xb( 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 _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 */
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)
}

View File

@ -78,7 +78,7 @@ static void blake2b_init0( blake2b_state *S )
}
/* 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 );
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];
@ -113,11 +113,11 @@ int blake2b_init( blake2b_state *S, size_t outlen )
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
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];
@ -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->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];
memset( block, 0, BLAKE2B_BLOCKBYTES );
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 */
}
return 0;
@ -218,7 +218,7 @@ static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOC
#undef G
#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;
if( inlen > 0 )
@ -245,7 +245,7 @@ int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
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};
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. */
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];
@ -287,26 +287,26 @@ int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void
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
{
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 );
blake2b_final( S, out, outlen );
_cryptonite_blake2b_update( S, ( const uint8_t * )in, inlen );
_cryptonite_blake2b_final( S, out, outlen );
return 0;
}
int 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);
int _cryptonite_blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
return _cryptonite_blake2b(out, outlen, in, inlen, key, keylen);
}
#if defined(SUPERCOP)
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
@ -329,9 +329,9 @@ int main( void )
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
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;
}
@ -346,25 +346,25 @@ int main( void )
size_t mlen = i;
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;
}
while (mlen >= step) {
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2b_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2b_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
if ( (err = _cryptonite_blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
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;
}
}

View File

@ -36,7 +36,7 @@
*/
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;
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->salt, 0, sizeof( P->salt ) );
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;
@ -99,7 +99,7 @@ int blake2bp_init( blake2bp_state *S, size_t outlen )
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;
@ -125,7 +125,7 @@ int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t
memcpy( block, key, keylen );
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 */
}
@ -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;
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 );
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;
inlen -= fill;
@ -168,7 +168,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
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;
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
}
@ -184,7 +184,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
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];
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;
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 )
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];
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 );
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 */
}
@ -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 )
{
blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
_cryptonite_blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
in__ += 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 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 )
@ -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 */
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)
@ -326,21 +326,21 @@ int main( void )
size_t mlen = i;
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;
}
while (mlen >= step) {
if ( (err = blake2bp_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2bp_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2bp_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2bp_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
if ( (err = _cryptonite_blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
goto fail;
}

View File

@ -73,7 +73,7 @@ static void blake2s_init0( blake2s_state *S )
}
/* 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 );
size_t i;
@ -90,7 +90,7 @@ int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
/* 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];
@ -109,10 +109,10 @@ int blake2s_init( blake2s_state *S, size_t outlen )
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
memset( P->salt, 0, sizeof( P->salt ) );
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];
@ -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->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];
memset( block, 0, BLAKE2S_BLOCKBYTES );
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 */
}
return 0;
@ -211,7 +211,7 @@ static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBY
#undef G
#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;
if( inlen > 0 )
@ -238,7 +238,7 @@ int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
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};
size_t i;
@ -262,7 +262,7 @@ int blake2s_final( blake2s_state *S, void *out, size_t outlen )
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];
@ -279,22 +279,22 @@ int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void
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
{
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 );
blake2s_final( S, out, outlen );
_cryptonite_blake2s_update( S, ( const uint8_t * )in, inlen );
_cryptonite_blake2s_final( S, out, outlen );
return 0;
}
#if defined(SUPERCOP)
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
@ -317,7 +317,7 @@ int main( void )
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
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 ) )
{
@ -334,21 +334,21 @@ int main( void )
size_t mlen = i;
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;
}
while (mlen >= step) {
if ( (err = blake2s_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2s_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2s_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2s_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
if ( (err = _cryptonite_blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}

View File

@ -35,7 +35,7 @@
*/
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;
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;
memset( P->salt, 0, sizeof( P->salt ) );
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;
@ -96,7 +96,7 @@ int blake2sp_init( blake2sp_state *S, size_t outlen )
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;
@ -122,7 +122,7 @@ int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t
memcpy( block, key, keylen );
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 */
}
@ -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;
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 );
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;
inlen -= fill;
@ -164,7 +164,7 @@ int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
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;
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];
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;
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 )
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];
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 );
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 */
}
@ -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 )
{
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
_cryptonite_blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
in__ += 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 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 )
@ -283,9 +283,9 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
FS->last_node = 1;
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 )
{
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 ) )
{
@ -326,21 +326,21 @@ int main( void )
size_t mlen = i;
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;
}
while (mlen >= step) {
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2sp_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2sp_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
if ( (err = _cryptonite_blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}

View File

@ -23,11 +23,11 @@
#include "blake2.h"
#include "blake2-impl.h"
int blake2xb_init( blake2xb_state *S, const size_t outlen ) {
return blake2xb_init_key(S, outlen, NULL, 0);
int _cryptonite_blake2xb_init( blake2xb_state *S, const size_t outlen ) {
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 ) {
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->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;
}
@ -63,17 +63,17 @@ int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key,
uint8_t block[BLAKE2B_BLOCKBYTES];
memset(block, 0, BLAKE2B_BLOCKBYTES);
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);
}
return 0;
}
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
return blake2b_update( S->S, in, inlen );
int _cryptonite_blake2xb_update( blake2xb_state *S, const void *in, size_t 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_param P[1];
@ -98,7 +98,7 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
}
/* 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;
}
@ -117,10 +117,10 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
/* Initialize state */
P->digest_length = block_size;
store32(&P->node_offset, i);
blake2b_init_param(C, P);
_cryptonite_blake2b_init_param(C, P);
/* Process key if needed */
blake2b_update(C, root, BLAKE2B_OUTBYTES);
if (blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
_cryptonite_blake2b_update(C, root, BLAKE2B_OUTBYTES);
if (_cryptonite_blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
return -1;
}
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];
@ -154,15 +154,15 @@ int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void
return -1;
/* 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;
}
/* 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 */
return blake2xb_final(S, out, outlen);
return _cryptonite_blake2xb_final(S, out, outlen);
}
#if defined(BLAKE2XB_SELFTEST)
@ -189,7 +189,7 @@ int main( void )
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
{
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;
}
@ -208,21 +208,21 @@ int main( void )
size_t mlen = BLAKE2_KAT_LENGTH;
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;
}
while (mlen >= step) {
if ( (err = blake2xb_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2xb_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2xb_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2xb_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2xb_final(&S, hash, outlen)) < 0) {
if ( (err = _cryptonite_blake2xb_final(&S, hash, outlen)) < 0) {
goto fail;
}

View File

@ -23,11 +23,11 @@
#include "blake2.h"
#include "blake2-impl.h"
int blake2xs_init( blake2xs_state *S, const size_t outlen ) {
return blake2xs_init_key(S, outlen, NULL, 0);
int _cryptonite_blake2xs_init( blake2xs_state *S, const size_t outlen ) {
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 ) {
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->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;
}
@ -62,17 +62,17 @@ int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key,
uint8_t block[BLAKE2S_BLOCKBYTES];
memset(block, 0, BLAKE2S_BLOCKBYTES);
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);
}
return 0;
}
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
return blake2s_update( S->S, in, inlen );
int _cryptonite_blake2xs_update( blake2xs_state *S, const void *in, size_t 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_param P[1];
@ -97,7 +97,7 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
}
/* 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;
}
@ -116,10 +116,10 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
/* Initialize state */
P->digest_length = block_size;
store32(&P->node_offset, i);
blake2s_init_param(C, P);
_cryptonite_blake2s_init_param(C, P);
/* Process key if needed */
blake2s_update(C, root, BLAKE2S_OUTBYTES);
if (blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
_cryptonite_blake2s_update(C, root, BLAKE2S_OUTBYTES);
if (_cryptonite_blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
return -1;
}
outlen -= block_size;
@ -131,7 +131,7 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
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];
@ -152,15 +152,15 @@ int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void
return -1;
/* 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;
}
/* 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 */
return blake2xs_final(S, out, outlen);
return _cryptonite_blake2xs_final(S, out, outlen);
}
#if defined(BLAKE2XS_SELFTEST)
@ -187,7 +187,7 @@ int main( void )
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
{
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;
}
@ -206,21 +206,21 @@ int main( void )
size_t mlen = BLAKE2_KAT_LENGTH;
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;
}
while (mlen >= step) {
if ( (err = blake2xs_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2xs_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2xs_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2xs_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2xs_final(&S, hash, outlen)) < 0) {
if ( (err = _cryptonite_blake2xs_final(&S, hash, outlen)) < 0) {
goto fail;
}

View File

@ -142,51 +142,51 @@ extern "C" {
};
/* Streaming API */
int 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 blake2s_init_param( blake2s_state *S, const blake2s_param *P );
int 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_init( blake2s_state *S, size_t outlen );
int _cryptonite_blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2s_init_param( blake2s_state *S, const blake2s_param *P );
int _cryptonite_blake2s_update( blake2s_state *S, const void *in, size_t inlen );
int _cryptonite_blake2s_final( blake2s_state *S, void *out, size_t outlen );
int 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 blake2b_init_param( blake2b_state *S, const blake2b_param *P );
int 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_init( blake2b_state *S, size_t outlen );
int _cryptonite_blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2b_init_param( blake2b_state *S, const blake2b_param *P );
int _cryptonite_blake2b_update( blake2b_state *S, const void *in, size_t inlen );
int _cryptonite_blake2b_final( blake2b_state *S, void *out, size_t outlen );
int 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 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_init( blake2sp_state *S, size_t outlen );
int _cryptonite_blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
int _cryptonite_blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
int 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 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_init( blake2bp_state *S, size_t outlen );
int _cryptonite_blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
int _cryptonite_blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
/* Variable output length API */
int 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 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_init( blake2xs_state *S, const size_t outlen );
int _cryptonite_blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
int _cryptonite_blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
int 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 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_init( blake2xb_state *S, const size_t outlen );
int _cryptonite_blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
int _cryptonite_blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
int _cryptonite_blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
/* Simple API */
int 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_blake2s( 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 blake2bp( 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 _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 blake2xb( 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 _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 */
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)
}

View File

@ -74,7 +74,7 @@ static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
}
/* 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;
/*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 */
int blake2b_init( blake2b_state *S, size_t outlen )
int _cryptonite_blake2b_init( blake2b_state *S, size_t outlen )
{
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->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];
@ -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->personal, 0, sizeof( P->personal ) );
if( blake2b_init_param( S, P ) < 0 )
if( _cryptonite_blake2b_init_param( S, P ) < 0 )
return 0;
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset( block, 0, BLAKE2B_BLOCKBYTES );
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 */
}
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;
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 )
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];
@ -281,26 +281,26 @@ int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void
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
{
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 );
blake2b_final( S, out, outlen );
_cryptonite_blake2b_update( S, ( const uint8_t * )in, inlen );
_cryptonite_blake2b_final( S, out, outlen );
return 0;
}
int 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);
int _cryptonite_blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
return _cryptonite_blake2b(out, outlen, in, inlen, key, keylen);
}
#if defined(SUPERCOP)
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
@ -340,21 +340,21 @@ int main( void )
size_t mlen = i;
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;
}
while (mlen >= step) {
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2b_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2b_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
if ( (err = _cryptonite_blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
goto fail;
}

View File

@ -36,7 +36,7 @@
*/
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;
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->salt, 0, sizeof( P->salt ) );
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;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
@ -98,7 +98,7 @@ int blake2bp_init( blake2bp_state *S, size_t outlen )
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;
@ -124,7 +124,7 @@ int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t
memcpy( block, key, keylen );
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 */
}
@ -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;
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 );
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;
inlen -= fill;
@ -167,7 +167,7 @@ int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
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;
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];
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;
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 )
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];
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 );
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 */
}
@ -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 )
{
blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
_cryptonite_blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
in__ += 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 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 )
@ -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 */
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 )
{
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 ) )
{
@ -328,21 +328,21 @@ int main( void )
size_t mlen = i;
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;
}
while (mlen >= step) {
if ( (err = blake2bp_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2bp_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2bp_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2bp_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
if ( (err = _cryptonite_blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
goto fail;
}

View File

@ -72,7 +72,7 @@ static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
}
/* 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;
/*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 */
int blake2s_init( blake2s_state *S, size_t outlen )
int _cryptonite_blake2s_init( blake2s_state *S, size_t outlen )
{
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->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];
@ -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->personal, 0, sizeof( P->personal ) );
if( blake2s_init_param( S, P ) < 0 )
if( _cryptonite_blake2s_init_param( S, P ) < 0 )
return -1;
{
uint8_t block[BLAKE2S_BLOCKBYTES];
memset( block, 0, BLAKE2S_BLOCKBYTES );
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 */
}
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 ) ) );
}
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;
if( inlen > 0 )
@ -233,7 +233,7 @@ int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
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};
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( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
if( _cryptonite_blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
}
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 );
blake2s_final( S, out, outlen );
_cryptonite_blake2s_update( S, ( const uint8_t * )in, inlen );
_cryptonite_blake2s_final( S, out, outlen );
return 0;
}
@ -330,21 +330,21 @@ int main( void )
size_t mlen = i;
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;
}
while (mlen >= step) {
if ( (err = blake2s_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2s_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2s_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2s_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
if ( (err = _cryptonite_blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}

View File

@ -35,7 +35,7 @@
*/
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;
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;
memset( P->salt, 0, sizeof( P->salt ) );
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;
@ -96,7 +96,7 @@ int blake2sp_init( blake2sp_state *S, size_t outlen )
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;
@ -122,7 +122,7 @@ int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t
memcpy( block, key, keylen );
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 */
}
@ -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;
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 );
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;
inlen -= fill;
@ -165,7 +165,7 @@ int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
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;
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];
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;
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 )
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];
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 );
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 */
}
@ -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 )
{
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
_cryptonite_blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
in__ += 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 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 )
@ -284,9 +284,9 @@ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void
FS->last_node = 1;
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)
@ -308,7 +308,7 @@ int main( void )
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
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 ) )
{
@ -325,21 +325,21 @@ int main( void )
size_t mlen = i;
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;
}
while (mlen >= step) {
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2sp_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2sp_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
if ( (err = _cryptonite_blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}

View File

@ -23,11 +23,11 @@
#include "blake2.h"
#include "blake2-impl.h"
int blake2xb_init( blake2xb_state *S, const size_t outlen ) {
return blake2xb_init_key(S, outlen, NULL, 0);
int _cryptonite_blake2xb_init( blake2xb_state *S, const size_t outlen ) {
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 ) {
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->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;
}
@ -63,17 +63,17 @@ int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key,
uint8_t block[BLAKE2B_BLOCKBYTES];
memset(block, 0, BLAKE2B_BLOCKBYTES);
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);
}
return 0;
}
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
return blake2b_update( S->S, in, inlen );
int _cryptonite_blake2xb_update( blake2xb_state *S, const void *in, size_t 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_param P[1];
@ -98,7 +98,7 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
}
/* 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;
}
@ -117,10 +117,10 @@ int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
/* Initialize state */
P->digest_length = block_size;
store32(&P->node_offset, i);
blake2b_init_param(C, P);
_cryptonite_blake2b_init_param(C, P);
/* Process key if needed */
blake2b_update(C, root, BLAKE2B_OUTBYTES);
if (blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
_cryptonite_blake2b_update(C, root, BLAKE2B_OUTBYTES);
if (_cryptonite_blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
return -1;
}
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];
@ -154,15 +154,15 @@ int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void
return -1;
/* 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;
}
/* 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 */
return blake2xb_final(S, out, outlen);
return _cryptonite_blake2xb_final(S, out, outlen);
}
#if defined(BLAKE2XB_SELFTEST)
@ -189,7 +189,7 @@ int main( void )
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
{
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;
}
@ -208,21 +208,21 @@ int main( void )
size_t mlen = BLAKE2_KAT_LENGTH;
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;
}
while (mlen >= step) {
if ( (err = blake2xb_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2xb_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2xb_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2xb_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2xb_final(&S, hash, outlen)) < 0) {
if ( (err = _cryptonite_blake2xb_final(&S, hash, outlen)) < 0) {
goto fail;
}

View File

@ -23,11 +23,11 @@
#include "blake2.h"
#include "blake2-impl.h"
int blake2xs_init( blake2xs_state *S, const size_t outlen ) {
return blake2xs_init_key(S, outlen, NULL, 0);
int _cryptonite_blake2xs_init( blake2xs_state *S, const size_t outlen ) {
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 ) {
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->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;
}
@ -62,17 +62,17 @@ int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key,
uint8_t block[BLAKE2S_BLOCKBYTES];
memset(block, 0, BLAKE2S_BLOCKBYTES);
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);
}
return 0;
}
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
return blake2s_update( S->S, in, inlen );
int _cryptonite_blake2xs_update( blake2xs_state *S, const void *in, size_t 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_param P[1];
@ -97,7 +97,7 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
}
/* 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;
}
@ -116,10 +116,10 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
/* Initialize state */
P->digest_length = block_size;
store32(&P->node_offset, i);
blake2s_init_param(C, P);
_cryptonite_blake2s_init_param(C, P);
/* Process key if needed */
blake2s_update(C, root, BLAKE2S_OUTBYTES);
if (blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
_cryptonite_blake2s_update(C, root, BLAKE2S_OUTBYTES);
if (_cryptonite_blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
return -1;
}
outlen -= block_size;
@ -131,7 +131,7 @@ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
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];
@ -152,15 +152,15 @@ int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void
return -1;
/* 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;
}
/* 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 */
return blake2xs_final(S, out, outlen);
return _cryptonite_blake2xs_final(S, out, outlen);
}
#if defined(BLAKE2XS_SELFTEST)
@ -187,7 +187,7 @@ int main( void )
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
{
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;
}
@ -206,21 +206,21 @@ int main( void )
size_t mlen = BLAKE2_KAT_LENGTH;
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;
}
while (mlen >= step) {
if ( (err = blake2xs_update(&S, p, step)) < 0 ) {
if ( (err = _cryptonite_blake2xs_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2xs_update(&S, p, mlen)) < 0) {
if ( (err = _cryptonite_blake2xs_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2xs_final(&S, hash, outlen)) < 0) {
if ( (err = _cryptonite_blake2xs_final(&S, hash, outlen)) < 0) {
goto fail;
}

View File

@ -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_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_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,
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,
@ -69,6 +70,8 @@ enum {
DECRYPT_CBC_128, DECRYPT_CBC_192, DECRYPT_CBC_256,
/* ctr */
ENCRYPT_CTR_128, ENCRYPT_CTR_192, ENCRYPT_CTR_256,
/* ctr with 32-bit wrapping */
ENCRYPT_C32_128, ENCRYPT_C32_192, ENCRYPT_C32_256,
/* xts */
ENCRYPT_XTS_128, ENCRYPT_XTS_192, ENCRYPT_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,
DECRYPT_CCM_128, DECRYPT_CCM_192, DECRYPT_CCM_256,
/* ghash */
GHASH_GF_MUL,
GHASH_HINIT, GHASH_GF_MUL,
};
void *cryptonite_aes_branch_table[] = {
@ -115,6 +118,10 @@ void *cryptonite_aes_branch_table[] = {
[ENCRYPT_CTR_128] = cryptonite_aes_generic_encrypt_ctr,
[ENCRYPT_CTR_192] = 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 */
[ENCRYPT_XTS_128] = 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_256] = cryptonite_aes_generic_ccm_decrypt,
/* GHASH */
[GHASH_HINIT] = cryptonite_aes_generic_hinit,
[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 (*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 (*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
#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]))
#define GET_CTR_ENCRYPT(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) \
((xts_f) (cryptonite_aes_branch_table[ENCRYPT_XTS_128 + 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))
#define cryptonite_aes_decrypt_block(o,k,i) \
(((block_f) (cryptonite_aes_branch_table[DECRYPT_BLOCK_128 + k->strength]))(o,k,i))
#define cryptonite_gf_mul(a,b) \
(((gf_mul_f) (cryptonite_aes_branch_table[GHASH_GF_MUL]))(a,b))
#define cryptonite_hinit(t,h) \
(((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
#define GET_INIT(strenght) cryptonite_aes_generic_init
#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_DECRYPT(strength) cryptonite_aes_generic_decrypt_cbc
#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_DECRYPT(strength) cryptonite_aes_generic_decrypt_xts
#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 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_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
#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)
static void initialize_table_ni(int aesni, int pclmul)
{
if (!aesni)
return;
cryptonite_aes_cpu_options[CPU_AESNI] = 1;
cryptonite_aes_branch_table[INIT_128] = 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 */
cryptonite_aes_branch_table[ENCRYPT_CTR_128] = cryptonite_aesni_encrypt_ctr128;
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 */
cryptonite_aes_branch_table[ENCRYPT_XTS_128] = cryptonite_aesni_encrypt_xts128;
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
if (!pclmul)
return;
cryptonite_aes_cpu_options[CPU_PCLMUL] = 1;
/* 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();
#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)
{
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 32: key->nbr = 14; key->strength = 2; break;
}
#if defined(ARCH_X86) && defined(WITH_AESNI)
cryptonite_aesni_initialize_hw(initialize_table_ni);
#endif
cryptonite_aes_cpu_init();
init_f _init = GET_INIT(key->strength);
_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);
}
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,
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)
{
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)
{
block128 h;
gcm->length_aad = 0;
gcm->length_input = 0;
block128_zero(&gcm->h);
block128_zero(&h);
block128_zero(&gcm->tag);
block128_zero(&gcm->iv);
/* 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) {
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;
for (; len >= 16; len -= 16, iv += 16) {
block128_xor(&gcm->iv, (block128 *) iv);
cryptonite_gf_mul(&gcm->iv, &gcm->h);
cryptonite_gf_mul(&gcm->iv, gcm->htable);
}
if (len > 0) {
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)
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);
@ -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)
{
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 */
@ -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,
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;
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);
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;
int i;
block128_inc_be(&gcm->civ);
block128_inc32_be(&gcm->civ);
/* create e(civ) in out */
cryptonite_aes_encrypt_block(&out, key, &gcm->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;
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);
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;
int i;
block128_inc_be(&gcm->civ);
block128_inc32_be(&gcm->civ);
block128_zero(&tmp);
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);
}
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);
}

View File

@ -45,10 +45,10 @@ typedef struct {
uint8_t data[16*14*2];
} aes_key;
/* size = 4*16+2*8= 80 */
/* size = 19*16+2*8= 320 */
typedef struct {
aes_block tag;
aes_block h;
aes_block htable[16];
aes_block iv;
aes_block civ;
uint64_t length_aad;
@ -77,6 +77,12 @@ typedef struct {
block128 li[4];
} aes_ocb;
/* size = 17*16= 272 */
typedef struct {
aes_block htable[16];
aes_block s;
} aes_polyval;
/* in bytes: either 16,24,32 */
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_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

View File

@ -44,11 +44,21 @@ static inline void store_le32_aligned(uint8_t *dst, const uint32_t 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)
{
*((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)
{
*((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);
}
static inline void xor_be64_aligned(uint8_t *dst, const uint64_t v)
{
*((uint64_t *) dst) ^= cpu_to_be64(v);
}
#ifdef UNALIGNED_ACCESS_OK
#define load_le32(a) load_le32_aligned(a)
#else
@ -70,20 +85,30 @@ static inline uint32_t load_le32(const uint8_t *p)
#ifdef UNALIGNED_ACCESS_OK
#define store_le32(a, b) store_le32_aligned(a, b)
#define xor_le32(a, b) xor_le32_aligned(a, b)
#else
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;
}
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
#ifdef UNALIGNED_ACCESS_OK
#define store_be32(a, b) store_be32_aligned(a, b)
#define xor_be32(a, b) xor_be32_aligned(a, b)
#else
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;
}
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
#ifdef UNALIGNED_ACCESS_OK
@ -98,12 +123,18 @@ static inline void store_le64(uint8_t *dst, const uint64_t v)
#ifdef UNALIGNED_ACCESS_OK
#define store_be64(a, b) store_be64_aligned(a, b)
#define xor_be64(a, b) xor_be64_aligned(a, b)
#else
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[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

View File

@ -2,15 +2,15 @@
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)
{
blake2b_update(ctx, data, len);
_cryptonite_blake2b_update(ctx, data, len);
}
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);
}

View File

@ -2,15 +2,15 @@
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)
{
blake2bp_update(ctx, data, len);
_cryptonite_blake2bp_update(ctx, data, len);
}
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);
}

View File

@ -2,15 +2,15 @@
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)
{
blake2s_update(ctx, data, len);
_cryptonite_blake2s_update(ctx, data, len);
}
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);
}

View File

@ -2,15 +2,15 @@
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)
{
blake2sp_update(ctx, data, len);
_cryptonite_blake2sp_update(ctx, data, len);
}
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);
}

View File

@ -98,7 +98,6 @@ void cryptonite_chacha_init_core(cryptonite_chacha_state *st,
uint32_t ivlen, const uint8_t *iv)
{
const uint8_t *constants = (keylen == 32) ? sigma : tau;
int i;
ASSERT_ALIGNMENT(constants, 4);

View 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);
}
}
}

View 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

View File

@ -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+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>

View File

@ -39,5 +39,6 @@ struct md5_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_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

View File

@ -91,7 +91,7 @@ static inline int cryptonite_rdrand_step(RDRAND_T *buffer)
}
#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)
{
RDRAND_T tmp;

View File

@ -120,7 +120,6 @@ void cryptonite_salsa_init_core(cryptonite_salsa_state *st,
uint32_t ivlen, const uint8_t *iv)
{
const uint8_t *constants = (keylen == 32) ? sigma : tau;
int i;
st->d[0] = load_le32_aligned(constants + 0);
st->d[5] = load_le32_aligned(constants + 4);

View File

@ -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+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>

View File

@ -41,5 +41,6 @@ struct sha1_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_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

View File

@ -161,6 +161,14 @@ void cryptonite_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out)
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)
{
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++)
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>

View File

@ -47,9 +47,11 @@ struct sha256_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_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_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_prefix(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out);
#endif

View File

@ -121,14 +121,14 @@ void cryptonite_sha3_update(struct sha3_ctx *ctx, const uint8_t *data, uint32_t
to_fill = ctx->bufsz - ctx->bufindex;
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;
}
/* process partial buffer if there's enough data to make a block */
if (ctx->bufindex && len >= 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;
data += to_fill;
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 */
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;
}
@ -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;
/* 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;
}
@ -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_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));
}

View File

@ -29,9 +29,12 @@
struct sha3_ctx
{
uint32_t bufindex;
uint32_t bufsz;
uint32_t bufsz; /* size of buf, i.e. in bytes */
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)
@ -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_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

View File

@ -180,6 +180,14 @@ void cryptonite_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out)
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)
{
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]);
}
#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>
void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen)

View File

@ -46,10 +46,12 @@ struct sha512_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_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_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_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 */
void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen);

View File

@ -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)
{
uint32_t outsize;
uint64_t *p = (uint64_t *) out;
uint64_t x[4];
int i, j, n;

View File

@ -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)
{
uint32_t outsize;
uint64_t *p = (uint64_t *) out;
uint64_t x[8];
int i, j, n;

View File

@ -777,7 +777,6 @@ static void processBuffer(whirlpool_ctx * const ctx)
uint64_t K[8]; /* the round key */
uint64_t block[8]; /* mu(buffer) */
uint64_t state[8]; /* the cipher state */
uint64_t L[8];
uint8_t *buffer = ctx->buffer;
/*

View File

@ -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
*/
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) */
block hSalsa;
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 (x0, x1, . . . , x15):
(x0, x5, x10, x15) 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[13] = hSalsa.d[ 8] - ctx->st.d[ 8];
ctx->st.d[14] = hSalsa.d[ 9] - ctx->st.d[ 9];
ctx->st.d[ 6] = load_le32(iv + 16);
ctx->st.d[ 7] = load_le32(iv + 20);
ctx->st.d[ 6] = load_le32(iv + 8);
ctx->st.d[ 7] = load_le32(iv + 12);
ctx->st.d[ 8] = 0;
ctx->st.d[ 9] = 0;
}

Some files were not shown because too many files have changed in this diff Show More