Merge pull request #14 from lbryio/next

Update Yiimp Live Branch that gets pulled to installs
This commit is contained in:
Ralph 2021-04-28 15:03:38 -04:00 committed by GitHub
commit a9dd7f7ac2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2381 changed files with 31671 additions and 10052 deletions

5
.gitignore vendored
View file

@ -1,5 +1,7 @@
*.o
*.a
.deps
.dirstamp
stratum/stratum
stratum/blocknotify
blocknotify/blocknotify
@ -18,3 +20,6 @@ web/serverconfig.php
web/assets/
*.rej
*.orig
.idea/*
web/yaamp/.idea/
*.0

5
.travis.yml.disable Normal file
View file

@ -0,0 +1,5 @@
language: cpp
script:
- (cd blocknotify && make)
- (cd stratum/iniparser && make)
- (cd stratum && make)

10
LICENSE Normal file
View file

@ -0,0 +1,10 @@
The MIT License (MIT)
Copyright (c) 2016-2018 LBRY Inc
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.

116
README.md
View file

@ -1,90 +1,65 @@
#yiimp - yaamp fork
Required:
linux, mysql, php, memcached, a webserver (lighttpd or nginx recommended)
# Lbry Mining Pool based on Yiimp
Config for nginx:
location / {
try_files $uri @rewrite;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?r=$1;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
### TODO: Rewrite this README, Rewrite Install Script to be more logical, Do it all again to document the hax. Be sure to rewrite things to use TMUX and document as such.
If you use apache, it should be something like that (already set in web/.htaccess):
## Prerequisites:
1. Ubuntu 18.04
2. Install Script (Provided in this repo)
RewriteEngine on
WARNINGS
- Use at your own risks.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) index.php?r=$1 [QSA]
The install Script will install the pool and all dependencies needed.
TO INSTALL:
1. Log in to your server
2. Create new user - sudo adduser (username)
3. Add user to sudo group - sudo adduser (username) sudo
4. Log in to new user - sudo su (username)
5. cd ~/
6. `wget https://raw.githubusercontent.com/lbryio/pool/next/install.sh && chmod +x install.sh && ./install.sh`
7. Follow the instructions on the screen.
8. sudo bash pool-start.sh
If you use lighttpd, use the following config:
$HTTP["host"] =~ "yiimp.ccminer.org" {
server.document-root = "/var/yaamp/web"
url.rewrite-if-not-file = (
"^(.*)/([0-9]+)$" => "index.php?r=$1&id=$2",
"^(.*)\?(.*)" => "index.php?r=$1&$2",
"^(.*)" => "index.php?r=$1",
"." => "index.php"
)
url.access-deny = ( "~", ".dat", ".log" )
}
For the database, import the initial dump present in the sql/ folder
Then, apply the migration scripts to be in sync with the current git, they are sorted by date of change.
Your database need at least 2 users, one for the web site (php) and one for the stratum connections (password set in config/algo.conf).
The recommended install folder for the stratum engine is /var/stratum. Copy all the .conf files, run.sh, the stratum binary and the blocknotify binary to this folder.
Some scripts are expecting the web folder to be /var/web. You can use directory symlinks...
Add your exchange API public and secret keys in these two separated files:
/etc/yiimp/keys.php - fixed path in code
web/serverconfig.php - use sample as base...
This will setup the pool ready for coin daemons to be added.
You can find sample config files in web/serverconfig.sample.php and web/keys.sample.php
This web application includes some command line tools, add bin/ folder to your path and type "yiic" to list them, "yiic checkup" can help to test your initial setup.
Future scripts and maybe the "cron" jobs will then use this yiic console interface.
You need at least three backend shells (in screen) running these scripts:
You need at least three backend shells (in tmux) running these scripts:
web/main.sh
web/loop2.sh
web/block.sh
Start one stratum per algo using the run.sh script with the algo as parameter. For example, for x11:
This is done running the pool-start.sh script in the home folder.
run.sh x11
Now you will need to edit the coin in the admin panel, this will be http://IP/site/ADMIN_ADDRESS_USED_WHILE_INSTALLING then go to Coins on the headers, Find LBRY Credits and click LBC.
Edit each .conf file with proper values.
Here you need to do the following:
1. Edit algo to lbry
2. Edit image to /images/coin-LBRY.png
3. Edit Daemon information to the following:
4. process name - lbrycrdd
5. Conf.folder - .lbrycrd
6. RPC Host - 127.0.0.1
7. RPC User - This is the Username at the end of the install script.
8. RPC Password - This is the Password at the end of the install script.
9. RPC Type - POW
10. Edit Settings and tick the following boxes:
11. Enable
12. Auto Ready
13. Visable
14. Installed
15. Click Save
Look at rc.local, it starts all three backend shells and all stratum processes. Copy it to the /etc folder so that all screen shells are started at boot up.
Once you have clicked save, you need to restart the lbry daemon in the VPS:
1. lbrycrd-cli stop
2. lbrycrdd -daemon
All your coin's config files need to blocknotify their corresponding stratum using something like:
blocknotify=blocknotify yaamp.com:port coinid %s
At the moment you will find other wallets active, you can click the install tick box on all of the ones that you are not using. I will update this at some point to remove them when installing.
On the website, go to http://server.com/site/adminRights to login as admin. You have to change it to something different in the code (web/yaamp/modules/site/SiteController.php). A real admin login may be added later, but you can setup a password authentification with your web server, sample for lighttpd:
@ -114,13 +89,10 @@ There are logs generated in the /var/stratum folder and /var/log/stratum/debug.l
More instructions coming as needed.
There a lot of unused code in the php branch. Lot come from other projects I worked on and I've been lazy to clean it up before to integrate it to yaamp. It's mostly based on the Yii framework which implements a lightweight MVC.
http://www.yiiframework.com/
Credits:
Thanks to globalzon to have released the initial Yaamp source code.
Thanks to tpruvot for updating the source code to yiimp.
Thanks to oakey22 for customising this for Lbry.
Thanks to Coolguy3289 for picking this project back up and getting the software compatible with lbrycrd again.

13
bin/kill_stratum Executable file
View file

@ -0,0 +1,13 @@
#!/bin/bash
PLINE=$(ps -ef | grep "stratum config/$1" | grep -v grep)
if [ $? ]; then
PS=$(echo $PLINE | cut -d ' ' -f 2)
if [ $PS ]; then
kill $PS
echo "killed stratum process $PS"
else
echo "Process not found"
exit 1
fi
fi

View file

@ -3,6 +3,6 @@
ROOTDIR=/data/yiimp
DIR=`pwd`
cd "$ROOTDIR/web" && php yaamp/yiic.php $*
cd "$ROOTDIR/web" && php yaamp/yiic.php "$@"
cd $DIR

View file

@ -1,9 +1,14 @@
OUT_GO=blocknotify-dcr
OUTPUT=blocknotify-dcr
ROOT=`pwd`
all:
rm -f $(OUT_GO)
go build
rm -rf vendor
glide install
ln -s ../vendor vendor/src
rm -f vendor/src/github.com/decred/dcrrpcclient/wallet.go
GOPATH="$(GOPATH):$(ROOT)/vendor" go build
install: all
strip -s $(OUT_GO)
@ -11,3 +16,7 @@ install: all
mv $(OUT_GO) ../bin/$(OUTPUT)
sh -c "../bin/$(OUTPUT) &"
clean:
rm -f $(OUT_GO)
rm -rf vendor

View file

@ -1,10 +1,9 @@
// Copyright (c) 2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
// Copyright (c) 2015-2017 YiiMP
// Sample blocknofify tool compatible with decred
// will call the standard blocknotify yiimp tool on new block event.
// Sample blocknotify wrapper tool compatible with decred notifications
// will call the standard bin/blocknotify yiimp tool on new block event.
// Note: this tool is connected directly to dcrd, not to the wallet!
package main
@ -13,20 +12,21 @@ import (
"log"
"os/exec"
"path/filepath"
"time"
"github.com/decred/dcrd/chaincfg/chainhash"
"bytes" // dcrd > 0.6+
"github.com/decred/dcrd/wire"
"github.com/decred/dcrrpcclient"
// "github.com/decred/dcrutil"
)
const (
processName = "blocknotify" // set the full path if required
stratumDest = "yaamp.com:5744" // stratum host:port
stratumDest = "yaamp.com:3252" // stratum host:port
coinId = "1574" // decred database coin id
walletUser = "yiimprpc"
walletPass = "myDecredPassword"
dcrdUser = "yiimprpc"
dcrdPass = "myDcrdPassword"
debug = false
)
@ -37,10 +37,13 @@ func main() {
// for notifications. See the documentation of the dcrrpcclient
// NotificationHandlers type for more details about each handler.
ntfnHandlers := dcrrpcclient.NotificationHandlers{
OnBlockConnected: func(hash *chainhash.Hash, height int32, time time.Time, vb uint16) {
// Find the process path.
str := hash.String()
OnBlockConnected: func(blockHeader []byte, transactions [][]byte) {
// log.Printf("Block bytes: %v %v", blockHeader, transactions)
var bhead wire.BlockHeader
err := bhead.Deserialize(bytes.NewReader(blockHeader))
if err == nil {
str := bhead.BlockHash().String();
args := []string{ stratumDest, coinId, str }
out, err := exec.Command(processName, args...).Output()
if err != nil {
@ -48,16 +51,17 @@ func main() {
} else if debug {
log.Printf("out %s", out)
}
if (debug) {
log.Printf("Block connected: %s %d", hash, height)
log.Printf("Block connected: %s", str)
}
}
},
}
// Connect to local dcrd RPC server using websockets.
// dcrwHomeDir := dcrutil.AppDataDir("dcrwallet", false)
// folder := dcrwHomeDir
// dcrdHomeDir := dcrutil.AppDataDir("dcrd", false)
// folder := dcrdHomeDir
folder := ""
certs, err := ioutil.ReadFile(filepath.Join(folder, "rpc.cert"))
if err != nil {
@ -66,11 +70,11 @@ func main() {
}
connCfg := &dcrrpcclient.ConnConfig{
Host: "127.0.0.1:15740",
Host: "127.0.0.1:9109",
Endpoint: "ws", // websocket
User: walletUser,
Pass: walletPass,
User: dcrdUser,
Pass: dcrdPass,
DisableTLS: (certs == nil),
Certificates: certs,

46
blocknotify-dcr/glide.lock generated Normal file
View file

@ -0,0 +1,46 @@
hash: 4e74a8534cece2f2c1de27bcab0da6efba0e47d533cf8475f588e87851473e81
updated: 2017-09-12T12:14:36.151798958+02:00
imports:
- name: github.com/btcsuite/btclog
version: 73889fb79bd687870312b6e40effcecffbd57d30
- name: github.com/btcsuite/go-socks
version: 4720035b7bfd2a9bb130b1c184f8bbe41b6f0d0f
subpackages:
- socks
- name: github.com/btcsuite/seelog
version: 313961b101eb55f65ae0f03ddd4e322731763b6c
- name: github.com/btcsuite/websocket
version: 31079b6807923eb23992c421b114992b95131b55
- name: github.com/decred/blake256
version: a840e32d7c31fe2e0218607334cb120a683951a4
- name: github.com/decred/dcrd
version: 5bed758f85159b2ee76240207ba775c40000a4c1
subpackages:
- blockchain/stake
- blockchain/stake/internal/dbnamespace
- blockchain/stake/internal/ticketdb
- blockchain/stake/internal/tickettreap
- chaincfg
- chaincfg/chainec
- chaincfg/chainhash
- database
- dcrec/edwards
- dcrec/secp256k1
- dcrec/secp256k1/schnorr
- dcrjson
- txscript
- wire
- name: github.com/decred/dcrrpcclient
version: d6edcb0f8f2d01fbf9169f240f73756b41423189
- name: github.com/decred/dcrutil
version: ebd2e98736e819ac043d54439969b30144b92ced
subpackages:
- base58
- name: github.com/decred/ed25519
version: b0909d3f798b97a03c9e77023f97a5301a2a7900
subpackages:
- edwards25519
- name: golang.org/x/crypto
version: c7af5bf2638a1164f2eb5467c39c6cffbd13a02e
subpackages:
- ripemd160

View file

@ -0,0 +1,9 @@
package: github.com/tpruvot/yiimp/blocknotify-dcr
import:
- package: github.com/decred/dcrd
subpackages:
- wire
- package: github.com/decred/dcrjson
# - package: github.com/decred/dcrrpcclient
- package: github.com/decred/dcrutil

859
install.sh Normal file
View file

@ -0,0 +1,859 @@
#!/bin/bash
################################################################################
# Original Author: Oakey22
# Maintained by: Coolguy3289
# Version 1.99 (April 2021)
#
# Program:
# Install Lbry Pool on Ubuntu 18.04 running Nginx, MariaDB, and php7.x
#
################################################################################
output() {
printf "\E[0;33;40m"
echo $1
printf "\E[0m"
}
displayErr() {
echo
echo $1;
echo
exit 1;
}
clear
output "Make sure you double check before hitting enter! Only one shot at these!"
output ""
read -e -p "Enter time zone (e.g. America/New_York) : " TIME
read -e -p "Server name (no http:// or www. just example.com) : " server_name
read -e -p "Are you using a subdomain (pool.example.com?) [y/N] : " sub_domain
read -e -p "Enter support email (e.g. admin@example.com) : " EMAIL
read -e -p "Set stratum to AutoExchange? i.e. mine any coin with BTC address? [y/N] : " BTC
read -e -p "Please enter a new location for /site/adminRights this is to customize the admin entrance url (e.g. myAdminpanel) : " admin_panel
read -e -p "Enter your Public IP for admin access (http://www.whatsmyip.org/) : " Public
read -e -p "Install Fail2ban? [Y/n] : " install_fail2ban
read -e -p "Install UFW and configure ports? [Y/n] : " UFW
read -e -p "Install LetsEncrypt SSL? IMPORTANT! You MUST have your domain name pointed to this server prior to running the script!! [Y/n]: " ssl_install
clear
output "If you found this helpful, please donate to BTC Donation: "
output ""
output "Updating system and installing required packages."
output ""
# update package and upgrade Ubuntu
output "Updating System through apt"
sudo apt update
sudo apt upgrade -y
sudo apt autoremove -y
output "Removing Snapd, and Cloud-Init (Ubuntu 18.x+)
sudo snap stop lxc && sudo snap remove lxc
sudo snap stop core18 && sudo snap remove core18
sudo snap remove snapd
sudo apt purge -y snapd*
sudo apt purge cloud-init*
sudo rm -rf /etc/cloud
sudo apt autoremove -y
clear
# install all dependencies
output "Installing MySQL Repository."
output ""
wget https://dev.mysql.com/get/mysql-apt-config_0.8.14-1_all.deb
sudo dpkg -i ./mysql-apt-config_0.8.14-1_all.deb
sudo apt update
# create random password
rootpasswd=$(openssl rand -base64 12)
export DEBIAN_FRONTEND="noninteractive"
output "Installing pre-requisite repos."
output ""
sudo apt install software-properties-common -y
sudo add-apt-repository ppa:ondrej/php -y
sudo add-apt-repository ppa:bitcoin/bitcoin -y
sudo apt update
output "Installing Required Software."
output ""
sudo apt install nginx mysql-server php7.4-opcache php7.4-fpm php7.4-common php7.4-gd php7.4-mysql php7.4-imap php7.4-cli php7.4-cgi php7.4-curl php7.4-intl php7.4-pspell recode php7.4-sqlite3 php7.4-tidy php7.4-xmlrpc php7.4-xsl php7.4-memcache php7.4-imagick php7.4-zip php7.4-mbstring php-pear php-auth-sasl mcrypt imagemagick libruby memcached libgmp3-dev libmysqlclient-dev libcurl4-gnutls-dev libkrb5-dev libldap2-dev libidn11-dev gnutls-dev librtmp-dev build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils sendmail git pwgen unzip libdb4.8-dev libdb4.8++-dev libssl-dev libboost-all-dev libminiupnpc-dev libqt5gui5 libqt5core5a libqt5webkit5-dev libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler libqrencode-dev libnghttp2-dev libpsl-dev -y
output "Configuring Nginx server."
output ""
sudo rm /etc/nginx/sites-enabled/default
sudo service nginx start
sudo service cron start
#Making Nginx a bit hard
echo 'map $http_user_agent $blockedagent {
default 0;
~*malicious 1;
~*bot 1;
~*backdoor 1;
~*crawler 1;
~*bandit 1;
}
' | sudo -E tee /etc/nginx/blockuseragents.rules >/dev/null 2>&1
#Generating Random Passwords
password=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
password2=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
AUTOGENERATED_PASS=`pwgen -c -1 20`
output "Testing to see if server emails are sent"
output ""
if [[ "$root_email" != "" ]]; then
echo $root_email > sudo tee --append ~/.email
echo $root_email > sudo tee --append ~/.forward
if [[ ("$send_email" == "y" || "$send_email" == "Y" || "$send_email" == "") ]]; then
echo "This is a mail test for the SMTP Service." > sudo tee --append /tmp/email.message
echo "You should receive this !" >> sudo tee --append /tmp/email.message
echo "" >> sudo tee --append /tmp/email.message
echo "Cheers" >> sudo tee --append /tmp/email.message
sudo sendmail -s "SMTP Testing" $root_email < sudo tee --append /tmp/email.message
sudo rm -f /tmp/email.message
echo "Mail sent"
fi
fi
output "Some optional installs"
if [[ ("$install_fail2ban" == "y" || "$install_fail2ban" == "Y" || "$install_fail2ban" == "") ]]; then
sudo apt install fail2ban -y
fi
if [[ ("$UFW" == "y" || "$UFW" == "Y" || "$UFW" == "") ]]; then
sudo apt-get install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 3334/tcp
sudo ufw --force enable
fi
clear
output " Installing yiimp"
output ""
output "Grabbing yiimp fron Github, building files and setting file structure."
output ""
#Generating Random Password for stratum
blckntifypass=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
cd ~
git clone https://github.com/lbryio/pool.git yiimp
cd $HOME/yiimp/blocknotify
sudo sed -i 's/tu8tu5/'$blckntifypass'/' blocknotify.cpp
sudo make
cd $HOME/yiimp/stratum/iniparser
sudo make
cd $HOME/yiimp/stratum
if [[ ("$BTC" == "y" || "$BTC" == "Y") ]]; then
sudo sed -i 's/CFLAGS += -DNO_EXCHANGE/#CFLAGS += -DNO_EXCHANGE/' $HOME/yiimp/stratum/Makefile
sudo make
fi
sudo make
cd $HOME/yiimp
sudo sed -i 's/AdminRights/'$admin_panel'/' $HOME/yiimp/web/yaamp/modules/site/SiteController.php
sudo cp -r $HOME/yiimp/web /var/
sudo mkdir -p /var/stratum
cd $HOME/yiimp/stratum
sudo cp -a config.sample/. /var/stratum/config
sudo cp -r stratum /var/stratum
sudo cp -r run.sh /var/stratum
cd $HOME/yiimp
sudo cp -r $HOME/yiimp/bin/. /bin/
# sudo cp -r $HOME/yiimp/blocknotify/blocknotify /var/stratum
sudo cp -r $HOME/yiimp/blocknotify/blocknotify /usr/bin
sudo mkdir -p /etc/yiimp
sudo mkdir -p /$HOME/backup/
#fixing yiimp
sed -i "s|ROOTDIR=/data/yiimp|ROOTDIR=/var|g" /bin/yiimp
#fixing run.sh
sudo rm -r /var/stratum/config/run.sh
echo '
#!/bin/bash
ulimit -n 10240
ulimit -u 10240
cd /var/stratum
while true; do
./stratum /var/stratum/config/$1
sleep 2
done
exec bash
' | sudo -E tee /var/stratum/config/run.sh >/dev/null 2>&1
sudo chmod +x /var/stratum/config/run.sh
output "Update default timezone."
output "Thanks for using this installation script. Donations welcome"
# check if link file
sudo [ -L /etc/localtime ] && sudo unlink /etc/localtime
# update time zone
sudo ln -sf /usr/share/zoneinfo/$TIME /etc/localtime
sudo apt install -y ntpdate
# write time to clock.
sudo hwclock -w
clear
output "Making Web Server Magic Happen!"
# adding user to group, creating dir structure, setting permissions
sudo mkdir -p /var/www/$server_name/html
output "Creating webserver initial config file"
output ""
if [[ ("$sub_domain" == "y" || "$sub_domain" == "Y") ]]; then
echo 'include /etc/nginx/blockuseragents.rules;
server {
if ($blockedagent) {
return 403;
}
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}
listen 80;
listen [::]:80;
server_name '"${server_name}"';
root "/var/www/'"${server_name}"'/html/web";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$args;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?r=$1;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/'"${server_name}"'.app-error.log error;
# allow larger file uploads and longer script runtimes
client_body_buffer_size 50k;
client_header_buffer_size 50k;
client_max_body_size 50k;
large_client_header_buffers 2 50k;
sendfile off;
location ~ ^/index\.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
try_files $uri $uri/ =404;
}
location ~ \.php$ {
return 404;
}
location ~ \.sh {
return 404;
}
location ~ /\.ht {
deny all;
}
location ~ /.well-known {
allow all;
}
location /phpmyadmin {
root /usr/share/;
index index.php;
try_files $uri $uri/ =404;
location ~ ^/phpmyadmin/(doc|sql|setup)/ {
deny all;
}
location ~ /phpmyadmin/(.+\.php)$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include snippets/fastcgi-php.conf;
}
}
}
' | sudo -E tee /etc/nginx/sites-available/$server_name.conf >/dev/null 2>&1
sudo ln -s /etc/nginx/sites-available/$server_name.conf /etc/nginx/sites-enabled/$server_name.conf
sudo ln -s /var/web /var/www/$server_name/html
sudo service nginx restart
if [[ ("$ssl_install" == "y" || "$ssl_install" == "Y" || "$ssl_install" == "") ]]; then
output "Install LetsEncrypt and setting SSL"
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install -y certbot python-certbot-nginx
sudo certbot certonly -a webroot --webroot-path=/var/web --email "$EMAIL" --agree-tos -d "$server_name"
sudo rm /etc/nginx/sites-available/$server_name.conf
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
# I am SSL Man!
echo 'include /etc/nginx/blockuseragents.rules;
server {
if ($blockedagent) {
return 403;
}
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}
listen 80;
listen [::]:80;
server_name '"${server_name}"';
# enforce https
return 301 https://$server_name$request_uri;
}
server {
if ($blockedagent) {
return 403;
}
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name '"${server_name}"';
root /var/www/'"${server_name}"'/html/web;
index index.php;
access_log /var/log/nginx/'"${server_name}"'.app-accress.log;
error_log /var/log/nginx/'"${server_name}"'.app-error.log error;
# allow larger file uploads and longer script runtimes
client_body_buffer_size 50k;
client_header_buffer_size 50k;
client_max_body_size 50k;
large_client_header_buffers 2 50k;
sendfile off;
# strengthen ssl security
ssl_certificate /etc/letsencrypt/live/'"${server_name}"'/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/'"${server_name}"'/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# Add headers to serve security related headers
add_header Strict-Transport-Security "max-age=15768000; preload;";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header Content-Security-Policy "frame-ancestors 'self'";
location / {
try_files $uri $uri/ /index.php?$args;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?r=$1;
}
location ~ ^/index\.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
include /etc/nginx/fastcgi_params;
try_files $uri $uri/ =404;
}
location ~ \.php$ {
return 404;
}
location ~ \.sh {
return 404;
}
location ~ /\.ht {
deny all;
}
location /phpmyadmin {
root /usr/share/;
index index.php;
try_files $uri $uri/ =404;
location ~ ^/phpmyadmin/(doc|sql|setup)/ {
deny all;
}
location ~ /phpmyadmin/(.+\.php)$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include snippets/fastcgi-php.conf;
}
}
}
' | sudo -E tee /etc/nginx/sites-available/$server_name.conf >/dev/null 2>&1
fi
sudo service nginx restart
sudo service php7.4-fpm reload
else
echo 'include /etc/nginx/blockuseragents.rules;
server {
if ($blockedagent) {
return 403;
}
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}
listen 80;
listen [::]:80;
server_name '"${server_name}"' www.'"${server_name}"';
root "/var/www/'"${server_name}"'/html/web";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$args;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?r=$1;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/'"${server_name}"'.app-error.log error;
# allow larger file uploads and longer script runtimes
client_body_buffer_size 50k;
client_header_buffer_size 50k;
client_max_body_size 50k;
large_client_header_buffers 2 50k;
sendfile off;
location ~ ^/index\.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
try_files $uri $uri/ =404;
}
location ~ \.php$ {
return 404;
}
location ~ \.sh {
return 404;
}
location ~ /\.ht {
deny all;
}
location ~ /.well-known {
allow all;
}
location /phpmyadmin {
root /usr/share/;
index index.php;
try_files $uri $uri/ =404;
location ~ ^/phpmyadmin/(doc|sql|setup)/ {
deny all;
}
location ~ /phpmyadmin/(.+\.php)$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include snippets/fastcgi-php.conf;
}
}
}
' | sudo -E tee /etc/nginx/sites-available/$server_name.conf >/dev/null 2>&1
sudo ln -s /etc/nginx/sites-available/$server_name.conf /etc/nginx/sites-enabled/$server_name.conf
sudo ln -s /var/web /var/www/$server_name/html
sudo service nginx restart
if [[ ("$ssl_install" == "y" || "$ssl_install" == "Y" || "$ssl_install" == "") ]]; then
output "Install LetsEncrypt and setting SSL"
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install -y certbot python-certbot-nginx
sudo certbot certonly -a webroot --webroot-path=/var/web --email "$EMAIL" --agree-tos -d "$server_name" -d www."$server_name"
sudo rm /etc/nginx/sites-available/$server_name.conf
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
# I am SSL Man!
echo 'include /etc/nginx/blockuseragents.rules;
server {
if ($blockedagent) {
return 403;
}
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}
listen 80;
listen [::]:80;
server_name '"${server_name}"';
# enforce https
return 301 https://$server_name$request_uri;
}
server {
if ($blockedagent) {
return 403;
}
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 444;
}
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name '"${server_name}"' www.'"${server_name}"';
root /var/www/'"${server_name}"'/html/web;
index index.php;
access_log /var/log/nginx/'"${server_name}"'.app-accress.log;
error_log /var/log/nginx/'"${server_name}"'.app-error.log error;
# allow larger file uploads and longer script runtimes
client_body_buffer_size 50k;
client_header_buffer_size 50k;
client_max_body_size 50k;
large_client_header_buffers 2 50k;
sendfile off;
# strengthen ssl security
ssl_certificate /etc/letsencrypt/live/'"${server_name}"'/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/'"${server_name}"'/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# Add headers to serve security related headers
add_header Strict-Transport-Security "max-age=15768000; preload;";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header Content-Security-Policy "frame-ancestors 'self'";
location / {
try_files $uri $uri/ /index.php?$args;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?r=$1;
}
location ~ ^/index\.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
include /etc/nginx/fastcgi_params;
try_files $uri $uri/ =404;
}
location ~ \.php$ {
return 404;
}
location ~ \.sh {
return 404;
}
location ~ /\.ht {
deny all;
}
location /phpmyadmin {
root /usr/share/;
index index.php;
try_files $uri $uri/ =404;
location ~ ^/phpmyadmin/(doc|sql|setup)/ {
deny all;
}
location ~ /phpmyadmin/(.+\.php)$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include snippets/fastcgi-php.conf;
}
}
}
' | sudo -E tee /etc/nginx/sites-available/$server_name.conf >/dev/null 2>&1
fi
sudo service nginx restart
sudo service php7.4-fpm reload
fi
clear
output "Now for the database fun!"
# create database
Q1="CREATE DATABASE IF NOT EXISTS yiimpfrontend;"
Q2="GRANT ALL ON *.* TO 'panel'@'localhost' IDENTIFIED BY '$password';"
Q3="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}${Q3}"
sudo mysql -u root -p="" -e "$SQL"
# create stratum user
Q1="GRANT ALL ON *.* TO 'stratum'@'localhost' IDENTIFIED BY '$password2';"
Q2="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}"
sudo mysql -u root -p="" -e "$SQL"
#Create my.cnf
echo '
[clienthost1]
user=panel
password='"${password}"'
database=yiimpfrontend
host=localhost
[clienthost2]
user=stratum
password='"${password2}"'
database=yiimpfrontend
host=localhost
[mysql]
user=root
password='"${rootpasswd}"'
[myphpadmin]
user=root
password='"${AUTOGENERATED_PASS}"'
' | sudo -E tee ~/.my.cnf >/dev/null 2>&1
sudo chmod 0600 ~/.my.cnf
#Create keys file
echo '
<?php
/* Sample config file to put in /etc/yiimp/keys.php */
define('"'"'YIIMP_MYSQLDUMP_USER'"'"', '"'"'panel'"'"');
define('"'"'YIIMP_MYSQLDUMP_PASS'"'"', '"'"''"${password}"''"'"');
/* Keys required to create/cancel orders and access your balances/deposit addresses */
define('"'"'EXCH_BITTREX_SECRET'"'"', '"'"'<my_bittrex_api_secret_key>'"'"');
define('"'"'EXCH_BITSTAMP_SECRET'"'"','"'"''"'"');
define('"'"'EXCH_BLEUTRADE_SECRET'"'"', '"'"''"'"');
define('"'"'EXCH_BTER_SECRET'"'"', '"'"''"'"');
define('"'"'EXCH_CCEX_SECRET'"'"', '"'"''"'"');
define('"'"'EXCH_COINMARKETS_PASS'"'"', '"'"''"'"');
define('"'"'EXCH_CRYPTOPIA_SECRET'"'"', '"'"''"'"');
define('"'"'EXCH_EMPOEX_SECKEY'"'"', '"'"''"'"');
define('"'"'EXCH_HITBTC_SECRET'"'"', '"'"''"'"');
define('"'"'EXCH_KRAKEN_SECRET'"'"','"'"''"'"');
define('"'"'EXCH_LIVECOIN_SECRET'"'"', '"'"''"'"');
define('"'"'EXCH_NOVA_SECRET'"'"','"'"''"'"');
define('"'"'EXCH_POLONIEX_SECRET'"'"', '"'"''"'"');
define('"'"'EXCH_YOBIT_SECRET'"'"', '"'"''"'"');
' | sudo -E tee /etc/yiimp/keys.php >/dev/null 2>&1
output "Peforming the SQL import"
output ""
cd ~
cd yiimp/sql
# import sql dump
sudo zcat 2016-04-03-yaamp.sql.gz | sudo mysql --defaults-group-suffix=host1
# oh the humanity!
sudo mysql --defaults-group-suffix=host1 --force < 2016-04-24-market_history.sql
sudo mysql --defaults-group-suffix=host1 --force < 2016-04-27-settings.sql
sudo mysql --defaults-group-suffix=host1 --force < 2016-05-11-coins.sql
sudo mysql --defaults-group-suffix=host1 --force < 2016-05-15-benchmarks.sql
sudo mysql --defaults-group-suffix=host1 --force < 2016-05-23-bookmarks.sql
sudo mysql --defaults-group-suffix=host1 --force < 2016-06-01-notifications.sql
sudo mysql --defaults-group-suffix=host1 --force < 2016-06-04-bench_chips.sql
sudo mysql --defaults-group-suffix=host1 --force < 2016-11-23-coins.sql
sudo mysql --defaults-group-suffix=host1 --force < 2017-02-05-benchmarks.sql
sudo mysql --defaults-group-suffix=host1 --force < 2017-03-31-earnings_index.sql
sudo mysql --defaults-group-suffix=host1 --force < 2017-05-accounts_case_swaptime.sql
sudo mysql --defaults-group-suffix=host1 --force < 2017-06-payouts_coinid_memo.sql
sudo mysql --defaults-group-suffix=host1 --force < 2017-09-notifications.sql
sudo mysql --defaults-group-suffix=host1 --force < 2017-11-segwit.sql
sudo mysql --defaults-group-suffix=host1 --force < 2018-01-stratums_ports.sql
sudo mysql --defaults-group-suffix=host1 --force < 2018-02-coins_getinfo.sql
clear
output "Generating a basic serverconfig.php"
output ""
# make config file
echo '
<?php
ini_set('"'"'date.timezone'"'"', '"'"'UTC'"'"');
define('"'"'YAAMP_LOGS'"'"', '"'"'/var/log'"'"');
define('"'"'YAAMP_HTDOCS'"'"', '"'"'/var/web'"'"');
define('"'"'YAAMP_BIN'"'"', '"'"'/var/bin'"'"');
define('"'"'YAAMP_DBHOST'"'"', '"'"'localhost'"'"');
define('"'"'YAAMP_DBNAME'"'"', '"'"'yiimpfrontend'"'"');
define('"'"'YAAMP_DBUSER'"'"', '"'"'panel'"'"');
define('"'"'YAAMP_DBPASSWORD'"'"', '"'"''"${password}"''"'"');
define('"'"'YAAMP_PRODUCTION'"'"', true);
define('"'"'YAAMP_RENTAL'"'"', false);
define('"'"'YAAMP_LIMIT_ESTIMATE'"'"', false);
define('"'"'YAAMP_FEES_MINING'"'"', 0.5);
define('"'"'YAAMP_FEES_EXCHANGE'"'"', 2);
define('"'"'YAAMP_FEES_RENTING'"'"', 2);
define('"'"'YAAMP_TXFEE_RENTING_WD'"'"', 0.002);
define('"'"'YAAMP_PAYMENTS_FREQ'"'"', 3*60*60);
define('"'"'YAAMP_PAYMENTS_MINI'"'"', 0.001);
define('"'"'YAAMP_ALLOW_EXCHANGE'"'"', false);
define('"'"'YIIMP_PUBLIC_EXPLORER'"'"', true);
define('"'"'YIIMP_PUBLIC_BENCHMARK'"'"', true);
define('"'"'YIIMP_FIAT_ALTERNATIVE'"'"', '"'"'USD'"'"'); // USD is main
define('"'"'YAAMP_USE_NICEHASH_API'"'"', false);
define('"'"'YAAMP_BTCADDRESS'"'"', '"'"'1NMDeanjyad2gcpumbZmF13fMLqDKNxxQ5'"'"');
define('"'"'YAAMP_SITE_URL'"'"', '"'"''"${server_name}"''"'"');
define('"'"'YAAMP_STRATUM_URL'"'"', YAAMP_SITE_URL); // change if your stratum server is on a different host
define('"'"'YAAMP_SITE_NAME'"'"', '"'"'Crypto'"'"');
define('"'"'YAAMP_ADMIN_EMAIL'"'"', '"'"''"${EMAIL}"''"'"');
define('"'"'YAAMP_ADMIN_IP'"'"', '"'"''"${Public}"''"'"'); // samples: "80.236.118.26,90.234.221.11" or "10.0.0.1/8"
define('"'"'YAAMP_ADMIN_WEBCONSOLE'"'"', true);
define('"'"'YAAMP_NOTIFY_NEW_COINS'"'"', false);
define('"'"'YAAMP_DEFAULT_ALGO'"'"', '"'"'lbry'"'"');
define('"'"'YAAMP_USE_NGINX'"'"', true);
// Exchange public keys (private keys are in a separate config file)
define('"'"'EXCH_CRYPTOPIA_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_POLONIEX_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_BITTREX_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_BLEUTRADE_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_BTER_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_YOBIT_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_CCEX_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_COINMARKETS_USER'"'"', '"'"''"'"');
define('"'"'EXCH_COINMARKETS_PIN'"'"', '"'"''"'"');
define('"'"'EXCH_BITSTAMP_ID'"'"','"'"''"'"');
define('"'"'EXCH_BITSTAMP_KEY'"'"','"'"''"'"');
define('"'"'EXCH_HITBTC_KEY'"'"','"'"''"'"');
define('"'"'EXCH_KRAKEN_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_LIVECOIN_KEY'"'"', '"'"''"'"');
define('"'"'EXCH_NOVA_KEY'"'"', '"'"''"'"');
// Automatic withdraw to Yaamp btc wallet if btc balance > 0.3
define('"'"'EXCH_AUTO_WITHDRAW'"'"', 0.3);
// nicehash keys deposit account & amount to deposit at a time
define('"'"'NICEHASH_API_KEY'"'"','"'"''"'"');
define('"'"'NICEHASH_API_ID'"'"','"'"''"'"');
define('"'"'NICEHASH_DEPOSIT'"'"','"'"''"'"');
define('"'"'NICEHASH_DEPOSIT_AMOUNT'"'"','"'"''"'"');
$cold_wallet_table = array(
'"'"'1NMDeanjyad2gcpumbZmF13fMLqDKNxxQ5'"'"' => 0.10,
);
// Sample fixed pool fees
$configFixedPoolFees = array(
'"'"'zr5'"'"' => 2.0,
'"'"'scrypt'"'"' => 20.0,
'"'"'sha256'"'"' => 5.0,
);
// Sample custom stratum ports
$configCustomPorts = array(
// '"'"'x11'"'"' => 7000,
);
// mBTC Coefs per algo (default is 1.0)
$configAlgoNormCoef = array(
// '"'"'x11'"'"' => 5.0,
);
' | sudo -E tee /var/web/serverconfig.php >/dev/null 2>&1
output "Adding tmux start file to ~/"
echo '
#!/bin/bash
LOG_DIR=/var/log
WEB_DIR=/var/web
STRATUM_DIR=/var/stratum
USR_BIN=/usr/bin
tmux new -d -s main bash $WEB_DIR/main.sh
tmux new -d -s loop2 bash $WEB_DIR/loop2.sh
tmux new -d -s blocks bash $WEB_DIR/blocks.sh
tmux new -d -s debug tail -f $LOG_DIR/debug.log
tmux new -d -s stratum bash $STRATUM_DIR/run.sh lbry
' | sudo -E tee ~/pool-start.sh >/dev/null 2>&1
sudo chmod +x ~/pool-start.sh
# Old screen commands:
# screen -dmS main bash $WEB_DIR/main.sh
# screen -dmS loop2 bash $WEB_DIR/loop2.sh
# screen -dmS blocks bash $WEB_DIR/blocks.sh
# screen -dmS debug tail -f $LOG_DIR/debug.log
# screen -dmS stratum bash $STRATUM_DIR/run.sh lbry
output "Updating stratum config files with database connection info."
output ""
cd /var/stratum/config
sudo sed -i 's/password = tu8tu5/password = '$blckntifypass'/g' *.conf
sudo sed -i 's/server = yaamp.com/server = '$server_name'/g' *.conf
sudo sed -i 's/host = yaampdb/host = localhost/g' *.conf
sudo sed -i 's/database = yaamp/database = yiimpfrontend/g' *.conf
sudo sed -i 's/username = root/username = stratum/g' *.conf
sudo sed -i 's/password = patofpaq/password = '$password2'/g' *.conf
cd ~
sudo rm -rf $HOME/yiimp
sudo service nginx restart
sudo service php7.3-fpm reload
cd ~
wget https://github.com/lbryio/lbrycrd/releases/download/v0.17.3.2/lbrycrd-linux-1732.zip
sudo unzip lbrycrd-linux-1732.zip -d /usr/bin
lbrycrdd -daemon
sleep 3
lbrycrd-cli stop
# Create config for Lbry
echo && echo "Configuring Lbrycrd.conf"
sleep 3
rpcuser=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
rpcpassword=`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1`
echo '
rpcuser='$rpcuser'
rpcpassword='$rpcpassword'
rpcport=14390
rpcthreads=24
rpcallowip=127.0.0.1
# onlynet=ipv4
maxconnections=36
daemon=1
deprecatedrpc=accounts
gen=0
alertnotify=echo %s | mail -s "LBRY Credits alert!" ${EMAIL}
blocknotify=blocknotify 127.0.0.1:3334 1439 %s
' | sudo -E tee ~/.lbrycrd/lbrycrd.conf
sleep 3
output "Final Directory permissions"
output ""
whoami=`whoami`
sudo usermod -aG www-data $whoami
sudo mkdir /root/backup/
sudo mkdir /data
sudo mkdir /data/yiimp
sudo ln -s /var/web /data/yiimp/web
sudo chown -R www-data:www-data /var/log
sudo chown -R www-data:www-data /var/stratum
sudo chown -R www-data:www-data /var/web
sudo chmod -R 775 /var/www/$server_name/html
sudo chmod -R 775 /var/web
sudo chmod -R 775 /var/stratum
sudo chmod -R 775 /var/web/yaamp/runtime
sudo chmod -R 775 /root/backup/
sudo chmod -R 775 /var/log
sudo chmod -R 775 /var/web/serverconfig.php
sudo chmod a+w /var/web/yaamp/runtime
sudo chmod a+w /var/log
sudo chmod a+w /var/web/assets
lbrycrdd -daemon
clear
output "Your mysql information is saved in ~/.my.cnf"
output ""
output "Please login to the admin panel at http://${server_name}/site/${admin_panel}"
output ""
output "Your RPC username is ${rpcuser}"
output "Your RPC Password is ${rpcpassword}"

