mirror of
https://github.com/JayDDee/cpuminer-opt.git
synced 2025-09-17 23:44:27 +00:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7b94436202 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,6 +11,7 @@ autom4te.cache
|
|||||||
Makefile
|
Makefile
|
||||||
Makefile.in
|
Makefile.in
|
||||||
INSTALL
|
INSTALL
|
||||||
|
configure
|
||||||
configure.lineno
|
configure.lineno
|
||||||
depcomp
|
depcomp
|
||||||
missing
|
missing
|
||||||
|
12
AUTHORS
12
AUTHORS
@@ -16,16 +16,4 @@ LucasJones
|
|||||||
|
|
||||||
tpruvot@github
|
tpruvot@github
|
||||||
|
|
||||||
elmad
|
|
||||||
|
|
||||||
djm34
|
|
||||||
|
|
||||||
palmd
|
|
||||||
|
|
||||||
ig0tik3d
|
|
||||||
|
|
||||||
Wolf0
|
|
||||||
|
|
||||||
Optiminer
|
|
||||||
|
|
||||||
Jay D Dee
|
Jay D Dee
|
||||||
|
34
Dockerfile
34
Dockerfile
@@ -5,31 +5,19 @@
|
|||||||
# ex: docker run -it --rm cpuminer-opt:latest -a cryptonight -o cryptonight.eu.nicehash.com:3355 -u 1MiningDW2GKzf4VQfmp4q2XoUvR6iy6PD.worker1 -p x -t 3
|
# ex: docker run -it --rm cpuminer-opt:latest -a cryptonight -o cryptonight.eu.nicehash.com:3355 -u 1MiningDW2GKzf4VQfmp4q2XoUvR6iy6PD.worker1 -p x -t 3
|
||||||
#
|
#
|
||||||
|
|
||||||
# Build
|
FROM ubuntu:16.04
|
||||||
FROM ubuntu:16.04 as builder
|
RUN BUILD_DEPS="build-essential \
|
||||||
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y \
|
|
||||||
build-essential \
|
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libgmp-dev \
|
libgmp-dev \
|
||||||
libcurl4-openssl-dev \
|
libcurl4-openssl-dev \
|
||||||
libjansson-dev \
|
libjansson-dev \
|
||||||
automake \
|
automake" && \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install -y ${BUILD_DEPS}
|
||||||
|
|
||||||
COPY . /app/
|
COPY . /app/
|
||||||
RUN cd /app/ && ./build.sh
|
RUN cd /app/ && ./build.sh
|
||||||
|
|
||||||
# App
|
ENTRYPOINT ["/app/cpuminer"]
|
||||||
FROM ubuntu:16.04
|
|
||||||
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y \
|
|
||||||
libcurl3 \
|
|
||||||
libjansson4 \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
COPY --from=builder /app/cpuminer .
|
|
||||||
ENTRYPOINT ["./cpuminer"]
|
|
||||||
CMD ["-h"]
|
CMD ["-h"]
|
||||||
|
242
Makefile.am
242
Makefile.am
@@ -22,6 +22,30 @@ cpuminer_SOURCES = \
|
|||||||
api.c \
|
api.c \
|
||||||
sysinfos.c \
|
sysinfos.c \
|
||||||
algo-gate-api.c\
|
algo-gate-api.c\
|
||||||
|
algo/groestl/sph_groestl.c \
|
||||||
|
algo/skein/sph_skein.c \
|
||||||
|
algo/bmw/sph_bmw.c \
|
||||||
|
algo/shavite/sph_shavite.c \
|
||||||
|
algo/shavite/shavite.c \
|
||||||
|
algo/echo/sph_echo.c \
|
||||||
|
algo/blake/sph_blake.c \
|
||||||
|
algo/blake/sph_blake2b.c \
|
||||||
|
algo/heavy/sph_hefty1.c \
|
||||||
|
algo/blake/mod_blakecoin.c \
|
||||||
|
algo/luffa/sph_luffa.c \
|
||||||
|
algo/cubehash/sph_cubehash.c \
|
||||||
|
algo/simd/sph_simd.c \
|
||||||
|
algo/hamsi/sph_hamsi.c \
|
||||||
|
algo/fugue/sph_fugue.c \
|
||||||
|
algo/gost/sph_gost.c \
|
||||||
|
algo/jh/sph_jh.c \
|
||||||
|
algo/keccak/sph_keccak.c \
|
||||||
|
algo/keccak/keccak.c\
|
||||||
|
algo/sha3/sph_sha2.c \
|
||||||
|
algo/sha3/sph_sha2big.c \
|
||||||
|
algo/shabal/sph_shabal.c \
|
||||||
|
algo/whirlpool/sph_whirlpool.c\
|
||||||
|
crypto/blake2s.c \
|
||||||
crypto/oaes_lib.c \
|
crypto/oaes_lib.c \
|
||||||
crypto/c_keccak.c \
|
crypto/c_keccak.c \
|
||||||
crypto/c_groestl.c \
|
crypto/c_groestl.c \
|
||||||
@@ -31,228 +55,98 @@ cpuminer_SOURCES = \
|
|||||||
crypto/hash.c \
|
crypto/hash.c \
|
||||||
crypto/aesb.c \
|
crypto/aesb.c \
|
||||||
crypto/magimath.cpp \
|
crypto/magimath.cpp \
|
||||||
algo/argon2/argon2a/argon2a.c \
|
algo/argon2/argon2a.c \
|
||||||
algo/argon2/argon2a/ar2/argon2.c \
|
algo/argon2/ar2/argon2.c \
|
||||||
algo/argon2/argon2a/ar2/opt.c \
|
algo/argon2/ar2/opt.c \
|
||||||
algo/argon2/argon2a/ar2/cores.c \
|
algo/argon2/ar2/cores.c \
|
||||||
algo/argon2/argon2a/ar2/ar2-scrypt-jane.c \
|
algo/argon2/ar2/ar2-scrypt-jane.c \
|
||||||
algo/argon2/argon2a/ar2/blake2b.c \
|
algo/argon2/ar2/blake2b.c \
|
||||||
algo/argon2/argon2d/argon2d-gate.c \
|
algo/axiom.c \
|
||||||
algo/argon2/argon2d/blake2/blake2b.c \
|
|
||||||
algo/argon2/argon2d/argon2d/argon2.c \
|
|
||||||
algo/argon2/argon2d/argon2d/core.c \
|
|
||||||
algo/argon2/argon2d/argon2d/opt.c \
|
|
||||||
algo/argon2/argon2d/argon2d/thread.c \
|
|
||||||
algo/argon2/argon2d/argon2d/encoding.c \
|
|
||||||
algo/blake/sph_blake.c \
|
|
||||||
algo/blake/blake-hash-4way.c \
|
|
||||||
algo/blake/blake-gate.c \
|
|
||||||
algo/blake/blake.c \
|
algo/blake/blake.c \
|
||||||
algo/blake/blake-4way.c \
|
|
||||||
algo/blake/sph_blake2b.c \
|
|
||||||
algo/blake/blake2b.c \
|
algo/blake/blake2b.c \
|
||||||
algo/blake/sph-blake2s.c \
|
|
||||||
algo/blake/blake2s-hash-4way.c \
|
|
||||||
algo/blake/blake2s.c \
|
algo/blake/blake2s.c \
|
||||||
algo/blake/blake2s-gate.c \
|
|
||||||
algo/blake/blake2s-4way.c \
|
|
||||||
algo/blake/blakecoin-gate.c \
|
|
||||||
algo/blake/mod_blakecoin.c \
|
|
||||||
algo/blake/blakecoin.c \
|
algo/blake/blakecoin.c \
|
||||||
algo/blake/blakecoin-4way.c \
|
|
||||||
algo/blake/decred-gate.c \
|
|
||||||
algo/blake/decred.c \
|
algo/blake/decred.c \
|
||||||
algo/blake/decred-4way.c \
|
|
||||||
algo/blake/pentablake-gate.c \
|
|
||||||
algo/blake/pentablake-4way.c \
|
|
||||||
algo/blake/pentablake.c \
|
algo/blake/pentablake.c \
|
||||||
algo/bmw/sph_bmw.c \
|
|
||||||
algo/bmw/bmw-hash-4way.c \
|
|
||||||
algo/bmw/bmw256.c \
|
algo/bmw/bmw256.c \
|
||||||
|
algo/cubehash/sse2/cubehash_sse2.c\
|
||||||
algo/cryptonight/cryptolight.c \
|
algo/cryptonight/cryptolight.c \
|
||||||
algo/cryptonight/cryptonight-common.c\
|
algo/cryptonight/cryptonight-common.c\
|
||||||
algo/cryptonight/cryptonight-aesni.c\
|
algo/cryptonight/cryptonight-aesni.c\
|
||||||
algo/cryptonight/cryptonight.c\
|
algo/cryptonight/cryptonight.c\
|
||||||
algo/cubehash/sph_cubehash.c \
|
algo/drop.c \
|
||||||
algo/cubehash/sse2/cubehash_sse2.c\
|
|
||||||
algo/cubehash/cube-hash-2way.c \
|
|
||||||
algo/echo/sph_echo.c \
|
|
||||||
algo/echo/aes_ni/hash.c\
|
algo/echo/aes_ni/hash.c\
|
||||||
algo/gost/sph_gost.c \
|
algo/fresh.c \
|
||||||
algo/groestl/sph_groestl.c \
|
|
||||||
algo/groestl/groestl.c \
|
algo/groestl/groestl.c \
|
||||||
algo/groestl/myrgr-gate.c \
|
|
||||||
algo/groestl/myrgr-4way.c \
|
|
||||||
algo/groestl/myr-groestl.c \
|
algo/groestl/myr-groestl.c \
|
||||||
algo/groestl/aes_ni/hash-groestl.c \
|
algo/groestl/aes_ni/hash-groestl.c \
|
||||||
algo/groestl/aes_ni/hash-groestl256.c \
|
algo/groestl/aes_ni/hash-groestl256.c \
|
||||||
algo/fugue/sph_fugue.c \
|
algo/groestl/sse2/grso.c \
|
||||||
algo/hamsi/sph_hamsi.c \
|
algo/groestl/sse2/grso-asm.c \
|
||||||
algo/hamsi/hamsi-hash-4way.c \
|
|
||||||
algo/haval/haval.c \
|
algo/haval/haval.c \
|
||||||
algo/haval/haval-hash-4way.c \
|
|
||||||
algo/heavy/sph_hefty1.c \
|
|
||||||
algo/heavy/heavy.c \
|
algo/heavy/heavy.c \
|
||||||
algo/heavy/bastion.c \
|
algo/heavy/bastion.c \
|
||||||
algo/hodl/aes.c \
|
algo/hmq1725.c \
|
||||||
|
algo/hodl/hodl.cpp \
|
||||||
algo/hodl/hodl-gate.c \
|
algo/hodl/hodl-gate.c \
|
||||||
|
algo/hodl/hodl_arith_uint256.cpp \
|
||||||
|
algo/hodl/hodl_uint256.cpp \
|
||||||
|
algo/hodl/hash.cpp \
|
||||||
|
algo/hodl/hmac_sha512.cpp \
|
||||||
|
algo/hodl/sha256.cpp \
|
||||||
|
algo/hodl/sha512.cpp \
|
||||||
|
algo/hodl/utilstrencodings.cpp \
|
||||||
algo/hodl/hodl-wolf.c \
|
algo/hodl/hodl-wolf.c \
|
||||||
|
algo/hodl/aes.c \
|
||||||
algo/hodl/sha512_avx.c \
|
algo/hodl/sha512_avx.c \
|
||||||
algo/hodl/sha512_avx2.c \
|
algo/hodl/sha512_avx2.c \
|
||||||
algo/jh/sph_jh.c \
|
algo/lbry.c \
|
||||||
algo/jh/jh-hash-4way.c \
|
|
||||||
algo/jh/jha-gate.c \
|
|
||||||
algo/jh/jha-4way.c \
|
|
||||||
algo/jh/jha.c \
|
|
||||||
algo/keccak/sph_keccak.c \
|
|
||||||
algo/keccak/keccak.c\
|
|
||||||
algo/keccak/keccak-hash-4way.c \
|
|
||||||
algo/keccak/keccak-4way.c\
|
|
||||||
algo/keccak/keccak-gate.c \
|
|
||||||
algo/keccak/sse2/keccak.c \
|
|
||||||
algo/luffa/sph_luffa.c \
|
|
||||||
algo/luffa/luffa.c \
|
algo/luffa/luffa.c \
|
||||||
algo/luffa/luffa_for_sse2.c \
|
algo/luffa/sse2/luffa_for_sse2.c \
|
||||||
algo/luffa/luffa-hash-2way.c \
|
|
||||||
algo/lyra2/lyra2.c \
|
algo/lyra2/lyra2.c \
|
||||||
algo/lyra2/sponge.c \
|
algo/lyra2/sponge.c \
|
||||||
algo/lyra2/lyra2rev2-gate.c \
|
|
||||||
algo/lyra2/lyra2rev2.c \
|
algo/lyra2/lyra2rev2.c \
|
||||||
algo/lyra2/lyra2rev2-4way.c \
|
|
||||||
algo/lyra2/lyra2re.c \
|
algo/lyra2/lyra2re.c \
|
||||||
algo/lyra2/lyra2z-gate.c \
|
algo/lyra2/zcoin.c \
|
||||||
algo/lyra2/lyra2z.c \
|
algo/lyra2/zoin.c \
|
||||||
algo/lyra2/lyra2z-4way.c \
|
algo/keccak/sse2/keccak.c \
|
||||||
algo/lyra2/lyra2z330.c \
|
|
||||||
algo/lyra2/lyra2h-gate.c \
|
|
||||||
algo/lyra2/lyra2h.c \
|
|
||||||
algo/lyra2/lyra2h-4way.c \
|
|
||||||
algo/lyra2/allium-gate.c \
|
|
||||||
algo/lyra2/allium-4way.c \
|
|
||||||
algo/lyra2/allium.c \
|
|
||||||
algo/m7m.c \
|
algo/m7m.c \
|
||||||
algo/neoscrypt/neoscrypt.c \
|
algo/neoscrypt.c \
|
||||||
algo/nist5/nist5-gate.c \
|
algo/nist5.c \
|
||||||
algo/nist5/nist5-4way.c \
|
|
||||||
algo/nist5/nist5.c \
|
|
||||||
algo/nist5/zr5.c \
|
|
||||||
algo/pluck.c \
|
algo/pluck.c \
|
||||||
algo/quark/quark-gate.c \
|
|
||||||
algo/quark/quark.c \
|
algo/quark/quark.c \
|
||||||
algo/quark/quark-4way.c \
|
|
||||||
algo/quark/anime-gate.c \
|
|
||||||
algo/quark/anime.c \
|
|
||||||
algo/quark/anime-4way.c \
|
|
||||||
algo/qubit/qubit-gate.c \
|
|
||||||
algo/qubit/qubit.c \
|
algo/qubit/qubit.c \
|
||||||
algo/qubit/qubit-2way.c \
|
|
||||||
algo/qubit/deep-gate.c \
|
|
||||||
algo/qubit/deep-2way.c \
|
|
||||||
algo/qubit/deep.c \
|
algo/qubit/deep.c \
|
||||||
algo/ripemd/sph_ripemd.c \
|
algo/ripemd/sph_ripemd.c \
|
||||||
algo/ripemd/ripemd-hash-4way.c \
|
|
||||||
algo/ripemd/lbry-gate.c \
|
|
||||||
algo/ripemd/lbry.c \
|
|
||||||
algo/ripemd/lbry-4way.c \
|
|
||||||
algo/scrypt.c \
|
algo/scrypt.c \
|
||||||
algo/scryptjane/scrypt-jane.c \
|
algo/scryptjane/scrypt-jane.c \
|
||||||
algo/sha/sph_sha2.c \
|
algo/sha2/sha2.c \
|
||||||
algo/sha/sph_sha2big.c \
|
algo/sha2/sha256t.c \
|
||||||
algo/sha/sha2-hash-4way.c \
|
algo/simd/sse2/nist.c \
|
||||||
algo/sha/sha2.c \
|
algo/simd/sse2/vector.c \
|
||||||
algo/sha/sha256t-gate.c \
|
|
||||||
algo/sha/sha256t-4way.c \
|
|
||||||
algo/sha/sha256t.c \
|
|
||||||
algo/shabal/sph_shabal.c \
|
|
||||||
algo/shabal/shabal-hash-4way.c \
|
|
||||||
algo/shavite/sph_shavite.c \
|
|
||||||
algo/shavite/sph-shavite-aesni.c \
|
|
||||||
algo/shavite/shavite.c \
|
|
||||||
algo/simd/sph_simd.c \
|
|
||||||
algo/simd/nist.c \
|
|
||||||
algo/simd/vector.c \
|
|
||||||
algo/simd/simd-hash-2way.c \
|
|
||||||
algo/skein/sph_skein.c \
|
|
||||||
algo/skein/skein-hash-4way.c \
|
|
||||||
algo/skein/skein.c \
|
algo/skein/skein.c \
|
||||||
algo/skein/skein-4way.c \
|
|
||||||
algo/skein/skein-gate.c \
|
|
||||||
algo/skein/skein2.c \
|
algo/skein/skein2.c \
|
||||||
algo/skein/skein2-4way.c \
|
algo/s3.c \
|
||||||
algo/skein/skein2-gate.c \
|
|
||||||
algo/sm3/sm3.c \
|
|
||||||
algo/sm3/sm3-hash-4way.c \
|
|
||||||
algo/tiger/sph_tiger.c \
|
algo/tiger/sph_tiger.c \
|
||||||
algo/whirlpool/sph_whirlpool.c \
|
algo/timetravel.c \
|
||||||
algo/whirlpool/whirlpool-hash-4way.c \
|
algo/veltor.c \
|
||||||
algo/whirlpool/whirlpool-gate.c \
|
|
||||||
algo/whirlpool/whirlpool-4way.c \
|
|
||||||
algo/whirlpool/whirlpool.c \
|
algo/whirlpool/whirlpool.c \
|
||||||
algo/whirlpool/whirlpoolx.c \
|
algo/whirlpool/whirlpoolx.c \
|
||||||
algo/x11/x11-gate.c \
|
|
||||||
algo/x11/x11.c \
|
algo/x11/x11.c \
|
||||||
algo/x11/x11-4way.c \
|
|
||||||
algo/x11/x11gost-gate.c \
|
|
||||||
algo/x11/x11gost.c \
|
|
||||||
algo/x11/x11gost-4way.c \
|
|
||||||
algo/x11/c11-gate.c \
|
|
||||||
algo/x11/c11.c \
|
|
||||||
algo/x11/c11-4way.c \
|
|
||||||
algo/x11/tribus-gate.c \
|
|
||||||
algo/x11/tribus.c \
|
|
||||||
algo/x11/tribus-4way.c \
|
|
||||||
algo/x11/timetravel-gate.c \
|
|
||||||
algo/x11/timetravel.c \
|
|
||||||
algo/x11/timetravel-4way.c \
|
|
||||||
algo/x11/timetravel10-gate.c \
|
|
||||||
algo/x11/timetravel10.c \
|
|
||||||
algo/x11/timetravel10-4way.c \
|
|
||||||
algo/x11/fresh.c \
|
|
||||||
algo/x11/x11evo.c \
|
algo/x11/x11evo.c \
|
||||||
algo/x11/x11evo-4way.c \
|
algo/x11/x11gost.c \
|
||||||
algo/x11/x11evo-gate.c \
|
algo/x11/c11.c \
|
||||||
algo/x12/x12-gate.c \
|
|
||||||
algo/x12/x12.c \
|
|
||||||
algo/x12/x12-4way.c \
|
|
||||||
algo/x13/x13-gate.c \
|
|
||||||
algo/x13/x13.c \
|
algo/x13/x13.c \
|
||||||
algo/x13/x13-4way.c \
|
|
||||||
algo/x13/x13sm3-gate.c \
|
|
||||||
algo/x13/x13sm3.c \
|
|
||||||
algo/x13/x13sm3-4way.c \
|
|
||||||
algo/x13/phi1612-gate.c \
|
|
||||||
algo/x13/phi1612.c \
|
|
||||||
algo/x13/phi1612-4way.c \
|
|
||||||
algo/x13/skunk-gate.c \
|
|
||||||
algo/x13/skunk-4way.c \
|
|
||||||
algo/x13/skunk.c \
|
|
||||||
algo/x13/drop.c \
|
|
||||||
algo/x14/x14-gate.c \
|
|
||||||
algo/x14/x14.c \
|
algo/x14/x14.c \
|
||||||
algo/x14/x14-4way.c \
|
|
||||||
algo/x14/veltor-gate.c \
|
|
||||||
algo/x14/veltor.c \
|
|
||||||
algo/x14/veltor-4way.c \
|
|
||||||
algo/x14/polytimos-gate.c \
|
|
||||||
algo/x14/polytimos.c \
|
|
||||||
algo/x14/polytimos-4way.c \
|
|
||||||
algo/x14/axiom.c \
|
|
||||||
algo/x15/x15-gate.c \
|
|
||||||
algo/x15/x15.c \
|
algo/x15/x15.c \
|
||||||
algo/x15/x15-4way.c \
|
|
||||||
algo/x17/x17-gate.c \
|
|
||||||
algo/x17/x17.c \
|
algo/x17/x17.c \
|
||||||
algo/x17/x17-4way.c \
|
algo/xevan.c \
|
||||||
algo/x17/xevan-gate.c \
|
|
||||||
algo/x17/xevan.c \
|
|
||||||
algo/x17/xevan-4way.c \
|
|
||||||
algo/x17/x16r-gate.c \
|
|
||||||
algo/x17/x16r.c \
|
|
||||||
algo/x17/x16r-4way.c \
|
|
||||||
algo/x17/hmq1725.c \
|
|
||||||
algo/yescrypt/yescrypt.c \
|
algo/yescrypt/yescrypt.c \
|
||||||
algo/yescrypt/sha256_Y.c \
|
algo/yescrypt/yescrypt-common.c \
|
||||||
algo/yescrypt/yescrypt-best.c
|
algo/yescrypt/sha256_Y.c\
|
||||||
|
algo/yescrypt/yescrypt-simd.c\
|
||||||
|
algo/zr5.c
|
||||||
|
|
||||||
|
|
||||||
disable_flags =
|
disable_flags =
|
||||||
|
|
||||||
|
167
README.md
167
README.md
@@ -13,6 +13,64 @@ mailto://jayddee246@gmail.com
|
|||||||
|
|
||||||
See file RELEASE_NOTES for change log and compile instructions.
|
See file RELEASE_NOTES for change log and compile instructions.
|
||||||
|
|
||||||
|
Supported Algorithms
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
argon2
|
||||||
|
axiom Shabal-256 MemoHash
|
||||||
|
bastion
|
||||||
|
blake Blake-256 (SFR)
|
||||||
|
blakecoin blake256r8
|
||||||
|
blake2s Blake-2 S
|
||||||
|
bmw BMW 256
|
||||||
|
c11 Flax
|
||||||
|
cryptolight Cryptonight-light
|
||||||
|
cryptonight cryptonote, Monero (XMR)
|
||||||
|
decred
|
||||||
|
drop Dropcoin
|
||||||
|
fresh Fresh
|
||||||
|
groestl groestl
|
||||||
|
heavy Heavy
|
||||||
|
hmq1725 Espers
|
||||||
|
hodl Hodlcoin
|
||||||
|
keccak Keccak
|
||||||
|
lbry LBC, LBRY Credits
|
||||||
|
luffa Luffa
|
||||||
|
lyra2re lyra2
|
||||||
|
lyra2rev2 lyrav2
|
||||||
|
lyra2z Zcoin (XZC)
|
||||||
|
lyra2zoin Zoin (ZOI)
|
||||||
|
m7m Magi (XMG)
|
||||||
|
myr-gr Myriad-Groestl
|
||||||
|
neoscrypt NeoScrypt(128, 2, 1)
|
||||||
|
nist5 Nist5
|
||||||
|
pluck Pluck:128 (Supcoin)
|
||||||
|
pentablake Pentablake
|
||||||
|
quark Quark
|
||||||
|
qubit Qubit
|
||||||
|
scrypt scrypt(1024, 1, 1) (default)
|
||||||
|
scrypt:N scrypt(N, 1, 1)
|
||||||
|
scryptjane:nf
|
||||||
|
sha256d SHA-256d
|
||||||
|
shavite3 Shavite3
|
||||||
|
skein Skein+Sha (Skeincoin)
|
||||||
|
skein2 Double Skein (Woodcoin)
|
||||||
|
timetravel Machinecoin (MAC)
|
||||||
|
vanilla blake256r8vnl (VCash)
|
||||||
|
veltor
|
||||||
|
whirlpool
|
||||||
|
whirlpoolx
|
||||||
|
x11 X11
|
||||||
|
x11evo Revolvercoin
|
||||||
|
x11gost sib (SibCoin)
|
||||||
|
x13 X13
|
||||||
|
x14 X14
|
||||||
|
x15 X15
|
||||||
|
x17
|
||||||
|
xevan Bitsend
|
||||||
|
yescrypt
|
||||||
|
zr5 Ziftr
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@@ -25,105 +83,17 @@ algoritms for CPUs with AVX and AVX2, Sandybridge and Haswell respectively.
|
|||||||
Older CPUs are supported by cpuminer-multi by TPruvot but at reduced
|
Older CPUs are supported by cpuminer-multi by TPruvot but at reduced
|
||||||
performance.
|
performance.
|
||||||
|
|
||||||
ARM CPUs are not supported.
|
|
||||||
|
|
||||||
2. 64 bit Linux OS. Ubuntu and Fedora based distributions, including Mint and
|
2. 64 bit Linux OS. Ubuntu and Fedora based distributions, including Mint and
|
||||||
Centos, are known to work and have all dependencies in their repositories.
|
Centos are known to work and have all dependencies in their repositories.
|
||||||
Others may work but may require more effort. Older versions such as Centos 6
|
Others may work but may require more effort.
|
||||||
don't work due to missing features.
|
|
||||||
64 bit Windows OS is supported with mingw_w64 and msys or pre-built binaries.
|
64 bit Windows OS is supported with mingw_w64 and msys or pre-built binaries.
|
||||||
|
|
||||||
MacOS, OSx and Android are not supported.
|
3. Stratum pool, cpuminer-opt only supports stratum minning. Some algos
|
||||||
|
may work wallet mining but there are no guarantees.
|
||||||
3. Stratum pool. Some algos may work wallet mining using getwork or GBT. YMMV.
|
|
||||||
|
|
||||||
Supported Algorithms
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
allium Garlicoin
|
|
||||||
anime Animecoin
|
|
||||||
argon2 Argon2 coin (AR2)
|
|
||||||
argon2d-crds Credits (CRDS)
|
|
||||||
argon2d-dyn Dynamic (DYN)
|
|
||||||
axiom Shabal-256 MemoHash
|
|
||||||
bastion
|
|
||||||
blake Blake-256 (SFR)
|
|
||||||
blakecoin blake256r8
|
|
||||||
blake2s Blake-2 S
|
|
||||||
bmw BMW 256
|
|
||||||
c11 Chaincoin
|
|
||||||
cryptolight Cryptonight-light
|
|
||||||
cryptonight cryptonote, Monero (XMR)
|
|
||||||
decred
|
|
||||||
deep Deepcoin (DCN)
|
|
||||||
dmd-gr Diamond-Groestl
|
|
||||||
drop Dropcoin
|
|
||||||
fresh Fresh
|
|
||||||
groestl Groestl coin
|
|
||||||
heavy Heavy
|
|
||||||
hmq1725 Espers
|
|
||||||
hodl Hodlcoin
|
|
||||||
jha Jackpotcoin
|
|
||||||
keccak Maxcoin
|
|
||||||
keccakc Creative coin
|
|
||||||
lbry LBC, LBRY Credits
|
|
||||||
luffa Luffa
|
|
||||||
lyra2h Hppcoin
|
|
||||||
lyra2re lyra2
|
|
||||||
lyra2rev2 lyra2v2, Vertcoin
|
|
||||||
lyra2z Zcoin (XZC)
|
|
||||||
lyra2z330 Lyra2 330 rows, Zoin (ZOI)
|
|
||||||
m7m Magi (XMG)
|
|
||||||
myr-gr Myriad-Groestl
|
|
||||||
neoscrypt NeoScrypt(128, 2, 1)
|
|
||||||
nist5 Nist5
|
|
||||||
pentablake Pentablake
|
|
||||||
phi1612 phi, LUX coin
|
|
||||||
pluck Pluck:128 (Supcoin)
|
|
||||||
polytimos Ninja
|
|
||||||
quark Quark
|
|
||||||
qubit Qubit
|
|
||||||
scrypt scrypt(1024, 1, 1) (default)
|
|
||||||
scrypt:N scrypt(N, 1, 1)
|
|
||||||
scryptjane:nf
|
|
||||||
sha256d Double SHA-256
|
|
||||||
sha256t Triple SHA-256, Onecoin (OC)
|
|
||||||
shavite3 Shavite3
|
|
||||||
skein Skein+Sha (Skeincoin)
|
|
||||||
skein2 Double Skein (Woodcoin)
|
|
||||||
skunk Signatum (SIGT)
|
|
||||||
timetravel Machinecoin (MAC)
|
|
||||||
timetravel10 Bitcore
|
|
||||||
tribus Denarius (DNR)
|
|
||||||
vanilla blake256r8vnl (VCash)
|
|
||||||
veltor (VLT)
|
|
||||||
whirlpool
|
|
||||||
whirlpoolx
|
|
||||||
x11 Dash
|
|
||||||
x11evo Revolvercoin
|
|
||||||
x11gost sib (SibCoin)
|
|
||||||
x12 Galaxie Cash (GCH)
|
|
||||||
x13 X13
|
|
||||||
x13sm3 hsr (Hshare)
|
|
||||||
x14 X14
|
|
||||||
x15 X15
|
|
||||||
x16r Ravencoin
|
|
||||||
x17
|
|
||||||
xevan Bitsend
|
|
||||||
yescrypt Globalboost-Y (BSTY)
|
|
||||||
yescryptr8 BitZeny (ZNY)
|
|
||||||
yescryptr16 Yenten (YTN)
|
|
||||||
yescryptr32 WAVI
|
|
||||||
zr5 Ziftr
|
|
||||||
|
|
||||||
Errata
|
Errata
|
||||||
------
|
------
|
||||||
|
|
||||||
AMD CPUs older than Piledriver, including Athlon x2 and Phenom II x4, are not
|
|
||||||
supported by cpuminer-opt due to an incompatible implementation of SSE2 on
|
|
||||||
these CPUs. Some algos may crash the miner with an invalid instruction.
|
|
||||||
Users are recommended to use an unoptimized miner such as cpuminer-multi.
|
|
||||||
|
|
||||||
cpuminer-opt does not work mining Decred algo at Nicehash and produces
|
cpuminer-opt does not work mining Decred algo at Nicehash and produces
|
||||||
only "invalid extranonce2 size" rejects.
|
only "invalid extranonce2 size" rejects.
|
||||||
|
|
||||||
@@ -137,20 +107,13 @@ forum at:
|
|||||||
|
|
||||||
https://bitcointalk.org/index.php?topic=1326803.0
|
https://bitcointalk.org/index.php?topic=1326803.0
|
||||||
|
|
||||||
All problem reports must be accompanied by a proper definition.
|
|
||||||
This should include how the problem occurred, the command line and
|
|
||||||
output from the miner showing the startup and any errors.
|
|
||||||
|
|
||||||
Donations
|
Donations
|
||||||
---------
|
---------
|
||||||
|
|
||||||
cpuminer-opt has no fees of any kind but donations are accepted.
|
I do not do this for money but I have a donation address if users
|
||||||
|
are so inclined.
|
||||||
|
|
||||||
BTC: 12tdvfF7KmAsihBXQXynT6E6th2c2pByTT
|
bitcoin:12tdvfF7KmAsihBXQXynT6E6th2c2pByTT?label=donations
|
||||||
ETH: 0x72122edabcae9d3f57eab0729305a425f6fef6d0
|
|
||||||
LTC: LdUwoHJnux9r9EKqFWNvAi45kQompHk6e8
|
|
||||||
BCH: 1QKYkB6atn4P7RFozyziAXLEnurwnUM1cQ
|
|
||||||
BTG: GVUyECtRHeC5D58z9F3nGGfVQndwnsPnHQ
|
|
||||||
|
|
||||||
Happy mining!
|
Happy mining!
|
||||||
|
|
||||||
|
30
README.txt
30
README.txt
@@ -1,9 +1,6 @@
|
|||||||
This file is included in the Windows binary package. Compile instructions
|
This file is included in the Windows binary package. Compile instructions
|
||||||
for Linux and Windows can be found in RELEASE_NOTES.
|
for Linux and Windows can be found in RELEASE_NOTES.
|
||||||
|
|
||||||
cpuminer is a console program that is executed from a DOS command prompt.
|
|
||||||
There is no GUI and no mouse support.
|
|
||||||
|
|
||||||
Choose the exe that best matches you CPU's features or use trial and
|
Choose the exe that best matches you CPU's features or use trial and
|
||||||
error to find the fastest one that doesn't crash. Pay attention to
|
error to find the fastest one that doesn't crash. Pay attention to
|
||||||
the features listed at cpuminer startup to ensure you are mining at
|
the features listed at cpuminer startup to ensure you are mining at
|
||||||
@@ -11,26 +8,15 @@ optimum speed using all the available features.
|
|||||||
|
|
||||||
Architecture names and compile options used are only provided for Intel
|
Architecture names and compile options used are only provided for Intel
|
||||||
Core series. Pentium and Celeron often have fewer features.
|
Core series. Pentium and Celeron often have fewer features.
|
||||||
|
AMD is YMMV, see previous paragraph.
|
||||||
|
|
||||||
AMD CPUs older than Piledriver, including Athlon x2 and Phenom II x4, are not
|
Exe name Compile opts Arch name
|
||||||
supported by cpuminer-opt due to an incompatible implementation of SSE2 on
|
|
||||||
these CPUs. Some algos may crash the miner with an invalid instruction.
|
cpuminer-sse2.exe -march=core2, Core2
|
||||||
Users are recommended to use an unoptimized miner such as cpuminer-multi.
|
cpuminer-sse42.exe -march=corei7, Nehalem
|
||||||
|
cpuminer-aes-sse42.exe -maes -msse4.2 Westmere
|
||||||
|
cpuminer-aes-avx.exe -march=corei7-avx, Sandybridge, Ivybridge
|
||||||
|
cpuminer-aes-avx2.exe -march=core-avx2, Haswell, Broadwell, Skylake, Kabylake
|
||||||
|
|
||||||
Exe name Compile flags Arch name
|
|
||||||
|
|
||||||
cpuminer-sse2.exe "-msse2" Core2, Nehalem
|
|
||||||
cpuminer-aes-sse42.exe "-maes -msse4.2" Westmere
|
|
||||||
cpuminer-aes-avx.exe "-march=corei7-avx" Sandybridge, Ivybridge
|
|
||||||
cpuminer-avx2.exe "-march=core-avx2" Haswell...
|
|
||||||
cpuminer-avx2-sha.exe "-march=core-avx2 -msha" Ryzen
|
|
||||||
|
|
||||||
If you like this software feel free to donate:
|
|
||||||
|
|
||||||
BTC: 12tdvfF7KmAsihBXQXynT6E6th2c2pByTT
|
|
||||||
ETH: 0x72122edabcae9d3f57eab0729305a425f6fef6d0
|
|
||||||
LTC: LdUwoHJnux9r9EKqFWNvAi45kQompHk6e8
|
|
||||||
BCH: 1QKYkB6atn4P7RFozyziAXLEnurwnUM1cQ
|
|
||||||
BTG: GVUyECtRHeC5D58z9F3nGGfVQndwnsPnHQ
|
|
||||||
|
|
||||||
|
|
||||||
|
507
RELEASE_NOTES
507
RELEASE_NOTES
@@ -1,418 +1,8 @@
|
|||||||
puminer-opt now supports HW SHA acceleration available on AMD Ryzen CPUs.
|
Compile instruction for Linux and Windows are at the bottom of this file.
|
||||||
This feature requires recent SW including GCC version 5 or higher and
|
|
||||||
openssl version 1.1 or higher. It may also require using "-march=znver1"
|
|
||||||
compile flag.
|
|
||||||
|
|
||||||
HW SHA support is only available when compiled from source, Windows binaries
|
|
||||||
are not yet available.
|
|
||||||
|
|
||||||
cpuminer-opt is a console program, if you're using a mouse you're doing it
|
|
||||||
wrong.
|
|
||||||
|
|
||||||
Security warning
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Miner programs are often flagged as malware by antivirus programs. This is
|
|
||||||
a false positive, they are flagged simply because they are miners. The source
|
|
||||||
code is open for anyone to inspect. If you don't trust the software, don't use
|
|
||||||
it.
|
|
||||||
|
|
||||||
The cryptographic code has been taken from trusted sources but has been
|
|
||||||
modified for speed at the expense of accepted security practices. This
|
|
||||||
code should not be imported into applications where secure cryptography is
|
|
||||||
required.
|
|
||||||
|
|
||||||
Compile Instructions
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Requirements:
|
|
||||||
|
|
||||||
Intel Core2 or newer, or AMD Steamroller or newer CPU. ARM CPUs are not
|
|
||||||
supported.
|
|
||||||
64 bit Linux or Windows operating system. Apple is not supported.
|
|
||||||
|
|
||||||
Building on linux prerequisites:
|
|
||||||
|
|
||||||
It is assumed users know how to install packages on their system and
|
|
||||||
be able to compile standard source packages. This is basic Linux and
|
|
||||||
beyond the scope of cpuminer-opt.
|
|
||||||
|
|
||||||
Make sure you have the basic development packages installed.
|
|
||||||
Here is a good start:
|
|
||||||
|
|
||||||
http://askubuntu.com/questions/457526/how-to-install-cpuminer-in-ubuntu
|
|
||||||
|
|
||||||
Install any additional dependencies needed by cpuminer-opt. The list below
|
|
||||||
are some of the ones that may not be in the default install and need to
|
|
||||||
be installed manually. There may be others, read the error messages they
|
|
||||||
will give a clue as to the missing package.
|
|
||||||
|
|
||||||
The following command should install everything you need on Debian based
|
|
||||||
distributions such as Ubuntu:
|
|
||||||
|
|
||||||
sudo apt-get install build-essential libssl-dev libcurl4-openssl-dev libjansson-dev libgmp-dev automake
|
|
||||||
|
|
||||||
|
|
||||||
build-essential (for Ubuntu, Development Tools package group on Fedora)
|
|
||||||
automake
|
|
||||||
libjansson-dev
|
|
||||||
libgmp-dev
|
|
||||||
libcurl4-openssl-dev
|
|
||||||
libssl-dev
|
|
||||||
pthreads
|
|
||||||
zlib
|
|
||||||
|
|
||||||
SHA support on AMD Ryzen CPUs requires gcc version 5 or higher and openssl 1.1
|
|
||||||
or higher. Reports of improved performiance on Ryzen when using openssl 1.0.2
|
|
||||||
have been due to AVX and AVX2 optimizations added to that version.
|
|
||||||
Additional improvements are expected on Ryzen with openssl 1.1.
|
|
||||||
"-march-znver1" or "-msha".
|
|
||||||
|
|
||||||
Additional instructions for static compilalation can be found here:
|
|
||||||
https://lxadm.com/Static_compilation_of_cpuminer
|
|
||||||
Static builds should only considered in a homogeneous HW and SW environment.
|
|
||||||
Local builds will always have the best performance and compatibility.
|
|
||||||
|
|
||||||
Extract cpuminer source.
|
|
||||||
|
|
||||||
tar xvzf cpuminer-opt-x.y.z.tar.gz
|
|
||||||
cd cpuminer-opt-x.y.z
|
|
||||||
|
|
||||||
Run ./build.sh to build on Linux or execute the following commands.
|
|
||||||
|
|
||||||
./autogen.sh
|
|
||||||
CFLAGS="-O3 -march=native -Wall" CXXFLAGS="$CFLAGS -std=gnu++11" ./configure --with-curl
|
|
||||||
make
|
|
||||||
|
|
||||||
Additional optional compile flags, add the following to CFLAGS to activate:
|
|
||||||
|
|
||||||
-DUSE_SPH_SHA
|
|
||||||
|
|
||||||
SPH may give slightly better performance on algos that use sha256 when using
|
|
||||||
openssl 1.0.1 or older. Openssl 1.0.2 adds AVX2 and 1.1 adds SHA and perform
|
|
||||||
better than SPH. This option is ignored when 4-way is used, even for CPUs
|
|
||||||
with SHA.
|
|
||||||
|
|
||||||
Start mining.
|
|
||||||
|
|
||||||
./cpuminer -a algo -o url -u username -p password
|
|
||||||
|
|
||||||
Windows
|
|
||||||
|
|
||||||
Precompiled Windows binaries are built on a Linux host using Mingw
|
|
||||||
with a more recent compiler than the following Windows hosted procedure.
|
|
||||||
|
|
||||||
Building on Windows prerequisites:
|
|
||||||
|
|
||||||
msys
|
|
||||||
mingw_w64
|
|
||||||
Visual C++ redistributable 2008 X64
|
|
||||||
openssl
|
|
||||||
|
|
||||||
Install msys and mingw_w64, only needed once.
|
|
||||||
|
|
||||||
Unpack msys into C:\msys or your preferred directory.
|
|
||||||
|
|
||||||
Install mingw_w64 from win-builds.
|
|
||||||
Follow instructions, check "msys or cygwin" and "x86_64" and accept default
|
|
||||||
existing msys instalation.
|
|
||||||
|
|
||||||
Open a msys shell by double clicking on msys.bat.
|
|
||||||
Note that msys shell uses linux syntax for file specifications, "C:\" is
|
|
||||||
mounted at "/c/".
|
|
||||||
|
|
||||||
Add mingw bin directory to PATH variable
|
|
||||||
PATH="/c/msys/opt/windows_64/bin/:$PATH"
|
|
||||||
|
|
||||||
Instalation complete, compile cpuminer-opt.
|
|
||||||
|
|
||||||
Unpack cpuminer-opt source files using tar from msys shell, or using 7zip
|
|
||||||
or similar Windows program.
|
|
||||||
|
|
||||||
In msys shell cd to miner directory.
|
|
||||||
cd /c/path/to/cpuminer-opt
|
|
||||||
|
|
||||||
Run build.sh to build on Windows or execute the following commands.
|
|
||||||
|
|
||||||
./autogen.sh
|
|
||||||
CFLAGS="-O3 -march=native -Wall" ./configure --with-curl
|
|
||||||
make
|
|
||||||
|
|
||||||
Start mining
|
|
||||||
|
|
||||||
cpuminer.exe -a algo -o url -u user -p password
|
|
||||||
|
|
||||||
The following tips may be useful for older AMD CPUs.
|
|
||||||
|
|
||||||
AMD CPUs older than Steamroller, including Athlon x2 and Phenom II x4, are
|
|
||||||
not supported by cpuminer-opt due to an incompatible implementation of SSE2
|
|
||||||
on these CPUs. Some algos may crash the miner with an invalid instruction.
|
|
||||||
Users are recommended to use an unoptimized miner such as cpuminer-multi.
|
|
||||||
|
|
||||||
Some users with AMD CPUs without AES_NI have reported problems compiling
|
|
||||||
with build.sh or "-march=native". Problems have included compile errors
|
|
||||||
and poor performance. These users are recommended to compile manually
|
|
||||||
specifying "-march=btver1" on the configure command line.
|
|
||||||
|
|
||||||
Support for even older x86_64 without AES_NI or SSE2 is not availble.
|
|
||||||
|
|
||||||
|
|
||||||
Change Log
|
Change Log
|
||||||
----------
|
----------
|
||||||
|
|
||||||
v3.8.5
|
|
||||||
|
|
||||||
Added argon2d-crds and argon2d-dyn algos.
|
|
||||||
sha256t 8 way AVX2 & 4 way SSE4.2 optimized.
|
|
||||||
CPUs with SSE4.2 get optimizations previously reserved for AVX.
|
|
||||||
|
|
||||||
v3.8.4.1
|
|
||||||
|
|
||||||
Fixed sha256t low difficulty rejects.
|
|
||||||
Fixed compile error on CPUs with AVX512.
|
|
||||||
|
|
||||||
v3.8.4
|
|
||||||
|
|
||||||
Added yescryptr32 algo for WAVI coin.
|
|
||||||
Added URL to API data.
|
|
||||||
Improved detection of __int128 support (linux only)
|
|
||||||
Compile support for CPUs without SSSE3 (no binary support)
|
|
||||||
|
|
||||||
v3.8.3.3
|
|
||||||
|
|
||||||
Integrated getblocktemplate with algo_gate.
|
|
||||||
Added support for hodl gbt (untested).
|
|
||||||
Reworked some recent quick fixes.
|
|
||||||
|
|
||||||
v3.8.3.2
|
|
||||||
|
|
||||||
Reverted gbt changes from v3.8.0 that broke getwork.
|
|
||||||
Reverted scaled hash rate for API, added HS term in addition to KHS.
|
|
||||||
Added blocks solved to console display and API.
|
|
||||||
|
|
||||||
v3.8.3.1
|
|
||||||
|
|
||||||
Fixed regression in v3.8.3 that broke several algos.
|
|
||||||
|
|
||||||
v3.8.3
|
|
||||||
|
|
||||||
More restoration of lost lyra2 hash.
|
|
||||||
8 way AVX2 and 4way AVX optimization for blakecoin, vanilla & blake2s.
|
|
||||||
8 way AVX2 for lbry.
|
|
||||||
Scaled hashrate for API output.
|
|
||||||
A couple of GBT fixes.
|
|
||||||
|
|
||||||
v3.8.2.1
|
|
||||||
|
|
||||||
Fixed low difficulty rejects with allium.
|
|
||||||
Fixed qubit AVX2.
|
|
||||||
Restored lyra2z lost hash.
|
|
||||||
Fixed build.sh
|
|
||||||
|
|
||||||
v3.8.2
|
|
||||||
|
|
||||||
Fixed and faster myr-gr.
|
|
||||||
Added x12 algo (Galaxie Cash), allium algo (Garlicoin).
|
|
||||||
Faster lyra2rev2, lbry, skein.
|
|
||||||
Large reduction in compiler warnings.
|
|
||||||
|
|
||||||
v3.8.1.1
|
|
||||||
|
|
||||||
Fixed Windows AVX2 crash.
|
|
||||||
|
|
||||||
v3.8.1
|
|
||||||
|
|
||||||
Fixes x16r on CPUs with only SSE2.
|
|
||||||
More Optimizations for X algos, qubit & deep.
|
|
||||||
Corrected algo optimizations for scrypt and yescrypt, no new optimizations.
|
|
||||||
|
|
||||||
v3.8.0.1
|
|
||||||
|
|
||||||
Fixed x16r AVX2 low hash rate.
|
|
||||||
|
|
||||||
v3.8.0
|
|
||||||
|
|
||||||
4way no longer a seperate feature, included in AVX2.
|
|
||||||
Added x16r algo for Ravencoin, anime algo for Animecoin.
|
|
||||||
More 4way optimizations for X13 and up.
|
|
||||||
Tweaked CPU affinity to better support more than 64 CPUs.
|
|
||||||
Fixed compile problem on some old AMD CPUs.
|
|
||||||
|
|
||||||
v3.7.10
|
|
||||||
|
|
||||||
4way optimizations for lyra2rev2, lyra2h, quark, timetravel8, timetravel10
|
|
||||||
x11evo, blakecoin.
|
|
||||||
Faster x13sm3 (hsr).
|
|
||||||
Added share difficulty to accepted message.
|
|
||||||
|
|
||||||
v3.7.9
|
|
||||||
|
|
||||||
Partial 4way optimizations for veltor, skunk, polytimos, lyra2z.
|
|
||||||
Additional 4way optimizations for X algos.
|
|
||||||
New algo yescryptr8 for BitZeny, not to be confused with original
|
|
||||||
yescrypt Globalboost-Y.
|
|
||||||
|
|
||||||
v3.7.8
|
|
||||||
|
|
||||||
Partial 4way optimization for most X algos including c11, xevan, phi, hsr
|
|
||||||
|
|
||||||
v3.7.7
|
|
||||||
|
|
||||||
Fixed regression caused by 64 CPU support.
|
|
||||||
Fixed lyra2h.
|
|
||||||
|
|
||||||
v3.7.6
|
|
||||||
|
|
||||||
Added lyra2h algo for Hppcoin.
|
|
||||||
Added support for more than 64 CPUs.
|
|
||||||
Optimized shavite512 with AES, improves x11 etc.
|
|
||||||
|
|
||||||
v3.7.5
|
|
||||||
|
|
||||||
New algo keccakc for Creative coin with 4way optimizations
|
|
||||||
|
|
||||||
Rewrote some AVX/AVX2 code for more consistent implementation and some
|
|
||||||
optimizing.
|
|
||||||
|
|
||||||
Enhanced capabilities check to support 4way, more precise reporting of
|
|
||||||
features (not all algos use SSE2), and better error messages when using
|
|
||||||
an incompatible pre-built version (Windows users).
|
|
||||||
|
|
||||||
v3.7.4
|
|
||||||
|
|
||||||
Removed unnecessary build options.
|
|
||||||
|
|
||||||
Added 4way support for tribus and nist5.
|
|
||||||
|
|
||||||
v3.7.3
|
|
||||||
|
|
||||||
Added polytimos algo.
|
|
||||||
|
|
||||||
Introducing 4-way AVX2 optimization giving up to 4x performance inprovement
|
|
||||||
on many compute bound algos. First supported algos: skein, skein2, blake &
|
|
||||||
keccak. This feature is only available when compiled from source. See above
|
|
||||||
for instcuctions how to enable 4-way during compilation.
|
|
||||||
|
|
||||||
Updated Dockerfile.
|
|
||||||
|
|
||||||
v3.7.2
|
|
||||||
|
|
||||||
Fixed yescryptr16
|
|
||||||
Changed default sha256 and sha512 to openssl. This should be used when
|
|
||||||
compiling with openssl 1.0.2 or higher (Ubuntu 16.04).
|
|
||||||
This should increase the hashrate for yescrypt, yescryptr16, m7m, xevan, skein,
|
|
||||||
myr-gr & others when openssl 1.0.2 is installed.
|
|
||||||
Users with openssl 1.0.1 (Ubuntu 14.04) may get better perforance by adding
|
|
||||||
"-DUSE_SPH_SHA" to CLAGS.
|
|
||||||
Windows binaries are compiled with -DUSE_SPH_SHA and won't get the speedup.
|
|
||||||
|
|
||||||
v3.7.1
|
|
||||||
|
|
||||||
Added yescryptr16 algo for Yenten coin
|
|
||||||
Added SHA support to yescrypt and yescryptr16
|
|
||||||
Small code cleanup
|
|
||||||
|
|
||||||
v3.7.0
|
|
||||||
|
|
||||||
Fixed x14 misalignment bug.
|
|
||||||
Fixed decred stake version bug.
|
|
||||||
Getwork fixes for algos that use big endian data encoding: m7m, zr5, neoscrypt,
|
|
||||||
decred.
|
|
||||||
|
|
||||||
v3.6.10
|
|
||||||
|
|
||||||
Fixed misalignment bug in hsr.
|
|
||||||
|
|
||||||
v3.6.9
|
|
||||||
|
|
||||||
Added phi1612 algo for LUX coin
|
|
||||||
Added x13sm3 algo, alias hsr, for Hshare coin
|
|
||||||
|
|
||||||
v3.6.8
|
|
||||||
|
|
||||||
Fixed timetravel10 on Windows.
|
|
||||||
|
|
||||||
v3.6.7
|
|
||||||
|
|
||||||
Skunk algo added.
|
|
||||||
Tribus a little faster.
|
|
||||||
Minor restructuring.
|
|
||||||
|
|
||||||
v3.6.6
|
|
||||||
|
|
||||||
added tribus algo for Denarius (DNR)
|
|
||||||
|
|
||||||
configure removed from .gitignore. This should allow git clone to compile
|
|
||||||
on Windows/mingw.
|
|
||||||
|
|
||||||
Fixed CPU temperature monitoring on some CPUs (Linux only).
|
|
||||||
|
|
||||||
Fixed a compile error on FreeBSD (unsupported YMMV).
|
|
||||||
|
|
||||||
v3.6.5
|
|
||||||
|
|
||||||
Cryptonight a little faster.
|
|
||||||
Added jha algo (Jackpotcoin) with AES optimizations.
|
|
||||||
|
|
||||||
v3.6.4
|
|
||||||
|
|
||||||
Added support for Bitcore (BTX) using the timetravel10 algo, optimized for
|
|
||||||
AES and AVX2.
|
|
||||||
"-a bitcore" works as an alias and is less typing that "-a timetravel10".
|
|
||||||
|
|
||||||
v3.6.3
|
|
||||||
|
|
||||||
Fixed all known issues with SHA support on AMD Ryzen CPUs, still no
|
|
||||||
Windows binaries.
|
|
||||||
|
|
||||||
v3.6.2
|
|
||||||
|
|
||||||
SHA accceleration is now supported on AMD Ryzen CPUs when compiled from source,
|
|
||||||
Windows binaries not yet available.
|
|
||||||
Fixed groestl algo.
|
|
||||||
Fixed dmd-gr (Diamond) algo.
|
|
||||||
Fixed lbry compile error on Ryzen.
|
|
||||||
Added SHA support to m7m algo.
|
|
||||||
Hodl support for CPUs without AES has been removed, use legacy version.
|
|
||||||
|
|
||||||
v3.6.1
|
|
||||||
|
|
||||||
Fixed data alignment issue that broke lyra2rev2 AVX2 on Windows.
|
|
||||||
Added preliminary support for HW accelerated SHA.
|
|
||||||
Solo mining most algos should now work, cryptonight confirmed exception.
|
|
||||||
|
|
||||||
v3.6.0
|
|
||||||
|
|
||||||
Preliminary support for solo mining using getwork.
|
|
||||||
|
|
||||||
v3.5.13
|
|
||||||
|
|
||||||
Found more speed in Cubehash, algo improvement depends on chain length,
|
|
||||||
deep +8%, timetravel +1% , xevan +1%
|
|
||||||
Fixed a getwork bug, solo mining is not yet supported but testing is encouraged
|
|
||||||
|
|
||||||
v3.5.12
|
|
||||||
|
|
||||||
New algo sha256t for Onecoin (OC), 29% faster than ocminer version.
|
|
||||||
lyra2zoin algo renamed to lyra2z330, lyra2zoin and zoin still work
|
|
||||||
as aliases.
|
|
||||||
|
|
||||||
v3.5.11
|
|
||||||
|
|
||||||
Fixed hmq1725 crash on Ubuntu 16.04
|
|
||||||
Fixed compile error in hodl.cpp with gcc 6.3
|
|
||||||
Fixed x11 crash on Windows with AVX2
|
|
||||||
|
|
||||||
v3.5.10
|
|
||||||
|
|
||||||
Some AVX2 optimizations introduced for Luffa, shorter chained algos such
|
|
||||||
as Qubit and Deep should see the biggest gains, but many other algos should
|
|
||||||
also see improvement, longer chains like xevan not so much.
|
|
||||||
Rewrite of Groestl AES, now 100% vectorized, small improvement.
|
|
||||||
build.sh and winbuild.sh initialize with distclean instead of clean.
|
|
||||||
Implemented a workaround for a compile error in hodl code when compiling
|
|
||||||
with gcc 6.3.
|
|
||||||
|
|
||||||
V3.5.9
|
V3.5.9
|
||||||
|
|
||||||
Reduced stack usage for hmq1725 and small speedup.
|
Reduced stack usage for hmq1725 and small speedup.
|
||||||
@@ -578,3 +168,98 @@ AVX2 optimizations improving many algos:
|
|||||||
- x17 +2.8%
|
- x17 +2.8%
|
||||||
- qubit +8.4%
|
- qubit +8.4%
|
||||||
|
|
||||||
|
|
||||||
|
Compile Instructions
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Building on linux prerequisites:
|
||||||
|
|
||||||
|
It is assumed users know how to install packages on their system and
|
||||||
|
be able to compile standard source packages. This is basic Linux and
|
||||||
|
beyond the scope of cpuminer-opt.
|
||||||
|
|
||||||
|
Make sure you have the basic development packages installed.
|
||||||
|
Here is a good start:
|
||||||
|
|
||||||
|
http://askubuntu.com/questions/457526/how-to-install-cpuminer-in-ubuntu
|
||||||
|
|
||||||
|
Install any additional dependencies needed by cpuminer-opt. The list below
|
||||||
|
are some of the ones that may not be in the default install and need to
|
||||||
|
be installed manually. There may be others, read the error messages they
|
||||||
|
will give a clue as to the missing package.
|
||||||
|
|
||||||
|
The folliwing command should install everything you need on Debian based
|
||||||
|
packages:
|
||||||
|
|
||||||
|
sudo apt-get install build-essential libssl-dev libcurl4-openssl-dev libjansson-dev libgmp-dev automake
|
||||||
|
|
||||||
|
Building on Linux, see below for Windows.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
|
||||||
|
build-essential (for Ubuntu, Development Tools package group on Fedora)
|
||||||
|
automake
|
||||||
|
libjansson-dev
|
||||||
|
libgmp-dev
|
||||||
|
libcurl4-openssl-dev
|
||||||
|
libssl-dev
|
||||||
|
pthreads
|
||||||
|
zlib
|
||||||
|
|
||||||
|
tar xvzf [file.tar.gz]
|
||||||
|
cd [file]
|
||||||
|
|
||||||
|
Run build.sh to build on Linux or execute the following commands.
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
CFLAGS="-O3 -march=native -Wall" CXXFLAGS="$CFLAGS -std=gnu++11" ./configure --with-curl
|
||||||
|
make
|
||||||
|
|
||||||
|
Start mining.
|
||||||
|
|
||||||
|
./cpuminer -a algo ...
|
||||||
|
|
||||||
|
Building on Windows prerequisites:
|
||||||
|
|
||||||
|
msys
|
||||||
|
mingw_w64
|
||||||
|
Visual C++ redistributable 2008 X64
|
||||||
|
openssl, not sure about this
|
||||||
|
|
||||||
|
Install msys and mingw_w64, only needed once.
|
||||||
|
|
||||||
|
Unpack msys into C:\msys or your preferred directory.
|
||||||
|
|
||||||
|
Install mingw__w64 from win-builds.
|
||||||
|
Follow instructions, check "msys or cygwin" and "x86_64" and accept default
|
||||||
|
existing msys instalation.
|
||||||
|
|
||||||
|
Open a msys shell by double clicking on msys.bat.
|
||||||
|
Note that msys shell uses linux syntax for file specifications, "C:\" is
|
||||||
|
mounted at "/c/".
|
||||||
|
|
||||||
|
Add mingw bin directory to PATH variable
|
||||||
|
PATH="/c/msys/opt/windows_64/bin/:$PATH"
|
||||||
|
|
||||||
|
Instalation complete, compile cpuminer-opt
|
||||||
|
|
||||||
|
Unpack cpuminer-opt source files using tar from msys shell, or using 7zip
|
||||||
|
or similar Windows program.
|
||||||
|
|
||||||
|
In msys shell cd to miner directory.
|
||||||
|
cd /c/path/to/cpuminer-opt
|
||||||
|
|
||||||
|
Run winbuild.sh to build on Windows or execute the following commands.
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
CFLAGS="-O3 -march=native -Wall" CXXFLAGS="$CFLAGS -std=gnu++11 -fpermissive" ./configure --with-curl
|
||||||
|
make
|
||||||
|
|
||||||
|
The following tips may be useful for older AMD CPUs.
|
||||||
|
|
||||||
|
Some users with AMD CPUs without AES_NI have reported problems compiling
|
||||||
|
with build.sh or "-march=native". Problems have included compile errors
|
||||||
|
and poor performance. These users are recommended to compile manually
|
||||||
|
specifying "-march=btver1" on the configure command line.
|
||||||
|
|
||||||
|
Support for even older x86_64 without AES_NI or SSE2 is not availble.
|
||||||
|
225
algo-gate-api.c
225
algo-gate-api.c
@@ -16,7 +16,7 @@
|
|||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
//#include "miner.h"
|
#include "miner.h"
|
||||||
#include "algo-gate-api.h"
|
#include "algo-gate-api.h"
|
||||||
|
|
||||||
// Define null and standard functions.
|
// Define null and standard functions.
|
||||||
@@ -77,12 +77,6 @@ void algo_not_tested()
|
|||||||
applog(LOG_WARNING,"and bad things may happen. Use at your own risk.");
|
applog(LOG_WARNING,"and bad things may happen. Use at your own risk.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void four_way_not_tested()
|
|
||||||
{
|
|
||||||
applog( LOG_WARNING,"Algo %s has not been tested using 4way. It may not", algo_names[opt_algo] );
|
|
||||||
applog( LOG_WARNING,"work or may be slower. Please report your results.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void algo_not_implemented()
|
void algo_not_implemented()
|
||||||
{
|
{
|
||||||
applog(LOG_ERR,"Algo %s has not been Implemented.",algo_names[opt_algo]);
|
applog(LOG_ERR,"Algo %s has not been Implemented.",algo_names[opt_algo]);
|
||||||
@@ -104,12 +98,17 @@ void null_hash_suw()
|
|||||||
{
|
{
|
||||||
applog(LOG_WARNING,"SWERR: null_hash_suw unsafe null function");
|
applog(LOG_WARNING,"SWERR: null_hash_suw unsafe null function");
|
||||||
};
|
};
|
||||||
|
void null_hash_alt()
|
||||||
|
{
|
||||||
|
applog(LOG_WARNING,"SWERR: null_hash_alt unsafe null function");
|
||||||
|
};
|
||||||
|
|
||||||
void init_algo_gate( algo_gate_t* gate )
|
void init_algo_gate( algo_gate_t* gate )
|
||||||
{
|
{
|
||||||
gate->miner_thread_init = (void*)&return_true;
|
gate->miner_thread_init = (void*)&return_true;
|
||||||
gate->scanhash = (void*)&null_scanhash;
|
gate->scanhash = (void*)&null_scanhash;
|
||||||
gate->hash = (void*)&null_hash;
|
gate->hash = (void*)&null_hash;
|
||||||
|
gate->hash_alt = (void*)&null_hash_alt;
|
||||||
gate->hash_suw = (void*)&null_hash_suw;
|
gate->hash_suw = (void*)&null_hash_suw;
|
||||||
gate->get_new_work = (void*)&std_get_new_work;
|
gate->get_new_work = (void*)&std_get_new_work;
|
||||||
gate->get_nonceptr = (void*)&std_get_nonceptr;
|
gate->get_nonceptr = (void*)&std_get_nonceptr;
|
||||||
@@ -119,20 +118,18 @@ void init_algo_gate( algo_gate_t* gate )
|
|||||||
gate->gen_merkle_root = (void*)&sha256d_gen_merkle_root;
|
gate->gen_merkle_root = (void*)&sha256d_gen_merkle_root;
|
||||||
gate->stratum_gen_work = (void*)&std_stratum_gen_work;
|
gate->stratum_gen_work = (void*)&std_stratum_gen_work;
|
||||||
gate->build_stratum_request = (void*)&std_le_build_stratum_request;
|
gate->build_stratum_request = (void*)&std_le_build_stratum_request;
|
||||||
gate->malloc_txs_request = (void*)&std_malloc_txs_request;
|
|
||||||
gate->set_target = (void*)&std_set_target;
|
gate->set_target = (void*)&std_set_target;
|
||||||
gate->work_decode = (void*)&std_le_work_decode;
|
gate->submit_getwork_result = (void*)&std_submit_getwork_result;
|
||||||
gate->submit_getwork_result = (void*)&std_le_submit_getwork_result;
|
|
||||||
gate->build_block_header = (void*)&std_build_block_header;
|
|
||||||
gate->build_extraheader = (void*)&std_build_extraheader;
|
gate->build_extraheader = (void*)&std_build_extraheader;
|
||||||
gate->set_work_data_endian = (void*)&do_nothing;
|
gate->set_work_data_endian = (void*)&do_nothing;
|
||||||
gate->calc_network_diff = (void*)&std_calc_network_diff;
|
gate->calc_network_diff = (void*)&std_calc_network_diff;
|
||||||
|
// gate->prevent_dupes = (void*)&return_false;
|
||||||
gate->ready_to_mine = (void*)&std_ready_to_mine;
|
gate->ready_to_mine = (void*)&std_ready_to_mine;
|
||||||
gate->resync_threads = (void*)&do_nothing;
|
gate->resync_threads = (void*)&do_nothing;
|
||||||
gate->do_this_thread = (void*)&return_true;
|
gate->do_this_thread = (void*)&return_true;
|
||||||
gate->longpoll_rpc_call = (void*)&std_longpoll_rpc_call;
|
gate->longpoll_rpc_call = (void*)&std_longpoll_rpc_call;
|
||||||
gate->stratum_handle_response = (void*)&std_stratum_handle_response;
|
gate->stratum_handle_response = (void*)&std_stratum_handle_response;
|
||||||
gate->optimizations = EMPTY_SET;
|
gate->optimizations = SSE2_OPT;
|
||||||
gate->ntime_index = STD_NTIME_INDEX;
|
gate->ntime_index = STD_NTIME_INDEX;
|
||||||
gate->nbits_index = STD_NBITS_INDEX;
|
gate->nbits_index = STD_NBITS_INDEX;
|
||||||
gate->nonce_index = STD_NONCE_INDEX;
|
gate->nonce_index = STD_NONCE_INDEX;
|
||||||
@@ -140,10 +137,6 @@ void init_algo_gate( algo_gate_t* gate )
|
|||||||
gate->work_cmp_size = STD_WORK_CMP_SIZE;
|
gate->work_cmp_size = STD_WORK_CMP_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore warnings for not yet defined register functions
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
|
||||||
|
|
||||||
// called by each thread that uses the gate
|
// called by each thread that uses the gate
|
||||||
bool register_algo_gate( int algo, algo_gate_t *gate )
|
bool register_algo_gate( int algo, algo_gate_t *gate )
|
||||||
{
|
{
|
||||||
@@ -157,80 +150,71 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
|
|||||||
|
|
||||||
switch (algo)
|
switch (algo)
|
||||||
{
|
{
|
||||||
case ALGO_ALLIUM: register_allium_algo ( gate ); break;
|
|
||||||
case ALGO_ANIME: register_anime_algo ( gate ); break;
|
// Ignore warnings for not yet defined register fucntions
|
||||||
case ALGO_ARGON2: register_argon2_algo ( gate ); break;
|
#pragma GCC diagnostic push
|
||||||
case ALGO_ARGON2DCRDS: register_argon2d_crds_algo( gate ); break;
|
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
||||||
case ALGO_ARGON2DDYN: register_argon2d_dyn_algo ( gate ); break;
|
|
||||||
case ALGO_AXIOM: register_axiom_algo ( gate ); break;
|
case ALGO_ARGON2: register_argon2_algo ( gate ); break;
|
||||||
case ALGO_BASTION: register_bastion_algo ( gate ); break;
|
case ALGO_AXIOM: register_axiom_algo ( gate ); break;
|
||||||
case ALGO_BLAKE: register_blake_algo ( gate ); break;
|
case ALGO_BASTION: register_bastion_algo ( gate ); break;
|
||||||
case ALGO_BLAKECOIN: register_blakecoin_algo ( gate ); break;
|
case ALGO_BLAKE: register_blake_algo ( gate ); break;
|
||||||
// case ALGO_BLAKE2B: register_blake2b_algo ( gate ); break;
|
case ALGO_BLAKECOIN: register_blakecoin_algo ( gate ); break;
|
||||||
case ALGO_BLAKE2S: register_blake2s_algo ( gate ); break;
|
// case ALGO_BLAKE2B: register_blake2b_algo ( gate ); break;
|
||||||
case ALGO_C11: register_c11_algo ( gate ); break;
|
case ALGO_BLAKE2S: register_blake2s_algo ( gate ); break;
|
||||||
case ALGO_CRYPTOLIGHT: register_cryptolight_algo ( gate ); break;
|
case ALGO_C11: register_c11_algo ( gate ); break;
|
||||||
case ALGO_CRYPTONIGHT: register_cryptonight_algo ( gate ); break;
|
case ALGO_CRYPTOLIGHT: register_cryptolight_algo( gate ); break;
|
||||||
case ALGO_DECRED: register_decred_algo ( gate ); break;
|
case ALGO_CRYPTONIGHT: register_cryptonight_algo( gate ); break;
|
||||||
case ALGO_DEEP: register_deep_algo ( gate ); break;
|
case ALGO_DECRED: register_decred_algo ( gate ); break;
|
||||||
case ALGO_DMD_GR: register_dmd_gr_algo ( gate ); break;
|
case ALGO_DEEP: register_deep_algo ( gate ); break;
|
||||||
case ALGO_DROP: register_drop_algo ( gate ); break;
|
case ALGO_DROP: register_drop_algo ( gate ); break;
|
||||||
case ALGO_FRESH: register_fresh_algo ( gate ); break;
|
case ALGO_FRESH: register_fresh_algo ( gate ); break;
|
||||||
case ALGO_GROESTL: register_groestl_algo ( gate ); break;
|
case ALGO_GROESTL: register_groestl_algo ( gate ); break;
|
||||||
case ALGO_HEAVY: register_heavy_algo ( gate ); break;
|
case ALGO_HEAVY: register_heavy_algo ( gate ); break;
|
||||||
case ALGO_HMQ1725: register_hmq1725_algo ( gate ); break;
|
case ALGO_HMQ1725: register_hmq1725_algo ( gate ); break;
|
||||||
case ALGO_HODL: register_hodl_algo ( gate ); break;
|
case ALGO_HODL: register_hodl_algo ( gate ); break;
|
||||||
case ALGO_JHA: register_jha_algo ( gate ); break;
|
case ALGO_KECCAK: register_keccak_algo ( gate ); break;
|
||||||
case ALGO_KECCAK: register_keccak_algo ( gate ); break;
|
case ALGO_LBRY: register_lbry_algo ( gate ); break;
|
||||||
case ALGO_KECCAKC: register_keccakc_algo ( gate ); break;
|
case ALGO_LUFFA: register_luffa_algo ( gate ); break;
|
||||||
case ALGO_LBRY: register_lbry_algo ( gate ); break;
|
case ALGO_LYRA2RE: register_lyra2re_algo ( gate ); break;
|
||||||
case ALGO_LUFFA: register_luffa_algo ( gate ); break;
|
case ALGO_LYRA2REV2: register_lyra2rev2_algo ( gate ); break;
|
||||||
case ALGO_LYRA2H: register_lyra2h_algo ( gate ); break;
|
case ALGO_LYRA2Z: register_zcoin_algo ( gate ); break;
|
||||||
case ALGO_LYRA2RE: register_lyra2re_algo ( gate ); break;
|
case ALGO_LYRA2Z330: register_lyra2z330_algo ( gate ); break;
|
||||||
case ALGO_LYRA2REV2: register_lyra2rev2_algo ( gate ); break;
|
case ALGO_M7M: register_m7m_algo ( gate ); break;
|
||||||
case ALGO_LYRA2Z: register_lyra2z_algo ( gate ); break;
|
case ALGO_MYR_GR: register_myriad_algo ( gate ); break;
|
||||||
case ALGO_LYRA2Z330: register_lyra2z330_algo ( gate ); break;
|
case ALGO_NEOSCRYPT: register_neoscrypt_algo ( gate ); break;
|
||||||
case ALGO_M7M: register_m7m_algo ( gate ); break;
|
case ALGO_NIST5: register_nist5_algo ( gate ); break;
|
||||||
case ALGO_MYR_GR: register_myriad_algo ( gate ); break;
|
case ALGO_PENTABLAKE: register_pentablake_algo ( gate ); break;
|
||||||
case ALGO_NEOSCRYPT: register_neoscrypt_algo ( gate ); break;
|
case ALGO_PLUCK: register_pluck_algo ( gate ); break;
|
||||||
case ALGO_NIST5: register_nist5_algo ( gate ); break;
|
case ALGO_QUARK: register_quark_algo ( gate ); break;
|
||||||
case ALGO_PENTABLAKE: register_pentablake_algo ( gate ); break;
|
case ALGO_QUBIT: register_qubit_algo ( gate ); break;
|
||||||
case ALGO_PHI1612: register_phi1612_algo ( gate ); break;
|
case ALGO_SCRYPT: register_scrypt_algo ( gate ); break;
|
||||||
case ALGO_PLUCK: register_pluck_algo ( gate ); break;
|
case ALGO_SCRYPTJANE: register_scryptjane_algo ( gate ); break;
|
||||||
case ALGO_POLYTIMOS: register_polytimos_algo ( gate ); break;
|
case ALGO_SHA256D: register_sha256d_algo ( gate ); break;
|
||||||
case ALGO_QUARK: register_quark_algo ( gate ); break;
|
case ALGO_SHA256T: register_sha256t_algo ( gate ); break;
|
||||||
case ALGO_QUBIT: register_qubit_algo ( gate ); break;
|
case ALGO_SHAVITE3: register_shavite_algo ( gate ); break;
|
||||||
case ALGO_SCRYPT: register_scrypt_algo ( gate ); break;
|
case ALGO_SKEIN: register_skein_algo ( gate ); break;
|
||||||
case ALGO_SCRYPTJANE: register_scryptjane_algo ( gate ); break;
|
case ALGO_SKEIN2: register_skein2_algo ( gate ); break;
|
||||||
case ALGO_SHA256D: register_sha256d_algo ( gate ); break;
|
case ALGO_S3: register_s3_algo ( gate ); break;
|
||||||
case ALGO_SHA256T: register_sha256t_algo ( gate ); break;
|
case ALGO_TIMETRAVEL: register_timetravel_algo ( gate ); break;
|
||||||
case ALGO_SHAVITE3: register_shavite_algo ( gate ); break;
|
case ALGO_VANILLA: register_vanilla_algo ( gate ); break;
|
||||||
case ALGO_SKEIN: register_skein_algo ( gate ); break;
|
case ALGO_VELTOR: register_veltor_algo ( gate ); break;
|
||||||
case ALGO_SKEIN2: register_skein2_algo ( gate ); break;
|
case ALGO_WHIRLPOOL: register_whirlpool_algo ( gate ); break;
|
||||||
case ALGO_SKUNK: register_skunk_algo ( gate ); break;
|
case ALGO_WHIRLPOOLX: register_whirlpoolx_algo ( gate ); break;
|
||||||
case ALGO_TIMETRAVEL: register_timetravel_algo ( gate ); break;
|
case ALGO_X11: register_x11_algo ( gate ); break;
|
||||||
case ALGO_TIMETRAVEL10: register_timetravel10_algo( gate ); break;
|
case ALGO_X11EVO: register_x11evo_algo ( gate ); break;
|
||||||
case ALGO_TRIBUS: register_tribus_algo ( gate ); break;
|
case ALGO_X11GOST: register_sib_algo ( gate ); break;
|
||||||
case ALGO_VANILLA: register_vanilla_algo ( gate ); break;
|
case ALGO_X13: register_x13_algo ( gate ); break;
|
||||||
case ALGO_VELTOR: register_veltor_algo ( gate ); break;
|
case ALGO_X14: register_x14_algo ( gate ); break;
|
||||||
case ALGO_WHIRLPOOL: register_whirlpool_algo ( gate ); break;
|
case ALGO_X15: register_x15_algo ( gate ); break;
|
||||||
case ALGO_WHIRLPOOLX: register_whirlpoolx_algo ( gate ); break;
|
case ALGO_X17: register_x17_algo ( gate ); break;
|
||||||
case ALGO_X11: register_x11_algo ( gate ); break;
|
case ALGO_XEVAN: register_xevan_algo ( gate ); break;
|
||||||
case ALGO_X11EVO: register_x11evo_algo ( gate ); break;
|
case ALGO_YESCRYPT: register_yescrypt_algo ( gate ); break;
|
||||||
case ALGO_X11GOST: register_x11gost_algo ( gate ); break;
|
case ALGO_ZR5: register_zr5_algo ( gate ); break;
|
||||||
case ALGO_X12: register_x12_algo ( gate ); break;
|
|
||||||
case ALGO_X13: register_x13_algo ( gate ); break;
|
// restore warnings
|
||||||
case ALGO_X13SM3: register_x13sm3_algo ( gate ); break;
|
#pragma GCC diagnostic pop
|
||||||
case ALGO_X14: register_x14_algo ( gate ); break;
|
|
||||||
case ALGO_X15: register_x15_algo ( gate ); break;
|
|
||||||
case ALGO_X16R: register_x16r_algo ( gate ); break;
|
|
||||||
case ALGO_X17: register_x17_algo ( gate ); break;
|
|
||||||
case ALGO_XEVAN: register_xevan_algo ( gate ); break;
|
|
||||||
case ALGO_YESCRYPT: register_yescrypt_algo ( gate ); break;
|
|
||||||
case ALGO_YESCRYPTR8: register_yescryptr8_algo ( gate ); break;
|
|
||||||
case ALGO_YESCRYPTR16: register_yescryptr16_algo ( gate ); break;
|
|
||||||
case ALGO_YESCRYPTR32: register_yescryptr32_algo ( gate ); break;
|
|
||||||
case ALGO_ZR5: register_zr5_algo ( gate ); break;
|
|
||||||
default:
|
default:
|
||||||
applog(LOG_ERR,"FAIL: algo_gate registration failed, unknown algo %s.\n", algo_names[opt_algo] );
|
applog(LOG_ERR,"FAIL: algo_gate registration failed, unknown algo %s.\n", algo_names[opt_algo] );
|
||||||
return false;
|
return false;
|
||||||
@@ -245,9 +229,6 @@ bool register_algo_gate( int algo, algo_gate_t *gate )
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore warnings
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
// override std defaults with jr2 defaults
|
// override std defaults with jr2 defaults
|
||||||
bool register_json_rpc2( algo_gate_t *gate )
|
bool register_json_rpc2( algo_gate_t *gate )
|
||||||
{
|
{
|
||||||
@@ -263,7 +244,6 @@ bool register_json_rpc2( algo_gate_t *gate )
|
|||||||
gate->nonce_index = JR2_NONCE_INDEX;
|
gate->nonce_index = JR2_NONCE_INDEX;
|
||||||
jsonrpc_2 = true; // still needed
|
jsonrpc_2 = true; // still needed
|
||||||
opt_extranonce = false;
|
opt_extranonce = false;
|
||||||
// have_gbt = false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,48 +256,41 @@ void exec_hash_function( int algo, void *output, const void *pdata )
|
|||||||
gate.hash( output, pdata, 0 );
|
gate.hash( output, pdata, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// an algo can have multiple aliases but the aliases must be unique
|
||||||
|
|
||||||
#define PROPER (1)
|
#define PROPER (1)
|
||||||
#define ALIAS (0)
|
#define ALIAS (0)
|
||||||
|
|
||||||
// The only difference between the alias and the proper algo name is the
|
// The only difference between the alias and the proper algo name is the
|
||||||
// proper name is the one that is defined in ALGO_NAMES. There may be
|
// proper name s the one that is defined in ALGO_NAMES, there may be
|
||||||
// multiple aliases that map to the same proper name.
|
// multiple aliases that map to the same proper name.
|
||||||
// New aliases can be added anywhere in the array as long as NULL is last.
|
// New aliases can be added anywhere in the array as long as NULL is last.
|
||||||
// Alphabetic order of alias is recommended.
|
// Alphabetic order of alias is recommended.
|
||||||
const char* const algo_alias_map[][2] =
|
const char* const algo_alias_map[][2] =
|
||||||
{
|
{
|
||||||
// alias proper
|
// alias proper
|
||||||
{ "bitcore", "timetravel10" },
|
{ "blake256r8", "blakecoin" },
|
||||||
{ "bitzeny", "yescryptr8" },
|
{ "blake256r8vnl", "vanilla" },
|
||||||
{ "blake256r8", "blakecoin" },
|
{ "sia", "blake2b" },
|
||||||
{ "blake256r8vnl", "vanilla" },
|
{ "blake256r14", "blake" },
|
||||||
{ "blake256r14", "blake" },
|
{ "cryptonote", "cryptonight" },
|
||||||
{ "blake256r14dcr", "decred" },
|
{ "cryptonight-light", "cryptolight" },
|
||||||
{ "cryptonote", "cryptonight" },
|
{ "dmd-gr", "groestl" },
|
||||||
{ "cryptonight-light", "cryptolight" },
|
{ "droplp", "drop" },
|
||||||
{ "diamond", "dmd-gr" },
|
{ "espers", "hmq1725" },
|
||||||
{ "droplp", "drop" },
|
{ "flax", "c11" },
|
||||||
{ "espers", "hmq1725" },
|
{ "jane", "scryptjane" },
|
||||||
{ "flax", "c11" },
|
{ "lyra2", "lyra2re" },
|
||||||
{ "hsr", "x13sm3" },
|
{ "lyra2v2", "lyra2rev2" },
|
||||||
{ "jackpot", "jha" },
|
{ "lyra2zoin", "lyra2z330" },
|
||||||
{ "jane", "scryptjane" },
|
{ "myriad", "myr-gr" },
|
||||||
{ "lyra2", "lyra2re" },
|
{ "neo", "neoscrypt" },
|
||||||
{ "lyra2v2", "lyra2rev2" },
|
{ "sib", "x11gost" },
|
||||||
{ "lyra2zoin", "lyra2z330" },
|
{ "yes", "yescrypt" },
|
||||||
{ "myrgr", "myr-gr" },
|
{ "ziftr", "zr5" },
|
||||||
{ "myriad", "myr-gr" },
|
{ "zcoin", "lyra2z" },
|
||||||
{ "neo", "neoscrypt" },
|
{ "zoin", "lyra2z330" },
|
||||||
{ "phi", "phi1612" },
|
{ NULL, NULL }
|
||||||
// { "sia", "blake2b" },
|
|
||||||
{ "sib", "x11gost" },
|
|
||||||
{ "timetravel8", "timetravel" },
|
|
||||||
{ "ziftr", "zr5" },
|
|
||||||
{ "yenten", "yescryptr16" },
|
|
||||||
{ "yescryptr8k", "yescrypt" },
|
|
||||||
{ "zcoin", "lyra2z" },
|
|
||||||
{ "zoin", "lyra2z330" },
|
|
||||||
{ NULL, NULL }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// if arg is a valid alias for a known algo it is updated with the proper name.
|
// if arg is a valid alias for a known algo it is updated with the proper name.
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
@@ -84,13 +85,11 @@
|
|||||||
|
|
||||||
typedef uint32_t set_t;
|
typedef uint32_t set_t;
|
||||||
|
|
||||||
#define EMPTY_SET 0
|
#define EMPTY_SET 0
|
||||||
#define SSE2_OPT 1
|
#define SSE2_OPT 1
|
||||||
#define AES_OPT 2
|
#define AES_OPT 2
|
||||||
#define SSE42_OPT 4
|
#define AVX_OPT 4
|
||||||
#define AVX_OPT 8
|
#define AVX2_OPT 8
|
||||||
#define AVX2_OPT 0x10
|
|
||||||
#define SHA_OPT 0x20
|
|
||||||
|
|
||||||
// return set containing all elements from sets a & b
|
// return set containing all elements from sets a & b
|
||||||
inline set_t set_union ( set_t a, set_t b ) { return a | b; }
|
inline set_t set_union ( set_t a, set_t b ) { return a | b; }
|
||||||
@@ -111,6 +110,7 @@ int ( *scanhash ) ( int, struct work*, uint32_t, uint64_t* );
|
|||||||
|
|
||||||
// optional unsafe, must be overwritten if algo uses function
|
// optional unsafe, must be overwritten if algo uses function
|
||||||
void ( *hash ) ( void*, const void*, uint32_t ) ;
|
void ( *hash ) ( void*, const void*, uint32_t ) ;
|
||||||
|
void ( *hash_alt ) ( void*, const void*, uint32_t );
|
||||||
void ( *hash_suw ) ( void*, const void* );
|
void ( *hash_suw ) ( void*, const void* );
|
||||||
|
|
||||||
//optional, safe to use default in most cases
|
//optional, safe to use default in most cases
|
||||||
@@ -127,12 +127,10 @@ void ( *set_target) ( struct work*, double );
|
|||||||
bool ( *submit_getwork_result ) ( CURL*, struct work* );
|
bool ( *submit_getwork_result ) ( CURL*, struct work* );
|
||||||
void ( *gen_merkle_root ) ( char*, struct stratum_ctx* );
|
void ( *gen_merkle_root ) ( char*, struct stratum_ctx* );
|
||||||
void ( *build_extraheader ) ( struct work*, struct stratum_ctx* );
|
void ( *build_extraheader ) ( struct work*, struct stratum_ctx* );
|
||||||
void ( *build_block_header ) ( struct work*, uint32_t, uint32_t*,
|
|
||||||
uint32_t*, uint32_t, uint32_t );
|
|
||||||
void ( *build_stratum_request ) ( char*, struct work*, struct stratum_ctx* );
|
void ( *build_stratum_request ) ( char*, struct work*, struct stratum_ctx* );
|
||||||
char* ( *malloc_txs_request ) ( struct work* );
|
|
||||||
void ( *set_work_data_endian ) ( struct work* );
|
void ( *set_work_data_endian ) ( struct work* );
|
||||||
double ( *calc_network_diff ) ( struct work* );
|
double ( *calc_network_diff ) ( struct work* );
|
||||||
|
//bool ( *prevent_dupes ) ( struct work*, struct stratum_ctx*, int );
|
||||||
bool ( *ready_to_mine ) ( struct work*, struct stratum_ctx*, int );
|
bool ( *ready_to_mine ) ( struct work*, struct stratum_ctx*, int );
|
||||||
void ( *resync_threads ) ( struct work* );
|
void ( *resync_threads ) ( struct work* );
|
||||||
bool ( *do_this_thread ) ( int );
|
bool ( *do_this_thread ) ( int );
|
||||||
@@ -159,7 +157,7 @@ bool return_false();
|
|||||||
void *return_null();
|
void *return_null();
|
||||||
void algo_not_tested();
|
void algo_not_tested();
|
||||||
void algo_not_implemented();
|
void algo_not_implemented();
|
||||||
void four_way_not_tested();
|
|
||||||
|
|
||||||
// Warning: algo_gate.nonce_index should only be used in targetted code
|
// Warning: algo_gate.nonce_index should only be used in targetted code
|
||||||
// due to different behaviours by different targets. The JR2 index uses an
|
// due to different behaviours by different targets. The JR2 index uses an
|
||||||
@@ -187,6 +185,7 @@ int null_scanhash();
|
|||||||
|
|
||||||
// displays warning
|
// displays warning
|
||||||
void null_hash ();
|
void null_hash ();
|
||||||
|
void null_hash_alt();
|
||||||
void null_hash_suw();
|
void null_hash_suw();
|
||||||
|
|
||||||
// optional safe targets, default listed first unless noted.
|
// optional safe targets, default listed first unless noted.
|
||||||
@@ -215,33 +214,24 @@ int64_t get_max64_0x3fffffLL();
|
|||||||
int64_t get_max64_0x1ffff();
|
int64_t get_max64_0x1ffff();
|
||||||
int64_t get_max64_0xffffLL();
|
int64_t get_max64_0xffffLL();
|
||||||
|
|
||||||
void std_set_target( struct work *work, double job_diff );
|
void std_set_target ( struct work *work, double job_diff );
|
||||||
void alt_set_target( struct work* work, double job_diff );
|
|
||||||
void scrypt_set_target( struct work *work, double job_diff );
|
void scrypt_set_target( struct work *work, double job_diff );
|
||||||
|
|
||||||
bool std_le_work_decode( const json_t *val, struct work *work );
|
bool std_work_decode( const json_t *val, struct work *work );
|
||||||
bool std_be_work_decode( const json_t *val, struct work *work );
|
|
||||||
bool jr2_work_decode( const json_t *val, struct work *work );
|
bool jr2_work_decode( const json_t *val, struct work *work );
|
||||||
|
|
||||||
bool std_le_submit_getwork_result( CURL *curl, struct work *work );
|
bool std_submit_getwork_result( CURL *curl, struct work *work );
|
||||||
bool std_be_submit_getwork_result( CURL *curl, struct work *work );
|
|
||||||
bool jr2_submit_getwork_result( CURL *curl, struct work *work );
|
bool jr2_submit_getwork_result( CURL *curl, struct work *work );
|
||||||
|
|
||||||
void std_le_build_stratum_request( char *req, struct work *work );
|
void std_le_build_stratum_request( char *req, struct work *work );
|
||||||
void std_be_build_stratum_request( char *req, struct work *work );
|
void std_be_build_stratum_request( char *req, struct work *work );
|
||||||
void jr2_build_stratum_request ( char *req, struct work *work );
|
void jr2_build_stratum_request ( char *req, struct work *work );
|
||||||
|
|
||||||
char* std_malloc_txs_request( struct work *work );
|
// set_work_data_endian target, default is do_nothing;
|
||||||
|
void swab_work_data( struct work *work );
|
||||||
// Default is do_nothing (assumed LE)
|
|
||||||
void set_work_data_big_endian( struct work *work );
|
|
||||||
|
|
||||||
double std_calc_network_diff( struct work *work );
|
double std_calc_network_diff( struct work *work );
|
||||||
|
|
||||||
void std_build_block_header( struct work* g_work, uint32_t version,
|
|
||||||
uint32_t *prevhash, uint32_t *merkle_root,
|
|
||||||
uint32_t ntime, uint32_t nbits );
|
|
||||||
|
|
||||||
void std_build_extraheader( struct work *work, struct stratum_ctx *sctx );
|
void std_build_extraheader( struct work *work, struct stratum_ctx *sctx );
|
||||||
|
|
||||||
json_t* std_longpoll_rpc_call( CURL *curl, int *err, char *lp_url );
|
json_t* std_longpoll_rpc_call( CURL *curl, int *err, char *lp_url );
|
||||||
|
@@ -99,18 +99,18 @@ static const char *Argon2_ErrorMessage[] = {
|
|||||||
{ARGON2_MISSING_ARGS, */ "Missing arguments", /*},*/
|
{ARGON2_MISSING_ARGS, */ "Missing arguments", /*},*/
|
||||||
};
|
};
|
||||||
|
|
||||||
int argon2d(argon2_context *context) { return ar2_argon2_core(context, Argon2_d); }
|
int argon2d(argon2_context *context) { return argon2_core(context, Argon2_d); }
|
||||||
|
|
||||||
int argon2i(argon2_context *context) { return ar2_argon2_core(context, Argon2_i); }
|
int argon2i(argon2_context *context) { return argon2_core(context, Argon2_i); }
|
||||||
|
|
||||||
int ar2_verify_d(argon2_context *context, const char *hash)
|
int verify_d(argon2_context *context, const char *hash)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
/*if (0 == context->outlen || NULL == hash) {
|
/*if (0 == context->outlen || NULL == hash) {
|
||||||
return ARGON2_OUT_PTR_MISMATCH;
|
return ARGON2_OUT_PTR_MISMATCH;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
result = ar2_argon2_core(context, Argon2_d);
|
result = argon2_core(context, Argon2_d);
|
||||||
|
|
||||||
if (ARGON2_OK != result) {
|
if (ARGON2_OK != result) {
|
||||||
return result;
|
return result;
|
||||||
@@ -223,7 +223,7 @@ static size_t to_base64(char *dst, size_t dst_len, const void *src)
|
|||||||
* The output length is always exactly 32 bytes.
|
* The output length is always exactly 32 bytes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ar2_encode_string(char *dst, size_t dst_len, argon2_context *ctx)
|
int encode_string(char *dst, size_t dst_len, argon2_context *ctx)
|
||||||
{
|
{
|
||||||
#define SS(str) \
|
#define SS(str) \
|
||||||
do { \
|
do { \
|
@@ -255,7 +255,7 @@ int argon2id(argon2_context *context);
|
|||||||
* specified by the context outlen member
|
* specified by the context outlen member
|
||||||
* @return Zero if successful, a non zero error code otherwise
|
* @return Zero if successful, a non zero error code otherwise
|
||||||
*/
|
*/
|
||||||
int ar2_verify_d(argon2_context *context, const char *hash);
|
int verify_d(argon2_context *context, const char *hash);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the associated error message for given error code
|
* Get the associated error message for given error code
|
||||||
@@ -283,7 +283,7 @@ const char *error_message(int error_code);
|
|||||||
* The output length is always exactly 32 bytes.
|
* The output length is always exactly 32 bytes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ar2_encode_string(char *dst, size_t dst_len, argon2_context *ctx);
|
int encode_string(char *dst, size_t dst_len, argon2_context *ctx);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
@@ -52,22 +52,22 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Streaming API */
|
/* Streaming API */
|
||||||
int ar2_blake2b_init(blake2b_state *S, size_t outlen);
|
int blake2b_init(blake2b_state *S, size_t outlen);
|
||||||
int ar2_blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
|
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
|
||||||
size_t keylen);
|
size_t keylen);
|
||||||
int ar2_blake2b_init_param(blake2b_state *S, const blake2b_param *P);
|
int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
|
||||||
int ar2_blake2b_update(blake2b_state *S, const void *in, size_t inlen);
|
int blake2b_update(blake2b_state *S, const void *in, size_t inlen);
|
||||||
void my_blake2b_update(blake2b_state *S, const void *in, size_t inlen);
|
void my_blake2b_update(blake2b_state *S, const void *in, size_t inlen);
|
||||||
int ar2_blake2b_final(blake2b_state *S, void *out, size_t outlen);
|
int blake2b_final(blake2b_state *S, void *out, size_t outlen);
|
||||||
|
|
||||||
/* Simple API */
|
/* Simple API */
|
||||||
int ar2_blake2b(void *out, const void *in, const void *key, size_t keylen);
|
int blake2b(void *out, const void *in, const void *key, size_t keylen);
|
||||||
|
|
||||||
/* Argon2 Team - Begin Code */
|
/* Argon2 Team - Begin Code */
|
||||||
int ar2_blake2b_long(void *out, const void *in);
|
int blake2b_long(void *out, const void *in);
|
||||||
/* Argon2 Team - End Code */
|
/* Argon2 Team - End Code */
|
||||||
/* Miouyouyou */
|
/* Miouyouyou */
|
||||||
void ar2_blake2b_too(void *out, const void *in);
|
void blake2b_too(void *out, const void *in);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
@@ -107,7 +107,7 @@ static const blake2b_state miou = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int ar2_blake2b_init_param(blake2b_state *S, const blake2b_param *P)
|
int blake2b_init_param(blake2b_state *S, const blake2b_param *P)
|
||||||
{
|
{
|
||||||
const unsigned char *p = (const unsigned char *)P;
|
const unsigned char *p = (const unsigned char *)P;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@@ -133,7 +133,7 @@ void compare_buffs(uint64_t *h, size_t outlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Sequential blake2b initialization */
|
/* Sequential blake2b initialization */
|
||||||
int ar2_blake2b_init(blake2b_state *S, size_t outlen)
|
int blake2b_init(blake2b_state *S, size_t outlen)
|
||||||
{
|
{
|
||||||
memcpy(S, &miou, sizeof(*S));
|
memcpy(S, &miou, sizeof(*S));
|
||||||
S->h[0] += outlen;
|
S->h[0] += outlen;
|
||||||
@@ -147,7 +147,7 @@ void print64(const char *name, const uint64_t *array, uint16_t size)
|
|||||||
printf("};\n");
|
printf("};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int ar2_blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen)
|
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ static void blake2b_compress(blake2b_state *S, const uint8_t *block)
|
|||||||
#undef ROUND
|
#undef ROUND
|
||||||
}
|
}
|
||||||
|
|
||||||
int ar2_blake2b_update(blake2b_state *S, const void *in, size_t inlen)
|
int blake2b_update(blake2b_state *S, const void *in, size_t inlen)
|
||||||
{
|
{
|
||||||
const uint8_t *pin = (const uint8_t *)in;
|
const uint8_t *pin = (const uint8_t *)in;
|
||||||
/* Complete current block */
|
/* Complete current block */
|
||||||
@@ -235,7 +235,7 @@ void my_blake2b_update(blake2b_state *S, const void *in, size_t inlen)
|
|||||||
S->buflen += (unsigned int)inlen;
|
S->buflen += (unsigned int)inlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ar2_blake2b_final(blake2b_state *S, void *out, size_t outlen)
|
int blake2b_final(blake2b_state *S, void *out, size_t outlen)
|
||||||
{
|
{
|
||||||
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@@ -257,48 +257,48 @@ int ar2_blake2b_final(blake2b_state *S, void *out, size_t outlen)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ar2_blake2b(void *out, const void *in, const void *key, size_t keylen)
|
int blake2b(void *out, const void *in, const void *key, size_t keylen)
|
||||||
{
|
{
|
||||||
blake2b_state S;
|
blake2b_state S;
|
||||||
|
|
||||||
ar2_blake2b_init(&S, 64);
|
blake2b_init(&S, 64);
|
||||||
my_blake2b_update(&S, in, 64);
|
my_blake2b_update(&S, in, 64);
|
||||||
ar2_blake2b_final(&S, out, 64);
|
blake2b_final(&S, out, 64);
|
||||||
burn(&S, sizeof(S));
|
burn(&S, sizeof(S));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ar2_blake2b_too(void *pout, const void *in)
|
void blake2b_too(void *pout, const void *in)
|
||||||
{
|
{
|
||||||
uint8_t *out = (uint8_t *)pout;
|
uint8_t *out = (uint8_t *)pout;
|
||||||
uint8_t out_buffer[64];
|
uint8_t out_buffer[64];
|
||||||
uint8_t in_buffer[64];
|
uint8_t in_buffer[64];
|
||||||
|
|
||||||
blake2b_state blake_state;
|
blake2b_state blake_state;
|
||||||
ar2_blake2b_init(&blake_state, 64);
|
blake2b_init(&blake_state, 64);
|
||||||
blake_state.buflen = blake_state.buf[1] = 4;
|
blake_state.buflen = blake_state.buf[1] = 4;
|
||||||
my_blake2b_update(&blake_state, in, 72);
|
my_blake2b_update(&blake_state, in, 72);
|
||||||
ar2_blake2b_final(&blake_state, out_buffer, 64);
|
blake2b_final(&blake_state, out_buffer, 64);
|
||||||
memcpy(out, out_buffer, 32);
|
memcpy(out, out_buffer, 32);
|
||||||
out += 32;
|
out += 32;
|
||||||
|
|
||||||
register uint8_t i = 29;
|
register uint8_t i = 29;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
memcpy(in_buffer, out_buffer, 64);
|
memcpy(in_buffer, out_buffer, 64);
|
||||||
ar2_blake2b(out_buffer, in_buffer, NULL, 0);
|
blake2b(out_buffer, in_buffer, NULL, 0);
|
||||||
memcpy(out, out_buffer, 32);
|
memcpy(out, out_buffer, 32);
|
||||||
out += 32;
|
out += 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(in_buffer, out_buffer, 64);
|
memcpy(in_buffer, out_buffer, 64);
|
||||||
ar2_blake2b(out_buffer, in_buffer, NULL, 0);
|
blake2b(out_buffer, in_buffer, NULL, 0);
|
||||||
memcpy(out, out_buffer, 64);
|
memcpy(out, out_buffer, 64);
|
||||||
|
|
||||||
burn(&blake_state, sizeof(blake_state));
|
burn(&blake_state, sizeof(blake_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Argon2 Team - Begin Code */
|
/* Argon2 Team - Begin Code */
|
||||||
int ar2_blake2b_long(void *pout, const void *in)
|
int blake2b_long(void *pout, const void *in)
|
||||||
{
|
{
|
||||||
uint8_t *out = (uint8_t *)pout;
|
uint8_t *out = (uint8_t *)pout;
|
||||||
blake2b_state blake_state;
|
blake2b_state blake_state;
|
||||||
@@ -306,10 +306,10 @@ int ar2_blake2b_long(void *pout, const void *in)
|
|||||||
|
|
||||||
store32(outlen_bytes, 32);
|
store32(outlen_bytes, 32);
|
||||||
|
|
||||||
ar2_blake2b_init(&blake_state, 32);
|
blake2b_init(&blake_state, 32);
|
||||||
my_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes));
|
my_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes));
|
||||||
ar2_blake2b_update(&blake_state, in, 1024);
|
blake2b_update(&blake_state, in, 1024);
|
||||||
ar2_blake2b_final(&blake_state, out, 32);
|
blake2b_final(&blake_state, out, 32);
|
||||||
burn(&blake_state, sizeof(blake_state));
|
burn(&blake_state, sizeof(blake_state));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@@ -51,15 +51,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***************Instance and Position constructors**********/
|
/***************Instance and Position constructors**********/
|
||||||
void ar2_init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
|
void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
|
||||||
//inline void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
|
//inline void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
|
||||||
|
|
||||||
void ar2_copy_block(block *dst, const block *src) {
|
void copy_block(block *dst, const block *src) {
|
||||||
//inline void copy_block(block *dst, const block *src) {
|
//inline void copy_block(block *dst, const block *src) {
|
||||||
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_WORDS_IN_BLOCK);
|
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_WORDS_IN_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ar2_xor_block(block *dst, const block *src) {
|
void xor_block(block *dst, const block *src) {
|
||||||
//inline void xor_block(block *dst, const block *src) {
|
//inline void xor_block(block *dst, const block *src) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
|
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
|
||||||
@@ -67,7 +67,7 @@ void ar2_xor_block(block *dst, const block *src) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ar2_load_block(block *dst, const void *input) {
|
static void load_block(block *dst, const void *input) {
|
||||||
//static inline void load_block(block *dst, const void *input) {
|
//static inline void load_block(block *dst, const void *input) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
|
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
|
||||||
@@ -75,7 +75,7 @@ static void ar2_load_block(block *dst, const void *input) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ar2_store_block(void *output, const block *src) {
|
static void store_block(void *output, const block *src) {
|
||||||
//static inline void store_block(void *output, const block *src) {
|
//static inline void store_block(void *output, const block *src) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
|
for (i = 0; i < ARGON2_WORDS_IN_BLOCK; ++i) {
|
||||||
@@ -84,7 +84,7 @@ static void ar2_store_block(void *output, const block *src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***************Memory allocators*****************/
|
/***************Memory allocators*****************/
|
||||||
int ar2_allocate_memory(block **memory, uint32_t m_cost) {
|
int allocate_memory(block **memory, uint32_t m_cost) {
|
||||||
if (memory != NULL) {
|
if (memory != NULL) {
|
||||||
size_t memory_size = sizeof(block) * m_cost;
|
size_t memory_size = sizeof(block) * m_cost;
|
||||||
if (m_cost != 0 &&
|
if (m_cost != 0 &&
|
||||||
@@ -105,34 +105,34 @@ int ar2_allocate_memory(block **memory, uint32_t m_cost) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ar2_secure_wipe_memory(void *v, size_t n) { memset(v, 0, n); }
|
void secure_wipe_memory(void *v, size_t n) { memset(v, 0, n); }
|
||||||
//inline void secure_wipe_memory(void *v, size_t n) { memset(v, 0, n); }
|
//inline void secure_wipe_memory(void *v, size_t n) { memset(v, 0, n); }
|
||||||
|
|
||||||
/*********Memory functions*/
|
/*********Memory functions*/
|
||||||
|
|
||||||
void ar2_clear_memory(argon2_instance_t *instance, int clear) {
|
void clear_memory(argon2_instance_t *instance, int clear) {
|
||||||
//inline void clear_memory(argon2_instance_t *instance, int clear) {
|
//inline void clear_memory(argon2_instance_t *instance, int clear) {
|
||||||
if (instance->memory != NULL && clear) {
|
if (instance->memory != NULL && clear) {
|
||||||
ar2_secure_wipe_memory(instance->memory,
|
secure_wipe_memory(instance->memory,
|
||||||
sizeof(block) * /*instance->memory_blocks*/16);
|
sizeof(block) * /*instance->memory_blocks*/16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ar2_free_memory(block *memory) { free(memory); }
|
void free_memory(block *memory) { free(memory); }
|
||||||
//inline void free_memory(block *memory) { free(memory); }
|
//inline void free_memory(block *memory) { free(memory); }
|
||||||
|
|
||||||
void ar2_finalize(const argon2_context *context, argon2_instance_t *instance) {
|
void finalize(const argon2_context *context, argon2_instance_t *instance) {
|
||||||
if (context != NULL && instance != NULL) {
|
if (context != NULL && instance != NULL) {
|
||||||
block blockhash;
|
block blockhash;
|
||||||
ar2_copy_block(&blockhash, instance->memory + 15);
|
copy_block(&blockhash, instance->memory + 15);
|
||||||
|
|
||||||
/* Hash the result */
|
/* Hash the result */
|
||||||
{
|
{
|
||||||
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
||||||
ar2_store_block(blockhash_bytes, &blockhash);
|
store_block(blockhash_bytes, &blockhash);
|
||||||
ar2_blake2b_long(context->out, blockhash_bytes);
|
blake2b_long(context->out, blockhash_bytes);
|
||||||
ar2_secure_wipe_memory(blockhash.v, ARGON2_BLOCK_SIZE);
|
secure_wipe_memory(blockhash.v, ARGON2_BLOCK_SIZE);
|
||||||
ar2_secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
|
secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GENKAT
|
#ifdef GENKAT
|
||||||
@@ -142,11 +142,11 @@ void ar2_finalize(const argon2_context *context, argon2_instance_t *instance) {
|
|||||||
/* Clear memory */
|
/* Clear memory */
|
||||||
// clear_memory(instance, 1);
|
// clear_memory(instance, 1);
|
||||||
|
|
||||||
ar2_free_memory(instance->memory);
|
free_memory(instance->memory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ar2_index_alpha(const argon2_instance_t *instance,
|
uint32_t index_alpha(const argon2_instance_t *instance,
|
||||||
const argon2_position_t *position, uint32_t pseudo_rand,
|
const argon2_position_t *position, uint32_t pseudo_rand,
|
||||||
int same_lane) {
|
int same_lane) {
|
||||||
/*
|
/*
|
||||||
@@ -207,7 +207,7 @@ uint32_t ar2_index_alpha(const argon2_instance_t *instance,
|
|||||||
return absolute_position;
|
return absolute_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ar2_fill_memory_blocks(argon2_instance_t *instance) {
|
void fill_memory_blocks(argon2_instance_t *instance) {
|
||||||
uint32_t r, s;
|
uint32_t r, s;
|
||||||
|
|
||||||
for (r = 0; r < 2; ++r) {
|
for (r = 0; r < 2; ++r) {
|
||||||
@@ -218,7 +218,7 @@ void ar2_fill_memory_blocks(argon2_instance_t *instance) {
|
|||||||
position.lane = 0;
|
position.lane = 0;
|
||||||
position.slice = (uint8_t)s;
|
position.slice = (uint8_t)s;
|
||||||
position.index = 0;
|
position.index = 0;
|
||||||
ar2_fill_segment(instance, position);
|
fill_segment(instance, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GENKAT
|
#ifdef GENKAT
|
||||||
@@ -227,19 +227,19 @@ void ar2_fill_memory_blocks(argon2_instance_t *instance) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ar2_fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
|
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
|
||||||
/* Make the first and second block in each lane as G(H0||i||0) or
|
/* Make the first and second block in each lane as G(H0||i||0) or
|
||||||
G(H0||i||1) */
|
G(H0||i||1) */
|
||||||
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
||||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
|
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
|
||||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, 0);
|
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, 0);
|
||||||
ar2_blake2b_too(blockhash_bytes, blockhash);
|
blake2b_too(blockhash_bytes, blockhash);
|
||||||
ar2_load_block(&instance->memory[0], blockhash_bytes);
|
load_block(&instance->memory[0], blockhash_bytes);
|
||||||
|
|
||||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
|
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
|
||||||
ar2_blake2b_too(blockhash_bytes, blockhash);
|
blake2b_too(blockhash_bytes, blockhash);
|
||||||
ar2_load_block(&instance->memory[1], blockhash_bytes);
|
load_block(&instance->memory[1], blockhash_bytes);
|
||||||
ar2_secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ static const blake2b_state base_hash = {
|
|||||||
#define SALTLEN 32
|
#define SALTLEN 32
|
||||||
#define SECRETLEN 0
|
#define SECRETLEN 0
|
||||||
#define ADLEN 0
|
#define ADLEN 0
|
||||||
void ar2_initial_hash(uint8_t *blockhash, argon2_context *context,
|
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
||||||
argon2_type type) {
|
argon2_type type) {
|
||||||
|
|
||||||
uint8_t value[sizeof(uint32_t)];
|
uint8_t value[sizeof(uint32_t)];
|
||||||
@@ -280,7 +280,7 @@ void ar2_initial_hash(uint8_t *blockhash, argon2_context *context,
|
|||||||
PWDLEN);
|
PWDLEN);
|
||||||
|
|
||||||
|
|
||||||
ar2_secure_wipe_memory(context->pwd, PWDLEN);
|
secure_wipe_memory(context->pwd, PWDLEN);
|
||||||
context->pwdlen = 0;
|
context->pwdlen = 0;
|
||||||
|
|
||||||
store32(&value, SALTLEN);
|
store32(&value, SALTLEN);
|
||||||
@@ -298,19 +298,19 @@ void ar2_initial_hash(uint8_t *blockhash, argon2_context *context,
|
|||||||
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
|
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ar2_initialize(argon2_instance_t *instance, argon2_context *context) {
|
int initialize(argon2_instance_t *instance, argon2_context *context) {
|
||||||
/* 1. Memory allocation */
|
/* 1. Memory allocation */
|
||||||
|
|
||||||
|
|
||||||
ar2_allocate_memory(&(instance->memory), 16);
|
allocate_memory(&(instance->memory), 16);
|
||||||
|
|
||||||
/* 2. Initial hashing */
|
/* 2. Initial hashing */
|
||||||
/* H_0 + 8 extra bytes to produce the first blocks */
|
/* H_0 + 8 extra bytes to produce the first blocks */
|
||||||
/* Hashing all inputs */
|
/* Hashing all inputs */
|
||||||
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
|
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
|
||||||
ar2_initial_hash(blockhash, context, instance->type);
|
initial_hash(blockhash, context, instance->type);
|
||||||
/* Zeroing 8 extra bytes */
|
/* Zeroing 8 extra bytes */
|
||||||
ar2_secure_wipe_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
|
secure_wipe_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
|
||||||
ARGON2_PREHASH_SEED_LENGTH -
|
ARGON2_PREHASH_SEED_LENGTH -
|
||||||
ARGON2_PREHASH_DIGEST_LENGTH);
|
ARGON2_PREHASH_DIGEST_LENGTH);
|
||||||
|
|
||||||
@@ -320,14 +320,14 @@ int ar2_initialize(argon2_instance_t *instance, argon2_context *context) {
|
|||||||
|
|
||||||
/* 3. Creating first blocks, we always have at least two blocks in a slice
|
/* 3. Creating first blocks, we always have at least two blocks in a slice
|
||||||
*/
|
*/
|
||||||
ar2_fill_first_blocks(blockhash, instance);
|
fill_first_blocks(blockhash, instance);
|
||||||
/* Clearing the hash */
|
/* Clearing the hash */
|
||||||
ar2_secure_wipe_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
|
secure_wipe_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
|
||||||
|
|
||||||
return ARGON2_OK;
|
return ARGON2_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ar2_argon2_core(argon2_context *context, argon2_type type) {
|
int argon2_core(argon2_context *context, argon2_type type) {
|
||||||
argon2_instance_t instance;
|
argon2_instance_t instance;
|
||||||
instance.memory = NULL;
|
instance.memory = NULL;
|
||||||
instance.type = type;
|
instance.type = type;
|
||||||
@@ -336,14 +336,14 @@ int ar2_argon2_core(argon2_context *context, argon2_type type) {
|
|||||||
* blocks
|
* blocks
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int result = ar2_initialize(&instance, context);
|
int result = initialize(&instance, context);
|
||||||
if (ARGON2_OK != result) return result;
|
if (ARGON2_OK != result) return result;
|
||||||
|
|
||||||
/* 4. Filling memory */
|
/* 4. Filling memory */
|
||||||
ar2_fill_memory_blocks(&instance);
|
fill_memory_blocks(&instance);
|
||||||
|
|
||||||
/* 5. Finalization */
|
/* 5. Finalization */
|
||||||
ar2_finalize(context, &instance);
|
finalize(context, &instance);
|
||||||
|
|
||||||
return ARGON2_OK;
|
return ARGON2_OK;
|
||||||
}
|
}
|
@@ -62,13 +62,13 @@ typedef struct _block { uint64_t v[ARGON2_WORDS_IN_BLOCK]; } ALIGN(16) block;
|
|||||||
/*****************Functions that work with the block******************/
|
/*****************Functions that work with the block******************/
|
||||||
|
|
||||||
/* Initialize each byte of the block with @in */
|
/* Initialize each byte of the block with @in */
|
||||||
void ar2_init_block_value(block *b, uint8_t in);
|
void init_block_value(block *b, uint8_t in);
|
||||||
|
|
||||||
/* Copy block @src to block @dst */
|
/* Copy block @src to block @dst */
|
||||||
void ar2_copy_block(block *dst, const block *src);
|
void copy_block(block *dst, const block *src);
|
||||||
|
|
||||||
/* XOR @src onto @dst bytewise */
|
/* XOR @src onto @dst bytewise */
|
||||||
void ar2_xor_block(block *dst, const block *src);
|
void xor_block(block *dst, const block *src);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Argon2 instance: memory pointer, number of passes, amount of memory, type,
|
* Argon2 instance: memory pointer, number of passes, amount of memory, type,
|
||||||
@@ -101,24 +101,24 @@ typedef struct Argon2_position_t {
|
|||||||
* @param m_cost number of blocks to allocate in the memory
|
* @param m_cost number of blocks to allocate in the memory
|
||||||
* @return ARGON2_OK if @memory is a valid pointer and memory is allocated
|
* @return ARGON2_OK if @memory is a valid pointer and memory is allocated
|
||||||
*/
|
*/
|
||||||
int ar2_allocate_memory(block **memory, uint32_t m_cost);
|
int allocate_memory(block **memory, uint32_t m_cost);
|
||||||
|
|
||||||
/* Function that securely cleans the memory
|
/* Function that securely cleans the memory
|
||||||
* @param mem Pointer to the memory
|
* @param mem Pointer to the memory
|
||||||
* @param s Memory size in bytes
|
* @param s Memory size in bytes
|
||||||
*/
|
*/
|
||||||
void ar2_secure_wipe_memory(void *v, size_t n);
|
void secure_wipe_memory(void *v, size_t n);
|
||||||
|
|
||||||
/* Clears memory
|
/* Clears memory
|
||||||
* @param instance pointer to the current instance
|
* @param instance pointer to the current instance
|
||||||
* @param clear_memory indicates if we clear the memory with zeros.
|
* @param clear_memory indicates if we clear the memory with zeros.
|
||||||
*/
|
*/
|
||||||
void ar2_clear_memory(argon2_instance_t *instance, int clear);
|
void clear_memory(argon2_instance_t *instance, int clear);
|
||||||
|
|
||||||
/* Deallocates memory
|
/* Deallocates memory
|
||||||
* @param memory pointer to the blocks
|
* @param memory pointer to the blocks
|
||||||
*/
|
*/
|
||||||
void ar2_free_memory(block *memory);
|
void free_memory(block *memory);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Computes absolute position of reference block in the lane following a skewed
|
* Computes absolute position of reference block in the lane following a skewed
|
||||||
@@ -130,7 +130,7 @@ void ar2_free_memory(block *memory);
|
|||||||
* If so we can reference the current segment
|
* If so we can reference the current segment
|
||||||
* @pre All pointers must be valid
|
* @pre All pointers must be valid
|
||||||
*/
|
*/
|
||||||
uint32_t ar2_index_alpha(const argon2_instance_t *instance,
|
uint32_t index_alpha(const argon2_instance_t *instance,
|
||||||
const argon2_position_t *position, uint32_t pseudo_rand,
|
const argon2_position_t *position, uint32_t pseudo_rand,
|
||||||
int same_lane);
|
int same_lane);
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ uint32_t ar2_index_alpha(const argon2_instance_t *instance,
|
|||||||
* @return ARGON2_OK if everything is all right, otherwise one of error codes
|
* @return ARGON2_OK if everything is all right, otherwise one of error codes
|
||||||
* (all defined in <argon2.h>
|
* (all defined in <argon2.h>
|
||||||
*/
|
*/
|
||||||
int ar2_validate_inputs(const argon2_context *context);
|
int validate_inputs(const argon2_context *context);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
|
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
|
||||||
@@ -153,7 +153,7 @@ int ar2_validate_inputs(const argon2_context *context);
|
|||||||
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
|
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
|
||||||
* allocated
|
* allocated
|
||||||
*/
|
*/
|
||||||
void ar2_initial_hash(uint8_t *blockhash, argon2_context *context,
|
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
||||||
argon2_type type);
|
argon2_type type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -162,7 +162,7 @@ void ar2_initial_hash(uint8_t *blockhash, argon2_context *context,
|
|||||||
* @param blockhash Pointer to the pre-hashing digest
|
* @param blockhash Pointer to the pre-hashing digest
|
||||||
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
|
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
|
||||||
*/
|
*/
|
||||||
void ar2_fill_firsts_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
|
void fill_firsts_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function allocates memory, hashes the inputs with Blake, and creates first
|
* Function allocates memory, hashes the inputs with Blake, and creates first
|
||||||
@@ -174,7 +174,7 @@ void ar2_fill_firsts_blocks(uint8_t *blockhash, const argon2_instance_t *instanc
|
|||||||
* @return Zero if successful, -1 if memory failed to allocate. @context->state
|
* @return Zero if successful, -1 if memory failed to allocate. @context->state
|
||||||
* will be modified if successful.
|
* will be modified if successful.
|
||||||
*/
|
*/
|
||||||
int ar2_initialize(argon2_instance_t *instance, argon2_context *context);
|
int initialize(argon2_instance_t *instance, argon2_context *context);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XORing the last block of each lane, hashing it, making the tag. Deallocates
|
* XORing the last block of each lane, hashing it, making the tag. Deallocates
|
||||||
@@ -187,7 +187,7 @@ int ar2_initialize(argon2_instance_t *instance, argon2_context *context);
|
|||||||
* @pre if context->free_cbk is not NULL, it should point to a function that
|
* @pre if context->free_cbk is not NULL, it should point to a function that
|
||||||
* deallocates memory
|
* deallocates memory
|
||||||
*/
|
*/
|
||||||
void ar2_finalize(const argon2_context *context, argon2_instance_t *instance);
|
void finalize(const argon2_context *context, argon2_instance_t *instance);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function that fills the segment using previous segments also from other
|
* Function that fills the segment using previous segments also from other
|
||||||
@@ -196,7 +196,7 @@ void ar2_finalize(const argon2_context *context, argon2_instance_t *instance);
|
|||||||
* @param position Current position
|
* @param position Current position
|
||||||
* @pre all block pointers must be valid
|
* @pre all block pointers must be valid
|
||||||
*/
|
*/
|
||||||
void ar2_fill_segment(const argon2_instance_t *instance,
|
void fill_segment(const argon2_instance_t *instance,
|
||||||
argon2_position_t position);
|
argon2_position_t position);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -204,13 +204,13 @@ void ar2_fill_segment(const argon2_instance_t *instance,
|
|||||||
* blocks in each lane
|
* blocks in each lane
|
||||||
* @param instance Pointer to the current instance
|
* @param instance Pointer to the current instance
|
||||||
*/
|
*/
|
||||||
void ar2_fill_memory_blocks(argon2_instance_t *instance);
|
void fill_memory_blocks(argon2_instance_t *instance);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function that performs memory-hard hashing with certain degree of parallelism
|
* Function that performs memory-hard hashing with certain degree of parallelism
|
||||||
* @param context Pointer to the Argon2 internal structure
|
* @param context Pointer to the Argon2 internal structure
|
||||||
* @return Error code if smth is wrong, ARGON2_OK otherwise
|
* @return Error code if smth is wrong, ARGON2_OK otherwise
|
||||||
*/
|
*/
|
||||||
int ar2_argon2_core(argon2_context *context, argon2_type type);
|
int argon2_core(argon2_context *context, argon2_type type);
|
||||||
|
|
||||||
#endif
|
#endif
|
@@ -26,7 +26,7 @@
|
|||||||
#include "blake2/blake2.h"
|
#include "blake2/blake2.h"
|
||||||
#include "blake2/blamka-round-opt.h"
|
#include "blake2/blamka-round-opt.h"
|
||||||
|
|
||||||
void ar2_fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block)
|
void fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block)
|
||||||
{
|
{
|
||||||
__m128i ALIGN(16) block_XY[ARGON2_QWORDS_IN_BLOCK];
|
__m128i ALIGN(16) block_XY[ARGON2_QWORDS_IN_BLOCK];
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@@ -95,7 +95,7 @@ static const uint64_t bad_rands[32] = {
|
|||||||
UINT64_C(8548260058287621283), UINT64_C(8641748798041936364)
|
UINT64_C(8548260058287621283), UINT64_C(8641748798041936364)
|
||||||
};
|
};
|
||||||
|
|
||||||
void ar2_generate_addresses(const argon2_instance_t *instance,
|
void generate_addresses(const argon2_instance_t *instance,
|
||||||
const argon2_position_t *position,
|
const argon2_position_t *position,
|
||||||
uint64_t *pseudo_rands)
|
uint64_t *pseudo_rands)
|
||||||
{
|
{
|
||||||
@@ -113,7 +113,7 @@ void ar2_generate_addresses(const argon2_instance_t *instance,
|
|||||||
#define LANE_LENGTH 16
|
#define LANE_LENGTH 16
|
||||||
#define POS_LANE 0
|
#define POS_LANE 0
|
||||||
|
|
||||||
void ar2_fill_segment(const argon2_instance_t *instance,
|
void fill_segment(const argon2_instance_t *instance,
|
||||||
argon2_position_t position)
|
argon2_position_t position)
|
||||||
{
|
{
|
||||||
block *ref_block = NULL, *curr_block = NULL;
|
block *ref_block = NULL, *curr_block = NULL;
|
||||||
@@ -129,7 +129,7 @@ void ar2_fill_segment(const argon2_instance_t *instance,
|
|||||||
pseudo_rands = (uint64_t *)malloc(/*sizeof(uint64_t) * 4*/32);
|
pseudo_rands = (uint64_t *)malloc(/*sizeof(uint64_t) * 4*/32);
|
||||||
|
|
||||||
if (data_independent_addressing) {
|
if (data_independent_addressing) {
|
||||||
ar2_generate_addresses(instance, &position, pseudo_rands);
|
generate_addresses(instance, &position, pseudo_rands);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
@@ -173,12 +173,12 @@ void ar2_fill_segment(const argon2_instance_t *instance,
|
|||||||
* lane.
|
* lane.
|
||||||
*/
|
*/
|
||||||
position.index = i;
|
position.index = i;
|
||||||
ref_index = ar2_index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,1);
|
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,1);
|
||||||
|
|
||||||
/* 2 Creating a new block */
|
/* 2 Creating a new block */
|
||||||
ref_block = instance->memory + ref_index;
|
ref_block = instance->memory + ref_index;
|
||||||
curr_block = instance->memory + curr_offset;
|
curr_block = instance->memory + curr_offset;
|
||||||
ar2_fill_block(state, (__m128i const *)ref_block->v, (__m128i *)curr_block->v);
|
fill_block(state, (__m128i const *)ref_block->v, (__m128i *)curr_block->v);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pseudo_rands);
|
free(pseudo_rands);
|
@@ -21,7 +21,7 @@
|
|||||||
* @param next_block Pointer to the block to be constructed
|
* @param next_block Pointer to the block to be constructed
|
||||||
* @pre all block pointers must be valid
|
* @pre all block pointers must be valid
|
||||||
*/
|
*/
|
||||||
void ar2_fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block);
|
void fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate pseudo-random values to reference blocks in the segment and puts
|
* Generate pseudo-random values to reference blocks in the segment and puts
|
||||||
@@ -31,7 +31,7 @@ void ar2_fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_bloc
|
|||||||
* @param pseudo_rands Pointer to the array of 64-bit values
|
* @param pseudo_rands Pointer to the array of 64-bit values
|
||||||
* @pre pseudo_rands must point to @a instance->segment_length allocated values
|
* @pre pseudo_rands must point to @a instance->segment_length allocated values
|
||||||
*/
|
*/
|
||||||
void ar2_generate_addresses(const argon2_instance_t *instance,
|
void generate_addresses(const argon2_instance_t *instance,
|
||||||
const argon2_position_t *position,
|
const argon2_position_t *position,
|
||||||
uint64_t *pseudo_rands);
|
uint64_t *pseudo_rands);
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ void ar2_generate_addresses(const argon2_instance_t *instance,
|
|||||||
* @param position Current position
|
* @param position Current position
|
||||||
* @pre all block pointers must be valid
|
* @pre all block pointers must be valid
|
||||||
*/
|
*/
|
||||||
void ar2_fill_segment(const argon2_instance_t *instance,
|
void fill_segment(const argon2_instance_t *instance,
|
||||||
argon2_position_t position);
|
argon2_position_t position);
|
||||||
|
|
||||||
#endif /* ARGON2_OPT_H */
|
#endif /* ARGON2_OPT_H */
|
@@ -1,3 +1,5 @@
|
|||||||
|
#include "miner.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -24,7 +26,7 @@ inline void argon_call(void *out, void *in, void *salt, int type)
|
|||||||
context.allocate_cbk = NULL;
|
context.allocate_cbk = NULL;
|
||||||
context.free_cbk = NULL;
|
context.free_cbk = NULL;
|
||||||
|
|
||||||
ar2_argon2_core(&context, type);
|
argon2_core(&context, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void argon2hash(void *output, const void *input)
|
void argon2hash(void *output, const void *input)
|
@@ -1,143 +0,0 @@
|
|||||||
#include "argon2d-gate.h"
|
|
||||||
#include "argon2d/argon2.h"
|
|
||||||
|
|
||||||
static const size_t INPUT_BYTES = 80; // Lenth of a block header in bytes. Input Length = Salt Length (salt = input)
|
|
||||||
static const size_t OUTPUT_BYTES = 32; // Length of output needed for a 256-bit hash
|
|
||||||
static const unsigned int DEFAULT_ARGON2_FLAG = 2; //Same as ARGON2_DEFAULT_FLAGS
|
|
||||||
|
|
||||||
// Credits
|
|
||||||
|
|
||||||
void argon2d_crds_hash( void *output, const void *input )
|
|
||||||
{
|
|
||||||
argon2_context context;
|
|
||||||
context.out = (uint8_t *)output;
|
|
||||||
context.outlen = (uint32_t)OUTPUT_BYTES;
|
|
||||||
context.pwd = (uint8_t *)input;
|
|
||||||
context.pwdlen = (uint32_t)INPUT_BYTES;
|
|
||||||
context.salt = (uint8_t *)input; //salt = input
|
|
||||||
context.saltlen = (uint32_t)INPUT_BYTES;
|
|
||||||
context.secret = NULL;
|
|
||||||
context.secretlen = 0;
|
|
||||||
context.ad = NULL;
|
|
||||||
context.adlen = 0;
|
|
||||||
context.allocate_cbk = NULL;
|
|
||||||
context.free_cbk = NULL;
|
|
||||||
context.flags = DEFAULT_ARGON2_FLAG; // = ARGON2_DEFAULT_FLAGS
|
|
||||||
// main configurable Argon2 hash parameters
|
|
||||||
context.m_cost = 250; // Memory in KiB (~256KB)
|
|
||||||
context.lanes = 4; // Degree of Parallelism
|
|
||||||
context.threads = 1; // Threads
|
|
||||||
context.t_cost = 1; // Iterations
|
|
||||||
|
|
||||||
argon2_ctx( &context, Argon2_d );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_argon2d_crds( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t _ALIGN(64) endiandata[20];
|
|
||||||
uint32_t _ALIGN(64) hash[8];
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
const uint32_t Htarg = ptarget[7];
|
|
||||||
|
|
||||||
uint32_t nonce = first_nonce;
|
|
||||||
|
|
||||||
swab32_array( endiandata, pdata, 20 );
|
|
||||||
|
|
||||||
do {
|
|
||||||
be32enc(&endiandata[19], nonce);
|
|
||||||
argon2d_crds_hash( hash, endiandata );
|
|
||||||
if ( hash[7] <= Htarg && fulltest( hash, ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[19] = nonce;
|
|
||||||
*hashes_done = pdata[19] - first_nonce;
|
|
||||||
work_set_target_ratio(work, hash);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
nonce++;
|
|
||||||
} while (nonce < max_nonce && !work_restart[thr_id].restart);
|
|
||||||
|
|
||||||
pdata[19] = nonce;
|
|
||||||
*hashes_done = pdata[19] - first_nonce + 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool register_argon2d_crds_algo( algo_gate_t* gate )
|
|
||||||
{
|
|
||||||
gate->scanhash = (void*)&scanhash_argon2d_crds;
|
|
||||||
gate->hash = (void*)&argon2d_crds_hash;
|
|
||||||
gate->set_target = (void*)&scrypt_set_target;
|
|
||||||
gate->optimizations = SSE2_OPT | AES_OPT | AVX_OPT | AVX2_OPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dynamic
|
|
||||||
|
|
||||||
void argon2d_dyn_hash( void *output, const void *input )
|
|
||||||
{
|
|
||||||
argon2_context context;
|
|
||||||
context.out = (uint8_t *)output;
|
|
||||||
context.outlen = (uint32_t)OUTPUT_BYTES;
|
|
||||||
context.pwd = (uint8_t *)input;
|
|
||||||
context.pwdlen = (uint32_t)INPUT_BYTES;
|
|
||||||
context.salt = (uint8_t *)input; //salt = input
|
|
||||||
context.saltlen = (uint32_t)INPUT_BYTES;
|
|
||||||
context.secret = NULL;
|
|
||||||
context.secretlen = 0;
|
|
||||||
context.ad = NULL;
|
|
||||||
context.adlen = 0;
|
|
||||||
context.allocate_cbk = NULL;
|
|
||||||
context.free_cbk = NULL;
|
|
||||||
context.flags = DEFAULT_ARGON2_FLAG; // = ARGON2_DEFAULT_FLAGS
|
|
||||||
// main configurable Argon2 hash parameters
|
|
||||||
context.m_cost = 500; // Memory in KiB (512KB)
|
|
||||||
context.lanes = 8; // Degree of Parallelism
|
|
||||||
context.threads = 1; // Threads
|
|
||||||
context.t_cost = 2; // Iterations
|
|
||||||
|
|
||||||
argon2_ctx( &context, Argon2_d );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_argon2d_dyn( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t _ALIGN(64) endiandata[20];
|
|
||||||
uint32_t _ALIGN(64) hash[8];
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
const uint32_t Htarg = ptarget[7];
|
|
||||||
|
|
||||||
uint32_t nonce = first_nonce;
|
|
||||||
|
|
||||||
swab32_array( endiandata, pdata, 20 );
|
|
||||||
|
|
||||||
do {
|
|
||||||
be32enc(&endiandata[19], nonce);
|
|
||||||
argon2d_dyn_hash( hash, endiandata );
|
|
||||||
if ( hash[7] <= Htarg && fulltest( hash, ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[19] = nonce;
|
|
||||||
*hashes_done = pdata[19] - first_nonce;
|
|
||||||
work_set_target_ratio(work, hash);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
nonce++;
|
|
||||||
} while (nonce < max_nonce && !work_restart[thr_id].restart);
|
|
||||||
|
|
||||||
pdata[19] = nonce;
|
|
||||||
*hashes_done = pdata[19] - first_nonce + 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool register_argon2d_dyn_algo( algo_gate_t* gate )
|
|
||||||
{
|
|
||||||
gate->scanhash = (void*)&scanhash_argon2d_dyn;
|
|
||||||
gate->hash = (void*)&argon2d_dyn_hash;
|
|
||||||
gate->set_target = (void*)&scrypt_set_target;
|
|
||||||
gate->optimizations = SSE2_OPT | AES_OPT | AVX_OPT | AVX2_OPT;
|
|
||||||
}
|
|
||||||
|
|
@@ -1,25 +0,0 @@
|
|||||||
#ifndef ARGON2D_GATE_H__
|
|
||||||
#define ARGON2D_GATE_H__
|
|
||||||
|
|
||||||
#include "algo-gate-api.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// Credits
|
|
||||||
bool register_argon2d_crds_algo( algo_gate_t* gate );
|
|
||||||
|
|
||||||
void argon2d_crds_hash( void *state, const void *input );
|
|
||||||
|
|
||||||
int scanhash_argon2d_crds( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
|
|
||||||
// Dynamic
|
|
||||||
bool register_argon2d_dyn_algo( algo_gate_t* gate );
|
|
||||||
|
|
||||||
void argon2d_dyn_hash( void *state, const void *input );
|
|
||||||
|
|
||||||
int scanhash_argon2d_dyn( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,680 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <malloc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "argon2.h"
|
|
||||||
#include "encoding.h"
|
|
||||||
#include "core.h"
|
|
||||||
|
|
||||||
const char *argon2_type2string(argon2_type type, int uppercase) {
|
|
||||||
switch (type) {
|
|
||||||
case Argon2_d:
|
|
||||||
return uppercase ? "Argon2d" : "argon2d";
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2_ctx(argon2_context *context, argon2_type type) {
|
|
||||||
/* 1. Validate all inputs */
|
|
||||||
int result = validate_inputs(context);
|
|
||||||
uint32_t memory_blocks, segment_length;
|
|
||||||
argon2_instance_t instance;
|
|
||||||
|
|
||||||
if (ARGON2_OK != result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Argon2_d != type) {
|
|
||||||
return ARGON2_INCORRECT_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. Align memory size */
|
|
||||||
/* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
|
|
||||||
memory_blocks = context->m_cost;
|
|
||||||
|
|
||||||
if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
|
|
||||||
memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
|
|
||||||
}
|
|
||||||
|
|
||||||
segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
|
|
||||||
/* Ensure that all segments have equal length */
|
|
||||||
memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
|
|
||||||
|
|
||||||
instance.memory = NULL;
|
|
||||||
instance.passes = context->t_cost;
|
|
||||||
instance.memory_blocks = memory_blocks;
|
|
||||||
instance.segment_length = segment_length;
|
|
||||||
instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
|
|
||||||
instance.lanes = context->lanes;
|
|
||||||
instance.limit = 1;
|
|
||||||
instance.threads = context->threads;
|
|
||||||
instance.type = type;
|
|
||||||
|
|
||||||
if (instance.threads > instance.limit) {
|
|
||||||
instance.threads = instance.limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 3. Initialization: Hashing inputs, allocating memory, filling first
|
|
||||||
* blocks
|
|
||||||
*/
|
|
||||||
result = initialize(&instance, context);
|
|
||||||
|
|
||||||
if (ARGON2_OK != result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 4. Filling memory */
|
|
||||||
result = fill_memory_blocks(&instance);
|
|
||||||
|
|
||||||
if (ARGON2_OK != result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/* 5. Finalization */
|
|
||||||
finalize(context, &instance);
|
|
||||||
|
|
||||||
return ARGON2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
|
|
||||||
const uint32_t parallelism, const void *pwd,
|
|
||||||
const size_t pwdlen, const void *salt, const size_t saltlen,
|
|
||||||
void *hash, const size_t hashlen, char *encoded,
|
|
||||||
const size_t encodedlen, argon2_type type){
|
|
||||||
|
|
||||||
argon2_context context;
|
|
||||||
int result;
|
|
||||||
uint8_t *out;
|
|
||||||
|
|
||||||
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
|
|
||||||
return ARGON2_PWD_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saltlen > ARGON2_MAX_SALT_LENGTH) {
|
|
||||||
return ARGON2_SALT_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashlen > ARGON2_MAX_OUTLEN) {
|
|
||||||
return ARGON2_OUTPUT_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashlen < ARGON2_MIN_OUTLEN) {
|
|
||||||
return ARGON2_OUTPUT_TOO_SHORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
out = malloc(hashlen);
|
|
||||||
if (!out) {
|
|
||||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.out = (uint8_t *)out;
|
|
||||||
context.outlen = (uint32_t)hashlen;
|
|
||||||
context.pwd = CONST_CAST(uint8_t *)pwd;
|
|
||||||
context.pwdlen = (uint32_t)pwdlen;
|
|
||||||
context.salt = CONST_CAST(uint8_t *)salt;
|
|
||||||
context.saltlen = (uint32_t)saltlen;
|
|
||||||
context.secret = NULL;
|
|
||||||
context.secretlen = 0;
|
|
||||||
context.ad = NULL;
|
|
||||||
context.adlen = 0;
|
|
||||||
context.t_cost = t_cost;
|
|
||||||
context.m_cost = m_cost;
|
|
||||||
context.lanes = parallelism;
|
|
||||||
context.threads = parallelism;
|
|
||||||
context.allocate_cbk = NULL;
|
|
||||||
context.free_cbk = NULL;
|
|
||||||
context.flags = ARGON2_DEFAULT_FLAGS;
|
|
||||||
|
|
||||||
result = argon2_ctx(&context, type);
|
|
||||||
|
|
||||||
if (result != ARGON2_OK) {
|
|
||||||
clear_internal_memory(out, hashlen);
|
|
||||||
free(out);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if raw hash requested, write it */
|
|
||||||
if (hash) {
|
|
||||||
memcpy(hash, out, hashlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if encoding requested, write it */
|
|
||||||
if (encoded && encodedlen) {
|
|
||||||
if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
|
|
||||||
clear_internal_memory(out, hashlen); /* wipe buffers if error */
|
|
||||||
clear_internal_memory(encoded, encodedlen);
|
|
||||||
free(out);
|
|
||||||
return ARGON2_ENCODING_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clear_internal_memory(out, hashlen);
|
|
||||||
free(out);
|
|
||||||
|
|
||||||
return ARGON2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
|
|
||||||
const uint32_t parallelism, const void *pwd,
|
|
||||||
const size_t pwdlen, const void *salt,
|
|
||||||
const size_t saltlen, const size_t hashlen,
|
|
||||||
char *encoded, const size_t encodedlen) {
|
|
||||||
|
|
||||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
|
||||||
NULL, hashlen, encoded, encodedlen, Argon2_d);
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
|
||||||
const uint32_t parallelism, const void *pwd,
|
|
||||||
const size_t pwdlen, const void *salt,
|
|
||||||
const size_t saltlen, void *hash, const size_t hashlen) {
|
|
||||||
|
|
||||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
|
||||||
hash, hashlen, NULL, 0, Argon2_d);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) {
|
|
||||||
size_t i;
|
|
||||||
uint8_t d = 0U;
|
|
||||||
|
|
||||||
for (i = 0U; i < len; i++) {
|
|
||||||
d |= b1[i] ^ b2[i];
|
|
||||||
}
|
|
||||||
return (int)((1 & ((d - 1) >> 8)) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
|
|
||||||
argon2_type type) {
|
|
||||||
|
|
||||||
argon2_context ctx;
|
|
||||||
uint8_t *desired_result = NULL;
|
|
||||||
|
|
||||||
int ret = ARGON2_OK;
|
|
||||||
|
|
||||||
size_t encoded_len;
|
|
||||||
uint32_t max_field_len;
|
|
||||||
|
|
||||||
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
|
|
||||||
return ARGON2_PWD_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encoded == NULL) {
|
|
||||||
return ARGON2_DECODING_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
encoded_len = strlen(encoded);
|
|
||||||
if (encoded_len > UINT32_MAX) {
|
|
||||||
return ARGON2_DECODING_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No field can be longer than the encoded length */
|
|
||||||
max_field_len = (uint32_t)encoded_len;
|
|
||||||
|
|
||||||
ctx.saltlen = max_field_len;
|
|
||||||
ctx.outlen = max_field_len;
|
|
||||||
|
|
||||||
ctx.salt = malloc(ctx.saltlen);
|
|
||||||
ctx.out = malloc(ctx.outlen);
|
|
||||||
if (!ctx.salt || !ctx.out) {
|
|
||||||
ret = ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.pwd = (uint8_t *)pwd;
|
|
||||||
ctx.pwdlen = (uint32_t)pwdlen;
|
|
||||||
|
|
||||||
ret = decode_string(&ctx, encoded, type);
|
|
||||||
if (ret != ARGON2_OK) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set aside the desired result, and get a new buffer. */
|
|
||||||
desired_result = ctx.out;
|
|
||||||
ctx.out = malloc(ctx.outlen);
|
|
||||||
if (!ctx.out) {
|
|
||||||
ret = ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = argon2_verify_ctx(&ctx, (char *)desired_result, type);
|
|
||||||
if (ret != ARGON2_OK) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
fail:
|
|
||||||
free(ctx.salt);
|
|
||||||
free(ctx.out);
|
|
||||||
free(desired_result);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
|
|
||||||
|
|
||||||
return argon2_verify(encoded, pwd, pwdlen, Argon2_d);
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2d_ctx(argon2_context *context) {
|
|
||||||
return argon2_ctx(context, Argon2_d);
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2_verify_ctx(argon2_context *context, const char *hash,
|
|
||||||
argon2_type type) {
|
|
||||||
int ret = argon2_ctx(context, type);
|
|
||||||
if (ret != ARGON2_OK) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argon2_compare((uint8_t *)hash, context->out, context->outlen)) {
|
|
||||||
return ARGON2_VERIFY_MISMATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ARGON2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2d_verify_ctx(argon2_context *context, const char *hash) {
|
|
||||||
return argon2_verify_ctx(context, hash, Argon2_d);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *argon2_error_message(int error_code) {
|
|
||||||
switch (error_code) {
|
|
||||||
case ARGON2_OK:
|
|
||||||
return "OK";
|
|
||||||
case ARGON2_OUTPUT_PTR_NULL:
|
|
||||||
return "Output pointer is NULL";
|
|
||||||
case ARGON2_OUTPUT_TOO_SHORT:
|
|
||||||
return "Output is too short";
|
|
||||||
case ARGON2_OUTPUT_TOO_LONG:
|
|
||||||
return "Output is too long";
|
|
||||||
case ARGON2_PWD_TOO_SHORT:
|
|
||||||
return "Password is too short";
|
|
||||||
case ARGON2_PWD_TOO_LONG:
|
|
||||||
return "Password is too long";
|
|
||||||
case ARGON2_SALT_TOO_SHORT:
|
|
||||||
return "Salt is too short";
|
|
||||||
case ARGON2_SALT_TOO_LONG:
|
|
||||||
return "Salt is too long";
|
|
||||||
case ARGON2_AD_TOO_SHORT:
|
|
||||||
return "Associated data is too short";
|
|
||||||
case ARGON2_AD_TOO_LONG:
|
|
||||||
return "Associated data is too long";
|
|
||||||
case ARGON2_SECRET_TOO_SHORT:
|
|
||||||
return "Secret is too short";
|
|
||||||
case ARGON2_SECRET_TOO_LONG:
|
|
||||||
return "Secret is too long";
|
|
||||||
case ARGON2_TIME_TOO_SMALL:
|
|
||||||
return "Time cost is too small";
|
|
||||||
case ARGON2_TIME_TOO_LARGE:
|
|
||||||
return "Time cost is too large";
|
|
||||||
case ARGON2_MEMORY_TOO_LITTLE:
|
|
||||||
return "Memory cost is too small";
|
|
||||||
case ARGON2_MEMORY_TOO_MUCH:
|
|
||||||
return "Memory cost is too large";
|
|
||||||
case ARGON2_LANES_TOO_FEW:
|
|
||||||
return "Too few lanes";
|
|
||||||
case ARGON2_LANES_TOO_MANY:
|
|
||||||
return "Too many lanes";
|
|
||||||
case ARGON2_PWD_PTR_MISMATCH:
|
|
||||||
return "Password pointer is NULL, but password length is not 0";
|
|
||||||
case ARGON2_SALT_PTR_MISMATCH:
|
|
||||||
return "Salt pointer is NULL, but salt length is not 0";
|
|
||||||
case ARGON2_SECRET_PTR_MISMATCH:
|
|
||||||
return "Secret pointer is NULL, but secret length is not 0";
|
|
||||||
case ARGON2_AD_PTR_MISMATCH:
|
|
||||||
return "Associated data pointer is NULL, but ad length is not 0";
|
|
||||||
case ARGON2_MEMORY_ALLOCATION_ERROR:
|
|
||||||
return "Memory allocation error";
|
|
||||||
case ARGON2_FREE_MEMORY_CBK_NULL:
|
|
||||||
return "The free memory callback is NULL";
|
|
||||||
case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
|
|
||||||
return "The allocate memory callback is NULL";
|
|
||||||
case ARGON2_INCORRECT_PARAMETER:
|
|
||||||
return "Argon2_Context context is NULL";
|
|
||||||
case ARGON2_INCORRECT_TYPE:
|
|
||||||
return "There is no such version of Argon2";
|
|
||||||
case ARGON2_OUT_PTR_MISMATCH:
|
|
||||||
return "Output pointer mismatch";
|
|
||||||
case ARGON2_THREADS_TOO_FEW:
|
|
||||||
return "Not enough threads";
|
|
||||||
case ARGON2_THREADS_TOO_MANY:
|
|
||||||
return "Too many threads";
|
|
||||||
case ARGON2_MISSING_ARGS:
|
|
||||||
return "Missing arguments";
|
|
||||||
case ARGON2_ENCODING_FAIL:
|
|
||||||
return "Encoding failed";
|
|
||||||
case ARGON2_DECODING_FAIL:
|
|
||||||
return "Decoding failed";
|
|
||||||
case ARGON2_THREAD_FAIL:
|
|
||||||
return "Threading failure";
|
|
||||||
case ARGON2_DECODING_LENGTH_FAIL:
|
|
||||||
return "Some of encoded parameters are too long or too short";
|
|
||||||
case ARGON2_VERIFY_MISMATCH:
|
|
||||||
return "The password does not match the supplied hash";
|
|
||||||
default:
|
|
||||||
return "Unknown error code";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
|
|
||||||
uint32_t saltlen, uint32_t hashlen, argon2_type type) {
|
|
||||||
return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) +
|
|
||||||
numlen(t_cost) + numlen(m_cost) + numlen(parallelism) +
|
|
||||||
b64len(saltlen) + b64len(hashlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __AVX2__
|
|
||||||
|
|
||||||
///////////////////////////
|
|
||||||
// Wolf's Additions
|
|
||||||
///////////////////////////
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <x86intrin.h>
|
|
||||||
#include "../blake2/blake2.h"
|
|
||||||
|
|
||||||
typedef struct _Argon2d_Block
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint64_t data[1024 / 8] __attribute__((aligned(32)));
|
|
||||||
__m128i dqwords[1024 / 16] __attribute__((aligned(32)));
|
|
||||||
__m256i qqwords[1024 / 32] __attribute__((aligned(32)));
|
|
||||||
};
|
|
||||||
} Argon2d_Block;
|
|
||||||
|
|
||||||
typedef struct _Argon2ThreadData
|
|
||||||
{
|
|
||||||
Argon2d_Block *Matrix;
|
|
||||||
uint32_t slice;
|
|
||||||
uint32_t lane;
|
|
||||||
} Argon2ThreadData;
|
|
||||||
|
|
||||||
#define SEGMENT_LENGTH (250U / (4U * 4U)) // memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
|
|
||||||
#define LANE_LENGTH (SEGMENT_LENGTH * 4U) // segment_length * ARGON2_SYNC_POINTS;
|
|
||||||
#define CONCURRENT_THREADS 4
|
|
||||||
|
|
||||||
static const uint64_t blake2b_IV[8] =
|
|
||||||
{
|
|
||||||
0x6A09E667F3BCC908ULL, 0xBB67AE8584CAA73BULL,
|
|
||||||
0x3C6EF372FE94F82BULL, 0xA54FF53A5F1D36F1ULL,
|
|
||||||
0x510E527FADE682D1ULL, 0x9B05688C2B3E6C1FULL,
|
|
||||||
0x1F83D9ABFB41BD6BULL, 0x5BE0CD19137E2179ULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned int blake2b_sigma[12][16] =
|
|
||||||
{
|
|
||||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
|
||||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
|
||||||
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
|
|
||||||
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
|
|
||||||
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
|
|
||||||
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
|
|
||||||
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
|
|
||||||
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
|
|
||||||
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
|
|
||||||
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
|
|
||||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
|
||||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
|
|
||||||
|
|
||||||
#define G(r, i, a, b, c, d) \
|
|
||||||
do { \
|
|
||||||
a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
|
|
||||||
d = ROTL64(d ^ a, 32); \
|
|
||||||
c = c + d; \
|
|
||||||
b = ROTL64(b ^ c, 40); \
|
|
||||||
a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
|
|
||||||
d = ROTL64(d ^ a, 48); \
|
|
||||||
c = c + d; \
|
|
||||||
b = ROTL64(b ^ c, 1); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#define ROUND(r) \
|
|
||||||
do { \
|
|
||||||
G(r, 0, v[0], v[4], v[8], v[12]); \
|
|
||||||
G(r, 1, v[1], v[5], v[9], v[13]); \
|
|
||||||
G(r, 2, v[2], v[6], v[10], v[14]); \
|
|
||||||
G(r, 3, v[3], v[7], v[11], v[15]); \
|
|
||||||
G(r, 4, v[0], v[5], v[10], v[15]); \
|
|
||||||
G(r, 5, v[1], v[6], v[11], v[12]); \
|
|
||||||
G(r, 6, v[2], v[7], v[8], v[13]); \
|
|
||||||
G(r, 7, v[3], v[4], v[9], v[14]); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
void CompressBlock(uint64_t *h, const uint64_t *m, uint64_t t, uint64_t f)
|
|
||||||
{
|
|
||||||
uint64_t v[16];
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < 8; ++i) v[i] = h[i];
|
|
||||||
|
|
||||||
for(i = 8; i < 16; ++i) v[i] = blake2b_IV[i - 8];
|
|
||||||
|
|
||||||
v[12] ^= t;
|
|
||||||
v[14] ^= f;
|
|
||||||
|
|
||||||
int r;
|
|
||||||
for(r = 0; r < 12; ++r)
|
|
||||||
{
|
|
||||||
ROUND(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < 8; ++i) h[i] ^= v[i] ^ v[i + 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Argon2dInitHash(void *HashOut, void *Input)
|
|
||||||
{
|
|
||||||
blake2b_state BlakeHash;
|
|
||||||
uint32_t InBuf[64]; // Is only 50 uint32_t, but need more space for Blake2B
|
|
||||||
|
|
||||||
memset(InBuf, 0x00, 200);
|
|
||||||
|
|
||||||
InBuf[0] = 4UL; // Lanes
|
|
||||||
InBuf[1] = 32UL; // Output Length
|
|
||||||
InBuf[2] = 250UL; // Memory Cost
|
|
||||||
InBuf[3] = 1UL; // Time Cost
|
|
||||||
InBuf[4] = 16UL; // Argon2 Version Number
|
|
||||||
InBuf[5] = 0UL; // Type
|
|
||||||
InBuf[6] = 80UL; // Password Length
|
|
||||||
|
|
||||||
memcpy(InBuf + 7, Input, 80); // Password
|
|
||||||
|
|
||||||
InBuf[27] = 80UL; // Salt Length
|
|
||||||
|
|
||||||
memcpy(InBuf + 28, Input, 80); // Salt
|
|
||||||
|
|
||||||
InBuf[48] = 0UL; // Secret Length
|
|
||||||
InBuf[49] = 0UL; // Associated Data Length
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for(i = 50; i < 64; ++i) InBuf[i] = 0UL;
|
|
||||||
|
|
||||||
uint64_t H[8];
|
|
||||||
|
|
||||||
for(i = 0; i < 8; ++i) H[i] = blake2b_IV[i];
|
|
||||||
|
|
||||||
H[0] ^= 0x0000000001010040;
|
|
||||||
|
|
||||||
CompressBlock(H, (uint64_t *)InBuf, 128ULL, 0ULL);
|
|
||||||
CompressBlock(H, (uint64_t *)(InBuf + 32), 200ULL, 0xFFFFFFFFFFFFFFFFULL);
|
|
||||||
|
|
||||||
memcpy(HashOut, H, 64U);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Argon2dFillFirstBlocks(Argon2d_Block *Matrix, void *InitHash)
|
|
||||||
{
|
|
||||||
uint32_t lane;
|
|
||||||
for(lane = 0; lane < 4; ++lane)
|
|
||||||
{
|
|
||||||
((uint32_t *)InitHash)[16] = 0;
|
|
||||||
((uint32_t *)InitHash)[17] = lane;
|
|
||||||
blake2b_long(Matrix[lane * LANE_LENGTH].data, 1024, InitHash, 72);
|
|
||||||
((uint32_t *)InitHash)[16] |= 1;
|
|
||||||
blake2b_long(Matrix[lane * LANE_LENGTH + 1].data, 1024, InitHash, 72);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "../blake2/blamka-round-opt.h"
|
|
||||||
|
|
||||||
void Argon2dFillSingleBlock(Argon2d_Block *State, Argon2d_Block *RefBlock, Argon2d_Block *NextBlock)
|
|
||||||
{
|
|
||||||
__m256i XY[32];
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < 32; ++i)
|
|
||||||
XY[i] = State->qqwords[i] = _mm256_xor_si256(State->qqwords[i], RefBlock->qqwords[i]);
|
|
||||||
|
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
BLAKE2_ROUND( State->dqwords[8 * i + 0], State->dqwords[8 * i + 1], State->dqwords[8 * i + 2], State->dqwords[8 * i + 3],
|
|
||||||
State->dqwords[8 * i + 4], State->dqwords[8 * i + 5], State->dqwords[8 * i + 6], State->dqwords[8 * i + 7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
BLAKE2_ROUND( State->dqwords[8 * 0 + i], State->dqwords[8 * 1 + i], State->dqwords[8 * 2 + i], State->dqwords[8 * 3 + i],
|
|
||||||
State->dqwords[8 * 4 + i], State->dqwords[8 * 5 + i], State->dqwords[8 * 6 + i], State->dqwords[8 * 7 + i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < 32; ++i)
|
|
||||||
{
|
|
||||||
State->qqwords[i] = _mm256_xor_si256(State->qqwords[i], XY[i]);
|
|
||||||
_mm256_store_si256(NextBlock->qqwords + i, State->qqwords[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FillSegment(Argon2d_Block *Matrix, uint32_t slice, uint32_t lane)
|
|
||||||
{
|
|
||||||
uint32_t startidx, prevoff, curoff;
|
|
||||||
Argon2d_Block State;
|
|
||||||
|
|
||||||
startidx = (!slice) ? 2 : 0;
|
|
||||||
curoff = lane * LANE_LENGTH + slice * SEGMENT_LENGTH + startidx;
|
|
||||||
|
|
||||||
//if(!(curoff % LANE_LENGTH)) prevoff = curoff + LANE_LENGTH - 1;
|
|
||||||
//else prevoff = curoff - 1;
|
|
||||||
|
|
||||||
prevoff = (!(curoff % LANE_LENGTH)) ? curoff + LANE_LENGTH - 1 : curoff - 1;
|
|
||||||
|
|
||||||
memcpy(State.data, (Matrix + prevoff)->data, 1024);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for(i = startidx; i < SEGMENT_LENGTH; ++i, ++curoff, ++prevoff)
|
|
||||||
{
|
|
||||||
if((curoff % LANE_LENGTH) == 1) prevoff = curoff - 1;
|
|
||||||
|
|
||||||
uint64_t pseudorand = Matrix[prevoff].data[0];
|
|
||||||
uint64_t reflane = (!slice) ? lane : (pseudorand >> 32) & 3; // mod lanes
|
|
||||||
|
|
||||||
uint32_t index = i;
|
|
||||||
bool samelane = reflane == lane;
|
|
||||||
pseudorand &= 0xFFFFFFFFULL;
|
|
||||||
uint32_t refareasize = ((reflane == lane) ? slice * SEGMENT_LENGTH + index - 1 : slice * SEGMENT_LENGTH + ((!index) ? -1 : 0));
|
|
||||||
|
|
||||||
|
|
||||||
if(!slice) refareasize = index - 1;
|
|
||||||
|
|
||||||
uint64_t relativepos = (pseudorand & 0xFFFFFFFFULL);
|
|
||||||
relativepos = relativepos * relativepos >> 32;
|
|
||||||
relativepos = refareasize - 1 - (refareasize * relativepos >> 32);
|
|
||||||
|
|
||||||
uint32_t startpos = 0;
|
|
||||||
|
|
||||||
uint32_t abspos = (startpos + relativepos) % LANE_LENGTH;
|
|
||||||
|
|
||||||
uint32_t refidx = abspos;
|
|
||||||
|
|
||||||
Argon2dFillSingleBlock(&State, Matrix + (LANE_LENGTH * reflane + refidx), Matrix + curoff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ThreadedSegmentFill(void *ThrData)
|
|
||||||
{
|
|
||||||
Argon2ThreadData *Data = (Argon2ThreadData *)ThrData;
|
|
||||||
|
|
||||||
FillSegment(Data->Matrix, Data->slice, Data->lane);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Argon2dFillAllBlocks(Argon2d_Block *Matrix)
|
|
||||||
{
|
|
||||||
pthread_t ThrHandles[CONCURRENT_THREADS];
|
|
||||||
Argon2ThreadData ThrData[CONCURRENT_THREADS];
|
|
||||||
|
|
||||||
int s;
|
|
||||||
for(s = 0; s < 4; ++s)
|
|
||||||
{
|
|
||||||
// WARNING: Assumes CONCURRENT_THREADS == lanes == 4
|
|
||||||
int l;
|
|
||||||
for(l = 0; l < 4; ++l)
|
|
||||||
{
|
|
||||||
FillSegment(Matrix, s, l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Argon2dFinalizeHash(void *OutputHash, Argon2d_Block *Matrix)
|
|
||||||
{
|
|
||||||
int l;
|
|
||||||
for(l = 1; l < 4; ++l)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < 32; ++i)
|
|
||||||
Matrix[LANE_LENGTH - 1].qqwords[i] = _mm256_xor_si256(Matrix[LANE_LENGTH - 1].qqwords[i], Matrix[LANE_LENGTH * l + (LANE_LENGTH - 1)].qqwords[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
blake2b_long(OutputHash, 32, Matrix[LANE_LENGTH - 1].data, 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WolfArgon2dPoWHash(void *Output, void *Matrix, const void *BlkHdr)
|
|
||||||
{
|
|
||||||
uint8_t tmp[72];
|
|
||||||
|
|
||||||
Argon2dInitHash(tmp, (uint8_t *)BlkHdr);
|
|
||||||
|
|
||||||
Argon2dFillFirstBlocks(Matrix, tmp);
|
|
||||||
|
|
||||||
Argon2dFillAllBlocks(Matrix);
|
|
||||||
|
|
||||||
Argon2dFinalizeHash((uint8_t *)Output, Matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WolfArgon2dAllocateCtx(void **Matrix)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
*((Argon2d_Block **)Matrix) = (Argon2d_Block *)_aligned_malloc(32, sizeof(Argon2d_Block) * (SEGMENT_LENGTH << 4));
|
|
||||||
#else
|
|
||||||
*((Argon2d_Block **)Matrix) = (Argon2d_Block *)malloc(sizeof(Argon2d_Block) * (SEGMENT_LENGTH << 4));
|
|
||||||
posix_memalign(Matrix, 32, sizeof(Argon2d_Block) * (SEGMENT_LENGTH << 4));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void WolfArgon2dFreeCtx(void *Matrix)
|
|
||||||
{
|
|
||||||
free(Matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,345 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ARGON2_H
|
|
||||||
#define ARGON2_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Symbols visibility control */
|
|
||||||
#ifdef A2_VISCTL
|
|
||||||
#define ARGON2_PUBLIC __attribute__((visibility("default")))
|
|
||||||
#elif _MSC_VER
|
|
||||||
#define ARGON2_PUBLIC __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
#define ARGON2_PUBLIC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Argon2 input parameter restrictions
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Minimum and maximum number of lanes (degree of parallelism) */
|
|
||||||
#define ARGON2_MIN_LANES UINT32_C(1)
|
|
||||||
#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)
|
|
||||||
|
|
||||||
/* Minimum and maximum number of threads */
|
|
||||||
#define ARGON2_MIN_THREADS UINT32_C(1)
|
|
||||||
#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)
|
|
||||||
|
|
||||||
/* Number of synchronization points between lanes per pass */
|
|
||||||
#define ARGON2_SYNC_POINTS UINT32_C(4)
|
|
||||||
|
|
||||||
/* Minimum and maximum digest size in bytes */
|
|
||||||
#define ARGON2_MIN_OUTLEN UINT32_C(4)
|
|
||||||
#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF)
|
|
||||||
|
|
||||||
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
|
|
||||||
#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
|
|
||||||
|
|
||||||
#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */
|
|
||||||
#define ARGON2_MAX_MEMORY_BITS \
|
|
||||||
ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
|
|
||||||
#define ARGON2_MAX_MEMORY \
|
|
||||||
ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
|
|
||||||
|
|
||||||
/* Minimum and maximum number of passes */
|
|
||||||
#define ARGON2_MIN_TIME UINT32_C(1)
|
|
||||||
#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
|
|
||||||
|
|
||||||
/* Minimum and maximum password length in bytes */
|
|
||||||
#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)
|
|
||||||
#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)
|
|
||||||
|
|
||||||
/* Minimum and maximum associated data length in bytes */
|
|
||||||
#define ARGON2_MIN_AD_LENGTH UINT32_C(0)
|
|
||||||
#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)
|
|
||||||
|
|
||||||
/* Minimum and maximum salt length in bytes */
|
|
||||||
#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)
|
|
||||||
#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)
|
|
||||||
|
|
||||||
/* Minimum and maximum key length in bytes */
|
|
||||||
#define ARGON2_MIN_SECRET UINT32_C(0)
|
|
||||||
#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
|
|
||||||
|
|
||||||
/* Flags to determine which fields are securely wiped (default = no wipe). */
|
|
||||||
#define ARGON2_DEFAULT_FLAGS UINT32_C(0)
|
|
||||||
#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
|
|
||||||
#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
|
|
||||||
|
|
||||||
/* Global flag to determine if we are wiping internal memory buffers. This flag
|
|
||||||
* is defined in core.c and deafults to 1 (wipe internal memory). */
|
|
||||||
extern int FLAG_clear_internal_memory;
|
|
||||||
|
|
||||||
/* Error codes */
|
|
||||||
typedef enum Argon2_ErrorCodes {
|
|
||||||
ARGON2_OK = 0,
|
|
||||||
|
|
||||||
ARGON2_OUTPUT_PTR_NULL = -1,
|
|
||||||
|
|
||||||
ARGON2_OUTPUT_TOO_SHORT = -2,
|
|
||||||
ARGON2_OUTPUT_TOO_LONG = -3,
|
|
||||||
|
|
||||||
ARGON2_PWD_TOO_SHORT = -4,
|
|
||||||
ARGON2_PWD_TOO_LONG = -5,
|
|
||||||
|
|
||||||
ARGON2_SALT_TOO_SHORT = -6,
|
|
||||||
ARGON2_SALT_TOO_LONG = -7,
|
|
||||||
|
|
||||||
ARGON2_AD_TOO_SHORT = -8,
|
|
||||||
ARGON2_AD_TOO_LONG = -9,
|
|
||||||
|
|
||||||
ARGON2_SECRET_TOO_SHORT = -10,
|
|
||||||
ARGON2_SECRET_TOO_LONG = -11,
|
|
||||||
|
|
||||||
ARGON2_TIME_TOO_SMALL = -12,
|
|
||||||
ARGON2_TIME_TOO_LARGE = -13,
|
|
||||||
|
|
||||||
ARGON2_MEMORY_TOO_LITTLE = -14,
|
|
||||||
ARGON2_MEMORY_TOO_MUCH = -15,
|
|
||||||
|
|
||||||
ARGON2_LANES_TOO_FEW = -16,
|
|
||||||
ARGON2_LANES_TOO_MANY = -17,
|
|
||||||
|
|
||||||
ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
|
|
||||||
ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
|
|
||||||
ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
|
|
||||||
ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
|
|
||||||
|
|
||||||
ARGON2_MEMORY_ALLOCATION_ERROR = -22,
|
|
||||||
|
|
||||||
ARGON2_FREE_MEMORY_CBK_NULL = -23,
|
|
||||||
ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
|
|
||||||
|
|
||||||
ARGON2_INCORRECT_PARAMETER = -25,
|
|
||||||
ARGON2_INCORRECT_TYPE = -26,
|
|
||||||
|
|
||||||
ARGON2_OUT_PTR_MISMATCH = -27,
|
|
||||||
|
|
||||||
ARGON2_THREADS_TOO_FEW = -28,
|
|
||||||
ARGON2_THREADS_TOO_MANY = -29,
|
|
||||||
|
|
||||||
ARGON2_MISSING_ARGS = -30,
|
|
||||||
|
|
||||||
ARGON2_ENCODING_FAIL = -31,
|
|
||||||
|
|
||||||
ARGON2_DECODING_FAIL = -32,
|
|
||||||
|
|
||||||
ARGON2_THREAD_FAIL = -33,
|
|
||||||
|
|
||||||
ARGON2_DECODING_LENGTH_FAIL = -34,
|
|
||||||
|
|
||||||
ARGON2_VERIFY_MISMATCH = -35
|
|
||||||
} argon2_error_codes;
|
|
||||||
|
|
||||||
/* Memory allocator types --- for external allocation */
|
|
||||||
typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate);
|
|
||||||
typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
|
|
||||||
|
|
||||||
/* Argon2 external data structures */
|
|
||||||
|
|
||||||
/*
|
|
||||||
*****
|
|
||||||
* Context: structure to hold Argon2 inputs:
|
|
||||||
* output array and its length,
|
|
||||||
* password and its length,
|
|
||||||
* salt and its length,
|
|
||||||
* secret and its length,
|
|
||||||
* associated data and its length,
|
|
||||||
* number of passes, amount of used memory (in KBytes, can be rounded up a bit)
|
|
||||||
* number of parallel threads that will be run.
|
|
||||||
* All the parameters above affect the output hash value.
|
|
||||||
* Additionally, two function pointers can be provided to allocate and
|
|
||||||
* deallocate the memory (if NULL, memory will be allocated internally).
|
|
||||||
* Also, three flags indicate whether to erase password, secret as soon as they
|
|
||||||
* are pre-hashed (and thus not needed anymore), and the entire memory
|
|
||||||
*****
|
|
||||||
* Simplest situation: you have output array out[8], password is stored in
|
|
||||||
* pwd[32], salt is stored in salt[16], you do not have keys nor associated
|
|
||||||
* data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with
|
|
||||||
* 4 parallel lanes.
|
|
||||||
* You want to erase the password, but you're OK with last pass not being
|
|
||||||
* erased. You want to use the default memory allocator.
|
|
||||||
* Then you initialize:
|
|
||||||
Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false)
|
|
||||||
*/
|
|
||||||
typedef struct Argon2_Context {
|
|
||||||
uint8_t *out; /* output array */
|
|
||||||
uint32_t outlen; /* digest length */
|
|
||||||
|
|
||||||
uint8_t *pwd; /* password array */
|
|
||||||
uint32_t pwdlen; /* password length */
|
|
||||||
|
|
||||||
uint8_t *salt; /* salt array */
|
|
||||||
uint32_t saltlen; /* salt length */
|
|
||||||
|
|
||||||
uint8_t *secret; /* key array */
|
|
||||||
uint32_t secretlen; /* key length */
|
|
||||||
|
|
||||||
uint8_t *ad; /* associated data array */
|
|
||||||
uint32_t adlen; /* associated data length */
|
|
||||||
|
|
||||||
uint32_t t_cost; /* number of passes */
|
|
||||||
uint32_t m_cost; /* amount of memory requested (KB) */
|
|
||||||
uint32_t lanes; /* number of lanes */
|
|
||||||
uint32_t threads; /* maximum number of threads */
|
|
||||||
|
|
||||||
allocate_fptr allocate_cbk; /* pointer to memory allocator */
|
|
||||||
deallocate_fptr free_cbk; /* pointer to memory deallocator */
|
|
||||||
|
|
||||||
uint32_t flags; /* array of bool options */
|
|
||||||
} argon2_context;
|
|
||||||
|
|
||||||
/* Argon2 primitive type */
|
|
||||||
typedef enum Argon2_type {
|
|
||||||
Argon2_d = 0
|
|
||||||
} argon2_type;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function that gives the string representation of an argon2_type.
|
|
||||||
* @param type The argon2_type that we want the string for
|
|
||||||
* @param uppercase Whether the string should have the first letter uppercase
|
|
||||||
* @return NULL if invalid type, otherwise the string representation.
|
|
||||||
*/
|
|
||||||
ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function that performs memory-hard hashing with certain degree of parallelism
|
|
||||||
* @param context Pointer to the Argon2 internal structure
|
|
||||||
* @return Error code if smth is wrong, ARGON2_OK otherwise
|
|
||||||
*/
|
|
||||||
ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hashes a password with Argon2i, producing a raw hash by allocating memory at
|
|
||||||
* @hash
|
|
||||||
* @param t_cost Number of iterations
|
|
||||||
* @param m_cost Sets memory usage to m_cost kibibytes
|
|
||||||
* @param parallelism Number of threads and compute lanes
|
|
||||||
* @param pwd Pointer to password
|
|
||||||
* @param pwdlen Password size in bytes
|
|
||||||
* @param salt Pointer to salt
|
|
||||||
* @param saltlen Salt size in bytes
|
|
||||||
* @param hash Buffer where to write the raw hash - updated by the function
|
|
||||||
* @param hashlen Desired length of the hash in bytes
|
|
||||||
* @pre Different parallelism levels will give different results
|
|
||||||
* @pre Returns ARGON2_OK if successful
|
|
||||||
*/
|
|
||||||
ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
|
||||||
const uint32_t parallelism, const void *pwd,
|
|
||||||
const size_t pwdlen, const void *salt,
|
|
||||||
const size_t saltlen, void *hash,
|
|
||||||
const size_t hashlen);
|
|
||||||
|
|
||||||
ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost,
|
|
||||||
const uint32_t m_cost,
|
|
||||||
const uint32_t parallelism,
|
|
||||||
const void *pwd, const size_t pwdlen,
|
|
||||||
const void *salt, const size_t saltlen,
|
|
||||||
const size_t hashlen, char *encoded,
|
|
||||||
const size_t encodedlen);
|
|
||||||
|
|
||||||
/* generic function underlying the above ones */
|
|
||||||
ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
|
|
||||||
const uint32_t parallelism, const void *pwd,
|
|
||||||
const size_t pwdlen, const void *salt,
|
|
||||||
const size_t saltlen, void *hash,
|
|
||||||
const size_t hashlen, char *encoded,
|
|
||||||
const size_t encodedlen, argon2_type type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies a password against an encoded string
|
|
||||||
* Encoded string is restricted as in validate_inputs()
|
|
||||||
* @param encoded String encoding parameters, salt, hash
|
|
||||||
* @param pwd Pointer to password
|
|
||||||
* @pre Returns ARGON2_OK if successful
|
|
||||||
*/
|
|
||||||
ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd,
|
|
||||||
const size_t pwdlen);
|
|
||||||
|
|
||||||
/* generic function underlying the above ones */
|
|
||||||
ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd,
|
|
||||||
const size_t pwdlen, argon2_type type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Argon2d: Version of Argon2 that picks memory blocks depending
|
|
||||||
* on the password and salt. Only for side-channel-free
|
|
||||||
* environment!!
|
|
||||||
*****
|
|
||||||
* @param context Pointer to current Argon2 context
|
|
||||||
* @return Zero if successful, a non zero error code otherwise
|
|
||||||
*/
|
|
||||||
ARGON2_PUBLIC int argon2d_ctx(argon2_context *context);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify if a given password is correct for Argon2d hashing
|
|
||||||
* @param context Pointer to current Argon2 context
|
|
||||||
* @param hash The password hash to verify. The length of the hash is
|
|
||||||
* specified by the context outlen member
|
|
||||||
* @return Zero if successful, a non zero error code otherwise
|
|
||||||
*/
|
|
||||||
ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash);
|
|
||||||
|
|
||||||
/* generic function underlying the above ones */
|
|
||||||
ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash,
|
|
||||||
argon2_type type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the associated error message for given error code
|
|
||||||
* @return The error message associated with the given error code
|
|
||||||
*/
|
|
||||||
ARGON2_PUBLIC const char *argon2_error_message(int error_code);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the encoded hash length for the given input parameters
|
|
||||||
* @param t_cost Number of iterations
|
|
||||||
* @param m_cost Memory usage in kibibytes
|
|
||||||
* @param parallelism Number of threads; used to compute lanes
|
|
||||||
* @param saltlen Salt size in bytes
|
|
||||||
* @param hashlen Hash size in bytes
|
|
||||||
* @param type The argon2_type that we want the encoded length for
|
|
||||||
* @return The encoded hash length in bytes
|
|
||||||
*/
|
|
||||||
ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost,
|
|
||||||
uint32_t parallelism, uint32_t saltlen,
|
|
||||||
uint32_t hashlen, argon2_type type);
|
|
||||||
|
|
||||||
#ifdef __AVX2__
|
|
||||||
|
|
||||||
///////////////////////////
|
|
||||||
// Wolf's Additions
|
|
||||||
///////////////////////////
|
|
||||||
|
|
||||||
void WolfArgon2dPoWHash(void *Output, void *Matrix, const void *BlkHdr);
|
|
||||||
void WolfArgon2dAllocateCtx(void **Matrix);
|
|
||||||
void WolfArgon2dFreeCtx(void *Matrix);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,617 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*For memory wiping*/
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <windows.h>
|
|
||||||
#include <winbase.h> /* For SecureZeroMemory */
|
|
||||||
#endif
|
|
||||||
#if defined __STDC_LIB_EXT1__
|
|
||||||
#define __STDC_WANT_LIB_EXT1__ 1
|
|
||||||
#endif
|
|
||||||
#define VC_GE_2005(version) (version >= 1400)
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "core.h"
|
|
||||||
#include "thread.h"
|
|
||||||
#include "../blake2/blake2.h"
|
|
||||||
#include "../blake2/blake2-impl.h"
|
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
#if __has_attribute(optnone)
|
|
||||||
#define NOT_OPTIMIZED __attribute__((optnone))
|
|
||||||
#endif
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
#define GCC_VERSION \
|
|
||||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
|
||||||
#if GCC_VERSION >= 40400
|
|
||||||
#define NOT_OPTIMIZED __attribute__((optimize("O0")))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifndef NOT_OPTIMIZED
|
|
||||||
#define NOT_OPTIMIZED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/***************Instance and Position constructors**********/
|
|
||||||
void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
|
|
||||||
|
|
||||||
void copy_block(block *dst, const block *src) {
|
|
||||||
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void xor_block(block *dst, const block *src) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
|
||||||
dst->v[i] ^= src->v[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_block(block *dst, const void *input) {
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
|
||||||
dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void store_block(void *output, const block *src) {
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
|
||||||
store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************Memory functions*****************/
|
|
||||||
|
|
||||||
int allocate_memory(const argon2_context *context, uint8_t **memory,
|
|
||||||
size_t num, size_t size) {
|
|
||||||
size_t memory_size = num*size;
|
|
||||||
if (memory == NULL) {
|
|
||||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1. Check for multiplication overflow */
|
|
||||||
if (size != 0 && memory_size / size != num) {
|
|
||||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. Try to allocate with appropriate allocator */
|
|
||||||
if (context->allocate_cbk) {
|
|
||||||
(context->allocate_cbk)(memory, memory_size);
|
|
||||||
} else {
|
|
||||||
*memory = malloc(memory_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*memory == NULL) {
|
|
||||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ARGON2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free_memory(const argon2_context *context, uint8_t *memory,
|
|
||||||
size_t num, size_t size) {
|
|
||||||
size_t memory_size = num*size;
|
|
||||||
clear_internal_memory(memory, memory_size);
|
|
||||||
if (context->free_cbk) {
|
|
||||||
(context->free_cbk)(memory, memory_size);
|
|
||||||
} else {
|
|
||||||
free(memory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) {
|
|
||||||
#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER)
|
|
||||||
SecureZeroMemory(v, n);
|
|
||||||
#elif defined memset_s
|
|
||||||
memset_s(v, n, 0, n);
|
|
||||||
#elif defined(__OpenBSD__)
|
|
||||||
explicit_bzero(v, n);
|
|
||||||
#else
|
|
||||||
static void *(*const volatile memset_sec)(void *, int, size_t) = &memset;
|
|
||||||
memset_sec(v, 0, n);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Memory clear flag defaults to true. */
|
|
||||||
int FLAG_clear_internal_memory = 1;
|
|
||||||
void clear_internal_memory(void *v, size_t n) {
|
|
||||||
if (FLAG_clear_internal_memory && v) {
|
|
||||||
secure_wipe_memory(v, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void finalize(const argon2_context *context, argon2_instance_t *instance) {
|
|
||||||
if (context != NULL && instance != NULL) {
|
|
||||||
block blockhash;
|
|
||||||
uint32_t l;
|
|
||||||
|
|
||||||
copy_block(&blockhash, instance->memory + instance->lane_length - 1);
|
|
||||||
|
|
||||||
/* XOR the last blocks */
|
|
||||||
for (l = 1; l < instance->lanes; ++l) {
|
|
||||||
uint32_t last_block_in_lane =
|
|
||||||
l * instance->lane_length + (instance->lane_length - 1);
|
|
||||||
xor_block(&blockhash, instance->memory + last_block_in_lane);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hash the result */
|
|
||||||
{
|
|
||||||
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
|
||||||
store_block(blockhash_bytes, &blockhash);
|
|
||||||
blake2b_long(context->out, context->outlen, blockhash_bytes,
|
|
||||||
ARGON2_BLOCK_SIZE);
|
|
||||||
/* clear blockhash and blockhash_bytes */
|
|
||||||
clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE);
|
|
||||||
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
free_memory(context, (uint8_t *)instance->memory,
|
|
||||||
instance->memory_blocks, sizeof(block));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t index_alpha(const argon2_instance_t *instance,
|
|
||||||
const argon2_position_t *position, uint32_t pseudo_rand,
|
|
||||||
int same_lane) {
|
|
||||||
/*
|
|
||||||
* Pass 0:
|
|
||||||
* This lane : all already finished segments plus already constructed
|
|
||||||
* blocks in this segment
|
|
||||||
* Other lanes : all already finished segments
|
|
||||||
* Pass 1+:
|
|
||||||
* This lane : (SYNC_POINTS - 1) last segments plus already constructed
|
|
||||||
* blocks in this segment
|
|
||||||
* Other lanes : (SYNC_POINTS - 1) last segments
|
|
||||||
*/
|
|
||||||
uint32_t reference_area_size;
|
|
||||||
uint64_t relative_position;
|
|
||||||
uint32_t start_position, absolute_position;
|
|
||||||
|
|
||||||
if (0 == position->pass) {
|
|
||||||
/* First pass */
|
|
||||||
if (0 == position->slice) {
|
|
||||||
/* First slice */
|
|
||||||
reference_area_size =
|
|
||||||
position->index - 1; /* all but the previous */
|
|
||||||
} else {
|
|
||||||
if (same_lane) {
|
|
||||||
/* The same lane => add current segment */
|
|
||||||
reference_area_size =
|
|
||||||
position->slice * instance->segment_length +
|
|
||||||
position->index - 1;
|
|
||||||
} else {
|
|
||||||
reference_area_size =
|
|
||||||
position->slice * instance->segment_length +
|
|
||||||
((position->index == 0) ? (-1) : 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Second pass */
|
|
||||||
if (same_lane) {
|
|
||||||
reference_area_size = instance->lane_length -
|
|
||||||
instance->segment_length + position->index -
|
|
||||||
1;
|
|
||||||
} else {
|
|
||||||
reference_area_size = instance->lane_length -
|
|
||||||
instance->segment_length +
|
|
||||||
((position->index == 0) ? (-1) : 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
|
|
||||||
* relative position */
|
|
||||||
relative_position = pseudo_rand;
|
|
||||||
relative_position = relative_position * relative_position >> 32;
|
|
||||||
relative_position = reference_area_size - 1 -
|
|
||||||
(reference_area_size * relative_position >> 32);
|
|
||||||
|
|
||||||
/* 1.2.5 Computing starting position */
|
|
||||||
start_position = 0;
|
|
||||||
|
|
||||||
if (0 != position->pass) {
|
|
||||||
start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
|
|
||||||
? 0
|
|
||||||
: (position->slice + 1) * instance->segment_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1.2.6. Computing absolute position */
|
|
||||||
absolute_position = (start_position + relative_position) %
|
|
||||||
instance->lane_length; /* absolute position */
|
|
||||||
return absolute_position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Single-threaded version for p=1 case */
|
|
||||||
static int fill_memory_blocks_st(argon2_instance_t *instance) {
|
|
||||||
uint32_t r, s, l;
|
|
||||||
|
|
||||||
for (r = 0; r < instance->passes; ++r) {
|
|
||||||
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
|
|
||||||
for (l = 0; l < instance->lanes; ++l) {
|
|
||||||
argon2_position_t position = {r, l, (uint8_t)s, 0};
|
|
||||||
fill_segment(instance, position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ARGON2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(ARGON2_NO_THREADS)
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static unsigned __stdcall fill_segment_thr(void *thread_data)
|
|
||||||
#else
|
|
||||||
static void *fill_segment_thr(void *thread_data)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
argon2_thread_data *my_data = thread_data;
|
|
||||||
fill_segment(my_data->instance_ptr, my_data->pos);
|
|
||||||
argon2_thread_exit();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Multi-threaded version for p > 1 case */
|
|
||||||
static int fill_memory_blocks_mt(argon2_instance_t *instance) {
|
|
||||||
uint32_t r, s;
|
|
||||||
argon2_thread_handle_t *thread = NULL;
|
|
||||||
argon2_thread_data *thr_data = NULL;
|
|
||||||
int rc = ARGON2_OK;
|
|
||||||
|
|
||||||
/* 1. Allocating space for threads */
|
|
||||||
thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t));
|
|
||||||
if (thread == NULL) {
|
|
||||||
rc = ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
thr_data = calloc(instance->lanes, sizeof(argon2_thread_data));
|
|
||||||
if (thr_data == NULL) {
|
|
||||||
rc = ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (r = 0; r < instance->passes; ++r) {
|
|
||||||
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
|
|
||||||
uint32_t l;
|
|
||||||
|
|
||||||
/* 2. Calling threads */
|
|
||||||
for (l = 0; l < instance->lanes; ++l) {
|
|
||||||
argon2_position_t position;
|
|
||||||
|
|
||||||
/* 2.1 Join a thread if limit is exceeded */
|
|
||||||
if (l >= instance->threads) {
|
|
||||||
if (argon2_thread_join(thread[l - instance->threads])) {
|
|
||||||
rc = ARGON2_THREAD_FAIL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2.2 Create thread */
|
|
||||||
position.pass = r;
|
|
||||||
position.lane = l;
|
|
||||||
position.slice = (uint8_t)s;
|
|
||||||
position.index = 0;
|
|
||||||
thr_data[l].instance_ptr =
|
|
||||||
instance; /* preparing the thread input */
|
|
||||||
memcpy(&(thr_data[l].pos), &position,
|
|
||||||
sizeof(argon2_position_t));
|
|
||||||
if (argon2_thread_create(&thread[l], &fill_segment_thr,
|
|
||||||
(void *)&thr_data[l])) {
|
|
||||||
rc = ARGON2_THREAD_FAIL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fill_segment(instance, position); */
|
|
||||||
/*Non-thread equivalent of the lines above */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 3. Joining remaining threads */
|
|
||||||
for (l = instance->lanes - instance->threads; l < instance->lanes;
|
|
||||||
++l) {
|
|
||||||
if (argon2_thread_join(thread[l])) {
|
|
||||||
rc = ARGON2_THREAD_FAIL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (thread != NULL) {
|
|
||||||
free(thread);
|
|
||||||
}
|
|
||||||
if (thr_data != NULL) {
|
|
||||||
free(thr_data);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ARGON2_NO_THREADS */
|
|
||||||
|
|
||||||
int fill_memory_blocks(argon2_instance_t *instance) {
|
|
||||||
if (instance == NULL || instance->lanes == 0) {
|
|
||||||
return ARGON2_INCORRECT_PARAMETER;
|
|
||||||
}
|
|
||||||
#if defined(ARGON2_NO_THREADS)
|
|
||||||
return fill_memory_blocks_st(instance);
|
|
||||||
#else
|
|
||||||
return instance->threads == 1 ?
|
|
||||||
fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int validate_inputs(const argon2_context *context) {
|
|
||||||
if (NULL == context) {
|
|
||||||
return ARGON2_INCORRECT_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == context->out) {
|
|
||||||
return ARGON2_OUTPUT_PTR_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate output length */
|
|
||||||
if (ARGON2_MIN_OUTLEN > context->outlen) {
|
|
||||||
return ARGON2_OUTPUT_TOO_SHORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MAX_OUTLEN < context->outlen) {
|
|
||||||
return ARGON2_OUTPUT_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate password (required param) */
|
|
||||||
if (NULL == context->pwd) {
|
|
||||||
if (0 != context->pwdlen) {
|
|
||||||
return ARGON2_PWD_PTR_MISMATCH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
|
|
||||||
return ARGON2_PWD_TOO_SHORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
|
|
||||||
return ARGON2_PWD_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate salt (required param) */
|
|
||||||
if (NULL == context->salt) {
|
|
||||||
if (0 != context->saltlen) {
|
|
||||||
return ARGON2_SALT_PTR_MISMATCH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
|
|
||||||
return ARGON2_SALT_TOO_SHORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
|
|
||||||
return ARGON2_SALT_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate secret (optional param) */
|
|
||||||
if (NULL == context->secret) {
|
|
||||||
if (0 != context->secretlen) {
|
|
||||||
return ARGON2_SECRET_PTR_MISMATCH;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ARGON2_MIN_SECRET > context->secretlen) {
|
|
||||||
return ARGON2_SECRET_TOO_SHORT;
|
|
||||||
}
|
|
||||||
if (ARGON2_MAX_SECRET < context->secretlen) {
|
|
||||||
return ARGON2_SECRET_TOO_LONG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate associated data (optional param) */
|
|
||||||
if (NULL == context->ad) {
|
|
||||||
if (0 != context->adlen) {
|
|
||||||
return ARGON2_AD_PTR_MISMATCH;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ARGON2_MIN_AD_LENGTH > context->adlen) {
|
|
||||||
return ARGON2_AD_TOO_SHORT;
|
|
||||||
}
|
|
||||||
if (ARGON2_MAX_AD_LENGTH < context->adlen) {
|
|
||||||
return ARGON2_AD_TOO_LONG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate memory cost */
|
|
||||||
if (ARGON2_MIN_MEMORY > context->m_cost) {
|
|
||||||
return ARGON2_MEMORY_TOO_LITTLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MAX_MEMORY < context->m_cost) {
|
|
||||||
return ARGON2_MEMORY_TOO_MUCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context->m_cost < 8 * context->lanes) {
|
|
||||||
return ARGON2_MEMORY_TOO_LITTLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate time cost */
|
|
||||||
if (ARGON2_MIN_TIME > context->t_cost) {
|
|
||||||
return ARGON2_TIME_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MAX_TIME < context->t_cost) {
|
|
||||||
return ARGON2_TIME_TOO_LARGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate lanes */
|
|
||||||
if (ARGON2_MIN_LANES > context->lanes) {
|
|
||||||
return ARGON2_LANES_TOO_FEW;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MAX_LANES < context->lanes) {
|
|
||||||
return ARGON2_LANES_TOO_MANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate threads */
|
|
||||||
if (ARGON2_MIN_THREADS > context->threads) {
|
|
||||||
return ARGON2_THREADS_TOO_FEW;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MAX_THREADS < context->threads) {
|
|
||||||
return ARGON2_THREADS_TOO_MANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != context->allocate_cbk && NULL == context->free_cbk) {
|
|
||||||
return ARGON2_FREE_MEMORY_CBK_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == context->allocate_cbk && NULL != context->free_cbk) {
|
|
||||||
return ARGON2_ALLOCATE_MEMORY_CBK_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ARGON2_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
|
|
||||||
uint32_t l;
|
|
||||||
/* Make the first and second block in each lane as G(H0||0||i) or
|
|
||||||
G(H0||1||i) */
|
|
||||||
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
|
||||||
for (l = 0; l < instance->lanes; ++l) {
|
|
||||||
|
|
||||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
|
|
||||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
|
|
||||||
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
|
|
||||||
ARGON2_PREHASH_SEED_LENGTH);
|
|
||||||
load_block(&instance->memory[l * instance->lane_length + 0],
|
|
||||||
blockhash_bytes);
|
|
||||||
|
|
||||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
|
|
||||||
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
|
|
||||||
ARGON2_PREHASH_SEED_LENGTH);
|
|
||||||
load_block(&instance->memory[l * instance->lane_length + 1],
|
|
||||||
blockhash_bytes);
|
|
||||||
}
|
|
||||||
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
|
||||||
argon2_type type) {
|
|
||||||
blake2b_state BlakeHash;
|
|
||||||
uint8_t value[sizeof(uint32_t)];
|
|
||||||
|
|
||||||
if (NULL == context || NULL == blockhash) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
|
|
||||||
|
|
||||||
store32(&value, context->lanes);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
store32(&value, context->outlen);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
store32(&value, context->m_cost);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
store32(&value, context->t_cost);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
store32(&value, ARGON2_VERSION_NUMBER);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
store32(&value, (uint32_t)type);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
store32(&value, context->pwdlen);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
if (context->pwd != NULL) {
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
|
|
||||||
context->pwdlen);
|
|
||||||
|
|
||||||
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
|
|
||||||
secure_wipe_memory(context->pwd, context->pwdlen);
|
|
||||||
context->pwdlen = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
store32(&value, context->saltlen);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
if (context->salt != NULL) {
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
|
|
||||||
context->saltlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
store32(&value, context->secretlen);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
if (context->secret != NULL) {
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
|
|
||||||
context->secretlen);
|
|
||||||
|
|
||||||
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
|
|
||||||
secure_wipe_memory(context->secret, context->secretlen);
|
|
||||||
context->secretlen = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
store32(&value, context->adlen);
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
|
||||||
|
|
||||||
if (context->ad != NULL) {
|
|
||||||
blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
|
|
||||||
context->adlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
int initialize(argon2_instance_t *instance, argon2_context *context) {
|
|
||||||
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
|
|
||||||
int result = ARGON2_OK;
|
|
||||||
|
|
||||||
if (instance == NULL || context == NULL)
|
|
||||||
return ARGON2_INCORRECT_PARAMETER;
|
|
||||||
instance->context_ptr = context;
|
|
||||||
|
|
||||||
/* 1. Memory allocation */
|
|
||||||
result = allocate_memory(context, (uint8_t **)&(instance->memory),
|
|
||||||
instance->memory_blocks, sizeof(block));
|
|
||||||
if (result != ARGON2_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. Initial hashing */
|
|
||||||
/* H_0 + 8 extra bytes to produce the first blocks */
|
|
||||||
/* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
|
|
||||||
/* Hashing all inputs */
|
|
||||||
initial_hash(blockhash, context, instance->type);
|
|
||||||
/* Zeroing 8 extra bytes */
|
|
||||||
|
|
||||||
clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
|
|
||||||
ARGON2_PREHASH_SEED_LENGTH -
|
|
||||||
ARGON2_PREHASH_DIGEST_LENGTH);
|
|
||||||
|
|
||||||
/* 3. Creating first blocks, we always have at least two blocks in a slice
|
|
||||||
*/
|
|
||||||
fill_first_blocks(blockhash, instance);
|
|
||||||
/* Clearing the hash */
|
|
||||||
clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
|
|
||||||
|
|
||||||
return ARGON2_OK;
|
|
||||||
}
|
|
@@ -1,229 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ARGON2_CORE_H
|
|
||||||
#define ARGON2_CORE_H
|
|
||||||
|
|
||||||
#include "argon2.h"
|
|
||||||
|
|
||||||
#define CONST_CAST(x) (x)(uintptr_t)
|
|
||||||
|
|
||||||
/**********************Argon2 internal constants*******************************/
|
|
||||||
|
|
||||||
enum argon2_core_constants {
|
|
||||||
/* Version of the algorithm */
|
|
||||||
ARGON2_VERSION_NUMBER = 0x10,
|
|
||||||
/* Memory block size in bytes */
|
|
||||||
ARGON2_BLOCK_SIZE = 1024,
|
|
||||||
ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
|
|
||||||
ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
|
|
||||||
|
|
||||||
/* Number of pseudo-random values generated by one call to Blake in Argon2i
|
|
||||||
to
|
|
||||||
generate reference block positions */
|
|
||||||
ARGON2_ADDRESSES_IN_BLOCK = 128,
|
|
||||||
|
|
||||||
/* Pre-hashing digest length and its extension*/
|
|
||||||
ARGON2_PREHASH_DIGEST_LENGTH = 64,
|
|
||||||
ARGON2_PREHASH_SEED_LENGTH = 72
|
|
||||||
};
|
|
||||||
|
|
||||||
/*************************Argon2 internal data types***********************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure for the (1KB) memory block implemented as 128 64-bit words.
|
|
||||||
* Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
|
|
||||||
* bounds checking).
|
|
||||||
*/
|
|
||||||
typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
|
|
||||||
|
|
||||||
/*****************Functions that work with the block******************/
|
|
||||||
|
|
||||||
/* Initialize each byte of the block with @in */
|
|
||||||
void init_block_value(block *b, uint8_t in);
|
|
||||||
|
|
||||||
/* Copy block @src to block @dst */
|
|
||||||
void copy_block(block *dst, const block *src);
|
|
||||||
|
|
||||||
/* XOR @src onto @dst bytewise */
|
|
||||||
void xor_block(block *dst, const block *src);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Argon2 instance: memory pointer, number of passes, amount of memory, type,
|
|
||||||
* and derived values.
|
|
||||||
* Used to evaluate the number and location of blocks to construct in each
|
|
||||||
* thread
|
|
||||||
*/
|
|
||||||
typedef struct Argon2_instance_t {
|
|
||||||
block *memory; /* Memory pointer */
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t passes; /* Number of passes */
|
|
||||||
uint32_t memory_blocks; /* Number of blocks in memory */
|
|
||||||
uint32_t segment_length;
|
|
||||||
uint32_t lane_length;
|
|
||||||
uint32_t lanes;
|
|
||||||
uint32_t limit;
|
|
||||||
uint32_t threads;
|
|
||||||
argon2_type type;
|
|
||||||
int print_internals; /* whether to print the memory blocks */
|
|
||||||
argon2_context *context_ptr; /* points back to original context */
|
|
||||||
} argon2_instance_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Argon2 position: where we construct the block right now. Used to distribute
|
|
||||||
* work between threads.
|
|
||||||
*/
|
|
||||||
typedef struct Argon2_position_t {
|
|
||||||
uint32_t pass;
|
|
||||||
uint32_t lane;
|
|
||||||
uint8_t slice;
|
|
||||||
uint32_t index;
|
|
||||||
} argon2_position_t;
|
|
||||||
|
|
||||||
/*Struct that holds the inputs for thread handling FillSegment*/
|
|
||||||
typedef struct Argon2_thread_data {
|
|
||||||
argon2_instance_t *instance_ptr;
|
|
||||||
argon2_position_t pos;
|
|
||||||
} argon2_thread_data;
|
|
||||||
|
|
||||||
/*************************Argon2 core functions********************************/
|
|
||||||
|
|
||||||
/* Allocates memory to the given pointer, uses the appropriate allocator as
|
|
||||||
* specified in the context. Total allocated memory is num*size.
|
|
||||||
* @param context argon2_context which specifies the allocator
|
|
||||||
* @param memory pointer to the pointer to the memory
|
|
||||||
* @param size the size in bytes for each element to be allocated
|
|
||||||
* @param num the number of elements to be allocated
|
|
||||||
* @return ARGON2_OK if @memory is a valid pointer and memory is allocated
|
|
||||||
*/
|
|
||||||
int allocate_memory(const argon2_context *context, uint8_t **memory,
|
|
||||||
size_t num, size_t size);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Frees memory at the given pointer, uses the appropriate deallocator as
|
|
||||||
* specified in the context. Also cleans the memory using clear_internal_memory.
|
|
||||||
* @param context argon2_context which specifies the deallocator
|
|
||||||
* @param memory pointer to buffer to be freed
|
|
||||||
* @param size the size in bytes for each element to be deallocated
|
|
||||||
* @param num the number of elements to be deallocated
|
|
||||||
*/
|
|
||||||
void free_memory(const argon2_context *context, uint8_t *memory,
|
|
||||||
size_t num, size_t size);
|
|
||||||
|
|
||||||
/* Function that securely cleans the memory. This ignores any flags set
|
|
||||||
* regarding clearing memory. Usually one just calls clear_internal_memory.
|
|
||||||
* @param mem Pointer to the memory
|
|
||||||
* @param s Memory size in bytes
|
|
||||||
*/
|
|
||||||
void secure_wipe_memory(void *v, size_t n);
|
|
||||||
|
|
||||||
/* Function that securely clears the memory if FLAG_clear_internal_memory is
|
|
||||||
* set. If the flag isn't set, this function does nothing.
|
|
||||||
* @param mem Pointer to the memory
|
|
||||||
* @param s Memory size in bytes
|
|
||||||
*/
|
|
||||||
void clear_internal_memory(void *v, size_t n);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Computes absolute position of reference block in the lane following a skewed
|
|
||||||
* distribution and using a pseudo-random value as input
|
|
||||||
* @param instance Pointer to the current instance
|
|
||||||
* @param position Pointer to the current position
|
|
||||||
* @param pseudo_rand 32-bit pseudo-random value used to determine the position
|
|
||||||
* @param same_lane Indicates if the block will be taken from the current lane.
|
|
||||||
* If so we can reference the current segment
|
|
||||||
* @pre All pointers must be valid
|
|
||||||
*/
|
|
||||||
uint32_t index_alpha(const argon2_instance_t *instance,
|
|
||||||
const argon2_position_t *position, uint32_t pseudo_rand,
|
|
||||||
int same_lane);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function that validates all inputs against predefined restrictions and return
|
|
||||||
* an error code
|
|
||||||
* @param context Pointer to current Argon2 context
|
|
||||||
* @return ARGON2_OK if everything is all right, otherwise one of error codes
|
|
||||||
* (all defined in <argon2.h>
|
|
||||||
*/
|
|
||||||
int validate_inputs(const argon2_context *context);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
|
|
||||||
* password and secret if needed
|
|
||||||
* @param context Pointer to the Argon2 internal structure containing memory
|
|
||||||
* pointer, and parameters for time and space requirements.
|
|
||||||
* @param blockhash Buffer for pre-hashing digest
|
|
||||||
* @param type Argon2 type
|
|
||||||
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
|
|
||||||
* allocated
|
|
||||||
*/
|
|
||||||
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
|
||||||
argon2_type type);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function creates first 2 blocks per lane
|
|
||||||
* @param instance Pointer to the current instance
|
|
||||||
* @param blockhash Pointer to the pre-hashing digest
|
|
||||||
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
|
|
||||||
*/
|
|
||||||
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function allocates memory, hashes the inputs with Blake, and creates first
|
|
||||||
* two blocks. Returns the pointer to the main memory with 2 blocks per lane
|
|
||||||
* initialized
|
|
||||||
* @param context Pointer to the Argon2 internal structure containing memory
|
|
||||||
* pointer, and parameters for time and space requirements.
|
|
||||||
* @param instance Current Argon2 instance
|
|
||||||
* @return Zero if successful, -1 if memory failed to allocate. @context->state
|
|
||||||
* will be modified if successful.
|
|
||||||
*/
|
|
||||||
int initialize(argon2_instance_t *instance, argon2_context *context);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XORing the last block of each lane, hashing it, making the tag. Deallocates
|
|
||||||
* the memory.
|
|
||||||
* @param context Pointer to current Argon2 context (use only the out parameters
|
|
||||||
* from it)
|
|
||||||
* @param instance Pointer to current instance of Argon2
|
|
||||||
* @pre instance->state must point to necessary amount of memory
|
|
||||||
* @pre context->out must point to outlen bytes of memory
|
|
||||||
* @pre if context->free_cbk is not NULL, it should point to a function that
|
|
||||||
* deallocates memory
|
|
||||||
*/
|
|
||||||
void finalize(const argon2_context *context, argon2_instance_t *instance);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function that fills the segment using previous segments also from other
|
|
||||||
* threads
|
|
||||||
* @param context current context
|
|
||||||
* @param instance Pointer to the current instance
|
|
||||||
* @param position Current position
|
|
||||||
* @pre all block pointers must be valid
|
|
||||||
*/
|
|
||||||
void fill_segment(const argon2_instance_t *instance,
|
|
||||||
argon2_position_t position);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function that fills the entire memory t_cost times based on the first two
|
|
||||||
* blocks in each lane
|
|
||||||
* @param instance Pointer to the current instance
|
|
||||||
* @return ARGON2_OK if successful, @context->state
|
|
||||||
*/
|
|
||||||
int fill_memory_blocks(argon2_instance_t *instance);
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,456 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include "encoding.h"
|
|
||||||
#include "core.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Example code for a decoder and encoder of "hash strings", with Argon2
|
|
||||||
* parameters.
|
|
||||||
*
|
|
||||||
* This code comprises three sections:
|
|
||||||
*
|
|
||||||
* -- The first section contains generic Base64 encoding and decoding
|
|
||||||
* functions. It is conceptually applicable to any hash function
|
|
||||||
* implementation that uses Base64 to encode and decode parameters,
|
|
||||||
* salts and outputs. It could be made into a library, provided that
|
|
||||||
* the relevant functions are made public (non-static) and be given
|
|
||||||
* reasonable names to avoid collisions with other functions.
|
|
||||||
*
|
|
||||||
* -- The second section is specific to Argon2. It encodes and decodes
|
|
||||||
* the parameters, salts and outputs. It does not compute the hash
|
|
||||||
* itself.
|
|
||||||
*
|
|
||||||
* The code was originally written by Thomas Pornin <pornin@bolet.org>,
|
|
||||||
* to whom comments and remarks may be sent. It is released under what
|
|
||||||
* should amount to Public Domain or its closest equivalent; the
|
|
||||||
* following mantra is supposed to incarnate that fact with all the
|
|
||||||
* proper legal rituals:
|
|
||||||
*
|
|
||||||
* ---------------------------------------------------------------------
|
|
||||||
* This file is provided under the terms of Creative Commons CC0 1.0
|
|
||||||
* Public Domain Dedication. To the extent possible under law, the
|
|
||||||
* author (Thomas Pornin) has waived all copyright and related or
|
|
||||||
* neighboring rights to this file. This work is published from: Canada.
|
|
||||||
* ---------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Thomas Pornin
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ==================================================================== */
|
|
||||||
/*
|
|
||||||
* Common code; could be shared between different hash functions.
|
|
||||||
*
|
|
||||||
* Note: the Base64 functions below assume that uppercase letters (resp.
|
|
||||||
* lowercase letters) have consecutive numerical codes, that fit on 8
|
|
||||||
* bits. All modern systems use ASCII-compatible charsets, where these
|
|
||||||
* properties are true. If you are stuck with a dinosaur of a system
|
|
||||||
* that still defaults to EBCDIC then you already have much bigger
|
|
||||||
* interoperability issues to deal with.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some macros for constant-time comparisons. These work over values in
|
|
||||||
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
|
|
||||||
*/
|
|
||||||
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
|
|
||||||
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
|
|
||||||
#define GE(x, y) (GT(y, x) ^ 0xFF)
|
|
||||||
#define LT(x, y) GT(y, x)
|
|
||||||
#define LE(x, y) GE(y, x)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert value x (0..63) to corresponding Base64 character.
|
|
||||||
*/
|
|
||||||
static int b64_byte_to_char(unsigned x) {
|
|
||||||
return (LT(x, 26) & (x + 'A')) |
|
|
||||||
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
|
|
||||||
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
|
|
||||||
(EQ(x, 63) & '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert character c to the corresponding 6-bit value. If character c
|
|
||||||
* is not a Base64 character, then 0xFF (255) is returned.
|
|
||||||
*/
|
|
||||||
static unsigned b64_char_to_byte(int c) {
|
|
||||||
unsigned x;
|
|
||||||
|
|
||||||
x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
|
|
||||||
(GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
|
|
||||||
(GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
|
|
||||||
(EQ(c, '/') & 63);
|
|
||||||
return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert some bytes to Base64. 'dst_len' is the length (in characters)
|
|
||||||
* of the output buffer 'dst'; if that buffer is not large enough to
|
|
||||||
* receive the result (including the terminating 0), then (size_t)-1
|
|
||||||
* is returned. Otherwise, the zero-terminated Base64 string is written
|
|
||||||
* in the buffer, and the output length (counted WITHOUT the terminating
|
|
||||||
* zero) is returned.
|
|
||||||
*/
|
|
||||||
static size_t to_base64(char *dst, size_t dst_len, const void *src,
|
|
||||||
size_t src_len) {
|
|
||||||
size_t olen;
|
|
||||||
const unsigned char *buf;
|
|
||||||
unsigned acc, acc_len;
|
|
||||||
|
|
||||||
olen = (src_len / 3) << 2;
|
|
||||||
switch (src_len % 3) {
|
|
||||||
case 2:
|
|
||||||
olen++;
|
|
||||||
/* fall through */
|
|
||||||
case 1:
|
|
||||||
olen += 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (dst_len <= olen) {
|
|
||||||
return (size_t)-1;
|
|
||||||
}
|
|
||||||
acc = 0;
|
|
||||||
acc_len = 0;
|
|
||||||
buf = (const unsigned char *)src;
|
|
||||||
while (src_len-- > 0) {
|
|
||||||
acc = (acc << 8) + (*buf++);
|
|
||||||
acc_len += 8;
|
|
||||||
while (acc_len >= 6) {
|
|
||||||
acc_len -= 6;
|
|
||||||
*dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (acc_len > 0) {
|
|
||||||
*dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
|
|
||||||
}
|
|
||||||
*dst++ = 0;
|
|
||||||
return olen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Decode Base64 chars into bytes. The '*dst_len' value must initially
|
|
||||||
* contain the length of the output buffer '*dst'; when the decoding
|
|
||||||
* ends, the actual number of decoded bytes is written back in
|
|
||||||
* '*dst_len'.
|
|
||||||
*
|
|
||||||
* Decoding stops when a non-Base64 character is encountered, or when
|
|
||||||
* the output buffer capacity is exceeded. If an error occurred (output
|
|
||||||
* buffer is too small, invalid last characters leading to unprocessed
|
|
||||||
* buffered bits), then NULL is returned; otherwise, the returned value
|
|
||||||
* points to the first non-Base64 character in the source stream, which
|
|
||||||
* may be the terminating zero.
|
|
||||||
*/
|
|
||||||
static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
|
|
||||||
size_t len;
|
|
||||||
unsigned char *buf;
|
|
||||||
unsigned acc, acc_len;
|
|
||||||
|
|
||||||
buf = (unsigned char *)dst;
|
|
||||||
len = 0;
|
|
||||||
acc = 0;
|
|
||||||
acc_len = 0;
|
|
||||||
for (;;) {
|
|
||||||
unsigned d;
|
|
||||||
|
|
||||||
d = b64_char_to_byte(*src);
|
|
||||||
if (d == 0xFF) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
src++;
|
|
||||||
acc = (acc << 6) + d;
|
|
||||||
acc_len += 6;
|
|
||||||
if (acc_len >= 8) {
|
|
||||||
acc_len -= 8;
|
|
||||||
if ((len++) >= *dst_len) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*buf++ = (acc >> acc_len) & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the input length is equal to 1 modulo 4 (which is
|
|
||||||
* invalid), then there will remain 6 unprocessed bits;
|
|
||||||
* otherwise, only 0, 2 or 4 bits are buffered. The buffered
|
|
||||||
* bits must also all be zero.
|
|
||||||
*/
|
|
||||||
if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*dst_len = len;
|
|
||||||
return src;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Decode decimal integer from 'str'; the value is written in '*v'.
|
|
||||||
* Returned value is a pointer to the next non-decimal character in the
|
|
||||||
* string. If there is no digit at all, or the value encoding is not
|
|
||||||
* minimal (extra leading zeros), or the value does not fit in an
|
|
||||||
* 'unsigned long', then NULL is returned.
|
|
||||||
*/
|
|
||||||
static const char *decode_decimal(const char *str, unsigned long *v) {
|
|
||||||
const char *orig;
|
|
||||||
unsigned long acc;
|
|
||||||
|
|
||||||
acc = 0;
|
|
||||||
for (orig = str;; str++) {
|
|
||||||
int c;
|
|
||||||
|
|
||||||
c = *str;
|
|
||||||
if (c < '0' || c > '9') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
c -= '0';
|
|
||||||
if (acc > (ULONG_MAX / 10)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
acc *= 10;
|
|
||||||
if ((unsigned long)c > (ULONG_MAX - acc)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
acc += (unsigned long)c;
|
|
||||||
}
|
|
||||||
if (str == orig || (*orig == '0' && str != (orig + 1))) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*v = acc;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ==================================================================== */
|
|
||||||
/*
|
|
||||||
* Code specific to Argon2.
|
|
||||||
*
|
|
||||||
* The code below applies the following format:
|
|
||||||
*
|
|
||||||
* $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
|
|
||||||
*
|
|
||||||
* where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
|
|
||||||
* fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
|
|
||||||
* characters, no newline or whitespace).
|
|
||||||
*
|
|
||||||
* The last two binary chunks (encoded in Base64) are, in that order,
|
|
||||||
* the salt and the output. Both are required. The binary salt length and the
|
|
||||||
* output length must be in the allowed ranges defined in argon2.h.
|
|
||||||
*
|
|
||||||
* The ctx struct must contain buffers large enough to hold the salt and pwd
|
|
||||||
* when it is fed into decode_string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
|
|
||||||
|
|
||||||
/* check for prefix */
|
|
||||||
#define CC(prefix) \
|
|
||||||
do { \
|
|
||||||
size_t cc_len = strlen(prefix); \
|
|
||||||
if (strncmp(str, prefix, cc_len) != 0) { \
|
|
||||||
return ARGON2_DECODING_FAIL; \
|
|
||||||
} \
|
|
||||||
str += cc_len; \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
/* optional prefix checking with supplied code */
|
|
||||||
#define CC_opt(prefix, code) \
|
|
||||||
do { \
|
|
||||||
size_t cc_len = strlen(prefix); \
|
|
||||||
if (strncmp(str, prefix, cc_len) == 0) { \
|
|
||||||
str += cc_len; \
|
|
||||||
{ code; } \
|
|
||||||
} \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
/* Decoding prefix into decimal */
|
|
||||||
#define DECIMAL(x) \
|
|
||||||
do { \
|
|
||||||
unsigned long dec_x; \
|
|
||||||
str = decode_decimal(str, &dec_x); \
|
|
||||||
if (str == NULL) { \
|
|
||||||
return ARGON2_DECODING_FAIL; \
|
|
||||||
} \
|
|
||||||
(x) = dec_x; \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
|
|
||||||
/* Decoding prefix into uint32_t decimal */
|
|
||||||
#define DECIMAL_U32(x) \
|
|
||||||
do { \
|
|
||||||
unsigned long dec_x; \
|
|
||||||
str = decode_decimal(str, &dec_x); \
|
|
||||||
if (str == NULL || dec_x > UINT32_MAX) { \
|
|
||||||
return ARGON2_DECODING_FAIL; \
|
|
||||||
} \
|
|
||||||
(x) = (uint32_t)dec_x; \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
|
|
||||||
/* Decoding base64 into a binary buffer */
|
|
||||||
#define BIN(buf, max_len, len) \
|
|
||||||
do { \
|
|
||||||
size_t bin_len = (max_len); \
|
|
||||||
str = from_base64(buf, &bin_len, str); \
|
|
||||||
if (str == NULL || bin_len > UINT32_MAX) { \
|
|
||||||
return ARGON2_DECODING_FAIL; \
|
|
||||||
} \
|
|
||||||
(len) = (uint32_t)bin_len; \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
size_t maxsaltlen = ctx->saltlen;
|
|
||||||
size_t maxoutlen = ctx->outlen;
|
|
||||||
int validation_result;
|
|
||||||
const char* type_string;
|
|
||||||
|
|
||||||
/* We should start with the argon2_type we are using */
|
|
||||||
type_string = argon2_type2string(type, 0);
|
|
||||||
if (!type_string) {
|
|
||||||
return ARGON2_INCORRECT_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CC("$");
|
|
||||||
CC(type_string);
|
|
||||||
|
|
||||||
CC("$m=");
|
|
||||||
DECIMAL_U32(ctx->m_cost);
|
|
||||||
CC(",t=");
|
|
||||||
DECIMAL_U32(ctx->t_cost);
|
|
||||||
CC(",p=");
|
|
||||||
DECIMAL_U32(ctx->lanes);
|
|
||||||
ctx->threads = ctx->lanes;
|
|
||||||
|
|
||||||
CC("$");
|
|
||||||
BIN(ctx->salt, maxsaltlen, ctx->saltlen);
|
|
||||||
CC("$");
|
|
||||||
BIN(ctx->out, maxoutlen, ctx->outlen);
|
|
||||||
|
|
||||||
/* The rest of the fields get the default values */
|
|
||||||
ctx->secret = NULL;
|
|
||||||
ctx->secretlen = 0;
|
|
||||||
ctx->ad = NULL;
|
|
||||||
ctx->adlen = 0;
|
|
||||||
ctx->allocate_cbk = NULL;
|
|
||||||
ctx->free_cbk = NULL;
|
|
||||||
ctx->flags = ARGON2_DEFAULT_FLAGS;
|
|
||||||
|
|
||||||
/* On return, must have valid context */
|
|
||||||
validation_result = validate_inputs(ctx);
|
|
||||||
if (validation_result != ARGON2_OK) {
|
|
||||||
return validation_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Can't have any additional characters */
|
|
||||||
if (*str == 0) {
|
|
||||||
return ARGON2_OK;
|
|
||||||
} else {
|
|
||||||
return ARGON2_DECODING_FAIL;
|
|
||||||
}
|
|
||||||
#undef CC
|
|
||||||
#undef CC_opt
|
|
||||||
#undef DECIMAL
|
|
||||||
#undef BIN
|
|
||||||
}
|
|
||||||
|
|
||||||
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
|
||||||
argon2_type type) {
|
|
||||||
#define SS(str) \
|
|
||||||
do { \
|
|
||||||
size_t pp_len = strlen(str); \
|
|
||||||
if (pp_len >= dst_len) { \
|
|
||||||
return ARGON2_ENCODING_FAIL; \
|
|
||||||
} \
|
|
||||||
memcpy(dst, str, pp_len + 1); \
|
|
||||||
dst += pp_len; \
|
|
||||||
dst_len -= pp_len; \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#define SX(x) \
|
|
||||||
do { \
|
|
||||||
char tmp[30]; \
|
|
||||||
sprintf(tmp, "%lu", (unsigned long)(x)); \
|
|
||||||
SS(tmp); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#define SB(buf, len) \
|
|
||||||
do { \
|
|
||||||
size_t sb_len = to_base64(dst, dst_len, buf, len); \
|
|
||||||
if (sb_len == (size_t)-1) { \
|
|
||||||
return ARGON2_ENCODING_FAIL; \
|
|
||||||
} \
|
|
||||||
dst += sb_len; \
|
|
||||||
dst_len -= sb_len; \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
const char* type_string = argon2_type2string(type, 0);
|
|
||||||
int validation_result = validate_inputs(ctx);
|
|
||||||
|
|
||||||
if (!type_string) {
|
|
||||||
return ARGON2_ENCODING_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validation_result != ARGON2_OK) {
|
|
||||||
return validation_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SS("$");
|
|
||||||
SS(type_string);
|
|
||||||
|
|
||||||
SS("$m=");
|
|
||||||
SX(ctx->m_cost);
|
|
||||||
SS(",t=");
|
|
||||||
SX(ctx->t_cost);
|
|
||||||
SS(",p=");
|
|
||||||
SX(ctx->lanes);
|
|
||||||
|
|
||||||
SS("$");
|
|
||||||
SB(ctx->salt, ctx->saltlen);
|
|
||||||
|
|
||||||
SS("$");
|
|
||||||
SB(ctx->out, ctx->outlen);
|
|
||||||
return ARGON2_OK;
|
|
||||||
|
|
||||||
#undef SS
|
|
||||||
#undef SX
|
|
||||||
#undef SB
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t b64len(uint32_t len) {
|
|
||||||
size_t olen = ((size_t)len / 3) << 2;
|
|
||||||
|
|
||||||
switch (len % 3) {
|
|
||||||
case 2:
|
|
||||||
olen++;
|
|
||||||
/* fall through */
|
|
||||||
case 1:
|
|
||||||
olen += 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return olen;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t numlen(uint32_t num) {
|
|
||||||
size_t len = 1;
|
|
||||||
while (num >= 10) {
|
|
||||||
++len;
|
|
||||||
num = num / 10;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ENCODING_H
|
|
||||||
#define ENCODING_H
|
|
||||||
#include "argon2.h"
|
|
||||||
|
|
||||||
#define ARGON2_MAX_DECODED_LANES UINT32_C(255)
|
|
||||||
#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
|
|
||||||
#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* encode an Argon2 hash string into the provided buffer. 'dst_len'
|
|
||||||
* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
|
|
||||||
* is less than the number of required characters (including the
|
|
||||||
* terminating 0), then this function returns ARGON2_ENCODING_ERROR.
|
|
||||||
*
|
|
||||||
* on success, ARGON2_OK is returned.
|
|
||||||
*/
|
|
||||||
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
|
||||||
argon2_type type);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Decodes an Argon2 hash string into the provided structure 'ctx'.
|
|
||||||
* The only fields that must be set prior to this call are ctx.saltlen and
|
|
||||||
* ctx.outlen (which must be the maximal salt and out length values that are
|
|
||||||
* allowed), ctx.salt and ctx.out (which must be buffers of the specified
|
|
||||||
* length), and ctx.pwd and ctx.pwdlen which must hold a valid password.
|
|
||||||
*
|
|
||||||
* Invalid input string causes an error. On success, the ctx is valid and all
|
|
||||||
* fields have been initialized.
|
|
||||||
*
|
|
||||||
* Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
|
|
||||||
*/
|
|
||||||
int decode_string(argon2_context *ctx, const char *str, argon2_type type);
|
|
||||||
|
|
||||||
/* Returns the length of the encoded byte stream with length len */
|
|
||||||
size_t b64len(uint32_t len);
|
|
||||||
|
|
||||||
/* Returns the length of the encoded number num */
|
|
||||||
size_t numlen(uint32_t num);
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,172 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "argon2.h"
|
|
||||||
#include "core.h"
|
|
||||||
|
|
||||||
#include "../blake2/blake2.h"
|
|
||||||
#include "../blake2/blamka-round-opt.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Function fills a new memory block and optionally XORs the old block over the new one.
|
|
||||||
* Memory must be initialized.
|
|
||||||
* @param state Pointer to the just produced block. Content will be updated(!)
|
|
||||||
* @param ref_block Pointer to the reference block
|
|
||||||
* @param next_block Pointer to the block to be XORed over. May coincide with @ref_block
|
|
||||||
* @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
|
|
||||||
* @pre all block pointers must be valid
|
|
||||||
*/
|
|
||||||
static void fill_block(__m128i *state, const block *ref_block,
|
|
||||||
block *next_block, int with_xor) {
|
|
||||||
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (with_xor) {
|
|
||||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
|
||||||
state[i] = _mm_xor_si128(
|
|
||||||
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
|
|
||||||
block_XY[i] = _mm_xor_si128(
|
|
||||||
state[i], _mm_loadu_si128((const __m128i *)next_block->v + i));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
|
||||||
block_XY[i] = state[i] = _mm_xor_si128(
|
|
||||||
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
|
|
||||||
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
|
|
||||||
state[8 * i + 6], state[8 * i + 7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
|
|
||||||
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
|
|
||||||
state[8 * 6 + i], state[8 * 7 + i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
|
||||||
state[i] = _mm_xor_si128(state[i], block_XY[i]);
|
|
||||||
_mm_storeu_si128((__m128i *)next_block->v + i, state[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void next_addresses(block *address_block, block *input_block) {
|
|
||||||
/*Temporary zero-initialized blocks*/
|
|
||||||
__m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
|
|
||||||
__m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
|
|
||||||
|
|
||||||
memset(zero_block, 0, sizeof(zero_block));
|
|
||||||
memset(zero2_block, 0, sizeof(zero2_block));
|
|
||||||
|
|
||||||
/*Increasing index counter*/
|
|
||||||
input_block->v[6]++;
|
|
||||||
|
|
||||||
/*First iteration of G*/
|
|
||||||
fill_block(zero_block, input_block, address_block, 0);
|
|
||||||
|
|
||||||
/*Second iteration of G*/
|
|
||||||
fill_block(zero2_block, address_block, address_block, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill_segment(const argon2_instance_t *instance,
|
|
||||||
argon2_position_t position) {
|
|
||||||
block *ref_block = NULL, *curr_block = NULL;
|
|
||||||
block address_block, input_block;
|
|
||||||
uint64_t pseudo_rand, ref_index, ref_lane;
|
|
||||||
uint32_t prev_offset, curr_offset;
|
|
||||||
uint32_t starting_index, i;
|
|
||||||
__m128i state[64];
|
|
||||||
int data_independent_addressing;
|
|
||||||
|
|
||||||
if (instance == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
starting_index = 0;
|
|
||||||
|
|
||||||
if ((0 == position.pass) && (0 == position.slice)) {
|
|
||||||
starting_index = 2; /* we have already generated the first two blocks */
|
|
||||||
|
|
||||||
/* Don't forget to generate the first block of addresses: */
|
|
||||||
if (data_independent_addressing) {
|
|
||||||
next_addresses(&address_block, &input_block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Offset of the current block */
|
|
||||||
curr_offset = position.lane * instance->lane_length +
|
|
||||||
position.slice * instance->segment_length + starting_index;
|
|
||||||
|
|
||||||
if (0 == curr_offset % instance->lane_length) {
|
|
||||||
/* Last block in this lane */
|
|
||||||
prev_offset = curr_offset + instance->lane_length - 1;
|
|
||||||
} else {
|
|
||||||
/* Previous block */
|
|
||||||
prev_offset = curr_offset - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
|
|
||||||
|
|
||||||
for (i = starting_index; i < instance->segment_length;
|
|
||||||
++i, ++curr_offset, ++prev_offset) {
|
|
||||||
/*1.1 Rotating prev_offset if needed */
|
|
||||||
if (curr_offset % instance->lane_length == 1) {
|
|
||||||
prev_offset = curr_offset - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1.2 Computing the index of the reference block */
|
|
||||||
/* 1.2.1 Taking pseudo-random value from the previous block */
|
|
||||||
if (data_independent_addressing) {
|
|
||||||
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
|
|
||||||
next_addresses(&address_block, &input_block);
|
|
||||||
}
|
|
||||||
pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
|
|
||||||
} else {
|
|
||||||
pseudo_rand = instance->memory[prev_offset].v[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1.2.2 Computing the lane of the reference block */
|
|
||||||
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
|
|
||||||
|
|
||||||
if ((position.pass == 0) && (position.slice == 0)) {
|
|
||||||
/* Can not reference other lanes yet */
|
|
||||||
ref_lane = position.lane;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1.2.3 Computing the number of possible reference block within the
|
|
||||||
* lane.
|
|
||||||
*/
|
|
||||||
position.index = i;
|
|
||||||
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
|
|
||||||
ref_lane == position.lane);
|
|
||||||
|
|
||||||
/* 2 Creating a new block */
|
|
||||||
ref_block =
|
|
||||||
instance->memory + instance->lane_length * ref_lane + ref_index;
|
|
||||||
curr_block = instance->memory + curr_offset;
|
|
||||||
|
|
||||||
fill_block(state, ref_block, curr_block, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(ARGON2_NO_THREADS)
|
|
||||||
|
|
||||||
#include "thread.h"
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int argon2_thread_create(argon2_thread_handle_t *handle,
|
|
||||||
argon2_thread_func_t func, void *args) {
|
|
||||||
if (NULL == handle || func == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#if defined(_WIN32)
|
|
||||||
*handle = _beginthreadex(NULL, 0, func, args, 0, NULL);
|
|
||||||
return *handle != 0 ? 0 : -1;
|
|
||||||
#else
|
|
||||||
return pthread_create(handle, NULL, func, args);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int argon2_thread_join(argon2_thread_handle_t handle) {
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) {
|
|
||||||
return CloseHandle((HANDLE)handle) != 0 ? 0 : -1;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
#else
|
|
||||||
return pthread_join(handle, NULL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void argon2_thread_exit(void) {
|
|
||||||
#if defined(_WIN32)
|
|
||||||
_endthreadex(0);
|
|
||||||
#else
|
|
||||||
pthread_exit(NULL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ARGON2_NO_THREADS */
|
|
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ARGON2_THREAD_H
|
|
||||||
#define ARGON2_THREAD_H
|
|
||||||
|
|
||||||
#if !defined(ARGON2_NO_THREADS)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Here we implement an abstraction layer for the simpĺe requirements
|
|
||||||
of the Argon2 code. We only require 3 primitives---thread creation,
|
|
||||||
joining, and termination---so full emulation of the pthreads API
|
|
||||||
is unwarranted. Currently we wrap pthreads and Win32 threads.
|
|
||||||
|
|
||||||
The API defines 2 types: the function pointer type,
|
|
||||||
argon2_thread_func_t,
|
|
||||||
and the type of the thread handle---argon2_thread_handle_t.
|
|
||||||
*/
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <process.h>
|
|
||||||
typedef unsigned(__stdcall *argon2_thread_func_t)(void *);
|
|
||||||
typedef uintptr_t argon2_thread_handle_t;
|
|
||||||
#else
|
|
||||||
#include <pthread.h>
|
|
||||||
typedef void *(*argon2_thread_func_t)(void *);
|
|
||||||
typedef pthread_t argon2_thread_handle_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Creates a thread
|
|
||||||
* @param handle pointer to a thread handle, which is the output of this
|
|
||||||
* function. Must not be NULL.
|
|
||||||
* @param func A function pointer for the thread's entry point. Must not be
|
|
||||||
* NULL.
|
|
||||||
* @param args Pointer that is passed as an argument to @func. May be NULL.
|
|
||||||
* @return 0 if @handle and @func are valid pointers and a thread is successfuly
|
|
||||||
* created.
|
|
||||||
*/
|
|
||||||
int argon2_thread_create(argon2_thread_handle_t *handle,
|
|
||||||
argon2_thread_func_t func, void *args);
|
|
||||||
|
|
||||||
/* Waits for a thread to terminate
|
|
||||||
* @param handle Handle to a thread created with argon2_thread_create.
|
|
||||||
* @return 0 if @handle is a valid handle, and joining completed successfully.
|
|
||||||
*/
|
|
||||||
int argon2_thread_join(argon2_thread_handle_t handle);
|
|
||||||
|
|
||||||
/* Terminate the current thread. Must be run inside a thread created by
|
|
||||||
* argon2_thread_create.
|
|
||||||
*/
|
|
||||||
void argon2_thread_exit(void);
|
|
||||||
|
|
||||||
#endif /* ARGON2_NO_THREADS */
|
|
||||||
#endif
|
|
@@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PORTABLE_BLAKE2_IMPL_H
|
|
||||||
#define PORTABLE_BLAKE2_IMPL_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define BLAKE2_INLINE __inline
|
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
|
||||||
#define BLAKE2_INLINE __inline__
|
|
||||||
#else
|
|
||||||
#define BLAKE2_INLINE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Argon2 Team - Begin Code */
|
|
||||||
/*
|
|
||||||
Not an exhaustive list, but should cover the majority of modern platforms
|
|
||||||
Additionally, the code will always be correct---this is only a performance
|
|
||||||
tweak.
|
|
||||||
*/
|
|
||||||
#if (defined(__BYTE_ORDER__) && \
|
|
||||||
(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \
|
|
||||||
defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \
|
|
||||||
defined(__AARCH64EL__) || defined(__amd64__) || defined(__i386__) || \
|
|
||||||
defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || \
|
|
||||||
defined(_M_ARM)
|
|
||||||
#define NATIVE_LITTLE_ENDIAN
|
|
||||||
#endif
|
|
||||||
/* Argon2 Team - End Code */
|
|
||||||
|
|
||||||
static BLAKE2_INLINE uint32_t load32(const void *src) {
|
|
||||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
|
||||||
uint32_t w;
|
|
||||||
memcpy(&w, src, sizeof w);
|
|
||||||
return w;
|
|
||||||
#else
|
|
||||||
const uint8_t *p = (const uint8_t *)src;
|
|
||||||
uint32_t w = *p++;
|
|
||||||
w |= (uint32_t)(*p++) << 8;
|
|
||||||
w |= (uint32_t)(*p++) << 16;
|
|
||||||
w |= (uint32_t)(*p++) << 24;
|
|
||||||
return w;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE uint64_t load64(const void *src) {
|
|
||||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
|
||||||
uint64_t w;
|
|
||||||
memcpy(&w, src, sizeof w);
|
|
||||||
return w;
|
|
||||||
#else
|
|
||||||
const uint8_t *p = (const uint8_t *)src;
|
|
||||||
uint64_t w = *p++;
|
|
||||||
w |= (uint64_t)(*p++) << 8;
|
|
||||||
w |= (uint64_t)(*p++) << 16;
|
|
||||||
w |= (uint64_t)(*p++) << 24;
|
|
||||||
w |= (uint64_t)(*p++) << 32;
|
|
||||||
w |= (uint64_t)(*p++) << 40;
|
|
||||||
w |= (uint64_t)(*p++) << 48;
|
|
||||||
w |= (uint64_t)(*p++) << 56;
|
|
||||||
return w;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE void store32(void *dst, uint32_t w) {
|
|
||||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
|
||||||
memcpy(dst, &w, sizeof w);
|
|
||||||
#else
|
|
||||||
uint8_t *p = (uint8_t *)dst;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE void store64(void *dst, uint64_t w) {
|
|
||||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
|
||||||
memcpy(dst, &w, sizeof w);
|
|
||||||
#else
|
|
||||||
uint8_t *p = (uint8_t *)dst;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE uint64_t load48(const void *src) {
|
|
||||||
const uint8_t *p = (const uint8_t *)src;
|
|
||||||
uint64_t w = *p++;
|
|
||||||
w |= (uint64_t)(*p++) << 8;
|
|
||||||
w |= (uint64_t)(*p++) << 16;
|
|
||||||
w |= (uint64_t)(*p++) << 24;
|
|
||||||
w |= (uint64_t)(*p++) << 32;
|
|
||||||
w |= (uint64_t)(*p++) << 40;
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE void store48(void *dst, uint64_t w) {
|
|
||||||
uint8_t *p = (uint8_t *)dst;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
w >>= 8;
|
|
||||||
*p++ = (uint8_t)w;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) {
|
|
||||||
return (w >> c) | (w << (32 - c));
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) {
|
|
||||||
return (w >> c) | (w << (64 - c));
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_internal_memory(void *v, size_t n);
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PORTABLE_BLAKE2_H
|
|
||||||
#define PORTABLE_BLAKE2_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum blake2b_constant {
|
|
||||||
BLAKE2B_BLOCKBYTES = 128,
|
|
||||||
BLAKE2B_OUTBYTES = 64,
|
|
||||||
BLAKE2B_KEYBYTES = 64,
|
|
||||||
BLAKE2B_SALTBYTES = 16,
|
|
||||||
BLAKE2B_PERSONALBYTES = 16
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
typedef struct __blake2b_param {
|
|
||||||
uint8_t digest_length; /* 1 */
|
|
||||||
uint8_t key_length; /* 2 */
|
|
||||||
uint8_t fanout; /* 3 */
|
|
||||||
uint8_t depth; /* 4 */
|
|
||||||
uint32_t leaf_length; /* 8 */
|
|
||||||
uint64_t node_offset; /* 16 */
|
|
||||||
uint8_t node_depth; /* 17 */
|
|
||||||
uint8_t inner_length; /* 18 */
|
|
||||||
uint8_t reserved[14]; /* 32 */
|
|
||||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
|
||||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
|
||||||
} blake2b_param;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
typedef struct __blake2b_state {
|
|
||||||
uint64_t h[8];
|
|
||||||
uint64_t t[2];
|
|
||||||
uint64_t f[2];
|
|
||||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
|
||||||
unsigned buflen;
|
|
||||||
unsigned outlen;
|
|
||||||
uint8_t last_node;
|
|
||||||
} blake2b_state;
|
|
||||||
|
|
||||||
/* Ensure param structs have not been wrongly padded */
|
|
||||||
/* Poor man's static_assert */
|
|
||||||
enum {
|
|
||||||
blake2_size_check_0 = 1 / !!(CHAR_BIT == 8),
|
|
||||||
blake2_size_check_2 =
|
|
||||||
1 / !!(sizeof(blake2b_param) == sizeof(uint64_t) * CHAR_BIT)
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Streaming API */
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Simple API */
|
|
||||||
int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
|
|
||||||
const void *key, size_t keylen);
|
|
||||||
|
|
||||||
/* Argon2 Team - Begin Code */
|
|
||||||
int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);
|
|
||||||
/* Argon2 Team - End Code */
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,390 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "blake2.h"
|
|
||||||
#include "blake2-impl.h"
|
|
||||||
|
|
||||||
static const uint64_t blake2b_IV[8] = {
|
|
||||||
UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
|
|
||||||
UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
|
|
||||||
UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
|
|
||||||
UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)};
|
|
||||||
|
|
||||||
static const unsigned int blake2b_sigma[12][16] = {
|
|
||||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
|
||||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
|
||||||
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
|
|
||||||
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
|
|
||||||
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
|
|
||||||
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
|
|
||||||
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
|
|
||||||
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
|
|
||||||
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
|
|
||||||
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
|
|
||||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
|
||||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
|
||||||
};
|
|
||||||
|
|
||||||
static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) {
|
|
||||||
S->f[1] = (uint64_t)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) {
|
|
||||||
if (S->last_node) {
|
|
||||||
blake2b_set_lastnode(S);
|
|
||||||
}
|
|
||||||
S->f[0] = (uint64_t)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S,
|
|
||||||
uint64_t inc) {
|
|
||||||
S->t[0] += inc;
|
|
||||||
S->t[1] += (S->t[0] < inc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) {
|
|
||||||
clear_internal_memory(S, sizeof(*S)); /* wipe */
|
|
||||||
blake2b_set_lastblock(S); /* invalidate for further use */
|
|
||||||
}
|
|
||||||
|
|
||||||
static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) {
|
|
||||||
memset(S, 0, sizeof(*S));
|
|
||||||
memcpy(S->h, blake2b_IV, sizeof(S->h));
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
|
|
||||||
const unsigned char *p = (const unsigned char *)P;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (NULL == P || NULL == S) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
blake2b_init0(S);
|
|
||||||
/* IV XOR Parameter Block */
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
S->h[i] ^= load64(&p[i * sizeof(S->h[i])]);
|
|
||||||
}
|
|
||||||
S->outlen = P->digest_length;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sequential blake2b initialization */
|
|
||||||
int blake2b_init(blake2b_state *S, size_t outlen) {
|
|
||||||
blake2b_param P;
|
|
||||||
|
|
||||||
if (S == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
|
|
||||||
blake2b_invalidate_state(S);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup Parameter Block for unkeyed BLAKE2 */
|
|
||||||
P.digest_length = (uint8_t)outlen;
|
|
||||||
P.key_length = 0;
|
|
||||||
P.fanout = 1;
|
|
||||||
P.depth = 1;
|
|
||||||
P.leaf_length = 0;
|
|
||||||
P.node_offset = 0;
|
|
||||||
P.node_depth = 0;
|
|
||||||
P.inner_length = 0;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
|
|
||||||
size_t keylen) {
|
|
||||||
blake2b_param P;
|
|
||||||
|
|
||||||
if (S == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
|
|
||||||
blake2b_invalidate_state(S);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) {
|
|
||||||
blake2b_invalidate_state(S);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup Parameter Block for keyed BLAKE2 */
|
|
||||||
P.digest_length = (uint8_t)outlen;
|
|
||||||
P.key_length = (uint8_t)keylen;
|
|
||||||
P.fanout = 1;
|
|
||||||
P.depth = 1;
|
|
||||||
P.leaf_length = 0;
|
|
||||||
P.node_offset = 0;
|
|
||||||
P.node_depth = 0;
|
|
||||||
P.inner_length = 0;
|
|
||||||
memset(P.reserved, 0, sizeof(P.reserved));
|
|
||||||
memset(P.salt, 0, sizeof(P.salt));
|
|
||||||
memset(P.personal, 0, sizeof(P.personal));
|
|
||||||
|
|
||||||
if (blake2b_init_param(S, &P) < 0) {
|
|
||||||
blake2b_invalidate_state(S);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
|
||||||
memset(block, 0, BLAKE2B_BLOCKBYTES);
|
|
||||||
memcpy(block, key, keylen);
|
|
||||||
blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
|
|
||||||
/* Burn the key from stack */
|
|
||||||
clear_internal_memory(block, BLAKE2B_BLOCKBYTES);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void blake2b_compress(blake2b_state *S, const uint8_t *block) {
|
|
||||||
uint64_t m[16];
|
|
||||||
uint64_t v[16];
|
|
||||||
unsigned int i, r;
|
|
||||||
|
|
||||||
for (i = 0; i < 16; ++i) {
|
|
||||||
m[i] = load64(block + i * sizeof(m[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
v[i] = S->h[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
v[8] = blake2b_IV[0];
|
|
||||||
v[9] = blake2b_IV[1];
|
|
||||||
v[10] = blake2b_IV[2];
|
|
||||||
v[11] = blake2b_IV[3];
|
|
||||||
v[12] = blake2b_IV[4] ^ S->t[0];
|
|
||||||
v[13] = blake2b_IV[5] ^ S->t[1];
|
|
||||||
v[14] = blake2b_IV[6] ^ S->f[0];
|
|
||||||
v[15] = blake2b_IV[7] ^ S->f[1];
|
|
||||||
|
|
||||||
#define G(r, i, a, b, c, d) \
|
|
||||||
do { \
|
|
||||||
a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
|
|
||||||
d = rotr64(d ^ a, 32); \
|
|
||||||
c = c + d; \
|
|
||||||
b = rotr64(b ^ c, 24); \
|
|
||||||
a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
|
|
||||||
d = rotr64(d ^ a, 16); \
|
|
||||||
c = c + d; \
|
|
||||||
b = rotr64(b ^ c, 63); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#define ROUND(r) \
|
|
||||||
do { \
|
|
||||||
G(r, 0, v[0], v[4], v[8], v[12]); \
|
|
||||||
G(r, 1, v[1], v[5], v[9], v[13]); \
|
|
||||||
G(r, 2, v[2], v[6], v[10], v[14]); \
|
|
||||||
G(r, 3, v[3], v[7], v[11], v[15]); \
|
|
||||||
G(r, 4, v[0], v[5], v[10], v[15]); \
|
|
||||||
G(r, 5, v[1], v[6], v[11], v[12]); \
|
|
||||||
G(r, 6, v[2], v[7], v[8], v[13]); \
|
|
||||||
G(r, 7, v[3], v[4], v[9], v[14]); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
for (r = 0; r < 12; ++r) {
|
|
||||||
ROUND(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef G
|
|
||||||
#undef ROUND
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
|
|
||||||
const uint8_t *pin = (const uint8_t *)in;
|
|
||||||
|
|
||||||
if (inlen == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sanity check */
|
|
||||||
if (S == NULL || in == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is this a reused state? */
|
|
||||||
if (S->f[0] != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) {
|
|
||||||
/* Complete current block */
|
|
||||||
size_t left = S->buflen;
|
|
||||||
size_t fill = BLAKE2B_BLOCKBYTES - left;
|
|
||||||
memcpy(&S->buf[left], pin, fill);
|
|
||||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
|
||||||
blake2b_compress(S, S->buf);
|
|
||||||
S->buflen = 0;
|
|
||||||
inlen -= fill;
|
|
||||||
pin += fill;
|
|
||||||
/* Avoid buffer copies when possible */
|
|
||||||
while (inlen > BLAKE2B_BLOCKBYTES) {
|
|
||||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
|
||||||
blake2b_compress(S, pin);
|
|
||||||
inlen -= BLAKE2B_BLOCKBYTES;
|
|
||||||
pin += BLAKE2B_BLOCKBYTES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memcpy(&S->buf[S->buflen], pin, inlen);
|
|
||||||
S->buflen += (unsigned int)inlen;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
|
|
||||||
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* Sanity checks */
|
|
||||||
if (S == NULL || out == NULL || outlen < S->outlen) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is this a reused state? */
|
|
||||||
if (S->f[0] != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
blake2b_increment_counter(S, S->buflen);
|
|
||||||
blake2b_set_lastblock(S);
|
|
||||||
memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
|
|
||||||
blake2b_compress(S, S->buf);
|
|
||||||
|
|
||||||
for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
|
|
||||||
store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(out, buffer, S->outlen);
|
|
||||||
clear_internal_memory(buffer, sizeof(buffer));
|
|
||||||
clear_internal_memory(S->buf, sizeof(S->buf));
|
|
||||||
clear_internal_memory(S->h, sizeof(S->h));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
|
|
||||||
const void *key, size_t keylen) {
|
|
||||||
blake2b_state S;
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
/* Verify parameters */
|
|
||||||
if (NULL == in && inlen > 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keylen > 0) {
|
|
||||||
if (blake2b_init_key(&S, outlen, key, keylen) < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (blake2b_init(&S, outlen) < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blake2b_update(&S, in, inlen) < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
ret = blake2b_final(&S, out, outlen);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
clear_internal_memory(&S, sizeof(S));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Argon2 Team - Begin Code */
|
|
||||||
int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
|
|
||||||
uint8_t *out = (uint8_t *)pout;
|
|
||||||
blake2b_state blake_state;
|
|
||||||
uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
if (outlen > UINT32_MAX) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure little-endian byte order! */
|
|
||||||
store32(outlen_bytes, (uint32_t)outlen);
|
|
||||||
|
|
||||||
#define TRY(statement) \
|
|
||||||
do { \
|
|
||||||
ret = statement; \
|
|
||||||
if (ret < 0) { \
|
|
||||||
goto fail; \
|
|
||||||
} \
|
|
||||||
} 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));
|
|
||||||
} 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));
|
|
||||||
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,
|
|
||||||
BLAKE2B_OUTBYTES, NULL, 0));
|
|
||||||
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
|
|
||||||
out += BLAKE2B_OUTBYTES / 2;
|
|
||||||
toproduce -= BLAKE2B_OUTBYTES / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
|
|
||||||
TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
|
|
||||||
0));
|
|
||||||
memcpy(out, out_buffer, toproduce);
|
|
||||||
}
|
|
||||||
fail:
|
|
||||||
clear_internal_memory(&blake_state, sizeof(blake_state));
|
|
||||||
return ret;
|
|
||||||
#undef TRY
|
|
||||||
}
|
|
||||||
/* Argon2 Team - End Code */
|
|
@@ -1,180 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BLAKE_ROUND_MKA_OPT_H
|
|
||||||
#define BLAKE_ROUND_MKA_OPT_H
|
|
||||||
|
|
||||||
#include "blake2-impl.h"
|
|
||||||
|
|
||||||
#include <emmintrin.h>
|
|
||||||
#if defined(__SSSE3__)
|
|
||||||
#include <tmmintrin.h> /* for _mm_shuffle_epi8 and _mm_alignr_epi8 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__))
|
|
||||||
#include <x86intrin.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__XOP__)
|
|
||||||
#if defined(__SSSE3__)
|
|
||||||
#define r16 \
|
|
||||||
(_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
|
|
||||||
#define r24 \
|
|
||||||
(_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
|
|
||||||
#define _mm_roti_epi64(x, c) \
|
|
||||||
(-(c) == 32) \
|
|
||||||
? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
|
|
||||||
: (-(c) == 24) \
|
|
||||||
? _mm_shuffle_epi8((x), r24) \
|
|
||||||
: (-(c) == 16) \
|
|
||||||
? _mm_shuffle_epi8((x), r16) \
|
|
||||||
: (-(c) == 63) \
|
|
||||||
? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
|
|
||||||
_mm_add_epi64((x), (x))) \
|
|
||||||
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
|
|
||||||
_mm_slli_epi64((x), 64 - (-(c))))
|
|
||||||
#else /* defined(__SSE2__) */
|
|
||||||
#define _mm_roti_epi64(r, c) \
|
|
||||||
_mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c))))
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) {
|
|
||||||
const __m128i z = _mm_mul_epu32(x, y);
|
|
||||||
return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
|
|
||||||
do { \
|
|
||||||
A0 = fBlaMka(A0, B0); \
|
|
||||||
A1 = fBlaMka(A1, B1); \
|
|
||||||
\
|
|
||||||
D0 = _mm_xor_si128(D0, A0); \
|
|
||||||
D1 = _mm_xor_si128(D1, A1); \
|
|
||||||
\
|
|
||||||
D0 = _mm_roti_epi64(D0, -32); \
|
|
||||||
D1 = _mm_roti_epi64(D1, -32); \
|
|
||||||
\
|
|
||||||
C0 = fBlaMka(C0, D0); \
|
|
||||||
C1 = fBlaMka(C1, D1); \
|
|
||||||
\
|
|
||||||
B0 = _mm_xor_si128(B0, C0); \
|
|
||||||
B1 = _mm_xor_si128(B1, C1); \
|
|
||||||
\
|
|
||||||
B0 = _mm_roti_epi64(B0, -24); \
|
|
||||||
B1 = _mm_roti_epi64(B1, -24); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
|
|
||||||
do { \
|
|
||||||
A0 = fBlaMka(A0, B0); \
|
|
||||||
A1 = fBlaMka(A1, B1); \
|
|
||||||
\
|
|
||||||
D0 = _mm_xor_si128(D0, A0); \
|
|
||||||
D1 = _mm_xor_si128(D1, A1); \
|
|
||||||
\
|
|
||||||
D0 = _mm_roti_epi64(D0, -16); \
|
|
||||||
D1 = _mm_roti_epi64(D1, -16); \
|
|
||||||
\
|
|
||||||
C0 = fBlaMka(C0, D0); \
|
|
||||||
C1 = fBlaMka(C1, D1); \
|
|
||||||
\
|
|
||||||
B0 = _mm_xor_si128(B0, C0); \
|
|
||||||
B1 = _mm_xor_si128(B1, C1); \
|
|
||||||
\
|
|
||||||
B0 = _mm_roti_epi64(B0, -63); \
|
|
||||||
B1 = _mm_roti_epi64(B1, -63); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#if defined(__SSSE3__)
|
|
||||||
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
|
||||||
do { \
|
|
||||||
__m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
|
|
||||||
__m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
|
|
||||||
B0 = t0; \
|
|
||||||
B1 = t1; \
|
|
||||||
\
|
|
||||||
t0 = C0; \
|
|
||||||
C0 = C1; \
|
|
||||||
C1 = t0; \
|
|
||||||
\
|
|
||||||
t0 = _mm_alignr_epi8(D1, D0, 8); \
|
|
||||||
t1 = _mm_alignr_epi8(D0, D1, 8); \
|
|
||||||
D0 = t1; \
|
|
||||||
D1 = t0; \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
|
||||||
do { \
|
|
||||||
__m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
|
|
||||||
__m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
|
|
||||||
B0 = t0; \
|
|
||||||
B1 = t1; \
|
|
||||||
\
|
|
||||||
t0 = C0; \
|
|
||||||
C0 = C1; \
|
|
||||||
C1 = t0; \
|
|
||||||
\
|
|
||||||
t0 = _mm_alignr_epi8(D0, D1, 8); \
|
|
||||||
t1 = _mm_alignr_epi8(D1, D0, 8); \
|
|
||||||
D0 = t1; \
|
|
||||||
D1 = t0; \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
#else /* SSE2 */
|
|
||||||
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
|
||||||
do { \
|
|
||||||
__m128i t0 = D0; \
|
|
||||||
__m128i t1 = B0; \
|
|
||||||
D0 = C0; \
|
|
||||||
C0 = C1; \
|
|
||||||
C1 = D0; \
|
|
||||||
D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \
|
|
||||||
D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \
|
|
||||||
B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \
|
|
||||||
B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
|
||||||
do { \
|
|
||||||
__m128i t0, t1; \
|
|
||||||
t0 = C0; \
|
|
||||||
C0 = C1; \
|
|
||||||
C1 = t0; \
|
|
||||||
t0 = B0; \
|
|
||||||
t1 = D0; \
|
|
||||||
B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \
|
|
||||||
B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \
|
|
||||||
D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \
|
|
||||||
D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
|
|
||||||
do { \
|
|
||||||
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
|
|
||||||
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
|
|
||||||
\
|
|
||||||
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
|
|
||||||
\
|
|
||||||
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
|
|
||||||
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
|
|
||||||
\
|
|
||||||
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Argon2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Copyright 2015
|
|
||||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
|
||||||
*
|
|
||||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
|
||||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
|
||||||
* these licenses can be found at:
|
|
||||||
*
|
|
||||||
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
||||||
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* You should have received a copy of both of these licenses along with this
|
|
||||||
* software. If not, they may be obtained at the above URLs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BLAKE_ROUND_MKA_H
|
|
||||||
#define BLAKE_ROUND_MKA_H
|
|
||||||
|
|
||||||
#include "blake2.h"
|
|
||||||
#include "blake2-impl.h"
|
|
||||||
|
|
||||||
/*designed by the Lyra PHC team */
|
|
||||||
static BLAKE2_INLINE uint64_t fBlaMka(uint64_t x, uint64_t y) {
|
|
||||||
const uint64_t m = UINT64_C(0xFFFFFFFF);
|
|
||||||
const uint64_t xy = (x & m) * (y & m);
|
|
||||||
return x + y + 2 * xy;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define G(a, b, c, d) \
|
|
||||||
do { \
|
|
||||||
a = fBlaMka(a, b); \
|
|
||||||
d = rotr64(d ^ a, 32); \
|
|
||||||
c = fBlaMka(c, d); \
|
|
||||||
b = rotr64(b ^ c, 24); \
|
|
||||||
a = fBlaMka(a, b); \
|
|
||||||
d = rotr64(d ^ a, 16); \
|
|
||||||
c = fBlaMka(c, d); \
|
|
||||||
b = rotr64(b ^ c, 63); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
|
|
||||||
v12, v13, v14, v15) \
|
|
||||||
do { \
|
|
||||||
G(v0, v4, v8, v12); \
|
|
||||||
G(v1, v5, v9, v13); \
|
|
||||||
G(v2, v6, v10, v14); \
|
|
||||||
G(v3, v7, v11, v15); \
|
|
||||||
G(v0, v5, v10, v15); \
|
|
||||||
G(v1, v6, v11, v12); \
|
|
||||||
G(v2, v7, v8, v13); \
|
|
||||||
G(v3, v4, v9, v14); \
|
|
||||||
} while ((void)0, 0)
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "miner.h"
|
||||||
#include "algo-gate-api.h"
|
#include "algo-gate-api.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -5,11 +6,11 @@
|
|||||||
|
|
||||||
#include "algo/shabal/sph_shabal.h"
|
#include "algo/shabal/sph_shabal.h"
|
||||||
|
|
||||||
static __thread uint32_t _ALIGN(64) M[65536][8];
|
static __thread uint32_t _ALIGN(128) M[65536][8];
|
||||||
|
|
||||||
void axiomhash(void *output, const void *input)
|
void axiomhash(void *output, const void *input)
|
||||||
{
|
{
|
||||||
sph_shabal256_context ctx __attribute__ ((aligned (64)));
|
sph_shabal256_context ctx;
|
||||||
const int N = 65536;
|
const int N = 65536;
|
||||||
|
|
||||||
sph_shabal256_init(&ctx);
|
sph_shabal256_init(&ctx);
|
||||||
@@ -33,7 +34,7 @@ void axiomhash(void *output, const void *input)
|
|||||||
sph_shabal256(&ctx, M[p], 32);
|
sph_shabal256(&ctx, M[p], 32);
|
||||||
sph_shabal256(&ctx, M[j], 32);
|
sph_shabal256(&ctx, M[j], 32);
|
||||||
#else
|
#else
|
||||||
uint8_t _ALIGN(64) hash[64];
|
uint8_t _ALIGN(128) hash[64];
|
||||||
memcpy(hash, M[p], 32);
|
memcpy(hash, M[p], 32);
|
||||||
memcpy(&hash[32], M[j], 32);
|
memcpy(&hash[32], M[j], 32);
|
||||||
sph_shabal256(&ctx, hash, 64);
|
sph_shabal256(&ctx, hash, 64);
|
||||||
@@ -48,8 +49,8 @@ int scanhash_axiom(int thr_id, struct work *work,
|
|||||||
{
|
{
|
||||||
uint32_t *pdata = work->data;
|
uint32_t *pdata = work->data;
|
||||||
uint32_t *ptarget = work->target;
|
uint32_t *ptarget = work->target;
|
||||||
uint32_t _ALIGN(64) hash64[8];
|
uint32_t _ALIGN(128) hash64[8];
|
||||||
uint32_t _ALIGN(64) endiandata[20];
|
uint32_t _ALIGN(128) endiandata[20];
|
||||||
|
|
||||||
const uint32_t Htarg = ptarget[7];
|
const uint32_t Htarg = ptarget[7];
|
||||||
const uint32_t first_nonce = pdata[19];
|
const uint32_t first_nonce = pdata[19];
|
||||||
@@ -65,7 +66,6 @@ int scanhash_axiom(int thr_id, struct work *work,
|
|||||||
if (hash64[7] < Htarg && fulltest(hash64, ptarget)) {
|
if (hash64[7] < Htarg && fulltest(hash64, ptarget)) {
|
||||||
*hashes_done = n - first_nonce + 1;
|
*hashes_done = n - first_nonce + 1;
|
||||||
pdata[19] = n;
|
pdata[19] = n;
|
||||||
work_set_target_ratio( work, hash64 );
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
n++;
|
n++;
|
||||||
@@ -82,6 +82,7 @@ bool register_axiom_algo( algo_gate_t* gate )
|
|||||||
{
|
{
|
||||||
gate->scanhash = (void*)&scanhash_axiom;
|
gate->scanhash = (void*)&scanhash_axiom;
|
||||||
gate->hash = (void*)&axiomhash;
|
gate->hash = (void*)&axiomhash;
|
||||||
|
gate->hash_alt = (void*)&axiomhash;
|
||||||
gate->get_max64 = (void*)&get_max64_0x40LL;
|
gate->get_max64 = (void*)&get_max64_0x40LL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
203
algo/blake/b/sia-rpc.cpp
Normal file
203
algo/blake/b/sia-rpc.cpp
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
#include <ccminer-config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <miner.h>
|
||||||
|
|
||||||
|
#include "sia-rpc.h"
|
||||||
|
|
||||||
|
static bool sia_debug_diff = false;
|
||||||
|
|
||||||
|
extern int share_result(int result, int pooln, double sharediff, const char *reason);
|
||||||
|
|
||||||
|
/* compute nbits to get the network diff */
|
||||||
|
static void calc_network_diff(struct work *work)
|
||||||
|
{
|
||||||
|
uint32_t nbits = work->data[11]; // unsure if correct
|
||||||
|
uint32_t bits = (nbits & 0xffffff);
|
||||||
|
int16_t shift = (swab32(nbits) & 0xff); // 0x1c = 28
|
||||||
|
|
||||||
|
uint64_t diffone = 0x0000FFFF00000000ull;
|
||||||
|
double d = (double)0x0000ffff / (double)bits;
|
||||||
|
|
||||||
|
for (int m=shift; m < 29; m++) d *= 256.0;
|
||||||
|
for (int m=29; m < shift; m++) d /= 256.0;
|
||||||
|
if (sia_debug_diff)
|
||||||
|
applog(LOG_DEBUG, "net diff: %f -> shift %u, bits %08x", d, shift, bits);
|
||||||
|
|
||||||
|
net_diff = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- SIA LONGPOLL --------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct data_buffer {
|
||||||
|
void *buf;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t sia_data_cb(const void *ptr, size_t size, size_t nmemb,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct data_buffer *db = (struct data_buffer *)user_data;
|
||||||
|
size_t len = size * nmemb;
|
||||||
|
size_t oldlen, newlen;
|
||||||
|
void *newmem;
|
||||||
|
static const uchar zero = 0;
|
||||||
|
|
||||||
|
oldlen = db->len;
|
||||||
|
newlen = oldlen + len;
|
||||||
|
|
||||||
|
newmem = realloc(db->buf, newlen + 1);
|
||||||
|
if (!newmem)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
db->buf = newmem;
|
||||||
|
db->len = newlen;
|
||||||
|
memcpy((char*)db->buf + oldlen, ptr, len);
|
||||||
|
memcpy((char*)db->buf + newlen, &zero, 1); /* null terminate */
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* sia_getheader(CURL *curl, struct pool_infos *pool)
|
||||||
|
{
|
||||||
|
char curl_err_str[CURL_ERROR_SIZE] = { 0 };
|
||||||
|
struct data_buffer all_data = { 0 };
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
char data[256] = { 0 };
|
||||||
|
char url[512];
|
||||||
|
|
||||||
|
// nanopool
|
||||||
|
snprintf(url, 512, "%s/miner/header?address=%s&worker=%s", //&longpoll
|
||||||
|
pool->url, pool->user, pool->pass);
|
||||||
|
|
||||||
|
if (opt_protocol)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, opt_timeout);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, sia_data_cb);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
|
||||||
|
|
||||||
|
headers = curl_slist_append(headers, "Accept: application/octet-stream");
|
||||||
|
headers = curl_slist_append(headers, "Expect:"); // disable Expect hdr
|
||||||
|
headers = curl_slist_append(headers, "User-Agent: Sia-Agent"); // required for now
|
||||||
|
// headers = curl_slist_append(headers, "User-Agent: " USER_AGENT);
|
||||||
|
// headers = curl_slist_append(headers, "X-Mining-Extensions: longpoll");
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
|
int rc = curl_easy_perform(curl);
|
||||||
|
if (rc && strlen(curl_err_str)) {
|
||||||
|
applog(LOG_WARNING, "%s", curl_err_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_data.len >= 112)
|
||||||
|
cbin2hex(data, (const char*) all_data.buf, 112);
|
||||||
|
if (opt_protocol || all_data.len != 112)
|
||||||
|
applog(LOG_DEBUG, "received %d bytes: %s", (int) all_data.len, data);
|
||||||
|
|
||||||
|
curl_slist_free_all(headers);
|
||||||
|
|
||||||
|
return rc == 0 && all_data.len ? strdup(data) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sia_work_decode(const char *hexdata, struct work *work)
|
||||||
|
{
|
||||||
|
uint8_t target[32];
|
||||||
|
if (!work) return false;
|
||||||
|
|
||||||
|
hex2bin((uchar*)target, &hexdata[0], 32);
|
||||||
|
swab256(work->target, target);
|
||||||
|
work->targetdiff = target_to_diff(work->target);
|
||||||
|
|
||||||
|
hex2bin((uchar*)work->data, &hexdata[64], 80);
|
||||||
|
// high 16 bits of the 64 bits nonce
|
||||||
|
work->data[9] = rand() << 16;
|
||||||
|
|
||||||
|
// use work ntime as job id
|
||||||
|
cbin2hex(work->job_id, (const char*)&work->data[10], 4);
|
||||||
|
calc_network_diff(work);
|
||||||
|
|
||||||
|
if (stratum_diff != work->targetdiff) {
|
||||||
|
stratum_diff = work->targetdiff;
|
||||||
|
applog(LOG_WARNING, "Pool diff set to %g", stratum_diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sia_submit(CURL *curl, struct pool_infos *pool, struct work *work)
|
||||||
|
{
|
||||||
|
char curl_err_str[CURL_ERROR_SIZE] = { 0 };
|
||||||
|
struct data_buffer all_data = { 0 };
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
char buf[256] = { 0 };
|
||||||
|
char url[512];
|
||||||
|
|
||||||
|
if (opt_protocol)
|
||||||
|
applog_hex(work->data, 80);
|
||||||
|
//applog_hex(&work->data[8], 16);
|
||||||
|
//applog_hex(&work->data[10], 4);
|
||||||
|
|
||||||
|
// nanopool
|
||||||
|
snprintf(url, 512, "%s/miner/header?address=%s&worker=%s",
|
||||||
|
pool->url, pool->user, pool->pass);
|
||||||
|
|
||||||
|
if (opt_protocol)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, sia_data_cb);
|
||||||
|
|
||||||
|
memcpy(buf, work->data, 80);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 80);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*) buf);
|
||||||
|
|
||||||
|
// headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
|
||||||
|
// headers = curl_slist_append(headers, "Content-Length: 80");
|
||||||
|
headers = curl_slist_append(headers, "Accept:"); // disable Accept hdr
|
||||||
|
headers = curl_slist_append(headers, "Expect:"); // disable Expect hdr
|
||||||
|
headers = curl_slist_append(headers, "User-Agent: Sia-Agent");
|
||||||
|
// headers = curl_slist_append(headers, "User-Agent: " USER_AGENT);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
|
int res = curl_easy_perform(curl) == 0;
|
||||||
|
long errcode;
|
||||||
|
CURLcode c = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &errcode);
|
||||||
|
if (errcode != 204) {
|
||||||
|
if (strlen(curl_err_str))
|
||||||
|
applog(LOG_ERR, "submit err %ld %s", errcode, curl_err_str);
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
share_result(res, work->pooln, work->sharediff[0], res ? NULL : (char*) all_data.buf);
|
||||||
|
|
||||||
|
curl_slist_free_all(headers);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- END SIA LONGPOLL ----------------------------------------------------------------------------
|
6
algo/blake/b/sia-rpc.h
Normal file
6
algo/blake/b/sia-rpc.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include <miner.h>
|
||||||
|
|
||||||
|
char* sia_getheader(CURL *curl, struct pool_infos *pool);
|
||||||
|
bool sia_work_decode(const char *hexdata, struct work *work);
|
||||||
|
bool sia_submit(CURL *curl, struct pool_infos *pool, struct work *work);
|
||||||
|
|
@@ -1,144 +0,0 @@
|
|||||||
#include "blake-gate.h"
|
|
||||||
#include "blake-hash-4way.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
#if defined (BLAKE_4WAY)
|
|
||||||
|
|
||||||
blake256r14_4way_context blake_4w_ctx;
|
|
||||||
|
|
||||||
void blakehash_4way(void *state, const void *input)
|
|
||||||
{
|
|
||||||
uint32_t vhash[8*4] __attribute__ ((aligned (64)));
|
|
||||||
blake256r14_4way_context ctx;
|
|
||||||
memcpy( &ctx, &blake_4w_ctx, sizeof ctx );
|
|
||||||
blake256r14_4way( &ctx, input + (64<<2), 16 );
|
|
||||||
blake256r14_4way_close( &ctx, vhash );
|
|
||||||
mm_deinterleave_4x32( state, state+32, state+64, state+96, vhash, 256 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_blake_4way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t vdata[20*4] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t hash[8*4] __attribute__ ((aligned (32)));
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
uint32_t HTarget = ptarget[7];
|
|
||||||
uint32_t _ALIGN(32) edata[20];
|
|
||||||
uint32_t n = first_nonce;
|
|
||||||
uint32_t *nonces = work->nonces;
|
|
||||||
int num_found = 0;
|
|
||||||
|
|
||||||
if (opt_benchmark)
|
|
||||||
HTarget = 0x7f;
|
|
||||||
|
|
||||||
// we need big endian data...
|
|
||||||
swab32_array( edata, pdata, 20 );
|
|
||||||
mm_interleave_4x32( vdata, edata, edata, edata, edata, 640 );
|
|
||||||
blake256r14_4way_init( &blake_4w_ctx );
|
|
||||||
blake256r14_4way( &blake_4w_ctx, vdata, 64 );
|
|
||||||
|
|
||||||
uint32_t *noncep = vdata + 76; // 19*4
|
|
||||||
do {
|
|
||||||
be32enc( noncep, n );
|
|
||||||
be32enc( noncep +1, n+1 );
|
|
||||||
be32enc( noncep +2, n+2 );
|
|
||||||
be32enc( noncep +3, n+3 );
|
|
||||||
|
|
||||||
blakehash_4way( hash, vdata );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 4; i++ )
|
|
||||||
if ( (hash+(i<<3))[7] <= HTarget && fulltest( hash+(i<<3), ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[19] = n+i;
|
|
||||||
nonces[ num_found++ ] = n+i;
|
|
||||||
work_set_target_ratio( work, hash+(i<<3) );
|
|
||||||
}
|
|
||||||
n += 4;
|
|
||||||
|
|
||||||
} while ( (num_found == 0) && (n < max_nonce)
|
|
||||||
&& !work_restart[thr_id].restart );
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return num_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(BLAKE_8WAY)
|
|
||||||
|
|
||||||
blake256r14_8way_context blake_8w_ctx;
|
|
||||||
|
|
||||||
void blakehash_8way( void *state, const void *input )
|
|
||||||
{
|
|
||||||
uint32_t vhash[8*8] __attribute__ ((aligned (64)));
|
|
||||||
blake256r14_8way_context ctx;
|
|
||||||
memcpy( &ctx, &blake_8w_ctx, sizeof ctx );
|
|
||||||
blake256r14_8way( &ctx, input + (64<<3), 16 );
|
|
||||||
blake256r14_8way_close( &ctx, vhash );
|
|
||||||
mm256_deinterleave_8x32( state, state+ 32, state+ 64, state+ 96,
|
|
||||||
state+128, state+160, state+192, state+224,
|
|
||||||
vhash, 256 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_blake_8way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t vdata[20*8] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t hash[8*8] __attribute__ ((aligned (32)));
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
uint32_t HTarget = ptarget[7];
|
|
||||||
uint32_t _ALIGN(32) edata[20];
|
|
||||||
uint32_t n = first_nonce;
|
|
||||||
uint32_t *nonces = work->nonces;
|
|
||||||
int num_found = 0;
|
|
||||||
|
|
||||||
if (opt_benchmark)
|
|
||||||
HTarget = 0x7f;
|
|
||||||
|
|
||||||
// we need big endian data...
|
|
||||||
swab32_array( edata, pdata, 20 );
|
|
||||||
|
|
||||||
mm256_interleave_8x32( vdata, edata, edata, edata, edata,
|
|
||||||
edata, edata, edata, edata, 640 );
|
|
||||||
|
|
||||||
blake256r14_8way_init( &blake_8w_ctx );
|
|
||||||
blake256r14_8way( &blake_8w_ctx, vdata, 64 );
|
|
||||||
|
|
||||||
uint32_t *noncep = vdata + 152; // 19*8
|
|
||||||
do {
|
|
||||||
be32enc( noncep, n );
|
|
||||||
be32enc( noncep +1, n+1 );
|
|
||||||
be32enc( noncep +2, n+2 );
|
|
||||||
be32enc( noncep +3, n+3 );
|
|
||||||
be32enc( noncep +4, n+4 );
|
|
||||||
be32enc( noncep +5, n+5 );
|
|
||||||
be32enc( noncep +6, n+6 );
|
|
||||||
be32enc( noncep +7, n+7 );
|
|
||||||
pdata[19] = n;
|
|
||||||
|
|
||||||
blakehash_8way( hash, vdata );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 8; i++ )
|
|
||||||
if ( (hash+i)[7] <= HTarget && fulltest( hash+i, ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[19] = n+i;
|
|
||||||
num_found++;
|
|
||||||
nonces[i] = n+i;
|
|
||||||
work_set_target_ratio( work, hash+1 );
|
|
||||||
}
|
|
||||||
n += 8;
|
|
||||||
|
|
||||||
} while ( (num_found == 0) && (n < max_nonce)
|
|
||||||
&& !work_restart[thr_id].restart );
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return num_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,26 +0,0 @@
|
|||||||
#include "blake-gate.h"
|
|
||||||
|
|
||||||
int64_t blake_get_max64 ()
|
|
||||||
{
|
|
||||||
return 0x7ffffLL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool register_blake_algo( algo_gate_t* gate )
|
|
||||||
{
|
|
||||||
gate->optimizations = AVX2_OPT;
|
|
||||||
gate->get_max64 = (void*)&blake_get_max64;
|
|
||||||
//#if defined (__AVX2__) && defined (FOUR_WAY)
|
|
||||||
// gate->optimizations = SSE2_OPT | AVX_OPT | AVX2_OPT;
|
|
||||||
// gate->scanhash = (void*)&scanhash_blake_8way;
|
|
||||||
// gate->hash = (void*)&blakehash_8way;
|
|
||||||
#if defined(BLAKE_4WAY)
|
|
||||||
four_way_not_tested();
|
|
||||||
gate->scanhash = (void*)&scanhash_blake_4way;
|
|
||||||
gate->hash = (void*)&blakehash_4way;
|
|
||||||
#else
|
|
||||||
gate->scanhash = (void*)&scanhash_blake;
|
|
||||||
gate->hash = (void*)&blakehash;
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@@ -1,21 +0,0 @@
|
|||||||
#ifndef __BLAKE_GATE_H__
|
|
||||||
#define __BLAKE_GATE_H__
|
|
||||||
|
|
||||||
#include "algo-gate-api.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#if defined(__AVX2__)
|
|
||||||
#define BLAKE_4WAY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (BLAKE_4WAY)
|
|
||||||
void blakehash_4way(void *state, const void *input);
|
|
||||||
int scanhash_blake_4way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void blakehash( void *state, const void *input );
|
|
||||||
int scanhash_blake( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@@ -1,143 +0,0 @@
|
|||||||
/* $Id: sph_blake.h 252 2011-06-07 17:55:14Z tp $ */
|
|
||||||
/**
|
|
||||||
* BLAKE interface. BLAKE is a family of functions which differ by their
|
|
||||||
* output size; this implementation defines BLAKE for output sizes 224,
|
|
||||||
* 256, 384 and 512 bits. This implementation conforms to the "third
|
|
||||||
* round" specification.
|
|
||||||
*
|
|
||||||
* ==========================(LICENSE BEGIN)============================
|
|
||||||
*
|
|
||||||
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* ===========================(LICENSE END)=============================
|
|
||||||
*
|
|
||||||
* @file sph_blake.h
|
|
||||||
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __BLAKE_HASH_4WAY__
|
|
||||||
#define __BLAKE_HASH_4WAY__ 1
|
|
||||||
|
|
||||||
#ifdef __SSE4_2__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "algo/sha/sph_types.h"
|
|
||||||
#include "avxdefs.h"
|
|
||||||
|
|
||||||
#define SPH_SIZE_blake256 256
|
|
||||||
|
|
||||||
#define SPH_SIZE_blake512 512
|
|
||||||
|
|
||||||
// With SSE4.2 only Blake-256 4 way is available.
|
|
||||||
// With AVX2 Blake-256 8way & Blake-512 4 way are also available.
|
|
||||||
|
|
||||||
// Blake-256 4 way
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__m128i buf[16] __attribute__ ((aligned (64)));
|
|
||||||
__m128i H[8];
|
|
||||||
__m128i S[4];
|
|
||||||
size_t ptr;
|
|
||||||
sph_u32 T0, T1;
|
|
||||||
int rounds; // 14 for blake, 8 for blakecoin & vanilla
|
|
||||||
} blake_4way_small_context;
|
|
||||||
|
|
||||||
// Default 14 rounds
|
|
||||||
typedef blake_4way_small_context blake256_4way_context;
|
|
||||||
void blake256_4way_init(void *cc);
|
|
||||||
void blake256_4way(void *cc, const void *data, size_t len);
|
|
||||||
void blake256_4way_close(void *cc, void *dst);
|
|
||||||
|
|
||||||
// 14 rounds, blake, decred
|
|
||||||
typedef blake_4way_small_context blake256r14_4way_context;
|
|
||||||
void blake256r14_4way_init(void *cc);
|
|
||||||
void blake256r14_4way(void *cc, const void *data, size_t len);
|
|
||||||
void blake256r14_4way_close(void *cc, void *dst);
|
|
||||||
|
|
||||||
// 8 rounds, blakecoin, vanilla
|
|
||||||
typedef blake_4way_small_context blake256r8_4way_context;
|
|
||||||
void blake256r8_4way_init(void *cc);
|
|
||||||
void blake256r8_4way(void *cc, const void *data, size_t len);
|
|
||||||
void blake256r8_4way_close(void *cc, void *dst);
|
|
||||||
|
|
||||||
#ifdef __AVX2__
|
|
||||||
|
|
||||||
// Blake-256 8 way
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__m256i buf[16] __attribute__ ((aligned (64)));
|
|
||||||
__m256i H[8];
|
|
||||||
__m256i S[4];
|
|
||||||
size_t ptr;
|
|
||||||
sph_u32 T0, T1;
|
|
||||||
int rounds; // 14 for blake, 8 for blakecoin & vanilla
|
|
||||||
} blake_8way_small_context;
|
|
||||||
|
|
||||||
// Default 14 rounds
|
|
||||||
typedef blake_8way_small_context blake256_8way_context;
|
|
||||||
void blake256_8way_init(void *cc);
|
|
||||||
void blake256_8way(void *cc, const void *data, size_t len);
|
|
||||||
void blake256_8way_close(void *cc, void *dst);
|
|
||||||
|
|
||||||
// 14 rounds, blake, decred
|
|
||||||
typedef blake_8way_small_context blake256r14_8way_context;
|
|
||||||
void blake256r14_8way_init(void *cc);
|
|
||||||
void blake256r14_8way(void *cc, const void *data, size_t len);
|
|
||||||
void blake256r14_8way_close(void *cc, void *dst);
|
|
||||||
|
|
||||||
// 8 rounds, blakecoin, vanilla
|
|
||||||
typedef blake_8way_small_context blake256r8_8way_context;
|
|
||||||
void blake256r8_8way_init(void *cc);
|
|
||||||
void blake256r8_8way(void *cc, const void *data, size_t len);
|
|
||||||
void blake256r8_8way_close(void *cc, void *dst);
|
|
||||||
|
|
||||||
// Blake-512 4 way
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__m256i buf[16] __attribute__ ((aligned (64)));
|
|
||||||
__m256i H[8];
|
|
||||||
__m256i S[4];
|
|
||||||
size_t ptr;
|
|
||||||
sph_u64 T0, T1;
|
|
||||||
} blake_4way_big_context;
|
|
||||||
|
|
||||||
typedef blake_4way_big_context blake512_4way_context;
|
|
||||||
|
|
||||||
void blake512_4way_init(void *cc);
|
|
||||||
void blake512_4way(void *cc, const void *data, size_t len);
|
|
||||||
void blake512_4way_close(void *cc, void *dst);
|
|
||||||
void blake512_4way_addbits_and_close(
|
|
||||||
void *cc, unsigned ub, unsigned n, void *dst);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "miner.h"
|
||||||
#include "algo-gate-api.h"
|
#include "algo-gate-api.h"
|
||||||
#include "sph_blake.h"
|
#include "sph_blake.h"
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ void blakehash(void *state, const void *input)
|
|||||||
{
|
{
|
||||||
sph_blake256_context ctx;
|
sph_blake256_context ctx;
|
||||||
|
|
||||||
uint8_t hash[64] __attribute__ ((aligned (32)));
|
uint8_t hash[64];
|
||||||
uint8_t *ending = (uint8_t*) input;
|
uint8_t *ending = (uint8_t*) input;
|
||||||
ending += 64;
|
ending += 64;
|
||||||
|
|
||||||
@@ -89,3 +90,19 @@ int scanhash_blake( int thr_id, struct work *work, uint32_t max_nonce,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// changed to get_max64_0x3fffffLL in cpuminer-multi-decred
|
||||||
|
int64_t blake_get_max64 ()
|
||||||
|
{
|
||||||
|
return 0x7ffffLL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool register_blake_algo( algo_gate_t* gate )
|
||||||
|
{
|
||||||
|
gate->scanhash = (void*)&scanhash_blake;
|
||||||
|
gate->hash = (void*)&blakehash;
|
||||||
|
gate->hash_alt = (void*)&blakehash;
|
||||||
|
gate->get_max64 = (void*)&blake_get_max64;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -3,20 +3,22 @@
|
|||||||
* tpruvot@github 2015-2016
|
* tpruvot@github 2015-2016
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "miner.h"
|
||||||
#include "algo-gate-api.h"
|
#include "algo-gate-api.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "algo/blake/sph_blake2b.h"
|
#include "algo/blake/sph_blake2b.h"
|
||||||
|
|
||||||
//static __thread sph_blake2b_ctx s_midstate;
|
static __thread sph_blake2b_ctx s_midstate;
|
||||||
//static __thread sph_blake2b_ctx s_ctx;
|
static __thread sph_blake2b_ctx s_ctx;
|
||||||
#define MIDLEN 76
|
#define MIDLEN 76
|
||||||
#define A 64
|
#define A 64
|
||||||
|
|
||||||
void blake2b_hash(void *output, const void *input)
|
void blake2b_hash(void *output, const void *input)
|
||||||
{
|
{
|
||||||
uint8_t _ALIGN(A) hash[32];
|
uint8_t _ALIGN(A) hash[32];
|
||||||
sph_blake2b_ctx ctx __attribute__ ((aligned (64)));
|
sph_blake2b_ctx ctx;
|
||||||
|
|
||||||
sph_blake2b_init(&ctx, 32, NULL, 0);
|
sph_blake2b_init(&ctx, 32, NULL, 0);
|
||||||
sph_blake2b_update(&ctx, input, 80);
|
sph_blake2b_update(&ctx, input, 80);
|
||||||
@@ -25,7 +27,6 @@ void blake2b_hash(void *output, const void *input)
|
|||||||
memcpy(output, hash, 32);
|
memcpy(output, hash, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static void blake2b_hash_end(uint32_t *output, const uint32_t *input)
|
static void blake2b_hash_end(uint32_t *output, const uint32_t *input)
|
||||||
{
|
{
|
||||||
s_ctx.outlen = MIDLEN;
|
s_ctx.outlen = MIDLEN;
|
||||||
@@ -33,7 +34,6 @@ static void blake2b_hash_end(uint32_t *output, const uint32_t *input)
|
|||||||
sph_blake2b_update(&s_ctx, (uint8_t*) &input[MIDLEN/4], 80 - MIDLEN);
|
sph_blake2b_update(&s_ctx, (uint8_t*) &input[MIDLEN/4], 80 - MIDLEN);
|
||||||
sph_blake2b_final(&s_ctx, (uint8_t*) output);
|
sph_blake2b_final(&s_ctx, (uint8_t*) output);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
int scanhash_blake2b( int thr_id, struct work *work, uint32_t max_nonce,
|
int scanhash_blake2b( int thr_id, struct work *work, uint32_t max_nonce,
|
||||||
uint64_t *hashes_done )
|
uint64_t *hashes_done )
|
||||||
@@ -44,6 +44,7 @@ int scanhash_blake2b( int thr_id, struct work *work, uint32_t max_nonce,
|
|||||||
uint32_t *ptarget = work->target;
|
uint32_t *ptarget = work->target;
|
||||||
|
|
||||||
const uint32_t Htarg = ptarget[7];
|
const uint32_t Htarg = ptarget[7];
|
||||||
|
// const uint32_t first_nonce = pdata[19];
|
||||||
const uint32_t first_nonce = pdata[8];
|
const uint32_t first_nonce = pdata[8];
|
||||||
|
|
||||||
uint32_t n = first_nonce;
|
uint32_t n = first_nonce;
|
||||||
@@ -58,6 +59,7 @@ int scanhash_blake2b( int thr_id, struct work *work, uint32_t max_nonce,
|
|||||||
//memcpy(&s_ctx, &s_midstate, sizeof(blake2b_ctx));
|
//memcpy(&s_ctx, &s_midstate, sizeof(blake2b_ctx));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
// be32enc(&endiandata[19], n);
|
||||||
be32enc(&endiandata[8], n);
|
be32enc(&endiandata[8], n);
|
||||||
//blake2b_hash_end(vhashcpu, endiandata);
|
//blake2b_hash_end(vhashcpu, endiandata);
|
||||||
blake2b_hash(vhashcpu, endiandata);
|
blake2b_hash(vhashcpu, endiandata);
|
||||||
@@ -65,6 +67,7 @@ int scanhash_blake2b( int thr_id, struct work *work, uint32_t max_nonce,
|
|||||||
if (vhashcpu[7] < Htarg && fulltest(vhashcpu, ptarget)) {
|
if (vhashcpu[7] < Htarg && fulltest(vhashcpu, ptarget)) {
|
||||||
work_set_target_ratio(work, vhashcpu);
|
work_set_target_ratio(work, vhashcpu);
|
||||||
*hashes_done = n - first_nonce + 1;
|
*hashes_done = n - first_nonce + 1;
|
||||||
|
// pdata[19] = n;
|
||||||
pdata[8] = n;
|
pdata[8] = n;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -72,6 +75,7 @@ int scanhash_blake2b( int thr_id, struct work *work, uint32_t max_nonce,
|
|||||||
|
|
||||||
} while (n < max_nonce && !work_restart[thr_id].restart);
|
} while (n < max_nonce && !work_restart[thr_id].restart);
|
||||||
*hashes_done = n - first_nonce + 1;
|
*hashes_done = n - first_nonce + 1;
|
||||||
|
// pdata[19] = n;
|
||||||
pdata[8] = n;
|
pdata[8] = n;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -169,8 +173,8 @@ void blake2b_get_new_work( struct work* work, struct work* g_work, int thr_id,
|
|||||||
uint32_t *nonceptr = algo_gate.get_nonceptr( work->data );
|
uint32_t *nonceptr = algo_gate.get_nonceptr( work->data );
|
||||||
|
|
||||||
if ( memcmp( &work->data[ wkcmp_off ], &g_work->data[ wkcmp_off ], wkcmp_sz )
|
if ( memcmp( &work->data[ wkcmp_off ], &g_work->data[ wkcmp_off ], wkcmp_sz )
|
||||||
&& ( clean_job || ( *nonceptr >= *end_nonce_ptr )
|
&& ( clean_job || ( *nonceptr >= *end_nonce_ptr ) )
|
||||||
|| strcmp( work->job_id, g_work->job_id ) ) )
|
|| strcmp( work->job_id, g_work->job_id ) )
|
||||||
{
|
{
|
||||||
work_free( work );
|
work_free( work );
|
||||||
work_copy( work, g_work );
|
work_copy( work, g_work );
|
||||||
@@ -219,8 +223,6 @@ bool register_blake2b_algo( algo_gate_t* gate )
|
|||||||
gate->hash = (void*)&blake2b_hash;
|
gate->hash = (void*)&blake2b_hash;
|
||||||
gate->calc_network_diff = (void*)&blake2b_calc_network_diff;
|
gate->calc_network_diff = (void*)&blake2b_calc_network_diff;
|
||||||
gate->build_stratum_request = (void*)&blake2b_be_build_stratum_request;
|
gate->build_stratum_request = (void*)&blake2b_be_build_stratum_request;
|
||||||
gate->work_decode = (void*)&std_be_work_decode;
|
|
||||||
gate->submit_getwork_result = (void*)&std_be_submit_getwork_result;
|
|
||||||
gate->build_extraheader = (void*)&blake2b_build_extraheader;
|
gate->build_extraheader = (void*)&blake2b_build_extraheader;
|
||||||
gate->get_new_work = (void*)&blake2b_get_new_work;
|
gate->get_new_work = (void*)&blake2b_get_new_work;
|
||||||
gate->get_max64 = (void*)&blake2b_get_max64;
|
gate->get_max64 = (void*)&blake2b_get_max64;
|
||||||
|
@@ -1,136 +0,0 @@
|
|||||||
#include "blake2s-gate.h"
|
|
||||||
#include "blake2s-hash-4way.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#if defined(BLAKE2S_8WAY)
|
|
||||||
|
|
||||||
static __thread blake2s_8way_state blake2s_8w_ctx;
|
|
||||||
|
|
||||||
void blake2s_8way_hash( void *output, const void *input )
|
|
||||||
{
|
|
||||||
uint32_t vhash[8*8] __attribute__ ((aligned (64)));
|
|
||||||
blake2s_8way_state ctx;
|
|
||||||
memcpy( &ctx, &blake2s_8w_ctx, sizeof ctx );
|
|
||||||
|
|
||||||
blake2s_8way_update( &ctx, input + (64<<3), 16 );
|
|
||||||
blake2s_8way_final( &ctx, vhash, BLAKE2S_OUTBYTES );
|
|
||||||
|
|
||||||
mm256_deinterleave_8x32( output, output+ 32, output+ 64, output+ 96,
|
|
||||||
output+128, output+160, output+192, output+224,
|
|
||||||
vhash, 256 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_blake2s_8way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t vdata[20*8] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t hash[8*8] __attribute__ ((aligned (32)));
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
uint32_t _ALIGN(64) edata[20];
|
|
||||||
const uint32_t Htarg = ptarget[7];
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
uint32_t n = first_nonce;
|
|
||||||
uint32_t *nonces = work->nonces;
|
|
||||||
int num_found = 0;
|
|
||||||
uint32_t *noncep = vdata + 152; // 19*8
|
|
||||||
|
|
||||||
swab32_array( edata, pdata, 20 );
|
|
||||||
mm256_interleave_8x32( vdata, edata, edata, edata, edata,
|
|
||||||
edata, edata, edata, edata, 640 );
|
|
||||||
blake2s_8way_init( &blake2s_8w_ctx, BLAKE2S_OUTBYTES );
|
|
||||||
blake2s_8way_update( &blake2s_8w_ctx, vdata, 64 );
|
|
||||||
|
|
||||||
do {
|
|
||||||
be32enc( noncep, n );
|
|
||||||
be32enc( noncep +1, n+1 );
|
|
||||||
be32enc( noncep +2, n+2 );
|
|
||||||
be32enc( noncep +3, n+3 );
|
|
||||||
be32enc( noncep +4, n+4 );
|
|
||||||
be32enc( noncep +5, n+5 );
|
|
||||||
be32enc( noncep +6, n+6 );
|
|
||||||
be32enc( noncep +7, n+7 );
|
|
||||||
pdata[19] = n;
|
|
||||||
|
|
||||||
blake2s_8way_hash( hash, vdata );
|
|
||||||
|
|
||||||
|
|
||||||
for ( int i = 0; i < 8; i++ )
|
|
||||||
if ( (hash+(i<<3))[7] <= Htarg && fulltest( hash+(i<<3), ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[19] = n+i;
|
|
||||||
nonces[ num_found++ ] = n+i;
|
|
||||||
work_set_target_ratio( work, hash+(i<<3) );
|
|
||||||
}
|
|
||||||
n += 8;
|
|
||||||
|
|
||||||
} while ( (num_found == 0) && (n < max_nonce)
|
|
||||||
&& !work_restart[thr_id].restart );
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return num_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(BLAKE2S_4WAY)
|
|
||||||
|
|
||||||
static __thread blake2s_4way_state blake2s_4w_ctx;
|
|
||||||
|
|
||||||
void blake2s_4way_hash( void *output, const void *input )
|
|
||||||
{
|
|
||||||
uint32_t vhash[8*4] __attribute__ ((aligned (64)));
|
|
||||||
blake2s_4way_state ctx;
|
|
||||||
memcpy( &ctx, &blake2s_4w_ctx, sizeof ctx );
|
|
||||||
|
|
||||||
blake2s_4way_update( &ctx, input + (64<<2), 16 );
|
|
||||||
blake2s_4way_final( &ctx, vhash, BLAKE2S_OUTBYTES );
|
|
||||||
|
|
||||||
mm_deinterleave_4x32( output, output+32, output+64, output+96, vhash, 256 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_blake2s_4way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t vdata[20*4] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t hash[8*4] __attribute__ ((aligned (32)));
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
uint32_t _ALIGN(64) edata[20];
|
|
||||||
const uint32_t Htarg = ptarget[7];
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
uint32_t n = first_nonce;
|
|
||||||
uint32_t *nonces = work->nonces;
|
|
||||||
int num_found = 0;
|
|
||||||
uint32_t *noncep = vdata + 76; // 19*4
|
|
||||||
|
|
||||||
swab32_array( edata, pdata, 20 );
|
|
||||||
mm_interleave_4x32( vdata, edata, edata, edata, edata, 640 );
|
|
||||||
blake2s_4way_init( &blake2s_4w_ctx, BLAKE2S_OUTBYTES );
|
|
||||||
blake2s_4way_update( &blake2s_4w_ctx, vdata, 64 );
|
|
||||||
|
|
||||||
do {
|
|
||||||
be32enc( noncep, n );
|
|
||||||
be32enc( noncep +1, n+1 );
|
|
||||||
be32enc( noncep +2, n+2 );
|
|
||||||
be32enc( noncep +3, n+3 );
|
|
||||||
pdata[19] = n;
|
|
||||||
|
|
||||||
blake2s_4way_hash( hash, vdata );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 4; i++ )
|
|
||||||
if ( (hash+(i<<3))[7] <= Htarg && fulltest( hash+(i<<3), ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[19] = n+i;
|
|
||||||
nonces[ num_found++ ] = n+i;
|
|
||||||
work_set_target_ratio( work, hash+(i<<3) );
|
|
||||||
}
|
|
||||||
n += 4;
|
|
||||||
|
|
||||||
} while ( (num_found == 0) && (n < max_nonce)
|
|
||||||
&& !work_restart[thr_id].restart );
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return num_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,27 +0,0 @@
|
|||||||
#include "blake2s-gate.h"
|
|
||||||
|
|
||||||
|
|
||||||
// changed to get_max64_0x3fffffLL in cpuminer-multi-decred
|
|
||||||
int64_t blake2s_get_max64 ()
|
|
||||||
{
|
|
||||||
return 0x7ffffLL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool register_blake2s_algo( algo_gate_t* gate )
|
|
||||||
{
|
|
||||||
#if defined(BLAKE2S_8WAY)
|
|
||||||
gate->scanhash = (void*)&scanhash_blake2s_8way;
|
|
||||||
gate->hash = (void*)&blake2s_8way_hash;
|
|
||||||
#elif defined(BLAKE2S_4WAY)
|
|
||||||
gate->scanhash = (void*)&scanhash_blake2s_4way;
|
|
||||||
gate->hash = (void*)&blake2s_4way_hash;
|
|
||||||
#else
|
|
||||||
gate->scanhash = (void*)&scanhash_blake2s;
|
|
||||||
gate->hash = (void*)&blake2s_hash;
|
|
||||||
#endif
|
|
||||||
gate->get_max64 = (void*)&blake2s_get_max64;
|
|
||||||
gate->optimizations = SSE42_OPT | AVX_OPT | AVX2_OPT;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@@ -1,35 +0,0 @@
|
|||||||
#ifndef __BLAKE2S_GATE_H__
|
|
||||||
#define __BLAKE2S_GATE_H__ 1
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "algo-gate-api.h"
|
|
||||||
|
|
||||||
#if defined(__SSE4_2__)
|
|
||||||
#define BLAKE2S_4WAY
|
|
||||||
#endif
|
|
||||||
#if defined(__AVX2__)
|
|
||||||
#define BLAKE2S_8WAY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool register_blake2s_algo( algo_gate_t* gate );
|
|
||||||
|
|
||||||
#if defined(BLAKE2S_8WAY)
|
|
||||||
|
|
||||||
void blake2s_8way_hash( void *state, const void *input );
|
|
||||||
int scanhash_blake2s_8way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
|
|
||||||
#elif defined (BLAKE2S_4WAY)
|
|
||||||
|
|
||||||
void blake2s_4way_hash( void *state, const void *input );
|
|
||||||
int scanhash_blake2s_4way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
#else
|
|
||||||
|
|
||||||
void blake2s_hash( void *state, const void *input );
|
|
||||||
int scanhash_blake2s( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,362 +0,0 @@
|
|||||||
/**
|
|
||||||
* BLAKE2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
|
||||||
*
|
|
||||||
* To the extent possible under law, the author(s) have dedicated all copyright
|
|
||||||
* and related and neighboring rights to this software to the public domain
|
|
||||||
* worldwide. This software is distributed without any warranty.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the CC0 Public Domain Dedication along with
|
|
||||||
* this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "blake2s-hash-4way.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#if defined(__SSE4_2__)
|
|
||||||
|
|
||||||
static const uint32_t blake2s_IV[8] =
|
|
||||||
{
|
|
||||||
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
|
||||||
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t blake2s_sigma[10][16] =
|
|
||||||
{
|
|
||||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
|
||||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
|
||||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
|
||||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
|
||||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
|
||||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
|
||||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
|
||||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
|
||||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
|
||||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
|
||||||
};
|
|
||||||
|
|
||||||
// define a constant for initial param.
|
|
||||||
|
|
||||||
int blake2s_4way_init( blake2s_4way_state *S, const uint8_t outlen )
|
|
||||||
{
|
|
||||||
blake2s_nway_param P[1];
|
|
||||||
|
|
||||||
P->digest_length = outlen;
|
|
||||||
P->key_length = 0;
|
|
||||||
P->fanout = 1;
|
|
||||||
P->depth = 1;
|
|
||||||
P->leaf_length = 0;
|
|
||||||
*((uint64_t*)(P->node_offset)) = 0;
|
|
||||||
P->node_depth = 0;
|
|
||||||
P->inner_length = 0;
|
|
||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
|
||||||
|
|
||||||
memset( S, 0, sizeof( blake2s_4way_state ) );
|
|
||||||
for( int i = 0; i < 8; ++i )
|
|
||||||
S->h[i] = _mm_set1_epi32( blake2s_IV[i] );
|
|
||||||
|
|
||||||
uint32_t *p = ( uint32_t * )( P );
|
|
||||||
|
|
||||||
/* IV XOR ParamBlock */
|
|
||||||
for ( size_t i = 0; i < 8; ++i )
|
|
||||||
S->h[i] = _mm_xor_si128( S->h[i], _mm_set1_epi32( p[i] ) );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2s_4way_compress( blake2s_4way_state *S, const __m128i* block )
|
|
||||||
{
|
|
||||||
__m128i m[16];
|
|
||||||
__m128i v[16];
|
|
||||||
|
|
||||||
memcpy_128( m, block, 16 );
|
|
||||||
memcpy_128( v, S->h, 8 );
|
|
||||||
|
|
||||||
v[ 8] = _mm_set1_epi32( blake2s_IV[0] );
|
|
||||||
v[ 9] = _mm_set1_epi32( blake2s_IV[1] );
|
|
||||||
v[10] = _mm_set1_epi32( blake2s_IV[2] );
|
|
||||||
v[11] = _mm_set1_epi32( blake2s_IV[3] );
|
|
||||||
v[12] = _mm_xor_si128( _mm_set1_epi32( S->t[0] ),
|
|
||||||
_mm_set1_epi32( blake2s_IV[4] ) );
|
|
||||||
v[13] = _mm_xor_si128( _mm_set1_epi32( S->t[1] ),
|
|
||||||
_mm_set1_epi32( blake2s_IV[5] ) );
|
|
||||||
v[14] = _mm_xor_si128( _mm_set1_epi32( S->f[0] ),
|
|
||||||
_mm_set1_epi32( blake2s_IV[6] ) );
|
|
||||||
v[15] = _mm_xor_si128( _mm_set1_epi32( S->f[1] ),
|
|
||||||
_mm_set1_epi32( blake2s_IV[7] ) );
|
|
||||||
|
|
||||||
#define G4W(r,i,a,b,c,d) \
|
|
||||||
do { \
|
|
||||||
a = _mm_add_epi32( _mm_add_epi32( a, b ), m[ blake2s_sigma[r][2*i+0] ] ); \
|
|
||||||
d = mm_ror_32( _mm_xor_si128( d, a ), 16 ); \
|
|
||||||
c = _mm_add_epi32( c, d ); \
|
|
||||||
b = mm_ror_32( _mm_xor_si128( b, c ), 12 ); \
|
|
||||||
a = _mm_add_epi32( _mm_add_epi32( a, b ), m[ blake2s_sigma[r][2*i+1] ] ); \
|
|
||||||
d = mm_ror_32( _mm_xor_si128( d, a ), 8 ); \
|
|
||||||
c = _mm_add_epi32( c, d ); \
|
|
||||||
b = mm_ror_32( _mm_xor_si128( b, c ), 7 ); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define ROUND4W(r) \
|
|
||||||
do { \
|
|
||||||
G4W( r, 0, v[ 0], v[ 4], v[ 8], v[12] ); \
|
|
||||||
G4W( r, 1, v[ 1], v[ 5], v[ 9], v[13] ); \
|
|
||||||
G4W( r, 2, v[ 2], v[ 6], v[10], v[14] ); \
|
|
||||||
G4W( r, 3, v[ 3], v[ 7], v[11], v[15] ); \
|
|
||||||
G4W( r, 4, v[ 0], v[ 5], v[10], v[15] ); \
|
|
||||||
G4W( r, 5, v[ 1], v[ 6], v[11], v[12] ); \
|
|
||||||
G4W( r, 6, v[ 2], v[ 7], v[ 8], v[13] ); \
|
|
||||||
G4W( r, 7, v[ 3], v[ 4], v[ 9], v[14] ); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
ROUND4W( 0 );
|
|
||||||
ROUND4W( 1 );
|
|
||||||
ROUND4W( 2 );
|
|
||||||
ROUND4W( 3 );
|
|
||||||
ROUND4W( 4 );
|
|
||||||
ROUND4W( 5 );
|
|
||||||
ROUND4W( 6 );
|
|
||||||
ROUND4W( 7 );
|
|
||||||
ROUND4W( 8 );
|
|
||||||
ROUND4W( 9 );
|
|
||||||
|
|
||||||
for( size_t i = 0; i < 8; ++i )
|
|
||||||
S->h[i] = _mm_xor_si128( _mm_xor_si128( S->h[i], v[i] ), v[i + 8] );
|
|
||||||
|
|
||||||
#undef G4W
|
|
||||||
#undef ROUND4W
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2s_4way_update( blake2s_4way_state *S, const void *in,
|
|
||||||
uint64_t inlen )
|
|
||||||
{
|
|
||||||
__m128i *input = (__m128i*)in;
|
|
||||||
__m128i *buf = (__m128i*)S->buf;
|
|
||||||
const int bsize = BLAKE2S_BLOCKBYTES;
|
|
||||||
|
|
||||||
while( inlen > 0 )
|
|
||||||
{
|
|
||||||
size_t left = S->buflen;
|
|
||||||
if( inlen >= bsize - left )
|
|
||||||
{
|
|
||||||
memcpy_128( buf + (left>>2), input, (bsize - left) >> 2 );
|
|
||||||
S->buflen += bsize - left;
|
|
||||||
S->t[0] += BLAKE2S_BLOCKBYTES;
|
|
||||||
S->t[1] += ( S->t[0] < BLAKE2S_BLOCKBYTES );
|
|
||||||
blake2s_4way_compress( S, buf );
|
|
||||||
S->buflen = 0;
|
|
||||||
input += ( bsize >> 2 );
|
|
||||||
inlen -= bsize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy_128( buf + ( left>>2 ), input, inlen>>2 );
|
|
||||||
S->buflen += (size_t) inlen;
|
|
||||||
input += ( inlen>>2 );
|
|
||||||
inlen -= inlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2s_4way_final( blake2s_4way_state *S, void *out, uint8_t outlen )
|
|
||||||
{
|
|
||||||
__m128i *buf = (__m128i*)S->buf;
|
|
||||||
|
|
||||||
S->t[0] += S->buflen;
|
|
||||||
S->t[1] += ( S->t[0] < S->buflen );
|
|
||||||
if ( S->last_node )
|
|
||||||
S->f[1] = ~0U;
|
|
||||||
S->f[0] = ~0U;
|
|
||||||
|
|
||||||
memset_zero_128( buf + ( S->buflen>>2 ),
|
|
||||||
( BLAKE2S_BLOCKBYTES - S->buflen ) >> 2 );
|
|
||||||
blake2s_4way_compress( S, buf );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 8; ++i )
|
|
||||||
casti_m128i( out, i ) = S->h[ i ];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__AVX2__)
|
|
||||||
|
|
||||||
int blake2s_8way_compress( blake2s_8way_state *S, const __m256i *block )
|
|
||||||
{
|
|
||||||
__m256i m[16];
|
|
||||||
__m256i v[16];
|
|
||||||
|
|
||||||
memcpy_256( m, block, 16 );
|
|
||||||
memcpy_256( v, S->h, 8 );
|
|
||||||
|
|
||||||
v[ 8] = _mm256_set1_epi32( blake2s_IV[0] );
|
|
||||||
v[ 9] = _mm256_set1_epi32( blake2s_IV[1] );
|
|
||||||
v[10] = _mm256_set1_epi32( blake2s_IV[2] );
|
|
||||||
v[11] = _mm256_set1_epi32( blake2s_IV[3] );
|
|
||||||
v[12] = _mm256_xor_si256( _mm256_set1_epi32( S->t[0] ),
|
|
||||||
_mm256_set1_epi32( blake2s_IV[4] ) );
|
|
||||||
v[13] = _mm256_xor_si256( _mm256_set1_epi32( S->t[1] ),
|
|
||||||
_mm256_set1_epi32( blake2s_IV[5] ) );
|
|
||||||
v[14] = _mm256_xor_si256( _mm256_set1_epi32( S->f[0] ),
|
|
||||||
_mm256_set1_epi32( blake2s_IV[6] ) );
|
|
||||||
v[15] = _mm256_xor_si256( _mm256_set1_epi32( S->f[1] ),
|
|
||||||
_mm256_set1_epi32( blake2s_IV[7] ) );
|
|
||||||
|
|
||||||
#define G8W(r,i,a,b,c,d) \
|
|
||||||
do { \
|
|
||||||
a = _mm256_add_epi32( _mm256_add_epi32( a, b ), \
|
|
||||||
m[ blake2s_sigma[r][2*i+0] ] ); \
|
|
||||||
d = mm256_ror_32( _mm256_xor_si256( d, a ), 16 ); \
|
|
||||||
c = _mm256_add_epi32( c, d ); \
|
|
||||||
b = mm256_ror_32( _mm256_xor_si256( b, c ), 12 ); \
|
|
||||||
a = _mm256_add_epi32( _mm256_add_epi32( a, b ), \
|
|
||||||
m[ blake2s_sigma[r][2*i+1] ] ); \
|
|
||||||
d = mm256_ror_32( _mm256_xor_si256( d, a ), 8 ); \
|
|
||||||
c = _mm256_add_epi32( c, d ); \
|
|
||||||
b = mm256_ror_32( _mm256_xor_si256( b, c ), 7 ); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#define ROUND8W(r) \
|
|
||||||
do { \
|
|
||||||
G8W( r, 0, v[ 0], v[ 4], v[ 8], v[12] ); \
|
|
||||||
G8W( r, 1, v[ 1], v[ 5], v[ 9], v[13] ); \
|
|
||||||
G8W( r, 2, v[ 2], v[ 6], v[10], v[14] ); \
|
|
||||||
G8W( r, 3, v[ 3], v[ 7], v[11], v[15] ); \
|
|
||||||
G8W( r, 4, v[ 0], v[ 5], v[10], v[15] ); \
|
|
||||||
G8W( r, 5, v[ 1], v[ 6], v[11], v[12] ); \
|
|
||||||
G8W( r, 6, v[ 2], v[ 7], v[ 8], v[13] ); \
|
|
||||||
G8W( r, 7, v[ 3], v[ 4], v[ 9], v[14] ); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
ROUND8W( 0 );
|
|
||||||
ROUND8W( 1 );
|
|
||||||
ROUND8W( 2 );
|
|
||||||
ROUND8W( 3 );
|
|
||||||
ROUND8W( 4 );
|
|
||||||
ROUND8W( 5 );
|
|
||||||
ROUND8W( 6 );
|
|
||||||
ROUND8W( 7 );
|
|
||||||
ROUND8W( 8 );
|
|
||||||
ROUND8W( 9 );
|
|
||||||
|
|
||||||
for( size_t i = 0; i < 8; ++i )
|
|
||||||
S->h[i] = _mm256_xor_si256( _mm256_xor_si256( S->h[i], v[i] ), v[i + 8] );
|
|
||||||
|
|
||||||
#undef G8W
|
|
||||||
#undef ROUND8W
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2s_8way_init( blake2s_8way_state *S, const uint8_t outlen )
|
|
||||||
{
|
|
||||||
blake2s_nway_param P[1];
|
|
||||||
|
|
||||||
P->digest_length = outlen;
|
|
||||||
P->key_length = 0;
|
|
||||||
P->fanout = 1;
|
|
||||||
P->depth = 1;
|
|
||||||
P->leaf_length = 0;
|
|
||||||
*((uint64_t*)(P->node_offset)) = 0;
|
|
||||||
P->node_depth = 0;
|
|
||||||
P->inner_length = 0;
|
|
||||||
memset( P->salt, 0, sizeof( P->salt ) );
|
|
||||||
memset( P->personal, 0, sizeof( P->personal ) );
|
|
||||||
|
|
||||||
memset( S, 0, sizeof( blake2s_8way_state ) );
|
|
||||||
for( int i = 0; i < 8; ++i )
|
|
||||||
S->h[i] = _mm256_set1_epi32( blake2s_IV[i] );
|
|
||||||
|
|
||||||
uint32_t *p = ( uint32_t * )( P );
|
|
||||||
|
|
||||||
/* IV XOR ParamBlock */
|
|
||||||
for ( size_t i = 0; i < 8; ++i )
|
|
||||||
S->h[i] = _mm256_xor_si256( S->h[i], _mm256_set1_epi32( p[i] ) );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2s_8way_update( blake2s_8way_state *S, const void *in,
|
|
||||||
uint64_t inlen )
|
|
||||||
{
|
|
||||||
__m256i *input = (__m256i*)in;
|
|
||||||
__m256i *buf = (__m256i*)S->buf;
|
|
||||||
const int bsize = BLAKE2S_BLOCKBYTES;
|
|
||||||
|
|
||||||
while( inlen > 0 )
|
|
||||||
{
|
|
||||||
size_t left = S->buflen;
|
|
||||||
if( inlen >= bsize - left )
|
|
||||||
{
|
|
||||||
memcpy_256( buf + (left>>2), input, (bsize - left) >> 2 );
|
|
||||||
S->buflen += bsize - left;
|
|
||||||
S->t[0] += BLAKE2S_BLOCKBYTES;
|
|
||||||
S->t[1] += ( S->t[0] < BLAKE2S_BLOCKBYTES );
|
|
||||||
blake2s_8way_compress( S, buf );
|
|
||||||
S->buflen = 0;
|
|
||||||
input += ( bsize >> 2 );
|
|
||||||
inlen -= bsize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy_256( buf + ( left>>2 ), input, inlen>>2 );
|
|
||||||
S->buflen += (size_t) inlen;
|
|
||||||
input += ( inlen>>2 );
|
|
||||||
inlen -= inlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blake2s_8way_final( blake2s_8way_state *S, void *out, uint8_t outlen )
|
|
||||||
{
|
|
||||||
__m256i *buf = (__m256i*)S->buf;
|
|
||||||
|
|
||||||
S->t[0] += S->buflen;
|
|
||||||
S->t[1] += ( S->t[0] < S->buflen );
|
|
||||||
if ( S->last_node )
|
|
||||||
S->f[1] = ~0U;
|
|
||||||
S->f[0] = ~0U;
|
|
||||||
|
|
||||||
memset_zero_256( buf + ( S->buflen>>2 ),
|
|
||||||
( BLAKE2S_BLOCKBYTES - S->buflen ) >> 2 );
|
|
||||||
blake2s_8way_compress( S, buf );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 8; ++i )
|
|
||||||
casti_m256i( out, i ) = S->h[ i ];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __AVX2__
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
|
|
||||||
{
|
|
||||||
blake2s_state S[1];
|
|
||||||
|
|
||||||
/* Verify parameters */
|
|
||||||
if ( NULL == in ) return -1;
|
|
||||||
|
|
||||||
if ( NULL == out ) return -1;
|
|
||||||
|
|
||||||
if ( NULL == key ) keylen = 0; /* Fail here instead if keylen != 0 and key == NULL? */
|
|
||||||
|
|
||||||
if( keylen > 0 )
|
|
||||||
{
|
|
||||||
if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( blake2s_init( S, outlen ) < 0 ) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
blake2s_update( S, ( uint8_t * )in, inlen );
|
|
||||||
blake2s_final( S, out, outlen );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __SSE4_2__
|
|
@@ -1,112 +0,0 @@
|
|||||||
/**
|
|
||||||
* BLAKE2 reference source code package - reference C implementations
|
|
||||||
*
|
|
||||||
* Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
|
|
||||||
*
|
|
||||||
* To the extent possible under law, the author(s) have dedicated all copyright
|
|
||||||
* and related and neighboring rights to this software to the public domain
|
|
||||||
* worldwide. This software is distributed without any warranty.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the CC0 Public Domain Dedication along with
|
|
||||||
* this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
||||||
*/
|
|
||||||
//#pragma once
|
|
||||||
#ifndef __BLAKE2S_HASH_4WAY_H__
|
|
||||||
#define __BLAKE2S_HASH_4WAY_H__ 1
|
|
||||||
|
|
||||||
#if defined(__SSE4_2__)
|
|
||||||
|
|
||||||
#include "avxdefs.h"
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#include <inttypes.h>
|
|
||||||
#define inline __inline
|
|
||||||
#define ALIGN(x) __declspec(align(x))
|
|
||||||
#else
|
|
||||||
#define ALIGN(x) __attribute__((aligned(x)))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum blake2s_constant
|
|
||||||
{
|
|
||||||
BLAKE2S_BLOCKBYTES = 64,
|
|
||||||
BLAKE2S_OUTBYTES = 32,
|
|
||||||
BLAKE2S_KEYBYTES = 32,
|
|
||||||
BLAKE2S_SALTBYTES = 8,
|
|
||||||
BLAKE2S_PERSONALBYTES = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
typedef struct __blake2s_nway_param
|
|
||||||
{
|
|
||||||
uint8_t digest_length; // 1
|
|
||||||
uint8_t key_length; // 2
|
|
||||||
uint8_t fanout; // 3
|
|
||||||
uint8_t depth; // 4
|
|
||||||
uint32_t leaf_length; // 8
|
|
||||||
uint8_t node_offset[6];// 14
|
|
||||||
uint8_t node_depth; // 15
|
|
||||||
uint8_t inner_length; // 16
|
|
||||||
// uint8_t reserved[0];
|
|
||||||
uint8_t salt[BLAKE2S_SALTBYTES]; // 24
|
|
||||||
uint8_t personal[BLAKE2S_PERSONALBYTES]; // 32
|
|
||||||
} blake2s_nway_param;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
ALIGN( 64 ) typedef struct __blake2s_4way_state
|
|
||||||
{
|
|
||||||
__m128i h[8];
|
|
||||||
uint8_t buf[ BLAKE2S_BLOCKBYTES * 4 ];
|
|
||||||
uint32_t t[2];
|
|
||||||
uint32_t f[2];
|
|
||||||
size_t buflen;
|
|
||||||
uint8_t last_node;
|
|
||||||
} blake2s_4way_state ;
|
|
||||||
|
|
||||||
int blake2s_4way_init( blake2s_4way_state *S, const uint8_t outlen );
|
|
||||||
int blake2s_4way_update( blake2s_4way_state *S, const void *in,
|
|
||||||
uint64_t inlen );
|
|
||||||
int blake2s_4way_final( blake2s_4way_state *S, void *out, uint8_t outlen );
|
|
||||||
|
|
||||||
#if defined(__AVX2__)
|
|
||||||
|
|
||||||
ALIGN( 64 ) typedef struct __blake2s_8way_state
|
|
||||||
{
|
|
||||||
__m256i h[8];
|
|
||||||
uint8_t buf[ BLAKE2S_BLOCKBYTES * 8 ];
|
|
||||||
uint32_t t[2];
|
|
||||||
uint32_t f[2];
|
|
||||||
size_t buflen;
|
|
||||||
uint8_t last_node;
|
|
||||||
} blake2s_8way_state ;
|
|
||||||
|
|
||||||
int blake2s_8way_init( blake2s_8way_state *S, const uint8_t outlen );
|
|
||||||
int blake2s_8way_update( blake2s_8way_state *S, const void *in,
|
|
||||||
uint64_t inlen );
|
|
||||||
int blake2s_8way_final( blake2s_8way_state *S, void *out, uint8_t outlen );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Simple API
|
|
||||||
// int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
|
|
||||||
|
|
||||||
// Direct Hash Mining Helpers
|
|
||||||
#define blake2s_salt32(out, in, inlen, key32) blake2s(out, in, key32, 32, inlen, 32) /* neoscrypt */
|
|
||||||
#define blake2s_simple(out, in, inlen) blake2s(out, in, NULL, 32, inlen, 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __SSE4_2__
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,29 +1,27 @@
|
|||||||
#include "blake2s-gate.h"
|
#include "miner.h"
|
||||||
|
#include "algo-gate-api.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "sph-blake2s.h"
|
#include "crypto/blake2s.h"
|
||||||
|
|
||||||
static __thread blake2s_state blake2s_ctx;
|
static __thread blake2s_state s_midstate;
|
||||||
//static __thread blake2s_state s_ctx;
|
static __thread blake2s_state s_ctx;
|
||||||
#define MIDLEN 76
|
#define MIDLEN 76
|
||||||
|
|
||||||
void blake2s_hash( void *output, const void *input )
|
void blake2s_hash(void *output, const void *input)
|
||||||
{
|
{
|
||||||
unsigned char _ALIGN(64) hash[BLAKE2S_OUTBYTES];
|
unsigned char _ALIGN(64) hash[BLAKE2S_OUTBYTES];
|
||||||
blake2s_state ctx __attribute__ ((aligned (64)));
|
blake2s_state blake2_ctx;
|
||||||
|
|
||||||
memcpy( &ctx, &blake2s_ctx, sizeof ctx );
|
blake2s_init(&blake2_ctx, BLAKE2S_OUTBYTES);
|
||||||
blake2s_update( &ctx, input+64, 16 );
|
blake2s_update(&blake2_ctx, input, 80);
|
||||||
|
blake2s_final(&blake2_ctx, hash, BLAKE2S_OUTBYTES);
|
||||||
// blake2s_init(&ctx, BLAKE2S_OUTBYTES);
|
|
||||||
// blake2s_update(&ctx, input, 80);
|
|
||||||
blake2s_final( &ctx, hash, BLAKE2S_OUTBYTES );
|
|
||||||
|
|
||||||
memcpy(output, hash, 32);
|
memcpy(output, hash, 32);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
static void blake2s_hash_end(uint32_t *output, const uint32_t *input)
|
static void blake2s_hash_end(uint32_t *output, const uint32_t *input)
|
||||||
{
|
{
|
||||||
s_ctx.buflen = MIDLEN;
|
s_ctx.buflen = MIDLEN;
|
||||||
@@ -31,7 +29,7 @@ static void blake2s_hash_end(uint32_t *output, const uint32_t *input)
|
|||||||
blake2s_update(&s_ctx, (uint8_t*) &input[MIDLEN/4], 80 - MIDLEN);
|
blake2s_update(&s_ctx, (uint8_t*) &input[MIDLEN/4], 80 - MIDLEN);
|
||||||
blake2s_final(&s_ctx, (uint8_t*) output, BLAKE2S_OUTBYTES);
|
blake2s_final(&s_ctx, (uint8_t*) output, BLAKE2S_OUTBYTES);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
int scanhash_blake2s(int thr_id, struct work *work,
|
int scanhash_blake2s(int thr_id, struct work *work,
|
||||||
uint32_t max_nonce, uint64_t *hashes_done)
|
uint32_t max_nonce, uint64_t *hashes_done)
|
||||||
{
|
{
|
||||||
@@ -49,12 +47,13 @@ int scanhash_blake2s(int thr_id, struct work *work,
|
|||||||
swab32_array( endiandata, pdata, 20 );
|
swab32_array( endiandata, pdata, 20 );
|
||||||
|
|
||||||
// midstate
|
// midstate
|
||||||
blake2s_init( &blake2s_ctx, BLAKE2S_OUTBYTES );
|
blake2s_init(&s_midstate, BLAKE2S_OUTBYTES);
|
||||||
blake2s_update( &blake2s_ctx, (uint8_t*) endiandata, 64 );
|
blake2s_update(&s_midstate, (uint8_t*) endiandata, MIDLEN);
|
||||||
|
memcpy(&s_ctx, &s_midstate, sizeof(blake2s_state));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
be32enc(&endiandata[19], n);
|
be32enc(&endiandata[19], n);
|
||||||
blake2s_hash( hash64, endiandata );
|
blake2s_hash_end(hash64, endiandata);
|
||||||
if (hash64[7] < Htarg && fulltest(hash64, ptarget)) {
|
if (hash64[7] < Htarg && fulltest(hash64, ptarget)) {
|
||||||
*hashes_done = n - first_nonce + 1;
|
*hashes_done = n - first_nonce + 1;
|
||||||
pdata[19] = n;
|
pdata[19] = n;
|
||||||
@@ -69,7 +68,7 @@ int scanhash_blake2s(int thr_id, struct work *work,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
// changed to get_max64_0x3fffffLL in cpuminer-multi-decred
|
// changed to get_max64_0x3fffffLL in cpuminer-multi-decred
|
||||||
int64_t blake2s_get_max64 ()
|
int64_t blake2s_get_max64 ()
|
||||||
{
|
{
|
||||||
@@ -83,4 +82,4 @@ bool register_blake2s_algo( algo_gate_t* gate )
|
|||||||
gate->get_max64 = (void*)&blake2s_get_max64;
|
gate->get_max64 = (void*)&blake2s_get_max64;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
|
@@ -1,141 +0,0 @@
|
|||||||
#include "blakecoin-gate.h"
|
|
||||||
#include "blake-hash-4way.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
#if defined (BLAKECOIN_4WAY)
|
|
||||||
|
|
||||||
blake256r8_4way_context blakecoin_4w_ctx;
|
|
||||||
|
|
||||||
void blakecoin_4way_hash(void *state, const void *input)
|
|
||||||
{
|
|
||||||
uint32_t vhash[8*4] __attribute__ ((aligned (64)));
|
|
||||||
blake256r8_4way_context ctx;
|
|
||||||
|
|
||||||
memcpy( &ctx, &blakecoin_4w_ctx, sizeof ctx );
|
|
||||||
blake256r8_4way( &ctx, input + (64<<2), 16 );
|
|
||||||
blake256r8_4way_close( &ctx, vhash );
|
|
||||||
|
|
||||||
mm_deinterleave_4x32( state, state+32, state+64, state+96, vhash, 256 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_blakecoin_4way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t vdata[20*4] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t hash[8*4] __attribute__ ((aligned (32)));
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
uint32_t HTarget = ptarget[7];
|
|
||||||
uint32_t _ALIGN(32) edata[20];
|
|
||||||
uint32_t n = first_nonce;
|
|
||||||
uint32_t *nonces = work->nonces;
|
|
||||||
int num_found = 0;
|
|
||||||
if ( opt_benchmark )
|
|
||||||
HTarget = 0x7f;
|
|
||||||
|
|
||||||
swab32_array( edata, pdata, 20 );
|
|
||||||
mm_interleave_4x32( vdata, edata, edata, edata, edata, 640 );
|
|
||||||
blake256r8_4way_init( &blakecoin_4w_ctx );
|
|
||||||
blake256r8_4way( &blakecoin_4w_ctx, vdata, 64 );
|
|
||||||
|
|
||||||
uint32_t *noncep = vdata + 76; // 19*4
|
|
||||||
do {
|
|
||||||
be32enc( noncep, n );
|
|
||||||
be32enc( noncep +1, n+1 );
|
|
||||||
be32enc( noncep +2, n+2 );
|
|
||||||
be32enc( noncep +3, n+3 );
|
|
||||||
pdata[19] = n;
|
|
||||||
blakecoin_4way_hash( hash, vdata );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 4; i++ )
|
|
||||||
if ( (hash+(i<<3))[7] <= HTarget && fulltest( hash+(i<<3), ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[19] = n+i;
|
|
||||||
nonces[ num_found++ ] = n+i;
|
|
||||||
work_set_target_ratio( work, hash+(i<<3) );
|
|
||||||
}
|
|
||||||
n += 4;
|
|
||||||
|
|
||||||
} while ( (num_found == 0) && (n < max_nonce)
|
|
||||||
&& !work_restart[thr_id].restart );
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return num_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(BLAKECOIN_8WAY)
|
|
||||||
|
|
||||||
blake256r8_8way_context blakecoin_8w_ctx;
|
|
||||||
|
|
||||||
void blakecoin_8way_hash( void *state, const void *input )
|
|
||||||
{
|
|
||||||
uint32_t vhash[8*8] __attribute__ ((aligned (64)));
|
|
||||||
blake256r8_8way_context ctx;
|
|
||||||
|
|
||||||
memcpy( &ctx, &blakecoin_8w_ctx, sizeof ctx );
|
|
||||||
blake256r8_8way( &ctx, input + (64<<3), 16 );
|
|
||||||
blake256r8_8way_close( &ctx, vhash );
|
|
||||||
|
|
||||||
mm256_deinterleave_8x32( state, state+ 32, state+ 64, state+ 96,
|
|
||||||
state+128, state+160, state+192, state+224,
|
|
||||||
vhash, 256 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_blakecoin_8way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t vdata[20*8] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t hash[8*8] __attribute__ ((aligned (32)));
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
uint32_t HTarget = ptarget[7];
|
|
||||||
uint32_t _ALIGN(32) edata[20];
|
|
||||||
uint32_t n = first_nonce;
|
|
||||||
uint32_t *nonces = work->nonces;
|
|
||||||
uint32_t *noncep = vdata + 152; // 19*8
|
|
||||||
int num_found = 0;
|
|
||||||
if ( opt_benchmark )
|
|
||||||
HTarget = 0x7f;
|
|
||||||
|
|
||||||
// we need big endian data...
|
|
||||||
swab32_array( edata, pdata, 20 );
|
|
||||||
mm256_interleave_8x32( vdata, edata, edata, edata, edata,
|
|
||||||
edata, edata, edata, edata, 640 );
|
|
||||||
blake256r8_8way_init( &blakecoin_8w_ctx );
|
|
||||||
blake256r8_8way( &blakecoin_8w_ctx, vdata, 64 );
|
|
||||||
|
|
||||||
do {
|
|
||||||
be32enc( noncep, n );
|
|
||||||
be32enc( noncep +1, n+1 );
|
|
||||||
be32enc( noncep +2, n+2 );
|
|
||||||
be32enc( noncep +3, n+3 );
|
|
||||||
be32enc( noncep +4, n+4 );
|
|
||||||
be32enc( noncep +5, n+5 );
|
|
||||||
be32enc( noncep +6, n+6 );
|
|
||||||
be32enc( noncep +7, n+7 );
|
|
||||||
pdata[19] = n;
|
|
||||||
blakecoin_8way_hash( hash, vdata );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 8; i++ )
|
|
||||||
if ( (hash+(i<<3))[7] <= HTarget && fulltest( hash+(i<<3), ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[19] = n+i;
|
|
||||||
nonces[ num_found++ ] = n+i;
|
|
||||||
work_set_target_ratio( work, hash+(i<<3) );
|
|
||||||
}
|
|
||||||
n += 8;
|
|
||||||
} while ( (num_found == 0) && (n < max_nonce)
|
|
||||||
&& !work_restart[thr_id].restart );
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return num_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,36 +0,0 @@
|
|||||||
#include "blakecoin-gate.h"
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
// changed to get_max64_0x3fffffLL in cpuminer-multi-decred
|
|
||||||
int64_t blakecoin_get_max64 ()
|
|
||||||
{
|
|
||||||
return 0x7ffffLL;
|
|
||||||
// return 0x3fffffLL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// vanilla uses default gen merkle root, otherwise identical to blakecoin
|
|
||||||
bool register_vanilla_algo( algo_gate_t* gate )
|
|
||||||
{
|
|
||||||
#if defined(BLAKECOIN_8WAY)
|
|
||||||
gate->scanhash = (void*)&scanhash_blakecoin_8way;
|
|
||||||
gate->hash = (void*)&blakecoin_8way_hash;
|
|
||||||
|
|
||||||
#elif defined(BLAKECOIN_4WAY)
|
|
||||||
gate->scanhash = (void*)&scanhash_blakecoin_4way;
|
|
||||||
gate->hash = (void*)&blakecoin_4way_hash;
|
|
||||||
#else
|
|
||||||
gate->scanhash = (void*)&scanhash_blakecoin;
|
|
||||||
gate->hash = (void*)&blakecoinhash;
|
|
||||||
#endif
|
|
||||||
gate->optimizations = SSE42_OPT | AVX_OPT | AVX2_OPT;
|
|
||||||
gate->get_max64 = (void*)&blakecoin_get_max64;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool register_blakecoin_algo( algo_gate_t* gate )
|
|
||||||
{
|
|
||||||
register_vanilla_algo( gate );
|
|
||||||
gate->gen_merkle_root = (void*)&SHA256_gen_merkle_root;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@@ -1,30 +0,0 @@
|
|||||||
#ifndef __BLAKECOIN_GATE_H__
|
|
||||||
#define __BLAKECOIN_GATE_H__ 1
|
|
||||||
|
|
||||||
#include "algo-gate-api.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#if defined(__SSE4_2__)
|
|
||||||
#define BLAKECOIN_4WAY
|
|
||||||
#endif
|
|
||||||
#if defined(__AVX2__)
|
|
||||||
#define BLAKECOIN_8WAY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (BLAKECOIN_8WAY)
|
|
||||||
void blakecoin_8way_hash(void *state, const void *input);
|
|
||||||
int scanhash_blakecoin_8way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (BLAKECOIN_4WAY)
|
|
||||||
void blakecoin_4way_hash(void *state, const void *input);
|
|
||||||
int scanhash_blakecoin_4way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void blakecoinhash( void *state, const void *input );
|
|
||||||
int scanhash_blakecoin( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,4 +1,5 @@
|
|||||||
#include "blakecoin-gate.h"
|
#include "miner.h"
|
||||||
|
#include "algo-gate-api.h"
|
||||||
#define BLAKE32_ROUNDS 8
|
#define BLAKE32_ROUNDS 8
|
||||||
#include "sph_blake.h"
|
#include "sph_blake.h"
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ static void blake_midstate_init( const void* input )
|
|||||||
void blakecoinhash( void *state, const void *input )
|
void blakecoinhash( void *state, const void *input )
|
||||||
{
|
{
|
||||||
sph_blake256_context ctx;
|
sph_blake256_context ctx;
|
||||||
uint8_t hash[64] __attribute__ ((aligned (32)));
|
uint8_t hash[64];
|
||||||
uint8_t *ending = (uint8_t*) input + 64;
|
uint8_t *ending = (uint8_t*) input + 64;
|
||||||
|
|
||||||
// copy cached midstate
|
// copy cached midstate
|
||||||
@@ -92,13 +93,11 @@ int scanhash_blakecoin( int thr_id, struct work *work, uint32_t max_nonce,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
void blakecoin_gen_merkle_root ( char* merkle_root, struct stratum_ctx* sctx )
|
void blakecoin_gen_merkle_root ( char* merkle_root, struct stratum_ctx* sctx )
|
||||||
{
|
{
|
||||||
SHA256( sctx->job.coinbase, (int)sctx->job.coinbase_size, merkle_root );
|
SHA256( sctx->job.coinbase, (int)sctx->job.coinbase_size, merkle_root );
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
/*
|
|
||||||
// changed to get_max64_0x3fffffLL in cpuminer-multi-decred
|
// changed to get_max64_0x3fffffLL in cpuminer-multi-decred
|
||||||
int64_t blakecoin_get_max64 ()
|
int64_t blakecoin_get_max64 ()
|
||||||
{
|
{
|
||||||
@@ -110,6 +109,7 @@ bool register_vanilla_algo( algo_gate_t* gate )
|
|||||||
{
|
{
|
||||||
gate->scanhash = (void*)&scanhash_blakecoin;
|
gate->scanhash = (void*)&scanhash_blakecoin;
|
||||||
gate->hash = (void*)&blakecoinhash;
|
gate->hash = (void*)&blakecoinhash;
|
||||||
|
gate->hash_alt = (void*)&blakecoinhash;
|
||||||
gate->get_max64 = (void*)&blakecoin_get_max64;
|
gate->get_max64 = (void*)&blakecoin_get_max64;
|
||||||
blakecoin_init( &blake_init_ctx );
|
blakecoin_init( &blake_init_ctx );
|
||||||
return true;
|
return true;
|
||||||
@@ -121,4 +121,4 @@ bool register_blakecoin_algo( algo_gate_t* gate )
|
|||||||
gate->gen_merkle_root = (void*)&SHA256_gen_merkle_root;
|
gate->gen_merkle_root = (void*)&SHA256_gen_merkle_root;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
@@ -1,76 +0,0 @@
|
|||||||
#include "decred-gate.h"
|
|
||||||
#include "blake-hash-4way.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <memory.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#if defined (DECRED_4WAY)
|
|
||||||
|
|
||||||
static __thread blake256_4way_context blake_mid;
|
|
||||||
|
|
||||||
void decred_hash_4way( void *state, const void *input )
|
|
||||||
{
|
|
||||||
uint32_t vhash[8*4] __attribute__ ((aligned (64)));
|
|
||||||
// uint32_t hash0[8] __attribute__ ((aligned (32)));
|
|
||||||
// uint32_t hash1[8] __attribute__ ((aligned (32)));
|
|
||||||
// uint32_t hash2[8] __attribute__ ((aligned (32)));
|
|
||||||
// uint32_t hash3[8] __attribute__ ((aligned (32)));
|
|
||||||
const void *tail = input + ( DECRED_MIDSTATE_LEN << 2 );
|
|
||||||
int tail_len = 180 - DECRED_MIDSTATE_LEN;
|
|
||||||
blake256_4way_context ctx __attribute__ ((aligned (64)));
|
|
||||||
|
|
||||||
memcpy( &ctx, &blake_mid, sizeof(blake_mid) );
|
|
||||||
blake256_4way( &ctx, tail, tail_len );
|
|
||||||
blake256_4way_close( &ctx, vhash );
|
|
||||||
mm_deinterleave_4x32( state, state+32, state+64, state+96, vhash, 256 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_decred_4way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done)
|
|
||||||
{
|
|
||||||
uint32_t vdata[48*4] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t hash[8*4] __attribute__ ((aligned (32)));
|
|
||||||
uint32_t _ALIGN(64) edata[48];
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
const uint32_t first_nonce = pdata[DECRED_NONCE_INDEX];
|
|
||||||
uint32_t n = first_nonce;
|
|
||||||
const uint32_t HTarget = opt_benchmark ? 0x7f : ptarget[7];
|
|
||||||
uint32_t *nonces = work->nonces;
|
|
||||||
int num_found = 0;
|
|
||||||
|
|
||||||
// copy to buffer guaranteed to be aligned.
|
|
||||||
memcpy( edata, pdata, 180 );
|
|
||||||
|
|
||||||
// use the old way until new way updated for size.
|
|
||||||
mm_interleave_4x32x( vdata, edata, edata, edata, edata, 180*8 );
|
|
||||||
|
|
||||||
blake256_4way_init( &blake_mid );
|
|
||||||
blake256_4way( &blake_mid, vdata, DECRED_MIDSTATE_LEN );
|
|
||||||
|
|
||||||
uint32_t *noncep = vdata + DECRED_NONCE_INDEX * 4;
|
|
||||||
do {
|
|
||||||
* noncep = n;
|
|
||||||
*(noncep+1) = n+1;
|
|
||||||
*(noncep+2) = n+2;
|
|
||||||
*(noncep+3) = n+3;
|
|
||||||
|
|
||||||
decred_hash_4way( hash, vdata );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 4; i++ )
|
|
||||||
if ( (hash+(i<<3))[7] <= HTarget && fulltest( hash+(i<<3), ptarget ) )
|
|
||||||
{
|
|
||||||
pdata[DECRED_NONCE_INDEX] = n+i;
|
|
||||||
nonces[ num_found++ ] = n+i;
|
|
||||||
work_set_target_ratio( work, hash+(i<<3) );
|
|
||||||
}
|
|
||||||
n += 4;
|
|
||||||
} while ( (num_found == 0) && (n < max_nonce)
|
|
||||||
&& !work_restart[thr_id].restart );
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
return num_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,172 +0,0 @@
|
|||||||
#include "decred-gate.h"
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <memory.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
uint32_t *decred_get_nonceptr( uint32_t *work_data )
|
|
||||||
{
|
|
||||||
return &work_data[ DECRED_NONCE_INDEX ];
|
|
||||||
}
|
|
||||||
|
|
||||||
double decred_calc_network_diff( struct work* work )
|
|
||||||
{
|
|
||||||
// sample for diff 43.281 : 1c05ea29
|
|
||||||
// todo: endian reversed on longpoll could be zr5 specific...
|
|
||||||
uint32_t nbits = work->data[ DECRED_NBITS_INDEX ];
|
|
||||||
uint32_t bits = ( nbits & 0xffffff );
|
|
||||||
int16_t shift = ( swab32(nbits) & 0xff ); // 0x1c = 28
|
|
||||||
int m;
|
|
||||||
double d = (double)0x0000ffff / (double)bits;
|
|
||||||
|
|
||||||
for ( m = shift; m < 29; m++ )
|
|
||||||
d *= 256.0;
|
|
||||||
for ( m = 29; m < shift; m++ )
|
|
||||||
d /= 256.0;
|
|
||||||
if ( shift == 28 )
|
|
||||||
d *= 256.0; // testnet
|
|
||||||
if ( opt_debug_diff )
|
|
||||||
applog( LOG_DEBUG, "net diff: %f -> shift %u, bits %08x", d,
|
|
||||||
shift, bits );
|
|
||||||
return net_diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
void decred_decode_extradata( struct work* work, uint64_t* net_blocks )
|
|
||||||
{
|
|
||||||
// some random extradata to make the work unique
|
|
||||||
work->data[ DECRED_XNONCE_INDEX ] = (rand()*4);
|
|
||||||
work->height = work->data[32];
|
|
||||||
if (!have_longpoll && work->height > *net_blocks + 1)
|
|
||||||
{
|
|
||||||
char netinfo[64] = { 0 };
|
|
||||||
if (opt_showdiff && net_diff > 0.)
|
|
||||||
{
|
|
||||||
if (net_diff != work->targetdiff)
|
|
||||||
sprintf(netinfo, ", diff %.3f, target %.1f", net_diff,
|
|
||||||
work->targetdiff);
|
|
||||||
else
|
|
||||||
sprintf(netinfo, ", diff %.3f", net_diff);
|
|
||||||
}
|
|
||||||
applog(LOG_BLUE, "%s block %d%s", algo_names[opt_algo], work->height,
|
|
||||||
netinfo);
|
|
||||||
*net_blocks = work->height - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void decred_be_build_stratum_request( char *req, struct work *work,
|
|
||||||
struct stratum_ctx *sctx )
|
|
||||||
{
|
|
||||||
unsigned char *xnonce2str;
|
|
||||||
uint32_t ntime, nonce;
|
|
||||||
char ntimestr[9], noncestr[9];
|
|
||||||
|
|
||||||
be32enc( &ntime, work->data[ DECRED_NTIME_INDEX ] );
|
|
||||||
be32enc( &nonce, work->data[ DECRED_NONCE_INDEX ] );
|
|
||||||
bin2hex( ntimestr, (char*)(&ntime), sizeof(uint32_t) );
|
|
||||||
bin2hex( noncestr, (char*)(&nonce), sizeof(uint32_t) );
|
|
||||||
xnonce2str = abin2hex( (char*)( &work->data[ DECRED_XNONCE_INDEX ] ),
|
|
||||||
sctx->xnonce1_size );
|
|
||||||
snprintf( req, JSON_BUF_LEN,
|
|
||||||
"{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}",
|
|
||||||
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr );
|
|
||||||
free(xnonce2str);
|
|
||||||
}
|
|
||||||
#define min(a,b) (a>b ? (b) :(a))
|
|
||||||
|
|
||||||
void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
|
|
||||||
{
|
|
||||||
uchar merkle_root[64] = { 0 };
|
|
||||||
uint32_t extraheader[32] = { 0 };
|
|
||||||
int headersize = 0;
|
|
||||||
uint32_t* extradata = (uint32_t*) sctx->xnonce1;
|
|
||||||
size_t t;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// getwork over stratum, getwork merkle + header passed in coinb1
|
|
||||||
memcpy(merkle_root, sctx->job.coinbase, 32);
|
|
||||||
headersize = min((int)sctx->job.coinbase_size - 32,
|
|
||||||
sizeof(extraheader) );
|
|
||||||
memcpy( extraheader, &sctx->job.coinbase[32], headersize );
|
|
||||||
|
|
||||||
// Increment extranonce2
|
|
||||||
for ( t = 0; t < sctx->xnonce2_size && !( ++sctx->job.xnonce2[t] ); t++ );
|
|
||||||
|
|
||||||
// Assemble block header
|
|
||||||
memset( g_work->data, 0, sizeof(g_work->data) );
|
|
||||||
g_work->data[0] = le32dec( sctx->job.version );
|
|
||||||
for ( i = 0; i < 8; i++ )
|
|
||||||
g_work->data[1 + i] = swab32(
|
|
||||||
le32dec( (uint32_t *) sctx->job.prevhash + i ) );
|
|
||||||
for ( i = 0; i < 8; i++ )
|
|
||||||
g_work->data[9 + i] = swab32( be32dec( (uint32_t *) merkle_root + i ) );
|
|
||||||
|
|
||||||
// for ( i = 0; i < 8; i++ ) // prevhash
|
|
||||||
// g_work->data[1 + i] = swab32( g_work->data[1 + i] );
|
|
||||||
// for ( i = 0; i < 8; i++ ) // merkle
|
|
||||||
// g_work->data[9 + i] = swab32( g_work->data[9 + i] );
|
|
||||||
|
|
||||||
for ( i = 0; i < headersize/4; i++ ) // header
|
|
||||||
g_work->data[17 + i] = extraheader[i];
|
|
||||||
// extradata
|
|
||||||
|
|
||||||
for ( i = 0; i < sctx->xnonce1_size/4; i++ )
|
|
||||||
g_work->data[ DECRED_XNONCE_INDEX + i ] = extradata[i];
|
|
||||||
for ( i = DECRED_XNONCE_INDEX + sctx->xnonce1_size/4; i < 45; i++ )
|
|
||||||
g_work->data[i] = 0;
|
|
||||||
g_work->data[37] = (rand()*4) << 8;
|
|
||||||
// block header suffix from coinb2 (stake version)
|
|
||||||
memcpy( &g_work->data[44],
|
|
||||||
&sctx->job.coinbase[ sctx->job.coinbase_size-4 ], 4 );
|
|
||||||
sctx->bloc_height = g_work->data[32];
|
|
||||||
//applog_hex(work->data, 180);
|
|
||||||
//applog_hex(&work->data[36], 36);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef min
|
|
||||||
|
|
||||||
bool decred_ready_to_mine( struct work* work, struct stratum_ctx* stratum,
|
|
||||||
int thr_id )
|
|
||||||
{
|
|
||||||
if ( have_stratum && strcmp(stratum->job.job_id, work->job_id) )
|
|
||||||
// need to regen g_work..
|
|
||||||
return false;
|
|
||||||
if ( have_stratum && !work->data[0] && !opt_benchmark )
|
|
||||||
{
|
|
||||||
sleep(1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// extradata: prevent duplicates
|
|
||||||
work->data[ DECRED_XNONCE_INDEX ] += 1;
|
|
||||||
work->data[ DECRED_XNONCE_INDEX + 1 ] |= thr_id;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool register_decred_algo( algo_gate_t* gate )
|
|
||||||
{
|
|
||||||
#if defined(DECRED_4WAY)
|
|
||||||
four_way_not_tested();
|
|
||||||
gate->scanhash = (void*)&scanhash_decred_4way;
|
|
||||||
gate->hash = (void*)&decred_hash_4way;
|
|
||||||
#else
|
|
||||||
gate->scanhash = (void*)&scanhash_decred;
|
|
||||||
gate->hash = (void*)&decred_hash;
|
|
||||||
#endif
|
|
||||||
gate->optimizations = AVX2_OPT;
|
|
||||||
gate->get_nonceptr = (void*)&decred_get_nonceptr;
|
|
||||||
gate->get_max64 = (void*)&get_max64_0x3fffffLL;
|
|
||||||
gate->display_extra_data = (void*)&decred_decode_extradata;
|
|
||||||
gate->build_stratum_request = (void*)&decred_be_build_stratum_request;
|
|
||||||
gate->work_decode = (void*)&std_be_work_decode;
|
|
||||||
gate->submit_getwork_result = (void*)&std_be_submit_getwork_result;
|
|
||||||
gate->build_extraheader = (void*)&decred_build_extraheader;
|
|
||||||
gate->ready_to_mine = (void*)&decred_ready_to_mine;
|
|
||||||
gate->nbits_index = DECRED_NBITS_INDEX;
|
|
||||||
gate->ntime_index = DECRED_NTIME_INDEX;
|
|
||||||
gate->nonce_index = DECRED_NONCE_INDEX;
|
|
||||||
gate->work_data_size = DECRED_DATA_SIZE;
|
|
||||||
gate->work_cmp_size = DECRED_WORK_COMPARE_SIZE;
|
|
||||||
allow_mininginfo = false;
|
|
||||||
have_gbt = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@@ -1,36 +0,0 @@
|
|||||||
#ifndef __DECRED_GATE_H__
|
|
||||||
#define __DECRED_GATE_H__
|
|
||||||
|
|
||||||
#include "algo-gate-api.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define DECRED_NBITS_INDEX 29
|
|
||||||
#define DECRED_NTIME_INDEX 34
|
|
||||||
#define DECRED_NONCE_INDEX 35
|
|
||||||
#define DECRED_XNONCE_INDEX 36
|
|
||||||
#define DECRED_DATA_SIZE 192
|
|
||||||
#define DECRED_WORK_COMPARE_SIZE 140
|
|
||||||
#define DECRED_MIDSTATE_LEN 128
|
|
||||||
|
|
||||||
#if defined (__AVX2__)
|
|
||||||
//void blakehash_84way(void *state, const void *input);
|
|
||||||
//int scanhash_blake_8way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
// uint64_t *hashes_done );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__SSE4_2__)
|
|
||||||
#define DECRED_4WAY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined (DECRED_4WAY)
|
|
||||||
void decred_hash_4way(void *state, const void *input);
|
|
||||||
int scanhash_decred_4way( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void decred_hash( void *state, const void *input );
|
|
||||||
int scanhash_decred( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,11 +1,10 @@
|
|||||||
#include "decred-gate.h"
|
#include "miner.h"
|
||||||
|
#include "algo-gate-api.h"
|
||||||
#include "sph_blake.h"
|
#include "sph_blake.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#ifndef min
|
#ifndef min
|
||||||
#define min(a,b) (a>b ? b : a)
|
#define min(a,b) (a>b ? b : a)
|
||||||
@@ -14,33 +13,33 @@
|
|||||||
#define max(a,b) (a<b ? b : a)
|
#define max(a,b) (a<b ? b : a)
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
#define DECRED_NBITS_INDEX 29
|
#define DECRED_NBITS_INDEX 29
|
||||||
#define DECRED_NTIME_INDEX 34
|
#define DECRED_NTIME_INDEX 34
|
||||||
#define DECRED_NONCE_INDEX 35
|
#define DECRED_NONCE_INDEX 35
|
||||||
#define DECRED_XNONCE_INDEX 36
|
#define DECRED_XNONCE_INDEX 36
|
||||||
#define DECRED_DATA_SIZE 192
|
#define DECRED_DATA_SIZE 192
|
||||||
#define DECRED_WORK_COMPARE_SIZE 140
|
#define DECRED_WORK_COMPARE_SIZE 140
|
||||||
*/
|
|
||||||
static __thread sph_blake256_context blake_mid;
|
static __thread sph_blake256_context blake_mid;
|
||||||
static __thread bool ctx_midstate_done = false;
|
static __thread bool ctx_midstate_done = false;
|
||||||
|
|
||||||
void decred_hash(void *state, const void *input)
|
void decred_hash(void *state, const void *input)
|
||||||
{
|
{
|
||||||
// #define MIDSTATE_LEN 128
|
#define MIDSTATE_LEN 128
|
||||||
sph_blake256_context ctx __attribute__ ((aligned (64)));
|
sph_blake256_context ctx;
|
||||||
|
|
||||||
uint8_t *ending = (uint8_t*) input;
|
uint8_t *ending = (uint8_t*) input;
|
||||||
ending += DECRED_MIDSTATE_LEN;
|
ending += MIDSTATE_LEN;
|
||||||
|
|
||||||
if (!ctx_midstate_done) {
|
if (!ctx_midstate_done) {
|
||||||
sph_blake256_init(&blake_mid);
|
sph_blake256_init(&blake_mid);
|
||||||
sph_blake256(&blake_mid, input, DECRED_MIDSTATE_LEN);
|
sph_blake256(&blake_mid, input, MIDSTATE_LEN);
|
||||||
ctx_midstate_done = true;
|
ctx_midstate_done = true;
|
||||||
}
|
}
|
||||||
memcpy(&ctx, &blake_mid, sizeof(blake_mid));
|
memcpy(&ctx, &blake_mid, sizeof(blake_mid));
|
||||||
|
|
||||||
sph_blake256(&ctx, ending, (180 - DECRED_MIDSTATE_LEN));
|
sph_blake256(&ctx, ending, (180 - MIDSTATE_LEN));
|
||||||
sph_blake256_close(&ctx, state);
|
sph_blake256_close(&ctx, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,14 +53,14 @@ void decred_hash_simple(void *state, const void *input)
|
|||||||
|
|
||||||
int scanhash_decred(int thr_id, struct work *work, uint32_t max_nonce, uint64_t *hashes_done)
|
int scanhash_decred(int thr_id, struct work *work, uint32_t max_nonce, uint64_t *hashes_done)
|
||||||
{
|
{
|
||||||
uint32_t _ALIGN(64) endiandata[48];
|
uint32_t _ALIGN(128) endiandata[48];
|
||||||
uint32_t _ALIGN(64) hash32[8];
|
uint32_t _ALIGN(128) hash32[8];
|
||||||
uint32_t *pdata = work->data;
|
uint32_t *pdata = work->data;
|
||||||
uint32_t *ptarget = work->target;
|
uint32_t *ptarget = work->target;
|
||||||
|
|
||||||
// #define DCR_NONCE_OFT32 35
|
#define DCR_NONCE_OFT32 35
|
||||||
|
|
||||||
const uint32_t first_nonce = pdata[DECRED_NONCE_INDEX];
|
const uint32_t first_nonce = pdata[DCR_NONCE_OFT32];
|
||||||
const uint32_t HTarget = opt_benchmark ? 0x7f : ptarget[7];
|
const uint32_t HTarget = opt_benchmark ? 0x7f : ptarget[7];
|
||||||
|
|
||||||
uint32_t n = first_nonce;
|
uint32_t n = first_nonce;
|
||||||
@@ -81,7 +80,7 @@ int scanhash_decred(int thr_id, struct work *work, uint32_t max_nonce, uint64_t
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
//be32enc(&endiandata[DCR_NONCE_OFT32], n);
|
//be32enc(&endiandata[DCR_NONCE_OFT32], n);
|
||||||
endiandata[DECRED_NONCE_INDEX] = n;
|
endiandata[DCR_NONCE_OFT32] = n;
|
||||||
decred_hash(hash32, endiandata);
|
decred_hash(hash32, endiandata);
|
||||||
|
|
||||||
if (hash32[7] <= HTarget && fulltest(hash32, ptarget)) {
|
if (hash32[7] <= HTarget && fulltest(hash32, ptarget)) {
|
||||||
@@ -92,7 +91,7 @@ int scanhash_decred(int thr_id, struct work *work, uint32_t max_nonce, uint64_t
|
|||||||
applog_hash(ptarget);
|
applog_hash(ptarget);
|
||||||
applog_compare_hash(hash32, ptarget);
|
applog_compare_hash(hash32, ptarget);
|
||||||
#endif
|
#endif
|
||||||
pdata[DECRED_NONCE_INDEX] = n;
|
pdata[DCR_NONCE_OFT32] = n;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,17 +100,24 @@ int scanhash_decred(int thr_id, struct work *work, uint32_t max_nonce, uint64_t
|
|||||||
} while (n < max_nonce && !work_restart[thr_id].restart);
|
} while (n < max_nonce && !work_restart[thr_id].restart);
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
*hashes_done = n - first_nonce + 1;
|
||||||
pdata[DECRED_NONCE_INDEX] = n;
|
pdata[DCR_NONCE_OFT32] = n;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
uint32_t *decred_get_nonceptr( uint32_t *work_data )
|
uint32_t *decred_get_nonceptr( uint32_t *work_data )
|
||||||
{
|
{
|
||||||
return &work_data[ DECRED_NONCE_INDEX ];
|
return &work_data[ DECRED_NONCE_INDEX ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// does decred need a custom stratum_get_g_work to fix nicehash
|
||||||
|
// bad extranonce2 size?
|
||||||
|
//
|
||||||
|
// does decred need a custom init_nonce?
|
||||||
|
// does it need to increment nonce, seems not because gen_work_now always
|
||||||
|
// returns true
|
||||||
|
|
||||||
double decred_calc_network_diff( struct work* work )
|
double decred_calc_network_diff( struct work* work )
|
||||||
|
//void decred_calc_network_diff( struct work* work )
|
||||||
{
|
{
|
||||||
// sample for diff 43.281 : 1c05ea29
|
// sample for diff 43.281 : 1c05ea29
|
||||||
// todo: endian reversed on longpoll could be zr5 specific...
|
// todo: endian reversed on longpoll could be zr5 specific...
|
||||||
@@ -173,7 +179,7 @@ void decred_be_build_stratum_request( char *req, struct work *work,
|
|||||||
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr );
|
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr );
|
||||||
free(xnonce2str);
|
free(xnonce2str);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
// data shared between gen_merkle_root and build_extraheader.
|
// data shared between gen_merkle_root and build_extraheader.
|
||||||
__thread uint32_t decred_extraheader[32] = { 0 };
|
__thread uint32_t decred_extraheader[32] = { 0 };
|
||||||
@@ -189,7 +195,6 @@ void decred_gen_merkle_root( char* merkle_root, struct stratum_ctx* sctx )
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
#define min(a,b) (a>b ? (b) :(a))
|
#define min(a,b) (a>b ? (b) :(a))
|
||||||
|
|
||||||
void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
|
void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
|
||||||
@@ -227,15 +232,11 @@ void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
|
|||||||
for ( i = 0; i < headersize/4; i++ ) // header
|
for ( i = 0; i < headersize/4; i++ ) // header
|
||||||
g_work->data[17 + i] = extraheader[i];
|
g_work->data[17 + i] = extraheader[i];
|
||||||
// extradata
|
// extradata
|
||||||
|
|
||||||
for ( i = 0; i < sctx->xnonce1_size/4; i++ )
|
for ( i = 0; i < sctx->xnonce1_size/4; i++ )
|
||||||
g_work->data[ DECRED_XNONCE_INDEX + i ] = extradata[i];
|
g_work->data[ DECRED_XNONCE_INDEX + i ] = extradata[i];
|
||||||
for ( i = DECRED_XNONCE_INDEX + sctx->xnonce1_size/4; i < 45; i++ )
|
for ( i = DECRED_XNONCE_INDEX + sctx->xnonce1_size/4; i < 45; i++ )
|
||||||
g_work->data[i] = 0;
|
g_work->data[i] = 0;
|
||||||
g_work->data[37] = (rand()*4) << 8;
|
g_work->data[37] = (rand()*4) << 8;
|
||||||
// block header suffix from coinb2 (stake version)
|
|
||||||
memcpy( &g_work->data[44],
|
|
||||||
&sctx->job.coinbase[ sctx->job.coinbase_size-4 ], 4 );
|
|
||||||
sctx->bloc_height = g_work->data[32];
|
sctx->bloc_height = g_work->data[32];
|
||||||
//applog_hex(work->data, 180);
|
//applog_hex(work->data, 180);
|
||||||
//applog_hex(&work->data[36], 36);
|
//applog_hex(&work->data[36], 36);
|
||||||
@@ -243,6 +244,21 @@ void decred_build_extraheader( struct work* g_work, struct stratum_ctx* sctx )
|
|||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool decred_prevent_dupes( struct work* work, struct stratum_ctx* stratum,
|
||||||
|
int thr_id )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
if ( have_stratum && strcmp(stratum->job.job_id, work->job_id) )
|
||||||
|
// need to regen g_work..
|
||||||
|
return true;
|
||||||
|
// extradata: prevent duplicates
|
||||||
|
work->data[ DECRED_XNONCE_INDEX ] += 1;
|
||||||
|
work->data[ DECRED_XNONCE_INDEX + 1 ] |= thr_id;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
bool decred_ready_to_mine( struct work* work, struct stratum_ctx* stratum,
|
bool decred_ready_to_mine( struct work* work, struct stratum_ctx* stratum,
|
||||||
int thr_id )
|
int thr_id )
|
||||||
{
|
{
|
||||||
@@ -266,13 +282,14 @@ bool register_decred_algo( algo_gate_t* gate )
|
|||||||
gate->optimizations = SSE2_OPT;
|
gate->optimizations = SSE2_OPT;
|
||||||
gate->scanhash = (void*)&scanhash_decred;
|
gate->scanhash = (void*)&scanhash_decred;
|
||||||
gate->hash = (void*)&decred_hash;
|
gate->hash = (void*)&decred_hash;
|
||||||
|
gate->hash_alt = (void*)&decred_hash;
|
||||||
gate->get_nonceptr = (void*)&decred_get_nonceptr;
|
gate->get_nonceptr = (void*)&decred_get_nonceptr;
|
||||||
gate->get_max64 = (void*)&get_max64_0x3fffffLL;
|
gate->get_max64 = (void*)&get_max64_0x3fffffLL;
|
||||||
gate->display_extra_data = (void*)&decred_decode_extradata;
|
gate->display_extra_data = (void*)&decred_decode_extradata;
|
||||||
gate->build_stratum_request = (void*)&decred_be_build_stratum_request;
|
gate->build_stratum_request = (void*)&decred_be_build_stratum_request;
|
||||||
gate->work_decode = (void*)&std_be_work_decode;
|
// gate->gen_merkle_root = (void*)&decred_gen_merkle_root;
|
||||||
gate->submit_getwork_result = (void*)&std_be_submit_getwork_result;
|
|
||||||
gate->build_extraheader = (void*)&decred_build_extraheader;
|
gate->build_extraheader = (void*)&decred_build_extraheader;
|
||||||
|
// gate->prevent_dupes = (void*)&decred_prevent_dupes;
|
||||||
gate->ready_to_mine = (void*)&decred_ready_to_mine;
|
gate->ready_to_mine = (void*)&decred_ready_to_mine;
|
||||||
gate->nbits_index = DECRED_NBITS_INDEX;
|
gate->nbits_index = DECRED_NBITS_INDEX;
|
||||||
gate->ntime_index = DECRED_NTIME_INDEX;
|
gate->ntime_index = DECRED_NTIME_INDEX;
|
||||||
@@ -283,4 +300,4 @@ bool register_decred_algo( algo_gate_t* gate )
|
|||||||
have_gbt = false;
|
have_gbt = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
@@ -1,175 +0,0 @@
|
|||||||
#include "pentablake-gate.h"
|
|
||||||
|
|
||||||
#if defined (__AVX2__)
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "blake-hash-4way.h"
|
|
||||||
#include "sph_blake.h"
|
|
||||||
|
|
||||||
//#define DEBUG_ALGO
|
|
||||||
|
|
||||||
extern void pentablakehash_4way( void *output, const void *input )
|
|
||||||
{
|
|
||||||
unsigned char _ALIGN(32) hash[128];
|
|
||||||
// // same as uint32_t hashA[16], hashB[16];
|
|
||||||
// #define hashB hash+64
|
|
||||||
|
|
||||||
uint64_t hash0[8] __attribute__ ((aligned (64)));
|
|
||||||
uint64_t hash1[8] __attribute__ ((aligned (64)));
|
|
||||||
uint64_t hash2[8] __attribute__ ((aligned (64)));
|
|
||||||
uint64_t hash3[8] __attribute__ ((aligned (64)));
|
|
||||||
uint64_t vhash[8*4] __attribute__ ((aligned (64)));
|
|
||||||
blake512_4way_context ctx;
|
|
||||||
|
|
||||||
|
|
||||||
blake512_4way_init( &ctx );
|
|
||||||
blake512_4way( &ctx, input, 80 );
|
|
||||||
blake512_4way_close( &ctx, vhash );
|
|
||||||
|
|
||||||
uint64_t sin0[10], sin1[10], sin2[10], sin3[10];
|
|
||||||
mm256_deinterleave_4x64( sin0, sin1, sin2, sin3, input, 640 );
|
|
||||||
sph_blake512_context ctx2_blake;
|
|
||||||
sph_blake512_init(&ctx2_blake);
|
|
||||||
sph_blake512(&ctx2_blake, sin0, 80);
|
|
||||||
sph_blake512_close(&ctx2_blake, (void*) hash);
|
|
||||||
|
|
||||||
mm256_deinterleave_4x64( hash0, hash1, hash2, hash3, vhash, 512 );
|
|
||||||
uint64_t* hash64 = (uint64_t*)hash;
|
|
||||||
for( int i = 0; i < 8; i++ )
|
|
||||||
{
|
|
||||||
if ( hash0[i] != hash64[i] )
|
|
||||||
printf("hash mismatch %u\n",i);
|
|
||||||
}
|
|
||||||
|
|
||||||
blake512_4way_init( &ctx );
|
|
||||||
blake512_4way( &ctx, vhash, 64 );
|
|
||||||
blake512_4way_close( &ctx, vhash );
|
|
||||||
|
|
||||||
blake512_4way_init( &ctx );
|
|
||||||
blake512_4way( &ctx, vhash, 64 );
|
|
||||||
blake512_4way_close( &ctx, vhash );
|
|
||||||
|
|
||||||
blake512_4way_init( &ctx );
|
|
||||||
blake512_4way( &ctx, vhash, 64 );
|
|
||||||
blake512_4way_close( &ctx, vhash );
|
|
||||||
|
|
||||||
blake512_4way_init( &ctx );
|
|
||||||
blake512_4way( &ctx, vhash, 64 );
|
|
||||||
blake512_4way_close( &ctx, vhash );
|
|
||||||
|
|
||||||
mm256_deinterleave_4x64( hash0, hash1, hash2, hash3, vhash, 512 );
|
|
||||||
memcpy( output, hash0, 32 );
|
|
||||||
memcpy( output+32, hash1, 32 );
|
|
||||||
memcpy( output+64, hash2, 32 );
|
|
||||||
memcpy( output+96, hash3, 32 );
|
|
||||||
|
|
||||||
/*
|
|
||||||
uint64_t sin0[10] __attribute__ ((aligned (64)));
|
|
||||||
uint64_t sin1[10] __attribute__ ((aligned (64)));
|
|
||||||
uint64_t sin2[10] __attribute__ ((aligned (64)));
|
|
||||||
uint64_t sin3[10] __attribute__ ((aligned (64)));
|
|
||||||
|
|
||||||
sph_blake512_context ctx_blake;
|
|
||||||
|
|
||||||
sph_blake512_init(&ctx_blake);
|
|
||||||
sph_blake512(&ctx_blake, input, 80);
|
|
||||||
sph_blake512_close(&ctx_blake, hash);
|
|
||||||
|
|
||||||
sph_blake512_init(&ctx_blake);
|
|
||||||
sph_blake512(&ctx_blake, hash, 64);
|
|
||||||
sph_blake512_close(&ctx_blake, hash);
|
|
||||||
|
|
||||||
sph_blake512_init(&ctx_blake);
|
|
||||||
sph_blake512(&ctx_blake, hash, 64);
|
|
||||||
sph_blake512_close(&ctx_blake, hash);
|
|
||||||
|
|
||||||
sph_blake512_init(&ctx_blake);
|
|
||||||
sph_blake512(&ctx_blake, hash, 64);
|
|
||||||
sph_blake512_close(&ctx_blake, hash);
|
|
||||||
|
|
||||||
sph_blake512_init(&ctx_blake);
|
|
||||||
sph_blake512(&ctx_blake, hash, 64);
|
|
||||||
sph_blake512_close(&ctx_blake, hash);
|
|
||||||
|
|
||||||
memcpy(output, hash, 32);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanhash_pentablake_4way( int thr_id, struct work *work,
|
|
||||||
uint32_t max_nonce, uint64_t *hashes_done )
|
|
||||||
{
|
|
||||||
uint32_t hash[4*8] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t vdata[20*4] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t endiandata[32] __attribute__ ((aligned (64)));
|
|
||||||
uint32_t *pdata = work->data;
|
|
||||||
uint32_t *ptarget = work->target;
|
|
||||||
uint32_t n = pdata[19] - 1;
|
|
||||||
const uint32_t first_nonce = pdata[19];
|
|
||||||
const uint32_t Htarg = ptarget[7];
|
|
||||||
uint32_t *nonces = work->nonces;
|
|
||||||
int num_found = 0;
|
|
||||||
uint32_t *noncep = vdata + 73; // 9*8 + 1
|
|
||||||
|
|
||||||
// uint32_t _ALIGN(32) hash64[8];
|
|
||||||
// uint32_t _ALIGN(32) endiandata[32];
|
|
||||||
|
|
||||||
uint64_t htmax[] = {
|
|
||||||
0,
|
|
||||||
0xF,
|
|
||||||
0xFF,
|
|
||||||
0xFFF,
|
|
||||||
0xFFFF,
|
|
||||||
0x10000000
|
|
||||||
};
|
|
||||||
uint32_t masks[] = {
|
|
||||||
0xFFFFFFFF,
|
|
||||||
0xFFFFFFF0,
|
|
||||||
0xFFFFFF00,
|
|
||||||
0xFFFFF000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
// we need bigendian data...
|
|
||||||
swab32_array( endiandata, pdata, 20 );
|
|
||||||
|
|
||||||
uint64_t *edata = (uint64_t*)endiandata;
|
|
||||||
mm256_interleave_4x64( (uint64_t*)vdata, edata, edata, edata, edata, 640 );
|
|
||||||
|
|
||||||
for ( int m=0; m < 6; m++ )
|
|
||||||
{
|
|
||||||
if ( Htarg <= htmax[m] )
|
|
||||||
{
|
|
||||||
uint32_t mask = masks[m];
|
|
||||||
do {
|
|
||||||
be32enc( noncep, n );
|
|
||||||
be32enc( noncep+2, n+1 );
|
|
||||||
be32enc( noncep+4, n+2 );
|
|
||||||
be32enc( noncep+6, n+3 );
|
|
||||||
|
|
||||||
pentablakehash_4way( hash, vdata );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 4; i++ )
|
|
||||||
if ( !( (hash+(i<<3))[7] & mask )
|
|
||||||
&& fulltest( hash+(i<<3), ptarget ) )
|
|
||||||
{
|
|
||||||
nonces[ num_found++ ] = n+i;
|
|
||||||
work_set_target_ratio( work, hash+(i<<3) );
|
|
||||||
}
|
|
||||||
n += 4;
|
|
||||||
|
|
||||||
} while (n < max_nonce && !work_restart[thr_id].restart);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*hashes_done = n - first_nonce + 1;
|
|
||||||
pdata[19] = n;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,16 +0,0 @@
|
|||||||
#include "pentablake-gate.h"
|
|
||||||
|
|
||||||
bool register_pentablake_algo( algo_gate_t* gate )
|
|
||||||
{
|
|
||||||
#if defined (PENTABLAKE_4WAY)
|
|
||||||
gate->scanhash = (void*)&scanhash_pentablake_4way;
|
|
||||||
gate->hash = (void*)&pentablakehash_4way;
|
|
||||||
#else
|
|
||||||
gate->scanhash = (void*)&scanhash_pentablake;
|
|
||||||
gate->hash = (void*)&pentablakehash;
|
|
||||||
#endif
|
|
||||||
gate->optimizations = AVX2_OPT;
|
|
||||||
gate->get_max64 = (void*)&get_max64_0x3ffff;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
@@ -1,21 +0,0 @@
|
|||||||
#ifndef __PENTABLAKE_GATE_H__
|
|
||||||
#define __PENTABLAKE_GATE_H__
|
|
||||||
|
|
||||||
#include "algo-gate-api.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#if defined(__AVX2__)
|
|
||||||
#define PENTABLAKE_4WAY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PENTABLAKE_4WAY)
|
|
||||||
void pentablakehash_4way( void *state, const void *input );
|
|
||||||
int scanhash_pentablake_4way( int thr_id, struct work *work,
|
|
||||||
uint32_t max_nonce, uint64_t *hashes_done );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void pentablakehash( void *state, const void *input );
|
|
||||||
int scanhash_pentablake( int thr_id, struct work *work, uint32_t max_nonce,
|
|
||||||
uint64_t *hashes_done );
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,4 +1,5 @@
|
|||||||
#include "pentablake-gate.h"
|
#include "miner.h"
|
||||||
|
#include "algo-gate-api.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -110,3 +111,11 @@ int scanhash_pentablake(int thr_id, struct work *work, uint32_t max_nonce,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool register_pentablake_algo( algo_gate_t* gate )
|
||||||
|
{
|
||||||
|
gate->scanhash = (void*)&scanhash_pentablake;
|
||||||
|
gate->hash = (void*)&pentablakehash;
|
||||||
|
gate->get_max64 = (void*)&get_max64_0x3ffff;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -813,7 +813,6 @@ blake32(sph_blake_small_context *sc, const void *data, size_t len)
|
|||||||
|
|
||||||
buf = sc->buf;
|
buf = sc->buf;
|
||||||
ptr = sc->ptr;
|
ptr = sc->ptr;
|
||||||
|
|
||||||
if (len < (sizeof sc->buf) - ptr) {
|
if (len < (sizeof sc->buf) - ptr) {
|
||||||
memcpy(buf + ptr, data, len);
|
memcpy(buf + ptr, data, len);
|
||||||
ptr += len;
|
ptr += len;
|
||||||
@@ -872,7 +871,6 @@ blake32_close(sph_blake_small_context *sc,
|
|||||||
} else {
|
} else {
|
||||||
sc->T0 -= 512 - bit_len;
|
sc->T0 -= 512 - bit_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bit_len <= 446) {
|
if (bit_len <= 446) {
|
||||||
memset(u.buf + ptr + 1, 0, 55 - ptr);
|
memset(u.buf + ptr + 1, 0, 55 - ptr);
|
||||||
if (out_size_w32 == 8)
|
if (out_size_w32 == 8)
|
||||||
@@ -892,9 +890,9 @@ blake32_close(sph_blake_small_context *sc,
|
|||||||
sph_enc32be_aligned(u.buf + 60, tl);
|
sph_enc32be_aligned(u.buf + 60, tl);
|
||||||
blake32(sc, u.buf, 64);
|
blake32(sc, u.buf, 64);
|
||||||
}
|
}
|
||||||
out = dst;
|
out = dst;
|
||||||
for (k = 0; k < out_size_w32; k ++)
|
for (k = 0; k < out_size_w32; k ++)
|
||||||
sph_enc32be(out + (k << 2), sc->H[k]);
|
sph_enc32be(out + (k << 2), sc->H[k]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SPH_64
|
#if SPH_64
|
||||||
@@ -984,11 +982,9 @@ blake64_close(sph_blake_big_context *sc,
|
|||||||
u.buf[111] |= 1;
|
u.buf[111] |= 1;
|
||||||
sph_enc64be_aligned(u.buf + 112, th);
|
sph_enc64be_aligned(u.buf + 112, th);
|
||||||
sph_enc64be_aligned(u.buf + 120, tl);
|
sph_enc64be_aligned(u.buf + 120, tl);
|
||||||
|
|
||||||
blake64(sc, u.buf + ptr, 128 - ptr);
|
blake64(sc, u.buf + ptr, 128 - ptr);
|
||||||
} else {
|
} else {
|
||||||
memset(u.buf + ptr + 1, 0, 127 - ptr);
|
memset(u.buf + ptr + 1, 0, 127 - ptr);
|
||||||
|
|
||||||
blake64(sc, u.buf + ptr, 128 - ptr);
|
blake64(sc, u.buf + ptr, 128 - ptr);
|
||||||
sc->T0 = SPH_C64(0xFFFFFFFFFFFFFC00);
|
sc->T0 = SPH_C64(0xFFFFFFFFFFFFFC00);
|
||||||
sc->T1 = SPH_C64(0xFFFFFFFFFFFFFFFF);
|
sc->T1 = SPH_C64(0xFFFFFFFFFFFFFFFF);
|
||||||
@@ -997,7 +993,6 @@ blake64_close(sph_blake_big_context *sc,
|
|||||||
u.buf[111] = 1;
|
u.buf[111] = 1;
|
||||||
sph_enc64be_aligned(u.buf + 112, th);
|
sph_enc64be_aligned(u.buf + 112, th);
|
||||||
sph_enc64be_aligned(u.buf + 120, tl);
|
sph_enc64be_aligned(u.buf + 120, tl);
|
||||||
|
|
||||||
blake64(sc, u.buf, 128);
|
blake64(sc, u.buf, 128);
|
||||||
}
|
}
|
||||||
out = dst;
|
out = dst;
|
||||||
|
@@ -42,7 +42,7 @@ extern "C"{
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "algo/sha/sph_types.h"
|
#include "algo/sha3/sph_types.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output size (in bits) for BLAKE-224.
|
* Output size (in bits) for BLAKE-224.
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "algo/sha/sph_types.h"
|
#include "algo/sha3/sph_types.h"
|
||||||
#include "sph_blake2b.h"
|
#include "sph_blake2b.h"
|
||||||
|
|
||||||
// Cyclic right rotation.
|
// Cyclic right rotation.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,95 +0,0 @@
|
|||||||
/* $Id: sph_bmw.h 216 2010-06-08 09:46:57Z tp $ */
|
|
||||||
/**
|
|
||||||
* BMW interface. BMW (aka "Blue Midnight Wish") is a family of
|
|
||||||
* functions which differ by their output size; this implementation
|
|
||||||
* defines BMW for output sizes 224, 256, 384 and 512 bits.
|
|
||||||
*
|
|
||||||
* ==========================(LICENSE BEGIN)============================
|
|
||||||
*
|
|
||||||
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* ===========================(LICENSE END)=============================
|
|
||||||
*
|
|
||||||
* @file sph_bmw.h
|
|
||||||
* @author Thomas Pornin <thomas.pornin@cryptolog.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BMW_HASH_H__
|
|
||||||
#define BMW_HASH_H__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#ifdef __AVX2__
|
|
||||||
|
|
||||||
#include "algo/sha/sph_types.h"
|
|
||||||
#include "avxdefs.h"
|
|
||||||
|
|
||||||
#define SPH_SIZE_bmw256 256
|
|
||||||
|
|
||||||
#define SPH_SIZE_bmw512 512
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__m128i buf[64];
|
|
||||||
__m128i H[16];
|
|
||||||
size_t ptr;
|
|
||||||
sph_u32 bit_count; // assume bit_count fits in 32 bits
|
|
||||||
} bmw_4way_small_context;
|
|
||||||
|
|
||||||
typedef bmw_4way_small_context bmw256_4way_context;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__m256i buf[16];
|
|
||||||
__m256i H[16];
|
|
||||||
size_t ptr;
|
|
||||||
sph_u64 bit_count;
|
|
||||||
} bmw_4way_big_context;
|
|
||||||
|
|
||||||
typedef bmw_4way_big_context bmw512_4way_context;
|
|
||||||
|
|
||||||
void bmw256_4way_init(void *cc);
|
|
||||||
|
|
||||||
void bmw256_4way(void *cc, const void *data, size_t len);
|
|
||||||
|
|
||||||
void bmw256_4way_close(void *cc, void *dst);
|
|
||||||
|
|
||||||
void bmw256_4way_addbits_and_close(
|
|
||||||
void *cc, unsigned ub, unsigned n, void *dst);
|
|
||||||
|
|
||||||
void bmw512_4way_init(void *cc);
|
|
||||||
|
|
||||||
void bmw512_4way(void *cc, const void *data, size_t len);
|
|
||||||
|
|
||||||
void bmw512_4way_close(void *cc, void *dst);
|
|
||||||
|
|
||||||
void bmw512_4way_addbits_and_close(
|
|
||||||
void *cc, unsigned ub, unsigned n, void *dst);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "miner.h"
|
||||||
#include "algo-gate-api.h"
|
#include "algo-gate-api.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@@ -41,7 +41,7 @@ extern "C"{
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "algo/sha/sph_types.h"
|
#include "algo/sha3/sph_types.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output size (in bits) for BMW-224.
|
* Output size (in bits) for BMW-224.
|
||||||
|
@@ -477,7 +477,7 @@ do { \
|
|||||||
for (u = 0; u < 16; u ++) \
|
for (u = 0; u < 16; u ++) \
|
||||||
sph_enc64le_aligned(data + 8 * u, h2[u]); \
|
sph_enc64le_aligned(data + 8 * u, h2[u]); \
|
||||||
dh = h1; \
|
dh = h1; \
|
||||||
h = (sph_u64*)final_b; \
|
h = final_b; \
|
||||||
} \
|
} \
|
||||||
/* end wrapped for break loop */ \
|
/* end wrapped for break loop */ \
|
||||||
out = dst; \
|
out = dst; \
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include "miner.h"
|
||||||
#include "algo-gate-api.h"
|
#include "algo-gate-api.h"
|
||||||
|
|
||||||
#if defined(__arm__) || defined(_MSC_VER)
|
#if defined(__arm__) || defined(_MSC_VER)
|
||||||
|
@@ -3,8 +3,7 @@
|
|||||||
#include "cryptonight.h"
|
#include "cryptonight.h"
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
#include "crypto/c_keccak.h"
|
#include "crypto/c_keccak.h"
|
||||||
#include <immintrin.h>
|
#include "avxdefs.h"
|
||||||
//#include "avxdefs.h"
|
|
||||||
|
|
||||||
void aesni_parallel_noxor(uint8_t *long_state, uint8_t *text, uint8_t *ExpandedKey);
|
void aesni_parallel_noxor(uint8_t *long_state, uint8_t *text, uint8_t *ExpandedKey);
|
||||||
void aesni_parallel_xor(uint8_t *text, uint8_t *ExpandedKey, uint8_t *long_state);
|
void aesni_parallel_xor(uint8_t *text, uint8_t *ExpandedKey, uint8_t *long_state);
|
||||||
@@ -110,43 +109,43 @@ static __thread cryptonight_ctx ctx;
|
|||||||
void cryptonight_hash_aes( void *restrict output, const void *input, int len )
|
void cryptonight_hash_aes( void *restrict output, const void *input, int len )
|
||||||
{
|
{
|
||||||
#ifndef NO_AES_NI
|
#ifndef NO_AES_NI
|
||||||
|
keccak( (const uint8_t*)input, 76, (char*)&ctx.state.hs.b, 200 );
|
||||||
uint8_t ExpandedKey[256] __attribute__((aligned(64)));
|
uint8_t ExpandedKey[256] __attribute__((aligned(64)));
|
||||||
__m128i *longoutput, *expkey, *xmminput;
|
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
|
|
||||||
keccak( (const uint8_t*)input, 76, (char*)&ctx.state.hs.b, 200 );
|
memcpy(ctx.text, ctx.state.init, INIT_SIZE_BYTE);
|
||||||
memcpy( ExpandedKey, ctx.state.hs.b, AES_KEY_SIZE );
|
memcpy(ExpandedKey, ctx.state.hs.b, AES_KEY_SIZE);
|
||||||
ExpandAESKey256( ExpandedKey );
|
ExpandAESKey256(ExpandedKey);
|
||||||
memcpy( ctx.text, ctx.state.init, INIT_SIZE_BYTE );
|
|
||||||
|
|
||||||
longoutput = (__m128i*)ctx.long_state;
|
__m128i *longoutput, *expkey, *xmminput;
|
||||||
xmminput = (__m128i*)ctx.text;
|
longoutput = (__m128i *)ctx.long_state;
|
||||||
expkey = (__m128i*)ExpandedKey;
|
expkey = (__m128i *)ExpandedKey;
|
||||||
|
xmminput = (__m128i *)ctx.text;
|
||||||
|
|
||||||
// prefetch expkey, xmminput and enough longoutput for 4 iterations
|
//for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE)
|
||||||
|
// aesni_parallel_noxor(&ctx->long_state[i], ctx->text, ExpandedKey);
|
||||||
|
|
||||||
|
// prefetch expkey, all of xmminput and enough longoutput for 4 loops
|
||||||
_mm_prefetch( xmminput, _MM_HINT_T0 );
|
_mm_prefetch( xmminput, _MM_HINT_T0 );
|
||||||
_mm_prefetch( xmminput + 4, _MM_HINT_T0 );
|
_mm_prefetch( xmminput + 4, _MM_HINT_T0 );
|
||||||
|
for ( i = 0; i < 64; i += 16 )
|
||||||
|
{
|
||||||
|
_mm_prefetch( longoutput + i, _MM_HINT_T0 );
|
||||||
|
_mm_prefetch( longoutput + i + 4, _MM_HINT_T0 );
|
||||||
|
_mm_prefetch( longoutput + i + 8, _MM_HINT_T0 );
|
||||||
|
_mm_prefetch( longoutput + i + 12, _MM_HINT_T0 );
|
||||||
|
}
|
||||||
_mm_prefetch( expkey, _MM_HINT_T0 );
|
_mm_prefetch( expkey, _MM_HINT_T0 );
|
||||||
_mm_prefetch( expkey + 4, _MM_HINT_T0 );
|
_mm_prefetch( expkey + 4, _MM_HINT_T0 );
|
||||||
_mm_prefetch( expkey + 8, _MM_HINT_T0 );
|
_mm_prefetch( expkey + 8, _MM_HINT_T0 );
|
||||||
for ( i = 0; i < 64; i += 16 )
|
|
||||||
{
|
|
||||||
__builtin_prefetch( longoutput + i, 1, 0 );
|
|
||||||
__builtin_prefetch( longoutput + i + 4, 1, 0 );
|
|
||||||
__builtin_prefetch( longoutput + i + 8, 1, 0 );
|
|
||||||
__builtin_prefetch( longoutput + i + 12, 1, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// n-4 iterations
|
for ( i = 0; likely( i < MEMORY_M128I ); i += INIT_SIZE_M128I )
|
||||||
for ( i = 0; likely( i < MEMORY_M128I - 4*INIT_SIZE_M128I );
|
|
||||||
i += INIT_SIZE_M128I )
|
|
||||||
{
|
{
|
||||||
// prefetch 4 iterations ahead.
|
// prefetch 4 loops ahead,
|
||||||
__builtin_prefetch( longoutput + i + 64, 1, 0 );
|
__builtin_prefetch( longoutput + i + 64, 1, 0 );
|
||||||
__builtin_prefetch( longoutput + i + 68, 1, 0 );
|
__builtin_prefetch( longoutput + i + 68, 1, 0 );
|
||||||
|
|
||||||
for ( j = 0; j < 10; j++ )
|
for (j = 0; j < 10; j++ )
|
||||||
{
|
{
|
||||||
xmminput[0] = _mm_aesenc_si128( xmminput[0], expkey[j] );
|
xmminput[0] = _mm_aesenc_si128( xmminput[0], expkey[j] );
|
||||||
xmminput[1] = _mm_aesenc_si128( xmminput[1], expkey[j] );
|
xmminput[1] = _mm_aesenc_si128( xmminput[1], expkey[j] );
|
||||||
@@ -166,99 +165,84 @@ void cryptonight_hash_aes( void *restrict output, const void *input, int len )
|
|||||||
_mm_store_si128( &( longoutput[i+6] ), xmminput[6] );
|
_mm_store_si128( &( longoutput[i+6] ), xmminput[6] );
|
||||||
_mm_store_si128( &( longoutput[i+7] ), xmminput[7] );
|
_mm_store_si128( &( longoutput[i+7] ), xmminput[7] );
|
||||||
}
|
}
|
||||||
// last 4 iterations
|
|
||||||
for ( ; likely( i < MEMORY_M128I ); i += INIT_SIZE_M128I )
|
|
||||||
{
|
|
||||||
for ( j = 0; j < 10; j++ )
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128( xmminput[0], expkey[j] );
|
|
||||||
xmminput[1] = _mm_aesenc_si128( xmminput[1], expkey[j] );
|
|
||||||
xmminput[2] = _mm_aesenc_si128( xmminput[2], expkey[j] );
|
|
||||||
xmminput[3] = _mm_aesenc_si128( xmminput[3], expkey[j] );
|
|
||||||
xmminput[4] = _mm_aesenc_si128( xmminput[4], expkey[j] );
|
|
||||||
xmminput[5] = _mm_aesenc_si128( xmminput[5], expkey[j] );
|
|
||||||
xmminput[6] = _mm_aesenc_si128( xmminput[6], expkey[j] );
|
|
||||||
xmminput[7] = _mm_aesenc_si128( xmminput[7], expkey[j] );
|
|
||||||
}
|
|
||||||
_mm_store_si128( &( longoutput[i ] ), xmminput[0] );
|
|
||||||
_mm_store_si128( &( longoutput[i+1] ), xmminput[1] );
|
|
||||||
_mm_store_si128( &( longoutput[i+2] ), xmminput[2] );
|
|
||||||
_mm_store_si128( &( longoutput[i+3] ), xmminput[3] );
|
|
||||||
_mm_store_si128( &( longoutput[i+4] ), xmminput[4] );
|
|
||||||
_mm_store_si128( &( longoutput[i+5] ), xmminput[5] );
|
|
||||||
_mm_store_si128( &( longoutput[i+6] ), xmminput[6] );
|
|
||||||
_mm_store_si128( &( longoutput[i+7] ), xmminput[7] );
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.a[0] = ((uint64_t *)ctx.state.k)[0] ^ ((uint64_t *)ctx.state.k)[4];
|
// cast_m128i( ctx.a ) = _mm_xor_si128( casti_m128i( ctx.state.k, 0 ) ,
|
||||||
ctx.b[0] = ((uint64_t *)ctx.state.k)[2] ^ ((uint64_t *)ctx.state.k)[6];
|
// casti_m128i( ctx.state.k, 2 ) );
|
||||||
ctx.a[1] = ((uint64_t *)ctx.state.k)[1] ^ ((uint64_t *)ctx.state.k)[5];
|
// cast_m128i( ctx.b ) = _mm_xor_si128( casti_m128i( ctx.state.k, 1 ),
|
||||||
ctx.b[1] = ((uint64_t *)ctx.state.k)[3] ^ ((uint64_t *)ctx.state.k)[7];
|
// casti_m128i( ctx.state.k, 3 ) );
|
||||||
|
|
||||||
uint64_t a[2] __attribute((aligned(16))),
|
ctx.a[0] = ((uint64_t *)ctx.state.k)[0] ^ ((uint64_t *)ctx.state.k)[4];
|
||||||
b[2] __attribute((aligned(16))),
|
ctx.b[0] = ((uint64_t *)ctx.state.k)[2] ^ ((uint64_t *)ctx.state.k)[6];
|
||||||
c[2] __attribute((aligned(16)));
|
ctx.a[1] = ((uint64_t *)ctx.state.k)[1] ^ ((uint64_t *)ctx.state.k)[5];
|
||||||
|
ctx.b[1] = ((uint64_t *)ctx.state.k)[3] ^ ((uint64_t *)ctx.state.k)[7];
|
||||||
|
|
||||||
|
// for (i = 0; i < 2; i++)
|
||||||
|
// {
|
||||||
|
// ctx.a[i] = ((uint64_t *)ctx.state.k)[i] ^ ((uint64_t *)ctx.state.k)[i+4];
|
||||||
|
// ctx.b[i] = ((uint64_t *)ctx.state.k)[i+2] ^ ((uint64_t *)ctx.state.k)[i+6];
|
||||||
|
// }
|
||||||
|
|
||||||
|
__m128i b_x = _mm_load_si128((__m128i *)ctx.b);
|
||||||
|
uint64_t a[2] __attribute((aligned(16))), b[2] __attribute((aligned(16)));
|
||||||
a[0] = ctx.a[0];
|
a[0] = ctx.a[0];
|
||||||
a[1] = ctx.a[1];
|
a[1] = ctx.a[1];
|
||||||
__m128i b_x = _mm_load_si128( (__m128i*)ctx.b );
|
|
||||||
__m128i a_x = _mm_load_si128( (__m128i*)a );
|
for(i = 0; __builtin_expect(i < 0x80000, 1); i++)
|
||||||
__m128i* lsa = (__m128i*)&ctx.long_state[ a[0] & 0x1FFFF0 ];
|
|
||||||
__m128i c_x = _mm_load_si128( lsa );
|
|
||||||
uint64_t *nextblock;
|
|
||||||
uint64_t hi, lo;
|
|
||||||
|
|
||||||
// n-1 iterations
|
|
||||||
for( i = 0; __builtin_expect( i < 0x7ffff, 1 ); i++ )
|
|
||||||
{
|
{
|
||||||
c_x = _mm_aesenc_si128( c_x, a_x );
|
uint64_t c[2];
|
||||||
_mm_store_si128( (__m128i*)c, c_x );
|
__builtin_prefetch( &ctx.long_state[c[0] & 0x1FFFF0], 0, 1 );
|
||||||
b_x = _mm_xor_si128( b_x, c_x );
|
|
||||||
nextblock = (uint64_t *)&ctx.long_state[c[0] & 0x1FFFF0];
|
__m128i c_x = _mm_load_si128(
|
||||||
_mm_store_si128( lsa, b_x );
|
(__m128i *)&ctx.long_state[a[0] & 0x1FFFF0]);
|
||||||
|
__m128i a_x = _mm_load_si128((__m128i *)a);
|
||||||
|
c_x = _mm_aesenc_si128(c_x, a_x);
|
||||||
|
_mm_store_si128((__m128i *)c, c_x);
|
||||||
|
|
||||||
|
b_x = _mm_xor_si128(b_x, c_x);
|
||||||
|
_mm_store_si128((__m128i *)&ctx.long_state[a[0] & 0x1FFFF0], b_x);
|
||||||
|
|
||||||
|
uint64_t *nextblock = (uint64_t *)&ctx.long_state[c[0] & 0x1FFFF0];
|
||||||
|
// uint64_t b[2];
|
||||||
b[0] = nextblock[0];
|
b[0] = nextblock[0];
|
||||||
b[1] = nextblock[1];
|
b[1] = nextblock[1];
|
||||||
|
|
||||||
// hi,lo = 64bit x 64bit multiply of c[0] and b[0]
|
{
|
||||||
__asm__( "mulq %3\n\t"
|
uint64_t hi, lo;
|
||||||
: "=d" ( hi ),
|
// hi,lo = 64bit x 64bit multiply of c[0] and b[0]
|
||||||
"=a" ( lo )
|
|
||||||
: "%a" ( c[0] ),
|
|
||||||
"rm" ( b[0] )
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
b_x = c_x;
|
__asm__("mulq %3\n\t"
|
||||||
nextblock[0] = a[0] + hi;
|
: "=d" (hi),
|
||||||
nextblock[1] = a[1] + lo;
|
"=a" (lo)
|
||||||
a[0] = b[0] ^ nextblock[0];
|
: "%a" (c[0]),
|
||||||
a[1] = b[1] ^ nextblock[1];
|
"rm" (b[0])
|
||||||
lsa = (__m128i*)&ctx.long_state[ a[0] & 0x1FFFF0 ];
|
: "cc" );
|
||||||
a_x = _mm_load_si128( (__m128i*)a );
|
|
||||||
c_x = _mm_load_si128( lsa );
|
a[0] += hi;
|
||||||
|
a[1] += lo;
|
||||||
|
}
|
||||||
|
uint64_t *dst = (uint64_t*)&ctx.long_state[c[0] & 0x1FFFF0];
|
||||||
|
// __m128i *dst = (__m128i*)&ctx.long_state[c[0] & 0x1FFFF0];
|
||||||
|
|
||||||
|
// *dst = cast_m128i( a );
|
||||||
|
dst[0] = a[0];
|
||||||
|
dst[1] = a[1];
|
||||||
|
|
||||||
|
// cast_m128i( a ) = _mm_xor_si128( cast_m128i( a ), cast_m128i( b ) );
|
||||||
|
a[0] ^= b[0];
|
||||||
|
a[1] ^= b[1];
|
||||||
|
b_x = c_x;
|
||||||
|
__builtin_prefetch( &ctx.long_state[a[0] & 0x1FFFF0], 0, 3 );
|
||||||
}
|
}
|
||||||
// abreviated nth iteration
|
|
||||||
c_x = _mm_aesenc_si128( c_x, a_x );
|
|
||||||
_mm_store_si128( (__m128i*)c, c_x );
|
|
||||||
b_x = _mm_xor_si128( b_x, c_x );
|
|
||||||
nextblock = (uint64_t *)&ctx.long_state[c[0] & 0x1FFFF0];
|
|
||||||
_mm_store_si128( lsa, b_x );
|
|
||||||
b[0] = nextblock[0];
|
|
||||||
b[1] = nextblock[1];
|
|
||||||
|
|
||||||
__asm__( "mulq %3\n\t"
|
|
||||||
: "=d" ( hi ),
|
|
||||||
"=a" ( lo )
|
|
||||||
: "%a" ( c[0] ),
|
|
||||||
"rm" ( b[0] )
|
|
||||||
: "cc" );
|
|
||||||
|
|
||||||
nextblock[0] = a[0] + hi;
|
|
||||||
nextblock[1] = a[1] + lo;
|
|
||||||
|
|
||||||
|
memcpy( ctx.text, ctx.state.init, INIT_SIZE_BYTE );
|
||||||
memcpy( ExpandedKey, &ctx.state.hs.b[32], AES_KEY_SIZE );
|
memcpy( ExpandedKey, &ctx.state.hs.b[32], AES_KEY_SIZE );
|
||||||
ExpandAESKey256( ExpandedKey );
|
ExpandAESKey256( ExpandedKey );
|
||||||
memcpy( ctx.text, ctx.state.init, INIT_SIZE_BYTE );
|
|
||||||
|
//for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE)
|
||||||
|
// aesni_parallel_xor(&ctx->text, ExpandedKey, &ctx->long_state[i]);
|
||||||
|
|
||||||
// prefetch expkey, all of xmminput and enough longoutput for 4 loops
|
// prefetch expkey, all of xmminput and enough longoutput for 4 loops
|
||||||
|
|
||||||
_mm_prefetch( xmminput, _MM_HINT_T0 );
|
_mm_prefetch( xmminput, _MM_HINT_T0 );
|
||||||
_mm_prefetch( xmminput + 4, _MM_HINT_T0 );
|
_mm_prefetch( xmminput + 4, _MM_HINT_T0 );
|
||||||
for ( i = 0; i < 64; i += 16 )
|
for ( i = 0; i < 64; i += 16 )
|
||||||
@@ -272,11 +256,9 @@ void cryptonight_hash_aes( void *restrict output, const void *input, int len )
|
|||||||
_mm_prefetch( expkey + 4, _MM_HINT_T0 );
|
_mm_prefetch( expkey + 4, _MM_HINT_T0 );
|
||||||
_mm_prefetch( expkey + 8, _MM_HINT_T0 );
|
_mm_prefetch( expkey + 8, _MM_HINT_T0 );
|
||||||
|
|
||||||
// n-4 iterations
|
for ( i = 0; likely( i < MEMORY_M128I ); i += INIT_SIZE_M128I )
|
||||||
for ( i = 0; likely( i < MEMORY_M128I - 4*INIT_SIZE_M128I );
|
|
||||||
i += INIT_SIZE_M128I )
|
|
||||||
{
|
{
|
||||||
// stay 4 iterations ahead.
|
// stay 4 loops ahead,
|
||||||
_mm_prefetch( longoutput + i + 64, _MM_HINT_T0 );
|
_mm_prefetch( longoutput + i + 64, _MM_HINT_T0 );
|
||||||
_mm_prefetch( longoutput + i + 68, _MM_HINT_T0 );
|
_mm_prefetch( longoutput + i + 68, _MM_HINT_T0 );
|
||||||
|
|
||||||
@@ -301,34 +283,10 @@ void cryptonight_hash_aes( void *restrict output, const void *input, int len )
|
|||||||
xmminput[7] = _mm_aesenc_si128( xmminput[7], expkey[j] );
|
xmminput[7] = _mm_aesenc_si128( xmminput[7], expkey[j] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// last 4 iterations
|
|
||||||
for ( ; likely( i < MEMORY_M128I ); i += INIT_SIZE_M128I )
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_xor_si128( longoutput[i ], xmminput[0] );
|
|
||||||
xmminput[1] = _mm_xor_si128( longoutput[i+1], xmminput[1] );
|
|
||||||
xmminput[2] = _mm_xor_si128( longoutput[i+2], xmminput[2] );
|
|
||||||
xmminput[3] = _mm_xor_si128( longoutput[i+3], xmminput[3] );
|
|
||||||
xmminput[4] = _mm_xor_si128( longoutput[i+4], xmminput[4] );
|
|
||||||
xmminput[5] = _mm_xor_si128( longoutput[i+5], xmminput[5] );
|
|
||||||
xmminput[6] = _mm_xor_si128( longoutput[i+6], xmminput[6] );
|
|
||||||
xmminput[7] = _mm_xor_si128( longoutput[i+7], xmminput[7] );
|
|
||||||
|
|
||||||
for( j = 0; j < 10; j++ )
|
|
||||||
{
|
|
||||||
xmminput[0] = _mm_aesenc_si128( xmminput[0], expkey[j] );
|
|
||||||
xmminput[1] = _mm_aesenc_si128( xmminput[1], expkey[j] );
|
|
||||||
xmminput[2] = _mm_aesenc_si128( xmminput[2], expkey[j] );
|
|
||||||
xmminput[3] = _mm_aesenc_si128( xmminput[3], expkey[j] );
|
|
||||||
xmminput[4] = _mm_aesenc_si128( xmminput[4], expkey[j] );
|
|
||||||
xmminput[5] = _mm_aesenc_si128( xmminput[5], expkey[j] );
|
|
||||||
xmminput[6] = _mm_aesenc_si128( xmminput[6], expkey[j] );
|
|
||||||
xmminput[7] = _mm_aesenc_si128( xmminput[7], expkey[j] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy( ctx.state.init, ctx.text, INIT_SIZE_BYTE);
|
memcpy( ctx.state.init, ctx.text, INIT_SIZE_BYTE);
|
||||||
keccakf( (uint64_t*)&ctx.state.hs.w, 24 );
|
keccakf( (uint64_t*)&ctx.state.hs.w, 24 );
|
||||||
extra_hashes[ctx.state.hs.b[0] & 3](&ctx.state, 200, output);
|
|
||||||
|
|
||||||
|
extra_hashes[ctx.state.hs.b[0] & 3](&ctx.state, 200, output);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
// Modified for CPUminer by Lucas Jones
|
// Modified for CPUminer by Lucas Jones
|
||||||
|
|
||||||
#include "cpuminer-config.h"
|
#include "cpuminer-config.h"
|
||||||
|
//#include "miner.h"
|
||||||
#include "algo-gate-api.h"
|
#include "algo-gate-api.h"
|
||||||
|
|
||||||
#ifndef NO_AES_NI
|
#ifndef NO_AES_NI
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user