sorcery-argon2 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/codeql.yml +74 -0
- data/.github/workflows/ruby.yml +13 -3
- data/.rubocop.yml +112 -2
- data/CHANGELOG.md +8 -0
- data/MAINTAINING.md +8 -3
- data/README.md +155 -14
- data/bin/setup +4 -0
- data/ext/argon2_wrap/{Makefile → Makefile.real} +1 -0
- data/ext/argon2_wrap/extconf.rb +4 -1
- data/ext/argon2_wrap/libargon2_wrap.so +0 -0
- data/ext/argon2_wrap/tests +0 -0
- data/ext/phc-winner-argon2/.git +1 -0
- data/ext/phc-winner-argon2/.gitattributes +10 -0
- data/ext/phc-winner-argon2/.gitignore +22 -0
- data/ext/phc-winner-argon2/.travis.yml +25 -0
- data/ext/phc-winner-argon2/Argon2.sln +158 -0
- data/ext/phc-winner-argon2/CHANGELOG.md +32 -0
- data/ext/phc-winner-argon2/LICENSE +314 -0
- data/ext/phc-winner-argon2/Makefile +255 -0
- data/ext/phc-winner-argon2/Package.swift +46 -0
- data/ext/phc-winner-argon2/README.md +303 -0
- data/ext/phc-winner-argon2/appveyor.yml +25 -0
- data/ext/phc-winner-argon2/argon2-specs.pdf +0 -0
- data/ext/phc-winner-argon2/export.sh +7 -0
- data/ext/phc-winner-argon2/include/argon2.h +437 -0
- data/ext/phc-winner-argon2/kats/argon2d +12304 -0
- data/ext/phc-winner-argon2/kats/argon2d.shasum +1 -0
- data/ext/phc-winner-argon2/kats/argon2d_v16 +12304 -0
- data/ext/phc-winner-argon2/kats/argon2d_v16.shasum +1 -0
- data/ext/phc-winner-argon2/kats/argon2i +12304 -0
- data/ext/phc-winner-argon2/kats/argon2i.shasum +1 -0
- data/ext/phc-winner-argon2/kats/argon2i_v16 +12304 -0
- data/ext/phc-winner-argon2/kats/argon2i_v16.shasum +1 -0
- data/ext/phc-winner-argon2/kats/argon2id +12304 -0
- data/ext/phc-winner-argon2/kats/argon2id.shasum +1 -0
- data/ext/phc-winner-argon2/kats/argon2id_v16 +12304 -0
- data/ext/phc-winner-argon2/kats/argon2id_v16.shasum +1 -0
- data/ext/phc-winner-argon2/kats/check-sums.ps1 +42 -0
- data/ext/phc-winner-argon2/kats/check-sums.sh +13 -0
- data/ext/phc-winner-argon2/kats/test.ps1 +50 -0
- data/ext/phc-winner-argon2/kats/test.sh +49 -0
- data/ext/phc-winner-argon2/latex/IEEEtran.cls +6347 -0
- data/ext/phc-winner-argon2/latex/Makefile +18 -0
- data/ext/phc-winner-argon2/latex/argon2-specs.tex +920 -0
- data/ext/phc-winner-argon2/latex/pics/argon2-par.pdf +0 -0
- data/ext/phc-winner-argon2/latex/pics/compression.pdf +0 -0
- data/ext/phc-winner-argon2/latex/pics/generic.pdf +0 -0
- data/ext/phc-winner-argon2/latex/pics/power-distribution.jpg +0 -0
- data/ext/phc-winner-argon2/latex/tradeoff.bib +822 -0
- data/ext/phc-winner-argon2/libargon2.pc.in +18 -0
- data/ext/phc-winner-argon2/man/argon2.1 +57 -0
- data/ext/phc-winner-argon2/src/argon2.c +452 -0
- data/ext/phc-winner-argon2/src/bench.c +111 -0
- data/ext/phc-winner-argon2/src/blake2/blake2-impl.h +156 -0
- data/ext/phc-winner-argon2/src/blake2/blake2.h +89 -0
- data/ext/phc-winner-argon2/src/blake2/blake2b.c +390 -0
- data/ext/phc-winner-argon2/src/blake2/blamka-round-opt.h +471 -0
- data/ext/phc-winner-argon2/src/blake2/blamka-round-ref.h +56 -0
- data/ext/phc-winner-argon2/src/core.c +648 -0
- data/ext/phc-winner-argon2/src/core.h +228 -0
- data/ext/phc-winner-argon2/src/encoding.c +463 -0
- data/ext/phc-winner-argon2/src/encoding.h +57 -0
- data/ext/phc-winner-argon2/src/genkat.c +213 -0
- data/ext/phc-winner-argon2/src/genkat.h +51 -0
- data/ext/phc-winner-argon2/src/opt.c +283 -0
- data/ext/phc-winner-argon2/src/ref.c +194 -0
- data/ext/phc-winner-argon2/src/run.c +337 -0
- data/ext/phc-winner-argon2/src/test.c +289 -0
- data/ext/phc-winner-argon2/src/thread.c +57 -0
- data/ext/phc-winner-argon2/src/thread.h +67 -0
- data/ext/phc-winner-argon2/vs2015/Argon2Opt/Argon2Opt.vcxproj +231 -0
- data/ext/phc-winner-argon2/vs2015/Argon2Opt/Argon2Opt.vcxproj.filters +69 -0
- data/ext/phc-winner-argon2/vs2015/Argon2OptBench/Argon2OptBench.vcxproj +231 -0
- data/ext/phc-winner-argon2/vs2015/Argon2OptBench/Argon2OptBench.vcxproj.filters +69 -0
- data/ext/phc-winner-argon2/vs2015/Argon2OptDll/Argon2OptDll.vcxproj +230 -0
- data/ext/phc-winner-argon2/vs2015/Argon2OptDll/Argon2OptDll.vcxproj.filters +66 -0
- data/ext/phc-winner-argon2/vs2015/Argon2OptGenKAT/Argon2OptGenKAT.vcxproj +244 -0
- data/ext/phc-winner-argon2/vs2015/Argon2OptGenKAT/Argon2OptGenKAT.vcxproj.filters +72 -0
- data/ext/phc-winner-argon2/vs2015/Argon2OptTestCI/Argon2OptTestCI.vcxproj +235 -0
- data/ext/phc-winner-argon2/vs2015/Argon2OptTestCI/Argon2OptTestCI.vcxproj.filters +69 -0
- data/ext/phc-winner-argon2/vs2015/Argon2Ref/Argon2Ref.vcxproj +243 -0
- data/ext/phc-winner-argon2/vs2015/Argon2Ref/Argon2Ref.vcxproj.filters +69 -0
- data/ext/phc-winner-argon2/vs2015/Argon2RefBench/Argon2RefBench.vcxproj +231 -0
- data/ext/phc-winner-argon2/vs2015/Argon2RefBench/Argon2RefBench.vcxproj.filters +69 -0
- data/ext/phc-winner-argon2/vs2015/Argon2RefDll/Argon2RefDll.vcxproj +230 -0
- data/ext/phc-winner-argon2/vs2015/Argon2RefDll/Argon2RefDll.vcxproj.filters +66 -0
- data/ext/phc-winner-argon2/vs2015/Argon2RefGenKAT/Argon2RefGenKAT.vcxproj +232 -0
- data/ext/phc-winner-argon2/vs2015/Argon2RefGenKAT/Argon2RefGenKAT.vcxproj.filters +72 -0
- data/ext/phc-winner-argon2/vs2015/Argon2RefTestCI/Argon2RefTestCI.vcxproj +231 -0
- data/ext/phc-winner-argon2/vs2015/Argon2RefTestCI/Argon2RefTestCI.vcxproj.filters +69 -0
- data/lib/argon2/ffi_engine.rb +4 -4
- data/lib/argon2/password.rb +28 -5
- data/lib/argon2/version.rb +1 -1
- data/sorcery-argon2.gemspec +3 -2
- metadata +91 -8
@@ -0,0 +1,57 @@
|
|
1
|
+
/*
|
2
|
+
* Argon2 reference source code package - reference C implementations
|
3
|
+
*
|
4
|
+
* Copyright 2015
|
5
|
+
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
6
|
+
*
|
7
|
+
* You may use this work under the terms of a Creative Commons CC0 1.0
|
8
|
+
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
9
|
+
* these licenses can be found at:
|
10
|
+
*
|
11
|
+
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
12
|
+
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
*
|
14
|
+
* You should have received a copy of both of these licenses along with this
|
15
|
+
* software. If not, they may be obtained at the above URLs.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#ifndef ENCODING_H
|
19
|
+
#define ENCODING_H
|
20
|
+
#include "argon2.h"
|
21
|
+
|
22
|
+
#define ARGON2_MAX_DECODED_LANES UINT32_C(255)
|
23
|
+
#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
|
24
|
+
#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
|
25
|
+
|
26
|
+
/*
|
27
|
+
* encode an Argon2 hash string into the provided buffer. 'dst_len'
|
28
|
+
* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
|
29
|
+
* is less than the number of required characters (including the
|
30
|
+
* terminating 0), then this function returns ARGON2_ENCODING_ERROR.
|
31
|
+
*
|
32
|
+
* on success, ARGON2_OK is returned.
|
33
|
+
*/
|
34
|
+
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
35
|
+
argon2_type type);
|
36
|
+
|
37
|
+
/*
|
38
|
+
* Decodes an Argon2 hash string into the provided structure 'ctx'.
|
39
|
+
* The only fields that must be set prior to this call are ctx.saltlen and
|
40
|
+
* ctx.outlen (which must be the maximal salt and out length values that are
|
41
|
+
* allowed), ctx.salt and ctx.out (which must be buffers of the specified
|
42
|
+
* length), and ctx.pwd and ctx.pwdlen which must hold a valid password.
|
43
|
+
*
|
44
|
+
* Invalid input string causes an error. On success, the ctx is valid and all
|
45
|
+
* fields have been initialized.
|
46
|
+
*
|
47
|
+
* Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
|
48
|
+
*/
|
49
|
+
int decode_string(argon2_context *ctx, const char *str, argon2_type type);
|
50
|
+
|
51
|
+
/* Returns the length of the encoded byte stream with length len */
|
52
|
+
size_t b64len(uint32_t len);
|
53
|
+
|
54
|
+
/* Returns the length of the encoded number num */
|
55
|
+
size_t numlen(uint32_t num);
|
56
|
+
|
57
|
+
#endif
|
@@ -0,0 +1,213 @@
|
|
1
|
+
/*
|
2
|
+
* Argon2 reference source code package - reference C implementations
|
3
|
+
*
|
4
|
+
* Copyright 2015
|
5
|
+
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
6
|
+
*
|
7
|
+
* You may use this work under the terms of a Creative Commons CC0 1.0
|
8
|
+
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
9
|
+
* these licenses can be found at:
|
10
|
+
*
|
11
|
+
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
12
|
+
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
*
|
14
|
+
* You should have received a copy of both of these licenses along with this
|
15
|
+
* software. If not, they may be obtained at the above URLs.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include <stdio.h>
|
19
|
+
#include <stdlib.h>
|
20
|
+
#include <string.h>
|
21
|
+
#include "argon2.h"
|
22
|
+
#include "core.h"
|
23
|
+
#ifdef __MINGW32__
|
24
|
+
#include <inttypes.h>
|
25
|
+
#else
|
26
|
+
/* Don't use <inttypes.h> (it's not C89) */
|
27
|
+
#define PRIx64 "llx"
|
28
|
+
#endif
|
29
|
+
|
30
|
+
void initial_kat(const uint8_t *blockhash, const argon2_context *context,
|
31
|
+
argon2_type type) {
|
32
|
+
unsigned i;
|
33
|
+
|
34
|
+
if (blockhash != NULL && context != NULL) {
|
35
|
+
printf("=======================================\n");
|
36
|
+
|
37
|
+
printf("%s version number %d\n", argon2_type2string(type, 1),
|
38
|
+
context->version);
|
39
|
+
|
40
|
+
printf("=======================================\n");
|
41
|
+
|
42
|
+
|
43
|
+
printf("Memory: %u KiB, Iterations: %u, Parallelism: %u lanes, Tag "
|
44
|
+
"length: %u bytes\n",
|
45
|
+
context->m_cost, context->t_cost, context->lanes,
|
46
|
+
context->outlen);
|
47
|
+
|
48
|
+
printf("Password[%u]: ", context->pwdlen);
|
49
|
+
|
50
|
+
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
|
51
|
+
printf("CLEARED\n");
|
52
|
+
} else {
|
53
|
+
for (i = 0; i < context->pwdlen; ++i) {
|
54
|
+
printf("%2.2x ", ((unsigned char *)context->pwd)[i]);
|
55
|
+
}
|
56
|
+
|
57
|
+
printf("\n");
|
58
|
+
}
|
59
|
+
|
60
|
+
printf("Salt[%u]: ", context->saltlen);
|
61
|
+
|
62
|
+
for (i = 0; i < context->saltlen; ++i) {
|
63
|
+
printf("%2.2x ", ((unsigned char *)context->salt)[i]);
|
64
|
+
}
|
65
|
+
|
66
|
+
printf("\n");
|
67
|
+
|
68
|
+
printf("Secret[%u]: ", context->secretlen);
|
69
|
+
|
70
|
+
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
|
71
|
+
printf("CLEARED\n");
|
72
|
+
} else {
|
73
|
+
for (i = 0; i < context->secretlen; ++i) {
|
74
|
+
printf("%2.2x ", ((unsigned char *)context->secret)[i]);
|
75
|
+
}
|
76
|
+
|
77
|
+
printf("\n");
|
78
|
+
}
|
79
|
+
|
80
|
+
printf("Associated data[%u]: ", context->adlen);
|
81
|
+
|
82
|
+
for (i = 0; i < context->adlen; ++i) {
|
83
|
+
printf("%2.2x ", ((unsigned char *)context->ad)[i]);
|
84
|
+
}
|
85
|
+
|
86
|
+
printf("\n");
|
87
|
+
|
88
|
+
printf("Pre-hashing digest: ");
|
89
|
+
|
90
|
+
for (i = 0; i < ARGON2_PREHASH_DIGEST_LENGTH; ++i) {
|
91
|
+
printf("%2.2x ", ((unsigned char *)blockhash)[i]);
|
92
|
+
}
|
93
|
+
|
94
|
+
printf("\n");
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
void print_tag(const void *out, uint32_t outlen) {
|
99
|
+
unsigned i;
|
100
|
+
if (out != NULL) {
|
101
|
+
printf("Tag: ");
|
102
|
+
|
103
|
+
for (i = 0; i < outlen; ++i) {
|
104
|
+
printf("%2.2x ", ((uint8_t *)out)[i]);
|
105
|
+
}
|
106
|
+
|
107
|
+
printf("\n");
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
void internal_kat(const argon2_instance_t *instance, uint32_t pass) {
|
112
|
+
|
113
|
+
if (instance != NULL) {
|
114
|
+
uint32_t i, j;
|
115
|
+
printf("\n After pass %u:\n", pass);
|
116
|
+
|
117
|
+
for (i = 0; i < instance->memory_blocks; ++i) {
|
118
|
+
uint32_t how_many_words =
|
119
|
+
(instance->memory_blocks > ARGON2_QWORDS_IN_BLOCK)
|
120
|
+
? 1
|
121
|
+
: ARGON2_QWORDS_IN_BLOCK;
|
122
|
+
|
123
|
+
for (j = 0; j < how_many_words; ++j)
|
124
|
+
printf("Block %.4u [%3u]: %016" PRIx64 "\n", i, j,
|
125
|
+
(unsigned long long)instance->memory[i].v[j]);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
static void fatal(const char *error) {
|
131
|
+
fprintf(stderr, "Error: %s\n", error);
|
132
|
+
exit(1);
|
133
|
+
}
|
134
|
+
|
135
|
+
static void generate_testvectors(argon2_type type, const uint32_t version) {
|
136
|
+
#define TEST_OUTLEN 32
|
137
|
+
#define TEST_PWDLEN 32
|
138
|
+
#define TEST_SALTLEN 16
|
139
|
+
#define TEST_SECRETLEN 8
|
140
|
+
#define TEST_ADLEN 12
|
141
|
+
argon2_context context;
|
142
|
+
|
143
|
+
unsigned char out[TEST_OUTLEN];
|
144
|
+
unsigned char pwd[TEST_PWDLEN];
|
145
|
+
unsigned char salt[TEST_SALTLEN];
|
146
|
+
unsigned char secret[TEST_SECRETLEN];
|
147
|
+
unsigned char ad[TEST_ADLEN];
|
148
|
+
const allocate_fptr myown_allocator = NULL;
|
149
|
+
const deallocate_fptr myown_deallocator = NULL;
|
150
|
+
|
151
|
+
unsigned t_cost = 3;
|
152
|
+
unsigned m_cost = 32;
|
153
|
+
unsigned lanes = 4;
|
154
|
+
|
155
|
+
memset(pwd, 1, TEST_OUTLEN);
|
156
|
+
memset(salt, 2, TEST_SALTLEN);
|
157
|
+
memset(secret, 3, TEST_SECRETLEN);
|
158
|
+
memset(ad, 4, TEST_ADLEN);
|
159
|
+
|
160
|
+
context.out = out;
|
161
|
+
context.outlen = TEST_OUTLEN;
|
162
|
+
context.version = version;
|
163
|
+
context.pwd = pwd;
|
164
|
+
context.pwdlen = TEST_PWDLEN;
|
165
|
+
context.salt = salt;
|
166
|
+
context.saltlen = TEST_SALTLEN;
|
167
|
+
context.secret = secret;
|
168
|
+
context.secretlen = TEST_SECRETLEN;
|
169
|
+
context.ad = ad;
|
170
|
+
context.adlen = TEST_ADLEN;
|
171
|
+
context.t_cost = t_cost;
|
172
|
+
context.m_cost = m_cost;
|
173
|
+
context.lanes = lanes;
|
174
|
+
context.threads = lanes;
|
175
|
+
context.allocate_cbk = myown_allocator;
|
176
|
+
context.free_cbk = myown_deallocator;
|
177
|
+
context.flags = ARGON2_DEFAULT_FLAGS;
|
178
|
+
|
179
|
+
#undef TEST_OUTLEN
|
180
|
+
#undef TEST_PWDLEN
|
181
|
+
#undef TEST_SALTLEN
|
182
|
+
#undef TEST_SECRETLEN
|
183
|
+
#undef TEST_ADLEN
|
184
|
+
|
185
|
+
argon2_ctx(&context, type);
|
186
|
+
}
|
187
|
+
|
188
|
+
int main(int argc, char *argv[]) {
|
189
|
+
/* Get and check Argon2 type */
|
190
|
+
const char *type_str = (argc > 1) ? argv[1] : "i";
|
191
|
+
argon2_type type = Argon2_i;
|
192
|
+
uint32_t version = ARGON2_VERSION_NUMBER;
|
193
|
+
if (!strcmp(type_str, "d")) {
|
194
|
+
type = Argon2_d;
|
195
|
+
} else if (!strcmp(type_str, "i")) {
|
196
|
+
type = Argon2_i;
|
197
|
+
} else if (!strcmp(type_str, "id")) {
|
198
|
+
type = Argon2_id;
|
199
|
+
} else {
|
200
|
+
fatal("wrong Argon2 type");
|
201
|
+
}
|
202
|
+
|
203
|
+
/* Get and check Argon2 version number */
|
204
|
+
if (argc > 2) {
|
205
|
+
version = strtoul(argv[2], NULL, 10);
|
206
|
+
}
|
207
|
+
if (ARGON2_VERSION_10 != version && ARGON2_VERSION_NUMBER != version) {
|
208
|
+
fatal("wrong Argon2 version number");
|
209
|
+
}
|
210
|
+
|
211
|
+
generate_testvectors(type, version);
|
212
|
+
return ARGON2_OK;
|
213
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
/*
|
2
|
+
* Argon2 reference source code package - reference C implementations
|
3
|
+
*
|
4
|
+
* Copyright 2015
|
5
|
+
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
6
|
+
*
|
7
|
+
* You may use this work under the terms of a Creative Commons CC0 1.0
|
8
|
+
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
9
|
+
* these licenses can be found at:
|
10
|
+
*
|
11
|
+
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
12
|
+
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
*
|
14
|
+
* You should have received a copy of both of these licenses along with this
|
15
|
+
* software. If not, they may be obtained at the above URLs.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#ifndef ARGON2_KAT_H
|
19
|
+
#define ARGON2_KAT_H
|
20
|
+
|
21
|
+
#include "core.h"
|
22
|
+
|
23
|
+
/*
|
24
|
+
* Initial KAT function that prints the inputs to the file
|
25
|
+
* @param blockhash Array that contains pre-hashing digest
|
26
|
+
* @param context Holds inputs
|
27
|
+
* @param type Argon2 type
|
28
|
+
* @pre blockhash must point to INPUT_INITIAL_HASH_LENGTH bytes
|
29
|
+
* @pre context member pointers must point to allocated memory of size according
|
30
|
+
* to the length values
|
31
|
+
*/
|
32
|
+
void initial_kat(const uint8_t *blockhash, const argon2_context *context,
|
33
|
+
argon2_type type);
|
34
|
+
|
35
|
+
/*
|
36
|
+
* Function that prints the output tag
|
37
|
+
* @param out output array pointer
|
38
|
+
* @param outlen digest length
|
39
|
+
* @pre out must point to @a outlen bytes
|
40
|
+
**/
|
41
|
+
void print_tag(const void *out, uint32_t outlen);
|
42
|
+
|
43
|
+
/*
|
44
|
+
* Function that prints the internal state at given moment
|
45
|
+
* @param instance pointer to the current instance
|
46
|
+
* @param pass current pass number
|
47
|
+
* @pre instance must have necessary memory allocated
|
48
|
+
**/
|
49
|
+
void internal_kat(const argon2_instance_t *instance, uint32_t pass);
|
50
|
+
|
51
|
+
#endif
|
@@ -0,0 +1,283 @@
|
|
1
|
+
/*
|
2
|
+
* Argon2 reference source code package - reference C implementations
|
3
|
+
*
|
4
|
+
* Copyright 2015
|
5
|
+
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
6
|
+
*
|
7
|
+
* You may use this work under the terms of a Creative Commons CC0 1.0
|
8
|
+
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
9
|
+
* these licenses can be found at:
|
10
|
+
*
|
11
|
+
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
12
|
+
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
*
|
14
|
+
* You should have received a copy of both of these licenses along with this
|
15
|
+
* software. If not, they may be obtained at the above URLs.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include <stdint.h>
|
19
|
+
#include <string.h>
|
20
|
+
#include <stdlib.h>
|
21
|
+
|
22
|
+
#include "argon2.h"
|
23
|
+
#include "core.h"
|
24
|
+
|
25
|
+
#include "blake2/blake2.h"
|
26
|
+
#include "blake2/blamka-round-opt.h"
|
27
|
+
|
28
|
+
/*
|
29
|
+
* Function fills a new memory block and optionally XORs the old block over the new one.
|
30
|
+
* Memory must be initialized.
|
31
|
+
* @param state Pointer to the just produced block. Content will be updated(!)
|
32
|
+
* @param ref_block Pointer to the reference block
|
33
|
+
* @param next_block Pointer to the block to be XORed over. May coincide with @ref_block
|
34
|
+
* @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
|
35
|
+
* @pre all block pointers must be valid
|
36
|
+
*/
|
37
|
+
#if defined(__AVX512F__)
|
38
|
+
static void fill_block(__m512i *state, const block *ref_block,
|
39
|
+
block *next_block, int with_xor) {
|
40
|
+
__m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
|
41
|
+
unsigned int i;
|
42
|
+
|
43
|
+
if (with_xor) {
|
44
|
+
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
|
45
|
+
state[i] = _mm512_xor_si512(
|
46
|
+
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
|
47
|
+
block_XY[i] = _mm512_xor_si512(
|
48
|
+
state[i], _mm512_loadu_si512((const __m512i *)next_block->v + i));
|
49
|
+
}
|
50
|
+
} else {
|
51
|
+
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
|
52
|
+
block_XY[i] = state[i] = _mm512_xor_si512(
|
53
|
+
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
for (i = 0; i < 2; ++i) {
|
58
|
+
BLAKE2_ROUND_1(
|
59
|
+
state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
|
60
|
+
state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
|
61
|
+
}
|
62
|
+
|
63
|
+
for (i = 0; i < 2; ++i) {
|
64
|
+
BLAKE2_ROUND_2(
|
65
|
+
state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
|
66
|
+
state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
|
67
|
+
}
|
68
|
+
|
69
|
+
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
|
70
|
+
state[i] = _mm512_xor_si512(state[i], block_XY[i]);
|
71
|
+
_mm512_storeu_si512((__m512i *)next_block->v + i, state[i]);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
#elif defined(__AVX2__)
|
75
|
+
static void fill_block(__m256i *state, const block *ref_block,
|
76
|
+
block *next_block, int with_xor) {
|
77
|
+
__m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
|
78
|
+
unsigned int i;
|
79
|
+
|
80
|
+
if (with_xor) {
|
81
|
+
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
|
82
|
+
state[i] = _mm256_xor_si256(
|
83
|
+
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
|
84
|
+
block_XY[i] = _mm256_xor_si256(
|
85
|
+
state[i], _mm256_loadu_si256((const __m256i *)next_block->v + i));
|
86
|
+
}
|
87
|
+
} else {
|
88
|
+
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
|
89
|
+
block_XY[i] = state[i] = _mm256_xor_si256(
|
90
|
+
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
for (i = 0; i < 4; ++i) {
|
95
|
+
BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
|
96
|
+
state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
|
97
|
+
}
|
98
|
+
|
99
|
+
for (i = 0; i < 4; ++i) {
|
100
|
+
BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
|
101
|
+
state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
|
102
|
+
}
|
103
|
+
|
104
|
+
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
|
105
|
+
state[i] = _mm256_xor_si256(state[i], block_XY[i]);
|
106
|
+
_mm256_storeu_si256((__m256i *)next_block->v + i, state[i]);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
#else
|
110
|
+
static void fill_block(__m128i *state, const block *ref_block,
|
111
|
+
block *next_block, int with_xor) {
|
112
|
+
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
|
113
|
+
unsigned int i;
|
114
|
+
|
115
|
+
if (with_xor) {
|
116
|
+
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
117
|
+
state[i] = _mm_xor_si128(
|
118
|
+
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
|
119
|
+
block_XY[i] = _mm_xor_si128(
|
120
|
+
state[i], _mm_loadu_si128((const __m128i *)next_block->v + i));
|
121
|
+
}
|
122
|
+
} else {
|
123
|
+
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
124
|
+
block_XY[i] = state[i] = _mm_xor_si128(
|
125
|
+
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
for (i = 0; i < 8; ++i) {
|
130
|
+
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
|
131
|
+
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
|
132
|
+
state[8 * i + 6], state[8 * i + 7]);
|
133
|
+
}
|
134
|
+
|
135
|
+
for (i = 0; i < 8; ++i) {
|
136
|
+
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
|
137
|
+
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
|
138
|
+
state[8 * 6 + i], state[8 * 7 + i]);
|
139
|
+
}
|
140
|
+
|
141
|
+
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
142
|
+
state[i] = _mm_xor_si128(state[i], block_XY[i]);
|
143
|
+
_mm_storeu_si128((__m128i *)next_block->v + i, state[i]);
|
144
|
+
}
|
145
|
+
}
|
146
|
+
#endif
|
147
|
+
|
148
|
+
static void next_addresses(block *address_block, block *input_block) {
|
149
|
+
/*Temporary zero-initialized blocks*/
|
150
|
+
#if defined(__AVX512F__)
|
151
|
+
__m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK];
|
152
|
+
__m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK];
|
153
|
+
#elif defined(__AVX2__)
|
154
|
+
__m256i zero_block[ARGON2_HWORDS_IN_BLOCK];
|
155
|
+
__m256i zero2_block[ARGON2_HWORDS_IN_BLOCK];
|
156
|
+
#else
|
157
|
+
__m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
|
158
|
+
__m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
|
159
|
+
#endif
|
160
|
+
|
161
|
+
memset(zero_block, 0, sizeof(zero_block));
|
162
|
+
memset(zero2_block, 0, sizeof(zero2_block));
|
163
|
+
|
164
|
+
/*Increasing index counter*/
|
165
|
+
input_block->v[6]++;
|
166
|
+
|
167
|
+
/*First iteration of G*/
|
168
|
+
fill_block(zero_block, input_block, address_block, 0);
|
169
|
+
|
170
|
+
/*Second iteration of G*/
|
171
|
+
fill_block(zero2_block, address_block, address_block, 0);
|
172
|
+
}
|
173
|
+
|
174
|
+
void fill_segment(const argon2_instance_t *instance,
|
175
|
+
argon2_position_t position) {
|
176
|
+
block *ref_block = NULL, *curr_block = NULL;
|
177
|
+
block address_block, input_block;
|
178
|
+
uint64_t pseudo_rand, ref_index, ref_lane;
|
179
|
+
uint32_t prev_offset, curr_offset;
|
180
|
+
uint32_t starting_index, i;
|
181
|
+
#if defined(__AVX512F__)
|
182
|
+
__m512i state[ARGON2_512BIT_WORDS_IN_BLOCK];
|
183
|
+
#elif defined(__AVX2__)
|
184
|
+
__m256i state[ARGON2_HWORDS_IN_BLOCK];
|
185
|
+
#else
|
186
|
+
__m128i state[ARGON2_OWORDS_IN_BLOCK];
|
187
|
+
#endif
|
188
|
+
int data_independent_addressing;
|
189
|
+
|
190
|
+
if (instance == NULL) {
|
191
|
+
return;
|
192
|
+
}
|
193
|
+
|
194
|
+
data_independent_addressing =
|
195
|
+
(instance->type == Argon2_i) ||
|
196
|
+
(instance->type == Argon2_id && (position.pass == 0) &&
|
197
|
+
(position.slice < ARGON2_SYNC_POINTS / 2));
|
198
|
+
|
199
|
+
if (data_independent_addressing) {
|
200
|
+
init_block_value(&input_block, 0);
|
201
|
+
|
202
|
+
input_block.v[0] = position.pass;
|
203
|
+
input_block.v[1] = position.lane;
|
204
|
+
input_block.v[2] = position.slice;
|
205
|
+
input_block.v[3] = instance->memory_blocks;
|
206
|
+
input_block.v[4] = instance->passes;
|
207
|
+
input_block.v[5] = instance->type;
|
208
|
+
}
|
209
|
+
|
210
|
+
starting_index = 0;
|
211
|
+
|
212
|
+
if ((0 == position.pass) && (0 == position.slice)) {
|
213
|
+
starting_index = 2; /* we have already generated the first two blocks */
|
214
|
+
|
215
|
+
/* Don't forget to generate the first block of addresses: */
|
216
|
+
if (data_independent_addressing) {
|
217
|
+
next_addresses(&address_block, &input_block);
|
218
|
+
}
|
219
|
+
}
|
220
|
+
|
221
|
+
/* Offset of the current block */
|
222
|
+
curr_offset = position.lane * instance->lane_length +
|
223
|
+
position.slice * instance->segment_length + starting_index;
|
224
|
+
|
225
|
+
if (0 == curr_offset % instance->lane_length) {
|
226
|
+
/* Last block in this lane */
|
227
|
+
prev_offset = curr_offset + instance->lane_length - 1;
|
228
|
+
} else {
|
229
|
+
/* Previous block */
|
230
|
+
prev_offset = curr_offset - 1;
|
231
|
+
}
|
232
|
+
|
233
|
+
memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
|
234
|
+
|
235
|
+
for (i = starting_index; i < instance->segment_length;
|
236
|
+
++i, ++curr_offset, ++prev_offset) {
|
237
|
+
/*1.1 Rotating prev_offset if needed */
|
238
|
+
if (curr_offset % instance->lane_length == 1) {
|
239
|
+
prev_offset = curr_offset - 1;
|
240
|
+
}
|
241
|
+
|
242
|
+
/* 1.2 Computing the index of the reference block */
|
243
|
+
/* 1.2.1 Taking pseudo-random value from the previous block */
|
244
|
+
if (data_independent_addressing) {
|
245
|
+
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
|
246
|
+
next_addresses(&address_block, &input_block);
|
247
|
+
}
|
248
|
+
pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
|
249
|
+
} else {
|
250
|
+
pseudo_rand = instance->memory[prev_offset].v[0];
|
251
|
+
}
|
252
|
+
|
253
|
+
/* 1.2.2 Computing the lane of the reference block */
|
254
|
+
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
|
255
|
+
|
256
|
+
if ((position.pass == 0) && (position.slice == 0)) {
|
257
|
+
/* Can not reference other lanes yet */
|
258
|
+
ref_lane = position.lane;
|
259
|
+
}
|
260
|
+
|
261
|
+
/* 1.2.3 Computing the number of possible reference block within the
|
262
|
+
* lane.
|
263
|
+
*/
|
264
|
+
position.index = i;
|
265
|
+
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
|
266
|
+
ref_lane == position.lane);
|
267
|
+
|
268
|
+
/* 2 Creating a new block */
|
269
|
+
ref_block =
|
270
|
+
instance->memory + instance->lane_length * ref_lane + ref_index;
|
271
|
+
curr_block = instance->memory + curr_offset;
|
272
|
+
if (ARGON2_VERSION_10 == instance->version) {
|
273
|
+
/* version 1.2.1 and earlier: overwrite, not XOR */
|
274
|
+
fill_block(state, ref_block, curr_block, 0);
|
275
|
+
} else {
|
276
|
+
if(0 == position.pass) {
|
277
|
+
fill_block(state, ref_block, curr_block, 0);
|
278
|
+
} else {
|
279
|
+
fill_block(state, ref_block, curr_block, 1);
|
280
|
+
}
|
281
|
+
}
|
282
|
+
}
|
283
|
+
}
|