View file

@ -17,18 +17,26 @@ screen -dmS loop2 $WEB_DIR/loop2.sh
screen -dmS blocks $WEB_DIR/blocks.sh
screen -dmS debug tail -f $LOG_DIR/debug.log
# Stratum ports
# Stratum instances (skipped/exit if no .conf)
screen -dmS c11 $STRATUM_DIR/run.sh c11
screen -dmS deep $STRATUM_DIR/run.sh deep
screen -dmS x11 $STRATUM_DIR/run.sh x11
screen -dmS x11evo $STRATUM_DIR/run.sh x11evo
screen -dmS x13 $STRATUM_DIR/run.sh x13
screen -dmS x14 $STRATUM_DIR/run.sh x14
screen -dmS x15 $STRATUM_DIR/run.sh x15
#screen -dmS x14 $STRATUM_DIR/run.sh x14
#screen -dmS x15 $STRATUM_DIR/run.sh x15
#screen -dmS x16r $STRATUM_DIR/run.sh x16r
screen -dmS x17 $STRATUM_DIR/run.sh x17
screen -dmS xevan $STRATUM_DIR/run.sh xevan
screen -dmS timetravel $STRATUM_DIR/run.sh timetravel
screen -dmS bitcore $STRATUM_DIR/run.sh bitcore
screen -dmS hmq1725 $STRATUM_DIR/run.sh hmq1725
screen -dmS tribus $STRATUM_DIR/run.sh tribus
screen -dmS sha $STRATUM_DIR/run.sh sha
screen -dmS sha256t $STRATUM_DIR/run.sh sha256t
screen -dmS scrypt $STRATUM_DIR/run.sh scrypt
screen -dmS scryptn $STRATUM_DIR/run.sh scryptn
screen -dmS luffa $STRATUM_DIR/run.sh luffa
@ -37,11 +45,16 @@ screen -dmS nist5 $STRATUM_DIR/run.sh nist5
screen -dmS penta $STRATUM_DIR/run.sh penta
screen -dmS quark $STRATUM_DIR/run.sh quark
screen -dmS qubit $STRATUM_DIR/run.sh qubit
screen -dmS jha $STRATUM_DIR/run.sh jha
#screen -dmS dmd-gr $STRATUM_DIR/run.sh dmd-gr
screen -dmS myr-gr $STRATUM_DIR/run.sh myr-gr
screen -dmS lbry $STRATUM_DIR/run.sh lbry
screen -dmS lyra2 $STRATUM_DIR/run.sh lyra2
screen -dmS allium $STRATUM_DIR/run.sh allium
#screen -dmS lyra2 $STRATUM_DIR/run.sh lyra2
screen -dmS lyra2v2 $STRATUM_DIR/run.sh lyra2v2
screen -dmS lyra2z $STRATUM_DIR/run.sh lyra2z
screen -dmS lyra2zz $STRATUM_DIR/run.sh lyra2zz
screen -dmS rainforest $STRATUM_DIR/run.sh rainforest
screen -dmS blakecoin $STRATUM_DIR/run.sh blakecoin # blake 8
screen -dmS blake $STRATUM_DIR/run.sh blake
@ -50,15 +63,22 @@ screen -dmS vanilla $STRATUM_DIR/run.sh vanilla # blake 8
screen -dmS decred $STRATUM_DIR/run.sh decred # blake 14
#screen -dmS keccak $STRATUM_DIR/run.sh keccak
#screen -dmS keccakc $STRATUM_DIR/run.sh keccakc
#screen -dmS phi $STRATUM_DIR/run.sh phi
#screen -dmS polytimos $STRATUM_DIR/run.sh polytimos
screen -dmS whirlpool $STRATUM_DIR/run.sh whirlpool
screen -dmS skein $STRATUM_DIR/run.sh skein
screen -dmS skein2 $STRATUM_DIR/run.sh skein2
screen -dmS yescrypt $STRATUM_DIR/run.sh yescrypt
#screen -dmS yescryptR16 $STRATUM_DIR/run.sh yescryptR16
screen -dmS zr5 $STRATUM_DIR/run.sh zr5
screen -dmS sib $STRATUM_DIR/run.sh sib
screen -dmS m7m $STRATUM_DIR/run.sh m7m
screen -dmS veltor $STRATUM_DIR/run.sh veltor
screen -dmS velvet $STRATUM_DIR/run.sh velvet
screen -dmS argon2 $STRATUM_DIR/run.sh argon2
screen -dmS argon2d-dyn $STRATUM_DIR/run.sh argon2d-dyn
screen -dmS x22i $STRATUM_DIR/run.sh x22i
screen -dmS lbk3 $STRATUM_DIR/run.sh lbk3

13
sql/2016-11-23-coins.sql Normal file
View file

@ -0,0 +1,13 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
-- don't forget to restart memcached service to refresh the db structure
ALTER TABLE `coins` ADD `powend_height` INT(11) NULL AFTER `target_height`;
ALTER TABLE `coins` ADD `mature_blocks` INT(11) NULL AFTER `reward_mul`;
ALTER TABLE `coins` ADD `block_time` INT(11) NULL AFTER `payout_max`;
ALTER TABLE `coins` ADD `available` DOUBLE NULL AFTER `balance`;
ALTER TABLE `coins` ADD `cleared` DOUBLE NULL AFTER `balance`;
ALTER TABLE `coins` ADD `immature` DOUBLE NULL AFTER `balance`;
ALTER TABLE `coins` ADD `max_miners` INT(11) NULL AFTER `visible`;
ALTER TABLE `coins` ADD `max_shares` INT(11) NULL AFTER `max_miners`;

View file

@ -0,0 +1,10 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
-- don't forget to restart memcached service to refresh the db structure
ALTER TABLE `benchmarks` ADD `realfreq` INT(8) UNSIGNED NULL AFTER `freq`;
ALTER TABLE `benchmarks` ADD `realmemf` INT(8) UNSIGNED NULL AFTER `memf`;
ALTER TABLE `benchmarks` ADD `plimit` INT(5) UNSIGNED NULL AFTER `power`;
ALTER TABLE `benchmarks` DROP COLUMN `mem`;

View file

@ -0,0 +1,5 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
ALTER TABLE `earnings` ADD UNIQUE INDEX `ndx_user_block`(`userid`, `blockid`);

View file

@ -0,0 +1,9 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
-- Adds binary type to be case sensitive
ALTER TABLE accounts CHANGE `username` `username` varchar(128) binary NOT NULL;
-- Remember last coin id swap
ALTER TABLE accounts ADD `swap_time` INT(10) UNSIGNED NULL AFTER `coinsymbol`;

View file

@ -0,0 +1,20 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
-- Store coin id used on payment, memoid could be used later for xrp
ALTER TABLE `payouts`
ADD `idcoin` int(11) NULL AFTER `account_id`,
ADD `memoid` varchar(128) NULL AFTER `tx`;
ALTER TABLE `payouts` DROP COLUMN `account_ids`;
ALTER TABLE `payouts`
ADD KEY `payouts_coin` (`idcoin`);
ALTER TABLE `payouts` ADD CONSTRAINT fk_payouts_coin FOREIGN KEY (`idcoin`)
REFERENCES coins (`id`) ON DELETE CASCADE;
ALTER TABLE `payouts` ADD CONSTRAINT fk_payouts_account FOREIGN KEY (`account_id`)
REFERENCES accounts (`id`) ON DELETE CASCADE;

View file

@ -0,0 +1,6 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
ALTER TABLE `notifications` CHANGE `lastchecked` `lastchecked` int(10) UNSIGNED NOT NULL DEFAULT '0';
ALTER TABLE `notifications` CHANGE `lasttriggered` `lasttriggered` int(10) UNSIGNED NOT NULL DEFAULT '0';

View file

@ -0,0 +1,8 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
ALTER TABLE `notifications` CHANGE `lastchecked` `lastchecked` int(10) UNSIGNED NULL;
ALTER TABLE `notifications` CHANGE `lasttriggered` `lasttriggered` int(10) UNSIGNED NULL;
ALTER TABLE `bookmarks` CHANGE `lastused` `lastused` int(10) UNSIGNED NULL;

7
sql/2017-11-segwit.sql Normal file
View file

