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
|
|
|
*/
|
|
|
|
|
2016-01-23 21:45:11 +01:00
|
|
|
#define _GNU_SOURCE 1
|
|
|
|
|
2016-03-11 18:34:24 +01:00
|
|
|
#include <inttypes.h>
|
2016-03-13 22:39:42 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
2015-10-16 10:52:09 +02:00
|
|
|
#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-23 23:30:44 +02:00
|
|
|
#include "core.h"
|
2015-10-21 13:00:22 +02:00
|
|
|
|
2015-10-16 16:07:06 +02:00
|
|
|
#define T_COST_DEF 3
|
2015-10-28 11:45:20 +01:00
|
|
|
#define LOG_M_COST_DEF 12 /* 2^12 = 4 MiB */
|
2015-10-31 21:09:00 +01:00
|
|
|
#define LANES_DEF 1
|
|
|
|
#define THREADS_DEF 1
|
2016-03-13 22:39:42 +01:00
|
|
|
#define OUTLEN_DEF 32
|
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-27 01:49:45 +01:00
|
|
|
static void usage(const char *cmd) {
|
2015-11-06 16:48:22 +01:00
|
|
|
printf("Usage: %s salt [-d] [-t iterations] [-m memory] "
|
2016-03-13 22:39:42 +01:00
|
|
|
"[-p parallelism] [-h hash length]\n",
|
2015-10-30 08:00:42 +01:00
|
|
|
cmd);
|
2015-11-06 16:48:22 +01:00
|
|
|
printf("\tPassword is read from stdin\n");
|
2015-10-28 16:42:52 +01:00
|
|
|
printf("Parameters:\n");
|
2016-03-13 22:39:42 +01:00
|
|
|
printf("\tsalt\t\tThe salt to use, at least 8 characters\n");
|
2015-10-28 16:42:52 +01:00
|
|
|
printf("\t-d\t\tUse Argon2d instead of Argon2i (which is the default)\n");
|
2015-10-30 08:00:42 +01:00
|
|
|
printf("\t-t N\t\tSets the number of iterations to N (default = %d)\n",
|
|
|
|
T_COST_DEF);
|
|
|
|
printf("\t-m N\t\tSets the memory usage of 2^N KiB (default %d)\n",
|
|
|
|
LOG_M_COST_DEF);
|
|
|
|
printf("\t-p N\t\tSets parallelism to N threads (default %d)\n",
|
|
|
|
THREADS_DEF);
|
2016-03-13 22:39:42 +01:00
|
|
|
printf("\t-h N\t\tSets hash output length to N bytes (default %d)\n",
|
|
|
|
OUTLEN_DEF);
|
2015-10-16 20:13:31 +02:00
|
|
|
}
|
|
|
|
|
2015-10-27 01:49:45 +01:00
|
|
|
static 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-21 12:54:59 +02:00
|
|
|
/*
|
2015-10-23 23:30:44 +02:00
|
|
|
Runs Argon2 with certain inputs and parameters, inputs not cleared. Prints the
|
|
|
|
Base64-encoded hash string
|
2015-10-21 12:54:59 +02:00
|
|
|
@out output array with at least 32 bytes allocated
|
|
|
|
@pwd NULL-terminated string, presumably from argv[]
|
2016-03-13 22:39:42 +01:00
|
|
|
@salt salt array
|
2015-10-21 12:54:59 +02:00
|
|
|
@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
|
|
|
|
*/
|
2016-03-13 22:39:42 +01:00
|
|
|
static void run(uint32_t outlen, char *pwd, char *salt, uint32_t t_cost,
|
2015-10-27 21:38:01 +01:00
|
|
|
uint32_t m_cost, uint32_t lanes, uint32_t threads,
|
2015-11-06 13:53:52 +01:00
|
|
|
argon2_type type) {
|
2015-10-26 10:16:13 +01:00
|
|
|
clock_t start_time, stop_time;
|
2016-03-13 22:39:42 +01:00
|
|
|
size_t pwdlen, saltlen, encodedlen;
|
2015-11-03 10:52:28 +01:00
|
|
|
uint32_t i;
|
2015-11-06 13:53:52 +01:00
|
|
|
int result;
|
2015-10-27 01:26:25 +01:00
|
|
|
|
|
|
|
start_time = clock();
|
2015-10-21 08:55:42 +02:00
|
|
|
|
2015-10-27 01:26:25 +01:00
|
|
|
if (!pwd) {
|
2015-10-21 10:08:17 +02:00
|
|
|
fatal("password missing");
|
2015-10-27 01:26:25 +01:00
|
|
|
}
|
|
|
|
|
2015-10-23 23:30:44 +02:00
|
|
|
if (!salt) {
|
|
|
|
secure_wipe_memory(pwd, strlen(pwd));
|
|
|
|
fatal("salt missing");
|
|
|
|
}
|
2015-10-21 10:08:17 +02:00
|
|
|
|
2015-11-06 11:42:22 +01:00
|
|
|
pwdlen = strlen(pwd);
|
2016-03-13 22:39:42 +01:00
|
|
|
saltlen = strlen(salt);
|
2015-10-21 08:55:42 +02:00
|
|
|
|
2015-11-07 16:10:33 +01:00
|
|
|
UNUSED_PARAMETER(lanes);
|
2015-10-21 08:55:42 +02:00
|
|
|
|
2016-03-13 22:39:42 +01:00
|
|
|
unsigned char* out = malloc(outlen + 1);
|
|
|
|
if (!out) {
|
|
|
|
secure_wipe_memory(pwd, strlen(pwd));
|
|
|
|
fatal("could not allocate memory for output");
|
|
|
|
}
|
|
|
|
|
|
|
|
encodedlen = argon2_encodedlen(t_cost, m_cost, lanes, saltlen, outlen);
|
|
|
|
char* encoded = malloc(encodedlen + 1);
|
|
|
|
if (!encoded) {
|
|
|
|
secure_wipe_memory(pwd, strlen(pwd));
|
|
|
|
fatal("could not allocate memory for hash");
|
|
|
|
}
|
|
|
|
|
|
|
|
result = argon2_hash(t_cost, m_cost, threads, pwd, pwdlen, salt, saltlen,
|
|
|
|
out, outlen, encoded, encodedlen, type,
|
|
|
|
ARGON2_VERSION_NUMBER);
|
2015-11-06 13:53:52 +01:00
|
|
|
if (result != ARGON2_OK)
|
2016-01-23 21:49:33 +01:00
|
|
|
fatal(argon2_error_message(result));
|
2015-10-21 08:55:42 +02:00
|
|
|
|
2015-10-26 10:16:13 +01:00
|
|
|
stop_time = clock();
|
2015-10-21 08:55:42 +02:00
|
|
|
|
2015-11-02 17:05:29 +01:00
|
|
|
printf("Hash:\t\t");
|
2016-03-13 22:39:42 +01:00
|
|
|
for (i = 0; i < outlen; ++i) {
|
2015-11-06 11:42:22 +01:00
|
|
|
printf("%02x", out[i]);
|
2015-11-02 17:05:29 +01:00
|
|
|
}
|
2016-03-13 22:39:42 +01:00
|
|
|
free(out);
|
2015-11-02 17:05:29 +01:00
|
|
|
printf("\n");
|
2015-11-06 11:42:22 +01:00
|
|
|
printf("Encoded:\t%s\n", encoded);
|
2015-11-02 17:05:29 +01:00
|
|
|
|
2015-10-30 08:00:42 +01:00
|
|
|
printf("%2.3f seconds\n",
|
|
|
|
((double)stop_time - start_time) / (CLOCKS_PER_SEC));
|
2015-11-06 13:53:52 +01:00
|
|
|
|
|
|
|
result = argon2_verify(encoded, pwd, pwdlen, type);
|
|
|
|
if (result != ARGON2_OK)
|
2016-01-23 21:49:33 +01:00
|
|
|
fatal(argon2_error_message(result));
|
2015-11-06 13:53:52 +01:00
|
|
|
printf("Verification ok\n");
|
2016-03-13 22:39:42 +01:00
|
|
|
free(encoded);
|
2015-10-16 10:52:09 +02:00
|
|
|
}
|
|
|
|
|
2016-01-24 09:14:56 +01:00
|
|
|
int main(int argc, char *argv[]) {
|
2016-03-13 22:39:42 +01:00
|
|
|
uint32_t outlen = OUTLEN_DEF;
|
2015-10-21 08:55:42 +02:00
|
|
|
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;
|
2015-11-06 13:53:52 +01:00
|
|
|
argon2_type type = Argon2_i;
|
2015-10-27 01:26:25 +01:00
|
|
|
int i;
|
2015-11-06 21:14:47 +01:00
|
|
|
size_t n;
|
2016-03-13 22:39:42 +01:00
|
|
|
char pwd[128], *salt;
|
2015-10-16 19:05:50 +02:00
|
|
|
|
2015-11-06 16:48:22 +01:00
|
|
|
if (argc < 2) {
|
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-11-06 16:48:22 +01:00
|
|
|
/* get password from stdin */
|
2015-11-07 16:10:33 +01:00
|
|
|
while ((n = fread(pwd, 1, sizeof pwd - 1, stdin)) > 0) {
|
2015-11-06 16:48:22 +01:00
|
|
|
pwd[n] = '\0';
|
2015-11-07 16:10:33 +01:00
|
|
|
if (pwd[n - 1] == '\n')
|
|
|
|
pwd[n - 1] = '\0';
|
2015-11-06 16:48:22 +01:00
|
|
|
}
|
|
|
|
|
2016-03-13 22:39:42 +01:00
|
|
|
salt = argv[1];
|
2016-03-11 18:34:24 +01:00
|
|
|
|
2015-10-27 01:26:25 +01:00
|
|
|
/* parse options */
|
2015-11-06 16:48:22 +01:00
|
|
|
for (i = 2; i < argc; i++) {
|
2015-10-27 17:40:32 +01:00
|
|
|
const char *a = argv[i];
|
|
|
|
unsigned long input = 0;
|
2015-10-21 08:55:42 +02:00
|
|
|
if (!strcmp(a, "-m")) {
|
|
|
|
if (i < argc - 1) {
|
|
|
|
i++;
|
2015-10-27 17:40:32 +01:00
|
|
|
input = strtoul(argv[i], NULL, 10);
|
2015-10-27 21:38:01 +01:00
|
|
|
if (input == 0 || input == ULONG_MAX ||
|
|
|
|
input > ARGON2_MAX_MEMORY_BITS) {
|
2015-10-27 17:40:32 +01:00
|
|
|
fatal("bad numeric input for -m");
|
|
|
|
}
|
|
|
|
m_cost = ARGON2_MIN(UINT64_C(1) << input, UINT32_C(0xFFFFFFFF));
|
2015-10-27 21:38:01 +01:00
|
|
|
if (m_cost > ARGON2_MAX_MEMORY) {
|
2015-10-27 17:40:32 +01:00
|
|
|
fatal("m_cost overflow");
|
|
|
|
}
|
2015-10-21 08:55:42 +02:00
|
|
|
continue;
|
2015-10-27 17:40:32 +01:00
|
|
|
} else {
|
2015-10-21 08:55:42 +02:00
|
|
|
fatal("missing -m argument");
|
2015-10-27 17:40:32 +01:00
|
|
|
}
|
2015-10-21 08:55:42 +02:00
|
|
|
} else if (!strcmp(a, "-t")) {
|
|
|
|
if (i < argc - 1) {
|
|
|
|
i++;
|
2015-10-27 17:40:32 +01:00
|
|
|
input = strtoul(argv[i], NULL, 10);
|
2015-10-27 21:38:01 +01:00
|
|
|
if (input == 0 || input == ULONG_MAX ||
|
|
|
|
input > ARGON2_MAX_TIME) {
|
2015-10-27 17:40:32 +01:00
|
|
|
fatal("bad numeric input for -t");
|
|
|
|
}
|
|
|
|
t_cost = input;
|
2015-10-21 08:55:42 +02:00
|
|
|
continue;
|
2015-10-27 17:40:32 +01:00
|
|
|
} else {
|
2015-10-21 08:55:42 +02:00
|
|
|
fatal("missing -t argument");
|
2015-10-27 17:40:32 +01:00
|
|
|
}
|
2015-10-21 08:55:42 +02:00
|
|
|
} else if (!strcmp(a, "-p")) {
|
|
|
|
if (i < argc - 1) {
|
|
|
|
i++;
|
2015-10-27 17:40:32 +01:00
|
|
|
input = strtoul(argv[i], NULL, 10);
|
2015-10-27 21:38:01 +01:00
|
|
|
if (input == 0 || input == ULONG_MAX ||
|
|
|
|
input > ARGON2_MAX_THREADS || input > ARGON2_MAX_LANES) {
|
2015-10-27 17:40:32 +01:00
|
|
|
fatal("bad numeric input for -p");
|
|
|
|
}
|
|
|
|
threads = input;
|
2015-10-21 08:55:42 +02:00
|
|
|
lanes = threads;
|
|
|
|
continue;
|
2015-10-27 17:40:32 +01:00
|
|
|
} else {
|
2015-10-21 08:55:42 +02:00
|
|
|
fatal("missing -p argument");
|
2015-10-27 17:40:32 +01:00
|
|
|
}
|
2016-03-13 22:39:42 +01:00
|
|
|
} else if (!strcmp(a, "-h")) {
|
|
|
|
if (i < argc - 1) {
|
|
|
|
i++;
|
|
|
|
input = strtoul(argv[i], NULL, 10);
|
|
|
|
outlen = input;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
fatal("missing -h argument");
|
|
|
|
}
|
2015-10-28 16:42:52 +01:00
|
|
|
} else if (!strcmp(a, "-d")) {
|
2015-11-06 13:53:52 +01:00
|
|
|
type = Argon2_d;
|
2015-10-27 17:40:32 +01:00
|
|
|
} else {
|
2015-10-21 08:55:42 +02:00
|
|
|
fatal("unknown argument");
|
2015-10-27 17:40:32 +01:00
|
|
|
}
|
2015-10-21 08:55:42 +02:00
|
|
|
}
|
2015-11-07 16:10:33 +01:00
|
|
|
if (type == Argon2_i) {
|
2015-11-06 13:53:52 +01:00
|
|
|
printf("Type:\t\tArgon2i\n");
|
2015-11-07 16:10:33 +01:00
|
|
|
} else {
|
2015-11-06 13:53:52 +01:00
|
|
|
printf("Type:\t\tArgon2d\n");
|
2015-11-07 16:10:33 +01:00
|
|
|
}
|
2015-10-27 21:38:01 +01:00
|
|
|
printf("Iterations:\t%" PRIu32 " \n", t_cost);
|
2015-10-30 08:55:53 +01:00
|
|
|
printf("Memory:\t\t%" PRIu32 " KiB\n", m_cost);
|
2015-10-27 21:38:01 +01:00
|
|
|
printf("Parallelism:\t%" PRIu32 " \n", lanes);
|
2016-03-13 22:39:42 +01:00
|
|
|
run(outlen, 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
|
|
|
}
|
2016-03-11 18:34:24 +01:00
|
|
|
|