2015-10-16 10:52:09 +02:00
|
|
|
/*
|
|
|
|
* Argon2 source code package
|
2015-10-16 19:05:50 +02:00
|
|
|
*
|
2015-10-16 10:52:09 +02:00
|
|
|
* Written by Daniel Dinu and Dmitry Khovratovich, 2015
|
2015-10-16 19:05:50 +02:00
|
|
|
*
|
2015-10-16 10:52:09 +02:00
|
|
|
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
|
2015-10-16 19:05:50 +02:00
|
|
|
*
|
2015-10-20 22:46:17 +02:00
|
|
|
* You should have received a copy of the CC0 Public Domain Dedication along
|
|
|
|
* with
|
|
|
|
* this software. If not, see
|
|
|
|
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
2015-10-16 10:52:09 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2015-10-19 10:07:13 +02:00
|
|
|
#include <time.h>
|
2015-10-16 10:52:09 +02:00
|
|
|
|
|
|
|
#include "argon2.h"
|
2015-10-19 10:07:13 +02:00
|
|
|
#include "encoding.h"
|
2015-10-16 10:52:09 +02:00
|
|
|
#ifdef _MSC_VER
|
2015-10-19 10:17:11 +02:00
|
|
|
#include <intrin.h>
|
2015-10-16 19:05:50 +02:00
|
|
|
#endif
|
2015-10-21 13:00:22 +02:00
|
|
|
|
2015-10-16 10:52:09 +02:00
|
|
|
|
2015-10-16 16:07:06 +02:00
|
|
|
#define T_COST_DEF 3
|
2015-10-20 22:46:17 +02:00
|
|
|
#define LOG_M_COST_DEF 12 /*4 MB*/
|
2015-10-16 16:07:06 +02:00
|
|
|
#define LANES_DEF 4
|
|
|
|
#define THREADS_DEF 4
|
2015-10-21 10:08:17 +02:00
|
|
|
#define SALTLEN_DEF 16
|
2015-10-16 16:07:06 +02:00
|
|
|
|
2015-10-16 18:41:54 +02:00
|
|
|
#define UNUSED_PARAMETER(x) (void)(x)
|
2015-10-16 16:07:06 +02:00
|
|
|
|
2015-10-20 22:46:17 +02:00
|
|
|
static __inline uint64_t rdtsc(void) {
|
2015-10-16 10:52:09 +02:00
|
|
|
#ifdef _MSC_VER
|
2015-10-21 08:55:42 +02:00
|
|
|
return __rdtsc();
|
2015-10-16 10:52:09 +02:00
|
|
|
#else
|
2015-10-20 22:46:17 +02:00
|
|
|
#if defined(__amd64__) || defined(__x86_64__)
|
2015-10-21 08:55:42 +02:00
|
|
|
uint64_t rax, rdx;
|
|
|
|
__asm__ __volatile__("rdtsc" : "=a"(rax), "=d"(rdx) : :);
|
|
|
|
return (rdx << 32) | rax;
|
2015-10-20 22:46:17 +02:00
|
|
|
#elif defined(__i386__) || defined(__i386) || defined(__X86__)
|
2015-10-21 08:55:42 +02:00
|
|
|
uint64_t rax;
|
|
|
|
__asm__ __volatile__("rdtsc" : "=A"(rax) : :);
|
|
|
|
return rax;
|
2015-10-20 22:46:17 +02:00
|
|
|
#else
|
|
|
|
#error "Not implemented!"
|
|
|
|
#endif
|
2015-10-16 10:52:09 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Custom allocate memory
|
|
|
|
*/
|
2015-10-20 22:46:17 +02:00
|
|
|
int CustomAllocateMemory(uint8_t **memory, size_t length) {
|
2015-10-21 08:55:42 +02:00
|
|
|
*memory = (uint8_t *)malloc(length);
|
2015-10-16 19:05:50 +02:00
|
|
|
|
2015-10-21 08:55:42 +02:00
|
|
|
if (!*memory) {
|
|
|
|
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
|
|
|
}
|
2015-10-16 19:05:50 +02:00
|
|
|
|
2015-10-21 08:55:42 +02:00
|
|
|
return ARGON2_OK;
|
2015-10-16 10:52:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Custom free memory
|
|
|
|
*/
|
2015-10-20 22:46:17 +02:00
|
|
|
void CustomFreeMemory(uint8_t *memory, size_t length) {
|
2015-10-21 08:55:42 +02:00
|
|
|
UNUSED_PARAMETER(length);
|
2015-10-16 19:05:50 +02:00
|
|
|
|
2015-10-21 08:55:42 +02:00
|
|
|
if (memory) {
|
|
|
|
free(memory);
|
|
|
|
}
|
2015-10-16 10:52:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-20 22:46:17 +02:00
|
|
|
void usage(const char *cmd) {
|
2015-10-21 08:55:42 +02:00
|
|
|
printf("Usage: %s pwd salt [-y version] [-t t_cost] [-m m_cost] [-l "
|
2015-10-21 10:08:17 +02:00
|
|
|
"#lanes] [-p #threads]\n",
|
|
|
|
cmd);
|
2015-10-21 08:55:42 +02:00
|
|
|
|
|
|
|
printf("Options:\n");
|
2015-10-21 10:08:17 +02:00
|
|
|
printf("\tpwd\t\tThe password to hash (required)\n");
|
|
|
|
printf("\tsalt\t\tThe salt to use, at most 16 characters (required)\n");
|
2015-10-21 08:55:42 +02:00
|
|
|
printf("\t-y version\tArgon2 version, either d or i (default)\n");
|
|
|
|
printf("\t-t t_cost\tNumber of rounds to t_cost between 1 and 2^24, "
|
|
|
|
"default %d\n",
|
|
|
|
T_COST_DEF);
|
|
|
|
printf("\t-m m_cost\tMemory usage of 2^t_cost kibibytes, default %d]\n",
|
|
|
|
LOG_M_COST_DEF);
|
|
|
|
printf("\t-p N\t\tParallelism, default %d\n", THREADS_DEF);
|
2015-10-16 20:13:31 +02:00
|
|
|
}
|
|
|
|
|
2015-10-20 22:46:17 +02:00
|
|
|
void fatal(const char *error) {
|
2015-10-21 08:55:42 +02:00
|
|
|
fprintf(stderr, "Error: %s\n", error);
|
|
|
|
exit(1);
|
2015-10-16 20:13:31 +02:00
|
|
|
}
|
|
|
|
|
2015-10-20 22:46:17 +02:00
|
|
|
void print_bytes(const void *s, size_t len) {
|
2015-10-21 08:55:42 +02:00
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
printf("%02x", ((const unsigned char *)s)[i] & 0xff);
|
|
|
|
}
|
2015-10-17 13:27:39 +02:00
|
|
|
|
2015-10-21 08:55:42 +02:00
|
|
|
printf("\n");
|
2015-10-16 20:13:31 +02:00
|
|
|
}
|
|
|
|
|
2015-10-16 10:52:09 +02:00
|
|
|
/*
|
2015-10-17 13:51:35 +02:00
|
|
|
* Benchmarks Argon2 with salt length 16, password length 16, t_cost 1,
|
2015-10-18 08:25:32 +02:00
|
|
|
and different m_cost and threads
|
2015-10-16 10:52:09 +02:00
|
|
|
*/
|
2015-10-20 22:46:17 +02:00
|
|
|
void benchmark() {
|
2015-10-19 13:37:08 +02:00
|
|
|
#define BENCH_OUTLEN 16
|
|
|
|
#define BENCH_INLEN 16
|
2015-10-21 08:55:42 +02:00
|
|
|
const uint32_t inlen = BENCH_INLEN;
|
|
|
|
const unsigned outlen = BENCH_OUTLEN;
|
|
|
|
unsigned char out[BENCH_OUTLEN];
|
|
|
|
unsigned char pwd_array[BENCH_INLEN];
|
|
|
|
unsigned char salt_array[BENCH_INLEN];
|
2015-10-19 13:37:08 +02:00
|
|
|
#undef BENCH_INLEN
|
|
|
|
#undef BENCH_OUTLEN
|
2015-10-16 10:52:09 +02:00
|
|
|
|
2015-10-21 08:55:42 +02:00
|
|
|
uint32_t t_cost = 1;
|
|
|
|
|
|
|
|
memset(pwd_array, 0, inlen);
|
|
|
|
memset(salt_array, 1, inlen);
|
|
|
|
uint32_t thread_test[6] = {1, 2, 4, 6, 8, 16};
|
|
|
|
|
|
|
|
uint32_t m_cost;
|
|
|
|
|
|
|
|
for (m_cost = (uint32_t)1 << 10; m_cost <= (uint32_t)1 << 22; m_cost *= 2) {
|
2015-10-21 12:23:25 +02:00
|
|
|
for (uint32_t i = 0; i < 6; ++i) {
|
2015-10-21 08:55:42 +02:00
|
|
|
uint32_t thread_n = thread_test[i];
|
|
|
|
uint64_t start_cycles, stop_cycles, stop_cycles_i;
|
|
|
|
|
|
|
|
clock_t start_time = clock();
|
|
|
|
start_cycles = rdtsc();
|
|
|
|
|
|
|
|
Argon2_Context context = {
|
|
|
|
out, outlen, pwd_array, inlen, salt_array, inlen, NULL,
|
|
|
|
0, NULL, 0, t_cost, m_cost, thread_n, thread_n,
|
|
|
|
NULL, NULL, false, false, false, false};
|
|
|
|
argon2d(&context);
|
|
|
|
stop_cycles = rdtsc();
|
|
|
|
argon2i(&context);
|
|
|
|
stop_cycles_i = rdtsc();
|
|
|
|
clock_t stop_time = clock();
|
|
|
|
|
|
|
|
uint64_t delta_d = (stop_cycles - start_cycles) / (m_cost);
|
|
|
|
uint64_t delta_i = (stop_cycles_i - stop_cycles) / (m_cost);
|
|
|
|
float mcycles_d = (float)(stop_cycles - start_cycles) / (1 << 20);
|
|
|
|
float mcycles_i = (float)(stop_cycles_i - stop_cycles) / (1 << 20);
|
|
|
|
printf(
|
|
|
|
"Argon2d %d pass(es) %d Mbytes %d threads: %2.2f cpb %2.2f "
|
|
|
|
"Mcycles \n",
|
|
|
|
t_cost, m_cost >> 10, thread_n, (float)delta_d / 1024,
|
|
|
|
mcycles_d);
|
|
|
|
printf(
|
|
|
|
"Argon2i %d pass(es) %d Mbytes %d threads: %2.2f cpb %2.2f "
|
|
|
|
"Mcycles \n",
|
|
|
|
t_cost, m_cost >> 10, thread_n, (float)delta_i / 1024,
|
|
|
|
mcycles_i);
|
|
|
|
|
|
|
|
float run_time = ((float)stop_time - start_time) / (CLOCKS_PER_SEC);
|
|
|
|
printf("%2.4f seconds\n\n", run_time);
|
|
|
|
}
|
2015-10-16 10:52:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-21 12:54:59 +02:00
|
|
|
/*
|
|
|
|
Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the Base64-encoded hash string
|
|
|
|
@out output array with at least 32 bytes allocated
|
|
|
|
@pwd NULL-terminated string, presumably from argv[]
|
|
|
|
@salt salt array with at least SALTLEN_DEF bytes allocated
|
|
|
|
@t_cost number of iterations
|
|
|
|
@m_cost amount of requested memory in KB
|
|
|
|
@lanes amount of requested parallelism
|
|
|
|
@threads actual parallelism
|
|
|
|
@type String, only "d" and "i" are accepted
|
|
|
|
*/
|
2015-10-21 10:08:17 +02:00
|
|
|
void run(uint8_t *out, char *pwd, uint8_t *salt, uint32_t t_cost,
|
|
|
|
uint32_t m_cost, uint32_t lanes, uint32_t threads, const char *type) {
|
2015-10-21 08:55:42 +02:00
|
|
|
uint64_t start_cycles, stop_cycles;
|
2015-10-16 10:52:09 +02:00
|
|
|
|
2015-10-21 08:55:42 +02:00
|
|
|
clock_t start_time = clock();
|
|
|
|
start_cycles = rdtsc();
|
2015-10-16 10:52:09 +02:00
|
|
|
|
2015-10-21 08:55:42 +02:00
|
|
|
/*Fixed parameters*/
|
|
|
|
const unsigned out_length = 32;
|
2015-10-21 10:08:17 +02:00
|
|
|
const unsigned salt_length = SALTLEN_DEF;
|
2015-10-21 08:55:42 +02:00
|
|
|
bool clear_memory = false;
|
|
|
|
bool clear_secret = false;
|
2015-10-23 18:08:48 +02:00
|
|
|
bool clear_password = true;
|
2015-10-21 08:55:42 +02:00
|
|
|
uint8_t *in = NULL;
|
|
|
|
|
2015-10-21 10:08:17 +02:00
|
|
|
if (!pwd)
|
|
|
|
fatal("password missing");
|
2015-10-23 18:08:48 +02:00
|
|
|
if (!salt)
|
|
|
|
{
|
|
|
|
secure_wipe_memory(pwd, strlen(pwd));
|
|
|
|
fatal("salt missing");
|
|
|
|
}
|
2015-10-21 10:08:17 +02:00
|
|
|
|
|
|
|
in = malloc(strlen(pwd) + 1);
|
2015-10-21 12:23:25 +02:00
|
|
|
if(!in)
|
|
|
|
{
|
2015-10-23 18:08:48 +02:00
|
|
|
secure_wipe_memory(pwd, strlen(pwd));
|
2015-10-21 12:23:25 +02:00
|
|
|
fatal("Memory allocation error in the initialization phase");
|
|
|
|
}
|
2015-10-21 10:08:17 +02:00
|
|
|
strcpy((char *)in, pwd);
|
2015-10-23 18:08:48 +02:00
|
|
|
secure_wipe_memory(pwd, strlen(pwd));
|
2015-10-21 08:55:42 +02:00
|
|
|
const unsigned in_length = strlen((char *)in);
|
|
|
|
|
|
|
|
UNUSED_PARAMETER(threads);
|
|
|
|
|
|
|
|
Argon2_Context context = {
|
|
|
|
out, out_length, in, in_length, salt, salt_length,
|
|
|
|
NULL, 0, NULL, 0, t_cost, m_cost,
|
|
|
|
lanes, lanes, NULL, NULL, clear_password, clear_secret,
|
2015-10-21 10:08:17 +02:00
|
|
|
clear_memory, false};
|
2015-10-21 08:55:42 +02:00
|
|
|
|
|
|
|
if (!strcmp(type, "d"))
|
|
|
|
argon2d(&context);
|
|
|
|
else if (!strcmp(type, "i"))
|
|
|
|
argon2i(&context);
|
|
|
|
else
|
2015-10-21 12:23:25 +02:00
|
|
|
{
|
|
|
|
free(in);
|
2015-10-21 08:55:42 +02:00
|
|
|
fatal("wrong Argon2 type");
|
2015-10-21 12:23:25 +02:00
|
|
|
}
|
2015-10-21 08:55:42 +02:00
|
|
|
|
|
|
|
stop_cycles = rdtsc();
|
|
|
|
clock_t finish_time = clock();
|
|
|
|
|
|
|
|
// show string encoding
|
|
|
|
char string[300];
|
|
|
|
encode_string(string, sizeof string, &context);
|
|
|
|
printf("%s\n", string);
|
|
|
|
|
2015-10-21 11:52:43 +02:00
|
|
|
float run_time = ((float)finish_time - start_time) / (CLOCKS_PER_SEC);
|
|
|
|
float mcycles = (float)(stop_cycles - start_cycles) / (1 << 20);
|
|
|
|
printf("%2.3f seconds ", run_time);
|
|
|
|
printf("(%.3f mebicycles)\n", mcycles);
|
|
|
|
|
2015-10-21 08:55:42 +02:00
|
|
|
free(in);
|
2015-10-16 10:52:09 +02:00
|
|
|
}
|
|
|
|
|
2015-10-20 22:46:17 +02:00
|
|
|
void generate_testvectors(const char *type) {
|
2015-10-19 13:37:08 +02:00
|
|
|
#define TEST_OUTLEN 32
|
|
|
|
#define TEST_PWDLEN 32
|
|
|
|
#define TEST_SALTLEN 16
|
|
|
|
#define TEST_SECRETLEN 8
|
|
|
|
#define TEST_ADLEN 12
|
2015-10-21 08:55:42 +02:00
|
|
|
bool clear_memory = false;
|
|
|
|
bool clear_secret = false;
|
|
|
|
bool clear_password = false;
|
|
|
|
bool print_internals = true;
|
|
|
|
|
|
|
|
unsigned char out[TEST_OUTLEN];
|
|
|
|
unsigned char pwd[TEST_PWDLEN];
|
|
|
|
unsigned char salt[TEST_SALTLEN];
|
|
|
|
unsigned char secret[TEST_SECRETLEN];
|
|
|
|
unsigned char ad[TEST_ADLEN];
|
|
|
|
const AllocateMemoryCallback myown_allocator = NULL;
|
|
|
|
const FreeMemoryCallback myown_deallocator = NULL;
|
|
|
|
|
|
|
|
unsigned t_cost = 3;
|
|
|
|
unsigned m_cost = 16;
|
|
|
|
unsigned lanes = 4;
|
|
|
|
|
|
|
|
memset(pwd, 1, TEST_OUTLEN);
|
|
|
|
memset(salt, 2, TEST_SALTLEN);
|
|
|
|
memset(secret, 3, TEST_SECRETLEN);
|
|
|
|
memset(ad, 4, TEST_ADLEN);
|
|
|
|
|
|
|
|
printf("Generating test vectors for Argon2%s in file \"%s\".\n", type,
|
|
|
|
ARGON2_KAT_FILENAME);
|
|
|
|
|
|
|
|
Argon2_Context context = {out,
|
|
|
|
TEST_OUTLEN,
|
|
|
|
pwd,
|
|
|
|
TEST_PWDLEN,
|
|
|
|
salt,
|
|
|
|
TEST_SALTLEN,
|
|
|
|
secret,
|
|
|
|
TEST_SECRETLEN,
|
|
|
|
ad,
|
|
|
|
TEST_ADLEN,
|
|
|
|
t_cost,
|
|
|
|
m_cost,
|
|
|
|
lanes,
|
|
|
|
lanes,
|
|
|
|
myown_allocator,
|
|
|
|
myown_deallocator,
|
|
|
|
clear_password,
|
|
|
|
clear_secret,
|
|
|
|
clear_memory,
|
|
|
|
print_internals};
|
2015-10-20 22:46:17 +02:00
|
|
|
#undef TEST_OUTLEN
|
|
|
|
#undef TEST_PWDLEN
|
|
|
|
#undef TEST_SALTLEN
|
|
|
|
#undef TEST_SECRETLEN
|
|
|
|
#undef TEST_ADLEN
|
|
|
|
|
2015-10-21 12:44:41 +02:00
|
|
|
if (!strcmp(type, "d")){
|
2015-10-21 12:43:10 +02:00
|
|
|
printf("Generating test vectors for Argon2d in file \"%s\".\n", ARGON2_KAT_FILENAME);
|
2015-10-21 08:55:42 +02:00
|
|
|
argon2d(&context);
|
2015-10-21 12:43:10 +02:00
|
|
|
}
|
2015-10-21 08:55:42 +02:00
|
|
|
else if (!strcmp(type, "i"))
|
2015-10-21 12:43:10 +02:00
|
|
|
{
|
2015-10-21 12:44:41 +02:00
|
|
|
printf("Generating test vectors for Argon2i in file \"%s\".\n", ARGON2_KAT_FILENAME);
|
2015-10-21 08:55:42 +02:00
|
|
|
argon2i(&context);
|
2015-10-21 12:44:41 +02:00
|
|
|
}
|
2015-10-21 08:55:42 +02:00
|
|
|
else
|
|
|
|
fatal("wrong Argon2 type");
|
2015-10-16 16:07:06 +02:00
|
|
|
}
|
|
|
|
|
2015-10-20 22:46:17 +02:00
|
|
|
int main(int argc, char *argv[]) {
|
2015-10-21 08:55:42 +02:00
|
|
|
unsigned char out[32];
|
|
|
|
uint32_t m_cost = 1 << LOG_M_COST_DEF;
|
|
|
|
uint32_t t_cost = T_COST_DEF;
|
|
|
|
uint32_t lanes = LANES_DEF;
|
|
|
|
uint32_t threads = THREADS_DEF;
|
|
|
|
char *pwd = NULL;
|
2015-10-21 10:08:17 +02:00
|
|
|
uint8_t salt[SALTLEN_DEF];
|
2015-10-21 08:55:42 +02:00
|
|
|
const char *type = "i";
|
|
|
|
|
|
|
|
remove(ARGON2_KAT_FILENAME);
|
|
|
|
|
|
|
|
#ifdef BENCH
|
|
|
|
benchmark();
|
2015-10-21 11:59:39 +02:00
|
|
|
return ARGON2_OK;
|
2015-10-21 08:55:42 +02:00
|
|
|
#endif
|
|
|
|
#ifdef GENKAT
|
2015-10-21 12:14:51 +02:00
|
|
|
if(argc>1)
|
|
|
|
{
|
|
|
|
type[0] = argv[1][0];
|
|
|
|
}
|
2015-10-20 22:46:17 +02:00
|
|
|
generate_testvectors(type);
|
2015-10-21 11:59:39 +02:00
|
|
|
return ARGON2_OK;
|
2015-10-21 08:55:42 +02:00
|
|
|
#endif
|
2015-10-16 19:05:50 +02:00
|
|
|
|
2015-10-21 10:08:17 +02:00
|
|
|
if (argc < 3) {
|
2015-10-21 08:55:42 +02:00
|
|
|
usage(argv[0]);
|
2015-10-21 11:59:39 +02:00
|
|
|
return ARGON2_MISSING_ARGS;
|
2015-10-21 08:55:42 +02:00
|
|
|
}
|
2015-10-16 10:52:09 +02:00
|
|
|
|
2015-10-21 10:08:17 +02:00
|
|
|
// get password and salt from command line
|
|
|
|
pwd = argv[1];
|
|
|
|
if (strlen(argv[2]) > SALTLEN_DEF)
|
|
|
|
fatal("salt too long");
|
|
|
|
memset(salt, 0x00, SALTLEN_DEF); // padding
|
|
|
|
memcpy(salt, (uint8_t *)argv[2], strlen(argv[2]));
|
2015-10-21 08:55:42 +02:00
|
|
|
|
2015-10-21 10:08:17 +02:00
|
|
|
for (int i = 3; i < argc; i++) {
|
2015-10-21 08:55:42 +02:00
|
|
|
char *a = argv[i];
|
|
|
|
|
|
|
|
if (!strcmp(a, "-m")) {
|
|
|
|
if (i < argc - 1) {
|
|
|
|
i++;
|
|
|
|
m_cost = (uint8_t)1 << ((uint8_t)atoi(argv[i]) % 22);
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
fatal("missing -m argument");
|
|
|
|
} else if (!strcmp(a, "-t")) {
|
|
|
|
if (i < argc - 1) {
|
|
|
|
i++;
|
|
|
|
t_cost = atoi(argv[i]) & 0xffffff;
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
fatal("missing -t argument");
|
|
|
|
} else if (!strcmp(a, "-p")) {
|
|
|
|
if (i < argc - 1) {
|
|
|
|
i++;
|
|
|
|
threads = atoi(argv[i]) % ARGON2_MAX_THREADS;
|
|
|
|
lanes = threads;
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
fatal("missing -p argument");
|
|
|
|
} else if (!strcmp(a, "-y")) {
|
|
|
|
if (i < argc - 1) {
|
|
|
|
i++;
|
|
|
|
type = argv[i];
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
fatal("missing type argument");
|
|
|
|
} else
|
|
|
|
fatal("unknown argument");
|
|
|
|
}
|
|
|
|
|
2015-10-21 10:08:17 +02:00
|
|
|
run(out, pwd, salt, t_cost, m_cost, lanes, threads, type);
|
2015-10-21 08:55:42 +02:00
|
|
|
|
2015-10-21 11:59:39 +02:00
|
|
|
return ARGON2_OK;
|
2015-10-16 10:52:09 +02:00
|
|
|
}
|