@ -0,0 +1,7 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
ALTER TABLE `blocks` ADD `segwit` tinyint(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `txhash`;
ALTER TABLE `coins` ADD `usesegwit` tinyint(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `usememorypool`;

View file

@ -0,0 +1,17 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
-- filled by the stratum instance, to allow to handle/watch multiple instances
ALTER TABLE `stratums` ADD `started` int(11) UNSIGNED NULL AFTER `time`;
ALTER TABLE `stratums` ADD `workers` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `algo`;
ALTER TABLE `stratums` ADD `port` int(6) UNSIGNED NULL AFTER `workers`;
ALTER TABLE `stratums` ADD `symbol` varchar(16) NULL AFTER `port`;
ALTER TABLE `stratums` ADD `url` varchar(128) NULL AFTER `symbol`;
ALTER TABLE `stratums` ADD `fds` int(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `url`;

View file

@ -0,0 +1,13 @@
-- Recent additions to add after db init (.gz)
-- mysql yaamp -p < file.sql
-- filled by the stratum instance, to allow to handle/watch multiple instances
ALTER TABLE `coins` ADD `hasgetinfo` tinyint(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `account`;
UPDATE coins SET hassubmitblock=0 WHERE hassubmitblock IS NULL;
UPDATE coins SET hassubmitblock=1 WHERE hassubmitblock > 0;
ALTER TABLE `coins` CHANGE `hassubmitblock` `hassubmitblock` tinyint(1) UNSIGNED NOT NULL DEFAULT '1';
ALTER TABLE `coins` ADD `no_explorer` tinyint(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `visible`;

View file

@ -8,12 +8,6 @@ SQLFLAGS= `mysql_config --cflags --libs`
# if you use the auto exchange feature...
CFLAGS += -DNO_EXCHANGE
#CFLAGS += -DHASH_DEBUGLOG_
#CFLAGS += -DRPC_DEBUGLOG_
#CFLAGS += -DREMOTE_DEBUGLOG_
#CFLAGS += -DSOCKET_DEBUGLOG_
#CFLAGS += -DCLIENT_DEBUGLOG_
#CFLAGS=-c -O2 -I /usr/include/mysql
LDFLAGS=-O2 `mysql_config --libs`
@ -63,6 +57,7 @@ clean:
rm -f algos/*.a
rm -f sha3/*.o
rm -f sha3/*.a
rm -f algos/ar2/*.o
install: clean all
strip -s stratum

250
stratum/algos/Lyra2-z.c Executable file
View file

@ -0,0 +1,250 @@
/**
* Implementation of the Lyra2 Password Hashing Scheme (PHS).
*
* Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014.
*
* This software is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "Lyra2.h"
#include "Sponge.h"
static __thread uint64_t *wholeMatrix = NULL;
static __thread uint64_t **memMatrix = NULL;
static __thread uint64_t curRows = 0;
/**
* Executes Lyra2 based on the G function from Blake2b. This version supports salts and passwords
* whose combined length is smaller than the size of the memory matrix, (i.e., (nRows x nCols x b) bits,
* where "b" is the underlying sponge's bitrate). In this implementation, the "basil" is composed by all
* integer parameters (treated as type "unsigned int") in the order they are provided, plus the value
* of nCols, (i.e., basil = kLen || pwdlen || saltlen || timeCost || nRows || nCols).
*
* @param K The derived key to be output by the algorithm
* @param kLen Desired key length
* @param pwd User password
* @param pwdlen Password length
* @param salt Salt
* @param saltlen Salt length
* @param timeCost Parameter to determine the processing time (T)
* @param nRows Number or rows of the memory matrix (R)
* @param nCols Number of columns of the memory matrix (C)
*
* @return 0 if the key is generated correctly; -1 if there is an error (usually due to lack of memory for allocation)
*/
int LYRA2z(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols) {
//============================= Basic variables ============================//
int64_t row = 2; //index of row to be processed
int64_t prev = 1; //index of prev (last row ever computed/modified)
int64_t rowa = 0; //index of row* (a previous row, deterministically picked during Setup and randomly picked while Wandering)
int64_t tau; //Time Loop iterator
int64_t step = 1; //Visitation step (used during Setup and Wandering phases)
int64_t window = 2; //Visitation window (used to define which rows can be revisited during Setup)
int64_t gap = 1; //Modifier to the step, assuming the values 1 or -1
int64_t i; //auxiliary iteration counter
//==========================================================================/
//========== Initializing the Memory Matrix and pointers to it =============//
//Tries to allocate enough space for the whole memory matrix
const int64_t ROW_LEN_INT64 = BLOCK_LEN_INT64 * nCols;
const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8;
uint64_t *ptrWord = wholeMatrix;
if (!wholeMatrix || !memMatrix) {
curRows = nRows + 32;
i = (int64_t) ((int64_t) curRows * (int64_t) ROW_LEN_BYTES);
wholeMatrix = (uint64_t*) malloc(i);
if (wholeMatrix == NULL) {
return -1;
}
//Allocates pointers to each row of the matrix
memMatrix = malloc(sizeof(uint64_t*) * curRows);
if (memMatrix == NULL) {
return -1;
}
//Places the pointers in the correct positions
ptrWord = wholeMatrix;
for (i = 0; i < curRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
} else {
if (nRows > curRows) {
free(memMatrix); memMatrix = NULL;
free(wholeMatrix); wholeMatrix = NULL;
return -2;
}
memset(wholeMatrix, 0, nRows * ROW_LEN_BYTES);
}
/*
i = (int64_t) ((int64_t) nRows * (int64_t) ROW_LEN_BYTES);
uint64_t *wholeMatrix = malloc(i);
if (wholeMatrix == NULL) {
return -1;
}
memset(wholeMatrix, 0, i);
//Allocates pointers to each row of the matrix
uint64_t **memMatrix = malloc(nRows * sizeof (uint64_t*));
if (memMatrix == NULL) {
return -1;
}
//Places the pointers in the correct positions
uint64_t *ptrWord = wholeMatrix;
for (i = 0; i < nRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
*/
//==========================================================================/
//============= Getting the password + salt + basil padded with 10*1 ===============//
//OBS.:The memory matrix will temporarily hold the password: not for saving memory,
//but this ensures that the password copied locally will be overwritten as soon as possible
//First, we clean enough blocks for the password, salt, basil and padding
uint64_t nBlocksInput = ((saltlen + pwdlen + 6 * sizeof (uint64_t)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1;
byte *ptrByte = (byte*) wholeMatrix;
memset(ptrByte, 0, nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES);
//Prepends the password
memcpy(ptrByte, pwd, pwdlen);
ptrByte += pwdlen;
//Concatenates the salt
memcpy(ptrByte, salt, saltlen);
ptrByte += saltlen;
//Concatenates the basil: every integer passed as parameter, in the order they are provided by the interface
memcpy(ptrByte, &kLen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &pwdlen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &saltlen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &timeCost, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &nRows, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &nCols, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
//Now comes the padding
*ptrByte = 0x80; //first byte of padding: right after the password
ptrByte = (byte*) wholeMatrix; //resets the pointer to the start of the memory matrix
ptrByte += nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1; //sets the pointer to the correct position: end of incomplete block
*ptrByte ^= 0x01; //last byte of padding: at the end of the last incomplete block
//==========================================================================/
//======================= Initializing the Sponge State ====================//
//Sponge state: 16 uint64_t, BLOCK_LEN_INT64 words of them for the bitrate (b) and the remainder for the capacity (c)
uint64_t *state = malloc(16 * sizeof (uint64_t));
if (state == NULL) {
return -1;
}
initState(state);
//==========================================================================/
//================================ Setup Phase =============================//
//Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits
ptrWord = wholeMatrix;
for (i = 0; i < nBlocksInput; i++) {
absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil)
ptrWord += BLOCK_LEN_BLAKE2_SAFE_INT64; //goes to next block of pad(pwd || salt || basil)
}
//Initializes M[0] and M[1]
reducedSqueezeRow0(state, memMatrix[0], nCols); //The locally copied password is most likely overwritten here
reducedDuplexRow1(state, memMatrix[0], memMatrix[1], nCols);
do {
//M[row] = rand; //M[row*] = M[row*] XOR rotW(rand)
reducedDuplexRowSetup(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//updates the value of row* (deterministically picked during Setup))
rowa = (rowa + step) & (window - 1);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
row++;
//Checks if all rows in the window where visited.
if (rowa == 0) {
step = window + gap; //changes the step: approximately doubles its value
window *= 2; //doubles the size of the re-visitation window
gap = -gap; //inverts the modifier to the step
}
} while (row < nRows);
//==========================================================================/
//============================ Wandering Phase =============================//
row = 0; //Resets the visitation to the first row of the memory matrix
for (tau = 1; tau <= timeCost; tau++) {
//Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1
step = (tau % 2 == 0) ? -1 : nRows / 2 - 1;
do {
//Selects a pseudorandom index row*
//------------------------------------------------------------------------------------------
//rowa = ((unsigned int)state[0]) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
rowa = ((uint64_t) (state[0])) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
//Performs a reduced-round duplexing operation over M[row*] XOR M[prev], updating both M[row*] and M[row]
reducedDuplexRow(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
//------------------------------------------------------------------------------------------
//row = (row + step) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
row = (row + step) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
} while (row != 0);
}
//==========================================================================/
//============================ Wrap-up Phase ===============================//
//Absorbs the last block of the memory matrix
absorbBlock(state, memMatrix[rowa]);
//Squeezes the key
squeeze(state, K, kLen);
//==========================================================================/
//========================= Freeing the memory =============================//
//free(memMatrix);
//free(wholeMatrix);
//Wiping out the sponge's internal state before freeing it
memset(state, 0, 16 * sizeof (uint64_t));
free(state);
//==========================================================================/
return 0;
}

51
stratum/algos/Lyra2-z.h Executable file
View file

@ -0,0 +1,51 @@
/**
* Header file for the Lyra2 Password Hashing Scheme (PHS).
*
* Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014.
*
* This software is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LYRA2z_H_
#define LYRA2z_H_
#include <stdint.h>
typedef unsigned char byte;
//Block length required so Blake2's Initialization Vector (IV) is not overwritten (THIS SHOULD NOT BE MODIFIED)
#define BLOCK_LEN_BLAKE2_SAFE_INT64 8 //512 bits (=64 bytes, =8 uint64_t)
#define BLOCK_LEN_BLAKE2_SAFE_BYTES (BLOCK_LEN_BLAKE2_SAFE_INT64 * 8) //same as above, in bytes
#ifdef BLOCK_LEN_BITS
#define BLOCK_LEN_INT64 (BLOCK_LEN_BITS/64) //Block length: 768 bits (=96 bytes, =12 uint64_t)
#define BLOCK_LEN_BYTES (BLOCK_LEN_BITS/8) //Block length, in bytes
#else //default block lenght: 768 bits
#define BLOCK_LEN_INT64 12 //Block length: 768 bits (=96 bytes, =12 uint64_t)
#define BLOCK_LEN_BYTES (BLOCK_LEN_INT64 * 8) //Block length, in bytes
#endif
#ifdef __cplusplus
extern "C" {
#endif
int LYRA2z(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols);
#ifdef __cplusplus
}
#endif
#endif /* LYRA2z_H_ */

210
stratum/algos/Lyra2-zz.c Normal file
View file

@ -0,0 +1,210 @@
/**
* Implementation of the Lyra2 Password Hashing Scheme (PHS).
*
* Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014.
*
* This software is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "Lyra2-zz.h"
#include "Sponge.h"
/**
* Executes Lyra2 based on the G function from Blake2b. This version supports salts and passwords
* whose combined length is smaller than the size of the memory matrix, (i.e., (nRows x nCols x b) bits,
* where "b" is the underlying sponge's bitrate). In this implementation, the "basil" is composed by all
* integer parameters (treated as type "unsigned int") in the order they are provided, plus the value
* of nCols, (i.e., basil = kLen || pwdlen || saltlen || timeCost || nRows || nCols).
*
* @param K The derived key to be output by the algorithm
* @param kLen Desired key length
* @param pwd User password
* @param pwdlen Password length
* @param salt Salt
* @param saltlen Salt length
* @param timeCost Parameter to determine the processing time (T)
* @param nRows Number or rows of the memory matrix (R)
* @param nCols Number of columns of the memory matrix (C)
*
* @return 0 if the key is generated correctly; -1 if there is an error (usually due to lack of memory for allocation)
*/
int LYRA2ZZ(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols)
{
//============================= Basic variables ============================//
int64_t row = 2; //index of row to be processed
int64_t prev = 1; //index of prev (last row ever computed/modified)
int64_t rowa = 0; //index of row* (a previous row, deterministically picked during Setup and randomly picked while Wandering)
int64_t tau; //Time Loop iterator
int64_t step = 1; //Visitation step (used during Setup and Wandering phases)
int64_t window = 2; //Visitation window (used to define which rows can be revisited during Setup)
int64_t gap = 1; //Modifier to the step, assuming the values 1 or -1
int64_t i; //auxiliary iteration counter
//==========================================================================/
//========== Initializing the Memory Matrix and pointers to it =============//
//Tries to allocate enough space for the whole memory matrix
const int64_t ROW_LEN_INT64 = BLOCK_LEN_INT64 * nCols;
const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8;
i = (int64_t) ((int64_t) nRows * (int64_t) ROW_LEN_BYTES);
uint64_t *wholeMatrix = malloc(i);
if (wholeMatrix == NULL) {
return -1;
}
memset(wholeMatrix, 0, i);
//Allocates pointers to each row of the matrix
uint64_t **memMatrix = malloc(nRows * sizeof (uint64_t*));
if (memMatrix == NULL) {
return -1;
}
//Places the pointers in the correct positions
uint64_t *ptrWord = wholeMatrix;
for (i = 0; i < nRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
//==========================================================================/
//============= Getting the password + salt + basil padded with 10*1 ===============//
//OBS.:The memory matrix will temporarily hold the password: not for saving memory,
//but this ensures that the password copied locally will be overwritten as soon as possible
//First, we clean enough blocks for the password, salt, basil and padding
uint64_t nBlocksInput = ((saltlen + pwdlen + 6 * sizeof (uint64_t)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1;
byte *ptrByte = (byte*) wholeMatrix;
memset(ptrByte, 0, nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES);
//Prepends the password
memcpy(ptrByte, pwd, pwdlen);
ptrByte += pwdlen;
//Concatenates the salt
memcpy(ptrByte, salt, saltlen);
ptrByte += saltlen;
//Concatenates the basil: every integer passed as parameter, in the order they are provided by the interface
memcpy(ptrByte, &kLen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &pwdlen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &saltlen, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &timeCost, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &nRows, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
memcpy(ptrByte, &nCols, sizeof (uint64_t));
ptrByte += sizeof (uint64_t);
//Now comes the padding
*ptrByte = 0x80; //first byte of padding: right after the password
ptrByte = (byte*) wholeMatrix; //resets the pointer to the start of the memory matrix
ptrByte += nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1; //sets the pointer to the correct position: end of incomplete block
*ptrByte ^= 0x01; //last byte of padding: at the end of the last incomplete block
//==========================================================================/
//======================= Initializing the Sponge State ====================//
//Sponge state: 16 uint64_t, BLOCK_LEN_INT64 words of them for the bitrate (b) and the remainder for the capacity (c)
uint64_t *state = malloc(16 * sizeof (uint64_t));
if (state == NULL) {
return -1;
}
initState(state);
//==========================================================================/
//================================ Setup Phase =============================//
//Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits
ptrWord = wholeMatrix;
for (i = 0; i < nBlocksInput; i++) {
absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil)
ptrWord += BLOCK_LEN_BLAKE2_SAFE_INT64; //goes to next block of pad(pwd || salt || basil)
}
//Initializes M[0] and M[1]
reducedSqueezeRow0(state, memMatrix[0], nCols); //The locally copied password is most likely overwritten here
reducedDuplexRow1(state, memMatrix[0], memMatrix[1], nCols);
do {
//M[row] = rand; //M[row*] = M[row*] XOR rotW(rand)
reducedDuplexRowSetup(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//updates the value of row* (deterministically picked during Setup))
rowa = (rowa + step) & (window - 1);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
row++;
//Checks if all rows in the window where visited.
if (rowa == 0) {
step = window + gap; //changes the step: approximately doubles its value
window *= 2; //doubles the size of the re-visitation window
gap = -gap; //inverts the modifier to the step
}
} while (row < nRows);
//==========================================================================/
//============================ Wandering Phase =============================//
row = 0; //Resets the visitation to the first row of the memory matrix
for (tau = 1; tau <= timeCost; tau++) {
//Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1
step = (tau % 2 == 0) ? -1 : nRows / 2 - 1;
do {
//Selects a pseudorandom index row*
//------------------------------------------------------------------------------------------
//rowa = ((unsigned int)state[0]) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
rowa = ((uint64_t) (state[0])) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
//Performs a reduced-round duplexing operation over M[row*] XOR M[prev], updating both M[row*] and M[row]
reducedDuplexRow(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
//------------------------------------------------------------------------------------------
//row = (row + step) & (nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
row = (row + step) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
} while (row != 0);
}
//==========================================================================/
//============================ Wrap-up Phase ===============================//
//Absorbs the last block of the memory matrix
absorbBlock(state, memMatrix[rowa]);
//Squeezes the key
squeeze(state, K, kLen);
//==========================================================================/
//========================= Freeing the memory =============================//
free(memMatrix);
free(wholeMatrix);
//Wiping out the sponge's internal state before freeing it
memset(state, 0, 16 * sizeof (uint64_t));
free(state);
//==========================================================================/
return 0;
}

55
stratum/algos/Lyra2-zz.h Normal file
View file

@ -0,0 +1,55 @@
/**
* Header file for the Lyra2 Password Hashing Scheme (PHS).
*
* Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014.
*
* This software is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LYRA2ZZ_H_
#define LYRA2ZZ_H_
#include <stdint.h>
typedef unsigned char byte;
//Block length required so Blake2's Initialization Vector (IV) is not overwritten (THIS SHOULD NOT BE MODIFIED)
#define BLOCK_LEN_BLAKE2_SAFE_INT64 12 //768 bits (=96 bytes, =12 uint64_t)
#define BLOCK_LEN_BLAKE2_SAFE_BYTES (BLOCK_LEN_BLAKE2_SAFE_INT64 * 8) //same as above, in bytes
#define LYRA2ZZ_BLOCK_HEADER_LEN_BYTES 112
#define LYRA2ZZ_BLOCK_HEADER_NONCE_OFFSET 19 /* 19 * 4 bytes */
#define LYRA2ZZ_BLOCK_HEADER_UINT32_LEN 32
#ifdef BLOCK_LEN_BITS
#define BLOCK_LEN_INT64 (BLOCK_LEN_BITS/64) //Block length: 1024 bits (=128 bytes, =16 uint64_t)
#define BLOCK_LEN_BYTES (BLOCK_LEN_BITS/8) //Block length, in bytes
#else //default block length: 1024 bits
#define BLOCK_LEN_INT64 16 //Block length: 1024 bits (=128 bytes, =16 uint64_t)
#define BLOCK_LEN_BYTES (BLOCK_LEN_INT64 * 8) //Block length, in bytes
#endif
#ifdef __cplusplus
extern "C" {
#endif
int LYRA2ZZ(void *K, uint64_t kLen, const void *pwd, uint64_t pwdlen, const void *salt, uint64_t saltlen, uint64_t timeCost, uint64_t nRows, uint64_t nCols);
#ifdef __cplusplus
}
#endif
#endif /* LYRA2ZZ_H_ */

View file

@ -212,3 +212,175 @@ int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *sa
return 0;
}
int LYRA2_3(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols)
{
//============================= Basic variables ============================//
int64_t row = 2; //index of row to be processed
int64_t prev = 1; //index of prev (last row ever computed/modified)
int64_t rowa = 0; //index of row* (a previous row, deterministically picked during Setup and randomly picked while Wandering)
int64_t tau; //Time Loop iterator
int64_t step = 1; //Visitation step (used during Setup and Wandering phases)
int64_t window = 2; //Visitation window (used to define which rows can be revisited during Setup)
int64_t gap = 1; //Modifier to the step, assuming the values 1 or -1
int64_t i; //auxiliary iteration counter
int64_t v64; // 64bit var for memcpy
uint64_t instance = 0;
//==========================================================================/
//========== Initializing the Memory Matrix and pointers to it =============//
//Tries to allocate enough space for the whole memory matrix
const int64_t ROW_LEN_INT64 = BLOCK_LEN_INT64 * nCols;
const int64_t ROW_LEN_BYTES = ROW_LEN_INT64 * 8;
const int64_t BLOCK_LEN = BLOCK_LEN_BLAKE2_SAFE_INT64;
size_t sz = (size_t)ROW_LEN_BYTES * nRows;
uint64_t *wholeMatrix = malloc(sz);
if (wholeMatrix == NULL) {
return -1;
}
memset(wholeMatrix, 0, sz);
//Allocates pointers to each row of the matrix
uint64_t **memMatrix = malloc(sizeof(uint64_t*) * nRows);
if (memMatrix == NULL) {
return -1;
}
//Places the pointers in the correct positions
uint64_t *ptrWord = wholeMatrix;
for (i = 0; i < nRows; i++) {
memMatrix[i] = ptrWord;
ptrWord += ROW_LEN_INT64;
}
//==========================================================================/
//============= Getting the password + salt + basil padded with 10*1 ===============//
//OBS.:The memory matrix will temporarily hold the password: not for saving memory,
//but this ensures that the password copied locally will be overwritten as soon as possible
//First, we clean enough blocks for the password, salt, basil and padding
int64_t nBlocksInput = ((saltlen + pwdlen + 6 * sizeof(uint64_t)) / BLOCK_LEN_BLAKE2_SAFE_BYTES) + 1;
byte *ptrByte = (byte*) wholeMatrix;
//Prepends the password
memcpy(ptrByte, pwd, pwdlen);
ptrByte += pwdlen;
//Concatenates the salt
memcpy(ptrByte, salt, saltlen);
ptrByte += saltlen;
memset(ptrByte, 0, (size_t) (nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - (saltlen + pwdlen)));
//Concatenates the basil: every integer passed as parameter, in the order they are provided by the interface
memcpy(ptrByte, &kLen, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = pwdlen;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = saltlen;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = timeCost;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = nRows;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
v64 = nCols;
memcpy(ptrByte, &v64, sizeof(int64_t));
ptrByte += sizeof(uint64_t);
//Now comes the padding
*ptrByte = 0x80; //first byte of padding: right after the password
ptrByte = (byte*) wholeMatrix; //resets the pointer to the start of the memory matrix
ptrByte += nBlocksInput * BLOCK_LEN_BLAKE2_SAFE_BYTES - 1; //sets the pointer to the correct position: end of incomplete block
*ptrByte ^= 0x01; //last byte of padding: at the end of the last incomplete block
//==========================================================================/
//======================= Initializing the Sponge State ====================//
//Sponge state: 16 uint64_t, BLOCK_LEN_INT64 words of them for the bitrate (b) and the remainder for the capacity (c)
uint64_t state[16];
initState(state);
//==========================================================================/
//================================ Setup Phase =============================//
//Absorbing salt, password and basil: this is the only place in which the block length is hard-coded to 512 bits
ptrWord = wholeMatrix;
for (i = 0; i < nBlocksInput; i++) {
absorbBlockBlake2Safe(state, ptrWord); //absorbs each block of pad(pwd || salt || basil)
ptrWord += BLOCK_LEN; //goes to next block of pad(pwd || salt || basil)
}
//Initializes M[0] and M[1]
reducedSqueezeRow0(state, memMatrix[0], nCols); //The locally copied password is most likely overwritten here
reducedDuplexRow1(state, memMatrix[0], memMatrix[1], nCols);
do {
//M[row] = rand; //M[row*] = M[row*] XOR rotW(rand)
reducedDuplexRowSetup(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//updates the value of row* (deterministically picked during Setup))
rowa = (rowa + step) & (window - 1);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
row++;
//Checks if all rows in the window where visited.
if (rowa == 0) {
step = window + gap; //changes the step: approximately doubles its value
window *= 2; //doubles the size of the re-visitation window
gap = -gap; //inverts the modifier to the step
}
} while (row < nRows);
//==========================================================================/
//============================ Wandering Phase =============================//
row = 0; //Resets the visitation to the first row of the memory matrix
for (tau = 1; tau <= timeCost; tau++) {
//Step is approximately half the number of all rows of the memory matrix for an odd tau; otherwise, it is -1
step = ((tau & 1) == 0) ? -1 : (nRows >> 1) - 1;
do {
//Selects a pseudorandom index row*
//------------------------------------------------------------------------------------------
instance = state[instance & 0xF];
rowa = state[instance & 0xF] & (unsigned int)(nRows-1);
//rowa = state[0] & (unsigned int)(nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
//rowa = state[0] % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
//Performs a reduced-round duplexing operation over M[row*] XOR M[prev], updating both M[row*] and M[row]
reducedDuplexRow(state, memMatrix[prev], memMatrix[rowa], memMatrix[row], nCols);
//update prev: it now points to the last row ever computed
prev = row;
//updates row: goes to the next row to be computed
//------------------------------------------------------------------------------------------
row = (row + step) & (unsigned int)(nRows-1); //(USE THIS IF nRows IS A POWER OF 2)
//row = (row + step) % nRows; //(USE THIS FOR THE "GENERIC" CASE)
//------------------------------------------------------------------------------------------
} while (row != 0);
}
//============================ Wrap-up Phase ===============================//
//Absorbs the last block of the memory matrix
absorbBlock(state, memMatrix[rowa]);
//Squeezes the key
squeeze(state, K, (unsigned int) kLen);
//========================= Freeing the memory =============================//
free(memMatrix);
free(wholeMatrix);
return 0;
}

View file

@ -39,4 +39,6 @@ typedef unsigned char byte;
int LYRA2(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols);
int LYRA2_3(void *K, int64_t kLen, const void *pwd, int32_t pwdlen, const void *salt, int32_t saltlen, int64_t timeCost, const int16_t nRows, const int16_t nCols);
#endif /* LYRA2_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,73 @@
///////////////////////////////////////////////////////////////////////////////////////////////
//
// SWIFFTX ANSI C OPTIMIZED 32BIT IMPLEMENTATION FOR NIST SHA-3 COMPETITION
//
// SWIFFTX.h
//
// October 2008
//
// This file is the exact copy from the reference implementation.
//
///////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __SWIFFTX__
#define __SWIFFTX__
#ifdef __cplusplus
extern "C"{
#endif
// See the remarks concerning compatibility issues inside stdint.h.
#include "stdint.h"
#include "stdbool.h"
// The size of SWIFFTX input in bytes.
#define SWIFFTX_INPUT_BLOCK_SIZE 256
// The size of output block in bytes. The compression function of SWIFFT outputs a block of
// this size (i.e., this is the size of the resulting hash value).
#define SWIFFTX_OUTPUT_BLOCK_SIZE 65
// Computes the result of a single SWIFFT operation.
// This is the simple implementation, where our main concern is to show our design principles.
// It is made more efficient in the optimized version, by using FFT instead of DFT, and
// through other speed-up techniques.
//
// Parameters:
// - input: the input string. Consists of 8*m input bytes, where each octet passes the DFT
// processing.
// - m: the length of the input in bytes.
// - output: the resulting hash value of SWIFFT, of size 65 bytes (520 bit). This is the
// result of summing the dot products of the DFTS with the A's after applying the base
// change transformation
// - A: the A's coefficients to work with (since every SWIFFT in SWIFFTX uses different As).
// A single application of SWIFFT uses 64*m A's.
void ComputeSingleSWIFFT(unsigned char *input, unsigned short m,
unsigned char output[SWIFFTX_OUTPUT_BLOCK_SIZE],
const swift_int16_t *a);
// Computes the result of a single SWIFFTX operation.
// NOTE: for simplicity we use 'ComputeSingleSWIFFT()' as a subroutine. This is only to show
// the design idea. In the optimized versions we don't do this for efficiency concerns, since
// there we compute the first part (which doesn't involve the A coefficients) only once for all
// of the 3 invocations of SWIFFT. This enables us to introduce a significant speedup.
//
// Parameters:
// - input: the input input of 256 bytes (2048 bit).
// - output: the resulting hash value of SWIFFT, of size 64 bytes (512 bit).
// - doSMooth: if true, a final smoothing stage is performed and the output is of size 512 bits.
//
// Returns:
// - Success value.
void ComputeSingleSWIFFTX(unsigned char input[SWIFFTX_INPUT_BLOCK_SIZE],
unsigned char output[SWIFFTX_OUTPUT_BLOCK_SIZE],
bool doSmooth);
// Calculates the powers of OMEGA and generates the bit reversal permutation.
// You must call this function before doing SWIFFT/X, otherwise you will get zeroes everywhere.
void InitializeSWIFFTX();
#ifdef __cplusplus
}
#endif
#endif // __SWIFFTX__

View file

@ -0,0 +1,39 @@
/*
inttypes.h
Contributors:
Created by Marek Michalkiewicz <marekm@linux.org.pl>
THIS SOFTWARE IS NOT COPYRIGHTED
This source code is offered for use in the public domain. You may
use, modify or distribute it freely.
This code is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
DISCLAIMED. This includes but is not limited to warranties of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __INTTYPES_H_
#define __INTTYPES_H_
/* Use [u]intN_t if you need exactly N bits.
XXX - doesn't handle the -mint8 option. */
typedef signed char swift_int8_t;
typedef unsigned char swift_uint8_t;
typedef int swift_int16_t;
typedef unsigned int swift_uint16_t;
typedef long swift_int32_t;
typedef unsigned long swift_uint32_t;
typedef long long swift_int64_t;
typedef unsigned long long swift_uint64_t;
//typedef swift_int16_t intptr_t;
//typedef swift_uint16_t uintptr_t;
#endif

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2000 Jeroen Ruigrok van der Werven <asmodai@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/include/stdbool.h,v 1.6 2002/08/16 07:33:14 alfred Exp $
*/
#ifndef _STDBOOL_H_
#define _STDBOOL_H_
#define __bool_true_false_are_defined 1
#ifndef __cplusplus
#define false 0
#define true 1
#define bool _Bool
#if __STDC_VERSION__ < 199901L && __GNUC__ < 3
typedef int _Bool;
#endif
#endif /* !__cplusplus */
#endif /* !_STDBOOL_H_ */

View file

@ -0,0 +1,54 @@
#ifndef _SWIFFT_STDINT_H
#define _SWIFFT_STDINT_H
///////////////////////////////////////////////////////////////////////////////////////////////
//
// A note from SWIFFTX implementers:
//
// Although the submission was targeted for Microsoft Visual Studio 2005 compiler, we strived
// to make the code as portable as possible. This is why we preferred to use the types defined
// here, instead of Microsoft-specific types. We compiled the code with gcc to make this sure.
// However, we couldn't use this header as is, due to VS2005 compiler objections. This is why
// we commented out certain defines and clearly marked it.
// To compile our code on gcc you may define SYS_STDINT.
//
///////////////////////////////////////////////////////////////////////////////////////////////
#ifdef SYS_STDINT
#include <stdint.h>
#else
#include "inttypes.h"
// The following was commented out by SWIFFTX implementers:
// __BEGIN_DECLS
typedef swift_int8_t swifftx_int_least8_t;
typedef swift_int16_t swifftx_int_least16_t;
typedef swift_int32_t swifftx_int_least32_t;
typedef swift_uint8_t swifftx_uint_least8_t;
typedef swift_uint16_t swifftx_uint_least16_t;
typedef swift_uint32_t swifftx_uint_least32_t;
#ifndef __STRICT_ANSI__
typedef swift_int64_t swifftx_int_least64_t;
typedef swift_uint64_t swifftx_uint_least64_t;
#endif
/*typedef signed char int_fast8_t;
typedef signed long int int_fast16_t;
typedef signed long int int_fast32_t;
typedef signed long long int int_fast64_t;
typedef unsigned char uint_fast8_t;
typedef unsigned long int uint_fast16_t;
typedef unsigned long int uint_fast32_t;
typedef unsigned long long int uint_fast64_t;*/
// The following was commented out by SWIFFTX implementers:
// #include <endian.h>
// __END_DECLS
#endif
#endif

260
stratum/algos/a5a.c Normal file
View file

@ -0,0 +1,260 @@
#include <float.h>
#include <math.h>
#include <gmp.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "a5amath.h"
#include "../sha3/sph_sha2.h"
#include "../sha3/sph_keccak.h"
#include "../sha3/sph_whirlpool.h"
#include "../sha3/sph_ripemd.h"
static void mpz_set_uint256(mpz_t r, uint8_t *u)
{
mpz_import(r, 32 / sizeof(unsigned long), -1, sizeof(unsigned long), -1, 0, u);
}
static void mpz_get_uint256(mpz_t r, uint8_t *u)
{
u=0;
mpz_export(u, 0, -1, sizeof(unsigned long), -1, 0, r);
}
static void mpz_set_uint512(mpz_t r, uint8_t *u)
{
mpz_import(r, 64 / sizeof(unsigned long), -1, sizeof(unsigned long), -1, 0, u);
}
static void set_one_if_zero(uint8_t *hash512) {
int i;
for (i = 0; i < 32; i++) {
if (hash512[i] != 0) {
return;
}
}
hash512[0] = 1;
}
#define BITS_PER_DIGIT 3.32192809488736234787
//#define EPS (std::numeric_limits<double>::epsilon())
#define EPS (DBL_EPSILON)
#define Na5a 5
#define SW_DIVS 5
//#define SW_MAX 1000
void a5a_hash(const char* input, char* output, uint32_t len)
{
unsigned int nnNonce;
uint32_t pdata[32];
memcpy(pdata, input, 80);
// memcpy(&nnNonce, input+76, 4);
int i, j, bytes, nnNonce2;
nnNonce2 = (int)(pdata[19]/2);
size_t sz = 80;
uint8_t bhash[5][64];
uint32_t hash[6];
memset(bhash, 0, 5 * 64);
sph_sha256_context ctx_final_sha256;
sph_sha256_context ctx_sha256;
sph_sha512_context ctx_sha512;
sph_keccak512_context ctx_keccak;
sph_whirlpool_context ctx_whirlpool;
sph_ripemd160_context ctx_ripemd;
sph_sha256_init(&ctx_sha256);
// ZSHA256;
sph_sha256 (&ctx_sha256, input, sz);
sph_sha256_close(&ctx_sha256, (void*)(bhash[0]));
sph_sha512_init(&ctx_sha512);
// ZSHA512;
sph_sha512 (&ctx_sha512, input, sz);
sph_sha512_close(&ctx_sha512, (void*)(bhash[1]));
sph_keccak512_init(&ctx_keccak);
// ZKECCAK;
sph_keccak512 (&ctx_keccak, input, sz);
sph_keccak512_close(&ctx_keccak, (void*)(bhash[2]));
sph_whirlpool_init(&ctx_whirlpool);
// ZWHIRLPOOL;
sph_whirlpool (&ctx_whirlpool, input, sz);
sph_whirlpool_close(&ctx_whirlpool, (void*)(bhash[3]));
sph_ripemd160_init(&ctx_ripemd);
// ZRIPEMD;
sph_ripemd160 (&ctx_ripemd, input, sz);
sph_ripemd160_close(&ctx_ripemd, (void*)(bhash[4]));
// printf("%s\n", hash[4].GetHex().c_str());
mpz_t bns[6];
for(i=0; i < 6; i++){
mpz_init(bns[i]);
}
//Take care of zeros and load gmp
for(i=0; i < 5; i++){
set_one_if_zero(bhash[i]);
mpz_set_uint512(bns[i],bhash[i]);
}
mpz_set_ui(bns[5],0);
for(i=0; i < 5; i++)
mpz_add(bns[5], bns[5], bns[i]);
mpz_t product;
mpz_init(product);
mpz_set_ui(product,1);
// mpz_pow_ui(bns[5], bns[5], 2);
for(i=0; i < 6; i++){
mpz_mul(product,product,bns[i]);
}
mpz_pow_ui(product, product, 2);
bytes = mpz_sizeinbase(product, 256);
// printf("a5a data space: %iB\n", bytes);
char *data = (char*)malloc(bytes);
mpz_export(data, NULL, -1, 1, 0, 0, product);
sph_sha256_init(&ctx_final_sha256);
// ZSHA256;
sph_sha256 (&ctx_final_sha256, data, bytes);
sph_sha256_close(&ctx_final_sha256, (void*)(hash));
free(data);
int digits=(int)((sqrt((double)(nnNonce2))*(1.+EPS))/9000+75);
// int iterations=(int)((sqrt((double)(nnNonce2))+EPS)/500+350); // <= 500
// int digits=100;
int iterations=20; // <= 500
mpf_set_default_prec((long int)(digits*BITS_PER_DIGIT+16));
mpz_t a5api;
mpz_t a5asw;
mpf_t a5afpi;
mpf_t mpa1, mpb1, mpt1, mpp1;
mpf_t mpa2, mpb2, mpt2, mpp2;
mpf_t mpsft;
mpz_init(a5api);
mpz_init(a5asw);
mpf_init(a5afpi);
mpf_init(mpsft);
mpf_init(mpa1);
mpf_init(mpb1);
mpf_init(mpt1);
mpf_init(mpp1);
mpf_init(mpa2);
mpf_init(mpb2);
mpf_init(mpt2);
mpf_init(mpp2);
uint32_t usw_;
usw_ = sw_(nnNonce2, SW_DIVS);
if (usw_ < 1) usw_ = 1;
// if(fDebuga5a) printf("usw_: %d\n", usw_);
mpz_set_ui(a5asw, usw_);
uint32_t mpzscale=mpz_size(a5asw);
for(i=0; i < Na5a; i++)
{
if (mpzscale > 1000) {
mpzscale = 1000;
}
else if (mpzscale < 1) {
mpzscale = 1;
}
// if(fDebuga5a) printf("mpzscale: %d\n", mpzscale);
mpf_set_ui(mpa1, 1);
mpf_set_ui(mpb1, 2);
mpf_set_d(mpt1, 0.25*mpzscale);
mpf_set_ui(mpp1, 1);
mpf_sqrt(mpb1, mpb1);
mpf_ui_div(mpb1, 1, mpb1);
mpf_set_ui(mpsft, 10);
for(j=0; j <= iterations; j++)
{
mpf_add(mpa2, mpa1, mpb1);
mpf_div_ui(mpa2, mpa2, 2);
mpf_mul(mpb2, mpa1, mpb1);
mpf_abs(mpb2, mpb2);
mpf_sqrt(mpb2, mpb2);
mpf_sub(mpt2, mpa1, mpa2);
mpf_abs(mpt2, mpt2);
mpf_sqrt(mpt2, mpt2);
mpf_mul(mpt2, mpt2, mpp1);
mpf_sub(mpt2, mpt1, mpt2);
mpf_mul_ui(mpp2, mpp1, 2);
mpf_swap(mpa1, mpa2);
mpf_swap(mpb1, mpb2);
mpf_swap(mpt1, mpt2);
mpf_swap(mpp1, mpp2);
}
mpf_add(a5afpi, mpa1, mpb1);
mpf_pow_ui(a5afpi, a5afpi, 2);
mpf_div_ui(a5afpi, a5afpi, 4);
mpf_abs(mpt1, mpt1);
mpf_div(a5afpi, a5afpi, mpt1);
// mpf_out_str(stdout, 10, digits+2, a5afpi);
mpf_pow_ui(mpsft, mpsft, digits/2);
mpf_mul(a5afpi, a5afpi, mpsft);
mpz_set_f(a5api, a5afpi);
//mpz_set_ui(a5api,1);
mpz_add(product,product,a5api);
mpz_add(product,product,a5asw);
mpz_set_uint256(bns[0], (void*)(hash));
mpz_add(bns[5], bns[5], bns[0]);
mpz_mul(product,product,bns[5]);
mpz_cdiv_q (product, product, bns[0]);
if (mpz_sgn(product) <= 0) mpz_set_ui(product,1);
bytes = mpz_sizeinbase(product, 256);
mpzscale=bytes;
// printf("a5a data space: %iB\n", bytes);
char *bdata = (char*)malloc(bytes);
mpz_export(bdata, NULL, -1, 1, 0, 0, product);
sph_sha256_init(&ctx_final_sha256);
// ZSHA256;
sph_sha256 (&ctx_final_sha256, bdata, bytes);
sph_sha256_close(&ctx_final_sha256, (void*)(hash));
free(bdata);
}
//Free the memory
for(i=0; i < 6; i++){
mpz_clear(bns[i]);
}
// mpz_clear(dSpectralWeight);
mpz_clear(product);
mpz_clear(a5api);
mpz_clear(a5asw);
mpf_clear(a5afpi);
mpf_clear(mpsft);
mpf_clear(mpa1);
mpf_clear(mpb1);
mpf_clear(mpt1);
mpf_clear(mpp1);
mpf_clear(mpa2);
mpf_clear(mpb2);
mpf_clear(mpt2);
mpf_clear(mpp2);
memcpy(output, hash, 32);
}

14
stratum/algos/a5a.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef SCRYPT_H
#define SCRYPT_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void a5a_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

116
stratum/algos/a5amath.c Normal file
View file

@ -0,0 +1,116 @@
// Copyright (c) 2014 The a5a developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <stdio.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//#include <gmpxx.h>
#include "a5amath.h"
//#define EPS1 (std::numeric_limits<double>::epsilon())
#define EPS1 (DBL_EPSILON)
#define EPS2 3.0e-11
double exp_n(double xt)
{
double p1 = -700.0, p3 = -0.8e-8, p4 = 0.8e-8, p6 = 700.0;
if(xt < p1)
return 0;
else if(xt > p6)
return 1e200;
else if(xt > p3 && xt < p4)
return (1.0 + xt);
else
return exp(xt);
}
// 1 / (1 + exp(x1-x2))
double exp_n2(double x1, double x2)
{
double p1 = -700., p2 = -37., p3 = -0.8e-8, p4 = 0.8e-8, p5 = 37., p6 = 700.;
double xt = x1 - x2;
if (xt < p1+1.e-200)
return 1.;
else if (xt > p1 && xt < p2 + 1.e-200)
return ( 1. - exp(xt) );
else if (xt > p2 && xt < p3 + 1.e-200)
return ( 1. / (1. + exp(xt)) );
else if (xt > p3 && xt < p4)
return ( 1. / (2. + xt) );
else if (xt > p4 - 1.e-200 && xt < p5)
return ( exp(-xt) / (1. + exp(-xt)) );
else if (xt > p5 - 1.e-200 && xt < p6)
return ( exp(-xt) );
else if (xt > p6 - 1.e-200)
return 0.;
}
void gauleg(double x1, double x2, double x[], double w[], int n)
{
int m,j,i;
double z1, z, xm, xl, pp, p3, p2, p1;
m=(n+1)/2;
xm=0.5*(x2+x1);
xl=0.5*(x2-x1);
for (i=1;i<=m;i++) {
z=cos(3.141592654*(i-0.25)/(n+0.5));
do {
p1=1.0;
p2=0.0;
for (j=1;j<=n;j++) {
p3=p2;
p2=p1;
p1=((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j;
}
pp=n*(z*p1-p2)/(z*z-1.0);
z1=z;
z=z1-p1/pp;
} while (fabs(z-z1) > EPS2);
x[i]=xm-xl*z;
x[n+1-i]=xm+xl*z;
w[i]=2.0*xl/((1.0-z*z)*pp*pp);
w[n+1-i]=w[i];
}
}
double GaussianQuad_N(double func(const double), const double a2, const double b2, int NptGQ)
{
double s=0.0;
double x[NptGQ], w[NptGQ];
int j;
// double dh=(b2-a2)/double(divs);
gauleg(a2, b2, x, w, NptGQ);
for (j=1; j<=NptGQ; j++) {
s += w[j]*func(x[j]);
}
/*
for (i=1; i<=divs; i++)
{
a0 = a2 + (i-1)*dh;
b0 = a0 + dh;
gauleg(a0, b0, x, w, NptGQ);
for (j=1; j<=NptGQ; j++)
{
s += w[j]*func(x[j]);
}
}
*/
return s;
}
double swit_(double wvnmb)
{
return pow( (5.55243*(exp_n(-0.3*wvnmb/15.762) - exp_n(-0.6*wvnmb/15.762)))*wvnmb, 0.5)
/ 1034.66 * pow(sin(wvnmb/65.), 2.);
}
uint32_t sw_(int nnounce, int divs)
{
double wmax = ((sqrt((double)(nnounce))*(1.+EPS1))/450+100);
return ((uint32_t)(GaussianQuad_N(swit_, 0., wmax, divs)*(1.+EPS1)*1.e6));
}

16
stratum/algos/a5amath.h Normal file
View file

@ -0,0 +1,16 @@
// Copyright (c) 2014 The a5a developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef a5a_MATH_H
#define a5a_MATH_H
double exp_n(double xt);
double exp_n2(double x1, double x2);
void gauleg(double x1, double x2, double x[], double w[], int n);
double GaussianQuad_N(double func(const double), const double a2, const double b2, int NptGQ);
double swit_(double wvnmb);
uint32_t sw_(int nnounce, int divs);
#endif

162
stratum/algos/aergo.c Normal file
View file

@ -0,0 +1,162 @@
#include "aergo.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_shabal.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_haval.h>
#include "gost.h"
#include "common.h"
void aergo_hash(const char* input, char* output, uint32_t len)
{
uint32_t hash[16];
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_skein512_context ctx_skein;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_gost512_context ctx_gost;
sph_whirlpool_context ctx_whirlpool;
sph_haval256_5_context ctx_haval;
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, input, len);
sph_echo512_close(&ctx_echo, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, hash, 64);
sph_blake512_close(&ctx_blake, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_gost512_init(&ctx_gost);
sph_gost512(&ctx_gost, hash, 64);
sph_gost512_close(&ctx_gost, hash);
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_gost512_init(&ctx_gost);
sph_gost512(&ctx_gost, hash, 64);
sph_gost512_close(&ctx_gost, hash);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_haval256_5_init(&ctx_haval);
sph_haval256_5(&ctx_haval,(const void*) hash, 64);
sph_haval256_5_close(&ctx_haval, hash);
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, hash, 64);
sph_shavite512_close(&ctx_shavite, hash);
sph_gost512_init(&ctx_gost);
sph_gost512(&ctx_gost, hash, 64);
sph_gost512_close(&ctx_gost, hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, hash, 64);
sph_blake512_close(&ctx_blake, hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hash, 64);
sph_cubehash512_close(&ctx_cubehash, hash);
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hash, 64);
sph_simd512_close(&ctx_simd, hash);
memcpy(output, hash, 32);
}

17
stratum/algos/aergo.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef AERGO_H
#define AERGO_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void aergo_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

46
stratum/algos/allium.c Normal file
View file

@ -0,0 +1,46 @@
#include <memory.h>
#include "sha3/sph_blake.h"
#include "sha3/sph_groestl.h"
#include "sha3/sph_skein.h"
#include "sha3/sph_keccak.h"
#include "sha3/sph_cubehash.h"
#include "Lyra2.h"
void allium_hash(const char* input, char* output, uint32_t len)
{
uint32_t hashA[8], hashB[8];
sph_blake256_context ctx_blake;
sph_keccak256_context ctx_keccak;
sph_cubehash512_context ctx_cubehash;
sph_skein256_context ctx_skein;
sph_groestl256_context ctx_groestl;
sph_blake256_init(&ctx_blake);
sph_blake256(&ctx_blake, input, 80);
sph_blake256_close(&ctx_blake, hashA);
sph_keccak256_init(&ctx_keccak);
sph_keccak256(&ctx_keccak, hashA, 32);
sph_keccak256_close(&ctx_keccak, hashB);
LYRA2(hashA, 32, hashB, 32, hashB, 32, 1, 8, 8);
sph_cubehash256_init(&ctx_cubehash);
sph_cubehash256(&ctx_cubehash, hashA, 32);
sph_cubehash256_close(&ctx_cubehash, hashB);
LYRA2(hashA, 32, hashB, 32, hashB, 32, 1, 8, 8);
sph_skein256_init(&ctx_skein);
sph_skein256(&ctx_skein, hashA, 32);
sph_skein256_close(&ctx_skein, hashB);
sph_groestl256_init(&ctx_groestl);
sph_groestl256(&ctx_groestl, hashB, 32);
sph_groestl256_close(&ctx_groestl, hashA);
memcpy(output, hashA, 32);
}

16
stratum/algos/allium.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef ALLIUM_H
#define ALLIUM_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void allium_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,279 +1,378 @@
/*
* Argon2 source code package
* Argon2 reference source code package - reference C implementations
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
* 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:
*
* 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/>.
* - 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 <stdio.h>
#include <limits.h>
#include "argon2.h"
#include "cores.h"
#include "encoding.h"
#include "core.h"
/* Error messages */
static const char *Argon2_ErrorMessage[] = {
/*{ARGON2_OK, */ "OK",
/*},
const char *argon2_type2string(argon2_type type, int uppercase) {
switch (type) {
case Argon2_d:
return uppercase ? "Argon2d" : "argon2d";
}
{ARGON2_OUTPUT_PTR_NULL, */ "Output pointer is NULL",
/*},
return NULL;
}
{ARGON2_OUTPUT_TOO_SHORT, */ "Output is too short",
/*},
{ARGON2_OUTPUT_TOO_LONG, */ "Output is too long",
/*},
{ARGON2_PWD_TOO_SHORT, */ "Password is too short",
/*},
{ARGON2_PWD_TOO_LONG, */ "Password is too long",
/*},
{ARGON2_SALT_TOO_SHORT, */ "Salt is too short",
/*},
{ARGON2_SALT_TOO_LONG, */ "Salt is too long",
/*},
{ARGON2_AD_TOO_SHORT, */ "Associated data is too short",
/*},
{ARGON2_AD_TOO_LONG, */ "Associated date is too long",
/*},
{ARGON2_SECRET_TOO_SHORT, */ "Secret is too short",
/*},
{ARGON2_SECRET_TOO_LONG, */ "Secret is too long",
/*},
{ARGON2_TIME_TOO_SMALL, */ "Time cost is too small",
/*},
{ARGON2_TIME_TOO_LARGE, */ "Time cost is too large",
/*},
{ARGON2_MEMORY_TOO_LITTLE, */ "Memory cost is too small",
/*},
{ARGON2_MEMORY_TOO_MUCH, */ "Memory cost is too large",
/*},
{ARGON2_LANES_TOO_FEW, */ "Too few lanes",
/*},
{ARGON2_LANES_TOO_MANY, */ "Too many lanes",
/*},
{ARGON2_PWD_PTR_MISMATCH, */ "Password pointer is NULL, but password length is not 0",
/*},
{ARGON2_SALT_PTR_MISMATCH, */ "Salt pointer is NULL, but salt length is not 0",
/*},
{ARGON2_SECRET_PTR_MISMATCH, */ "Secret pointer is NULL, but secret length is not 0",
/*},
{ARGON2_AD_PTR_MISMATCH, */ "Associated data pointer is NULL, but ad length is not 0",
/*},
{ARGON2_MEMORY_ALLOCATION_ERROR, */ "Memory allocation error",
/*},
{ARGON2_FREE_MEMORY_CBK_NULL, */ "The free memory callback is NULL",
/*},
{ARGON2_ALLOCATE_MEMORY_CBK_NULL, */ "The allocate memory callback is NULL",
/*},
{ARGON2_INCORRECT_PARAMETER, */ "Argon2_Context context is NULL",
/*},
{ARGON2_INCORRECT_TYPE, */ "There is no such version of Argon2",
/*},
{ARGON2_OUT_PTR_MISMATCH, */ "Output pointer mismatch",
/*},
{ARGON2_THREADS_TOO_FEW, */ "Not enough threads",
/*},
{ARGON2_THREADS_TOO_MANY, */ "Too many threads",
/*},
{ARGON2_MISSING_ARGS, */ "Missing arguments", /*},*/
};
int argon2d(argon2_context *context) { return argon2_core(context, Argon2_d); }
int argon2i(argon2_context *context) { return argon2_core(context, Argon2_i); }
int verify_d(argon2_context *context, const char *hash) {
int result;
/*if (0 == context->outlen || NULL == hash) {
return ARGON2_OUT_PTR_MISMATCH;
}*/
result = argon2_core(context, Argon2_d);
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;
}
return 0 == memcmp(hash, context->out, 32);
if (Argon2_d != type) {
return ARGON2_INCORRECT_TYPE;
}
const char *error_message(int error_code) {
enum {
/* Make sure---at compile time---that the enum size matches the array
size */
ERROR_STRING_CHECK =
1 /
!!((sizeof(Argon2_ErrorMessage) / sizeof(Argon2_ErrorMessage[0])) ==
ARGON2_ERROR_CODES_LENGTH)
};
if (error_code < ARGON2_ERROR_CODES_LENGTH) {
return Argon2_ErrorMessage[(argon2_error_codes)error_code];
}
return "Unknown error code.";
/* 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;
}
/* encoding/decoding helpers */
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);
/*
* Some macros for constant-time comparisons. These work over values in
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
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.threads = context->threads;
instance.type = type;
if (instance.threads > instance.lanes) {
instance.threads = instance.lanes;
}
/* 3. Initialization: Hashing inputs, allocating memory, filling first
* blocks
*/
#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)
result = initialize(&instance, context);
/*
* 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) & '/');
if (ARGON2_OK != result) {
return result;
}
/*
* 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 olen;
const unsigned char *buf;
unsigned acc, acc_len;
/* 4. Filling memory */
result = fill_memory_blocks(&instance);
olen = 43;
/*switch (32 % 3) {
case 2:
olen++;*/
/* fall through */
/*case 1:
olen += 2;
break;
}*/
if (dst_len <= olen) {
return (size_t)-1;
if (ARGON2_OK != result) {
return result;
}
acc = 0;
acc_len = 0;
buf = (const unsigned char *)src;
size_t src_len = 32;
while (src_len-- > 0) {
acc = (acc << 8) + (*buf++);
acc_len += 8;
while (acc_len >= 6) {
acc_len -= 6;
*dst++ = b64_byte_to_char((acc >> acc_len) & 0x3F);
}
}
if (acc_len > 0) {
*dst++ = b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
}
*dst++ = 0;
return olen;
/* 5. Finalization */
finalize(context, &instance);
return ARGON2_OK;
}
/* ==================================================================== */
/*
* Code specific to Argon2i.
*
* The code below applies the following format:
*
* $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
*
* where <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 "keyid" is a binary identifier for a key (up to 8
* bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
* (resp. the 'data') is empty, then it is ommitted from the output.
*
* The last two binary chunks (encoded in Base64) are, in that order,
* the salt and the output. Both are optional, but you cannot have an
* output without a salt. The binary salt length is between 8 and 48 bytes.
* The output length is always exactly 32 bytes.
*/
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){
int encode_string(char *dst, size_t dst_len, argon2_context *ctx) {
#define SS(str) \
do { \
size_t pp_len = strlen(str); \
if (pp_len >= dst_len) { \
return 0; \
} \
memcpy(dst, str, pp_len + 1); \
dst += pp_len; \
dst_len -= pp_len; \
} while (0)
argon2_context context;
int result;
uint8_t *out;
#define SX(x) \
do { \
char tmp[30]; \
sprintf(tmp, "%lu", (unsigned long)(x)); \
SS(tmp); \
} while (0);
#define SB(buf) \
do { \
size_t sb_len = to_base64(dst, dst_len, buf); \
if (sb_len == (size_t)-1) { \
return 0; \
} \
dst += sb_len; \
dst_len -= sb_len; \
} while (0);
SS("$argon2i$m=");
SX(16);
SS(",t=");
SX(2);
SS(",p=");
SX(1);
/*if (ctx->adlen > 0) {
SS(",data=");
SB(ctx->ad, ctx->adlen);
}*/
/*if (ctx->saltlen == 0)
return 1;*/
SS("$");
SB(ctx->salt);
/*if (ctx->outlen32 == 0)
return 1;*/
SS("$");
SB(ctx->out);
return 1;
#undef SS
#undef SX
#undef SB
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);
}

View file

@ -1,18 +1,27 @@
/*
* Argon2 source code package
* Argon2 reference source code package - reference C implementations
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
* 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:
*
* 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/>.
* - 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
#if defined(HAVE_CONFIG_H)
#include "config/dynamic-config.h"
#endif
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
@ -21,8 +30,18 @@
extern "C" {
#endif
/*************************Argon2 input parameter
* restrictions**************************************************/
/* 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)
@ -43,8 +62,7 @@ extern "C" {
#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 half the addressing space, topping at 2^32 blocks (4 TB)
*/
/* 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 \
@ -70,65 +88,74 @@ extern "C" {
#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)
#define ARGON2_FLAG_CLEAR_MEMORY (UINT32_C(1) << 2)
#define ARGON2_DEFAULT_FLAGS \
(ARGON2_FLAG_CLEAR_PASSWORD | ARGON2_FLAG_CLEAR_MEMORY)
/* 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_PTR_NULL = -1,
ARGON2_OUTPUT_TOO_SHORT = 2,
ARGON2_OUTPUT_TOO_LONG = 3,
ARGON2_OUTPUT_TOO_SHORT = -2,
ARGON2_OUTPUT_TOO_LONG = -3,
ARGON2_PWD_TOO_SHORT = 4,
ARGON2_PWD_TOO_LONG = 5,
ARGON2_PWD_TOO_SHORT = -4,
ARGON2_PWD_TOO_LONG = -5,
ARGON2_SALT_TOO_SHORT = 6,
ARGON2_SALT_TOO_LONG = 7,
ARGON2_SALT_TOO_SHORT = -6,
ARGON2_SALT_TOO_LONG = -7,
ARGON2_AD_TOO_SHORT = 8,
ARGON2_AD_TOO_LONG = 9,
ARGON2_AD_TOO_SHORT = -8,
ARGON2_AD_TOO_LONG = -9,
ARGON2_SECRET_TOO_SHORT = 10,
ARGON2_SECRET_TOO_LONG = 11,
ARGON2_SECRET_TOO_SHORT = -10,
ARGON2_SECRET_TOO_LONG = -11,
ARGON2_TIME_TOO_SMALL = 12,
ARGON2_TIME_TOO_LARGE = 13,
ARGON2_TIME_TOO_SMALL = -12,
ARGON2_TIME_TOO_LARGE = -13,
ARGON2_MEMORY_TOO_LITTLE = 14,
ARGON2_MEMORY_TOO_MUCH = 15,
ARGON2_MEMORY_TOO_LITTLE = -14,
ARGON2_MEMORY_TOO_MUCH = -15,
ARGON2_LANES_TOO_FEW = 16,
ARGON2_LANES_TOO_MANY = 17,
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_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_MEMORY_ALLOCATION_ERROR = -22,
ARGON2_FREE_MEMORY_CBK_NULL = 23,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = 24,
ARGON2_FREE_MEMORY_CBK_NULL = -23,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
ARGON2_INCORRECT_PARAMETER = 25,
ARGON2_INCORRECT_TYPE = 26,
ARGON2_INCORRECT_PARAMETER = -25,
ARGON2_INCORRECT_TYPE = -26,
ARGON2_OUT_PTR_MISMATCH = 27,
ARGON2_OUT_PTR_MISMATCH = -27,
ARGON2_THREADS_TOO_FEW = 28,
ARGON2_THREADS_TOO_MANY = 29,
ARGON2_THREADS_TOO_FEW = -28,
ARGON2_THREADS_TOO_MANY = -29,
ARGON2_MISSING_ARGS = 30,
ARGON2_MISSING_ARGS = -30,
ARGON2_ERROR_CODES_LENGTH /* Do NOT remove; Do NOT add error codes after
this
error code */
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 */
@ -138,7 +165,8 @@ typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
/* Argon2 external data structures */
/*
*****Context: structure to hold Argon2 inputs:
*****
* Context: structure to hold Argon2 inputs:
* output array and its length,
* password and its length,
* salt and its length,
@ -148,142 +176,159 @@ typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
* 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).
* 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.
* 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 */
/*uint8_t *secret;*/ /* key array */
/*uint8_t *ad;*/ /* associated data 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 outlen;*/ /* digest length */
uint32_t pwdlen; /* password length */
/*uint32_t saltlen;*/ /* salt length */
/*uint32_t secretlen;*/ /* key length */
/*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 */
/*uint32_t flags;*/ /* array of bool options */
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);
/**
* Function to hash the inputs in the memory-hard fashion (uses Argon2i)
* @param out Pointer to the memory where the hash digest will be written
* @param outlen Digest length in bytes
* @param in Pointer to the input (password)
* @param inlen Input length in bytes
* @param salt Pointer to the salt
* @param saltlen Salt length in bytes
* @pre @a out must have at least @a outlen bytes allocated
* @pre @a in must be at least @inlen bytes long
* @pre @a saltlen must be at least @saltlen bytes long
* @return Zero if successful, 1 otherwise.
* 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
*/
/*int hash_argon2i(void *out, size_t outlen, const void *in, size_t inlen,
const void *salt, size_t saltlen, unsigned int t_cost,
unsigned int m_cost);*/
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);
/* same for argon2d */
/*int hash_argon2d(void *out, size_t outlen, const void *in, size_t inlen,
const void *salt, size_t saltlen, unsigned int t_cost,
unsigned int m_cost);*/
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);
/*
* **************Argon2d: Version of Argon2 that picks memory blocks depending
/* 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!!***************
* environment!!
*****
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2d(argon2_context *context);
ARGON2_PUBLIC int argon2d_ctx(argon2_context *context);
/*
* * **************Argon2i: Version of Argon2 that picks memory blocks
*independent on the password and salt. Good for side-channels,
******************* but worse w.r.t. tradeoff attacks if
*******************only one pass is used***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2i(argon2_context *context);
/*
* * **************Argon2di: Reserved name***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2di(argon2_context *context);
/*
* * **************Argon2ds: Argon2d hardened against GPU attacks, 20%
* slower***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2ds(argon2_context *context);
/*
* * **************Argon2id: First half-pass over memory is
*password-independent, the rest are password-dependent
********************OK against side channels: they reduce to 1/2-pass
*Argon2i***************
* @param context Pointer to current Argon2 context
* @return Zero if successful, a non zero error code otherwise
*/
int argon2id(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
*/
int verify_d(argon2_context *context, const char *hash);
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
*/
const char *error_message(int error_code);
ARGON2_PUBLIC const char *argon2_error_message(int error_code);
/* ==================================================================== */
/*
* Code specific to Argon2i.
*
* The code below applies the following format:
*
* $argon2i$m=<num>,t=<num>,p=<num>[,keyid=<bin>][,data=<bin>][$<bin>[$<bin>]]
*
* where <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 "keyid" is a binary identifier for a key (up to 8
* bytes); "data" is associated data (up to 32 bytes). When the 'keyid'
* (resp. the 'data') is empty, then it is ommitted from the output.
*
* The last two binary chunks (encoded in Base64) are, in that order,
* the salt and the output. Both are optional, but you cannot have an
* output without a salt. The binary salt length is between 8 and 48 bytes.
* The output length is always exactly 32 bytes.
/**
* 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
*/
int encode_string(char *dst, size_t dst_len, argon2_context *ctx);
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);
#if defined(__cplusplus)
}

View file

@ -1,111 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include "argon2.h"
static uint64_t rdtsc(void) {
#ifdef _MSC_VER
return __rdtsc();
#else
#if defined(__amd64__) || defined(__x86_64__)
uint64_t rax, rdx;
__asm__ __volatile__("rdtsc" : "=a"(rax), "=d"(rdx) : :);
return (rdx << 32) | rax;
#elif defined(__i386__) || defined(__i386) || defined(__X86__)
uint64_t rax;
__asm__ __volatile__("rdtsc" : "=A"(rax) : :);
return rax;
#else
#error "Not implemented!"
#endif
#endif
}
/*
* Benchmarks Argon2 with salt length 16, password length 16, t_cost 1,
and different m_cost and threads
*/
static void benchmark() {
#define BENCH_OUTLEN 16
#define BENCH_INLEN 16
const uint32_t inlen = BENCH_INLEN;
const unsigned outlen = BENCH_OUTLEN;
unsigned char out[BENCH_OUTLEN];
unsigned char pwd_array[BENCH_INLEN];
unsigned char salt_array[BENCH_INLEN];
#undef BENCH_INLEN
#undef BENCH_OUTLEN
uint32_t t_cost = 1;
uint32_t m_cost;
uint32_t thread_test[6] = {1, 2, 4, 6, 8, 16};
memset(pwd_array, 0, inlen);
memset(salt_array, 1, inlen);
for (m_cost = (uint32_t)1 << 10; m_cost <= (uint32_t)1 << 22; m_cost *= 2) {
unsigned i;
for (i = 0; i < 6; ++i) {
argon2_context context;
uint32_t thread_n = thread_test[i];
uint64_t stop_cycles, stop_cycles_i;
clock_t stop_time;
uint64_t delta_d, delta_i;
double mcycles_d, mcycles_i, run_time;
clock_t start_time = clock();
uint64_t start_cycles = rdtsc();
context.out = out;
context.outlen = outlen;
context.pwd = pwd_array;
context.pwdlen = inlen;
context.salt = salt_array;
context.saltlen = inlen;
context.secret = NULL;
context.secretlen = 0;
context.ad = NULL;
context.adlen = 0;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = thread_n;
context.threads = thread_n;
context.allocate_cbk = NULL;
context.free_cbk = NULL;
context.flags = 0;
argon2d(&context);
stop_cycles = rdtsc();
argon2i(&context);
stop_cycles_i = rdtsc();
stop_time = clock();
delta_d = (stop_cycles - start_cycles) / (m_cost);
delta_i = (stop_cycles_i - stop_cycles) / (m_cost);
mcycles_d = (double)(stop_cycles - start_cycles) / (1UL << 20);
mcycles_i = (double)(stop_cycles_i - stop_cycles) / (1UL << 20);
printf("Argon2d %d iterations %d MiB %d threads: %2.2f cpb %2.2f "
"Mcycles \n",
t_cost, m_cost >> 10, thread_n, (float)delta_d / 1024,
mcycles_d);
printf("Argon2i %d iterations %d MiB %d threads: %2.2f cpb %2.2f "
"Mcycles \n",
t_cost, m_cost >> 10, thread_n, (float)delta_i / 1024,
mcycles_i);
run_time = ((double)stop_time - start_time) / (CLOCKS_PER_SEC);
printf("%2.4f seconds\n\n", run_time);
}
}
}
int main() {
benchmark();
return ARGON2_OK;
}

View file

@ -1,162 +0,0 @@
#ifndef BLAKE_ROUND_MKA_OPT_H
#define BLAKE_ROUND_MKA_OPT_H
#include "blake2-impl.h"
#if defined(_MSC_VER)
#include <intrin.h>
#endif
#include <immintrin.h>
#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 = C0; \
C0 = C1; \
C1 = t0; \
t0 = B0; \
__m128i 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

View file

@ -1,305 +0,0 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
#include "blake2/blake2.h"
#include "blake2/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) {
burn(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));
}
/*void print_state(blake2b_state BlakeHash) {
printf(".h = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n"
"UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n"
"UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 "),\n"
"UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")},\n"
".t = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")},\n"
".f = {UINT64_C(%" PRIu64 "), UINT64_C(%" PRIu64 ")}\n",
BlakeHash.h[0], BlakeHash.h[1], BlakeHash.h[2], BlakeHash.h[3],
BlakeHash.h[4], BlakeHash.h[5], BlakeHash.h[6], BlakeHash.h[7],
BlakeHash.t[0], BlakeHash.t[1],
BlakeHash.f[0], BlakeHash.f[1]);
printf(".buf = {");
for (register uint8_t i = 0; i < BLAKE2B_BLOCKBYTES; i++)
printf("%" PRIu8 ", ", BlakeHash.buf[i]);
puts("\n");
printf("}\n.buflen = %d\n.outlen = %d\n",
BlakeHash.buflen, BlakeHash.outlen);
printf(".last_node = %" PRIu8 "\n", BlakeHash.last_node);
fflush(stdout);
}*/
static const blake2b_state miou = {
.h = {
UINT64_C(7640891576939301128), UINT64_C(13503953896175478587),
UINT64_C(4354685564936845355), UINT64_C(11912009170470909681),
UINT64_C(5840696475078001361), UINT64_C(11170449401992604703),
UINT64_C(2270897969802886507), UINT64_C(6620516959819538809)
},
.t = {UINT64_C(0), UINT64_C(0)},
.f = {UINT64_C(0), UINT64_C(0)},
.buf = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
.buflen = 0,
.outlen = 64,
.last_node = 0
};
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;
}
void compare_buffs(uint64_t *h, size_t outlen)
{
// printf("CMP : %d", memcmp(h, miou.h, 8*(sizeof(uint64_t))));
printf("miou : %" PRIu64 " - h : %" PRIu64 " - outlen : %ld\n", miou.h[0], h[0], outlen);
fflush(stdout);
}
/* Sequential blake2b initialization */
int blake2b_init(blake2b_state *S, size_t outlen) {
memcpy(S, &miou, sizeof(*S));
S->h[0] += outlen;
return 0;
}
void print64(const char *name, const uint64_t *array, uint16_t size) {
printf("%s = {", name);
for (uint8_t i = 0; i < size; i++) printf("UINT64_C(%" PRIu64 "), ", array[i]);
printf("};\n");
}
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
size_t keylen) {
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 * 8);
}
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;
/* Complete current block */
memcpy(&S->buf[4], pin, 124);
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, S->buf);
S->buflen = 0;
pin += 124;
register int8_t i = 7;
/* Avoid buffer copies when possible */
while (i--) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress(S, pin);
pin += BLAKE2B_BLOCKBYTES;
}
memcpy(&S->buf[S->buflen], pin, 4);
S->buflen += 4;
return 0;
}
void my_blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
memcpy(&S->buf[S->buflen], in, inlen);
S->buflen += (unsigned int)inlen;
}
int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
unsigned int i;
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);
burn(buffer, sizeof(buffer));
burn(S->buf, sizeof(S->buf));
burn(S->h, sizeof(S->h));
return 0;
}
int blake2b(void *out, const void *in, const void *key, size_t keylen)
{
blake2b_state S;
blake2b_init(&S, 64);
my_blake2b_update(&S, in, 64);
blake2b_final(&S, out, 64);
burn(&S, sizeof(S));
return 0;
}
void blake2b_too(void *pout, const void *in)
{
uint8_t *out = (uint8_t *)pout;
uint8_t out_buffer[64];
uint8_t in_buffer[64];
blake2b_state blake_state;
blake2b_init(&blake_state, 64);
blake_state.buflen = blake_state.buf[1] = 4;
my_blake2b_update(&blake_state, in, 72);
blake2b_final(&blake_state, out_buffer, 64);
memcpy(out, out_buffer, 32);
out += 32;
register uint8_t i = 29;
while (i--) {
memcpy(in_buffer, out_buffer, 64);
blake2b(out_buffer, in_buffer, NULL, 0);
memcpy(out, out_buffer, 32);
out += 32;
}
memcpy(in_buffer, out_buffer, 64);
blake2b(out_buffer, in_buffer, NULL, 0);
memcpy(out, out_buffer, 64);
burn(&blake_state, sizeof(blake_state));
}
/* Argon2 Team - Begin Code */
int blake2b_long(void *pout, const void *in)
{
uint8_t *out = (uint8_t *)pout;
blake2b_state blake_state;
uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
store32(outlen_bytes, 32);
blake2b_init(&blake_state, 32);
my_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes));
blake2b_update(&blake_state, in, 1024);
blake2b_final(&blake_state, out, 32);
burn(&blake_state, sizeof(blake_state));
return 0;
}
/* Argon2 Team - End Code */

