├── .gitignore
├── .travis.yml
├── README.md
├── pom.xml
└── src
└── main
├── java
└── tk
│ └── netindev
│ └── drill
│ ├── Drill.java
│ ├── hasher
│ └── Hasher.java
│ ├── miner
│ ├── Job.java
│ ├── Miner.java
│ └── Worker.java
│ └── util
│ ├── Hashrate.java
│ ├── Hex.java
│ └── Misc.java
├── jni
├── CMakeLists.txt
├── algos.hpp
├── c_blake256.c
├── c_blake256.h
├── c_groestl.c
├── c_groestl.h
├── c_jh.c
├── c_jh.h
├── c_keccak.c
├── c_keccak.h
├── c_skein.c
├── c_skein.h
├── cryptonight.h
├── cryptonight_aesni.h
├── cryptonight_common.cpp
├── groestl_tables.h
├── hash.h
├── hasher.cpp
├── int-util.h
├── skein_port.h
└── soft_aes.hpp
└── resources
├── simplelogger.properties
├── unix
└── x64
│ └── libcryptonight.so
└── win
└── x64
└── cryptonight.dll
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /bin
3 | .classpath
4 | .project
5 | /.settings
6 | /.idea
7 | *.DS_Store
8 | dependency-reduced-pom.xml
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - oraclejdk8
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # drill [](https://travis-ci.org/netindev/drill)
2 | Monero miner written in java using JNI bindings.
3 |
4 | ## Download
5 | * Binary releases: https://github.com/netindev/drill/releases
6 | * Git tree: https://github.com/netindev/drill.git
7 |
8 | ## Usage
9 | Usage: ```java -jar drill-x.x.x.jar -thread 2 -host localhost -port 3333 -user 4AignrnSVPiXUwk3nKBsTWVi4PCvAKPsrJKSpqinK55bQPFXHTsbYbe5FtUmxjJTbcATQ233gkntYA51fd6Hmur5F3v2o1G -pass x```
10 |
11 | ### Options
12 | | Arg | Description | Required |
13 | | --- | --- | --- |
14 | | -host | Pool host to connect | Yes |
15 | | -user | Username to login, also can be used your address | Yes |
16 | | -port | Pool host port | Yes |
17 | | -pass | Password to login | Optional |
18 | | -thread | Thread count | Optional |
19 | | -help | Prints the help | Optional |
20 |
21 | ## Build
22 | CMake:
23 | * Install [CMake](https://cmake.org/download/)
24 | * Go to: `..\drill\src\main\jni` and execute `cmake .`
25 |
26 | Java:
27 | * Install [Maven](https://maven.apache.org/download.html)
28 | * Go to: `..\drill` and execute `mvn clean install`
29 |
30 | ## Contacts
31 | * [email](mailto:contact@netindev.tk)
32 | * [twitter](https://twitter.com/netindev)
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
4 | 4.0.0
5 | tk.netindev.drill
6 | drill
7 | 0.1.0-SNAPSHOT
8 |
9 |
10 | commons-cli
11 | commons-cli
12 | 1.4
13 |
14 |
15 | org.slf4j
16 | slf4j-simple
17 | 1.7.21
18 |
19 |
20 | org.slf4j
21 | slf4j-api
22 | 1.7.5
23 |
24 |
25 | com.eclipsesource.minimal-json
26 | minimal-json
27 | 0.9.2
28 |
29 |
30 |
31 | target/classes
32 |
33 |
34 | org.apache.maven.plugins
35 | maven-jar-plugin
36 |
37 |
38 |
39 | true
40 | tk.netindev.drill.Drill
41 |
42 |
43 |
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-compiler-plugin
48 | 3.8.0
49 |
50 | 1.7
51 | 1.7
52 |
53 |
54 |
55 | org.apache.maven.plugins
56 | maven-shade-plugin
57 | 3.2.0
58 |
59 |
60 | package
61 |
62 | shade
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/main/java/tk/netindev/drill/Drill.java:
--------------------------------------------------------------------------------
1 | package tk.netindev.drill;
2 |
3 | import org.apache.commons.cli.CommandLine;
4 | import org.apache.commons.cli.DefaultParser;
5 | import org.apache.commons.cli.Option;
6 | import org.apache.commons.cli.Options;
7 | import org.apache.commons.cli.ParseException;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import tk.netindev.drill.miner.Miner;
12 | import tk.netindev.drill.util.Misc;
13 |
14 | /**
15 | *
16 | * @author netindev
17 | *
18 | */
19 | public class Drill {
20 |
21 | private static final Logger logger = LoggerFactory
22 | .getLogger(Drill.class.getName());
23 | public static final double PACKAGE_VERSION = 0.10D;
24 |
25 | public static void main(String[] args) {
26 | if (args.length == 0) {
27 | logger.error(
28 | "Invalid arguments, please add to the arguments \"-help\".");
29 | return;
30 | }
31 | try {
32 | System.out.println("Drill cryptonight miner, written by netindev, V: "
33 | + PACKAGE_VERSION);
34 | final String system = System.getProperty("os.name").toLowerCase();
35 | if (!(system.indexOf("win") >= 0 || system.indexOf("nix") >= 0
36 | || system.indexOf("nux") >= 0 || system.indexOf("aix") >= 0)
37 | || !System.getProperty("sun.arch.data.model").equals("64")) {
38 | logger.error("Unfortunately, " + system
39 | + " isn't supported at this time.");
40 | return;
41 | }
42 | parseArgs(args);
43 | } catch (final Throwable e) {
44 | logger.error(e.getMessage());
45 | }
46 | }
47 |
48 | private static void parseArgs(String[] args) {
49 | final Options options = new Options();
50 | options.addOption(Option.builder("host").hasArg().required().build());
51 | options.addOption(Option.builder("user").hasArg().required().build());
52 | options.addOption(Option.builder("port").hasArg().required().build());
53 |
54 | options.addOption(Option.builder("pass").hasArg().build());
55 | options.addOption(Option.builder("thread").hasArg().build());
56 |
57 | options.addOption(Option.builder("help").build());
58 | try {
59 | final CommandLine parse = new DefaultParser().parse(options, args);
60 | if (parse.hasOption("help")) {
61 | logger.info("Arguments with * are optional.");
62 | logger.info(
63 | "java -jar drill.jar -host \"localhost\" -user \"netindev.8700k\" -port \"1000\" -pass* \"12345\" -thread* \"7\"");
64 | return;
65 | }
66 | final String host = parse.getOptionValue("host"),
67 | user = parse.getOptionValue("user"),
68 | port = parse.getOptionValue("port");
69 | final String pass = parse.hasOption("pass")
70 | ? parse.getOptionValue("pass")
71 | : "",
72 | thread = parse.hasOption("thread")
73 | ? parse.getOptionValue("thread")
74 | : String.valueOf(
75 | Runtime.getRuntime().availableProcessors() - 1);
76 | if (!Misc.isInteger(port)) {
77 | logger.error("The port isn't an integer");
78 | return;
79 | } else if (!Misc.isInteger(thread)) {
80 | logger.error("The thread isn't an integer");
81 | return;
82 | }
83 | new Miner(host, user, pass, Integer.parseInt(port),
84 | Integer.parseInt(thread)).start();
85 | } catch (final ParseException e) {
86 | logger.error(e.getMessage());
87 | logger.error("Correct use: java -jar scuti-lite.jar --help");
88 | } catch (final Exception e) {
89 | logger.error(e.getMessage());
90 | }
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/tk/netindev/drill/hasher/Hasher.java:
--------------------------------------------------------------------------------
1 | package tk.netindev.drill.hasher;
2 |
3 | import java.io.IOException;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | import tk.netindev.drill.util.Misc;
9 |
10 | /**
11 | *
12 | * @author netindev
13 | *
14 | */
15 | public class Hasher {
16 |
17 | private static final Logger logger = LoggerFactory
18 | .getLogger(Hasher.class.getName());
19 |
20 | public static native void slowHash(byte[] input, byte[] output);
21 |
22 | static {
23 | String library = null;
24 | final String system = System.getProperty("os.name").toLowerCase();
25 | if (system.indexOf("win") >= 0) {
26 | library = "/win/x64/cryptonight.dll";
27 | } else if (system.indexOf("nix") >= 0 || system.indexOf("nux") >= 0
28 | || system.indexOf("aix") >= 0) {
29 | library = "/unix/x64/libcryptonight.so";
30 | } else {
31 | logger.error("Couldn't find a dynamic-link library for your system.");
32 | }
33 | try {
34 | Misc.loadLibrary(library);
35 | } catch (final IOException e) {
36 | logger.error(e.getMessage());
37 | }
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/tk/netindev/drill/miner/Job.java:
--------------------------------------------------------------------------------
1 | package tk.netindev.drill.miner;
2 |
3 | /**
4 | *
5 | * @author netindev
6 | *
7 | */
8 | public class Job {
9 |
10 | private String id, jobId;
11 | private byte[] blob;
12 | private int target;
13 |
14 | public String getId() {
15 | return this.id;
16 | }
17 |
18 | public void setId(String id) {
19 | this.id = id;
20 | }
21 |
22 | public byte[] getBlob() {
23 | return this.blob;
24 | }
25 |
26 | public void setBlob(byte[] blob) {
27 | this.blob = blob;
28 | }
29 |
30 | public String getJobId() {
31 | return this.jobId;
32 | }
33 |
34 | public void setJobId(String jobId) {
35 | this.jobId = jobId;
36 | }
37 |
38 | public int getTarget() {
39 | return this.target;
40 | }
41 |
42 | public void setTarget(int target) {
43 | this.target = target;
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/src/main/java/tk/netindev/drill/miner/Miner.java:
--------------------------------------------------------------------------------
1 | package tk.netindev.drill.miner;
2 |
3 | import java.io.IOException;
4 | import java.io.PrintWriter;
5 | import java.net.Socket;
6 | import java.net.UnknownHostException;
7 | import java.util.HashSet;
8 | import java.util.Scanner;
9 | import java.util.Set;
10 | import java.util.concurrent.atomic.AtomicBoolean;
11 |
12 | import org.slf4j.Logger;
13 | import org.slf4j.LoggerFactory;
14 |
15 | import com.eclipsesource.json.JsonObject;
16 | import com.eclipsesource.json.JsonObject.Member;
17 |
18 | import tk.netindev.drill.Drill;
19 | import tk.netindev.drill.util.Hashrate;
20 | import tk.netindev.drill.util.Hex;
21 |
22 | /**
23 | *
24 | * @author netindev
25 | *
26 | */
27 | public class Miner {
28 |
29 | private static final Logger logger = LoggerFactory
30 | .getLogger(Miner.class.getName());
31 |
32 | private final String host, user, pass;
33 | private final int port, thread;
34 |
35 | private Socket socket;
36 | private PrintWriter printWriter;
37 | private Scanner scanner;
38 |
39 | protected final Hashrate hashrate = new Hashrate();
40 |
41 | private final Set set = new HashSet<>();
42 |
43 | public Miner(String host, String user, String pass, int port, int thread) {
44 | this.host = host;
45 | this.user = user;
46 | this.pass = pass;
47 | this.port = port;
48 | this.thread = thread;
49 | }
50 |
51 | private boolean connect() {
52 | try {
53 | this.socket = new Socket(this.host, this.port);
54 | this.printWriter = new PrintWriter(this.socket.getOutputStream());
55 | this.scanner = new Scanner(this.socket.getInputStream());
56 | this.socket.setTcpNoDelay(true);
57 | this.socket.setSoTimeout(1000 * 150 /* 2:30 mins */);
58 | final JsonObject params = new JsonObject(), doc = new JsonObject();
59 | params.add("login", this.user);
60 | params.add("pass", this.pass);
61 | params.add("agent", "drill/" + Drill.PACKAGE_VERSION);
62 |
63 | doc.add("jsonrpc", "2.0");
64 | doc.add("id", 1);
65 | doc.add("method", "login");
66 | doc.add("params", params);
67 | this.printWriter.print(doc.toString() + "\n");
68 | this.printWriter.flush();
69 | return true;
70 | } catch (final UnknownHostException e) {
71 | logger.error("Can't connect to: " + e.getMessage());
72 | return false;
73 | } catch (final IOException e) {
74 | logger.error(e.getMessage());
75 | return false;
76 | }
77 | }
78 |
79 | public void start() throws Exception {
80 | if (this.connect()) {
81 | logger.info("Connected to: " + this.host + ":" + this.port);
82 | while (this.scanner.hasNextLine()) {
83 | try {
84 | final String string = this.scanner.nextLine();
85 | final Job job = this.parseJob(string);
86 | if (job != null) {
87 | logger.info("New job received, diff: "
88 | + (Integer.MAX_VALUE / job.getTarget()) * 2);
89 | this.work(job);
90 | logger.info("Hashrate: "
91 | + String.format("%.2f", this.getHashrate()) + " h/s");
92 | }
93 | } catch (final Exception e) {
94 | logger.error(e.getMessage());
95 | break;
96 | }
97 | }
98 | for (final Thread thread : this.set) {
99 | thread.interrupt();
100 | }
101 | this.set.clear();
102 | logger.error("Disconnected from the pool");
103 | this.reconnect();
104 | } else {
105 | logger.error("Couldn't connect to the pool");
106 | this.reconnect();
107 | }
108 | }
109 |
110 | private Job parseJob(String string) {
111 | final Job job = new Job();
112 | final AtomicBoolean status = new AtomicBoolean(false),
113 | info = new AtomicBoolean(false);
114 | for (final Member member : JsonObject.readFrom(string)) {
115 | if (member.getName().equals("result")) {
116 | for (final Member resultTable : member.getValue().asObject()) {
117 | if (resultTable.getName().equals("id")) {
118 | job.setId(resultTable.getValue().asString());
119 | } else if (resultTable.getName().equals("job")) {
120 | for (final Member jobTable : resultTable.getValue()
121 | .asObject()) {
122 | if (jobTable.getName().equals("blob")) {
123 | job.setBlob(
124 | Hex.unhexlify(jobTable.getValue().asString()));
125 | } else if (jobTable.getName().equals("job_id")) {
126 | job.setJobId(jobTable.getValue().asString());
127 | } else if (jobTable.getName().equals("target")) {
128 | final byte[] target = Hex
129 | .unhexlify(jobTable.getValue().asString());
130 | job.setTarget(
131 | (((target[3] << 24) | ((target[2] & 255) << 16))
132 | | ((target[1] & 255) << 8))
133 | | (target[0] & 255));
134 | }
135 | }
136 | status.set(true);
137 | } else if (resultTable.getName().equals("status")) {
138 | if (resultTable.getValue().asString().equals("OK")
139 | && !status.get()) {
140 | logger.info("Result accepted by the pool!");
141 | info.set(true);
142 | }
143 | }
144 | }
145 | } else if (member.getName().equals("error")) {
146 | if (!member.getValue().isNull()) {
147 | for (final Member errorTable : member.getValue().asObject()) {
148 | if (errorTable.getName().equals("message")) {
149 | if (errorTable.getValue().asString()
150 | .equals("Unauthenticated")) {
151 | throw new RuntimeException("Unauthenticated");
152 | }
153 | logger.error(errorTable.getValue().asString());
154 | info.set(true);
155 | }
156 | }
157 | }
158 | } else if (member.getName().equals("params")) {
159 | for (final Member paramTable : member.getValue().asObject()) {
160 | if (paramTable.getName().equals("id")) {
161 | job.setId(paramTable.getValue().asString());
162 | } else if (paramTable.getName().equals("blob")) {
163 | job.setBlob(Hex.unhexlify(paramTable.getValue().asString()));
164 | } else if (paramTable.getName().equals("job_id")) {
165 | job.setJobId(paramTable.getValue().asString());
166 | } else if (paramTable.getName().equals("target")) {
167 | final byte[] target = Hex
168 | .unhexlify(paramTable.getValue().asString());
169 | job.setTarget((((target[3] << 24) | ((target[2] & 255) << 16))
170 | | ((target[1] & 255) << 8)) | (target[0] & 255));
171 | }
172 | }
173 | }
174 | }
175 | return info.get() ? null : job;
176 | }
177 |
178 | protected void send(Job job, byte[] nonce, byte[] result) {
179 | final JsonObject params = new JsonObject(), doc = new JsonObject();
180 | params.add("id", job.getId());
181 | params.add("job_id", job.getJobId());
182 | params.add("nonce", Hex.hexlify(nonce).toLowerCase());
183 | params.add("result", Hex.hexlify(result).toLowerCase());
184 |
185 | doc.add("id", 1);
186 | doc.add("jsonrpc", "2.0");
187 | doc.add("method", "submit");
188 | doc.add("params", params);
189 | this.printWriter.print(doc.toString() + "\n");
190 | this.printWriter.flush();
191 | }
192 |
193 | private void work(Job job) {
194 | // I didn't find a better way than this.
195 | for (final Thread thread : this.set) {
196 | thread.interrupt();
197 | }
198 | this.set.clear();
199 |
200 | for (int i = 0; i < this.thread; i++) {
201 | final Worker worker = new Worker(this, job, 100000 * i);
202 | worker.start();
203 | this.set.add(worker);
204 | }
205 | }
206 |
207 | private float getHashrate() {
208 | if (this.hashrate.size() < 10) {
209 | return 0.0F;
210 | } else {
211 | final long runningTime = System.currentTimeMillis()
212 | - this.hashrate.element();
213 | if (runningTime < 10) {
214 | return 0.0F;
215 | } else {
216 | return (float) (this.hashrate.size() / (runningTime * 0.001D));
217 | }
218 | }
219 | }
220 |
221 | private void reconnect() {
222 | try {
223 | logger.info("Reconnecting in 30 seconds");
224 | Thread.sleep(1000L * 30L);
225 | while (!this.connect()) {
226 | logger.error("Couldn't connect, trying to reconnect in 30 seconds");
227 | Thread.sleep(1000L * 30L);
228 | }
229 | this.start();
230 | } catch (final Exception e) {
231 | e.printStackTrace();
232 | }
233 | }
234 |
235 | }
236 |
--------------------------------------------------------------------------------
/src/main/java/tk/netindev/drill/miner/Worker.java:
--------------------------------------------------------------------------------
1 | package tk.netindev.drill.miner;
2 |
3 | import tk.netindev.drill.hasher.Hasher;
4 |
5 | /**
6 | *
7 | * @author netindev
8 | *
9 | */
10 | public class Worker extends Thread {
11 |
12 | private final Miner miner;
13 | private final Job job;
14 | private final int nonce;
15 |
16 | public Worker(Miner miner, Job job, int nonce) {
17 | this.miner = miner;
18 | this.job = job;
19 | this.nonce = nonce;
20 | }
21 |
22 | @Override
23 | public void run() {
24 | int nonce = this.nonce;
25 | final byte[] hash = new byte[32];
26 | final byte[] array = new byte[4];
27 | final byte[] blob = this.job.getBlob();
28 | final int target = this.job.getTarget();
29 | while (!interrupted()) {
30 | blob[39] = (byte) nonce;
31 | blob[40] = (byte) (nonce >> 8);
32 | blob[41] = (byte) (nonce >> 16);
33 | blob[42] = (byte) (nonce >> 24);
34 | Hasher.slowHash(blob, hash);
35 | final int difficulty = (((hash[31] << 24) | ((hash[30] & 255) << 16))
36 | | ((hash[29] & 255) << 8)) | (hash[28] & 255);
37 | if (difficulty >= 0 && difficulty <= target) {
38 | array[0] = (byte) nonce;
39 | array[1] = (byte) (nonce >> 8);
40 | array[2] = (byte) (nonce >> 16);
41 | array[3] = (byte) (nonce >> 24);
42 | this.miner.send(this.job, array, hash);
43 | }
44 | synchronized (this.miner.hashrate) {
45 | while (this.miner.hashrate.size() > 99
46 | && !this.miner.hashrate.isEmpty()) {
47 | this.miner.hashrate.pop();
48 | }
49 | }
50 | this.miner.hashrate.add(System.currentTimeMillis());
51 | nonce++;
52 | }
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/src/main/java/tk/netindev/drill/util/Hashrate.java:
--------------------------------------------------------------------------------
1 | package tk.netindev.drill.util;
2 |
3 | import java.util.ArrayDeque;
4 |
5 | /**
6 | *
7 | * @author netindev
8 | *
9 | */
10 | public class Hashrate extends ArrayDeque {
11 |
12 | private static final long serialVersionUID = -1940501882802741874L;
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/tk/netindev/drill/util/Hex.java:
--------------------------------------------------------------------------------
1 | package tk.netindev.drill.util;
2 |
3 | /**
4 | *
5 | * @author netindev
6 | *
7 | */
8 | public class Hex {
9 |
10 | private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
11 |
12 | public static int fromHexChar(char c) {
13 | if ((c >= '0') && (c <= '9')) {
14 | c -= 48;
15 | }
16 | if ((c >= 'A') && (c <= 'F')) {
17 | c = (char) (c - 'A' + 10);
18 | } else {
19 | c = (char) (c - 'a' + 10);
20 | }
21 | return c;
22 | }
23 |
24 | public static String hexlify(byte[] bytes) {
25 | final char[] hexChars = new char[bytes.length * 2];
26 | for (int j = 0; j < bytes.length; j++) {
27 | final int v = bytes[j] & 0xFF;
28 | hexChars[j * 2] = hexArray[v >>> 4];
29 | hexChars[j * 2 + 1] = hexArray[v & 0x0F];
30 | }
31 | final String ret = new String(hexChars);
32 | return ret;
33 | }
34 |
35 | public static byte[] unhexlify(String string) {
36 | final int length = string.length();
37 | if (length % 2 != 0) {
38 | throw new RuntimeException("Odd-length string");
39 | }
40 | final byte[] bytes = new byte[length / 2];
41 | for (int i = 0; i < length; i += 2) {
42 | final int top = Character.digit(string.charAt(i), 16);
43 | final int bot = Character.digit(string.charAt(i + 1), 16);
44 | if (top == -1 || bot == -1) {
45 | throw new RuntimeException("Non-hexadecimal digit found");
46 | }
47 | bytes[i / 2] = (byte) ((top << 4) + bot);
48 | }
49 | return bytes;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/tk/netindev/drill/util/Misc.java:
--------------------------------------------------------------------------------
1 | package tk.netindev.drill.util;
2 |
3 | import java.io.File;
4 | import java.io.FileOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 |
8 | /**
9 | *
10 | * @author netindev
11 | *
12 | */
13 | public class Misc {
14 |
15 | public static boolean isInteger(String string) {
16 | try {
17 | Integer.parseInt(string);
18 | return true;
19 | } catch (final Exception e) {
20 | return false;
21 | }
22 | }
23 |
24 | public static void loadLibrary(String name) throws IOException {
25 | final InputStream inputStream = Misc.class.getResourceAsStream(name);
26 | final byte[] buffer = new byte[1024];
27 | int read = -1;
28 | final File temp = File.createTempFile(name, "");
29 | final FileOutputStream outputStream = new FileOutputStream(temp);
30 | while ((read = inputStream.read(buffer)) != -1) {
31 | outputStream.write(buffer, 0, read);
32 | }
33 | outputStream.close();
34 | inputStream.close();
35 | System.load(temp.getAbsolutePath());
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/jni/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.6)
2 | project (cryptonight)
3 |
4 | set (HEADER_FILES
5 | algos.hpp
6 | c_blake256.h
7 | c_groestl.h
8 | c_jh.h
9 | c_keccak.h
10 | c_skein.h
11 | cryptonight.h
12 | cryptonight_aesni.h
13 | groestl_tables.h
14 | hash.h
15 | int-util.h
16 | skein_port.h
17 | soft_aes.hpp
18 | )
19 |
20 | set (SOURCE_FILES
21 | c_blake256.c
22 | c_groestl.c
23 | c_jh.c
24 | c_keccak.c
25 | c_skein.c
26 | cryptonight_common.cpp
27 | hasher.cpp
28 | )
29 |
30 | add_definitions(-D_CRT_SECURE_NO_WARNINGS -msse4.1 -maes)
31 |
32 | add_library(cryptonight SHARED
33 | ${HEADER_FILES}
34 | ${SOURCE_FILES})
--------------------------------------------------------------------------------
/src/main/jni/algos.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 |
6 | // define aeon settings
7 | constexpr size_t CRYPTONIGHT_LITE_MEMORY = 1 * 1024 * 1024;
8 | constexpr uint32_t CRYPTONIGHT_LITE_MASK = 0xFFFF0;
9 | constexpr uint32_t CRYPTONIGHT_LITE_ITER = 0x40000;
10 |
11 | constexpr size_t CRYPTONIGHT_MEMORY = 2 * 1024 * 1024;
12 | constexpr uint32_t CRYPTONIGHT_MASK = 0x1FFFF0;
13 | constexpr uint32_t CRYPTONIGHT_ITER = 0x80000;
14 |
15 | constexpr size_t CRYPTONIGHT_HEAVY_MEMORY = 4 * 1024 * 1024;
16 | constexpr uint32_t CRYPTONIGHT_HEAVY_MASK = 0x3FFFF0;
17 | constexpr uint32_t CRYPTONIGHT_HEAVY_ITER = 0x40000;
18 |
19 | constexpr uint32_t CRYPTONIGHT_MASARI_ITER = 0x40000;
20 |
21 | constexpr uint32_t CRYPTONIGHT_SUPERFAST_ITER = 0x20000;
22 |
23 | enum algo
24 | {
25 | invalid_algo = 0,
26 | cryptonight = 1,
27 | cryptonight_lite = 2,
28 | cryptonight_monero = 3,
29 | cryptonight_heavy = 4,
30 | cryptonight_aeon = 5,
31 | cryptonight_ipbc = 6, // equal to cryptonight_aeon with a small tweak in the miner code
32 | cryptonight_stellite = 7, //equal to cryptonight_monero but with one tiny change
33 | cryptonight_masari = 8, //equal to cryptonight_monero but with less iterations, used by masari
34 | cryptonight_haven = 9, // equal to cryptonight_heavy with a small tweak
35 | cryptonight_bittube2 = 10, // derived from cryptonight_heavy with own aes-round implementation and minor other tweaks
36 | cryptonight_monero_v8 = 11,
37 | cryptonight_superfast = 12
38 | };
39 |
40 | template
41 | inline constexpr size_t cn_select_memory() { return 0; }
42 |
43 | template<>
44 | inline constexpr size_t cn_select_memory<1>() { return CRYPTONIGHT_MEMORY; }
45 |
46 | template<>
47 | inline constexpr size_t cn_select_memory<2>() { return CRYPTONIGHT_LITE_MEMORY; }
48 |
49 | template<>
50 | inline constexpr size_t cn_select_memory<3>() { return CRYPTONIGHT_MEMORY; }
51 |
52 | template<>
53 | inline constexpr size_t cn_select_memory<11>() { return CRYPTONIGHT_MEMORY; }
54 |
55 | template<>
56 | inline constexpr size_t cn_select_memory<4>() { return CRYPTONIGHT_HEAVY_MEMORY; }
57 |
58 | template<>
59 | inline constexpr size_t cn_select_memory<5>() { return CRYPTONIGHT_LITE_MEMORY; }
60 |
61 | template<>
62 | inline constexpr size_t cn_select_memory<6>() { return CRYPTONIGHT_LITE_MEMORY; }
63 |
64 | template<>
65 | inline constexpr size_t cn_select_memory<7>() { return CRYPTONIGHT_MEMORY; }
66 |
67 | template<>
68 | inline constexpr size_t cn_select_memory<8>() { return CRYPTONIGHT_MEMORY; }
69 |
70 | template<>
71 | inline constexpr size_t cn_select_memory<9>() { return CRYPTONIGHT_HEAVY_MEMORY; }
72 |
73 | template<>
74 | inline constexpr size_t cn_select_memory<10>() { return CRYPTONIGHT_HEAVY_MEMORY; }
75 |
76 | template<>
77 | inline constexpr size_t cn_select_memory<12>() { return CRYPTONIGHT_MEMORY; }
78 |
79 | inline size_t cn_select_memory(algo algo)
80 | {
81 | switch (algo)
82 | {
83 | case cryptonight_stellite:
84 | case cryptonight_monero:
85 | case cryptonight_monero_v8:
86 | case cryptonight_masari:
87 | case cryptonight:
88 | case cryptonight_superfast:
89 | return CRYPTONIGHT_MEMORY;
90 | case cryptonight_ipbc:
91 | case cryptonight_aeon:
92 | case cryptonight_lite:
93 | return CRYPTONIGHT_LITE_MEMORY;
94 | case cryptonight_bittube2:
95 | case cryptonight_haven:
96 | case cryptonight_heavy:
97 | return CRYPTONIGHT_HEAVY_MEMORY;
98 | default:
99 | return 0;
100 | }
101 | }
102 |
103 | template
104 | inline constexpr uint32_t cn_select_mask() { return 0; }
105 |
106 | template<>
107 | inline constexpr uint32_t cn_select_mask<1>() { return CRYPTONIGHT_MASK; }
108 |
109 | template<>
110 | inline constexpr uint32_t cn_select_mask<2>() { return CRYPTONIGHT_LITE_MASK; }
111 |
112 | template<>
113 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_MASK; }
114 |
115 | template<>
116 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_MASK; }
117 |
118 | template<>
119 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_HEAVY_MASK; }
120 |
121 | template<>
122 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_LITE_MASK; }
123 |
124 | template<>
125 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_LITE_MASK; }
126 |
127 | template<>
128 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_MASK; }
129 |
130 | template<>
131 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_MASK; }
132 |
133 | template<>
134 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_HEAVY_MASK; }
135 |
136 | template<>
137 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_HEAVY_MASK; }
138 |
139 | template<>
140 | inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_MASK; }
141 |
142 | inline size_t cn_select_mask(algo algo)
143 | {
144 | switch (algo)
145 | {
146 | case cryptonight_stellite:
147 | case cryptonight_monero:
148 | case cryptonight_monero_v8:
149 | case cryptonight_masari:
150 | case cryptonight:
151 | case cryptonight_superfast:
152 | return CRYPTONIGHT_MASK;
153 | case cryptonight_ipbc:
154 | case cryptonight_aeon:
155 | case cryptonight_lite:
156 | return CRYPTONIGHT_LITE_MASK;
157 | case cryptonight_bittube2:
158 | case cryptonight_haven:
159 | case cryptonight_heavy:
160 | return CRYPTONIGHT_HEAVY_MASK;
161 | default:
162 | return 0;
163 | }
164 | }
165 |
166 | template
167 | inline constexpr uint32_t cn_select_iter() { return 0; }
168 |
169 | template<>
170 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; }
171 |
172 | template<>
173 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_LITE_ITER; }
174 |
175 | template<>
176 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; }
177 |
178 | template<>
179 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; }
180 |
181 | template<>
182 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HEAVY_ITER; }
183 |
184 | template<>
185 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_LITE_ITER; }
186 |
187 | template<>
188 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_LITE_ITER; }
189 |
190 | template<>
191 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; }
192 |
193 | template<>
194 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_MASARI_ITER; }
195 |
196 | template<>
197 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HEAVY_ITER; }
198 |
199 | template<>
200 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HEAVY_ITER; }
201 |
202 | template<>
203 | inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_SUPERFAST_ITER; }
204 |
205 | inline size_t cn_select_iter(algo algo)
206 | {
207 | switch (algo)
208 | {
209 | case cryptonight_stellite:
210 | case cryptonight_monero:
211 | case cryptonight_monero_v8:
212 | case cryptonight:
213 | return CRYPTONIGHT_ITER;
214 | case cryptonight_ipbc:
215 | case cryptonight_aeon:
216 | case cryptonight_lite:
217 | return CRYPTONIGHT_LITE_ITER;
218 | case cryptonight_bittube2:
219 | case cryptonight_haven:
220 | case cryptonight_heavy:
221 | return CRYPTONIGHT_HEAVY_ITER;
222 | case cryptonight_masari:
223 | return CRYPTONIGHT_MASARI_ITER;
224 | case cryptonight_superfast:
225 | return CRYPTONIGHT_SUPERFAST_ITER;
226 | default:
227 | return 0;
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/src/main/jni/c_blake256.c:
--------------------------------------------------------------------------------
1 | /*
2 | * The blake256_* and blake224_* functions are largely copied from
3 | * blake256_light.c and blake224_light.c from the BLAKE website:
4 | *
5 | * http://131002.net/blake/
6 | *
7 | * The hmac_* functions implement HMAC-BLAKE-256 and HMAC-BLAKE-224.
8 | * HMAC is specified by RFC 2104.
9 | */
10 |
11 | #include
12 | #include
13 | #include
14 | #include "c_blake256.h"
15 |
16 | #define U8TO32(p) \
17 | (((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \
18 | ((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]) ))
19 | #define U32TO8(p, v) \
20 | (p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \
21 | (p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) );
22 |
23 | const uint8_t sigma[][16] = {
24 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
25 | {14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3},
26 | {11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4},
27 | { 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8},
28 | { 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13},
29 | { 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9},
30 | {12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11},
31 | {13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10},
32 | { 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5},
33 | {10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13, 0},
34 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
35 | {14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3},
36 | {11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4},
37 | { 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8}
38 | };
39 |
40 | const uint32_t cst[16] = {
41 | 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
42 | 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
43 | 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
44 | 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917
45 | };
46 |
47 | static const uint8_t padding[] = {
48 | 0x80,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,
49 | 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
50 | };
51 |
52 |
53 | void blake256_compress(state *S, const uint8_t *block) {
54 | uint32_t v[16], m[16], i;
55 |
56 | #define ROT(x,n) (((x)<<(32-n))|((x)>>(n)))
57 | #define G(a,b,c,d,e) \
58 | v[a] += (m[sigma[i][e]] ^ cst[sigma[i][e+1]]) + v[b]; \
59 | v[d] = ROT(v[d] ^ v[a],16); \
60 | v[c] += v[d]; \
61 | v[b] = ROT(v[b] ^ v[c],12); \
62 | v[a] += (m[sigma[i][e+1]] ^ cst[sigma[i][e]])+v[b]; \
63 | v[d] = ROT(v[d] ^ v[a], 8); \
64 | v[c] += v[d]; \
65 | v[b] = ROT(v[b] ^ v[c], 7);
66 |
67 | for (i = 0; i < 16; ++i) m[i] = U8TO32(block + i * 4);
68 | for (i = 0; i < 8; ++i) v[i] = S->h[i];
69 | v[ 8] = S->s[0] ^ 0x243F6A88;
70 | v[ 9] = S->s[1] ^ 0x85A308D3;
71 | v[10] = S->s[2] ^ 0x13198A2E;
72 | v[11] = S->s[3] ^ 0x03707344;
73 | v[12] = 0xA4093822;
74 | v[13] = 0x299F31D0;
75 | v[14] = 0x082EFA98;
76 | v[15] = 0xEC4E6C89;
77 |
78 | if (S->nullt == 0) {
79 | v[12] ^= S->t[0];
80 | v[13] ^= S->t[0];
81 | v[14] ^= S->t[1];
82 | v[15] ^= S->t[1];
83 | }
84 |
85 | for (i = 0; i < 14; ++i) {
86 | G(0, 4, 8, 12, 0);
87 | G(1, 5, 9, 13, 2);
88 | G(2, 6, 10, 14, 4);
89 | G(3, 7, 11, 15, 6);
90 | G(3, 4, 9, 14, 14);
91 | G(2, 7, 8, 13, 12);
92 | G(0, 5, 10, 15, 8);
93 | G(1, 6, 11, 12, 10);
94 | }
95 |
96 | for (i = 0; i < 16; ++i) S->h[i % 8] ^= v[i];
97 | for (i = 0; i < 8; ++i) S->h[i] ^= S->s[i % 4];
98 | }
99 |
100 | void blake256_init(state *S) {
101 | S->h[0] = 0x6A09E667;
102 | S->h[1] = 0xBB67AE85;
103 | S->h[2] = 0x3C6EF372;
104 | S->h[3] = 0xA54FF53A;
105 | S->h[4] = 0x510E527F;
106 | S->h[5] = 0x9B05688C;
107 | S->h[6] = 0x1F83D9AB;
108 | S->h[7] = 0x5BE0CD19;
109 | S->t[0] = S->t[1] = S->buflen = S->nullt = 0;
110 | S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0;
111 | }
112 |
113 | void blake224_init(state *S) {
114 | S->h[0] = 0xC1059ED8;
115 | S->h[1] = 0x367CD507;
116 | S->h[2] = 0x3070DD17;
117 | S->h[3] = 0xF70E5939;
118 | S->h[4] = 0xFFC00B31;
119 | S->h[5] = 0x68581511;
120 | S->h[6] = 0x64F98FA7;
121 | S->h[7] = 0xBEFA4FA4;
122 | S->t[0] = S->t[1] = S->buflen = S->nullt = 0;
123 | S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0;
124 | }
125 |
126 | // datalen = number of bits
127 | void blake256_update(state *S, const uint8_t *data, uint32_t datalen) {
128 | int left = S->buflen >> 3;
129 | int fill = 64 - left;
130 |
131 | if (left && (((datalen >> 3) & 0x3F) >= (unsigned) fill)) {
132 | memcpy((void *) (S->buf + left), (void *) data, fill);
133 | S->t[0] += 512;
134 | if (S->t[0] == 0) S->t[1]++;
135 | blake256_compress(S, S->buf);
136 | data += fill;
137 | datalen -= (fill << 3);
138 | left = 0;
139 | }
140 |
141 | while (datalen >= 512) {
142 | S->t[0] += 512;
143 | if (S->t[0] == 0) S->t[1]++;
144 | blake256_compress(S, data);
145 | data += 64;
146 | datalen -= 512;
147 | }
148 |
149 | if (datalen > 0) {
150 | memcpy((void *) (S->buf + left), (void *) data, datalen >> 3);
151 | S->buflen = (left << 3) + datalen;
152 | } else {
153 | S->buflen = 0;
154 | }
155 | }
156 |
157 | // datalen = number of bits
158 | void blake224_update(state *S, const uint8_t *data, uint32_t datalen) {
159 | blake256_update(S, data, datalen);
160 | }
161 |
162 | void blake256_final_h(state *S, uint8_t *digest, uint8_t pa, uint8_t pb) {
163 | uint8_t msglen[8];
164 | uint32_t lo = S->t[0] + S->buflen, hi = S->t[1];
165 | if (lo < (unsigned) S->buflen) hi++;
166 | U32TO8(msglen + 0, hi);
167 | U32TO8(msglen + 4, lo);
168 |
169 | if (S->buflen == 440) { /* one padding byte */
170 | S->t[0] -= 8;
171 | blake256_update(S, &pa, 8);
172 | } else {
173 | if (S->buflen < 440) { /* enough space to fill the block */
174 | if (S->buflen == 0) S->nullt = 1;
175 | S->t[0] -= 440 - S->buflen;
176 | blake256_update(S, padding, 440 - S->buflen);
177 | } else { /* need 2 compressions */
178 | S->t[0] -= 512 - S->buflen;
179 | blake256_update(S, padding, 512 - S->buflen);
180 | S->t[0] -= 440;
181 | blake256_update(S, padding + 1, 440);
182 | S->nullt = 1;
183 | }
184 | blake256_update(S, &pb, 8);
185 | S->t[0] -= 8;
186 | }
187 | S->t[0] -= 64;
188 | blake256_update(S, msglen, 64);
189 |
190 | U32TO8(digest + 0, S->h[0]);
191 | U32TO8(digest + 4, S->h[1]);
192 | U32TO8(digest + 8, S->h[2]);
193 | U32TO8(digest + 12, S->h[3]);
194 | U32TO8(digest + 16, S->h[4]);
195 | U32TO8(digest + 20, S->h[5]);
196 | U32TO8(digest + 24, S->h[6]);
197 | U32TO8(digest + 28, S->h[7]);
198 | }
199 |
200 | void blake256_final(state *S, uint8_t *digest) {
201 | blake256_final_h(S, digest, 0x81, 0x01);
202 | }
203 |
204 | void blake224_final(state *S, uint8_t *digest) {
205 | blake256_final_h(S, digest, 0x80, 0x00);
206 | }
207 |
208 | // inlen = number of bytes
209 | void blake256_hash(uint8_t *out, const uint8_t *in, uint32_t inlen) {
210 | state S;
211 | blake256_init(&S);
212 | blake256_update(&S, in, inlen * 8);
213 | blake256_final(&S, out);
214 | }
215 |
216 | // inlen = number of bytes
217 | void blake224_hash(uint8_t *out, const uint8_t *in, uint32_t inlen) {
218 | state S;
219 | blake224_init(&S);
220 | blake224_update(&S, in, inlen * 8);
221 | blake224_final(&S, out);
222 | }
223 |
224 | // keylen = number of bytes
225 | void hmac_blake256_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) {
226 | const uint8_t *key = _key;
227 | uint8_t keyhash[32];
228 | uint8_t pad[64];
229 | uint64_t i;
230 |
231 | if (keylen > 64) {
232 | blake256_hash(keyhash, key, keylen);
233 | key = keyhash;
234 | keylen = 32;
235 | }
236 |
237 | blake256_init(&S->inner);
238 | memset(pad, 0x36, 64);
239 | for (i = 0; i < keylen; ++i) {
240 | pad[i] ^= key[i];
241 | }
242 | blake256_update(&S->inner, pad, 512);
243 |
244 | blake256_init(&S->outer);
245 | memset(pad, 0x5c, 64);
246 | for (i = 0; i < keylen; ++i) {
247 | pad[i] ^= key[i];
248 | }
249 | blake256_update(&S->outer, pad, 512);
250 |
251 | memset(keyhash, 0, 32);
252 | }
253 |
254 | // keylen = number of bytes
255 | void hmac_blake224_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) {
256 | const uint8_t *key = _key;
257 | uint8_t keyhash[32];
258 | uint8_t pad[64];
259 | uint64_t i;
260 |
261 | if (keylen > 64) {
262 | blake256_hash(keyhash, key, keylen);
263 | key = keyhash;
264 | keylen = 28;
265 | }
266 |
267 | blake224_init(&S->inner);
268 | memset(pad, 0x36, 64);
269 | for (i = 0; i < keylen; ++i) {
270 | pad[i] ^= key[i];
271 | }
272 | blake224_update(&S->inner, pad, 512);
273 |
274 | blake224_init(&S->outer);
275 | memset(pad, 0x5c, 64);
276 | for (i = 0; i < keylen; ++i) {
277 | pad[i] ^= key[i];
278 | }
279 | blake224_update(&S->outer, pad, 512);
280 |
281 | memset(keyhash, 0, 32);
282 | }
283 |
284 | // datalen = number of bits
285 | void hmac_blake256_update(hmac_state *S, const uint8_t *data, uint32_t datalen) {
286 | // update the inner state
287 | blake256_update(&S->inner, data, datalen);
288 | }
289 |
290 | // datalen = number of bits
291 | void hmac_blake224_update(hmac_state *S, const uint8_t *data, uint32_t datalen) {
292 | // update the inner state
293 | blake224_update(&S->inner, data, datalen);
294 | }
295 |
296 | void hmac_blake256_final(hmac_state *S, uint8_t *digest) {
297 | uint8_t ihash[32];
298 | blake256_final(&S->inner, ihash);
299 | blake256_update(&S->outer, ihash, 256);
300 | blake256_final(&S->outer, digest);
301 | memset(ihash, 0, 32);
302 | }
303 |
304 | void hmac_blake224_final(hmac_state *S, uint8_t *digest) {
305 | uint8_t ihash[32];
306 | blake224_final(&S->inner, ihash);
307 | blake224_update(&S->outer, ihash, 224);
308 | blake224_final(&S->outer, digest);
309 | memset(ihash, 0, 32);
310 | }
311 |
312 | // keylen = number of bytes; inlen = number of bytes
313 | void hmac_blake256_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint32_t inlen) {
314 | hmac_state S;
315 | hmac_blake256_init(&S, key, keylen);
316 | hmac_blake256_update(&S, in, inlen * 8);
317 | hmac_blake256_final(&S, out);
318 | }
319 |
320 | // keylen = number of bytes; inlen = number of bytes
321 | void hmac_blake224_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint32_t inlen) {
322 | hmac_state S;
323 | hmac_blake224_init(&S, key, keylen);
324 | hmac_blake224_update(&S, in, inlen * 8);
325 | hmac_blake224_final(&S, out);
326 | }
327 |
--------------------------------------------------------------------------------
/src/main/jni/c_blake256.h:
--------------------------------------------------------------------------------
1 | #ifndef _BLAKE256_H_
2 | #define _BLAKE256_H_
3 |
4 | #include
5 |
6 | typedef struct {
7 | uint32_t h[8], s[4], t[2];
8 | int buflen, nullt;
9 | uint8_t buf[64];
10 | } state;
11 |
12 | typedef struct {
13 | state inner;
14 | state outer;
15 | } hmac_state;
16 |
17 | void blake256_init(state *);
18 | void blake224_init(state *);
19 |
20 | void blake256_update(state *, const uint8_t *, uint32_t);
21 | void blake224_update(state *, const uint8_t *, uint32_t);
22 |
23 | void blake256_final(state *, uint8_t *);
24 | void blake224_final(state *, uint8_t *);
25 |
26 | void blake256_hash(uint8_t *, const uint8_t *, uint32_t);
27 | void blake224_hash(uint8_t *, const uint8_t *, uint32_t);
28 |
29 | /* HMAC functions: */
30 |
31 | void hmac_blake256_init(hmac_state *, const uint8_t *, uint64_t);
32 | void hmac_blake224_init(hmac_state *, const uint8_t *, uint64_t);
33 |
34 | void hmac_blake256_update(hmac_state *, const uint8_t *, uint32_t);
35 | void hmac_blake224_update(hmac_state *, const uint8_t *, uint32_t);
36 |
37 | void hmac_blake256_final(hmac_state *, uint8_t *);
38 | void hmac_blake224_final(hmac_state *, uint8_t *);
39 |
40 | void hmac_blake256_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint32_t);
41 | void hmac_blake224_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint32_t);
42 |
43 | #endif /* _BLAKE256_H_ */
44 |
--------------------------------------------------------------------------------
/src/main/jni/c_groestl.c:
--------------------------------------------------------------------------------
1 | /* hash.c April 2012
2 | * Groestl ANSI C code optimised for 32-bit machines
3 | * Author: Thomas Krinninger
4 | *
5 | * This work is based on the implementation of
6 | * Soeren S. Thomsen and Krystian Matusiewicz
7 | *
8 | *
9 | */
10 |
11 | #include "c_groestl.h"
12 | #include "groestl_tables.h"
13 |
14 | #define P_TYPE 0
15 | #define Q_TYPE 1
16 |
17 | const uint8_t shift_Values[2][8] = {{0,1,2,3,4,5,6,7},{1,3,5,7,0,2,4,6}};
18 |
19 | const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6};
20 |
21 |
22 | #define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \
23 | v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \
24 | v1 = temp_var;}
25 |
26 |
27 | #define COLUMN(x,y,i,c0,c1,c2,c3,c4,c5,c6,c7,tv1,tv2,tu,tl,t) \
28 | tu = T[2*(uint32_t)x[4*c0+0]]; \
29 | tl = T[2*(uint32_t)x[4*c0+0]+1]; \
30 | tv1 = T[2*(uint32_t)x[4*c1+1]]; \
31 | tv2 = T[2*(uint32_t)x[4*c1+1]+1]; \
32 | ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \
33 | tu ^= tv1; \
34 | tl ^= tv2; \
35 | tv1 = T[2*(uint32_t)x[4*c2+2]]; \
36 | tv2 = T[2*(uint32_t)x[4*c2+2]+1]; \
37 | ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \
38 | tu ^= tv1; \
39 | tl ^= tv2; \
40 | tv1 = T[2*(uint32_t)x[4*c3+3]]; \
41 | tv2 = T[2*(uint32_t)x[4*c3+3]+1]; \
42 | ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \
43 | tu ^= tv1; \
44 | tl ^= tv2; \
45 | tl ^= T[2*(uint32_t)x[4*c4+0]]; \
46 | tu ^= T[2*(uint32_t)x[4*c4+0]+1]; \
47 | tv1 = T[2*(uint32_t)x[4*c5+1]]; \
48 | tv2 = T[2*(uint32_t)x[4*c5+1]+1]; \
49 | ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \
50 | tl ^= tv1; \
51 | tu ^= tv2; \
52 | tv1 = T[2*(uint32_t)x[4*c6+2]]; \
53 | tv2 = T[2*(uint32_t)x[4*c6+2]+1]; \
54 | ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \
55 | tl ^= tv1; \
56 | tu ^= tv2; \
57 | tv1 = T[2*(uint32_t)x[4*c7+3]]; \
58 | tv2 = T[2*(uint32_t)x[4*c7+3]+1]; \
59 | ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \
60 | tl ^= tv1; \
61 | tu ^= tv2; \
62 | y[i] = tu; \
63 | y[i+1] = tl;
64 |
65 |
66 | /* compute one round of P (short variants) */
67 | static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) {
68 | uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
69 | uint32_t* x32 = (uint32_t*)x;
70 | x32[ 0] ^= 0x00000000^r;
71 | x32[ 2] ^= 0x00000010^r;
72 | x32[ 4] ^= 0x00000020^r;
73 | x32[ 6] ^= 0x00000030^r;
74 | x32[ 8] ^= 0x00000040^r;
75 | x32[10] ^= 0x00000050^r;
76 | x32[12] ^= 0x00000060^r;
77 | x32[14] ^= 0x00000070^r;
78 | COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
79 | COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
80 | COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
81 | COLUMN(x,y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
82 | COLUMN(x,y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
83 | COLUMN(x,y,10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
84 | COLUMN(x,y,12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
85 | COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
86 | }
87 |
88 | /* compute one round of Q (short variants) */
89 | static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) {
90 | uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
91 | uint32_t* x32 = (uint32_t*)x;
92 | x32[ 0] = ~x32[ 0];
93 | x32[ 1] ^= 0xffffffff^r;
94 | x32[ 2] = ~x32[ 2];
95 | x32[ 3] ^= 0xefffffff^r;
96 | x32[ 4] = ~x32[ 4];
97 | x32[ 5] ^= 0xdfffffff^r;
98 | x32[ 6] = ~x32[ 6];
99 | x32[ 7] ^= 0xcfffffff^r;
100 | x32[ 8] = ~x32[ 8];
101 | x32[ 9] ^= 0xbfffffff^r;
102 | x32[10] = ~x32[10];
103 | x32[11] ^= 0xafffffff^r;
104 | x32[12] = ~x32[12];
105 | x32[13] ^= 0x9fffffff^r;
106 | x32[14] = ~x32[14];
107 | x32[15] ^= 0x8fffffff^r;
108 | COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
109 | COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
110 | COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
111 | COLUMN(x,y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
112 | COLUMN(x,y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
113 | COLUMN(x,y,10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
114 | COLUMN(x,y,12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
115 | COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
116 | }
117 |
118 | /* compute compression function (short variants) */
119 | static void F512(uint32_t *h, const uint32_t *m) {
120 | int i;
121 | uint32_t Ptmp[2*COLS512];
122 | uint32_t Qtmp[2*COLS512];
123 | uint32_t y[2*COLS512];
124 | uint32_t z[2*COLS512];
125 |
126 | for (i = 0; i < 2*COLS512; i++) {
127 | z[i] = m[i];
128 | Ptmp[i] = h[i]^m[i];
129 | }
130 |
131 | /* compute Q(m) */
132 | RND512Q((uint8_t*)z, y, 0x00000000);
133 | RND512Q((uint8_t*)y, z, 0x01000000);
134 | RND512Q((uint8_t*)z, y, 0x02000000);
135 | RND512Q((uint8_t*)y, z, 0x03000000);
136 | RND512Q((uint8_t*)z, y, 0x04000000);
137 | RND512Q((uint8_t*)y, z, 0x05000000);
138 | RND512Q((uint8_t*)z, y, 0x06000000);
139 | RND512Q((uint8_t*)y, z, 0x07000000);
140 | RND512Q((uint8_t*)z, y, 0x08000000);
141 | RND512Q((uint8_t*)y, Qtmp, 0x09000000);
142 |
143 | /* compute P(h+m) */
144 | RND512P((uint8_t*)Ptmp, y, 0x00000000);
145 | RND512P((uint8_t*)y, z, 0x00000001);
146 | RND512P((uint8_t*)z, y, 0x00000002);
147 | RND512P((uint8_t*)y, z, 0x00000003);
148 | RND512P((uint8_t*)z, y, 0x00000004);
149 | RND512P((uint8_t*)y, z, 0x00000005);
150 | RND512P((uint8_t*)z, y, 0x00000006);
151 | RND512P((uint8_t*)y, z, 0x00000007);
152 | RND512P((uint8_t*)z, y, 0x00000008);
153 | RND512P((uint8_t*)y, Ptmp, 0x00000009);
154 |
155 | /* compute P(h+m) + Q(m) + h */
156 | for (i = 0; i < 2*COLS512; i++) {
157 | h[i] ^= Ptmp[i]^Qtmp[i];
158 | }
159 | }
160 |
161 |
162 | /* digest up to msglen bytes of input (full blocks only) */
163 | static void Transform(groestlHashState *ctx,
164 | const uint8_t *input,
165 | int msglen) {
166 |
167 | /* digest message, one block at a time */
168 | for (; msglen >= SIZE512;
169 | msglen -= SIZE512, input += SIZE512) {
170 | F512(ctx->chaining,(uint32_t*)input);
171 |
172 | /* increment block counter */
173 | ctx->block_counter1++;
174 | if (ctx->block_counter1 == 0) ctx->block_counter2++;
175 | }
176 | }
177 |
178 | /* given state h, do h <- P(h)+h */
179 | static void OutputTransformation(groestlHashState *ctx) {
180 | int j;
181 | uint32_t temp[2*COLS512];
182 | uint32_t y[2*COLS512];
183 | uint32_t z[2*COLS512];
184 |
185 |
186 |
187 | for (j = 0; j < 2*COLS512; j++) {
188 | temp[j] = ctx->chaining[j];
189 | }
190 | RND512P((uint8_t*)temp, y, 0x00000000);
191 | RND512P((uint8_t*)y, z, 0x00000001);
192 | RND512P((uint8_t*)z, y, 0x00000002);
193 | RND512P((uint8_t*)y, z, 0x00000003);
194 | RND512P((uint8_t*)z, y, 0x00000004);
195 | RND512P((uint8_t*)y, z, 0x00000005);
196 | RND512P((uint8_t*)z, y, 0x00000006);
197 | RND512P((uint8_t*)y, z, 0x00000007);
198 | RND512P((uint8_t*)z, y, 0x00000008);
199 | RND512P((uint8_t*)y, temp, 0x00000009);
200 | for (j = 0; j < 2*COLS512; j++) {
201 | ctx->chaining[j] ^= temp[j];
202 | }
203 | }
204 |
205 | /* initialise context */
206 | static void Init(groestlHashState* ctx) {
207 | int i = 0;
208 | /* allocate memory for state and data buffer */
209 |
210 | for(;i<(SIZE512/sizeof(uint32_t));i++)
211 | {
212 | ctx->chaining[i] = 0;
213 | }
214 |
215 | /* set initial value */
216 | ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN);
217 |
218 | /* set other variables */
219 | ctx->buf_ptr = 0;
220 | ctx->block_counter1 = 0;
221 | ctx->block_counter2 = 0;
222 | ctx->bits_in_last_byte = 0;
223 | }
224 |
225 | /* update state with databitlen bits of input */
226 | static void Update(groestlHashState* ctx,
227 | const BitSequence* input,
228 | DataLength databitlen) {
229 | int index = 0;
230 | int msglen = (int)(databitlen/8);
231 | int rem = (int)(databitlen%8);
232 |
233 | /* if the buffer contains data that has not yet been digested, first
234 | add data to buffer until full */
235 | if (ctx->buf_ptr) {
236 | while (ctx->buf_ptr < SIZE512 && index < msglen) {
237 | ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
238 | }
239 | if (ctx->buf_ptr < SIZE512) {
240 | /* buffer still not full, return */
241 | if (rem) {
242 | ctx->bits_in_last_byte = rem;
243 | ctx->buffer[(int)ctx->buf_ptr++] = input[index];
244 | }
245 | return;
246 | }
247 |
248 | /* digest buffer */
249 | ctx->buf_ptr = 0;
250 | Transform(ctx, ctx->buffer, SIZE512);
251 | }
252 |
253 | /* digest bulk of message */
254 | Transform(ctx, input+index, msglen-index);
255 | index += ((msglen-index)/SIZE512)*SIZE512;
256 |
257 | /* store remaining data in buffer */
258 | while (index < msglen) {
259 | ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
260 | }
261 |
262 | /* if non-integral number of bytes have been supplied, store
263 | remaining bits in last byte, together with information about
264 | number of bits */
265 | if (rem) {
266 | ctx->bits_in_last_byte = rem;
267 | ctx->buffer[(int)ctx->buf_ptr++] = input[index];
268 | }
269 | }
270 |
271 | #define BILB ctx->bits_in_last_byte
272 |
273 | /* finalise: process remaining data (including padding), perform
274 | output transformation, and write hash result to 'output' */
275 | static void Final(groestlHashState* ctx,
276 | BitSequence* output) {
277 | int i, j = 0, hashbytelen = HASH_BIT_LEN/8;
278 | uint8_t *s = (BitSequence*)ctx->chaining;
279 |
280 | /* pad with '1'-bit and first few '0'-bits */
281 | if (BILB) {
282 | ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB);
284 | BILB = 0;
285 | }
286 | else ctx->buffer[(int)ctx->buf_ptr++] = 0x80;
287 |
288 | /* pad with '0'-bits */
289 | if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {
290 | /* padding requires two blocks */
291 | while (ctx->buf_ptr < SIZE512) {
292 | ctx->buffer[(int)ctx->buf_ptr++] = 0;
293 | }
294 | /* digest first padding block */
295 | Transform(ctx, ctx->buffer, SIZE512);
296 | ctx->buf_ptr = 0;
297 | }
298 | while (ctx->buf_ptr < SIZE512-LENGTHFIELDLEN) {
299 | ctx->buffer[(int)ctx->buf_ptr++] = 0;
300 | }
301 |
302 | /* length padding */
303 | ctx->block_counter1++;
304 | if (ctx->block_counter1 == 0) ctx->block_counter2++;
305 | ctx->buf_ptr = SIZE512;
306 |
307 | while (ctx->buf_ptr > SIZE512-(int)sizeof(uint32_t)) {
308 | ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1;
309 | ctx->block_counter1 >>= 8;
310 | }
311 | while (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {
312 | ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2;
313 | ctx->block_counter2 >>= 8;
314 | }
315 | /* digest final padding block */
316 | Transform(ctx, ctx->buffer, SIZE512);
317 | /* perform output transformation */
318 | OutputTransformation(ctx);
319 |
320 | /* store hash result in output */
321 | for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) {
322 | output[j] = s[i];
323 | }
324 |
325 | /* zeroise relevant variables and deallocate memory */
326 | for (i = 0; i < COLS512; i++) {
327 | ctx->chaining[i] = 0;
328 | }
329 | for (i = 0; i < SIZE512; i++) {
330 | ctx->buffer[i] = 0;
331 | }
332 | }
333 |
334 | /* hash bit sequence */
335 | void groestl(const BitSequence* data,
336 | DataLength databitlen,
337 | BitSequence* hashval) {
338 |
339 | groestlHashState context;
340 |
341 | /* initialise */
342 | Init(&context);
343 |
344 |
345 | /* process message */
346 | Update(&context, data, databitlen);
347 |
348 | /* finalise */
349 | Final(&context, hashval);
350 | }
351 | /*
352 | static int crypto_hash(unsigned char *out,
353 | const unsigned char *in,
354 | unsigned long long len)
355 | {
356 | groestl(in, 8*len, out);
357 | return 0;
358 | }
359 |
360 | */
361 |
--------------------------------------------------------------------------------
/src/main/jni/c_groestl.h:
--------------------------------------------------------------------------------
1 | #ifndef __hash_h
2 | #define __hash_h
3 | /*
4 | #include "crypto_uint8.h"
5 | #include "crypto_uint32.h"
6 | #include "crypto_uint64.h"
7 | #include "crypto_hash.h"
8 |
9 | typedef crypto_uint8 uint8_t;
10 | typedef crypto_uint32 uint32_t;
11 | typedef crypto_uint64 uint64_t;
12 | */
13 | #include
14 |
15 | #include "hash.h"
16 |
17 | /* some sizes (number of bytes) */
18 | #define ROWS 8
19 | #define LENGTHFIELDLEN ROWS
20 | #define COLS512 8
21 |
22 | #define SIZE512 (ROWS*COLS512)
23 |
24 | #define ROUNDS512 10
25 | #define HASH_BIT_LEN 256
26 |
27 | #define ROTL32(v, n) ((((v)<<(n))|((v)>>(32-(n))))&li_32(ffffffff))
28 |
29 |
30 | #define li_32(h) 0x##h##u
31 | #define EXT_BYTE(var,n) ((uint8_t)((uint32_t)(var) >> (8*n)))
32 | #define u32BIG(a) \
33 | ((ROTL32(a,8) & li_32(00FF00FF)) | \
34 | (ROTL32(a,24) & li_32(FF00FF00)))
35 |
36 |
37 | /* NIST API begin */
38 | typedef struct {
39 | uint32_t chaining[SIZE512/sizeof(uint32_t)]; /* actual state */
40 | uint32_t block_counter1,
41 | block_counter2; /* message block counter(s) */
42 | BitSequence buffer[SIZE512]; /* data buffer */
43 | int buf_ptr; /* data buffer pointer */
44 | int bits_in_last_byte; /* no. of message bits in last byte of
45 | data buffer */
46 | } groestlHashState;
47 |
48 | /*void Init(hashState*);
49 | void Update(hashState*, const BitSequence*, DataLength);
50 | void Final(hashState*, BitSequence*); */
51 | void groestl(const BitSequence*, DataLength, BitSequence*);
52 | /* NIST API end */
53 |
54 | /*
55 | int crypto_hash(unsigned char *out,
56 | const unsigned char *in,
57 | unsigned long long len);
58 | */
59 |
60 | #endif /* __hash_h */
61 |
--------------------------------------------------------------------------------
/src/main/jni/c_jh.c:
--------------------------------------------------------------------------------
1 | /*This program gives the 64-bit optimized bitslice implementation of JH using ANSI C
2 |
3 | --------------------------------
4 | Performance
5 |
6 | Microprocessor: Intel CORE 2 processor (Core 2 Duo Mobile T6600 2.2GHz)
7 | Operating System: 64-bit Ubuntu 10.04 (Linux kernel 2.6.32-22-generic)
8 | Speed for long message:
9 | 1) 45.8 cycles/byte compiler: Intel C++ Compiler 11.1 compilation option: icc -O2
10 | 2) 56.8 cycles/byte compiler: gcc 4.4.3 compilation option: gcc -O3
11 |
12 | --------------------------------
13 | Last Modified: January 16, 2011
14 | */
15 |
16 | #include "c_jh.h"
17 |
18 | #include
19 | #include
20 |
21 | /*typedef unsigned long long uint64;*/
22 | typedef uint64_t uint64;
23 |
24 | /*define data alignment for different C compilers*/
25 | #if defined(__GNUC__)
26 | #define DATA_ALIGN16(x) x __attribute__ ((aligned(16)))
27 | #else
28 | #define DATA_ALIGN16(x) __declspec(align(16)) x
29 | #endif
30 |
31 |
32 | typedef struct {
33 | int hashbitlen; /*the message digest size*/
34 | unsigned long long databitlen; /*the message size in bits*/
35 | unsigned long long datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/
36 | DATA_ALIGN16(uint64 x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/
37 | unsigned char buffer[64]; /*the 512-bit message block to be hashed;*/
38 | } hashState;
39 |
40 |
41 | /*The initial hash value H(0)*/
42 | const unsigned char JH224_H0[128]={0x2d,0xfe,0xdd,0x62,0xf9,0x9a,0x98,0xac,0xae,0x7c,0xac,0xd6,0x19,0xd6,0x34,0xe7,0xa4,0x83,0x10,0x5,0xbc,0x30,0x12,0x16,0xb8,0x60,0x38,0xc6,0xc9,0x66,0x14,0x94,0x66,0xd9,0x89,0x9f,0x25,0x80,0x70,0x6f,0xce,0x9e,0xa3,0x1b,0x1d,0x9b,0x1a,0xdc,0x11,0xe8,0x32,0x5f,0x7b,0x36,0x6e,0x10,0xf9,0x94,0x85,0x7f,0x2,0xfa,0x6,0xc1,0x1b,0x4f,0x1b,0x5c,0xd8,0xc8,0x40,0xb3,0x97,0xf6,0xa1,0x7f,0x6e,0x73,0x80,0x99,0xdc,0xdf,0x93,0xa5,0xad,0xea,0xa3,0xd3,0xa4,0x31,0xe8,0xde,0xc9,0x53,0x9a,0x68,0x22,0xb4,0xa9,0x8a,0xec,0x86,0xa1,0xe4,0xd5,0x74,0xac,0x95,0x9c,0xe5,0x6c,0xf0,0x15,0x96,0xd,0xea,0xb5,0xab,0x2b,0xbf,0x96,0x11,0xdc,0xf0,0xdd,0x64,0xea,0x6e};
43 | const unsigned char JH256_H0[128]={0xeb,0x98,0xa3,0x41,0x2c,0x20,0xd3,0xeb,0x92,0xcd,0xbe,0x7b,0x9c,0xb2,0x45,0xc1,0x1c,0x93,0x51,0x91,0x60,0xd4,0xc7,0xfa,0x26,0x0,0x82,0xd6,0x7e,0x50,0x8a,0x3,0xa4,0x23,0x9e,0x26,0x77,0x26,0xb9,0x45,0xe0,0xfb,0x1a,0x48,0xd4,0x1a,0x94,0x77,0xcd,0xb5,0xab,0x26,0x2,0x6b,0x17,0x7a,0x56,0xf0,0x24,0x42,0xf,0xff,0x2f,0xa8,0x71,0xa3,0x96,0x89,0x7f,0x2e,0x4d,0x75,0x1d,0x14,0x49,0x8,0xf7,0x7d,0xe2,0x62,0x27,0x76,0x95,0xf7,0x76,0x24,0x8f,0x94,0x87,0xd5,0xb6,0x57,0x47,0x80,0x29,0x6c,0x5c,0x5e,0x27,0x2d,0xac,0x8e,0xd,0x6c,0x51,0x84,0x50,0xc6,0x57,0x5,0x7a,0xf,0x7b,0xe4,0xd3,0x67,0x70,0x24,0x12,0xea,0x89,0xe3,0xab,0x13,0xd3,0x1c,0xd7,0x69};
44 | const unsigned char JH384_H0[128]={0x48,0x1e,0x3b,0xc6,0xd8,0x13,0x39,0x8a,0x6d,0x3b,0x5e,0x89,0x4a,0xde,0x87,0x9b,0x63,0xfa,0xea,0x68,0xd4,0x80,0xad,0x2e,0x33,0x2c,0xcb,0x21,0x48,0xf,0x82,0x67,0x98,0xae,0xc8,0x4d,0x90,0x82,0xb9,0x28,0xd4,0x55,0xea,0x30,0x41,0x11,0x42,0x49,0x36,0xf5,0x55,0xb2,0x92,0x48,0x47,0xec,0xc7,0x25,0xa,0x93,0xba,0xf4,0x3c,0xe1,0x56,0x9b,0x7f,0x8a,0x27,0xdb,0x45,0x4c,0x9e,0xfc,0xbd,0x49,0x63,0x97,0xaf,0xe,0x58,0x9f,0xc2,0x7d,0x26,0xaa,0x80,0xcd,0x80,0xc0,0x8b,0x8c,0x9d,0xeb,0x2e,0xda,0x8a,0x79,0x81,0xe8,0xf8,0xd5,0x37,0x3a,0xf4,0x39,0x67,0xad,0xdd,0xd1,0x7a,0x71,0xa9,0xb4,0xd3,0xbd,0xa4,0x75,0xd3,0x94,0x97,0x6c,0x3f,0xba,0x98,0x42,0x73,0x7f};
45 | const unsigned char JH512_H0[128]={0x6f,0xd1,0x4b,0x96,0x3e,0x0,0xaa,0x17,0x63,0x6a,0x2e,0x5,0x7a,0x15,0xd5,0x43,0x8a,0x22,0x5e,0x8d,0xc,0x97,0xef,0xb,0xe9,0x34,0x12,0x59,0xf2,0xb3,0xc3,0x61,0x89,0x1d,0xa0,0xc1,0x53,0x6f,0x80,0x1e,0x2a,0xa9,0x5,0x6b,0xea,0x2b,0x6d,0x80,0x58,0x8e,0xcc,0xdb,0x20,0x75,0xba,0xa6,0xa9,0xf,0x3a,0x76,0xba,0xf8,0x3b,0xf7,0x1,0x69,0xe6,0x5,0x41,0xe3,0x4a,0x69,0x46,0xb5,0x8a,0x8e,0x2e,0x6f,0xe6,0x5a,0x10,0x47,0xa7,0xd0,0xc1,0x84,0x3c,0x24,0x3b,0x6e,0x71,0xb1,0x2d,0x5a,0xc1,0x99,0xcf,0x57,0xf6,0xec,0x9d,0xb1,0xf8,0x56,0xa7,0x6,0x88,0x7c,0x57,0x16,0xb1,0x56,0xe3,0xc2,0xfc,0xdf,0xe6,0x85,0x17,0xfb,0x54,0x5a,0x46,0x78,0xcc,0x8c,0xdd,0x4b};
46 |
47 | /*42 round constants, each round constant is 32-byte (256-bit)*/
48 | const unsigned char E8_bitslice_roundconstant[42][32]={
49 | {0x72,0xd5,0xde,0xa2,0xdf,0x15,0xf8,0x67,0x7b,0x84,0x15,0xa,0xb7,0x23,0x15,0x57,0x81,0xab,0xd6,0x90,0x4d,0x5a,0x87,0xf6,0x4e,0x9f,0x4f,0xc5,0xc3,0xd1,0x2b,0x40},
50 | {0xea,0x98,0x3a,0xe0,0x5c,0x45,0xfa,0x9c,0x3,0xc5,0xd2,0x99,0x66,0xb2,0x99,0x9a,0x66,0x2,0x96,0xb4,0xf2,0xbb,0x53,0x8a,0xb5,0x56,0x14,0x1a,0x88,0xdb,0xa2,0x31},
51 | {0x3,0xa3,0x5a,0x5c,0x9a,0x19,0xe,0xdb,0x40,0x3f,0xb2,0xa,0x87,0xc1,0x44,0x10,0x1c,0x5,0x19,0x80,0x84,0x9e,0x95,0x1d,0x6f,0x33,0xeb,0xad,0x5e,0xe7,0xcd,0xdc},
52 | {0x10,0xba,0x13,0x92,0x2,0xbf,0x6b,0x41,0xdc,0x78,0x65,0x15,0xf7,0xbb,0x27,0xd0,0xa,0x2c,0x81,0x39,0x37,0xaa,0x78,0x50,0x3f,0x1a,0xbf,0xd2,0x41,0x0,0x91,0xd3},
53 | {0x42,0x2d,0x5a,0xd,0xf6,0xcc,0x7e,0x90,0xdd,0x62,0x9f,0x9c,0x92,0xc0,0x97,0xce,0x18,0x5c,0xa7,0xb,0xc7,0x2b,0x44,0xac,0xd1,0xdf,0x65,0xd6,0x63,0xc6,0xfc,0x23},
54 | {0x97,0x6e,0x6c,0x3,0x9e,0xe0,0xb8,0x1a,0x21,0x5,0x45,0x7e,0x44,0x6c,0xec,0xa8,0xee,0xf1,0x3,0xbb,0x5d,0x8e,0x61,0xfa,0xfd,0x96,0x97,0xb2,0x94,0x83,0x81,0x97},
55 | {0x4a,0x8e,0x85,0x37,0xdb,0x3,0x30,0x2f,0x2a,0x67,0x8d,0x2d,0xfb,0x9f,0x6a,0x95,0x8a,0xfe,0x73,0x81,0xf8,0xb8,0x69,0x6c,0x8a,0xc7,0x72,0x46,0xc0,0x7f,0x42,0x14},
56 | {0xc5,0xf4,0x15,0x8f,0xbd,0xc7,0x5e,0xc4,0x75,0x44,0x6f,0xa7,0x8f,0x11,0xbb,0x80,0x52,0xde,0x75,0xb7,0xae,0xe4,0x88,0xbc,0x82,0xb8,0x0,0x1e,0x98,0xa6,0xa3,0xf4},
57 | {0x8e,0xf4,0x8f,0x33,0xa9,0xa3,0x63,0x15,0xaa,0x5f,0x56,0x24,0xd5,0xb7,0xf9,0x89,0xb6,0xf1,0xed,0x20,0x7c,0x5a,0xe0,0xfd,0x36,0xca,0xe9,0x5a,0x6,0x42,0x2c,0x36},
58 | {0xce,0x29,0x35,0x43,0x4e,0xfe,0x98,0x3d,0x53,0x3a,0xf9,0x74,0x73,0x9a,0x4b,0xa7,0xd0,0xf5,0x1f,0x59,0x6f,0x4e,0x81,0x86,0xe,0x9d,0xad,0x81,0xaf,0xd8,0x5a,0x9f},
59 | {0xa7,0x5,0x6,0x67,0xee,0x34,0x62,0x6a,0x8b,0xb,0x28,0xbe,0x6e,0xb9,0x17,0x27,0x47,0x74,0x7,0x26,0xc6,0x80,0x10,0x3f,0xe0,0xa0,0x7e,0x6f,0xc6,0x7e,0x48,0x7b},
60 | {0xd,0x55,0xa,0xa5,0x4a,0xf8,0xa4,0xc0,0x91,0xe3,0xe7,0x9f,0x97,0x8e,0xf1,0x9e,0x86,0x76,0x72,0x81,0x50,0x60,0x8d,0xd4,0x7e,0x9e,0x5a,0x41,0xf3,0xe5,0xb0,0x62},
61 | {0xfc,0x9f,0x1f,0xec,0x40,0x54,0x20,0x7a,0xe3,0xe4,0x1a,0x0,0xce,0xf4,0xc9,0x84,0x4f,0xd7,0x94,0xf5,0x9d,0xfa,0x95,0xd8,0x55,0x2e,0x7e,0x11,0x24,0xc3,0x54,0xa5},
62 | {0x5b,0xdf,0x72,0x28,0xbd,0xfe,0x6e,0x28,0x78,0xf5,0x7f,0xe2,0xf,0xa5,0xc4,0xb2,0x5,0x89,0x7c,0xef,0xee,0x49,0xd3,0x2e,0x44,0x7e,0x93,0x85,0xeb,0x28,0x59,0x7f},
63 | {0x70,0x5f,0x69,0x37,0xb3,0x24,0x31,0x4a,0x5e,0x86,0x28,0xf1,0x1d,0xd6,0xe4,0x65,0xc7,0x1b,0x77,0x4,0x51,0xb9,0x20,0xe7,0x74,0xfe,0x43,0xe8,0x23,0xd4,0x87,0x8a},
64 | {0x7d,0x29,0xe8,0xa3,0x92,0x76,0x94,0xf2,0xdd,0xcb,0x7a,0x9,0x9b,0x30,0xd9,0xc1,0x1d,0x1b,0x30,0xfb,0x5b,0xdc,0x1b,0xe0,0xda,0x24,0x49,0x4f,0xf2,0x9c,0x82,0xbf},
65 | {0xa4,0xe7,0xba,0x31,0xb4,0x70,0xbf,0xff,0xd,0x32,0x44,0x5,0xde,0xf8,0xbc,0x48,0x3b,0xae,0xfc,0x32,0x53,0xbb,0xd3,0x39,0x45,0x9f,0xc3,0xc1,0xe0,0x29,0x8b,0xa0},
66 | {0xe5,0xc9,0x5,0xfd,0xf7,0xae,0x9,0xf,0x94,0x70,0x34,0x12,0x42,0x90,0xf1,0x34,0xa2,0x71,0xb7,0x1,0xe3,0x44,0xed,0x95,0xe9,0x3b,0x8e,0x36,0x4f,0x2f,0x98,0x4a},
67 | {0x88,0x40,0x1d,0x63,0xa0,0x6c,0xf6,0x15,0x47,0xc1,0x44,0x4b,0x87,0x52,0xaf,0xff,0x7e,0xbb,0x4a,0xf1,0xe2,0xa,0xc6,0x30,0x46,0x70,0xb6,0xc5,0xcc,0x6e,0x8c,0xe6},
68 | {0xa4,0xd5,0xa4,0x56,0xbd,0x4f,0xca,0x0,0xda,0x9d,0x84,0x4b,0xc8,0x3e,0x18,0xae,0x73,0x57,0xce,0x45,0x30,0x64,0xd1,0xad,0xe8,0xa6,0xce,0x68,0x14,0x5c,0x25,0x67},
69 | {0xa3,0xda,0x8c,0xf2,0xcb,0xe,0xe1,0x16,0x33,0xe9,0x6,0x58,0x9a,0x94,0x99,0x9a,0x1f,0x60,0xb2,0x20,0xc2,0x6f,0x84,0x7b,0xd1,0xce,0xac,0x7f,0xa0,0xd1,0x85,0x18},
70 | {0x32,0x59,0x5b,0xa1,0x8d,0xdd,0x19,0xd3,0x50,0x9a,0x1c,0xc0,0xaa,0xa5,0xb4,0x46,0x9f,0x3d,0x63,0x67,0xe4,0x4,0x6b,0xba,0xf6,0xca,0x19,0xab,0xb,0x56,0xee,0x7e},
71 | {0x1f,0xb1,0x79,0xea,0xa9,0x28,0x21,0x74,0xe9,0xbd,0xf7,0x35,0x3b,0x36,0x51,0xee,0x1d,0x57,0xac,0x5a,0x75,0x50,0xd3,0x76,0x3a,0x46,0xc2,0xfe,0xa3,0x7d,0x70,0x1},
72 | {0xf7,0x35,0xc1,0xaf,0x98,0xa4,0xd8,0x42,0x78,0xed,0xec,0x20,0x9e,0x6b,0x67,0x79,0x41,0x83,0x63,0x15,0xea,0x3a,0xdb,0xa8,0xfa,0xc3,0x3b,0x4d,0x32,0x83,0x2c,0x83},
73 | {0xa7,0x40,0x3b,0x1f,0x1c,0x27,0x47,0xf3,0x59,0x40,0xf0,0x34,0xb7,0x2d,0x76,0x9a,0xe7,0x3e,0x4e,0x6c,0xd2,0x21,0x4f,0xfd,0xb8,0xfd,0x8d,0x39,0xdc,0x57,0x59,0xef},
74 | {0x8d,0x9b,0xc,0x49,0x2b,0x49,0xeb,0xda,0x5b,0xa2,0xd7,0x49,0x68,0xf3,0x70,0xd,0x7d,0x3b,0xae,0xd0,0x7a,0x8d,0x55,0x84,0xf5,0xa5,0xe9,0xf0,0xe4,0xf8,0x8e,0x65},
75 | {0xa0,0xb8,0xa2,0xf4,0x36,0x10,0x3b,0x53,0xc,0xa8,0x7,0x9e,0x75,0x3e,0xec,0x5a,0x91,0x68,0x94,0x92,0x56,0xe8,0x88,0x4f,0x5b,0xb0,0x5c,0x55,0xf8,0xba,0xbc,0x4c},
76 | {0xe3,0xbb,0x3b,0x99,0xf3,0x87,0x94,0x7b,0x75,0xda,0xf4,0xd6,0x72,0x6b,0x1c,0x5d,0x64,0xae,0xac,0x28,0xdc,0x34,0xb3,0x6d,0x6c,0x34,0xa5,0x50,0xb8,0x28,0xdb,0x71},
77 | {0xf8,0x61,0xe2,0xf2,0x10,0x8d,0x51,0x2a,0xe3,0xdb,0x64,0x33,0x59,0xdd,0x75,0xfc,0x1c,0xac,0xbc,0xf1,0x43,0xce,0x3f,0xa2,0x67,0xbb,0xd1,0x3c,0x2,0xe8,0x43,0xb0},
78 | {0x33,0xa,0x5b,0xca,0x88,0x29,0xa1,0x75,0x7f,0x34,0x19,0x4d,0xb4,0x16,0x53,0x5c,0x92,0x3b,0x94,0xc3,0xe,0x79,0x4d,0x1e,0x79,0x74,0x75,0xd7,0xb6,0xee,0xaf,0x3f},
79 | {0xea,0xa8,0xd4,0xf7,0xbe,0x1a,0x39,0x21,0x5c,0xf4,0x7e,0x9,0x4c,0x23,0x27,0x51,0x26,0xa3,0x24,0x53,0xba,0x32,0x3c,0xd2,0x44,0xa3,0x17,0x4a,0x6d,0xa6,0xd5,0xad},
80 | {0xb5,0x1d,0x3e,0xa6,0xaf,0xf2,0xc9,0x8,0x83,0x59,0x3d,0x98,0x91,0x6b,0x3c,0x56,0x4c,0xf8,0x7c,0xa1,0x72,0x86,0x60,0x4d,0x46,0xe2,0x3e,0xcc,0x8,0x6e,0xc7,0xf6},
81 | {0x2f,0x98,0x33,0xb3,0xb1,0xbc,0x76,0x5e,0x2b,0xd6,0x66,0xa5,0xef,0xc4,0xe6,0x2a,0x6,0xf4,0xb6,0xe8,0xbe,0xc1,0xd4,0x36,0x74,0xee,0x82,0x15,0xbc,0xef,0x21,0x63},
82 | {0xfd,0xc1,0x4e,0xd,0xf4,0x53,0xc9,0x69,0xa7,0x7d,0x5a,0xc4,0x6,0x58,0x58,0x26,0x7e,0xc1,0x14,0x16,0x6,0xe0,0xfa,0x16,0x7e,0x90,0xaf,0x3d,0x28,0x63,0x9d,0x3f},
83 | {0xd2,0xc9,0xf2,0xe3,0x0,0x9b,0xd2,0xc,0x5f,0xaa,0xce,0x30,0xb7,0xd4,0xc,0x30,0x74,0x2a,0x51,0x16,0xf2,0xe0,0x32,0x98,0xd,0xeb,0x30,0xd8,0xe3,0xce,0xf8,0x9a},
84 | {0x4b,0xc5,0x9e,0x7b,0xb5,0xf1,0x79,0x92,0xff,0x51,0xe6,0x6e,0x4,0x86,0x68,0xd3,0x9b,0x23,0x4d,0x57,0xe6,0x96,0x67,0x31,0xcc,0xe6,0xa6,0xf3,0x17,0xa,0x75,0x5},
85 | {0xb1,0x76,0x81,0xd9,0x13,0x32,0x6c,0xce,0x3c,0x17,0x52,0x84,0xf8,0x5,0xa2,0x62,0xf4,0x2b,0xcb,0xb3,0x78,0x47,0x15,0x47,0xff,0x46,0x54,0x82,0x23,0x93,0x6a,0x48},
86 | {0x38,0xdf,0x58,0x7,0x4e,0x5e,0x65,0x65,0xf2,0xfc,0x7c,0x89,0xfc,0x86,0x50,0x8e,0x31,0x70,0x2e,0x44,0xd0,0xb,0xca,0x86,0xf0,0x40,0x9,0xa2,0x30,0x78,0x47,0x4e},
87 | {0x65,0xa0,0xee,0x39,0xd1,0xf7,0x38,0x83,0xf7,0x5e,0xe9,0x37,0xe4,0x2c,0x3a,0xbd,0x21,0x97,0xb2,0x26,0x1,0x13,0xf8,0x6f,0xa3,0x44,0xed,0xd1,0xef,0x9f,0xde,0xe7},
88 | {0x8b,0xa0,0xdf,0x15,0x76,0x25,0x92,0xd9,0x3c,0x85,0xf7,0xf6,0x12,0xdc,0x42,0xbe,0xd8,0xa7,0xec,0x7c,0xab,0x27,0xb0,0x7e,0x53,0x8d,0x7d,0xda,0xaa,0x3e,0xa8,0xde},
89 | {0xaa,0x25,0xce,0x93,0xbd,0x2,0x69,0xd8,0x5a,0xf6,0x43,0xfd,0x1a,0x73,0x8,0xf9,0xc0,0x5f,0xef,0xda,0x17,0x4a,0x19,0xa5,0x97,0x4d,0x66,0x33,0x4c,0xfd,0x21,0x6a},
90 | {0x35,0xb4,0x98,0x31,0xdb,0x41,0x15,0x70,0xea,0x1e,0xf,0xbb,0xed,0xcd,0x54,0x9b,0x9a,0xd0,0x63,0xa1,0x51,0x97,0x40,0x72,0xf6,0x75,0x9d,0xbf,0x91,0x47,0x6f,0xe2}};
91 |
92 |
93 | static void E8(hashState *state); /*The bijective function E8, in bitslice form*/
94 | static void F8(hashState *state); /*The compression function F8 */
95 |
96 | /*The API functions*/
97 | static HashReturn Init(hashState *state, int hashbitlen);
98 | static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen);
99 | static HashReturn Final(hashState *state, BitSequence *hashval);
100 | HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval);
101 |
102 | /*swapping bit 2i with bit 2i+1 of 64-bit x*/
103 | #define SWAP1(x) (x) = ((((x) & 0x5555555555555555ULL) << 1) | (((x) & 0xaaaaaaaaaaaaaaaaULL) >> 1));
104 | /*swapping bits 4i||4i+1 with bits 4i+2||4i+3 of 64-bit x*/
105 | #define SWAP2(x) (x) = ((((x) & 0x3333333333333333ULL) << 2) | (((x) & 0xccccccccccccccccULL) >> 2));
106 | /*swapping bits 8i||8i+1||8i+2||8i+3 with bits 8i+4||8i+5||8i+6||8i+7 of 64-bit x*/
107 | #define SWAP4(x) (x) = ((((x) & 0x0f0f0f0f0f0f0f0fULL) << 4) | (((x) & 0xf0f0f0f0f0f0f0f0ULL) >> 4));
108 | /*swapping bits 16i||16i+1||......||16i+7 with bits 16i+8||16i+9||......||16i+15 of 64-bit x*/
109 | #define SWAP8(x) (x) = ((((x) & 0x00ff00ff00ff00ffULL) << 8) | (((x) & 0xff00ff00ff00ff00ULL) >> 8));
110 | /*swapping bits 32i||32i+1||......||32i+15 with bits 32i+16||32i+17||......||32i+31 of 64-bit x*/
111 | #define SWAP16(x) (x) = ((((x) & 0x0000ffff0000ffffULL) << 16) | (((x) & 0xffff0000ffff0000ULL) >> 16));
112 | /*swapping bits 64i||64i+1||......||64i+31 with bits 64i+32||64i+33||......||64i+63 of 64-bit x*/
113 | #define SWAP32(x) (x) = (((x) << 32) | ((x) >> 32));
114 |
115 | /*The MDS transform*/
116 | #define L(m0,m1,m2,m3,m4,m5,m6,m7) \
117 | (m4) ^= (m1); \
118 | (m5) ^= (m2); \
119 | (m6) ^= (m0) ^ (m3); \
120 | (m7) ^= (m0); \
121 | (m0) ^= (m5); \
122 | (m1) ^= (m6); \
123 | (m2) ^= (m4) ^ (m7); \
124 | (m3) ^= (m4);
125 |
126 | /*Two Sboxes are computed in parallel, each Sbox implements S0 and S1, selected by a constant bit*/
127 | /*The reason to compute two Sboxes in parallel is to try to fully utilize the parallel processing power*/
128 | #define SS(m0,m1,m2,m3,m4,m5,m6,m7,cc0,cc1) \
129 | m3 = ~(m3); \
130 | m7 = ~(m7); \
131 | m0 ^= ((~(m2)) & (cc0)); \
132 | m4 ^= ((~(m6)) & (cc1)); \
133 | temp0 = (cc0) ^ ((m0) & (m1));\
134 | temp1 = (cc1) ^ ((m4) & (m5));\
135 | m0 ^= ((m2) & (m3)); \
136 | m4 ^= ((m6) & (m7)); \
137 | m3 ^= ((~(m1)) & (m2)); \
138 | m7 ^= ((~(m5)) & (m6)); \
139 | m1 ^= ((m0) & (m2)); \
140 | m5 ^= ((m4) & (m6)); \
141 | m2 ^= ((m0) & (~(m3))); \
142 | m6 ^= ((m4) & (~(m7))); \
143 | m0 ^= ((m1) | (m3)); \
144 | m4 ^= ((m5) | (m7)); \
145 | m3 ^= ((m1) & (m2)); \
146 | m7 ^= ((m5) & (m6)); \
147 | m1 ^= (temp0 & (m0)); \
148 | m5 ^= (temp1 & (m4)); \
149 | m2 ^= temp0; \
150 | m6 ^= temp1;
151 |
152 | /*The bijective function E8, in bitslice form*/
153 | static void E8(hashState *state)
154 | {
155 | uint64 i,roundnumber,temp0,temp1;
156 |
157 | for (roundnumber = 0; roundnumber < 42; roundnumber = roundnumber+7) {
158 | /*round 7*roundnumber+0: Sbox, MDS and Swapping layers*/
159 | for (i = 0; i < 2; i++) {
160 | SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i+2] );
161 | L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
162 | SWAP1(state->x[1][i]); SWAP1(state->x[3][i]); SWAP1(state->x[5][i]); SWAP1(state->x[7][i]);
163 | }
164 |
165 | /*round 7*roundnumber+1: Sbox, MDS and Swapping layers*/
166 | for (i = 0; i < 2; i++) {
167 | SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i+2] );
168 | L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
169 | SWAP2(state->x[1][i]); SWAP2(state->x[3][i]); SWAP2(state->x[5][i]); SWAP2(state->x[7][i]);
170 | }
171 |
172 | /*round 7*roundnumber+2: Sbox, MDS and Swapping layers*/
173 | for (i = 0; i < 2; i++) {
174 | SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i+2] );
175 | L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
176 | SWAP4(state->x[1][i]); SWAP4(state->x[3][i]); SWAP4(state->x[5][i]); SWAP4(state->x[7][i]);
177 | }
178 |
179 | /*round 7*roundnumber+3: Sbox, MDS and Swapping layers*/
180 | for (i = 0; i < 2; i++) {
181 | SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i+2] );
182 | L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
183 | SWAP8(state->x[1][i]); SWAP8(state->x[3][i]); SWAP8(state->x[5][i]); SWAP8(state->x[7][i]);
184 | }
185 |
186 | /*round 7*roundnumber+4: Sbox, MDS and Swapping layers*/
187 | for (i = 0; i < 2; i++) {
188 | SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i+2] );
189 | L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
190 | SWAP16(state->x[1][i]); SWAP16(state->x[3][i]); SWAP16(state->x[5][i]); SWAP16(state->x[7][i]);
191 | }
192 |
193 | /*round 7*roundnumber+5: Sbox, MDS and Swapping layers*/
194 | for (i = 0; i < 2; i++) {
195 | SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i+2] );
196 | L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
197 | SWAP32(state->x[1][i]); SWAP32(state->x[3][i]); SWAP32(state->x[5][i]); SWAP32(state->x[7][i]);
198 | }
199 |
200 | /*round 7*roundnumber+6: Sbox and MDS layers*/
201 | for (i = 0; i < 2; i++) {
202 | SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i+2] );
203 | L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
204 | }
205 | /*round 7*roundnumber+6: swapping layer*/
206 | for (i = 1; i < 8; i = i+2) {
207 | temp0 = state->x[i][0]; state->x[i][0] = state->x[i][1]; state->x[i][1] = temp0;
208 | }
209 | }
210 |
211 | }
212 |
213 | /*The compression function F8 */
214 | static void F8(hashState *state)
215 | {
216 | uint64 i;
217 |
218 | /*xor the 512-bit message with the fist half of the 1024-bit hash state*/
219 | for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i];
220 |
221 | /*the bijective function E8 */
222 | E8(state);
223 |
224 | /*xor the 512-bit message with the second half of the 1024-bit hash state*/
225 | for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i];
226 | }
227 |
228 | /*before hashing a message, initialize the hash state as H0 */
229 | static HashReturn Init(hashState *state, int hashbitlen)
230 | {
231 | state->databitlen = 0;
232 | state->datasize_in_buffer = 0;
233 |
234 | /*initialize the initial hash value of JH*/
235 | state->hashbitlen = hashbitlen;
236 |
237 | /*load the initial hash value into state*/
238 | switch (hashbitlen)
239 | {
240 | case 224: memcpy(state->x,JH224_H0,128); break;
241 | case 256: memcpy(state->x,JH256_H0,128); break;
242 | case 384: memcpy(state->x,JH384_H0,128); break;
243 | case 512: memcpy(state->x,JH512_H0,128); break;
244 | }
245 |
246 | return(SUCCESS);
247 | }
248 |
249 |
250 | /*hash each 512-bit message block, except the last partial block*/
251 | static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen)
252 | {
253 | DataLength index; /*the starting address of the data to be compressed*/
254 |
255 | state->databitlen += databitlen;
256 | index = 0;
257 |
258 | /*if there is remaining data in the buffer, fill it to a full message block first*/
259 | /*we assume that the size of the data in the buffer is the multiple of 8 bits if it is not at the end of a message*/
260 |
261 | /*There is data in the buffer, but the incoming data is insufficient for a full block*/
262 | if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) < 512) ) {
263 | if ( (databitlen & 7) == 0 ) {
264 | memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)) ;
265 | }
266 | else memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)+1) ;
267 | state->datasize_in_buffer += databitlen;
268 | databitlen = 0;
269 | }
270 |
271 | /*There is data in the buffer, and the incoming data is sufficient for a full block*/
272 | if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) >= 512) ) {
273 | memcpy( state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3) ) ;
274 | index = 64-(state->datasize_in_buffer >> 3);
275 | databitlen = databitlen - (512 - state->datasize_in_buffer);
276 | F8(state);
277 | state->datasize_in_buffer = 0;
278 | }
279 |
280 | /*hash the remaining full message blocks*/
281 | for ( ; databitlen >= 512; index = index+64, databitlen = databitlen - 512) {
282 | memcpy(state->buffer, data+index, 64);
283 | F8(state);
284 | }
285 |
286 | /*store the partial block into buffer, assume that -- if part of the last byte is not part of the message, then that part consists of 0 bits*/
287 | if ( databitlen > 0) {
288 | if ((databitlen & 7) == 0)
289 | memcpy(state->buffer, data+index, (databitlen & 0x1ff) >> 3);
290 | else
291 | memcpy(state->buffer, data+index, ((databitlen & 0x1ff) >> 3)+1);
292 | state->datasize_in_buffer = databitlen;
293 | }
294 |
295 | return(SUCCESS);
296 | }
297 |
298 | /*pad the message, process the padded block(s), truncate the hash value H to obtain the message digest*/
299 | static HashReturn Final(hashState *state, BitSequence *hashval)
300 | {
301 | unsigned int i;
302 |
303 | if ( (state->databitlen & 0x1ff) == 0 ) {
304 | /*pad the message when databitlen is multiple of 512 bits, then process the padded block*/
305 | memset(state->buffer, 0, 64);
306 | state->buffer[0] = 0x80;
307 | state->buffer[63] = state->databitlen & 0xff;
308 | state->buffer[62] = (state->databitlen >> 8) & 0xff;
309 | state->buffer[61] = (state->databitlen >> 16) & 0xff;
310 | state->buffer[60] = (state->databitlen >> 24) & 0xff;
311 | state->buffer[59] = (state->databitlen >> 32) & 0xff;
312 | state->buffer[58] = (state->databitlen >> 40) & 0xff;
313 | state->buffer[57] = (state->databitlen >> 48) & 0xff;
314 | state->buffer[56] = (state->databitlen >> 56) & 0xff;
315 | F8(state);
316 | }
317 | else {
318 | /*set the rest of the bytes in the buffer to 0*/
319 | if ( (state->datasize_in_buffer & 7) == 0)
320 | for (i = (state->databitlen & 0x1ff) >> 3; i < 64; i++) state->buffer[i] = 0;
321 | else
322 | for (i = ((state->databitlen & 0x1ff) >> 3)+1; i < 64; i++) state->buffer[i] = 0;
323 |
324 | /*pad and process the partial block when databitlen is not multiple of 512 bits, then hash the padded blocks*/
325 | state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7- (state->databitlen & 7));
326 |
327 | F8(state);
328 | memset(state->buffer, 0, 64);
329 | state->buffer[63] = state->databitlen & 0xff;
330 | state->buffer[62] = (state->databitlen >> 8) & 0xff;
331 | state->buffer[61] = (state->databitlen >> 16) & 0xff;
332 | state->buffer[60] = (state->databitlen >> 24) & 0xff;
333 | state->buffer[59] = (state->databitlen >> 32) & 0xff;
334 | state->buffer[58] = (state->databitlen >> 40) & 0xff;
335 | state->buffer[57] = (state->databitlen >> 48) & 0xff;
336 | state->buffer[56] = (state->databitlen >> 56) & 0xff;
337 | F8(state);
338 | }
339 |
340 | /*truncating the final hash value to generate the message digest*/
341 | switch(state->hashbitlen) {
342 | case 224: memcpy(hashval,(unsigned char*)state->x+64+36,28); break;
343 | case 256: memcpy(hashval,(unsigned char*)state->x+64+32,32); break;
344 | case 384: memcpy(hashval,(unsigned char*)state->x+64+16,48); break;
345 | case 512: memcpy(hashval,(unsigned char*)state->x+64,64); break;
346 | }
347 |
348 | return(SUCCESS);
349 | }
350 |
351 | /* hash a message,
352 | three inputs: message digest size in bits (hashbitlen); message (data); message length in bits (databitlen)
353 | one output: message digest (hashval)
354 | */
355 | HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval)
356 | {
357 | hashState state;
358 |
359 | if ( hashbitlen == 224 || hashbitlen == 256 || hashbitlen == 384 || hashbitlen == 512 ) {
360 | Init(&state, hashbitlen);
361 | Update(&state, data, databitlen);
362 | Final(&state, hashval);
363 | return SUCCESS;
364 | }
365 | else
366 | return(BAD_HASHLEN);
367 | }
368 |
--------------------------------------------------------------------------------
/src/main/jni/c_jh.h:
--------------------------------------------------------------------------------
1 | /*This program gives the 64-bit optimized bitslice implementation of JH using ANSI C
2 |
3 | --------------------------------
4 | Performance
5 |
6 | Microprocessor: Intel CORE 2 processor (Core 2 Duo Mobile T6600 2.2GHz)
7 | Operating System: 64-bit Ubuntu 10.04 (Linux kernel 2.6.32-22-generic)
8 | Speed for long message:
9 | 1) 45.8 cycles/byte compiler: Intel C++ Compiler 11.1 compilation option: icc -O2
10 | 2) 56.8 cycles/byte compiler: gcc 4.4.3 compilation option: gcc -O3
11 |
12 | --------------------------------
13 | Last Modified: January 16, 2011
14 | */
15 | #pragma once
16 |
17 | #include "hash.h"
18 |
19 | HashReturn jh_hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval);
20 |
--------------------------------------------------------------------------------
/src/main/jni/c_keccak.c:
--------------------------------------------------------------------------------
1 | // keccak.c
2 | // 19-Nov-11 Markku-Juhani O. Saarinen
3 | // A baseline Keccak (3rd round) implementation.
4 |
5 | #include
6 | #include
7 |
8 | #define HASH_DATA_AREA 136
9 | #define KECCAK_ROUNDS 24
10 |
11 | #ifndef ROTL64
12 | #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
13 | #endif
14 |
15 | const uint64_t keccakf_rndc[24] =
16 | {
17 | 0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
18 | 0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
19 | 0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
20 | 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
21 | 0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
22 | 0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
23 | 0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
24 | 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
25 | };
26 |
27 | // update the state with given number of rounds
28 |
29 | void keccakf(uint64_t st[25], int rounds)
30 | {
31 | int i, j, round;
32 | uint64_t t, bc[5];
33 |
34 | for (round = 0; round < rounds; ++round) {
35 |
36 | // Theta
37 | bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
38 | bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
39 | bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
40 | bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
41 | bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
42 |
43 | for (i = 0; i < 5; ++i) {
44 | t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
45 | st[i] ^= t;
46 | st[i + 5] ^= t;
47 | st[i + 10] ^= t;
48 | st[i + 15] ^= t;
49 | st[i + 20] ^= t;
50 | }
51 |
52 | // Rho Pi
53 | t = st[1];
54 | st[1] = ROTL64(st[6], 44);
55 | st[6] = ROTL64(st[9], 20);
56 | st[9] = ROTL64(st[22], 61);
57 | st[22] = ROTL64(st[14], 39);
58 | st[14] = ROTL64(st[20], 18);
59 | st[20] = ROTL64(st[2], 62);
60 | st[2] = ROTL64(st[12], 43);
61 | st[12] = ROTL64(st[13], 25);
62 | st[13] = ROTL64(st[19], 8);
63 | st[19] = ROTL64(st[23], 56);
64 | st[23] = ROTL64(st[15], 41);
65 | st[15] = ROTL64(st[4], 27);
66 | st[4] = ROTL64(st[24], 14);
67 | st[24] = ROTL64(st[21], 2);
68 | st[21] = ROTL64(st[8], 55);
69 | st[8] = ROTL64(st[16], 45);
70 | st[16] = ROTL64(st[5], 36);
71 | st[5] = ROTL64(st[3], 28);
72 | st[3] = ROTL64(st[18], 21);
73 | st[18] = ROTL64(st[17], 15);
74 | st[17] = ROTL64(st[11], 10);
75 | st[11] = ROTL64(st[7], 6);
76 | st[7] = ROTL64(st[10], 3);
77 | st[10] = ROTL64(t, 1);
78 |
79 | // Chi
80 | // unrolled loop, where only last iteration is different
81 | j = 0;
82 | bc[0] = st[j];
83 | bc[1] = st[j + 1];
84 |
85 | st[j] ^= (~st[j + 1]) & st[j + 2];
86 | st[j + 1] ^= (~st[j + 2]) & st[j + 3];
87 | st[j + 2] ^= (~st[j + 3]) & st[j + 4];
88 | st[j + 3] ^= (~st[j + 4]) & bc[0];
89 | st[j + 4] ^= (~bc[0]) & bc[1];
90 |
91 | j = 5;
92 | bc[0] = st[j];
93 | bc[1] = st[j + 1];
94 |
95 | st[j] ^= (~st[j + 1]) & st[j + 2];
96 | st[j + 1] ^= (~st[j + 2]) & st[j + 3];
97 | st[j + 2] ^= (~st[j + 3]) & st[j + 4];
98 | st[j + 3] ^= (~st[j + 4]) & bc[0];
99 | st[j + 4] ^= (~bc[0]) & bc[1];
100 |
101 | j = 10;
102 | bc[0] = st[j];
103 | bc[1] = st[j + 1];
104 |
105 | st[j] ^= (~st[j + 1]) & st[j + 2];
106 | st[j + 1] ^= (~st[j + 2]) & st[j + 3];
107 | st[j + 2] ^= (~st[j + 3]) & st[j + 4];
108 | st[j + 3] ^= (~st[j + 4]) & bc[0];
109 | st[j + 4] ^= (~bc[0]) & bc[1];
110 |
111 | j = 15;
112 | bc[0] = st[j];
113 | bc[1] = st[j + 1];
114 |
115 | st[j] ^= (~st[j + 1]) & st[j + 2];
116 | st[j + 1] ^= (~st[j + 2]) & st[j + 3];
117 | st[j + 2] ^= (~st[j + 3]) & st[j + 4];
118 | st[j + 3] ^= (~st[j + 4]) & bc[0];
119 | st[j + 4] ^= (~bc[0]) & bc[1];
120 |
121 | j = 20;
122 | bc[0] = st[j];
123 | bc[1] = st[j + 1];
124 | bc[2] = st[j + 2];
125 | bc[3] = st[j + 3];
126 | bc[4] = st[j + 4];
127 |
128 | st[j] ^= (~bc[1]) & bc[2];
129 | st[j + 1] ^= (~bc[2]) & bc[3];
130 | st[j + 2] ^= (~bc[3]) & bc[4];
131 | st[j + 3] ^= (~bc[4]) & bc[0];
132 | st[j + 4] ^= (~bc[0]) & bc[1];
133 |
134 | // Iota
135 | st[0] ^= keccakf_rndc[round];
136 | }
137 | }
138 |
139 | // compute a keccak hash (md) of given byte length from "in"
140 | typedef uint64_t state_t[25];
141 |
142 | void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
143 | {
144 | state_t st;
145 | uint8_t temp[144];
146 | int i, rsiz, rsizw;
147 |
148 | rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen;
149 | rsizw = rsiz / 8;
150 |
151 | memset(st, 0, sizeof(st));
152 |
153 | for (; inlen >= rsiz; inlen -= rsiz, in += rsiz) {
154 | for (i = 0; i < rsizw; i++)
155 | st[i] ^= ((uint64_t *)in)[i];
156 | keccakf(st, KECCAK_ROUNDS);
157 | }
158 |
159 | // last block and padding
160 | memcpy(temp, in, inlen);
161 | temp[inlen++] = 1;
162 | memset(temp + inlen, 0, rsiz - inlen);
163 | temp[rsiz - 1] |= 0x80;
164 |
165 | for (i = 0; i < rsizw; i++)
166 | st[i] ^= ((uint64_t *)temp)[i];
167 |
168 | keccakf(st, KECCAK_ROUNDS);
169 |
170 | memcpy(md, st, mdlen);
171 | }
172 |
173 | void keccak1600(const uint8_t *in, int inlen, uint8_t *md)
174 | {
175 | keccak(in, inlen, md, sizeof(state_t));
176 | }
177 |
--------------------------------------------------------------------------------
/src/main/jni/c_keccak.h:
--------------------------------------------------------------------------------
1 | // keccak.h
2 | // 19-Nov-11 Markku-Juhani O. Saarinen
3 |
4 | #ifndef KECCAK_H
5 | #define KECCAK_H
6 |
7 | #include
8 | #include
9 |
10 | #ifndef KECCAK_ROUNDS
11 | #define KECCAK_ROUNDS 24
12 | #endif
13 |
14 | #ifndef ROTL64
15 | #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
16 | #endif
17 |
18 | // compute a keccak hash (md) of given byte length from "in"
19 | int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen);
20 |
21 | // update the state
22 | void keccakf(uint64_t st[25], int norounds);
23 |
24 | void keccak1600(const uint8_t *in, int inlen, uint8_t *md);
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/src/main/jni/c_skein.h:
--------------------------------------------------------------------------------
1 | #ifndef _SKEIN_H_
2 | #define _SKEIN_H_ 1
3 | /**************************************************************************
4 | **
5 | ** Interface declarations and internal definitions for Skein hashing.
6 | **
7 | ** Source code author: Doug Whiting, 2008.
8 | **
9 | ** This algorithm and source code is released to the public domain.
10 | **
11 | ***************************************************************************
12 | **
13 | ** The following compile-time switches may be defined to control some
14 | ** tradeoffs between speed, code size, error checking, and security.
15 | **
16 | ** The "default" note explains what happens when the switch is not defined.
17 | **
18 | ** SKEIN_DEBUG -- make callouts from inside Skein code
19 | ** to examine/display intermediate values.
20 | ** [default: no callouts (no overhead)]
21 | **
22 | ** SKEIN_ERR_CHECK -- how error checking is handled inside Skein
23 | ** code. If not defined, most error checking
24 | ** is disabled (for performance). Otherwise,
25 | ** the switch value is interpreted as:
26 | ** 0: use assert() to flag errors
27 | ** 1: return SKEIN_FAIL to flag errors
28 | **
29 | ***************************************************************************/
30 | #include "skein_port.h" /* get platform-specific definitions */
31 |
32 | typedef enum
33 | {
34 | SKEIN_SUCCESS = 0, /* return codes from Skein calls */
35 | SKEIN_FAIL = 1,
36 | SKEIN_BAD_HASHLEN = 2
37 | }
38 | SkeinHashReturn;
39 |
40 | typedef uint32_t SkeinDataLength; /* bit count type */
41 | typedef u08b_t SkeinBitSequence; /* bit stream type */
42 |
43 | /* "all-in-one" call */
44 | SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data,
45 | SkeinDataLength databitlen, SkeinBitSequence *hashval);
46 |
47 | #endif /* ifndef _SKEIN_H_ */
48 |
--------------------------------------------------------------------------------
/src/main/jni/cryptonight.h:
--------------------------------------------------------------------------------
1 | #ifndef __CRYPTONIGHT_H_INCLUDED
2 | #define __CRYPTONIGHT_H_INCLUDED
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | #include
9 | #include
10 |
11 | typedef struct {
12 | uint8_t hash_state[224]; // Need only 200, explicit align
13 | uint8_t* long_state;
14 | uint8_t ctx_info[24]; //Use some of the extra memory for flags
15 | } cryptonight_ctx;
16 |
17 | typedef struct {
18 | const char* warning;
19 | } alloc_msg;
20 |
21 | size_t cryptonight_init(size_t use_fast_mem, size_t use_mlock, alloc_msg* msg);
22 | cryptonight_ctx* cryptonight_alloc_ctx(size_t use_fast_mem, size_t use_mlock, alloc_msg* msg);
23 | void cryptonight_free_ctx(cryptonight_ctx* ctx);
24 |
25 | #ifdef __cplusplus
26 | }
27 | #endif
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/src/main/jni/cryptonight_aesni.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software: you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation, either version 3 of the License, or
5 | * any later version.
6 | *
7 | * This program is distributed in the hope that it will be useful,
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | * GNU General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU General Public License
13 | * along with this program. If not, see .
14 | *
15 | */
16 | #pragma once
17 |
18 | #include "cryptonight.h"
19 | #include "algos.hpp"
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #ifdef __GNUC__
26 | #include
27 | static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
28 | {
29 | unsigned __int128 r = (unsigned __int128)a * (unsigned __int128)b;
30 | *hi = r >> 64;
31 | return (uint64_t)r;
32 | }
33 |
34 | #else
35 | #include
36 | #endif // __GNUC__
37 |
38 | #if !defined(_LP64) && !defined(_WIN64)
39 | #error You are trying to do a 32-bit build. This will all end in tears. I know it.
40 | #endif
41 |
42 | #include "soft_aes.hpp"
43 |
44 | extern "C"
45 | {
46 | void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen);
47 | void keccakf(uint64_t st[25], int rounds);
48 | extern void(*const extra_hashes[4])(const void *, uint32_t, char *);
49 | }
50 |
51 | // This will shift and xor tmp1 into itself as 4 32-bit vals such as
52 | // sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
53 | static inline __m128i sl_xor(__m128i tmp1)
54 | {
55 | __m128i tmp4;
56 | tmp4 = _mm_slli_si128(tmp1, 0x04);
57 | tmp1 = _mm_xor_si128(tmp1, tmp4);
58 | tmp4 = _mm_slli_si128(tmp4, 0x04);
59 | tmp1 = _mm_xor_si128(tmp1, tmp4);
60 | tmp4 = _mm_slli_si128(tmp4, 0x04);
61 | tmp1 = _mm_xor_si128(tmp1, tmp4);
62 | return tmp1;
63 | }
64 |
65 | template
66 | static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2)
67 | {
68 | __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, rcon);
69 | xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
70 | *xout0 = sl_xor(*xout0);
71 | *xout0 = _mm_xor_si128(*xout0, xout1);
72 | xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00);
73 | xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
74 | *xout2 = sl_xor(*xout2);
75 | *xout2 = _mm_xor_si128(*xout2, xout1);
76 | }
77 |
78 | static inline void soft_aes_genkey_sub(__m128i* xout0, __m128i* xout2, uint8_t rcon)
79 | {
80 | __m128i xout1 = soft_aeskeygenassist(*xout2, rcon);
81 | xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
82 | *xout0 = sl_xor(*xout0);
83 | *xout0 = _mm_xor_si128(*xout0, xout1);
84 | xout1 = soft_aeskeygenassist(*xout0, 0x00);
85 | xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
86 | *xout2 = sl_xor(*xout2);
87 | *xout2 = _mm_xor_si128(*xout2, xout1);
88 | }
89 |
90 | template
91 | static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3,
92 | __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
93 | {
94 | __m128i xout0, xout2;
95 |
96 | xout0 = _mm_load_si128(memory);
97 | xout2 = _mm_load_si128(memory + 1);
98 | *k0 = xout0;
99 | *k1 = xout2;
100 |
101 | if (SOFT_AES)
102 | soft_aes_genkey_sub(&xout0, &xout2, 0x01);
103 | else
104 | aes_genkey_sub<0x01>(&xout0, &xout2);
105 | *k2 = xout0;
106 | *k3 = xout2;
107 |
108 | if (SOFT_AES)
109 | soft_aes_genkey_sub(&xout0, &xout2, 0x02);
110 | else
111 | aes_genkey_sub<0x02>(&xout0, &xout2);
112 | *k4 = xout0;
113 | *k5 = xout2;
114 |
115 | if (SOFT_AES)
116 | soft_aes_genkey_sub(&xout0, &xout2, 0x04);
117 | else
118 | aes_genkey_sub<0x04>(&xout0, &xout2);
119 | *k6 = xout0;
120 | *k7 = xout2;
121 |
122 | if (SOFT_AES)
123 | soft_aes_genkey_sub(&xout0, &xout2, 0x08);
124 | else
125 | aes_genkey_sub<0x08>(&xout0, &xout2);
126 | *k8 = xout0;
127 | *k9 = xout2;
128 | }
129 |
130 | static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
131 | {
132 | *x0 = _mm_aesenc_si128(*x0, key);
133 | *x1 = _mm_aesenc_si128(*x1, key);
134 | *x2 = _mm_aesenc_si128(*x2, key);
135 | *x3 = _mm_aesenc_si128(*x3, key);
136 | *x4 = _mm_aesenc_si128(*x4, key);
137 | *x5 = _mm_aesenc_si128(*x5, key);
138 | *x6 = _mm_aesenc_si128(*x6, key);
139 | *x7 = _mm_aesenc_si128(*x7, key);
140 | }
141 |
142 | static inline void soft_aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
143 | {
144 | *x0 = soft_aesenc(*x0, key);
145 | *x1 = soft_aesenc(*x1, key);
146 | *x2 = soft_aesenc(*x2, key);
147 | *x3 = soft_aesenc(*x3, key);
148 | *x4 = soft_aesenc(*x4, key);
149 | *x5 = soft_aesenc(*x5, key);
150 | *x6 = soft_aesenc(*x6, key);
151 | *x7 = soft_aesenc(*x7, key);
152 | }
153 |
154 | inline void mix_and_propagate(__m128i& x0, __m128i& x1, __m128i& x2, __m128i& x3, __m128i& x4, __m128i& x5, __m128i& x6, __m128i& x7)
155 | {
156 | __m128i tmp0 = x0;
157 | x0 = _mm_xor_si128(x0, x1);
158 | x1 = _mm_xor_si128(x1, x2);
159 | x2 = _mm_xor_si128(x2, x3);
160 | x3 = _mm_xor_si128(x3, x4);
161 | x4 = _mm_xor_si128(x4, x5);
162 | x5 = _mm_xor_si128(x5, x6);
163 | x6 = _mm_xor_si128(x6, x7);
164 | x7 = _mm_xor_si128(x7, tmp0);
165 | }
166 |
167 | template
168 | void cn_explode_scratchpad(const __m128i* input, __m128i* output)
169 | {
170 | // This is more than we have registers, compiler will assign 2 keys on the stack
171 | __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
172 | __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
173 |
174 | aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
175 |
176 | xin0 = _mm_load_si128(input + 4);
177 | xin1 = _mm_load_si128(input + 5);
178 | xin2 = _mm_load_si128(input + 6);
179 | xin3 = _mm_load_si128(input + 7);
180 | xin4 = _mm_load_si128(input + 8);
181 | xin5 = _mm_load_si128(input + 9);
182 | xin6 = _mm_load_si128(input + 10);
183 | xin7 = _mm_load_si128(input + 11);
184 |
185 | if (ALGO == cryptonight_heavy || ALGO == cryptonight_haven || ALGO == cryptonight_bittube2 || ALGO == cryptonight_superfast)
186 | {
187 | for (size_t i = 0; i < 16; i++)
188 | {
189 | if (SOFT_AES)
190 | {
191 | soft_aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
192 | soft_aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
193 | soft_aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
194 | soft_aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
195 | soft_aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
196 | soft_aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
197 | soft_aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
198 | soft_aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
199 | soft_aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
200 | soft_aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
201 | }
202 | else
203 | {
204 | aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
205 | aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
206 | aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
207 | aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
208 | aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
209 | aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
210 | aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
211 | aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
212 | aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
213 | aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
214 | }
215 | mix_and_propagate(xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7);
216 | }
217 | }
218 |
219 | for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
220 | {
221 | if (SOFT_AES)
222 | {
223 | soft_aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
224 | soft_aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
225 | soft_aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
226 | soft_aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
227 | soft_aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
228 | soft_aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
229 | soft_aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
230 | soft_aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
231 | soft_aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
232 | soft_aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
233 | }
234 | else
235 | {
236 | aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
237 | aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
238 | aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
239 | aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
240 | aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
241 | aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
242 | aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
243 | aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
244 | aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
245 | aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
246 | }
247 |
248 | _mm_store_si128(output + i + 0, xin0);
249 | _mm_store_si128(output + i + 1, xin1);
250 | _mm_store_si128(output + i + 2, xin2);
251 | _mm_store_si128(output + i + 3, xin3);
252 |
253 | if (PREFETCH)
254 | _mm_prefetch((const char*)output + i + 0, _MM_HINT_T2);
255 |
256 | _mm_store_si128(output + i + 4, xin4);
257 | _mm_store_si128(output + i + 5, xin5);
258 | _mm_store_si128(output + i + 6, xin6);
259 | _mm_store_si128(output + i + 7, xin7);
260 |
261 | if (PREFETCH)
262 | _mm_prefetch((const char*)output + i + 4, _MM_HINT_T2);
263 | }
264 | }
265 |
266 | template
267 | void cn_implode_scratchpad(const __m128i* input, __m128i* output)
268 | {
269 | // This is more than we have registers, compiler will assign 2 keys on the stack
270 | __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
271 | __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
272 |
273 | aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9);
274 |
275 | xout0 = _mm_load_si128(output + 4);
276 | xout1 = _mm_load_si128(output + 5);
277 | xout2 = _mm_load_si128(output + 6);
278 | xout3 = _mm_load_si128(output + 7);
279 | xout4 = _mm_load_si128(output + 8);
280 | xout5 = _mm_load_si128(output + 9);
281 | xout6 = _mm_load_si128(output + 10);
282 | xout7 = _mm_load_si128(output + 11);
283 |
284 | for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
285 | {
286 | if (PREFETCH)
287 | _mm_prefetch((const char*)input + i + 0, _MM_HINT_NTA);
288 |
289 | xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
290 | xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
291 | xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
292 | xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
293 |
294 | if (PREFETCH)
295 | _mm_prefetch((const char*)input + i + 4, _MM_HINT_NTA);
296 |
297 | xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
298 | xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
299 | xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
300 | xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
301 |
302 | if (SOFT_AES)
303 | {
304 | soft_aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
305 | soft_aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
306 | soft_aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
307 | soft_aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
308 | soft_aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
309 | soft_aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
310 | soft_aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
311 | soft_aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
312 | soft_aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
313 | soft_aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
314 | }
315 | else
316 | {
317 | aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
318 | aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
319 | aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
320 | aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
321 | aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
322 | aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
323 | aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
324 | aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
325 | aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
326 | aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
327 | }
328 |
329 | if (ALGO == cryptonight_heavy || ALGO == cryptonight_haven || ALGO == cryptonight_bittube2 || ALGO == cryptonight_superfast)
330 | mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
331 | }
332 |
333 | if (ALGO == cryptonight_heavy || ALGO == cryptonight_haven || ALGO == cryptonight_bittube2 || ALGO == cryptonight_superfast)
334 | {
335 | for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
336 | {
337 | if (PREFETCH)
338 | _mm_prefetch((const char*)input + i + 0, _MM_HINT_NTA);
339 |
340 | xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
341 | xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
342 | xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2);
343 | xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3);
344 |
345 | if (PREFETCH)
346 | _mm_prefetch((const char*)input + i + 4, _MM_HINT_NTA);
347 |
348 | xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4);
349 | xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5);
350 | xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
351 | xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
352 |
353 | if (SOFT_AES)
354 | {
355 | soft_aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
356 | soft_aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
357 | soft_aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
358 | soft_aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
359 | soft_aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
360 | soft_aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
361 | soft_aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
362 | soft_aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
363 | soft_aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
364 | soft_aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
365 | }
366 | else
367 | {
368 | aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
369 | aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
370 | aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
371 | aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
372 | aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
373 | aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
374 | aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
375 | aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
376 | aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
377 | aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
378 | }
379 |
380 | if (ALGO == cryptonight_heavy || ALGO == cryptonight_haven || ALGO == cryptonight_bittube2 || ALGO == cryptonight_superfast)
381 | mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
382 | }
383 |
384 | for (size_t i = 0; i < 16; i++)
385 | {
386 | if (SOFT_AES)
387 | {
388 | soft_aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
389 | soft_aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
390 | soft_aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
391 | soft_aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
392 | soft_aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
393 | soft_aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
394 | soft_aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
395 | soft_aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
396 | soft_aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
397 | soft_aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
398 | }
399 | else
400 | {
401 | aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
402 | aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
403 | aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
404 | aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
405 | aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
406 | aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
407 | aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
408 | aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
409 | aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
410 | aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
411 | }
412 |
413 | mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
414 | }
415 | }
416 |
417 | _mm_store_si128(output + 4, xout0);
418 | _mm_store_si128(output + 5, xout1);
419 | _mm_store_si128(output + 6, xout2);
420 | _mm_store_si128(output + 7, xout3);
421 | _mm_store_si128(output + 8, xout4);
422 | _mm_store_si128(output + 9, xout5);
423 | _mm_store_si128(output + 10, xout6);
424 | _mm_store_si128(output + 11, xout7);
425 | }
426 |
427 | inline uint64_t int_sqrt33_1_double_precision(const uint64_t n0)
428 | {
429 | __m128d x = _mm_castsi128_pd(_mm_add_epi64(_mm_cvtsi64_si128(n0 >> 12), _mm_set_epi64x(0, 1023ULL << 52)));
430 | x = _mm_sqrt_sd(_mm_setzero_pd(), x);
431 | uint64_t r = static_cast(_mm_cvtsi128_si64(_mm_castpd_si128(x)));
432 |
433 | const uint64_t s = r >> 20;
434 | r >>= 19;
435 |
436 | uint64_t x2 = (s - (1022ULL << 32)) * (r - s - (1022ULL << 32) + 1);
437 |
438 | #ifdef __INTEL_COMPILER
439 | _addcarry_u64(_subborrow_u64(0, x2, n0, (unsigned __int64*)&x2), r, 0, (unsigned __int64*)&r);
440 | #elif defined(_MSC_VER) || (__GNUC__ >= 7)
441 | _addcarry_u64(_subborrow_u64(0, x2, n0, (unsigned long long int*)&x2), r, 0, (unsigned long long int*)&r);
442 | #else
443 | // GCC versions prior to 7 don't generate correct assembly for _subborrow_u64 -> _addcarry_u64 sequence
444 | // Fallback to simpler code
445 | if (x2 < n0) ++r;
446 | #endif
447 | return r;
448 | }
449 |
450 | inline __m128i aes_round_bittube2(const __m128i& val, const __m128i& key)
451 | {
452 | alignas(16) uint32_t k[4];
453 | alignas(16) uint32_t x[4];
454 | _mm_store_si128((__m128i*)k, key);
455 | _mm_store_si128((__m128i*)x, _mm_xor_si128(val, _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))); // x = ~val
456 | #define BYTE(p, i) ((unsigned char*)&p)[i]
457 | k[0] ^= saes_table[0][BYTE(x[0], 0)] ^ saes_table[1][BYTE(x[1], 1)] ^ saes_table[2][BYTE(x[2], 2)] ^ saes_table[3][BYTE(x[3], 3)];
458 | x[0] ^= k[0];
459 | k[1] ^= saes_table[0][BYTE(x[1], 0)] ^ saes_table[1][BYTE(x[2], 1)] ^ saes_table[2][BYTE(x[3], 2)] ^ saes_table[3][BYTE(x[0], 3)];
460 | x[1] ^= k[1];
461 | k[2] ^= saes_table[0][BYTE(x[2], 0)] ^ saes_table[1][BYTE(x[3], 1)] ^ saes_table[2][BYTE(x[0], 2)] ^ saes_table[3][BYTE(x[1], 3)];
462 | x[2] ^= k[2];
463 | k[3] ^= saes_table[0][BYTE(x[3], 0)] ^ saes_table[1][BYTE(x[0], 1)] ^ saes_table[2][BYTE(x[1], 2)] ^ saes_table[3][BYTE(x[2], 3)];
464 | #undef BYTE
465 | return _mm_load_si128((__m128i*)k);
466 | }
467 |
468 | template
469 | inline void cryptonight_monero_tweak(uint64_t* mem_out, __m128i tmp)
470 | {
471 | mem_out[0] = _mm_cvtsi128_si64(tmp);
472 |
473 | tmp = _mm_castps_si128(_mm_movehl_ps(_mm_castsi128_ps(tmp), _mm_castsi128_ps(tmp)));
474 | uint64_t vh = _mm_cvtsi128_si64(tmp);
475 |
476 | uint8_t x = static_cast(vh >> 24);
477 | static const uint16_t table = 0x7531;
478 | if (ALGO == cryptonight_monero || ALGO == cryptonight_aeon || ALGO == cryptonight_ipbc || ALGO == cryptonight_masari || ALGO == cryptonight_bittube2)
479 | {
480 | const uint8_t index = (((x >> 3) & 6) | (x & 1)) << 1;
481 | vh ^= ((table >> index) & 0x3) << 28;
482 |
483 | mem_out[1] = vh;
484 | }
485 | else if (ALGO == cryptonight_stellite)
486 | {
487 | const uint8_t index = (((x >> 4) & 6) | (x & 1)) << 1;
488 | vh ^= ((table >> index) & 0x3) << 28;
489 |
490 | mem_out[1] = vh;
491 | }
492 |
493 | }
494 |
495 | /** optimal type for sqrt
496 | *
497 | * Depending on the number of hashes calculated the optimal type for the sqrt value will be selected.
498 | *
499 | * @tparam N number of hashes per thread
500 | */
501 | template
502 | struct GetOptimalSqrtType
503 | {
504 | using type = __m128i;
505 | };
506 |
507 | template<>
508 | struct GetOptimalSqrtType<1u>
509 | {
510 | using type = uint64_t;
511 | };
512 | template
513 | using GetOptimalSqrtType_t = typename GetOptimalSqrtType::type;
514 |
515 | /** assign a value and convert if necessary
516 | *
517 | * @param output output type
518 | * @param input value which is assigned to output
519 | * @{
520 | */
521 | inline void assign(__m128i& output, const uint64_t input)
522 | {
523 | output = _mm_cvtsi64_si128(input);
524 | }
525 |
526 | inline void assign(uint64_t& output, const uint64_t input)
527 | {
528 | output = input;
529 | }
530 |
531 | inline void assign(uint64_t& output, const __m128i& input)
532 | {
533 | output = _mm_cvtsi128_si64(input);
534 | }
535 | /** @} */
536 |
537 | inline void set_float_rounding_mode()
538 | {
539 | #ifdef _MSC_VER
540 | _control87(RC_DOWN, MCW_RC);
541 | #else
542 | std::fesetround(FE_DOWNWARD);
543 | #endif
544 | }
545 |
546 | #define CN_MONERO_V8_SHUFFLE_0(n, l0, idx0, ax0, bx0, bx1) \
547 | /* Shuffle the other 3x16 byte chunks in the current 64-byte cache line */ \
548 | if(ALGO == cryptonight_monero_v8) \
549 | { \
550 | const uint64_t idx1 = idx0 & MASK; \
551 | const __m128i chunk1 = _mm_load_si128((__m128i *)&l0[idx1 ^ 0x10]); \
552 | const __m128i chunk2 = _mm_load_si128((__m128i *)&l0[idx1 ^ 0x20]); \
553 | const __m128i chunk3 = _mm_load_si128((__m128i *)&l0[idx1 ^ 0x30]); \
554 | _mm_store_si128((__m128i *)&l0[idx1 ^ 0x10], _mm_add_epi64(chunk3, bx1)); \
555 | _mm_store_si128((__m128i *)&l0[idx1 ^ 0x20], _mm_add_epi64(chunk1, bx0)); \
556 | _mm_store_si128((__m128i *)&l0[idx1 ^ 0x30], _mm_add_epi64(chunk2, ax0)); \
557 | }
558 |
559 | #define CN_MONERO_V8_SHUFFLE_1(n, l0, idx0, ax0, bx0, bx1, lo, hi) \
560 | /* Shuffle the other 3x16 byte chunks in the current 64-byte cache line */ \
561 | if(ALGO == cryptonight_monero_v8) \
562 | { \
563 | const uint64_t idx1 = idx0 & MASK; \
564 | const __m128i chunk1 = _mm_xor_si128(_mm_load_si128((__m128i *)&l0[idx1 ^ 0x10]), _mm_set_epi64x(lo, hi)); \
565 | const __m128i chunk2 = _mm_load_si128((__m128i *)&l0[idx1 ^ 0x20]); \
566 | hi ^= ((uint64_t*)&chunk2)[0]; \
567 | lo ^= ((uint64_t*)&chunk2)[1]; \
568 | const __m128i chunk3 = _mm_load_si128((__m128i *)&l0[idx1 ^ 0x30]); \
569 | _mm_store_si128((__m128i *)&l0[idx1 ^ 0x10], _mm_add_epi64(chunk3, bx1)); \
570 | _mm_store_si128((__m128i *)&l0[idx1 ^ 0x20], _mm_add_epi64(chunk1, bx0)); \
571 | _mm_store_si128((__m128i *)&l0[idx1 ^ 0x30], _mm_add_epi64(chunk2, ax0)); \
572 | }
573 |
574 | #define CN_MONERO_V8_DIV(n, cx, sqrt_result, division_result_xmm, cl) \
575 | if(ALGO == cryptonight_monero_v8) \
576 | { \
577 | uint64_t sqrt_result_tmp; \
578 | assign(sqrt_result_tmp, sqrt_result); \
579 | /* Use division and square root results from the _previous_ iteration to hide the latency */ \
580 | const uint64_t cx_64 = _mm_cvtsi128_si64(cx); \
581 | cl ^= static_cast(_mm_cvtsi128_si64(division_result_xmm)) ^ (sqrt_result_tmp << 32); \
582 | const uint32_t d = (cx_64 + (sqrt_result_tmp << 1)) | 0x80000001UL; \
583 | /* Most and least significant bits in the divisor are set to 1 \
584 | * to make sure we don't divide by a small or even number, \
585 | * so there are no shortcuts for such cases \
586 | * \
587 | * Quotient may be as large as (2^64 - 1)/(2^31 + 1) = 8589934588 = 2^33 - 4 \
588 | * We drop the highest bit to fit both quotient and remainder in 32 bits \
589 | */ \
590 | /* Compiler will optimize it to a single div instruction */ \
591 | const uint64_t cx_s = _mm_cvtsi128_si64(_mm_srli_si128(cx, 8)); \
592 | const uint64_t division_result = static_cast(cx_s / d) + ((cx_s % d) << 32); \
593 | division_result_xmm = _mm_cvtsi64_si128(static_cast(division_result)); \
594 | /* Use division_result as an input for the square root to prevent parallel implementation in hardware */ \
595 | assign(sqrt_result, int_sqrt33_1_double_precision(cx_64 + division_result)); \
596 | }
597 |
598 | #define CN_INIT_SINGLE \
599 | if((ALGO == cryptonight_monero || ALGO == cryptonight_aeon || ALGO == cryptonight_ipbc || ALGO == cryptonight_stellite || ALGO == cryptonight_masari || ALGO == cryptonight_bittube2) && len < 43) \
600 | { \
601 | memset(output, 0, 32 * N); \
602 | return; \
603 | }
604 |
605 | #define CN_INIT(n, monero_const, l0, ax0, bx0, idx0, ptr0, bx1, sqrt_result, division_result_xmm) \
606 | keccak((const uint8_t *)input + len * n, len, ctx[n]->hash_state, 200); \
607 | uint64_t monero_const; \
608 | if(ALGO == cryptonight_monero || ALGO == cryptonight_aeon || ALGO == cryptonight_ipbc || ALGO == cryptonight_stellite || ALGO == cryptonight_masari || ALGO == cryptonight_bittube2) \
609 | { \
610 | monero_const = *reinterpret_cast(reinterpret_cast(input) + len * n + 35); \
611 | monero_const ^= *(reinterpret_cast(ctx[n]->hash_state) + 24); \
612 | } \
613 | /* Optim - 99% time boundary */ \
614 | cn_explode_scratchpad((__m128i*)ctx[n]->hash_state, (__m128i*)ctx[n]->long_state); \
615 | \
616 | __m128i ax0; \
617 | uint64_t idx0; \
618 | __m128i bx0; \
619 | uint8_t* l0 = ctx[n]->long_state; \
620 | /* BEGIN cryptonight_monero_v8 variables */ \
621 | __m128i bx1; \
622 | __m128i division_result_xmm; \
623 | GetOptimalSqrtType_t sqrt_result; \
624 | /* END cryptonight_monero_v8 variables */ \
625 | { \
626 | uint64_t* h0 = (uint64_t*)ctx[n]->hash_state; \
627 | idx0 = h0[0] ^ h0[4]; \
628 | ax0 = _mm_set_epi64x(h0[1] ^ h0[5], idx0); \
629 | bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); \
630 | if(ALGO == cryptonight_monero_v8) \
631 | { \
632 | bx1 = _mm_set_epi64x(h0[9] ^ h0[11], h0[8] ^ h0[10]); \
633 | division_result_xmm = _mm_cvtsi64_si128(h0[12]); \
634 | assign(sqrt_result, h0[13]); \
635 | set_float_rounding_mode(); \
636 | } \
637 | } \
638 | __m128i *ptr0
639 |
640 | #define CN_STEP1(n, monero_const, l0, ax0, bx0, idx0, ptr0, cx, bx1) \
641 | __m128i cx; \
642 | ptr0 = (__m128i *)&l0[idx0 & MASK]; \
643 | cx = _mm_load_si128(ptr0); \
644 | if (ALGO == cryptonight_bittube2) \
645 | { \
646 | cx = aes_round_bittube2(cx, ax0); \
647 | } \
648 | else \
649 | { \
650 | if(SOFT_AES) \
651 | cx = soft_aesenc(cx, ax0); \
652 | else \
653 | cx = _mm_aesenc_si128(cx, ax0); \
654 | } \
655 | CN_MONERO_V8_SHUFFLE_0(n, l0, idx0, ax0, bx0, bx1)
656 |
657 | #define CN_STEP2(n, monero_const, l0, ax0, bx0, idx0, ptr0, cx) \
658 | if(ALGO == cryptonight_monero || ALGO == cryptonight_aeon || ALGO == cryptonight_ipbc || ALGO == cryptonight_stellite || ALGO == cryptonight_masari || ALGO == cryptonight_bittube2) \
659 | cryptonight_monero_tweak((uint64_t*)ptr0, _mm_xor_si128(bx0, cx)); \
660 | else \
661 | _mm_store_si128((__m128i *)ptr0, _mm_xor_si128(bx0, cx)); \
662 | idx0 = _mm_cvtsi128_si64(cx); \
663 | \
664 | ptr0 = (__m128i *)&l0[idx0 & MASK]; \
665 | if(PREFETCH) \
666 | _mm_prefetch((const char*)ptr0, _MM_HINT_T0); \
667 | if(ALGO != cryptonight_monero_v8) \
668 | bx0 = cx
669 |
670 | #define CN_STEP3(n, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0, cx, bx1, sqrt_result, division_result_xmm) \
671 | uint64_t lo, cl, ch; \
672 | uint64_t al0 = _mm_cvtsi128_si64(ax0); \
673 | uint64_t ah0 = ((uint64_t*)&ax0)[1]; \
674 | cl = ((uint64_t*)ptr0)[0]; \
675 | ch = ((uint64_t*)ptr0)[1]; \
676 | CN_MONERO_V8_DIV(n, cx, sqrt_result, division_result_xmm, cl); \
677 | { \
678 | uint64_t hi; \
679 | lo = _umul128(idx0, cl, &hi); \
680 | CN_MONERO_V8_SHUFFLE_1(n, l0, idx0, ax0, bx0, bx1, lo, hi); \
681 | ah0 += lo; \
682 | al0 += hi; \
683 | } \
684 | if(ALGO == cryptonight_monero_v8) \
685 | { \
686 | bx1 = bx0; \
687 | bx0 = cx; \
688 | } \
689 | ((uint64_t*)ptr0)[0] = al0; \
690 | if(PREFETCH) \
691 | _mm_prefetch((const char*)ptr0, _MM_HINT_T0)
692 |
693 | #define CN_STEP4(n, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0) \
694 | if (ALGO == cryptonight_monero || ALGO == cryptonight_aeon || ALGO == cryptonight_ipbc || ALGO == cryptonight_stellite || ALGO == cryptonight_masari || ALGO == cryptonight_bittube2) \
695 | { \
696 | if (ALGO == cryptonight_ipbc || ALGO == cryptonight_bittube2) \
697 | ((uint64_t*)ptr0)[1] = ah0 ^ monero_const ^ ((uint64_t*)ptr0)[0]; \
698 | else \
699 | ((uint64_t*)ptr0)[1] = ah0 ^ monero_const; \
700 | } \
701 | else \
702 | ((uint64_t*)ptr0)[1] = ah0; \
703 | al0 ^= cl; \
704 | ah0 ^= ch; \
705 | ax0 = _mm_set_epi64x(ah0, al0); \
706 | idx0 = al0;
707 |
708 | #define CN_STEP5(n, monero_const, l0, ax0, bx0, idx0, ptr0) \
709 | if(ALGO == cryptonight_heavy || ALGO == cryptonight_bittube2) \
710 | { \
711 | ptr0 = (__m128i *)&l0[idx0 & MASK]; \
712 | int64_t u = ((int64_t*)ptr0)[0]; \
713 | int32_t d = ((int32_t*)ptr0)[2]; \
714 | int64_t q = u / (d | 0x5); \
715 | \
716 | ((int64_t*)ptr0)[0] = u ^ q; \
717 | idx0 = d ^ q; \
718 | } \
719 | else if(ALGO == cryptonight_haven || ALGO == cryptonight_superfast) \
720 | { \
721 | ptr0 = (__m128i *)&l0[idx0 & MASK]; \
722 | int64_t u = ((int64_t*)ptr0)[0]; \
723 | int32_t d = ((int32_t*)ptr0)[2]; \
724 | int64_t q = u / (d | 0x5); \
725 | \
726 | ((int64_t*)ptr0)[0] = u ^ q; \
727 | idx0 = (~d) ^ q; \
728 | }
729 |
730 | #define CN_FINALIZE(n) \
731 | /* Optim - 90% time boundary */ \
732 | cn_implode_scratchpad((__m128i*)ctx[n]->long_state, (__m128i*)ctx[n]->hash_state); \
733 | /* Optim - 99% time boundary */ \
734 | keccakf((uint64_t*)ctx[n]->hash_state, 24); \
735 | extra_hashes[ctx[n]->hash_state[0] & 3](ctx[n]->hash_state, 200, (char*)output + 32 * n)
736 |
737 | //! defer the evaluation of an macro
738 | #ifndef _MSC_VER
739 | # define CN_DEFER(...) __VA_ARGS__
740 | #else
741 | # define CN_EMPTY(...)
742 | # define CN_DEFER(...) __VA_ARGS__ CN_EMPTY()
743 | #endif
744 |
745 | //! execute the macro f with the passed arguments
746 | #define CN_EXEC(f,...) CN_DEFER(f)(__VA_ARGS__)
747 |
748 | /** add append n to all arguments and keeps n as first argument
749 | *
750 | * @param n number which is appended to the arguments (expect the first argument n)
751 | *
752 | * @code{.cpp}
753 | * CN_ENUM_2(1, foo, bar)
754 | * // is transformed to
755 | * 1, foo1, bar1
756 | * @endcode
757 | */
758 | #define CN_ENUM_0(n, ...) n
759 | #define CN_ENUM_1(n, x1) n, x1 ## n
760 | #define CN_ENUM_2(n, x1, x2) n, x1 ## n, x2 ## n
761 | #define CN_ENUM_3(n, x1, x2, x3) n, x1 ## n, x2 ## n, x3 ## n
762 | #define CN_ENUM_4(n, x1, x2, x3, x4) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n
763 | #define CN_ENUM_5(n, x1, x2, x3, x4, x5) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n
764 | #define CN_ENUM_6(n, x1, x2, x3, x4, x5, x6) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n
765 | #define CN_ENUM_7(n, x1, x2, x3, x4, x5, x6, x7) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n
766 | #define CN_ENUM_8(n, x1, x2, x3, x4, x5, x6, x7, x8) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n, x8 ## n
767 | #define CN_ENUM_9(n, x1, x2, x3, x4, x5, x6, x7, x8, x9) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n, x8 ## n, x9 ## n
768 | #define CN_ENUM_10(n, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n, x8 ## n, x9 ## n, x10 ## n
769 | #define CN_ENUM_11(n, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n, x8 ## n, x9 ## n, x10 ## n, x11 ## n
770 | #define CN_ENUM_12(n, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n, x8 ## n, x9 ## n, x10 ## n, x11 ## n, x12 ## n
771 | #define CN_ENUM_13(n, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n, x8 ## n, x9 ## n, x10 ## n, x11 ## n, x12 ## n, x13 ## n
772 | #define CN_ENUM_14(n, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n, x8 ## n, x9 ## n, x10 ## n, x11 ## n, x12 ## n, x13 ## n, x14 ## n
773 | #define CN_ENUM_15(n, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) n, x1 ## n, x2 ## n, x3 ## n, x4 ## n, x5 ## n, x6 ## n, x7 ## n, x8 ## n, x9 ## n, x10 ## n, x11 ## n, x12 ## n, x13 ## n, x14 ## n, x15 ## n
774 |
775 | /** repeat a macro call multiple times
776 | *
777 | * @param n number of arguments followed after f
778 | * @param f name of the macro which should be executed
779 | * @param ... n parameter which name will get appended by a unique number
780 | *
781 | * @code{.cpp}
782 | * REPEAT_2(2, f, foo, bar)
783 | * // is transformed to
784 | * f(0, foo0, bar); f(1, foo1, bar1)
785 | * @endcode
786 | */
787 | #define REPEAT_1(n, f, ...) CN_EXEC(f, CN_ENUM_ ## n(0, __VA_ARGS__))
788 | #define REPEAT_2(n, f, ...) CN_EXEC(f, CN_ENUM_ ## n(0, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(1, __VA_ARGS__))
789 | #define REPEAT_3(n, f, ...) CN_EXEC(f, CN_ENUM_ ## n(0, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(1, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(2, __VA_ARGS__))
790 | #define REPEAT_4(n, f, ...) CN_EXEC(f, CN_ENUM_ ## n(0, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(1, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(2, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(3, __VA_ARGS__))
791 | #define REPEAT_5(n, f, ...) CN_EXEC(f, CN_ENUM_ ## n(0, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(1, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(2, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(3, __VA_ARGS__)); CN_EXEC(f, CN_ENUM_ ## n(4, __VA_ARGS__))
792 |
793 | template< size_t N>
794 | struct Cryptonight_hash;
795 |
796 | template< >
797 | struct Cryptonight_hash<1>
798 | {
799 | static constexpr size_t N = 1;
800 |
801 | template
802 | static void hash(const void* input, size_t len, void* output, cryptonight_ctx** ctx)
803 | {
804 | constexpr size_t MASK = cn_select_mask();
805 | constexpr size_t ITERATIONS = cn_select_iter();
806 | constexpr size_t MEM = cn_select_memory();
807 |
808 | CN_INIT_SINGLE;
809 | REPEAT_1(9, CN_INIT, monero_const, l0, ax0, bx0, idx0, ptr0, bx1, sqrt_result, division_result_xmm);
810 |
811 | // Optim - 90% time boundary
812 | for (size_t i = 0; i < ITERATIONS; i++)
813 | {
814 | REPEAT_1(8, CN_STEP1, monero_const, l0, ax0, bx0, idx0, ptr0, cx, bx1);
815 | REPEAT_1(7, CN_STEP2, monero_const, l0, ax0, bx0, idx0, ptr0, cx);
816 | REPEAT_1(15, CN_STEP3, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0, cx, bx1, sqrt_result, division_result_xmm);
817 | REPEAT_1(11, CN_STEP4, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0);
818 | REPEAT_1(6, CN_STEP5, monero_const, l0, ax0, bx0, idx0, ptr0);
819 | }
820 |
821 | REPEAT_1(0, CN_FINALIZE);
822 | }
823 | };
824 |
825 | template< >
826 | struct Cryptonight_hash<2>
827 | {
828 | static constexpr size_t N = 2;
829 |
830 | template
831 | static void hash(const void* input, size_t len, void* output, cryptonight_ctx** ctx)
832 | {
833 | constexpr size_t MASK = cn_select_mask();
834 | constexpr size_t ITERATIONS = cn_select_iter();
835 | constexpr size_t MEM = cn_select_memory();
836 |
837 | CN_INIT_SINGLE;
838 | REPEAT_2(9, CN_INIT, monero_const, l0, ax0, bx0, idx0, ptr0, bx1, sqrt_result, division_result_xmm);
839 |
840 | // Optim - 90% time boundary
841 | for (size_t i = 0; i < ITERATIONS; i++)
842 | {
843 | REPEAT_2(8, CN_STEP1, monero_const, l0, ax0, bx0, idx0, ptr0, cx, bx1);
844 | REPEAT_2(7, CN_STEP2, monero_const, l0, ax0, bx0, idx0, ptr0, cx);
845 | REPEAT_2(15, CN_STEP3, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0, cx, bx1, sqrt_result, division_result_xmm);
846 | REPEAT_2(11, CN_STEP4, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0);
847 | REPEAT_2(6, CN_STEP5, monero_const, l0, ax0, bx0, idx0, ptr0);
848 | }
849 |
850 | REPEAT_2(0, CN_FINALIZE);
851 | }
852 | };
853 |
854 | template< >
855 | struct Cryptonight_hash<3>
856 | {
857 | static constexpr size_t N = 3;
858 |
859 | template
860 | static void hash(const void* input, size_t len, void* output, cryptonight_ctx** ctx)
861 | {
862 | constexpr size_t MASK = cn_select_mask();
863 | constexpr size_t ITERATIONS = cn_select_iter();
864 | constexpr size_t MEM = cn_select_memory();
865 |
866 | CN_INIT_SINGLE;
867 | REPEAT_3(9, CN_INIT, monero_const, l0, ax0, bx0, idx0, ptr0, bx1, sqrt_result, division_result_xmm);
868 |
869 | // Optim - 90% time boundary
870 | for (size_t i = 0; i < ITERATIONS; i++)
871 | {
872 | REPEAT_3(8, CN_STEP1, monero_const, l0, ax0, bx0, idx0, ptr0, cx, bx1);
873 | REPEAT_3(7, CN_STEP2, monero_const, l0, ax0, bx0, idx0, ptr0, cx);
874 | REPEAT_3(15, CN_STEP3, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0, cx, bx1, sqrt_result, division_result_xmm);
875 | REPEAT_3(11, CN_STEP4, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0);
876 | REPEAT_3(6, CN_STEP5, monero_const, l0, ax0, bx0, idx0, ptr0);
877 | }
878 |
879 | REPEAT_3(0, CN_FINALIZE);
880 | }
881 | };
882 |
883 | template< >
884 | struct Cryptonight_hash<4>
885 | {
886 | static constexpr size_t N = 4;
887 |
888 | template
889 | static void hash(const void* input, size_t len, void* output, cryptonight_ctx** ctx)
890 | {
891 | constexpr size_t MASK = cn_select_mask();
892 | constexpr size_t ITERATIONS = cn_select_iter();
893 | constexpr size_t MEM = cn_select_memory();
894 |
895 | CN_INIT_SINGLE;
896 | REPEAT_4(9, CN_INIT, monero_const, l0, ax0, bx0, idx0, ptr0, bx1, sqrt_result, division_result_xmm);
897 |
898 | // Optim - 90% time boundary
899 | for (size_t i = 0; i < ITERATIONS; i++)
900 | {
901 | REPEAT_4(8, CN_STEP1, monero_const, l0, ax0, bx0, idx0, ptr0, cx, bx1);
902 | REPEAT_4(7, CN_STEP2, monero_const, l0, ax0, bx0, idx0, ptr0, cx);
903 | REPEAT_4(15, CN_STEP3, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0, cx, bx1, sqrt_result, division_result_xmm);
904 | REPEAT_4(11, CN_STEP4, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0);
905 | REPEAT_4(6, CN_STEP5, monero_const, l0, ax0, bx0, idx0, ptr0);
906 | }
907 |
908 | REPEAT_4(0, CN_FINALIZE);
909 | }
910 | };
911 |
912 | template< >
913 | struct Cryptonight_hash<5>
914 | {
915 | static constexpr size_t N = 5;
916 |
917 | template
918 | static void hash(const void* input, size_t len, void* output, cryptonight_ctx** ctx)
919 | {
920 | constexpr size_t MASK = cn_select_mask();
921 | constexpr size_t ITERATIONS = cn_select_iter();
922 | constexpr size_t MEM = cn_select_memory();
923 |
924 | CN_INIT_SINGLE;
925 | REPEAT_5(9, CN_INIT, monero_const, l0, ax0, bx0, idx0, ptr0, bx1, sqrt_result, division_result_xmm);
926 |
927 | // Optim - 90% time boundary
928 | for (size_t i = 0; i < ITERATIONS; i++)
929 | {
930 | REPEAT_5(8, CN_STEP1, monero_const, l0, ax0, bx0, idx0, ptr0, cx, bx1);
931 | REPEAT_5(7, CN_STEP2, monero_const, l0, ax0, bx0, idx0, ptr0, cx);
932 | REPEAT_5(15, CN_STEP3, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0, cx, bx1, sqrt_result, division_result_xmm);
933 | REPEAT_5(11, CN_STEP4, monero_const, l0, ax0, bx0, idx0, ptr0, lo, cl, ch, al0, ah0);
934 | REPEAT_5(6, CN_STEP5, monero_const, l0, ax0, bx0, idx0, ptr0);
935 | }
936 |
937 | REPEAT_5(0, CN_FINALIZE);
938 | }
939 | };
940 |
--------------------------------------------------------------------------------
/src/main/jni/cryptonight_common.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software: you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation, either version 3 of the License, or
5 | * any later version.
6 | *
7 | * This program is distributed in the hope that it will be useful,
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | * GNU General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU General Public License
13 | * along with this program. If not, see .
14 | *
15 | * Additional permission under GNU GPL version 3 section 7
16 | *
17 | * If you modify this Program, or any covered work, by linking or combining
18 | * it with OpenSSL (or a modified version of that library), containing parts
19 | * covered by the terms of OpenSSL License and SSLeay License, the licensors
20 | * of this Program grant you additional permission to convey the resulting work.
21 | *
22 | */
23 |
24 | extern "C"
25 | {
26 | #include "c_groestl.h"
27 | #include "c_blake256.h"
28 | #include "c_jh.h"
29 | #include "c_skein.h"
30 | }
31 | #include "algos.hpp"
32 | #include "cryptonight.h"
33 | #include "cryptonight_aesni.h"
34 | #include
35 | #include
36 | #include
37 |
38 | #ifdef __GNUC__
39 | #include
40 | #else
41 | #include
42 | #endif // __GNUC__
43 |
44 | #if defined(__APPLE__)
45 | #include
46 | #endif
47 |
48 | #ifdef _WIN32
49 | #include
50 | #include
51 | #else
52 | #include
53 | #include
54 | #include
55 | #endif // _WIN32
56 |
57 | void do_blake_hash(const void* input, uint32_t len, char* output) {
58 | blake256_hash((uint8_t*)output, (const uint8_t*)input, len);
59 | }
60 |
61 | void do_groestl_hash(const void* input, uint32_t len, char* output) {
62 | groestl((const uint8_t*)input, len * 8, (uint8_t*)output);
63 | }
64 |
65 | void do_jh_hash(const void* input, uint32_t len, char* output) {
66 | jh_hash(32 * 8, (const uint8_t*)input, 8 * len, (uint8_t*)output);
67 | }
68 |
69 | void do_skein_hash(const void* input, uint32_t len, char* output) {
70 | skein_hash(8 * 32, (const uint8_t*)input, 8 * len, (uint8_t*)output);
71 | }
72 |
73 | void(*const extra_hashes[4])(const void *, uint32_t, char *) = { do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash };
74 |
75 | #ifdef _WIN32
76 |
77 | BOOL bRebootDesirable = FALSE; //If VirtualAlloc fails, suggest a reboot
78 |
79 | BOOL AddPrivilege(TCHAR* pszPrivilege)
80 | {
81 | HANDLE hToken;
82 | TOKEN_PRIVILEGES tp;
83 | BOOL status;
84 |
85 | if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
86 | return FALSE;
87 |
88 | if (!LookupPrivilegeValue(NULL, pszPrivilege, &tp.Privileges[0].Luid))
89 | return FALSE;
90 |
91 | tp.PrivilegeCount = 1;
92 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
93 | status = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
94 |
95 | if (!status || (GetLastError() != ERROR_SUCCESS))
96 | return FALSE;
97 |
98 | CloseHandle(hToken);
99 | return TRUE;
100 | }
101 |
102 | BOOL AddLargePageRights()
103 | {
104 | HANDLE hToken;
105 | PTOKEN_USER user = NULL;
106 |
107 | if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) == TRUE)
108 | {
109 | TOKEN_ELEVATION Elevation;
110 | DWORD cbSize = sizeof(TOKEN_ELEVATION);
111 | BOOL bIsElevated = FALSE;
112 |
113 | if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize))
114 | bIsElevated = Elevation.TokenIsElevated;
115 |
116 | DWORD size = 0;
117 | GetTokenInformation(hToken, TokenUser, NULL, 0, &size);
118 |
119 | if (size > 0 && bIsElevated)
120 | {
121 | user = (PTOKEN_USER)LocalAlloc(LPTR, size);
122 | GetTokenInformation(hToken, TokenUser, user, size, &size);
123 | }
124 |
125 | CloseHandle(hToken);
126 | }
127 |
128 | if (!user)
129 | return FALSE;
130 |
131 | LSA_HANDLE handle;
132 | LSA_OBJECT_ATTRIBUTES attributes;
133 | ZeroMemory(&attributes, sizeof(attributes));
134 |
135 | BOOL result = FALSE;
136 | if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0)
137 | {
138 | LSA_UNICODE_STRING lockmem;
139 | lockmem.Buffer = L"SeLockMemoryPrivilege";
140 | lockmem.Length = 42;
141 | lockmem.MaximumLength = 44;
142 |
143 | PLSA_UNICODE_STRING rights = NULL;
144 | ULONG cnt = 0;
145 | BOOL bHasRights = FALSE;
146 | if (LsaEnumerateAccountRights(handle, user->User.Sid, &rights, &cnt) == 0)
147 | {
148 | for (size_t i = 0; i < cnt; i++)
149 | {
150 | if (rights[i].Length == lockmem.Length &&
151 | memcmp(rights[i].Buffer, lockmem.Buffer, 42) == 0)
152 | {
153 | bHasRights = TRUE;
154 | break;
155 | }
156 | }
157 |
158 | LsaFreeMemory(rights);
159 | }
160 |
161 | if (!bHasRights)
162 | result = LsaAddAccountRights(handle, user->User.Sid, &lockmem, 1) == 0;
163 |
164 | LsaClose(handle);
165 | }
166 |
167 | LocalFree(user);
168 | return result;
169 | }
170 | #endif
171 |
172 | size_t cryptonight_init(size_t use_fast_mem, size_t use_mlock, alloc_msg* msg)
173 | {
174 | #ifdef _WIN32
175 | if (use_fast_mem == 0)
176 | return 1;
177 |
178 | if (AddPrivilege(TEXT("SeLockMemoryPrivilege")) == 0)
179 | {
180 | if (AddLargePageRights())
181 | {
182 | msg->warning = "Added SeLockMemoryPrivilege to the current account. You need to reboot for it to work";
183 | bRebootDesirable = TRUE;
184 | }
185 | else
186 | msg->warning = "Obtaining SeLockMemoryPrivilege failed.";
187 |
188 | return 0;
189 | }
190 |
191 | bRebootDesirable = TRUE;
192 | return 1;
193 | #else
194 | return 1;
195 | #endif // _WIN32
196 | }
197 |
198 | cryptonight_ctx* cryptonight_alloc_ctx(size_t use_fast_mem, size_t use_mlock, alloc_msg* msg)
199 | {
200 | size_t hashMemSize = CRYPTONIGHT_MEMORY;
201 |
202 | cryptonight_ctx* ptr = (cryptonight_ctx*)_mm_malloc(sizeof(cryptonight_ctx), 4096);
203 |
204 | if (use_fast_mem == 0)
205 | {
206 | // use 2MiB aligned memory
207 | ptr->long_state = (uint8_t*)_mm_malloc(hashMemSize, hashMemSize);
208 | ptr->ctx_info[0] = 0;
209 | ptr->ctx_info[1] = 0;
210 | return ptr;
211 | }
212 |
213 | #ifdef _WIN32
214 | SIZE_T iLargePageMin = GetLargePageMinimum();
215 |
216 | if (hashMemSize > iLargePageMin)
217 | iLargePageMin *= 2;
218 |
219 | ptr->long_state = (uint8_t*)VirtualAlloc(NULL, iLargePageMin,
220 | MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE);
221 |
222 | if (ptr->long_state == NULL)
223 | {
224 | _mm_free(ptr);
225 | if (bRebootDesirable)
226 | msg->warning = "VirtualAlloc failed. Reboot might help.";
227 | else
228 | msg->warning = "VirtualAlloc failed.";
229 | return NULL;
230 | }
231 | else
232 | {
233 | ptr->ctx_info[0] = 1;
234 | return ptr;
235 | }
236 | #else
237 | //http://man7.org/linux/man-pages/man2/mmap.2.html
238 | #if defined(__APPLE__)
239 | ptr->long_state = (uint8_t*)mmap(NULL, hashMemSize, PROT_READ | PROT_WRITE,
240 | MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
241 | #elif defined(__FreeBSD__)
242 | ptr->long_state = (uint8_t*)mmap(NULL, hashMemSize, PROT_READ | PROT_WRITE,
243 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0);
244 | #elif defined(__OpenBSD__)
245 | ptr->long_state = (uint8_t*)mmap(NULL, hashMemSize, PROT_READ | PROT_WRITE,
246 | MAP_PRIVATE | MAP_ANON, -1, 0);
247 | #else
248 | ptr->long_state = (uint8_t*)mmap(NULL, hashMemSize, PROT_READ | PROT_WRITE,
249 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, -1, 0);
250 | #endif
251 |
252 | if (ptr->long_state == MAP_FAILED)
253 | {
254 | _mm_free(ptr);
255 | msg->warning = "mmap failed, check attribute 'use_slow_memory' in 'config.txt'";
256 | return NULL;
257 | }
258 |
259 | ptr->ctx_info[0] = 1;
260 |
261 | if (madvise(ptr->long_state, hashMemSize, MADV_RANDOM | MADV_WILLNEED) != 0)
262 | msg->warning = "madvise failed";
263 |
264 | ptr->ctx_info[1] = 0;
265 | if (use_mlock != 0 && mlock(ptr->long_state, hashMemSize) != 0)
266 | msg->warning = "mlock failed";
267 | else
268 | ptr->ctx_info[1] = 1;
269 |
270 | return ptr;
271 | #endif // _WIN32
272 | }
273 |
274 | void cryptonight_free_ctx(cryptonight_ctx* ctx)
275 | {
276 | size_t hashMemSize = CRYPTONIGHT_MEMORY;
277 |
278 | if (ctx->ctx_info[0] != 0)
279 | {
280 | #ifdef _WIN32
281 | VirtualFree(ctx->long_state, 0, MEM_RELEASE);
282 | #else
283 | if (ctx->ctx_info[1] != 0)
284 | munlock(ctx->long_state, hashMemSize);
285 | munmap(ctx->long_state, hashMemSize);
286 | #endif // _WIN32
287 | }
288 | else
289 | _mm_free(ctx->long_state);
290 |
291 | _mm_free(ctx);
292 | }
293 |
--------------------------------------------------------------------------------
/src/main/jni/groestl_tables.h:
--------------------------------------------------------------------------------
1 | #ifndef __tables_h
2 | #define __tables_h
3 |
4 |
5 | const uint32_t T[512] = {0xa5f432c6, 0xc6a597f4, 0x84976ff8, 0xf884eb97, 0x99b05eee, 0xee99c7b0, 0x8d8c7af6, 0xf68df78c, 0xd17e8ff, 0xff0de517, 0xbddc0ad6, 0xd6bdb7dc, 0xb1c816de, 0xdeb1a7c8, 0x54fc6d91, 0x915439fc
6 | , 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5
7 | , 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d
8 | , 0xec2f6e41, 0x41ec822f, 0x67a91ab3, 0xb3677da9, 0xfd1c435f, 0x5ffdbe1c, 0xea256045, 0x45ea8a25, 0xbfdaf923, 0x23bf46da, 0xf7025153, 0x53f7a602, 0x96a145e4, 0xe496d3a1, 0x5bed769b, 0x9b5b2ded
9 | , 0xc25d2875, 0x75c2ea5d, 0x1c24c5e1, 0xe11cd924, 0xaee9d43d, 0x3dae7ae9, 0x6abef24c, 0x4c6a98be, 0x5aee826c, 0x6c5ad8ee, 0x41c3bd7e, 0x7e41fcc3, 0x206f3f5, 0xf502f106, 0x4fd15283, 0x834f1dd1
10 | , 0x5ce48c68, 0x685cd0e4, 0xf4075651, 0x51f4a207, 0x345c8dd1, 0xd134b95c, 0x818e1f9, 0xf908e918, 0x93ae4ce2, 0xe293dfae, 0x73953eab, 0xab734d95, 0x53f59762, 0x6253c4f5, 0x3f416b2a, 0x2a3f5441
11 | , 0xc141c08, 0x80c1014, 0x52f66395, 0x955231f6, 0x65afe946, 0x46658caf, 0x5ee27f9d, 0x9d5e21e2, 0x28784830, 0x30286078, 0xa1f8cf37, 0x37a16ef8, 0xf111b0a, 0xa0f1411, 0xb5c4eb2f, 0x2fb55ec4
12 | , 0x91b150e, 0xe091c1b, 0x365a7e24, 0x2436485a, 0x9bb6ad1b, 0x1b9b36b6, 0x3d4798df, 0xdf3da547, 0x266aa7cd, 0xcd26816a, 0x69bbf54e, 0x4e699cbb, 0xcd4c337f, 0x7fcdfe4c, 0x9fba50ea, 0xea9fcfba
13 | , 0x1b2d3f12, 0x121b242d, 0x9eb9a41d, 0x1d9e3ab9, 0x749cc458, 0x5874b09c, 0x2e724634, 0x342e6872, 0x2d774136, 0x362d6c77, 0xb2cd11dc, 0xdcb2a3cd, 0xee299db4, 0xb4ee7329, 0xfb164d5b, 0x5bfbb616
14 | , 0xf601a5a4, 0xa4f65301, 0x4dd7a176, 0x764decd7, 0x61a314b7, 0xb76175a3, 0xce49347d, 0x7dcefa49, 0x7b8ddf52, 0x527ba48d, 0x3e429fdd, 0xdd3ea142, 0x7193cd5e, 0x5e71bc93, 0x97a2b113, 0x139726a2
15 | , 0xf504a2a6, 0xa6f55704, 0x68b801b9, 0xb96869b8, 0x0, 0x0, 0x2c74b5c1, 0xc12c9974, 0x60a0e040, 0x406080a0, 0x1f21c2e3, 0xe31fdd21, 0xc8433a79, 0x79c8f243, 0xed2c9ab6, 0xb6ed772c
16 | , 0xbed90dd4, 0xd4beb3d9, 0x46ca478d, 0x8d4601ca, 0xd9701767, 0x67d9ce70, 0x4bddaf72, 0x724be4dd, 0xde79ed94, 0x94de3379, 0xd467ff98, 0x98d42b67, 0xe82393b0, 0xb0e87b23, 0x4ade5b85, 0x854a11de
17 | , 0x6bbd06bb, 0xbb6b6dbd, 0x2a7ebbc5, 0xc52a917e, 0xe5347b4f, 0x4fe59e34, 0x163ad7ed, 0xed16c13a, 0xc554d286, 0x86c51754, 0xd762f89a, 0x9ad72f62, 0x55ff9966, 0x6655ccff, 0x94a7b611, 0x119422a7
18 | , 0xcf4ac08a, 0x8acf0f4a, 0x1030d9e9, 0xe910c930, 0x60a0e04, 0x406080a, 0x819866fe, 0xfe81e798, 0xf00baba0, 0xa0f05b0b, 0x44ccb478, 0x7844f0cc, 0xbad5f025, 0x25ba4ad5, 0xe33e754b, 0x4be3963e
19 | , 0xf30eaca2, 0xa2f35f0e, 0xfe19445d, 0x5dfeba19, 0xc05bdb80, 0x80c01b5b, 0x8a858005, 0x58a0a85, 0xadecd33f, 0x3fad7eec, 0xbcdffe21, 0x21bc42df, 0x48d8a870, 0x7048e0d8, 0x40cfdf1, 0xf104f90c
20 | , 0xdf7a1963, 0x63dfc67a, 0xc1582f77, 0x77c1ee58, 0x759f30af, 0xaf75459f, 0x63a5e742, 0x426384a5, 0x30507020, 0x20304050, 0x1a2ecbe5, 0xe51ad12e, 0xe12effd, 0xfd0ee112, 0x6db708bf, 0xbf6d65b7
21 | , 0x4cd45581, 0x814c19d4, 0x143c2418, 0x1814303c, 0x355f7926, 0x26354c5f, 0x2f71b2c3, 0xc32f9d71, 0xe13886be, 0xbee16738, 0xa2fdc835, 0x35a26afd, 0xcc4fc788, 0x88cc0b4f, 0x394b652e, 0x2e395c4b
22 | , 0x57f96a93, 0x93573df9, 0xf20d5855, 0x55f2aa0d, 0x829d61fc, 0xfc82e39d, 0x47c9b37a, 0x7a47f4c9, 0xacef27c8, 0xc8ac8bef, 0xe73288ba, 0xbae76f32, 0x2b7d4f32, 0x322b647d, 0x95a442e6, 0xe695d7a4
23 | , 0xa0fb3bc0, 0xc0a09bfb, 0x98b3aa19, 0x199832b3, 0xd168f69e, 0x9ed12768, 0x7f8122a3, 0xa37f5d81, 0x66aaee44, 0x446688aa, 0x7e82d654, 0x547ea882, 0xabe6dd3b, 0x3bab76e6, 0x839e950b, 0xb83169e
24 | , 0xca45c98c, 0x8cca0345, 0x297bbcc7, 0xc729957b, 0xd36e056b, 0x6bd3d66e, 0x3c446c28, 0x283c5044, 0x798b2ca7, 0xa779558b, 0xe23d81bc, 0xbce2633d, 0x1d273116, 0x161d2c27, 0x769a37ad, 0xad76419a
25 | , 0x3b4d96db, 0xdb3bad4d, 0x56fa9e64, 0x6456c8fa, 0x4ed2a674, 0x744ee8d2, 0x1e223614, 0x141e2822, 0xdb76e492, 0x92db3f76, 0xa1e120c, 0xc0a181e, 0x6cb4fc48, 0x486c90b4, 0xe4378fb8, 0xb8e46b37
26 | , 0x5de7789f, 0x9f5d25e7, 0x6eb20fbd, 0xbd6e61b2, 0xef2a6943, 0x43ef862a, 0xa6f135c4, 0xc4a693f1, 0xa8e3da39, 0x39a872e3, 0xa4f7c631, 0x31a462f7, 0x37598ad3, 0xd337bd59, 0x8b8674f2, 0xf28bff86
27 | , 0x325683d5, 0xd532b156, 0x43c54e8b, 0x8b430dc5, 0x59eb856e, 0x6e59dceb, 0xb7c218da, 0xdab7afc2, 0x8c8f8e01, 0x18c028f, 0x64ac1db1, 0xb16479ac, 0xd26df19c, 0x9cd2236d, 0xe03b7249, 0x49e0923b
28 | , 0xb4c71fd8, 0xd8b4abc7, 0xfa15b9ac, 0xacfa4315, 0x709faf3, 0xf307fd09, 0x256fa0cf, 0xcf25856f, 0xafea20ca, 0xcaaf8fea, 0x8e897df4, 0xf48ef389, 0xe9206747, 0x47e98e20, 0x18283810, 0x10182028
29 | , 0xd5640b6f, 0x6fd5de64, 0x888373f0, 0xf088fb83, 0x6fb1fb4a, 0x4a6f94b1, 0x7296ca5c, 0x5c72b896, 0x246c5438, 0x3824706c, 0xf1085f57, 0x57f1ae08, 0xc7522173, 0x73c7e652, 0x51f36497, 0x975135f3
30 | , 0x2365aecb, 0xcb238d65, 0x7c8425a1, 0xa17c5984, 0x9cbf57e8, 0xe89ccbbf, 0x21635d3e, 0x3e217c63, 0xdd7cea96, 0x96dd377c, 0xdc7f1e61, 0x61dcc27f, 0x86919c0d, 0xd861a91, 0x85949b0f, 0xf851e94
31 | , 0x90ab4be0, 0xe090dbab, 0x42c6ba7c, 0x7c42f8c6, 0xc4572671, 0x71c4e257, 0xaae529cc, 0xccaa83e5, 0xd873e390, 0x90d83b73, 0x50f0906, 0x6050c0f, 0x103f4f7, 0xf701f503, 0x12362a1c, 0x1c123836
32 | , 0xa3fe3cc2, 0xc2a39ffe, 0x5fe18b6a, 0x6a5fd4e1, 0xf910beae, 0xaef94710, 0xd06b0269, 0x69d0d26b, 0x91a8bf17, 0x17912ea8, 0x58e87199, 0x995829e8, 0x2769533a, 0x3a277469, 0xb9d0f727, 0x27b94ed0
33 | , 0x384891d9, 0xd938a948, 0x1335deeb, 0xeb13cd35, 0xb3cee52b, 0x2bb356ce, 0x33557722, 0x22334455, 0xbbd604d2, 0xd2bbbfd6, 0x709039a9, 0xa9704990, 0x89808707, 0x7890e80, 0xa7f2c133, 0x33a766f2
34 | , 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e
35 | , 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3
36 | , 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e};
37 |
38 | #endif /* __tables_h */
39 |
--------------------------------------------------------------------------------
/src/main/jni/hash.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | typedef unsigned char BitSequence;
6 | typedef uint32_t DataLength;
7 | typedef enum {SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2} HashReturn;
8 |
--------------------------------------------------------------------------------
/src/main/jni/hasher.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 | #include "jni.h"
6 | #include "cryptonight_aesni.h"
7 |
8 | /* Some parts are taken from XMR-STAK project, you can find here https://github.com/fireice-uk/xmr-stak*/
9 | extern "C" {
10 |
11 | #define SIZE 5
12 | #define FUNC 1
13 |
14 | cryptonight_ctx* alloc_ctx()
15 | {
16 | cryptonight_ctx* ctx;
17 | alloc_msg msg = { 0 };
18 | ctx = cryptonight_alloc_ctx(1, 1, &msg);
19 | if (ctx == NULL) {
20 | ctx = cryptonight_alloc_ctx(1, 0, &msg);
21 | if (ctx == NULL) {
22 | if (ctx == NULL) {
23 | ctx = cryptonight_alloc_ctx(0, 0, NULL);
24 | }
25 | return ctx;
26 | }
27 | return ctx;
28 | }
29 | return nullptr;
30 | }
31 |
32 | unsigned char* as_unsigned_char_array(JNIEnv *env, jbyteArray array) {
33 | int len = env->GetArrayLength(array);
34 | unsigned char* buf = new unsigned char[len];
35 | env->GetByteArrayRegion(array, 0, len, reinterpret_cast(buf));
36 | return buf;
37 | }
38 |
39 | jbyteArray as_byte_array(JNIEnv *env, unsigned char* buf, int len) {
40 | jbyteArray array = env->NewByteArray(len);
41 | env->SetByteArrayRegion(array, 0, len, reinterpret_cast(buf));
42 | return array;
43 | }
44 |
45 | JNIEXPORT void JNICALL Java_tk_netindev_drill_hasher_Hasher_slowHash(JNIEnv *env, jclass clazz, jbyteArray input, jbyteArray output) {
46 | unsigned char* inputBuffer = as_unsigned_char_array(env, input);
47 | unsigned char* outputBuffer = as_unsigned_char_array(env, output);
48 | cryptonight_ctx* ctx[SIZE];
49 | for (int i = 0; i < SIZE; i++) {
50 | ctx[i] = alloc_ctx();
51 | }
52 | Cryptonight_hash::template hash(inputBuffer, env->GetArrayLength(input), outputBuffer, ctx);
53 | for (int i = 0; i < SIZE; i++) {
54 | cryptonight_free_ctx(ctx[i]);
55 | }
56 | //env->ReleaseByteArrayElements(input, (jbyte *)inputBuffer, JNI_ABORT);
57 | env->ReleaseByteArrayElements(output, (jbyte *)outputBuffer, JNI_COMMIT);
58 | }
59 |
60 | };
--------------------------------------------------------------------------------
/src/main/jni/int-util.h:
--------------------------------------------------------------------------------
1 | // Copyright(c) 2012 - 2013 The Cryptonote developers
2 | // Distributed under the MIT/X11 software license, see the accompanying
3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 |
5 | #pragma once
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #if defined(_MSC_VER)
13 | #include
14 |
15 | static inline uint32_t rol32(uint32_t x, int r) {
16 | static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers");
17 | return _rotl(x, r);
18 | }
19 |
20 | static inline uint64_t rol64(uint64_t x, int r) {
21 | return _rotl64(x, r);
22 | }
23 |
24 | #else
25 |
26 | static inline uint32_t rol32(uint32_t x, int r) {
27 | return (x << (r & 31)) | (x >> (-r & 31));
28 | }
29 |
30 | static inline uint64_t rol64(uint64_t x, int r) {
31 | return (x << (r & 63)) | (x >> (-r & 63));
32 | }
33 |
34 | #endif
35 |
36 | static inline uint64_t hi_dword(uint64_t val) {
37 | return val >> 32;
38 | }
39 |
40 | static inline uint64_t lo_dword(uint64_t val) {
41 | return val & 0xFFFFFFFF;
42 | }
43 |
44 | static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) {
45 | dividend |= ((uint64_t)*remainder) << 32;
46 | *remainder = dividend % divisor;
47 | return dividend / divisor;
48 | }
49 |
50 | // Long division with 2^32 base
51 | static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) {
52 | uint64_t dividend_dwords[4];
53 | uint32_t remainder = 0;
54 |
55 | dividend_dwords[3] = hi_dword(dividend_hi);
56 | dividend_dwords[2] = lo_dword(dividend_hi);
57 | dividend_dwords[1] = hi_dword(dividend_lo);
58 | dividend_dwords[0] = lo_dword(dividend_lo);
59 |
60 | *quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32;
61 | *quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder);
62 | *quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32;
63 | *quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder);
64 |
65 | return remainder;
66 | }
67 |
68 | #define IDENT32(x) ((uint32_t) (x))
69 | #define IDENT64(x) ((uint64_t) (x))
70 |
71 | #define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \
72 | (((uint32_t) (x) & 0x0000ff00) << 8) | \
73 | (((uint32_t) (x) & 0x00ff0000) >> 8) | \
74 | (((uint32_t) (x) & 0xff000000) >> 24))
75 | #define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \
76 | (((uint64_t) (x) & 0x000000000000ff00) << 40) | \
77 | (((uint64_t) (x) & 0x0000000000ff0000) << 24) | \
78 | (((uint64_t) (x) & 0x00000000ff000000) << 8) | \
79 | (((uint64_t) (x) & 0x000000ff00000000) >> 8) | \
80 | (((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \
81 | (((uint64_t) (x) & 0x00ff000000000000) >> 40) | \
82 | (((uint64_t) (x) & 0xff00000000000000) >> 56))
83 |
84 | static inline uint32_t ident32(uint32_t x) { return x; }
85 | static inline uint64_t ident64(uint64_t x) { return x; }
86 |
87 | static inline uint32_t swap32(uint32_t x) {
88 | x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
89 | return (x << 16) | (x >> 16);
90 | }
91 | static inline uint64_t swap64(uint64_t x) {
92 | x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8);
93 | x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16);
94 | return (x << 32) | (x >> 32);
95 | }
96 |
97 | #if defined(__GNUC__)
98 | #define UNUSED __attribute__((unused))
99 | #else
100 | #define UNUSED
101 | #endif
102 | static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { }
103 | #undef UNUSED
104 |
105 | static inline void mem_inplace_swap32(void *mem, size_t n) {
106 | size_t i;
107 | for (i = 0; i < n; i++) {
108 | ((uint32_t *)mem)[i] = swap32(((const uint32_t *)mem)[i]);
109 | }
110 | }
111 | static inline void mem_inplace_swap64(void *mem, size_t n) {
112 | size_t i;
113 | for (i = 0; i < n; i++) {
114 | ((uint64_t *)mem)[i] = swap64(((const uint64_t *)mem)[i]);
115 | }
116 | }
117 |
118 | static inline void memcpy_ident32(void *dst, const void *src, size_t n) {
119 | memcpy(dst, src, 4 * n);
120 | }
121 | static inline void memcpy_ident64(void *dst, const void *src, size_t n) {
122 | memcpy(dst, src, 8 * n);
123 | }
124 |
125 | static inline void memcpy_swap32(void *dst, const void *src, size_t n) {
126 | size_t i;
127 | for (i = 0; i < n; i++) {
128 | ((uint32_t *)dst)[i] = swap32(((const uint32_t *)src)[i]);
129 | }
130 | }
131 | static inline void memcpy_swap64(void *dst, const void *src, size_t n) {
132 | size_t i;
133 | for (i = 0; i < n; i++) {
134 | ((uint64_t *)dst)[i] = swap64(((const uint64_t *)src)[i]);
135 | }
136 | }
137 |
138 | #define SWAP32LE IDENT32
139 | #define SWAP32BE SWAP32
140 | #define swap32le ident32
141 | #define swap32be swap32
142 | #define mem_inplace_swap32le mem_inplace_ident
143 | #define mem_inplace_swap32be mem_inplace_swap32
144 | #define memcpy_swap32le memcpy_ident32
145 | #define memcpy_swap32be memcpy_swap32
146 | #define SWAP64LE IDENT64
147 | #define SWAP64BE SWAP64
148 | #define swap64le ident64
149 | #define swap64be swap64
150 | #define mem_inplace_swap64le mem_inplace_ident
151 | #define mem_inplace_swap64be mem_inplace_swap64
152 | #define memcpy_swap64le memcpy_ident64
153 | #define memcpy_swap64be memcpy_swap64
--------------------------------------------------------------------------------
/src/main/jni/skein_port.h:
--------------------------------------------------------------------------------
1 | #ifndef _SKEIN_PORT_H_
2 | #define _SKEIN_PORT_H_
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #ifndef RETURN_VALUES
9 | # define RETURN_VALUES
10 | # if defined( DLL_EXPORT )
11 | # if defined( _MSC_VER ) || defined ( __INTEL_COMPILER )
12 | # define VOID_RETURN __declspec( dllexport ) void __stdcall
13 | # define INT_RETURN __declspec( dllexport ) int __stdcall
14 | # elif defined( __GNUC__ )
15 | # define VOID_RETURN __declspec( __dllexport__ ) void
16 | # define INT_RETURN __declspec( __dllexport__ ) int
17 | # else
18 | # error Use of the DLL is only available on the Microsoft, Intel and GCC compilers
19 | # endif
20 | # elif defined( DLL_IMPORT )
21 | # if defined( _MSC_VER ) || defined ( __INTEL_COMPILER )
22 | # define VOID_RETURN __declspec( dllimport ) void __stdcall
23 | # define INT_RETURN __declspec( dllimport ) int __stdcall
24 | # elif defined( __GNUC__ )
25 | # define VOID_RETURN __declspec( __dllimport__ ) void
26 | # define INT_RETURN __declspec( __dllimport__ ) int
27 | # else
28 | # error Use of the DLL is only available on the Microsoft, Intel and GCC compilers
29 | # endif
30 | # elif defined( __WATCOMC__ )
31 | # define VOID_RETURN void __cdecl
32 | # define INT_RETURN int __cdecl
33 | # else
34 | # define VOID_RETURN void
35 | # define INT_RETURN int
36 | # endif
37 | #endif
38 |
39 | /* These defines are used to declare buffers in a way that allows
40 | faster operations on longer variables to be used. In all these
41 | defines 'size' must be a power of 2 and >= 8
42 |
43 | dec_unit_type(size,x) declares a variable 'x' of length
44 | 'size' bits
45 |
46 | dec_bufr_type(size,bsize,x) declares a buffer 'x' of length 'bsize'
47 | bytes defined as an array of variables
48 | each of 'size' bits (bsize must be a
49 | multiple of size / 8)
50 |
51 | ptr_cast(x,size) casts a pointer to a pointer to a
52 | variable of length 'size' bits
53 | */
54 |
55 | #define ui_type(size) uint##size##_t
56 | #define dec_unit_type(size,x) typedef ui_type(size) x
57 | #define dec_bufr_type(size,bsize,x) typedef ui_type(size) x[bsize / (size >> 3)]
58 | #define ptr_cast(x,size) ((ui_type(size)*)(x))
59 |
60 | typedef unsigned int uint_t; /* native unsigned integer */
61 | typedef uint8_t u08b_t; /* 8-bit unsigned integer */
62 | typedef uint64_t u64b_t; /* 64-bit unsigned integer */
63 |
64 | #ifndef RotL_64
65 | #define RotL_64(x,N) (((x) << (N)) | ((x) >> (64-(N))))
66 | #endif
67 |
68 | /*
69 | * Skein is "natively" little-endian (unlike SHA-xxx), for optimal
70 | * performance on x86 CPUs. The Skein code requires the following
71 | * definitions for dealing with endianness:
72 | *
73 | * SKEIN_NEED_SWAP: 0 for little-endian, 1 for big-endian
74 | * Skein_Put64_LSB_First
75 | * Skein_Get64_LSB_First
76 | * Skein_Swap64
77 | *
78 | * If SKEIN_NEED_SWAP is defined at compile time, it is used here
79 | * along with the portable versions of Put64/Get64/Swap64, which
80 | * are slow in general.
81 | *
82 | * Otherwise, an "auto-detect" of endianness is attempted below.
83 | * If the default handling doesn't work well, the user may insert
84 | * platform-specific code instead (e.g., for big-endian CPUs).
85 | *
86 | */
87 | #ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */
88 |
89 | #define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
90 |
91 | /* special handler for IA64, which may be either endianness (?) */
92 | /* here we assume little-endian, but this may need to be changed */
93 | #if defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
94 | # define PLATFORM_MUST_ALIGN (1)
95 | #ifndef PLATFORM_BYTE_ORDER
96 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
97 | #endif
98 | #endif
99 |
100 | #ifndef PLATFORM_MUST_ALIGN
101 | # define PLATFORM_MUST_ALIGN (0)
102 | #endif
103 |
104 |
105 | #if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN
106 | /* here for big-endian CPUs */
107 | #define SKEIN_NEED_SWAP (1)
108 | #elif PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN
109 | /* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */
110 | #define SKEIN_NEED_SWAP (0)
111 | #if PLATFORM_MUST_ALIGN == 0 /* ok to use "fast" versions? */
112 | #define Skein_Put64_LSB_First(dst08,src64,bCnt) memcpy(dst08,src64,bCnt)
113 | #define Skein_Get64_LSB_First(dst64,src08,wCnt) memcpy(dst64,src08,8*(wCnt))
114 | #endif
115 | #else
116 | #error "Skein needs endianness setting!"
117 | #endif
118 |
119 | #endif /* ifndef SKEIN_NEED_SWAP */
120 |
121 | /*
122 | ******************************************************************
123 | * Provide any definitions still needed.
124 | ******************************************************************
125 | */
126 | #ifndef Skein_Swap64 /* swap for big-endian, nop for little-endian */
127 | #if SKEIN_NEED_SWAP
128 | #define Skein_Swap64(w64) \
129 | ( (( ((u64b_t)(w64)) & 0xFF) << 56) | \
130 | (((((u64b_t)(w64)) >> 8) & 0xFF) << 48) | \
131 | (((((u64b_t)(w64)) >>16) & 0xFF) << 40) | \
132 | (((((u64b_t)(w64)) >>24) & 0xFF) << 32) | \
133 | (((((u64b_t)(w64)) >>32) & 0xFF) << 24) | \
134 | (((((u64b_t)(w64)) >>40) & 0xFF) << 16) | \
135 | (((((u64b_t)(w64)) >>48) & 0xFF) << 8) | \
136 | (((((u64b_t)(w64)) >>56) & 0xFF) ) )
137 | #else
138 | #define Skein_Swap64(w64) (w64)
139 | #endif
140 | #endif /* ifndef Skein_Swap64 */
141 |
142 |
143 | #ifndef Skein_Put64_LSB_First
144 | void Skein_Put64_LSB_First(u08b_t *dst,const u64b_t *src,size_t bCnt)
145 | #ifdef SKEIN_PORT_CODE /* instantiate the function code here? */
146 | { /* this version is fully portable (big-endian or little-endian), but slow */
147 | size_t n;
148 |
149 | for (n=0;n>3] >> (8*(n&7)));
151 | }
152 | #else
153 | ; /* output only the function prototype */
154 | #endif
155 | #endif /* ifndef Skein_Put64_LSB_First */
156 |
157 |
158 | #ifndef Skein_Get64_LSB_First
159 | void Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt)
160 | #ifdef SKEIN_PORT_CODE /* instantiate the function code here? */
161 | { /* this version is fully portable (big-endian or little-endian), but slow */
162 | size_t n;
163 |
164 | for (n=0;n<8*wCnt;n+=8)
165 | dst[n/8] = (((u64b_t) src[n ]) ) +
166 | (((u64b_t) src[n+1]) << 8) +
167 | (((u64b_t) src[n+2]) << 16) +
168 | (((u64b_t) src[n+3]) << 24) +
169 | (((u64b_t) src[n+4]) << 32) +
170 | (((u64b_t) src[n+5]) << 40) +
171 | (((u64b_t) src[n+6]) << 48) +
172 | (((u64b_t) src[n+7]) << 56) ;
173 | }
174 | #else
175 | ; /* output only the function prototype */
176 | #endif
177 | #endif /* ifndef Skein_Get64_LSB_First */
178 |
179 | #endif /* ifndef _SKEIN_PORT_H_ */
180 |
--------------------------------------------------------------------------------
/src/main/jni/soft_aes.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software: you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation, either version 3 of the License, or
5 | * any later version.
6 | *
7 | * This program is distributed in the hope that it will be useful,
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | * GNU General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU General Public License
13 | * along with this program. If not, see .
14 | *
15 | * Additional permission under GNU GPL version 3 section 7
16 | *
17 | * If you modify this Program, or any covered work, by linking or combining
18 | * it with OpenSSL (or a modified version of that library), containing parts
19 | * covered by the terms of OpenSSL License and SSLeay License, the licensors
20 | * of this Program grant you additional permission to convey the resulting work.
21 | *
22 | */
23 |
24 | /*
25 | * Parts of this file are originally copyright (c) 2014-2017, The Monero Project
26 | */
27 | #pragma once
28 |
29 | #ifdef __GNUC__
30 | #include
31 | #else
32 | #include
33 | #endif // __GNUC__
34 |
35 | #include
36 |
37 | #define saes_data(w) {\
38 | w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
39 | w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
40 | w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
41 | w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
42 | w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
43 | w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
44 | w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
45 | w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
46 | w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
47 | w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
48 | w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
49 | w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
50 | w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
51 | w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
52 | w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
53 | w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
54 | w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
55 | w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
56 | w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
57 | w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
58 | w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
59 | w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
60 | w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
61 | w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
62 | w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
63 | w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
64 | w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
65 | w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
66 | w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
67 | w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
68 | w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
69 | w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
70 |
71 | #define SAES_WPOLY 0x011b
72 |
73 | #define saes_b2w(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | \
74 | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
75 |
76 | #define saes_f2(x) ((x<<1) ^ (((x>>7) & 1) * SAES_WPOLY))
77 | #define saes_f3(x) (saes_f2(x) ^ x)
78 | #define saes_h0(x) (x)
79 |
80 | #define saes_u0(p) saes_b2w(saes_f2(p), p, p, saes_f3(p))
81 | #define saes_u1(p) saes_b2w(saes_f3(p), saes_f2(p), p, p)
82 | #define saes_u2(p) saes_b2w( p, saes_f3(p), saes_f2(p), p)
83 | #define saes_u3(p) saes_b2w( p, p, saes_f3(p), saes_f2(p))
84 |
85 | alignas(16) const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) };
86 | alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0);
87 |
88 | static inline __m128i soft_aesenc(__m128i in, __m128i key)
89 | {
90 | uint32_t x0, x1, x2, x3;
91 | x0 = _mm_cvtsi128_si32(in);
92 | x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0x55));
93 | x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xAA));
94 | x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xFF));
95 |
96 | __m128i out = _mm_set_epi32(
97 | (saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]),
98 | (saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^ saes_table[3][x1 >> 24]),
99 | (saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^ saes_table[3][x0 >> 24]),
100 | (saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^ saes_table[3][x3 >> 24]));
101 |
102 | return _mm_xor_si128(out, key);
103 | }
104 |
105 | static inline uint32_t sub_word(uint32_t key)
106 | {
107 | return (saes_sbox[key >> 24 ] << 24) |
108 | (saes_sbox[(key >> 16) & 0xff] << 16 ) |
109 | (saes_sbox[(key >> 8) & 0xff] << 8 ) |
110 | saes_sbox[key & 0xff];
111 | }
112 |
113 | #ifdef __clang__
114 | static inline uint32_t _rotr(uint32_t value, uint32_t amount)
115 | {
116 | return (value >> amount) | (value << ((32 - amount) & 31));
117 | }
118 | #endif
119 |
120 | static inline __m128i soft_aeskeygenassist(__m128i key, uint8_t rcon)
121 | {
122 | uint32_t X1 = sub_word(_mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0x55)));
123 | uint32_t X3 = sub_word(_mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0xFF)));
124 | return _mm_set_epi32(_rotr(X3, 8) ^ rcon, X3,_rotr(X1, 8) ^ rcon, X1);
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/resources/simplelogger.properties:
--------------------------------------------------------------------------------
1 | org.slf4j.simpleLogger.logFile=System.out
2 | org.slf4j.simpleLogger.showDateTime=true
3 | org.slf4j.simpleLogger.dateTimeFormat=[HH:mm:ss]
4 | org.slf4j.simpleLogger.showThreadName=false
5 | org.slf4j.simpleLogger.showLogName=false
6 | org.slf4j.simpleLogger.levelInBrackets=true
--------------------------------------------------------------------------------
/src/main/resources/unix/x64/libcryptonight.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/netindev/drill/714f2e736457bde90fe610921cce1b4be5c2761c/src/main/resources/unix/x64/libcryptonight.so
--------------------------------------------------------------------------------
/src/main/resources/win/x64/cryptonight.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/netindev/drill/714f2e736457bde90fe610921cce1b4be5c2761c/src/main/resources/win/x64/cryptonight.dll
--------------------------------------------------------------------------------