615
stratum/algos/ar2/core.c Normal file
View file

@ -0,0 +1,615 @@
/*
* 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 <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;
}

View file

@ -1,38 +1,38 @@
/*
* Argon2 source code package
* Argon2 reference source code package - reference C implementations
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
* 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:
*
* 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/>.
* - 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_CORES_H
#define ARGON2_CORES_H
#ifndef ARGON2_CORE_H
#define ARGON2_CORE_H
#if defined(_MSC_VER)
#define ALIGN(n) __declspec(align(16))
#elif defined(__GNUC__) || defined(__clang)
#define ALIGN(x) __attribute__((__aligned__(x)))
#else
#define ALIGN(x)
#endif
#include "argon2.h"
/*************************Argon2 internal
* constants**************************************************/
#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_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
ARGON2_QWORDS_IN_BLOCK = 64,
ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
/* Number of pseudo-random values generated by one call to Blake in Argon2i
to
@ -44,18 +44,14 @@ enum argon2_core_constants {
ARGON2_PREHASH_SEED_LENGTH = 72
};
/* Argon2 primitive type */
typedef enum Argon2_type { Argon2_d = 0, Argon2_i = 1 } argon2_type;
/*************************Argon2 internal data
* types**************************************************/
/*************************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_WORDS_IN_BLOCK]; } __attribute__ ((aligned (16))) block;
typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
/*****************Functions that work with the block******************/
@ -76,8 +72,16 @@ void xor_block(block *dst, const block *src);
*/
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 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;
/*
@ -97,32 +101,43 @@ typedef struct Argon2_thread_data {
argon2_position_t pos;
} argon2_thread_data;
/*************************Argon2 core
* functions**************************************************/
/*************************Argon2 core functions********************************/
/* Allocates memory to the given pointer
/* 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 m_cost number of blocks to allocate in 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(block **memory, uint32_t m_cost);
int allocate_memory(const argon2_context *context, uint8_t **memory,
size_t num, size_t size);
/* Function that securely cleans the memory
/*
* 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);
/* Clears memory
* @param instance pointer to the current instance
* @param clear_memory indicates if we clear the memory with zeros.
/* 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_memory(argon2_instance_t *instance, int clear);
/* Deallocates memory
* @param memory pointer to the blocks
*/
void free_memory(block *memory);
void clear_internal_memory(void *v, size_t n);
/*
* Computes absolute position of reference block in the lane following a skewed
@ -166,7 +181,7 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
* @param blockhash Pointer to the pre-hashing digest
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
*/
void fill_firsts_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
/*
* Function allocates memory, hashes the inputs with Blake, and creates first
@ -196,6 +211,7 @@ 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
@ -207,14 +223,8 @@ void fill_segment(const argon2_instance_t *instance,
* 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
*/
void fill_memory_blocks(argon2_instance_t *instance);
/*
* 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
*/
int argon2_core(argon2_context *context, argon2_type type);
int fill_memory_blocks(argon2_instance_t *instance);
#endif

View file

@ -1,341 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* 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/>.
*/
/*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 "argon2.h"
#include "cores.h"
#include "blake2/blake2.h"
#include "blake2/blake2-impl.h"
#ifdef GENKAT
#include "genkat.h"
#endif
#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_WORDS_IN_BLOCK);
}
void xor_block(block *dst, const block *src) {
int i;
for (i = 0; i < ARGON2_WORDS_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_WORDS_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_WORDS_IN_BLOCK; ++i) {
store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
}
}
/***************Memory allocators*****************/
int allocate_memory(block **memory, uint32_t m_cost) {
if (memory != NULL) {
size_t memory_size = sizeof(block) * m_cost;
if (m_cost != 0 &&
memory_size / m_cost !=
sizeof(block)) { /*1. Check for multiplication overflow*/
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
*memory = (block *)malloc(memory_size); /*2. Try to allocate*/
if (!*memory) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
return ARGON2_OK;
} else {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
}
void secure_wipe_memory(void *v, size_t n) { memset(v, 0, n); }
/*********Memory functions*/
void clear_memory(argon2_instance_t *instance, int clear) {
if (instance->memory != NULL && clear) {
secure_wipe_memory(instance->memory,
sizeof(block) * /*instance->memory_blocks*/16);
}
}
void free_memory(block *memory) { free(memory); }
void finalize(const argon2_context *context, argon2_instance_t *instance) {
if (context != NULL && instance != NULL) {
block blockhash;
copy_block(&blockhash, instance->memory + 15);
/* Hash the result */
{
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
store_block(blockhash_bytes, &blockhash);
blake2b_long(context->out, blockhash_bytes);
secure_wipe_memory(blockhash.v, ARGON2_BLOCK_SIZE);
secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE); /* clear blockhash_bytes */
}
#ifdef GENKAT
print_tag(context->out, context->outlen);
#endif
/* Clear memory */
clear_memory(instance, 1);
free_memory(instance->memory);
}
}
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 * 4 +
position->index - 1;
} else {
reference_area_size =
position->slice * 4 +
((position->index == 0) ? (-1) : 0);
}
}
} else {
/* Second pass */
if (same_lane) {reference_area_size = 11 + position->index;}
else {reference_area_size = 12 - (position->index == 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) * 4;
}
/* 1.2.6. Computing absolute position */
absolute_position = (start_position + relative_position) % 16;
return absolute_position;
}
void fill_memory_blocks(argon2_instance_t *instance) {
uint32_t r, s;
for (r = 0; r < 2; ++r) {
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
argon2_position_t position;
position.pass = r;
position.lane = 0;
position.slice = (uint8_t)s;
position.index = 0;
fill_segment(instance, position);
}
#ifdef GENKAT
internal_kat(instance, r); /* Print all memory blocks */
#endif
}
}
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
G(H0||i||1) */
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, 0);
blake2b_too(blockhash_bytes, blockhash);
load_block(&instance->memory[0], blockhash_bytes);
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
blake2b_too(blockhash_bytes, blockhash);
load_block(&instance->memory[1], blockhash_bytes);
secure_wipe_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
}
static const blake2b_state base_hash = {
.h = {
UINT64_C(7640891576939301192), UINT64_C(13503953896175478587),
UINT64_C(4354685564936845355), UINT64_C(11912009170470909681),
UINT64_C(5840696475078001361), UINT64_C(11170449401992604703),
UINT64_C(2270897969802886507), UINT64_C(6620516959819538809)
},
.t = {UINT64_C(0),UINT64_C(0)},
.f = {UINT64_C(0),UINT64_C(0)},
.buf = {
1, 0, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 1, 0,
0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.buflen = 28,
.outlen = 64,
.last_node = 0
};
#define PWDLEN 32
#define SALTLEN 32
#define SECRETLEN 0
#define ADLEN 0
void initial_hash(uint8_t *blockhash, argon2_context *context,
argon2_type type) {
uint8_t value[sizeof(uint32_t)];
/* Is it generating cache invalidation between cores ? */
blake2b_state BlakeHash = base_hash;
BlakeHash.buf[20] = (uint8_t) type;
my_blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
PWDLEN);
secure_wipe_memory(context->pwd, PWDLEN);
context->pwdlen = 0;
store32(&value, SALTLEN);
my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
my_blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
SALTLEN);
store32(&value, SECRETLEN);
my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
store32(&value, ADLEN);
my_blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
}
int initialize(argon2_instance_t *instance, argon2_context *context) {
/* 1. Memory allocation */
allocate_memory(&(instance->memory), 16);
/* 2. Initial hashing */
/* H_0 + 8 extra bytes to produce the first blocks */
/* Hashing all inputs */
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
initial_hash(blockhash, context, instance->type);
/* Zeroing 8 extra bytes */
secure_wipe_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
ARGON2_PREHASH_SEED_LENGTH -
ARGON2_PREHASH_DIGEST_LENGTH);
#ifdef GENKAT
initial_kat(blockhash, context, instance->type);
#endif
/* 3. Creating first blocks, we always have at least two blocks in a slice
*/
fill_first_blocks(blockhash, instance);
/* Clearing the hash */
secure_wipe_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
return ARGON2_OK;
}
int argon2_core(argon2_context *context, argon2_type type) {
argon2_instance_t instance;
instance.memory = NULL;
instance.type = type;
/* 3. Initialization: Hashing inputs, allocating memory, filling first
* blocks
*/
int result = initialize(&instance, context);
if (ARGON2_OK != result) return result;
/* 4. Filling memory */
fill_memory_blocks(&instance);
/* 5. Finalization */
finalize(context, &instance);
return ARGON2_OK;
}

View file

@ -0,0 +1,455 @@
/*
* 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;
}

View file

@ -0,0 +1,57 @@
/*
* 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

View file

@ -1,182 +0,0 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "argon2.h"
#include "cores.h"
void initial_kat(const uint8_t *blockhash, const argon2_context *context,
argon2_type type) {
unsigned i;
if (blockhash != NULL && context != NULL) {
printf("=======================================");
switch (type) {
case Argon2_d:
printf("Argon2d\n");
break;
case Argon2_i:
printf("Argon2i\n");
break;
default:
break;
}
printf("Memory: %u KiB, Iterations: %u, Parallelism: %u lanes, Tag "
"length: %u bytes\n",
context->m_cost, context->t_cost, context->lanes,
context->outlen);
printf("Password[%u]: ", context->pwdlen);
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
printf("CLEARED\n");
} else {
for (i = 0; i < context->pwdlen; ++i) {
printf("%2.2x ", ((unsigned char *)context->pwd)[i]);
}
printf("\n");
}
printf("Salt[%u]: ", context->saltlen);
for (i = 0; i < context->saltlen; ++i) {
printf("%2.2x ", ((unsigned char *)context->salt)[i]);
}
printf("\n");
printf("Secret[%u]: ", context->secretlen);
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
printf("CLEARED\n");
} else {
for (i = 0; i < context->secretlen; ++i) {
printf("%2.2x ", ((unsigned char *)context->secret)[i]);
}
printf("\n");
}
printf("Associated data[%u]: ", context->adlen);
for (i = 0; i < context->adlen; ++i) {
printf("%2.2x ", ((unsigned char *)context->ad)[i]);
}
printf("\n");
printf("Pre-hashing digest: ");
for (i = 0; i < ARGON2_PREHASH_DIGEST_LENGTH; ++i) {
printf("%2.2x ", ((unsigned char *)blockhash)[i]);
}
printf("\n");
}
}
void print_tag(const void *out, uint32_t outlen) {
unsigned i;
if (out != NULL) {
printf("Tag: ");
for (i = 0; i < outlen; ++i) {
printf("%2.2x ", ((uint8_t *)out)[i]);
}
printf("\n");
}
}
void internal_kat(const argon2_instance_t *instance, uint32_t pass) {
if (instance != NULL) {
uint32_t i, j;
printf("\n After pass %u:\n", pass);
for (i = 0; i < instance->memory_blocks; ++i) {
uint32_t how_many_words =
(instance->memory_blocks > ARGON2_WORDS_IN_BLOCK)
? 1
: ARGON2_WORDS_IN_BLOCK;
for (j = 0; j < how_many_words; ++j)
printf("Block %.4u [%3u]: %016" PRIx64 "\n", i, j,
instance->memory[i].v[j]);
}
}
}
static void fatal(const char *error) {
fprintf(stderr, "Error: %s\n", error);
exit(1);
}
static void generate_testvectors(const char *type) {
#define TEST_OUTLEN 32
#define TEST_PWDLEN 32
#define TEST_SALTLEN 16
#define TEST_SECRETLEN 8
#define TEST_ADLEN 12
argon2_context context;
unsigned char out[TEST_OUTLEN];
unsigned char pwd[TEST_PWDLEN];
unsigned char salt[TEST_SALTLEN];
unsigned char secret[TEST_SECRETLEN];
unsigned char ad[TEST_ADLEN];
const allocate_fptr myown_allocator = NULL;
const deallocate_fptr myown_deallocator = NULL;
unsigned t_cost = 3;
unsigned m_cost = 16;
unsigned lanes = 4;
memset(pwd, 1, TEST_OUTLEN);
memset(salt, 2, TEST_SALTLEN);
memset(secret, 3, TEST_SECRETLEN);
memset(ad, 4, TEST_ADLEN);
context.out = out;
context.outlen = TEST_OUTLEN;
context.pwd = pwd;
context.pwdlen = TEST_PWDLEN;
context.salt = salt;
context.saltlen = TEST_SALTLEN;
context.secret = secret;
context.secretlen = TEST_SECRETLEN;
context.ad = ad;
context.adlen = TEST_ADLEN;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = lanes;
context.threads = lanes;
context.allocate_cbk = myown_allocator;
context.free_cbk = myown_deallocator;
context.flags = 0;
#undef TEST_OUTLEN
#undef TEST_PWDLEN
#undef TEST_SALTLEN
#undef TEST_SECRETLEN
#undef TEST_ADLEN
if (!strcmp(type, "d")) {
argon2d(&context);
} else if (!strcmp(type, "i")) {
argon2i(&context);
} else
fatal("wrong Argon2 type");
}
int main(int argc, char *argv[]) {
const char *type = (argc > 1) ? argv[1] : "i";
generate_testvectors(type);
return ARGON2_OK;
}

View file

@ -1,45 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* 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/>.
*/
#ifndef ARGON2_KAT_H
#define ARGON2_KAT_H
/*
* Initial KAT function that prints the inputs to the file
* @param blockhash Array that contains pre-hashing digest
* @param context Holds inputs
* @param type Argon2 type
* @pre blockhash must point to INPUT_INITIAL_HASH_LENGTH bytes
* @pre context member pointers must point to allocated memory of size according
* to the length values
*/
void initial_kat(const uint8_t *blockhash, const argon2_context *context,
argon2_type type);
/*
* Function that prints the output tag
* @param out output array pointer
* @param outlen digest length
* @pre out must point to @a outlen bytes
**/
void print_tag(const void *out, uint32_t outlen);
/*
* Function that prints the internal state at given moment
* @param instance pointer to the current instance
* @param pass current pass number
* @pre instance must have necessary memory allocated
**/
void internal_kat(const argon2_instance_t *instance, uint32_t pass);
#endif

View file

@ -1,150 +1,214 @@
/*
* Argon2 source code package
* Argon2 reference source code package - reference C implementations
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
* Copyright 2015
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
* 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:
*
* 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/>.
* - 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 <stdio.h>
#include <inttypes.h>
#include <immintrin.h>
#include "argon2.h"
#include "cores.h"
#include "opt.h"
#include "core.h"
#include "blake2/blake2.h"
#include "blake2/blamka-round-opt.h"
#include "../blake2/blake2.h"
#include "../blake2/blamka-round-opt.h"
void fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block)
{
__m128i block_XY[ARGON2_QWORDS_IN_BLOCK] __attribute__ ((aligned (16)));
uint32_t i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm_xor_si128(
state[i], _mm_load_si128(&ref_block[i]));
/*
* 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
*/
#if defined(__AVX512F__)
static void fill_block(__m512i *state, const block *ref_block,
block *next_block, int with_xor) {
__m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
unsigned int i;
if (with_xor) {
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
state[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
block_XY[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)next_block->v + i));
}
} else {
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm512_xor_si512(
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
}
}
BLAKE2_ROUND(state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7]);
BLAKE2_ROUND(state[8], state[9], state[10], state[11], state[12], state[13], state[14], state[15]);
BLAKE2_ROUND(state[16], state[17], state[18], state[19], state[20], state[21], state[22], state[23]);
BLAKE2_ROUND(state[24], state[25], state[26], state[27], state[28], state[29], state[30], state[31]);
BLAKE2_ROUND(state[32], state[33], state[34], state[35], state[36], state[37], state[38], state[39]);
BLAKE2_ROUND(state[40], state[41], state[42], state[43], state[44], state[45], state[46], state[47]);
BLAKE2_ROUND(state[48], state[49], state[50], state[51], state[52], state[53], state[54], state[55]);
BLAKE2_ROUND(state[56], state[57], state[58], state[59], state[60], state[61], state[62], state[63]);
/*for (i = 0; i < 8; ++i) {
for (i = 0; i < 2; ++i) {
BLAKE2_ROUND_1(
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 < 2; ++i) {
BLAKE2_ROUND_2(
state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
}
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
state[i] = _mm512_xor_si512(state[i], block_XY[i]);
_mm512_storeu_si512((__m512i *)next_block->v + i, state[i]);
}
}
#elif defined(__AVX2__)
static void fill_block(__m256i *state, const block *ref_block,
block *next_block, int with_xor) {
__m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
unsigned int i;
if (with_xor) {
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
state[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
block_XY[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)next_block->v + i));
}
} else {
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm256_xor_si256(
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
}
}
for (i = 0; i < 4; ++i) {
BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
}
for (i = 0; i < 4; ++i) {
BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
}
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
state[i] = _mm256_xor_si256(state[i], block_XY[i]);
_mm256_storeu_si256((__m256i *)next_block->v + i, state[i]);
}
}
#else
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]);
}*/
}
BLAKE2_ROUND(state[0], state[8], state[16], state[24], state[32], state[40], state[48], state[56]);
BLAKE2_ROUND(state[1], state[9], state[17], state[25], state[33], state[41], state[49], state[57]);
BLAKE2_ROUND(state[2], state[10], state[18], state[26], state[34], state[42], state[50], state[58]);
BLAKE2_ROUND(state[3], state[11], state[19], state[27], state[35], state[43], state[51], state[59]);
BLAKE2_ROUND(state[4], state[12], state[20], state[28], state[36], state[44], state[52], state[60]);
BLAKE2_ROUND(state[5], state[13], state[21], state[29], state[37], state[45], state[53], state[61]);
BLAKE2_ROUND(state[6], state[14], state[22], state[30], state[38], state[46], state[54], state[62]);
BLAKE2_ROUND(state[7], state[15], state[23], state[31], state[39], state[47], state[55], state[63]);
/*for (i = 0; i < 8; ++i) {
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_QWORDS_IN_BLOCK; i++) {
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(state[i], block_XY[i]);
_mm_storeu_si128(&next_block[i], state[i]);
_mm_storeu_si128((__m128i *)next_block->v + i, state[i]);
}
}
#endif
static const uint64_t bad_rands[32] = {
UINT64_C(17023632018251376180), UINT64_C(4911461131397773491),
UINT64_C(15927076453364631751), UINT64_C(7860239898779391109),
static void next_addresses(block *address_block, block *input_block) {
/*Temporary zero-initialized blocks*/
#if defined(__AVX512F__)
__m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK];
__m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK];
#elif defined(__AVX2__)
__m256i zero_block[ARGON2_HWORDS_IN_BLOCK];
__m256i zero2_block[ARGON2_HWORDS_IN_BLOCK];
#else
__m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
__m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
#endif
UINT64_C(11820267568857244377), UINT64_C(12188179869468676617),
UINT64_C(3732913385414474778), UINT64_C(7651458777762572084),
memset(zero_block, 0, sizeof(zero_block));
memset(zero2_block, 0, sizeof(zero2_block));
UINT64_C(3062274162574341415), UINT64_C(17922653540258786897),
UINT64_C(17393848266100524980), UINT64_C(8539695715554563839),
/*Increasing index counter*/
input_block->v[6]++;
UINT64_C(13824538050656654359), UINT64_C(12078939433126460936),
UINT64_C(15331979418564540430), UINT64_C(12058346794217174273),
/*First iteration of G*/
fill_block(zero_block, input_block, address_block, 0);
UINT64_C(13593922096015221049), UINT64_C(18356682276374416500),
UINT64_C(4968040514092703824), UINT64_C(11202790346130235567),
UINT64_C(2276229735041314644), UINT64_C(220837743321691382),
UINT64_C(4861211596230784273), UINT64_C(6330592584132590331),
UINT64_C(3515580430960296763), UINT64_C(9869356316971855173),
UINT64_C(485533243489193056), UINT64_C(14596447761048148032),
UINT64_C(16531790085730132900), UINT64_C(17328824500878824371),
UINT64_C(8548260058287621283), UINT64_C(8641748798041936364)
};
void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands)
{
uint8_t offset = position->pass * 16 + position->slice * 4;
pseudo_rands[0] = bad_rands[offset++];
pseudo_rands[1] = bad_rands[offset++];
pseudo_rands[2] = bad_rands[offset++];
pseudo_rands[3] = bad_rands[offset++];
/*if ((position->pass == 1 && position->slice == 3))
print64("pseudo_rands", pseudo_rands, 4);*/
/*Second iteration of G*/
fill_block(zero2_block, address_block, address_block, 0);
}
#define SEGMENT_LENGTH 4
#define LANE_LENGTH 16
#define POS_LANE 0
void fill_segment(const argon2_instance_t *instance,
argon2_position_t position)
{
argon2_position_t position) {
block *ref_block = NULL, *curr_block = NULL;
uint64_t pseudo_rand, ref_index;
block address_block, input_block;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint8_t i;
__m128i state[64];
int data_independent_addressing = (instance->type == Argon2_i);
uint32_t starting_index, i;
#if defined(__AVX512F__)
__m512i state[ARGON2_512BIT_WORDS_IN_BLOCK];
#elif defined(__AVX2__)
__m256i state[ARGON2_HWORDS_IN_BLOCK];
#else
__m128i state[ARGON2_OWORDS_IN_BLOCK];
#endif
int data_independent_addressing;
/* Pseudo-random values that determine the reference block position */
uint64_t *pseudo_rands = NULL;
pseudo_rands = (uint64_t *)malloc(/*sizeof(uint64_t) * 4*/32);
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
if (instance == NULL) {
return;
}
i = 0;
starting_index = 0;
if ((0 == position.pass) && (0 == position.slice)) {
i = 2; /* we have already generated the first two blocks */
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);
}
}
/*printf("Position.lane = %d\nPosition.slice = %d\nStarting index : %d\n", position.lane, position.slice, starting_index);*/
/* Offset of the current block */
curr_offset = position.slice * 4 + i;
curr_offset = position.lane * instance->lane_length +
position.slice * instance->segment_length + starting_index;
if (0 == curr_offset % 16) {
if (0 == curr_offset % instance->lane_length) {
/* Last block in this lane */
prev_offset = curr_offset + /*instance->lane_length - 1*/15;
prev_offset = curr_offset + instance->lane_length - 1;
} else {
/* Previous block */
prev_offset = curr_offset - 1;
@ -152,34 +216,45 @@ void fill_segment(const argon2_instance_t *instance,
memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
for (; i < SEGMENT_LENGTH;
for (i = starting_index; i < instance->segment_length;
++i, ++curr_offset, ++prev_offset) {
/*1.1 Rotating prev_offset if needed */
if (curr_offset % LANE_LENGTH == 1) {
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) {
pseudo_rand = pseudo_rands[i];
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,1);
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
ref_lane == position.lane);
/* 2 Creating a new block */
ref_block = instance->memory + ref_index;
ref_block =
instance->memory + instance->lane_length * ref_lane + ref_index;
curr_block = instance->memory + curr_offset;
fill_block(state, (__m128i const *)ref_block->v, (__m128i *)curr_block->v);
}
free(pseudo_rands);
fill_block(state, ref_block, curr_block, 0);
}
}

View file

@ -1,49 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* 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/>.
*/
#ifndef ARGON2_OPT_H
#define ARGON2_OPT_H
/*
* Function fills a new memory block. Differs from the
* @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 constructed
* @pre all block pointers must be valid
*/
void fill_block(__m128i *state, __m128i const *ref_block, __m128i *next_block);
/*
* Generate pseudo-random values to reference blocks in the segment and puts
* them into the array
* @param instance Pointer to the current instance
* @param position Pointer to the current position
* @param pseudo_rands Pointer to the array of 64-bit values
* @pre pseudo_rands must point to @a instance->segment_length allocated values
*/
void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands);
/*
* Function that fills the segment using previous segments also from other
* threads.
* Identical to the reference code except that it calls optimized FillBlock()
* @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);
#endif /* ARGON2_OPT_H */

View file

@ -1,174 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* 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 <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "argon2.h"
#include "cores.h"
#include "ref.h"
#include "blake2/blamka-round-ref.h"
#include "blake2/blake2-impl.h"
#include "blake2/blake2.h"
void fill_block(const block *prev_block, const block *ref_block,
block *next_block) {
block blockR, block_tmp;
unsigned i;
copy_block(&blockR, ref_block);
xor_block(&blockR, prev_block);
copy_block(&block_tmp, &blockR);
/* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
(16,17,..31)... finally (112,113,...127) */
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND_NOMSG(
blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
blockR.v[16 * i + 15]);
}
/* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
(2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
for (i = 0; i < 8; i++) {
BLAKE2_ROUND_NOMSG(
blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
blockR.v[2 * i + 113]);
}
copy_block(next_block, &block_tmp);
xor_block(next_block, &blockR);
}
void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands) {
block zero_block, input_block, address_block;
uint32_t i;
init_block_value(&zero_block, 0);
init_block_value(&input_block, 0);
init_block_value(&address_block, 0);
if (instance != NULL && position != NULL) {
input_block.v[0] = position->pass;
input_block.v[1] = position->lane;
input_block.v[2] = position->slice;
input_block.v[3] = 16;
input_block.v[4] = 2;
input_block.v[5] = instance->type;
for (i = 0; i < 4; ++i) {
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
input_block.v[6]++;
fill_block(&zero_block, &input_block, &address_block);
fill_block(&zero_block, &address_block, &address_block);
}
pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
}
}
}
void fill_segment(const argon2_instance_t *instance,
argon2_position_t position) {
block *ref_block = NULL, *curr_block = NULL;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint32_t starting_index;
uint32_t i;
int data_independent_addressing = (instance->type == Argon2_i);
/* Pseudo-random values that determine the reference block position */
uint64_t *pseudo_rands = NULL;
if (instance == NULL) {
return;
}
pseudo_rands =
(uint64_t *)malloc(sizeof(uint64_t) * 4);
if (pseudo_rands == NULL) {
return;
}
if (data_independent_addressing) {
generate_addresses(instance, &position, pseudo_rands);
}
starting_index = 0;
if ((0 == position.pass) && (0 == position.slice)) {
starting_index = 2; /* we have already generated the first two blocks */
}
/* Offset of the current block */
curr_offset = position.lane * 16 +
position.slice * 4 + starting_index;
if (0 == curr_offset % 16) {
/* Last block in this lane */
prev_offset = curr_offset + 16 - 1;
} else {
/* Previous block */
prev_offset = curr_offset - 1;
}
for (i = starting_index; i < 4; ++i, ++curr_offset, ++prev_offset) {
/*1.1 Rotating prev_offset if needed */
if (curr_offset % 16 == 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) {
pseudo_rand = pseudo_rands[i];
} else {
pseudo_rand = instance->memory[prev_offset].v[0];
}
/* 1.2.2 Computing the lane of the reference block */
ref_lane = ((pseudo_rand >> 32)) % 1;
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 + 16 * ref_lane + ref_index;
curr_block = instance->memory + curr_offset;
fill_block(instance->memory + prev_offset, ref_block, curr_block);
}
free(pseudo_rands);
}

View file

@ -1,49 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* 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/>.
*/
#ifndef ARGON2_REF_H
#define ARGON2_REF_H
/*
* Function fills a new memory block
* @param prev_block Pointer to the previous block
* @param ref_block Pointer to the reference block
* @param next_block Pointer to the block to be constructed
* @pre all block pointers must be valid
*/
void fill_block(const block *prev_block, const block *ref_block,
block *next_block);
/*
* Generate pseudo-random values to reference blocks in the segment and puts
* them into the array
* @param instance Pointer to the current instance
* @param position Pointer to the current position
* @param pseudo_rands Pointer to the array of 64-bit values
* @pre pseudo_rands must point to @a instance->segment_length allocated values
*/
void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands);
/*
* Function that fills the segment using previous segments also from other
* threads
* @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);
#endif /* ARGON2_REF_H */

View file

@ -1,223 +0,0 @@
/*
* Argon2 source code package
*
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
*
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* 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 <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "argon2.h"
#include "cores.h"
#define T_COST_DEF 3
#define LOG_M_COST_DEF 12 /* 2^12 = 4 MiB */
#define LANES_DEF 1
#define THREADS_DEF 1
#define OUT_LEN 32
#define SALT_LEN 16
#define UNUSED_PARAMETER(x) (void)(x)
static void usage(const char *cmd) {
printf("Usage: %s pwd salt [-y version] [-t iterations] [-m memory] [-p "
"parallelism]\n",
cmd);
printf("Parameters:\n");
printf("\tpwd\t\tThe password to hash\n");
printf("\tsalt\t\tThe salt to use, at most 16 characters\n");
printf("\t-d\t\tUse Argon2d instead of Argon2i (which is the default)\n");
printf("\t-t N\t\tSets the number of iterations to N (default = %d)\n",
T_COST_DEF);
printf("\t-m N\t\tSets the memory usage of 2^N KiB (default %d)\n",
LOG_M_COST_DEF);
printf("\t-p N\t\tSets parallelism to N threads (default %d)\n",
THREADS_DEF);
}
static void fatal(const char *error) {
fprintf(stderr, "Error: %s\n", error);
exit(1);
}
/*
Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the
Base64-encoded hash string
@out output array with at least 32 bytes allocated
@pwd NULL-terminated string, presumably from argv[]
@salt salt array with at least SALTLEN_DEF bytes allocated
@t_cost number of iterations
@m_cost amount of requested memory in KB
@lanes amount of requested parallelism
@threads actual parallelism
@type String, only "d" and "i" are accepted
*/
static void run(uint8_t *out, char *pwd, uint8_t *salt, uint32_t t_cost,
uint32_t m_cost, uint32_t lanes, uint32_t threads,
const char *type) {
clock_t start_time, stop_time;
unsigned pwd_length;
argon2_context context;
int i;
start_time = clock();
if (!pwd) {
fatal("password missing");
}
if (!salt) {
secure_wipe_memory(pwd, strlen(pwd));
fatal("salt missing");
}
pwd_length = strlen(pwd);
UNUSED_PARAMETER(threads);
context.out = out;
context.outlen = OUT_LEN;
context.pwd = (uint8_t *)pwd;
context.pwdlen = pwd_length;
context.salt = salt;
context.saltlen = SALT_LEN;
context.secret = NULL;
context.secretlen = 0;
context.ad = NULL;
context.adlen = 0;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = lanes;
context.threads = lanes;
context.allocate_cbk = NULL;
context.free_cbk = NULL;
context.flags = ARGON2_FLAG_CLEAR_PASSWORD;
if (!strcmp(type, "d")) {
int result = argon2d(&context);
if (result != ARGON2_OK)
fatal(error_message(result));
} else if (!strcmp(type, "i")) {
int result = argon2i(&context);
if (result != ARGON2_OK)
fatal(error_message(result));
} else {
secure_wipe_memory(pwd, strlen(pwd));
fatal("wrong Argon2 type");
}
stop_time = clock();
/* add back when proper decoding */
/*
char encoded[300];
encode_string(encoded, sizeof encoded, &context);
printf("%s\n", encoded);
*/
printf("Hash:\t\t");
for (i = 0; i < context.outlen; ++i) {
printf("%02x", context.out[i]);
}
printf("\n");
printf("%2.3f seconds\n",
((double)stop_time - start_time) / (CLOCKS_PER_SEC));
}
int main(int argc, char *argv[]) {
unsigned char out[OUT_LEN];
uint32_t m_cost = 1 << LOG_M_COST_DEF;
uint32_t t_cost = T_COST_DEF;
uint32_t lanes = LANES_DEF;
uint32_t threads = THREADS_DEF;
char *pwd = NULL;
uint8_t salt[SALT_LEN];
const char *type = "i";
int i;
if (argc < 3) {
usage(argv[0]);
return ARGON2_MISSING_ARGS;
}
/* get password and salt from command line */
pwd = argv[1];
if (strlen(argv[2]) > SALT_LEN) {
fatal("salt too long");
}
memset(salt, 0x00, SALT_LEN); /* pad with null bytes */
memcpy(salt, argv[2], strlen(argv[2]));
/* parse options */
for (i = 3; i < argc; i++) {
const char *a = argv[i];
unsigned long input = 0;
if (!strcmp(a, "-m")) {
if (i < argc - 1) {
i++;
input = strtoul(argv[i], NULL, 10);
if (input == 0 || input == ULONG_MAX ||
input > ARGON2_MAX_MEMORY_BITS) {
fatal("bad numeric input for -m");
}
m_cost = ARGON2_MIN(UINT64_C(1) << input, UINT32_C(0xFFFFFFFF));
if (m_cost > ARGON2_MAX_MEMORY) {
fatal("m_cost overflow");
}
continue;
} else {
fatal("missing -m argument");
}
} else if (!strcmp(a, "-t")) {
if (i < argc - 1) {
i++;
input = strtoul(argv[i], NULL, 10);
if (input == 0 || input == ULONG_MAX ||
input > ARGON2_MAX_TIME) {
fatal("bad numeric input for -t");
}
t_cost = input;
continue;
} else {
fatal("missing -t argument");
}
} else if (!strcmp(a, "-p")) {
if (i < argc - 1) {
i++;
input = strtoul(argv[i], NULL, 10);
if (input == 0 || input == ULONG_MAX ||
input > ARGON2_MAX_THREADS || input > ARGON2_MAX_LANES) {
fatal("bad numeric input for -p");
}
threads = input;
lanes = threads;
continue;
} else {
fatal("missing -p argument");
}
} else if (!strcmp(a, "-d")) {
type = "d";
} else {
fatal("unknown argument");
}
}
printf("Type:\t\tArgon2%c\n", type[0]);
printf("Iterations:\t%" PRIu32 " \n", t_cost);
printf("Memory:\t\t%" PRIu32 " KiB\n", m_cost);
printf("Parallelism:\t%" PRIu32 " \n", lanes);
run(out, pwd, salt, t_cost, m_cost, lanes, threads, type);
return ARGON2_OK;
}

View file

@ -0,0 +1,57 @@
/*
* 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 */

View file

@ -0,0 +1,67 @@
/*
* 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

View file

@ -5,8 +5,9 @@
#include "sysendian.h"
#include "argon2a.h"
#include "ar2/argon2.h"
#include "ar2/cores.h"
#include "ar2/core.h"
#include "ar2/ar2-scrypt-jane.h"
#define _ALIGN(x) __attribute__ ((aligned(x)))
@ -24,10 +25,10 @@ inline void argon_call(void *out, void *in, void *salt, int type)
context.pwd = (uint8_t *)in;
context.salt = (uint8_t *)salt;
argon2_core(&context, type);
argon2_ctx(&context, type);
}
void argon2_hash(const char* input, char* output, uint32_t len)
void argon2a_hash(const char* input, char* output, uint32_t len)
{
uint32_t _ALIGN(32) hashA[8], hashB[8];

View file

@ -7,7 +7,7 @@ extern "C" {
#include <stdint.h>
void argon2_hash(const char* input, char* output, uint32_t len);
void argon2a_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}

View file

@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "sysendian.h"
#include "ar2/argon2.h"
#include "ar2/core.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
void argon2d_call(const void *input, void *output)
{
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);
}
void argon2d_dyn_hash(const unsigned char* input, unsigned char* output, unsigned int len)
{
argon2d_call(input, output);
}

View file

@ -0,0 +1,16 @@
#ifndef ARGON2D_H
#define ARGON2D_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void argon2d_dyn_hash(const char* input, char* output, unsigned int len);
#ifdef __cplusplus
}
#endif
#endif

102
stratum/algos/bastion.c Normal file
View file

@ -0,0 +1,102 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_hefty1.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_shabal.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
void bastion_hash(const char* input, char* output, uint32_t len)
{
unsigned char _ALIGN(128) hash[64] = { 0 };
sph_echo512_context ctx_echo;
sph_luffa512_context ctx_luffa;
sph_fugue512_context ctx_fugue;
sph_whirlpool_context ctx_whirlpool;
sph_shabal512_context ctx_shabal;
sph_skein512_context ctx_skein;
sph_hamsi512_context ctx_hamsi;
HEFTY1(input, len, hash);
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
if (hash[0] & 0x8)
{
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
} else {
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
}
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, hash, 64);
sph_fugue512_close(&ctx_fugue, hash);
if (hash[0] & 0x8)
{
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, hash, 64);
sph_echo512_close(&ctx_echo, hash);
} else {
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
}
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
if (hash[0] & 0x8)
{
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
} else {
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, hash, 64);
sph_whirlpool_close(&ctx_whirlpool, hash);
}
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, hash, 64);
sph_shabal512_close(&ctx_shabal, hash);
if (hash[0] & 0x8)
{
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, hash, 64);
sph_hamsi512_close(&ctx_hamsi, hash);
} else {
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hash, 64);
sph_luffa512_close(&ctx_luffa, hash);
}
memcpy(output, hash, 32);
}

16
stratum/algos/bastion.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef BASTION_H
#define BASTION_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void bastion_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

171
stratum/algos/bitcore.c Normal file
View file

@ -0,0 +1,171 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HASH_FUNC_BASE_TIMESTAMP 1492973331U // BitCore: Genesis Timestamp
#define HASH_FUNC_COUNT 10
#define HASH_FUNC_COUNT_PERMUTATIONS 40320
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
// helpers
inline void swap(int *a, int *b) {
int c = *a;
*a = *b;
*b = c;
}
static void reverse(int *pbegin, int *pend) {
while ( (pbegin != pend) && (pbegin != --pend) )
swap(pbegin++, pend);
}
static void next_permutation(int *pbegin, int *pend) {
if (pbegin == pend)
return;
int *i = pbegin;
++i;
if (i == pend)
return;
i = pend;
--i;
while (1) {
int *j = i;
--i;
if (*i < *j) {
int *k = pend;
while (!(*i < *--k))
/* pass */;
swap(i, k);
reverse(j, pend);
return; // true
}
if (i == pbegin) {
reverse(pbegin, pend);
return; // false
}
}
}
// helpers
void timetravel10_hash(const char* input, char* output, uint32_t len)
{
uint32_t _ALIGN(64) hash[16 * HASH_FUNC_COUNT];
uint32_t *hashA, *hashB;
uint32_t dataLen = 64;
uint32_t *work_data = (uint32_t *)input;
const uint32_t timestamp = work_data[17];
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
// We want to permute algorithms. To get started we
// initialize an array with a sorted sequence of unique
// integers where every integer represents its own algorithm.
uint32_t permutation[HASH_FUNC_COUNT];
for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++) {
permutation[i]=i;
}
// Compute the next permuation
uint32_t steps = (timestamp - HASH_FUNC_BASE_TIMESTAMP) % HASH_FUNC_COUNT_PERMUTATIONS;
for (uint32_t i = 0; i < steps; i++) {
next_permutation(permutation, permutation + HASH_FUNC_COUNT);
}
for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++) {
if (i == 0) {
dataLen = len;
hashA = work_data;
} else {
dataLen = 64;
hashA = &hash[16 * (i - 1)];
}
hashB = &hash[16 * i];
switch(permutation[i]) {
case 0:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, hashA, dataLen);
sph_blake512_close(&ctx_blake, hashB);
break;
case 1:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hashA, dataLen);
sph_bmw512_close(&ctx_bmw, hashB);
break;
case 2:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hashA, dataLen);
sph_groestl512_close(&ctx_groestl, hashB);
break;
case 3:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hashA, dataLen);
sph_skein512_close(&ctx_skein, hashB);
break;
case 4:
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hashA, dataLen);
sph_jh512_close(&ctx_jh, hashB);
break;
case 5:
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hashA, dataLen);
sph_keccak512_close(&ctx_keccak, hashB);
break;
case 6:
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hashA, dataLen);
sph_luffa512_close(&ctx_luffa, hashB);
break;
case 7:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hashA, dataLen);
sph_cubehash512_close(&ctx_cubehash, hashB);
break;
case 8:
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, hashA, dataLen);
sph_shavite512_close(&ctx_shavite, hashB);
break;
case 9:
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, hashA, dataLen);
sph_simd512_close(&ctx_simd, hashB);
break;
default:
break;
}
}
memcpy(output, &hash[16 * (HASH_FUNC_COUNT - 1)], 32);
}

16
stratum/algos/bitcore.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef TIMETRAVEL10_H
#define TIMETRAVEL10_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void timetravel10_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,3 +1,20 @@
/*
* 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
@ -134,10 +151,6 @@ static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) {
return (w >> c) | (w << (64 - c));
}
/* prevents compiler optimizing out memset() */
static BLAKE2_INLINE void burn(void *v, size_t n) {
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
memset_v(v, 0, n);
}
void clear_internal_memory(void *v, size_t n);
#endif

View file

@ -1,3 +1,20 @@
/*
* 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
@ -37,10 +54,10 @@ 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;
uint8_t buf[BLAKE2B_BLOCKBYTES];
} blake2b_state;
/* Ensure param structs have not been wrongly padded */
@ -57,17 +74,15 @@ 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);
void my_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, const void *in, const void *key, size_t keylen);
int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
const void *key, size_t keylen);
/* Argon2 Team - Begin Code */
int blake2b_long(void *out, const void *in);
int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);
/* Argon2 Team - End Code */
/* Miouyouyou */
void blake2b_too(void *out, const void *in);
#if defined(__cplusplus)
}

View file

@ -0,0 +1,390 @@
/*
* 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 */

View file

@ -0,0 +1,476 @@
/*
* 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
#if defined(HAVE_CONFIG_H)
#include "config/dynamic-config.h"
#endif
#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(__AVX512F__)
#if !defined(__AVX2__)
#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)
#else /* __AVX2__ */
#include <immintrin.h>
#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1))
#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x)))
#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i ml = _mm256_mul_epu32(A0, B0); \
ml = _mm256_add_epi64(ml, ml); \
A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
D0 = _mm256_xor_si256(D0, A0); \
D0 = rotr32(D0); \
\
ml = _mm256_mul_epu32(C0, D0); \
ml = _mm256_add_epi64(ml, ml); \
C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
\
B0 = _mm256_xor_si256(B0, C0); \
B0 = rotr24(B0); \
\
ml = _mm256_mul_epu32(A1, B1); \
ml = _mm256_add_epi64(ml, ml); \
A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
D1 = _mm256_xor_si256(D1, A1); \
D1 = rotr32(D1); \
\
ml = _mm256_mul_epu32(C1, D1); \
ml = _mm256_add_epi64(ml, ml); \
C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
\
B1 = _mm256_xor_si256(B1, C1); \
B1 = rotr24(B1); \
} while((void)0, 0);
#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i ml = _mm256_mul_epu32(A0, B0); \
ml = _mm256_add_epi64(ml, ml); \
A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
D0 = _mm256_xor_si256(D0, A0); \
D0 = rotr16(D0); \
\
ml = _mm256_mul_epu32(C0, D0); \
ml = _mm256_add_epi64(ml, ml); \
C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
B0 = _mm256_xor_si256(B0, C0); \
B0 = rotr63(B0); \
\
ml = _mm256_mul_epu32(A1, B1); \
ml = _mm256_add_epi64(ml, ml); \
A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
D1 = _mm256_xor_si256(D1, A1); \
D1 = rotr16(D1); \
\
ml = _mm256_mul_epu32(C1, D1); \
ml = _mm256_add_epi64(ml, ml); \
C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
B1 = _mm256_xor_si256(B1, C1); \
B1 = rotr63(B1); \
} while((void)0, 0);
#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
\
B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
} while((void)0, 0);
#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
__m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
\
tmp1 = C0; \
C0 = C1; \
C1 = tmp1; \
\
tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \
tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \
D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
} while(0);
#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
\
B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
} while((void)0, 0);
#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
__m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
__m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
\
tmp1 = C0; \
C0 = C1; \
C1 = tmp1; \
\
tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \
tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \
D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
} while((void)0, 0);
#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \
do{ \
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
\
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
} while((void)0, 0);
#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do{ \
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
\
UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
} while((void)0, 0);
#endif /* __AVX2__ */
#else /* __AVX512F__ */
#include <immintrin.h>
#define ror64(x, n) _mm512_ror_epi64((x), (n))
static __m512i muladd(__m512i x, __m512i y)
{
__m512i z = _mm512_mul_epu32(x, y);
return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z));
}
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = muladd(A0, B0); \
A1 = muladd(A1, B1); \
\
D0 = _mm512_xor_si512(D0, A0); \
D1 = _mm512_xor_si512(D1, A1); \
\
D0 = ror64(D0, 32); \
D1 = ror64(D1, 32); \
\
C0 = muladd(C0, D0); \
C1 = muladd(C1, D1); \
\
B0 = _mm512_xor_si512(B0, C0); \
B1 = _mm512_xor_si512(B1, C1); \
\
B0 = ror64(B0, 24); \
B1 = ror64(B1, 24); \
} while ((void)0, 0)
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = muladd(A0, B0); \
A1 = muladd(A1, B1); \
\
D0 = _mm512_xor_si512(D0, A0); \
D1 = _mm512_xor_si512(D1, A1); \
\
D0 = ror64(D0, 16); \
D1 = ror64(D1, 16); \
\
C0 = muladd(C0, D0); \
C1 = muladd(C1, D1); \
\
B0 = _mm512_xor_si512(B0, C0); \
B1 = _mm512_xor_si512(B1, C1); \
\
B0 = ror64(B0, 63); \
B1 = ror64(B1, 63); \
} while ((void)0, 0)
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
\
C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
\
D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
\
C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
\
D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
} while ((void)0, 0)
#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, 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)
#define SWAP_HALVES(A0, A1) \
do { \
__m512i t0, t1; \
t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \
t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \
A0 = t0; \
A1 = t1; \
} while((void)0, 0)
#define SWAP_QUARTERS(A0, A1) \
do { \
SWAP_HALVES(A0, A1); \
A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
} while((void)0, 0)
#define UNSWAP_QUARTERS(A0, A1) \
do { \
A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
SWAP_HALVES(A0, A1); \
} while((void)0, 0)
#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \
do { \
SWAP_HALVES(A0, B0); \
SWAP_HALVES(C0, D0); \
SWAP_HALVES(A1, B1); \
SWAP_HALVES(C1, D1); \
BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
SWAP_HALVES(A0, B0); \
SWAP_HALVES(C0, D0); \
SWAP_HALVES(A1, B1); \
SWAP_HALVES(C1, D1); \
} while ((void)0, 0)
#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
SWAP_QUARTERS(A0, A1); \
SWAP_QUARTERS(B0, B1); \
SWAP_QUARTERS(C0, C1); \
SWAP_QUARTERS(D0, D1); \
BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
UNSWAP_QUARTERS(A0, A1); \
UNSWAP_QUARTERS(B0, B1); \
UNSWAP_QUARTERS(C0, C1); \
UNSWAP_QUARTERS(D0, D1); \
} while ((void)0, 0)
#endif /* __AVX512F__ */
#endif /* BLAKE_ROUND_MKA_OPT_H */

View file

@ -1,3 +1,20 @@
/*
* 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

23
stratum/algos/blake2b.c Normal file
View file

@ -0,0 +1,23 @@
/**
* Blake2-B Implementation
* tpruvot@github 2016-2018
*/
#include <string.h>
#include <stdint.h>
#include <sha3/blake2b.h>
#include <sha3/sph_types.h>
void blake2b_hash(const char* input, char* output, uint32_t len)
{
uint32_t ALIGN(64) hash[8];
blake2b_ctx ctx;
blake2b_init(&ctx, 32, NULL, 0);
blake2b_update(&ctx, input, len);
blake2b_final(&ctx, hash);
memcpy(output, hash, 32);
}

16
stratum/algos/blake2b.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef BLAKE2B_H
#define BLAKE2B_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void blake2b_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

4
stratum/algos/common.h Normal file
View file

@ -0,0 +1,4 @@
#define _ALIGN(x) __attribute__ ((aligned(x)))
extern void debuglog_hex(void *data, int len);

29
stratum/algos/deep.c Normal file
View file

@ -0,0 +1,29 @@
#include <string.h>
#include <stdlib.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_echo.h>
void deep_hash(const char* input, char* output, uint32_t len)
{
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_echo512_context ctx_echo;
char hash1[64], hash2[64];
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, (const void*) input, len);
sph_luffa512_close(&ctx_luffa, (void*) &hash1);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, (const void*) &hash1, 64);
sph_cubehash512_close(&ctx_cubehash, (void*) &hash2);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, (const void*) &hash2, 64);
sph_echo512_close(&ctx_echo, (void*) &hash1);
memcpy(output, &hash1, 32);
}

17
stratum/algos/deep.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef DEEP_H
#define DEEP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void deep_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

157
stratum/algos/exosis.c Normal file
View file

@ -0,0 +1,157 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HASH_FUNC_BASE_TIMESTAMP 1538556426 // Exosis: Genesis Timestamp
#define HASH_FUNC_COUNT 8
#define HASH_FUNC_COUNT_PERMUTATIONS 40320
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
// helpers
inline void swap(int *a, int *b) {
int c = *a;
*a = *b;
*b = c;
}
static void reverse(int *pbegin, int *pend) {
while ( (pbegin != pend) && (pbegin != --pend) )
swap(pbegin++, pend);
}
static void next_permutation(int *pbegin, int *pend) {
if (pbegin == pend)
return;
int *i = pbegin;
++i;
if (i == pend)
return;
i = pend;
--i;
while (1) {
int *j = i;
--i;
if (*i < *j) {
int *k = pend;
while (!(*i < *--k))
/* pass */;
swap(i, k);
reverse(j, pend);
return; // true
}
if (i == pbegin) {
reverse(pbegin, pend);
return; // false
}
}
}
// helpers
void exosis_hash(const char* input, char* output, uint32_t len)
{
uint32_t _ALIGN(64) hash[16 * HASH_FUNC_COUNT];
uint32_t *hashA, *hashB;
uint32_t dataLen = 64;
uint32_t *work_data = (uint32_t *)input;
const uint32_t timestamp = work_data[17];
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
// We want to permute algorithms. To get started we
// initialize an array with a sorted sequence of unique
// integers where every integer represents its own algorithm.
uint32_t permutation[HASH_FUNC_COUNT];
for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++) {
permutation[i]=i;
}
// Compute the next permuation
uint32_t steps = (timestamp - HASH_FUNC_BASE_TIMESTAMP) % HASH_FUNC_COUNT_PERMUTATIONS;
for (uint32_t i = 0; i < steps; i++) {
next_permutation(permutation, permutation + HASH_FUNC_COUNT);
}
for (uint32_t i = 0; i < HASH_FUNC_COUNT; i++) {
if (i == 0) {
dataLen = len;
hashA = work_data;
} else {
dataLen = 64;
hashA = &hash[16 * (i - 1)];
}
hashB = &hash[16 * i];
switch(permutation[i]) {
case 0:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, hashA, dataLen);
sph_blake512_close(&ctx_blake, hashB);
break;
case 1:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hashA, dataLen);
sph_bmw512_close(&ctx_bmw, hashB);
break;
case 2:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hashA, dataLen);
sph_groestl512_close(&ctx_groestl, hashB);
break;
case 3:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hashA, dataLen);
sph_skein512_close(&ctx_skein, hashB);
break;
case 4:
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hashA, dataLen);
sph_jh512_close(&ctx_jh, hashB);
break;
case 5:
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hashA, dataLen);
sph_keccak512_close(&ctx_keccak, hashB);
break;
case 6:
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, hashA, dataLen);
sph_luffa512_close(&ctx_luffa, hashB);
break;
case 7:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, hashA, dataLen);
sph_cubehash512_close(&ctx_cubehash, hashB);
break;
default:
break;
}
}
memcpy(output, &hash[16 * (HASH_FUNC_COUNT - 1)], 32);
}

16
stratum/algos/exosis.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef EXOSIS_H
#define EXOSIS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void exosis_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

180
stratum/algos/hex.c Normal file
View file

@ -0,0 +1,180 @@
// Copyright (c) 2018 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <stdint.h>
#include <stdio.h>
#include <memory.h>
#include "hex.h"
#include "../sha3/sph_blake.h"
#include "../sha3/sph_bmw.h"
#include "../sha3/sph_groestl.h"
#include "../sha3/sph_skein.h"
#include "../sha3/sph_jh.h"
#include "../sha3/sph_keccak.h"
#include "../sha3/sph_luffa.h"
#include "../sha3/sph_cubehash.h"
#include "../sha3/sph_shavite.h"
#include "../sha3/sph_simd.h"
#include "../sha3/sph_echo.h"
#include "../sha3/sph_hamsi.h"
#include "../sha3/sph_fugue.h"
#include "../sha3/sph_shabal.h"
#include "../sha3/sph_whirlpool.h"
#include "../sha3/sph_sha2.h"
enum Algo {
BLAKE = 0,
BMW,
GROESTL,
JH,
KECCAK,
SKEIN,
LUFFA,
CUBEHASH,
SHAVITE,
SIMD,
ECHO,
HAMSI,
FUGUE,
SHABAL,
WHIRLPOOL,
SHA512,
HASH_FUNC_COUNT
};
static const int TOTAL_CYCLES = 16;
static uint8_t get_first_algo(const uint32_t* prevblock) {
uint8_t* data = (uint8_t*)prevblock;
return data[7] >> 4;
}
void hex_hash(const char* input, char* output, uint32_t len)
{
unsigned char hash[128];
uint8_t curr_algo;
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_skein512_context ctx_skein;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_whirlpool_context ctx_whirlpool;
sph_sha512_context ctx_sha512;
const void *in = input;
int size = len;
uint32_t *in32 = (uint32_t*) input;
// initial algo = first digit of prev block hashorder (cheers, x16r)
curr_algo = get_first_algo(&in32[1]);
for (int i = 0; i < TOTAL_CYCLES; i++)
{
// Only 4 test algos yet
switch (curr_algo) {
case BLAKE:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, in, size);
sph_blake512_close(&ctx_blake, hash);
break;
case BMW:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, in, size);
sph_bmw512_close(&ctx_bmw, hash);
break;
case GROESTL:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, in, size);
sph_groestl512_close(&ctx_groestl, hash);
break;
case JH:
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, in, size);
sph_jh512_close(&ctx_jh, hash);
break;
case KECCAK:
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, in, size);
sph_keccak512_close(&ctx_keccak, hash);
break;
case SKEIN:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, in, size);
sph_skein512_close(&ctx_skein, hash);
break;
case LUFFA:
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, in, size);
sph_luffa512_close(&ctx_luffa, hash);
break;
case CUBEHASH:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, in, size);
sph_cubehash512_close(&ctx_cubehash, hash);
break;
case SHAVITE:
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, in, size);
sph_shavite512_close(&ctx_shavite, hash);
break;
case SIMD:
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, in, size);
sph_simd512_close(&ctx_simd, hash);
break;
case ECHO:
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, in, size);
sph_echo512_close(&ctx_echo, hash);
break;
case HAMSI:
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, in, size);
sph_hamsi512_close(&ctx_hamsi, hash);
break;
case FUGUE:
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, in, size);
sph_fugue512_close(&ctx_fugue, hash);
break;
case SHABAL:
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, in, size);
sph_shabal512_close(&ctx_shabal, hash);
break;
case WHIRLPOOL:
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, in, size);
sph_whirlpool_close(&ctx_whirlpool, hash);
break;
case SHA512:
sph_sha512_init(&ctx_sha512);
sph_sha512(&ctx_sha512,(const void*) in, size);
sph_sha512_close(&ctx_sha512,(void*) hash);
break;
}
// next algos = first digit on prev hash
curr_algo = (uint8_t)hash[0] % HASH_FUNC_COUNT;
in = (void*)hash;
size = 64;
}
memcpy(output, hash, 32);
}

20
stratum/algos/hex.h Normal file
View file

@ -0,0 +1,20 @@
// Copyright (c) 2018 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef HEXHASH_H
#define HEXHASH_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void hex_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif // HEXHASH_H

218
stratum/algos/hmq17.c Normal file
View file

@ -0,0 +1,218 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_luffa.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_shavite.h>
#include <sha3/sph_simd.h>
#include <sha3/sph_echo.h>
#include <sha3/sph_hamsi.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_shabal.h>
#include <sha3/sph_whirlpool.h>
#include <sha3/sph_sha2.h>
#include <sha3/sph_haval.h>
typedef struct
{
sph_blake512_context blake1, blake2;
sph_bmw512_context bmw1, bmw2, bmw3;
sph_groestl512_context groestl1, groestl2;
sph_skein512_context skein1, skein2;
sph_jh512_context jh1, jh2;
sph_keccak512_context keccak1, keccak2;
sph_luffa512_context luffa1, luffa2;
sph_cubehash512_context cubehash;
sph_shavite512_context shavite1, shavite2;
sph_simd512_context simd1, simd2;
sph_echo512_context echo1, echo2;
sph_hamsi512_context hamsi;
sph_fugue512_context fugue1, fugue2;
sph_shabal512_context shabal;
sph_whirlpool_context whirlpool1, whirlpool2, whirlpool3, whirlpool4;
sph_sha512_context sha1, sha2;
sph_haval256_5_context haval1, haval2;
} hmq_contexts;
static __thread hmq_contexts base_contexts;
static __thread int hmq_context_init = 0;
static void init_contexts(hmq_contexts *ctx)
{
sph_bmw512_init(&ctx->bmw1);
sph_bmw512_init(&ctx->bmw2);
sph_bmw512_init(&ctx->bmw2);
sph_bmw512_init(&ctx->bmw3);
sph_whirlpool_init(&ctx->whirlpool1);
sph_whirlpool_init(&ctx->whirlpool2);
sph_whirlpool_init(&ctx->whirlpool3);
sph_whirlpool_init(&ctx->whirlpool4);
sph_groestl512_init(&ctx->groestl1);
sph_groestl512_init(&ctx->groestl2);
sph_skein512_init(&ctx->skein1);
sph_skein512_init(&ctx->skein2);
sph_jh512_init(&ctx->jh1);
sph_jh512_init(&ctx->jh2);
sph_keccak512_init(&ctx->keccak1);
sph_keccak512_init(&ctx->keccak2);
sph_blake512_init(&ctx->blake1);
sph_blake512_init(&ctx->blake2);
sph_luffa512_init(&ctx->luffa1);
sph_luffa512_init(&ctx->luffa2);
sph_cubehash512_init(&ctx->cubehash);
sph_shavite512_init(&ctx->shavite1);
sph_shavite512_init(&ctx->shavite2);
sph_simd512_init(&ctx->simd1);
sph_simd512_init(&ctx->simd2);
sph_echo512_init(&ctx->echo1);
sph_echo512_init(&ctx->echo2);
sph_hamsi512_init(&ctx->hamsi);
sph_fugue512_init(&ctx->fugue1);
sph_fugue512_init(&ctx->fugue2);
sph_shabal512_init(&ctx->shabal);
sph_sha512_init(&ctx->sha1);
sph_sha512_init(&ctx->sha2);
sph_haval256_5_init(&ctx->haval1);
sph_haval256_5_init(&ctx->haval2);
}
void hmq17_hash(const char* input, char* output, uint32_t len)
{
uint32_t hash[32];
const uint32_t mask = 24;
hmq_contexts ctx;
if (!hmq_context_init) {
init_contexts(&base_contexts);
hmq_context_init = 1;
}
memcpy(&ctx, &base_contexts, sizeof(hmq_contexts));
sph_bmw512(&ctx.bmw1, input, len);
sph_bmw512_close(&ctx.bmw1, hash);
sph_whirlpool(&ctx.whirlpool1, hash, 64);
sph_whirlpool_close(&ctx.whirlpool1, hash);
if (hash[0] & mask) {
sph_groestl512(&ctx.groestl1, hash, 64);
sph_groestl512_close(&ctx.groestl1, hash);
} else {
sph_skein512(&ctx.skein1, hash, 64);
sph_skein512_close(&ctx.skein1, hash);
}
sph_jh512(&ctx.jh1, hash, 64);
sph_jh512_close(&ctx.jh1, hash);
sph_keccak512(&ctx.keccak1, hash, 64);
sph_keccak512_close(&ctx.keccak1, hash);
if (hash[0] & mask) {
sph_blake512(&ctx.blake1, hash, 64);
sph_blake512_close(&ctx.blake1, hash);
} else {
sph_bmw512 (&ctx.bmw2, hash, 64);
sph_bmw512_close(&ctx.bmw2, hash);
}
sph_luffa512(&ctx.luffa1, hash, 64);
sph_luffa512_close(&ctx.luffa1, hash);
sph_cubehash512(&ctx.cubehash, hash, 64);
sph_cubehash512_close(&ctx.cubehash, hash);
if (hash[0] & mask) {
sph_keccak512(&ctx.keccak2, hash, 64);
sph_keccak512_close(&ctx.keccak2, hash);
} else {
sph_jh512(&ctx.jh2, hash, 64);
sph_jh512_close(&ctx.jh2, hash);
}
sph_shavite512(&ctx.shavite1, hash, 64);
sph_shavite512_close(&ctx.shavite1, hash);
sph_simd512(&ctx.simd1, hash, 64);
sph_simd512_close(&ctx.simd1, hash);
if (hash[0] & mask) {
sph_whirlpool(&ctx.whirlpool2, hash, 64);
sph_whirlpool_close(&ctx.whirlpool2, hash);
} else {
sph_haval256_5(&ctx.haval1, hash, 64);
sph_haval256_5_close(&ctx.haval1, hash);
memset(&hash[8], 0, 32);
}
sph_echo512(&ctx.echo1, hash, 64);
sph_echo512_close(&ctx.echo1, hash);
sph_blake512(&ctx.blake2, hash, 64);
sph_blake512_close(&ctx.blake2, hash);
if (hash[0] & mask) {
sph_shavite512(&ctx.shavite2, hash, 64);
sph_shavite512_close(&ctx.shavite2, hash);
} else {
sph_luffa512 (&ctx.luffa2, hash, 64);
sph_luffa512_close(&ctx.luffa2, hash);
}
sph_hamsi512(&ctx.hamsi, hash, 64);
sph_hamsi512_close(&ctx.hamsi, hash);
sph_fugue512(&ctx.fugue1, hash, 64);
sph_fugue512_close(&ctx.fugue1, hash);
if (hash[0] & mask) {
sph_echo512(&ctx.echo2, hash, 64);
sph_echo512_close(&ctx.echo2, hash);
} else {
sph_simd512(&ctx.simd2, hash, 64);
sph_simd512_close(&ctx.simd2, hash);
}
sph_shabal512(&ctx.shabal, hash, 64);
sph_shabal512_close(&ctx.shabal, hash);
sph_whirlpool(&ctx.whirlpool3, hash, 64);
sph_whirlpool_close(&ctx.whirlpool3, hash);
if (hash[0] & mask) {
sph_fugue512(&ctx.fugue2, hash, 64);
sph_fugue512_close(&ctx.fugue2, hash);
} else {
sph_sha512(&ctx.sha1, hash, 64);
sph_sha512_close(&ctx.sha1, hash);
}
sph_groestl512(&ctx.groestl2, hash, 64);
sph_groestl512_close(&ctx.groestl2, hash);
sph_sha512(&ctx.sha2, hash, 64);
sph_sha512_close(&ctx.sha2, hash);
if (hash[0] & mask) {
sph_haval256_5(&ctx.haval2, hash, 64);
sph_haval256_5_close(&ctx.haval2, hash);
memset(&hash[8], 0, 32);
} else {
sph_whirlpool(&ctx.whirlpool4, hash, 64);
sph_whirlpool_close(&ctx.whirlpool4, hash);
}
sph_bmw512(&ctx.bmw3, hash, 64);
sph_bmw512_close(&ctx.bmw3, hash);
memcpy(output, hash, 32);
}

16
stratum/algos/hmq17.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef HMQ17_H
#define HMQ17_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void hmq17_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

101
stratum/algos/hsr14.c Normal file
View file

@ -0,0 +1,101 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "../sha3/sph_blake.h"
#include "../sha3/sph_bmw.h"
#include "../sha3/sph_groestl.h"
#include "../sha3/sph_jh.h"
#include "../sha3/sph_keccak.h"
#include "../sha3/sph_skein.h"
#include "../sha3/sph_luffa.h"
#include "../sha3/sph_cubehash.h"
#include "../sha3/sph_shavite.h"
#include "../sha3/sph_simd.h"
#include "../sha3/sph_echo.h"
#include "../sha3/sph_hamsi.h"
#include "../sha3/sph_fugue.h"
#include "sm3.h"
#include "common.h"
void hsr_hash(const char* input, char* output, uint32_t len)
{
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_luffa512_context ctx_luffa1;
sph_cubehash512_context ctx_cubehash1;
sph_shavite512_context ctx_shavite1;
sph_simd512_context ctx_simd1;
sph_echo512_context ctx_echo1;
sm3_ctx_t ctx_sm3;
sph_hamsi512_context ctx_hamsi1;
sph_fugue512_context ctx_fugue1;
uint8_t _ALIGN(128) hash[64];
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, input, len);
sph_blake512_close(&ctx_blake, hash);
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, hash, 64);
sph_bmw512_close(&ctx_bmw, hash);
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, hash, 64);
sph_skein512_close (&ctx_skein, hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, hash, 64);
sph_keccak512_close(&ctx_keccak, hash);
sph_luffa512_init(&ctx_luffa1);
sph_luffa512(&ctx_luffa1, hash, 64);
sph_luffa512_close(&ctx_luffa1, hash);
sph_cubehash512_init(&ctx_cubehash1);
sph_cubehash512(&ctx_cubehash1, hash, 64);
sph_cubehash512_close(&ctx_cubehash1, hash);
sph_shavite512_init(&ctx_shavite1);
sph_shavite512(&ctx_shavite1, hash, 64);
sph_shavite512_close(&ctx_shavite1, hash);
sph_simd512_init(&ctx_simd1);
sph_simd512(&ctx_simd1, hash, 64);
sph_simd512_close(&ctx_simd1, hash);
sph_echo512_init (&ctx_echo1);
sph_echo512(&ctx_echo1, hash, 64);
sph_echo512_close(&ctx_echo1, hash);
sm3_init(&ctx_sm3);
sm3_update(&ctx_sm3, hash, 64);
memset(hash, 0, sizeof hash);
sm3_close(&ctx_sm3, hash);
sph_hamsi512_init(&ctx_hamsi1);
sph_hamsi512(&ctx_hamsi1, hash, 64);
sph_hamsi512_close(&ctx_hamsi1, hash);
sph_fugue512_init(&ctx_fugue1);
sph_fugue512(&ctx_fugue1, hash, 64);
sph_fugue512_close(&ctx_fugue1, hash);
memcpy(output, hash, 32);
}

16
stratum/algos/hsr14.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef HSR14_H
#define HSR14_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void hsr_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,135 +1,56 @@
#include "jha.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "../sha3/sph_blake.h"
#include "../sha3/sph_groestl.h"
#include "../sha3/sph_jh.h"
#include "../sha3/sph_keccak.h"
#include "../sha3/sph_skein.h"
#include <sha3/sph_blake.h>
#include <sha3/sph_groestl.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_keccak.h>
#include <sha3/sph_skein.h>
#include "jha.h"
#include "common.h"
void jha_hash(const char* input, char* output, uint32_t len) {
void jha_hash(const char* input, char* output, uint32_t len)
{
sph_blake512_context ctx_blake;
sph_groestl512_context ctx_groestl;
sph_jh512_context ctx_jh;
sph_keccak512_context ctx_keccak;
sph_skein512_context ctx_skein;
uint32_t hash[16];
uint32_t _ALIGN(64) hash[16];
unsigned int round_mask = (
(unsigned int)(((unsigned char *)input)[84]) << 0 |
(unsigned int)(((unsigned char *)input)[85]) << 8 |
(unsigned int)(((unsigned char *)input)[86]) << 16 |
(unsigned int)(((unsigned char *)input)[87]) << 24 );
//
// JHA V7
//
if (round_mask == 7) {
//
// Input Hashing with SHA3 512, 88 bytes
//
sph_keccak512_init(&ctx_keccak);
sph_keccak512 (&ctx_keccak, input, 88);
sph_keccak512_close(&ctx_keccak, hash);
//
// Variable Rounds Loop
//
unsigned int rounds = hash[0] & 7;
unsigned int round;
for (round = 0; round < rounds; round++) {
switch (hash[0] & 3) {
case 0:
sph_blake512_init(&ctx_blake);
sph_blake512 (&ctx_blake, hash, 64);
sph_blake512_close(&ctx_blake, hash);
break;
case 1:
sph_groestl512_init(&ctx_groestl);
sph_groestl512 (&ctx_groestl, hash, 64);
sph_groestl512_close(&ctx_groestl, hash);
break;
case 2:
sph_jh512_init(&ctx_jh);
sph_jh512 (&ctx_jh, hash, 64);
sph_jh512_close(&ctx_jh, hash);
break;
case 3:
sph_skein512_init(&ctx_skein);
sph_skein512 (&ctx_skein, hash, 64);
sph_skein512_close(&ctx_skein, hash);
break;
}
}
//
// Return 256bit(32x8)
//
memcpy(output, hash, 32);
}
//
// JHA V8
//
else if (round_mask == 8) {
//
// Input Hashing with SHA3 512, 80 bytes
//
// JHA v8: SHA3 512, on 80 bytes (not 88)
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, input, 80);
sph_keccak512_close(&ctx_keccak, (&hash));
//
// Heavy & Light Pair Loop
//
unsigned int round;
for (round = 0; round < 3; round++) {
for (int round = 0; round < 3; round++)
{
if (hash[0] & 0x01) {
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, (&hash), 64);
sph_groestl512_close(&ctx_groestl, (&hash));
}
else {
} else {
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, (&hash), 64);
sph_skein512_close(&ctx_skein, (&hash));
}
if (hash[0] & 0x01) {
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, (&hash), 64);
sph_blake512_close(&ctx_blake, (&hash));
}
else {
} else {
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, (&hash), 64);
sph_jh512_close(&ctx_jh, (&hash));
}
}
//
// Return 256bit(32x8)
//
// Return 256 bits (32x8)
memcpy(output, hash, 32);
}
//
// Wrong Round Mask Data
//
else {
memset(output, 0xFF, 32);
}
}

36
stratum/algos/lbk3.c Normal file
View file

@ -0,0 +1,36 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_blake.h>
#include <sha3/sph_bmw.h>
#include <sha3/sph_keccak.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
extern uint64_t lbk3_height;
void lbk3_hash(const char* input, char* output, uint32_t len)
{
sph_bmw256_context ctx_bmw;
sph_blake256_context ctx_blake;
sph_keccak256_context ctx_keccak;
uint8_t _ALIGN(128) hash[96];
memset(&hash[32], 0, 64);
sph_bmw256_init(&ctx_bmw);
sph_bmw256 (&ctx_bmw, input, 80);
sph_bmw256_close(&ctx_bmw, &hash[0]);
sph_blake256_init(&ctx_blake);
sph_blake256 (&ctx_blake, &hash[0], 64);
sph_blake256_close(&ctx_blake, &hash[32]);
sph_keccak256_init(&ctx_keccak);
sph_keccak256 (&ctx_keccak, &hash[32], 64);
sph_keccak256_close(&ctx_keccak, &hash[64]);
memcpy(output, &hash[64], 32);
}

16
stratum/algos/lbk3.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef LBK3_H
#define LBK3_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void lbk3_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

68
stratum/algos/lyra2v3.c Normal file
View file

@ -0,0 +1,68 @@
/*-
* Copyright(or left) 2019 YiiMP
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file was originally written by Colin Percival as part of the Tarsnap
* online backup system.
*/
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "../sha3/sph_blake.h"
#include "../sha3/sph_cubehash.h"
#include "../sha3/sph_bmw.h"
#include "Lyra2.h"
void lyra2v3_hash(const char* input, char* output, uint32_t len)
{
uint32_t hash[8], hashB[8];
sph_blake256_context ctx_blake;
sph_cubehash256_context ctx_cubehash;
sph_bmw256_context ctx_bmw;
sph_blake256_set_rounds(14);
sph_blake256_init(&ctx_blake);
sph_blake256(&ctx_blake, input, len); /* 80 */
sph_blake256_close(&ctx_blake, hash);
LYRA2_3(hashB, 32, hash, 32, hash, 32, 1, 4, 4);
sph_cubehash256_init(&ctx_cubehash);
sph_cubehash256(&ctx_cubehash, hashB, 32);
sph_cubehash256_close(&ctx_cubehash, hash);
LYRA2_3(hashB, 32, hash, 32, hash, 32, 1, 4, 4);
sph_bmw256_init(&ctx_bmw);
sph_bmw256(&ctx_bmw, hashB, 32);
sph_bmw256_close(&ctx_bmw, hash);
memcpy(output, hash, 32);
}

16
stratum/algos/lyra2v3.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef LYRA2V3_H
#define LYRA2V3_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void lyra2v3_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

39
stratum/algos/lyra2z.c Normal file
View file

@ -0,0 +1,39 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "Lyra2-z.h"
#include <sha3/sph_blake.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
extern uint64_t lyra2z_height;
void lyra2z_hash(const char* input, char* output, uint32_t len)
{
uint32_t _ALIGN(64) hashB[8], hash[8];
sph_blake256_context ctx_blake;
/*
uint64_t height = lyra2z_height;
// initial implementation was pure lyra2 (no blake)
if (height < 100) {
fprintf(stderr, "submit error, height=%u, len=%u\n", (uint32_t) height, len);
memset(hash, 0xff, 32);
return;
}
LYRA2z((void*)hash, 32, (void*)input, len, (void*)input, len, 2, height, 256);
*/
sph_blake256_set_rounds(14);
sph_blake256_init(&ctx_blake);
sph_blake256(&ctx_blake, input, len);
sph_blake256_close(&ctx_blake, hashB);
LYRA2z(hash, 32, hashB, 32, hashB, 32, 8, 8, 8);
memcpy(output, hash, 32);
}

16
stratum/algos/lyra2z.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef LYRA2Z_H
#define LYRA2Z_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void lyra2z_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

28
stratum/algos/lyra2zz.c Normal file
View file

@ -0,0 +1,28 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "Lyra2-zz.h"
#include <sha3/sph_blake.h>
#define _ALIGN(x) __attribute__ ((aligned(x)))
extern uint64_t lyra2z_height;
void lyra2zz_hash(const char* input, char* output, uint32_t len)
{
uint32_t _ALIGN(64) hashB[8], hash[8];
sph_blake256_context ctx_blake;
sph_blake256_set_rounds(14);
sph_blake256_init(&ctx_blake);
sph_blake256(&ctx_blake, input, 112);
sph_blake256_close(&ctx_blake, hashB);
LYRA2ZZ(hash, 32, hashB, 32, hashB, 32, 8, 8, 8);
memcpy(output, hash, 32);
}

16
stratum/algos/lyra2zz.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef LYRA2ZZ_H
#define LYRA2ZZ_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void lyra2zz_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -8,16 +8,19 @@ CXXFLAGS = -O2 -I.. -march=native
CFLAGS= $(CXXFLAGS) -std=gnu99
LDFLAGS=-O2 -lgmp
SOURCES=lyra2re.c lyra2v2.c Lyra2.c Sponge.c blake.c scrypt.c c11.c x11.c x13.c sha256.c keccak.c \
x14.c x15.c x17.c nist5.c fresh.c quark.c neoscrypt.c scryptn.c qubit.c skein.c groestl.c \
xevan.c \
skein2.c zr5.c bmw.c luffa.c pentablake.c whirlpool.c whirlpoolx.c blakecoin.c \
blake2.c \
yescrypt.c yescrypt-opt.c sha256_Y.c lbry.c \
m7m.c magimath.cpp velvet.c \
argon2a.c ar2/blake2b.c ar2/argon2.c ar2/ref.c ar2/cores.c ar2/ar2-scrypt-jane.c \
hive.c pomelo.c \
sib.c veltor.c gost.c x11evo.c
SOURCES=lyra2re.c lyra2v2.c lyra2v3.c Lyra2.c lyra2z.c Lyra2-z.c lyra2zz.c Lyra2-zz.c Sponge.c allium.c \
c11.c x11.c x12.c x13.c hsr14.c sm3.c x14.c x15.c x17.c \
x22i.c SWIFFTX/SWIFFTX.c \
blake.c blakecoin.c blake2b.c blake2s.c jha.c keccak.c lbry.c tribus.c exosis.c \
deep.c fresh.c groestl.c neoscrypt.c nist5.c quark.c qubit.c skein.c skein2.c \
bitcore.c timetravel.c x11evo.c x16r.c x16rv2.c x16s.c xevan.c bastion.c hmq17.c sonoa.c \
bmw.c luffa.c pentablake.c vitalium.c whirlpool.c whirlpoolx.c zr5.c \
scrypt.c scryptn.c sha256.c sha256t.c sha256q.c \
yescrypt.c yescrypt-opt.c sha256_Y.c \
a5a.c a5amath.c m7m.c magimath.cpp velvet.c \
argon2a.c blake2/blake2b.c ar2/argon2.c ar2/core.c ar2/encoding.c ar2/opt.c ar2/thread.c ar2/ar2-scrypt-jane.c \
hive.c pomelo.c hex.c argon2d-dyn.c \
phi.c phi2.c polytimos.c rainforest.c skunk.c sib.c veltor.c gost.c aergo.c lbk3.c
OBJECTS=$(SOURCES:%.c=%.o) $(SOURCES:%.cpp=%.o)
OUTPUT=libalgos.a
@ -39,4 +42,5 @@ $(OUTPUT): $(OBJECTS)
clean:
rm -f *.o
rm -f ar2/*.o
rm -f blake2/*.o
rm -f SWIFFTX/*.o

51
stratum/algos/phi.c Normal file
View file

@ -0,0 +1,51 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sha3/sph_skein.h>
#include <sha3/sph_jh.h>
#include <sha3/sph_cubehash.h>
#include <sha3/sph_fugue.h>
#include <sha3/sph_echo.h>
#include "gost.h"
#include "common.h"
void phi_hash(const char* input, char* output, uint32_t len)
{
sph_skein512_context ctx_skein;
sph_jh512_context ctx_jh;
sph_cubehash512_context ctx_cubehash;
sph_fugue512_context ctx_fugue;
sph_gost512_context ctx_gost;
sph_echo512_context ctx_echo;
uint8_t _ALIGN(128) hash[64];
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, input, len);
sph_skein512_close(&ctx_skein, (void*) hash);
sph_jh512_init(&ctx_jh);
sph_jh512(&ctx_jh, (const void*) hash, 64);
sph_jh512_close(&ctx_jh, (void*) hash);
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, (const void*) hash, 64);
sph_cubehash512_close(&ctx_cubehash, (void*) hash);
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, (const void*) hash, 64);
sph_fugue512_close(&ctx_fugue, (void*) hash);
sph_gost512_init(&ctx_gost);
sph_gost512(&ctx_gost, (const void*) hash, 64);
sph_gost512_close(&ctx_gost, (void*) hash);
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, (const void*) hash, 64);
sph_echo512_close(&ctx_echo, (void*) hash);
memcpy(output, hash, 32);
}

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