This commit is contained in:
Frank Denis
2017-02-23 09:39:59 +01:00
parent b25cffb7f1
commit 9fbd5c0c18
12 changed files with 620 additions and 528 deletions
@@ -12,7 +12,7 @@
*/
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#include <sys/mman.h>
#endif
#include <errno.h>
#include <stdint.h>
@@ -21,46 +21,56 @@
#include <string.h>
#include "crypto_generichash_blake2b.h"
#include "private/common.h"
#include "runtime.h"
#include "utils.h"
#include "private/common.h"
#include "argon2-core.h"
#include "blake2b-long.h"
#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
# define MAP_ANON MAP_ANONYMOUS
#define MAP_ANON MAP_ANONYMOUS
#endif
static fill_segment_fn fill_segment = fill_segment_ref;
/***************Instance and Position constructors**********/
void init_block_value(block *b, uint8_t in) {
void
init_block_value(block *b, uint8_t in)
{
memset(b->v, in, sizeof(b->v));
}
void copy_block(block *dst, const block *src) {
void
copy_block(block *dst, const block *src)
{
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
}
void xor_block(block *dst, const block *src) {
void
xor_block(block *dst, const block *src)
{
int i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
dst->v[i] ^= src->v[i];
}
}
static void load_block(block *dst, const void *input) {
static void
load_block(block *dst, const void *input)
{
unsigned i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
dst->v[i] = LOAD64_LE((const uint8_t *)input + i * sizeof(dst->v[i]));
dst->v[i] = LOAD64_LE((const uint8_t *) input + i * sizeof(dst->v[i]));
}
}
static void store_block(void *output, const block *src) {
static void
store_block(void *output, const block *src)
{
unsigned i;
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
STORE64_LE((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
STORE64_LE((uint8_t *) output + i * sizeof(src->v[i]), src->v[i]);
}
}
@@ -72,8 +82,10 @@ static void store_block(void *output, const block *src) {
*/
static int allocate_memory(block_region **memory, uint32_t m_cost);
static int allocate_memory(block_region **region, uint32_t m_cost) {
void *base;
static int
allocate_memory(block_region **region, uint32_t m_cost)
{
void * base;
block *memory;
size_t memory_size;
@@ -82,24 +94,26 @@ static int allocate_memory(block_region **region, uint32_t m_cost) {
}
memory_size = sizeof(block) * m_cost;
if (m_cost == 0 ||
memory_size / m_cost != sizeof(block)) { /*1. Check for multiplication overflow*/
memory_size / m_cost !=
sizeof(block)) { /*1. Check for multiplication overflow*/
return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
}
*region = (block_region *)malloc(sizeof(block_region)); /*2. Try to allocate region*/
*region = (block_region *) malloc(
sizeof(block_region)); /*2. Try to allocate region*/
if (!*region) {
return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
}
#if defined(MAP_ANON) && defined(HAVE_MMAP)
if ((base = mmap(NULL, memory_size, PROT_READ | PROT_WRITE,
# ifdef MAP_NOCORE
#ifdef MAP_NOCORE
MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
# else
#else
MAP_ANON | MAP_PRIVATE,
# endif
#endif
-1, 0)) == MAP_FAILED) {
base = NULL; /* LCOV_EXCL_LINE */
} /* LCOV_EXCL_LINE */
} /* LCOV_EXCL_LINE */
memcpy(&memory, &base, sizeof memory);
#elif defined(HAVE_POSIX_MEMALIGN)
if ((errno = posix_memalign((void **) &base, 64, memory_size)) != 0) {
@@ -109,7 +123,7 @@ static int allocate_memory(block_region **region, uint32_t m_cost) {
#else
memory = NULL;
if (memory_size + 63 < memory_size) {
base = NULL;
base = NULL;
errno = ENOMEM;
} else if ((base = malloc(memory_size + 63)) != NULL) {
uint8_t *aligned = ((uint8_t *) base) + 63;
@@ -120,9 +134,9 @@ static int allocate_memory(block_region **region, uint32_t m_cost) {
if (base == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR; /* LCOV_EXCL_LINE */
}
(*region)->base = base;
(*region)->base = base;
(*region)->memory = memory;
(*region)->size = memory_size;
(*region)->size = memory_size;
return ARGON2_OK;
}
@@ -135,7 +149,9 @@ static int allocate_memory(block_region **region, uint32_t m_cost) {
*/
static void clear_memory(argon2_instance_t *instance, int clear);
static void clear_memory(argon2_instance_t *instance, int clear) {
static void
clear_memory(argon2_instance_t *instance, int clear)
{
if (instance->region != NULL && clear) {
/* LCOV_EXCL_START */
sodium_memzero(instance->region->memory,
@@ -149,7 +165,9 @@ static void clear_memory(argon2_instance_t *instance, int clear) {
*/
static void free_memory(block_region *memory);
static void free_memory(block_region *region) {
static void
free_memory(block_region *region)
{
if (region->base) {
#if defined(MAP_ANON) && defined(HAVE_MMAP)
if (munmap(region->base, region->size)) {
@@ -162,18 +180,22 @@ static void free_memory(block_region *region) {
free(region);
}
void finalize(const argon2_context *context, argon2_instance_t *instance) {
void
finalize(const argon2_context *context, argon2_instance_t *instance)
{
if (context != NULL && instance != NULL) {
block blockhash;
block blockhash;
uint32_t l;
copy_block(&blockhash, instance->region->memory + instance->lane_length - 1);
copy_block(&blockhash,
instance->region->memory + instance->lane_length - 1);
/* XOR the last blocks */
for (l = 1; l < instance->lanes; ++l) {
uint32_t last_block_in_lane =
l * instance->lane_length + (instance->lane_length - 1);
xor_block(&blockhash, instance->region->memory + last_block_in_lane);
xor_block(&blockhash,
instance->region->memory + last_block_in_lane);
}
/* Hash the result */
@@ -196,9 +218,11 @@ void finalize(const argon2_context *context, argon2_instance_t *instance) {
}
}
uint32_t index_alpha(const argon2_instance_t *instance,
const argon2_position_t *position, uint32_t pseudo_rand,
int same_lane) {
uint32_t
index_alpha(const argon2_instance_t *instance,
const argon2_position_t *position, uint32_t pseudo_rand,
int same_lane)
{
/*
* Pass 0:
* This lane : all already finished segments plus already constructed
@@ -266,8 +290,10 @@ uint32_t index_alpha(const argon2_instance_t *instance,
return absolute_position;
}
int fill_memory_blocks(argon2_instance_t *instance) {
int result;
int
fill_memory_blocks(argon2_instance_t *instance)
{
int result;
uint32_t r, s;
if (instance == NULL || instance->lanes == 0) {
@@ -281,11 +307,11 @@ int fill_memory_blocks(argon2_instance_t *instance) {
for (l = 0; l < instance->lanes; ++l) {
argon2_position_t position;
position.pass = r;
position.lane = l;
position.slice = (uint8_t)s;
position.pass = r;
position.lane = l;
position.slice = (uint8_t) s;
position.index = 0;
result = fill_segment(instance, position);
result = fill_segment(instance, position);
if (ARGON2_OK != result) {
return result; /* LCOV_EXCL_LINE */
}
@@ -295,8 +321,10 @@ int fill_memory_blocks(argon2_instance_t *instance) {
return ARGON2_OK;
}
int validate_inputs(const argon2_context *context) {
/* LCOV_EXCL_START */
int
validate_inputs(const argon2_context *context)
{
/* LCOV_EXCL_START */
if (NULL == context) {
return ARGON2_INCORRECT_PARAMETER;
}
@@ -418,13 +446,14 @@ int validate_inputs(const argon2_context *context) {
return ARGON2_OK;
}
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
void
fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance)
{
uint32_t l;
/* Make the first and second block in each lane as G(H0||i||0) or
G(H0||i||1) */
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
for (l = 0; l < instance->lanes; ++l) {
STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
STORE32_LE(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
@@ -441,10 +470,11 @@ void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
sodium_memzero(blockhash_bytes, ARGON2_BLOCK_SIZE);
}
void initial_hash(uint8_t *blockhash, argon2_context *context,
argon2_type type) {
void
initial_hash(uint8_t *blockhash, argon2_context *context, argon2_type type)
{
crypto_generichash_blake2b_state BlakeHash;
uint8_t value[4U /* sizeof(uint32_t) */];
uint8_t value[4U /* sizeof(uint32_t) */];
if (NULL == context || NULL == blockhash) {
return; /* LCOV_EXCL_LINE */
@@ -468,19 +498,19 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
STORE32_LE(value, ARGON2_VERSION_NUMBER);
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
STORE32_LE(value, (uint32_t)type);
STORE32_LE(value, (uint32_t) type);
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
STORE32_LE(value, context->pwdlen);
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
if (context->pwd != NULL) {
crypto_generichash_blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
context->pwdlen);
crypto_generichash_blake2b_update(
&BlakeHash, (const uint8_t *) context->pwd, context->pwdlen);
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
sodium_memzero(context->pwd, context->pwdlen); /* LCOV_EXCL_LINE */
context->pwdlen = 0; /* LCOV_EXCL_LINE */
context->pwdlen = 0; /* LCOV_EXCL_LINE */
}
}
@@ -488,41 +518,44 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
if (context->salt != NULL) {
crypto_generichash_blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
context->saltlen);
crypto_generichash_blake2b_update(
&BlakeHash, (const uint8_t *) context->salt, context->saltlen);
}
STORE32_LE(value, context->secretlen);
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
if (context->secret != NULL) {
/* LCOV_EXCL_START */
crypto_generichash_blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
context->secretlen);
/* LCOV_EXCL_START */
crypto_generichash_blake2b_update(
&BlakeHash, (const uint8_t *) context->secret, context->secretlen);
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
sodium_memzero(context->secret, context->secretlen);
context->secretlen = 0;
}
/* LCOV_EXCL_STOP */
/* LCOV_EXCL_STOP */
}
STORE32_LE(value, context->adlen);
crypto_generichash_blake2b_update(&BlakeHash, value, sizeof(value));
if (context->ad != NULL) {
/* LCOV_EXCL_START */
crypto_generichash_blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
context->adlen);
/* LCOV_EXCL_STOP */
/* LCOV_EXCL_START */
crypto_generichash_blake2b_update(
&BlakeHash, (const uint8_t *) context->ad, context->adlen);
/* LCOV_EXCL_STOP */
}
crypto_generichash_blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
crypto_generichash_blake2b_final(&BlakeHash, blockhash,
ARGON2_PREHASH_DIGEST_LENGTH);
}
int initialize(argon2_instance_t *instance, argon2_context *context) {
int
initialize(argon2_instance_t *instance, argon2_context *context)
{
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
int result = ARGON2_OK;
int result = ARGON2_OK;
if (instance == NULL || context == NULL)
return ARGON2_INCORRECT_PARAMETER;
@@ -552,11 +585,13 @@ int initialize(argon2_instance_t *instance, argon2_context *context) {
return ARGON2_OK;
}
int argon2_pick_best_implementation(void)
int
argon2_pick_best_implementation(void)
{
/* LCOV_EXCL_START */
#if (defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)) || \
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
(defined(_MSC_VER) && \
(defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
if (sodium_runtime_has_ssse3()) {
fill_segment = fill_segment_ssse3;
return 0;
@@ -565,5 +600,5 @@ int argon2_pick_best_implementation(void)
fill_segment = fill_segment_ref;
return 0;
/* LCOV_EXCL_STOP */
/* LCOV_EXCL_STOP */
}
@@ -24,7 +24,7 @@ enum argon2_ctx_constants {
ARGON2_VERSION_NUMBER = 0x13,
/* Memory block size in bytes */
ARGON2_BLOCK_SIZE = 1024,
ARGON2_BLOCK_SIZE = 1024,
ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
@@ -35,7 +35,7 @@ enum argon2_ctx_constants {
/* Pre-hashing digest length and its extension*/
ARGON2_PREHASH_DIGEST_LENGTH = 64,
ARGON2_PREHASH_SEED_LENGTH = 72
ARGON2_PREHASH_SEED_LENGTH = 72
};
/*************************Argon2 internal data
@@ -46,10 +46,12 @@ enum argon2_ctx_constants {
* Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
* bounds checking).
*/
typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
typedef struct block_ {
uint64_t v[ARGON2_QWORDS_IN_BLOCK];
} block;
typedef struct block_region_ {
void *base;
void * base;
block *memory;
size_t size;
} block_region;
@@ -72,15 +74,15 @@ void xor_block(block *dst, const block *src);
* thread
*/
typedef struct Argon2_instance_t {
block_region *region; /* Memory region pointer */
uint32_t passes; /* Number of passes */
uint32_t memory_blocks; /* Number of blocks in memory */
uint32_t segment_length;
uint32_t lane_length;
uint32_t lanes;
uint32_t threads;
argon2_type type;
int print_internals; /* whether to print the memory blocks */
block_region *region; /* Memory region pointer */
uint32_t passes; /* Number of passes */
uint32_t memory_blocks; /* Number of blocks in memory */
uint32_t segment_length;
uint32_t lane_length;
uint32_t lanes;
uint32_t threads;
argon2_type type;
int print_internals; /* whether to print the memory blocks */
} argon2_instance_t;
/*
@@ -90,14 +92,14 @@ typedef struct Argon2_instance_t {
typedef struct Argon2_position_t {
uint32_t pass;
uint32_t lane;
uint8_t slice;
uint8_t slice;
uint32_t index;
} argon2_position_t;
/*Struct that holds the inputs for thread handling FillSegment*/
typedef struct Argon2_thread_data {
argon2_instance_t *instance_ptr;
argon2_position_t pos;
argon2_position_t pos;
} argon2_thread_data;
/*************************Argon2 core
@@ -180,12 +182,12 @@ void finalize(const argon2_context *context, argon2_instance_t *instance);
* @pre all block pointers must be valid
*/
typedef int (*fill_segment_fn)(const argon2_instance_t *instance,
argon2_position_t position);
argon2_position_t position);
int argon2_pick_best_implementation(void);
int fill_segment_ssse3(const argon2_instance_t *instance,
argon2_position_t position);
argon2_position_t position);
int fill_segment_ref(const argon2_instance_t *instance,
argon2_position_t position);
argon2_position_t position);
/*
* Function that fills the entire memory t_cost times based on the first two
@@ -1,9 +1,9 @@
#include "argon2-encoding.h"
#include "argon2-core.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "argon2-core.h"
#include "argon2-encoding.h"
/*
* Example code for a decoder and encoder of "hash strings", with Argon2
@@ -54,8 +54,9 @@
* Some macros for constant-time comparisons. These work over values in
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
*/
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
#define EQ(x, y) \
((((0U - ((unsigned) (x) ^ (unsigned) (y))) >> 8) & 0xFF) ^ 0xFF)
#define GT(x, y) ((((unsigned) (y) - (unsigned) (x)) >> 8) & 0xFF)
#define GE(x, y) (GT(y, x) ^ 0xFF)
#define LT(x, y) GT(y, x)
#define LE(x, y) GE(y, x)
@@ -63,7 +64,9 @@
/*
* Convert value x (0..63) to corresponding Base64 character.
*/
static int b64_byte_to_char(unsigned x) {
static int
b64_byte_to_char(unsigned x)
{
return (LT(x, 26) & (x + 'A')) |
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
@@ -74,7 +77,9 @@ static int b64_byte_to_char(unsigned x) {
* Convert character c to the corresponding 6-bit value. If character c
* is not a Base64 character, then 0xFF (255) is returned.
*/
static unsigned b64_char_to_byte(int c) {
static unsigned
b64_char_to_byte(int c)
{
unsigned x;
x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
@@ -92,11 +97,12 @@ static unsigned b64_char_to_byte(int c) {
* in the buffer, and the output length (counted WITHOUT the terminating
* zero) is returned.
*/
static size_t to_base64(char *dst, size_t dst_len, const void *src,
size_t src_len) {
size_t olen;
static size_t
to_base64(char *dst, size_t dst_len, const void *src, size_t src_len)
{
size_t olen;
const unsigned char *buf;
unsigned acc, acc_len;
unsigned acc, acc_len;
olen = (src_len / 3) << 2;
switch (src_len % 3) {
@@ -108,21 +114,21 @@ static size_t to_base64(char *dst, size_t dst_len, const void *src,
break;
}
if (dst_len <= olen) {
return (size_t)-1;
return (size_t) -1;
}
acc = 0;
acc = 0;
acc_len = 0;
buf = (const unsigned char *)src;
buf = (const unsigned char *) src;
while (src_len-- > 0) {
acc = (acc << 8) + (*buf++);
acc_len += 8;
while (acc_len >= 6) {
acc_len -= 6;
*dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
*dst++ = (char) b64_byte_to_char((acc >> acc_len) & 0x3F);
}
}
if (acc_len > 0) {
*dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
*dst++ = (char) b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
}
*dst++ = 0;
return olen;
@@ -141,14 +147,16 @@ static size_t to_base64(char *dst, size_t dst_len, const void *src,
* points to the first non-Base64 character in the source stream, which
* may be the terminating zero.
*/
static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
size_t len;
static const char *
from_base64(void *dst, size_t *dst_len, const char *src)
{
size_t len;
unsigned char *buf;
unsigned acc, acc_len;
unsigned acc, acc_len;
buf = (unsigned char *)dst;
len = 0;
acc = 0;
buf = (unsigned char *) dst;
len = 0;
acc = 0;
acc_len = 0;
for (;;) {
unsigned d;
@@ -189,8 +197,10 @@ static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
* minimal (extra leading zeros), or the value does not fit in an
* 'unsigned long', then NULL is returned.
*/
static const char *decode_decimal(const char *str, unsigned long *v) {
const char *orig;
static const char *
decode_decimal(const char *str, unsigned long *v)
{
const char * orig;
unsigned long acc;
acc = 0;
@@ -206,10 +216,10 @@ static const char *decode_decimal(const char *str, unsigned long *v) {
return NULL;
}
acc *= 10;
if ((unsigned long)c > (ULONG_MAX - acc)) {
if ((unsigned long) c > (ULONG_MAX - acc)) {
return NULL;
}
acc += (unsigned long)c;
acc += (unsigned long) c;
}
if (str == orig || (*orig == '0' && str != (orig + 1))) {
return NULL;
@@ -242,57 +252,61 @@ static const char *decode_decimal(const char *str, unsigned long *v) {
* Decode an Argon2i hash string into the provided structure 'ctx'.
* Returned value is ARGON2_OK on success.
*/
int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
/* Prefix checking */
#define CC(prefix) \
do { \
size_t cc_len = strlen(prefix); \
if (strncmp(str, prefix, cc_len) != 0) { \
return ARGON2_DECODING_FAIL; \
} \
str += cc_len; \
} while ((void)0, 0)
int
decode_string(argon2_context *ctx, const char *str, argon2_type type)
{
/* Prefix checking */
#define CC(prefix) \
do { \
size_t cc_len = strlen(prefix); \
if (strncmp(str, prefix, cc_len) != 0) { \
return ARGON2_DECODING_FAIL; \
} \
str += cc_len; \
} while ((void) 0, 0)
/* Optional prefix checking with supplied code */
#define CC_opt(prefix, code) \
do { \
size_t cc_len = strlen(prefix); \
if (strncmp(str, prefix, cc_len) == 0) { \
str += cc_len; \
{ code; } \
} \
} while ((void)0, 0)
/* Optional prefix checking with supplied code */
#define CC_opt(prefix, code) \
do { \
size_t cc_len = strlen(prefix); \
if (strncmp(str, prefix, cc_len) == 0) { \
str += cc_len; \
{ \
code; \
} \
} \
} while ((void) 0, 0)
/* Decoding prefix into decimal */
#define DECIMAL(x) \
do { \
unsigned long dec_x; \
str = decode_decimal(str, &dec_x); \
if (str == NULL) { \
return ARGON2_DECODING_FAIL; \
} \
(x) = dec_x; \
} while ((void)0, 0)
/* Decoding prefix into decimal */
#define DECIMAL(x) \
do { \
unsigned long dec_x; \
str = decode_decimal(str, &dec_x); \
if (str == NULL) { \
return ARGON2_DECODING_FAIL; \
} \
(x) = dec_x; \
} while ((void) 0, 0)
/* Decoding base64 into a binary buffer */
#define BIN(buf, max_len, len) \
do { \
size_t bin_len = (max_len); \
str = from_base64(buf, &bin_len, str); \
if (str == NULL || bin_len > UINT32_MAX) { \
return ARGON2_DECODING_FAIL; \
} \
(len) = (uint32_t)bin_len; \
} while ((void)0, 0)
/* Decoding base64 into a binary buffer */
#define BIN(buf, max_len, len) \
do { \
size_t bin_len = (max_len); \
str = from_base64(buf, &bin_len, str); \
if (str == NULL || bin_len > UINT32_MAX) { \
return ARGON2_DECODING_FAIL; \
} \
(len) = (uint32_t) bin_len; \
} while ((void) 0, 0)
size_t maxsaltlen = ctx->saltlen;
size_t maxoutlen = ctx->outlen;
size_t maxsaltlen = ctx->saltlen;
size_t maxoutlen = ctx->outlen;
unsigned long val;
unsigned long version = 0;
int validation_result;
int validation_result;
ctx->saltlen = 0;
ctx->outlen = 0;
ctx->outlen = 0;
if (type == Argon2_i) {
CC("$argon2i");
@@ -321,7 +335,7 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
if (val > UINT32_MAX) {
return ARGON2_INCORRECT_TYPE;
}
ctx->lanes = (uint32_t) val;
ctx->lanes = (uint32_t) val;
ctx->threads = ctx->lanes;
CC("$");
@@ -345,7 +359,9 @@ int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
#define U32_STR_MAXSIZE 11U
static void u32_to_string(char *str, uint32_t x) {
static void
u32_to_string(char *str, uint32_t x)
{
char tmp[U32_STR_MAXSIZE - 1U];
size_t i;
@@ -370,35 +386,36 @@ static void u32_to_string(char *str, uint32_t x) {
*
* On success, ARGON2_OK is returned.
*/
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
argon2_type type) {
#define SS(str) \
do { \
size_t pp_len = strlen(str); \
if (pp_len >= dst_len) { \
return ARGON2_ENCODING_FAIL; \
} \
memcpy(dst, str, pp_len + 1); \
dst += pp_len; \
dst_len -= pp_len; \
} while ((void)0, 0)
int
encode_string(char *dst, size_t dst_len, argon2_context *ctx, argon2_type type)
{
#define SS(str) \
do { \
size_t pp_len = strlen(str); \
if (pp_len >= dst_len) { \
return ARGON2_ENCODING_FAIL; \
} \
memcpy(dst, str, pp_len + 1); \
dst += pp_len; \
dst_len -= pp_len; \
} while ((void) 0, 0)
#define SX(x) \
do { \
char tmp[U32_STR_MAXSIZE]; \
u32_to_string(tmp, x); \
SS(tmp); \
} while ((void)0, 0)
#define SX(x) \
do { \
char tmp[U32_STR_MAXSIZE]; \
u32_to_string(tmp, x); \
SS(tmp); \
} while ((void) 0, 0)
#define SB(buf, len) \
do { \
size_t sb_len = to_base64(dst, dst_len, buf, len); \
if (sb_len == (size_t)-1) { \
return ARGON2_ENCODING_FAIL; \
} \
dst += sb_len; \
dst_len -= sb_len; \
} while ((void)0, 0)
#define SB(buf, len) \
do { \
size_t sb_len = to_base64(dst, dst_len, buf, len); \
if (sb_len == (size_t) -1) { \
return ARGON2_ENCODING_FAIL; \
} \
dst += sb_len; \
dst_len -= sb_len; \
} while ((void) 0, 0)
int validation_result;
@@ -22,7 +22,8 @@ int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
/*
* Decodes an Argon2 hash string into the provided structure 'ctx'.
* The fields ctx.saltlen, ctx.adlen, ctx.outlen set the maximal salt, ad, out length values
* The fields ctx.saltlen, ctx.adlen, ctx.outlen set the maximal salt, ad, out
* length values
* that are allowed; invalid input string causes an error
*
* Returned value is ARGON2_OK on success.
@@ -15,14 +15,15 @@
#include <stdlib.h>
#include <string.h>
#include "argon2.h"
#include "argon2-core.h"
#include "argon2.h"
#include "blamka-round-ref.h"
#include "private/common.h"
static void fill_block(const block *prev_block, const block *ref_block,
block *next_block) {
block blockR, block_tmp;
static void
fill_block(const block *prev_block, const block *ref_block, block *next_block)
{
block blockR, block_tmp;
unsigned i;
copy_block(&blockR, ref_block);
@@ -57,16 +58,20 @@ static void fill_block(const block *prev_block, const block *ref_block,
xor_block(next_block, &blockR);
}
static void fill_block_with_xor(const block *prev_block, const block *ref_block,
block *next_block) {
block blockR, block_tmp;
static void
fill_block_with_xor(const block *prev_block, const block *ref_block,
block *next_block)
{
block blockR, block_tmp;
unsigned i;
copy_block(&blockR, ref_block);
xor_block(&blockR, prev_block);
copy_block(&block_tmp, &blockR);
xor_block(&block_tmp, next_block); /* Saving the next block contents for XOR over */
/* Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block + next_block */
xor_block(&block_tmp,
next_block); /* Saving the next block contents for XOR over */
/* Now blockR = ref_block + prev_block and bloc_tmp = ref_block + prev_block
* + next_block */
/* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
(16,17,..31)... finally (112,113,...127) */
for (i = 0; i < 8; ++i) {
@@ -103,10 +108,11 @@ static void fill_block_with_xor(const block *prev_block, const block *ref_block,
* @param pseudo_rands Pointer to the array of 64-bit values
* @pre pseudo_rands must point to @a instance->segment_length allocated values
*/
static void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands) {
block zero_block, input_block, address_block, tmp_block;
static void
generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position, uint64_t *pseudo_rands)
{
block zero_block, input_block, address_block, tmp_block;
uint32_t i;
init_block_value(&zero_block, 0);
@@ -134,13 +140,14 @@ static void generate_addresses(const argon2_instance_t *instance,
}
}
int fill_segment_ref(const argon2_instance_t *instance,
argon2_position_t position) {
block *ref_block = NULL, *curr_block = NULL;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint32_t starting_index;
uint32_t i;
int
fill_segment_ref(const argon2_instance_t *instance, argon2_position_t position)
{
block * ref_block = NULL, *curr_block = NULL;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint32_t starting_index;
uint32_t i;
const int data_independent_addressing = 1; /* instance->type == Argon2_i */
/* Pseudo-random values that determine the reference block position */
uint64_t *pseudo_rands = NULL;
@@ -150,7 +157,7 @@ int fill_segment_ref(const argon2_instance_t *instance,
}
pseudo_rands =
(uint64_t *)malloc(sizeof(uint64_t) * (instance->segment_length));
(uint64_t *) malloc(sizeof(uint64_t) * (instance->segment_length));
if (pseudo_rands == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
@@ -189,7 +196,7 @@ int fill_segment_ref(const argon2_instance_t *instance,
/* 1.2.1 Taking pseudo-random value from the previous block */
if (data_independent_addressing) {
#pragma warning(push)
#pragma warning(disable: 6385)
#pragma warning(disable : 6385)
pseudo_rand = pseudo_rands[i];
#pragma warning(pop)
} else {
@@ -212,13 +219,15 @@ int fill_segment_ref(const argon2_instance_t *instance,
ref_lane == position.lane);
/* 2 Creating a new block */
ref_block =
instance->region->memory + instance->lane_length * ref_lane + ref_index;
ref_block = instance->region->memory +
instance->lane_length * ref_lane + ref_index;
curr_block = instance->region->memory + curr_offset;
if (position.pass != 0) {
fill_block_with_xor(instance->region->memory + prev_offset, ref_block, curr_block);
fill_block_with_xor(instance->region->memory + prev_offset,
ref_block, curr_block);
} else {
fill_block(instance->region->memory + prev_offset, ref_block, curr_block);
fill_block(instance->region->memory + prev_offset, ref_block,
curr_block);
}
}
@@ -226,4 +235,3 @@ int fill_segment_ref(const argon2_instance_t *instance,
return ARGON2_OK;
}
@@ -16,56 +16,32 @@
#include <string.h>
#if (defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)) || \
(defined(_MSC_VER) && (defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
(defined(_MSC_VER) && \
(defined(_M_X64) || defined(_M_AMD64) || defined(_M_IX86)))
#pragma GCC target("sse2")
#pragma GCC target("ssse3")
#ifdef _MSC_VER
# include <intrin.h> /* for _mm_set_epi64x */
#include <intrin.h> /* for _mm_set_epi64x */
#endif
#include <emmintrin.h>
#include <tmmintrin.h>
#include "argon2.h"
#include "argon2-core.h"
#include "argon2.h"
#include "blamka-round-ssse3.h"
#include "private/common.h"
static void fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
static void
fill_block(__m128i *state, const uint8_t *ref_block, uint8_t *next_block)
{
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
uint32_t i;
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
block_XY[i] = state[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i])));
}
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
state[8 * i + 6], state[8 * i + 7]);
}
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
state[8 * 6 + i], state[8 * 7 + i]);
}
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(state[i], block_XY[i]);
_mm_storeu_si128((__m128i *)(&next_block[16 * i]), state[i]);
}
}
static void fill_block_with_xor(__m128i *state, const uint8_t *ref_block, uint8_t *next_block) {
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
uint32_t i;
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(state[i], _mm_loadu_si128((__m128i const *)(&ref_block[16 * i])));
block_XY[i] = _mm_xor_si128(state[i], _mm_loadu_si128((__m128i const *)(&next_block[16 * i])));
state[i], _mm_loadu_si128((__m128i const *) (&ref_block[16 * i])));
}
for (i = 0; i < 8; ++i) {
@@ -82,14 +58,47 @@ static void fill_block_with_xor(__m128i *state, const uint8_t *ref_block, uint8_
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(state[i], block_XY[i]);
_mm_storeu_si128((__m128i *)(&next_block[16 * i]), state[i]);
_mm_storeu_si128((__m128i *) (&next_block[16 * i]), state[i]);
}
}
static void generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position,
uint64_t *pseudo_rands) {
block address_block, input_block, tmp_block;
static void
fill_block_with_xor(__m128i *state, const uint8_t *ref_block,
uint8_t *next_block)
{
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
uint32_t i;
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((__m128i const *) (&ref_block[16 * i])));
block_XY[i] = _mm_xor_si128(
state[i], _mm_loadu_si128((__m128i const *) (&next_block[16 * i])));
}
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
state[8 * i + 6], state[8 * i + 7]);
}
for (i = 0; i < 8; ++i) {
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
state[8 * 6 + i], state[8 * 7 + i]);
}
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
state[i] = _mm_xor_si128(state[i], block_XY[i]);
_mm_storeu_si128((__m128i *) (&next_block[16 * i]), state[i]);
}
}
static void
generate_addresses(const argon2_instance_t *instance,
const argon2_position_t *position, uint64_t *pseudo_rands)
{
block address_block, input_block, tmp_block;
uint32_t i;
init_block_value(&address_block, 0);
@@ -115,9 +124,11 @@ static void generate_addresses(const argon2_instance_t *instance,
/* Increasing index counter */
input_block.v[6]++;
/* First iteration of G */
fill_block_with_xor(zero_block, (uint8_t *)&input_block.v, (uint8_t *)&tmp_block.v);
fill_block_with_xor(zero_block, (uint8_t *) &input_block.v,
(uint8_t *) &tmp_block.v);
/* Second iteration of G */
fill_block_with_xor(zero2_block, (uint8_t *)&tmp_block.v, (uint8_t *)&address_block.v);
fill_block_with_xor(zero2_block, (uint8_t *) &tmp_block.v,
(uint8_t *) &address_block.v);
}
pseudo_rands[i] = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
@@ -125,13 +136,15 @@ static void generate_addresses(const argon2_instance_t *instance,
}
}
int fill_segment_ssse3(const argon2_instance_t *instance,
argon2_position_t position) {
block *ref_block = NULL, *curr_block = NULL;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint32_t starting_index, i;
__m128i state[64];
int
fill_segment_ssse3(const argon2_instance_t *instance,
argon2_position_t position)
{
block * ref_block = NULL, *curr_block = NULL;
uint64_t pseudo_rand, ref_index, ref_lane;
uint32_t prev_offset, curr_offset;
uint32_t starting_index, i;
__m128i state[64];
const int data_independent_addressing = 1; /* instance->type == Argon2_i */
/* Pseudo-random values that determine the reference block position */
@@ -142,7 +155,7 @@ int fill_segment_ssse3(const argon2_instance_t *instance,
}
pseudo_rands =
(uint64_t *)malloc(sizeof(uint64_t) * instance->segment_length);
(uint64_t *) malloc(sizeof(uint64_t) * instance->segment_length);
if (pseudo_rands == NULL) {
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
@@ -169,7 +182,8 @@ int fill_segment_ssse3(const argon2_instance_t *instance,
prev_offset = curr_offset - 1;
}
memcpy(state, ((instance->region->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
memcpy(state, ((instance->region->memory + prev_offset)->v),
ARGON2_BLOCK_SIZE);
for (i = starting_index; i < instance->segment_length;
++i, ++curr_offset, ++prev_offset) {
@@ -182,7 +196,7 @@ int fill_segment_ssse3(const argon2_instance_t *instance,
/* 1.2.1 Taking pseudo-random value from the previous block */
if (data_independent_addressing) {
#pragma warning(push)
#pragma warning(disable: 6385)
#pragma warning(disable : 6385)
pseudo_rand = pseudo_rands[i];
#pragma warning(pop)
} else {
@@ -205,13 +219,15 @@ int fill_segment_ssse3(const argon2_instance_t *instance,
ref_lane == position.lane);
/* 2 Creating a new block */
ref_block =
instance->region->memory + instance->lane_length * ref_lane + ref_index;
ref_block = instance->region->memory +
instance->lane_length * ref_lane + ref_index;
curr_block = instance->region->memory + curr_offset;
if (position.pass != 0) {
fill_block_with_xor(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
fill_block_with_xor(state, (uint8_t *) ref_block->v,
(uint8_t *) curr_block->v);
} else {
fill_block(state, (uint8_t *)ref_block->v, (uint8_t *)curr_block->v);
fill_block(state, (uint8_t *) ref_block->v,
(uint8_t *) curr_block->v);
}
}
+74 -66
View File
@@ -11,22 +11,24 @@
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "argon2.h"
#include "argon2-encoding.h"
#include "argon2-core.h"
#include "argon2-encoding.h"
#include "argon2.h"
int argon2_ctx(argon2_context *context, argon2_type type) {
int
argon2_ctx(argon2_context *context, argon2_type type)
{
/* 1. Validate all inputs */
int result = validate_inputs(context);
uint32_t memory_blocks, segment_length;
int result = validate_inputs(context);
uint32_t memory_blocks, segment_length;
argon2_instance_t instance;
if (ARGON2_OK != result) {
@@ -49,14 +51,14 @@ int argon2_ctx(argon2_context *context, argon2_type type) {
/* Ensure that all segments have equal length */
memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
instance.region = NULL;
instance.passes = context->t_cost;
instance.memory_blocks = memory_blocks;
instance.region = NULL;
instance.passes = context->t_cost;
instance.memory_blocks = memory_blocks;
instance.segment_length = segment_length;
instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
instance.lanes = context->lanes;
instance.threads = context->threads;
instance.type = type;
instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
instance.lanes = context->lanes;
instance.threads = context->threads;
instance.type = type;
/* 3. Initialization: Hashing inputs, allocating memory, filling first
* blocks
@@ -80,15 +82,16 @@ int argon2_ctx(argon2_context *context, argon2_type type) {
return ARGON2_OK;
}
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt, const size_t saltlen,
void *hash, const size_t hashlen, char *encoded,
const size_t encodedlen, argon2_type type) {
int
argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd, const size_t pwdlen,
const void *salt, const size_t saltlen, void *hash,
const size_t hashlen, char *encoded, const size_t encodedlen,
argon2_type type)
{
argon2_context context;
int result;
uint8_t *out;
int result;
uint8_t * out;
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
return ARGON2_PWD_TOO_LONG;
@@ -107,21 +110,21 @@ int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
return ARGON2_MEMORY_ALLOCATION_ERROR;
}
context.out = (uint8_t *)out;
context.outlen = (uint32_t)hashlen;
context.pwd = (uint8_t *)pwd;
context.pwdlen = (uint32_t)pwdlen;
context.salt = (uint8_t *)salt;
context.saltlen = (uint32_t)saltlen;
context.secret = NULL;
context.out = (uint8_t *) out;
context.outlen = (uint32_t) hashlen;
context.pwd = (uint8_t *) pwd;
context.pwdlen = (uint32_t) pwdlen;
context.salt = (uint8_t *) salt;
context.saltlen = (uint32_t) saltlen;
context.secret = NULL;
context.secretlen = 0;
context.ad = NULL;
context.adlen = 0;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = parallelism;
context.threads = parallelism;
context.flags = ARGON2_DEFAULT_FLAGS;
context.ad = NULL;
context.adlen = 0;
context.t_cost = t_cost;
context.m_cost = m_cost;
context.lanes = parallelism;
context.threads = parallelism;
context.flags = ARGON2_DEFAULT_FLAGS;
result = argon2_ctx(&context, type);
@@ -152,39 +155,42 @@ int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
return ARGON2_OK;
}
int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, const size_t hashlen,
char *encoded, const size_t encodedlen) {
int
argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, const size_t hashlen, char *encoded,
const size_t encodedlen)
{
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
NULL, hashlen, encoded, encodedlen, Argon2_i);
}
int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt,
const size_t saltlen, void *hash, const size_t hashlen) {
int
argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
const uint32_t parallelism, const void *pwd,
const size_t pwdlen, const void *salt, const size_t saltlen,
void *hash, const size_t hashlen)
{
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
hash, hashlen, NULL, 0, Argon2_i);
}
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
argon2_type type) {
int
argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
argon2_type type)
{
argon2_context ctx;
uint8_t *out;
int decode_result;
int ret;
size_t encoded_len;
uint8_t * out;
int decode_result;
int ret;
size_t encoded_len;
memset(&ctx, 0, sizeof ctx);
ctx.pwd = NULL;
ctx.pwdlen = 0;
ctx.secret = NULL;
ctx.pwd = NULL;
ctx.pwdlen = 0;
ctx.secret = NULL;
ctx.secretlen = 0;
/* max values, to be updated in decode_string */
@@ -192,13 +198,13 @@ int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
if (encoded_len > UINT32_MAX) {
return ARGON2_DECODING_LENGTH_FAIL;
}
ctx.adlen = (uint32_t) encoded_len;
ctx.adlen = (uint32_t) encoded_len;
ctx.saltlen = (uint32_t) encoded_len;
ctx.outlen = (uint32_t) encoded_len;
ctx.outlen = (uint32_t) encoded_len;
ctx.ad = (uint8_t *) malloc(ctx.adlen);
ctx.ad = (uint8_t *) malloc(ctx.adlen);
ctx.salt = (uint8_t *) malloc(ctx.saltlen);
ctx.out = (uint8_t *) malloc(ctx.outlen);
ctx.out = (uint8_t *) malloc(ctx.outlen);
if (!ctx.out || !ctx.salt || !ctx.ad) {
free(ctx.ad);
free(ctx.salt);
@@ -222,8 +228,8 @@ int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
return decode_result;
}
ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, ctx.salt,
ctx.saltlen, out, ctx.outlen, NULL, 0, type);
ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen,
ctx.salt, ctx.saltlen, out, ctx.outlen, NULL, 0, type);
free(ctx.ad);
free(ctx.salt);
@@ -237,6 +243,8 @@ int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
return ret;
}
int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
int
argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen)
{
return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
}
+27 -22
View File
@@ -6,14 +6,15 @@
* This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef argon2_H
#define argon2_H
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
/*
* Argon2 input parameter restrictions
@@ -38,10 +39,11 @@
#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
/* Max memory size is half the addressing space, topping at 2^32 blocks (4 TB) */
#define ARGON2_MAX_MEMORY_BITS \
/* Max memory size is half the addressing space, topping at 2^32 blocks (4 TB)
*/
#define ARGON2_MAX_MEMORY_BITS \
ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
#define ARGON2_MAX_MEMORY \
#define ARGON2_MAX_MEMORY \
ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
/* Minimum and maximum number of passes */
@@ -76,45 +78,45 @@ typedef enum Argon2_ErrorCodes {
ARGON2_OUTPUT_PTR_NULL = -1,
ARGON2_OUTPUT_TOO_SHORT = -2,
ARGON2_OUTPUT_TOO_LONG = -3,
ARGON2_OUTPUT_TOO_LONG = -3,
ARGON2_PWD_TOO_SHORT = -4,
ARGON2_PWD_TOO_LONG = -5,
ARGON2_PWD_TOO_LONG = -5,
ARGON2_SALT_TOO_SHORT = -6,
ARGON2_SALT_TOO_LONG = -7,
ARGON2_SALT_TOO_LONG = -7,
ARGON2_AD_TOO_SHORT = -8,
ARGON2_AD_TOO_LONG = -9,
ARGON2_AD_TOO_LONG = -9,
ARGON2_SECRET_TOO_SHORT = -10,
ARGON2_SECRET_TOO_LONG = -11,
ARGON2_SECRET_TOO_LONG = -11,
ARGON2_TIME_TOO_SMALL = -12,
ARGON2_TIME_TOO_LARGE = -13,
ARGON2_MEMORY_TOO_LITTLE = -14,
ARGON2_MEMORY_TOO_MUCH = -15,
ARGON2_MEMORY_TOO_MUCH = -15,
ARGON2_LANES_TOO_FEW = -16,
ARGON2_LANES_TOO_FEW = -16,
ARGON2_LANES_TOO_MANY = -17,
ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
ARGON2_MEMORY_ALLOCATION_ERROR = -22,
ARGON2_FREE_MEMORY_CBK_NULL = -23,
ARGON2_FREE_MEMORY_CBK_NULL = -23,
ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
ARGON2_INCORRECT_PARAMETER = -25,
ARGON2_INCORRECT_TYPE = -26,
ARGON2_INCORRECT_TYPE = -26,
ARGON2_OUT_PTR_MISMATCH = -27,
ARGON2_THREADS_TOO_FEW = -28,
ARGON2_THREADS_TOO_FEW = -28,
ARGON2_THREADS_TOO_MANY = -29,
ARGON2_MISSING_ARGS = -30,
@@ -148,9 +150,12 @@ typedef enum Argon2_ErrorCodes {
* are pre-hashed (and thus not needed anymore), and the entire memory
*****
* Simplest situation: you have output array out[8], password is stored in
* pwd[32], salt is stored in salt[16], you do not have keys nor associated data.
* You need to spend 1 GB of RAM and you run 5 passes of Argon2 with 4 parallel lanes.
* You want to erase the password, but you're OK with last pass not being erased.
* pwd[32], salt is stored in salt[16], you do not have keys nor associated
*data.
* You need to spend 1 GB of RAM and you run 5 passes of Argon2 with 4 parallel
*lanes.
* You want to erase the password, but you're OK with last pass not being
*erased.
* You want to use the default memory allocator.
* Then you initialize:
* Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false).
@@ -4,63 +4,63 @@
#include <string.h>
#include "crypto_generichash_blake2b.h"
#include "utils.h"
#include "private/common.h"
#include "utils.h"
#include "blake2b-long.h"
int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
uint8_t *out = (uint8_t *)pout;
int
blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen)
{
uint8_t * out = (uint8_t *) pout;
crypto_generichash_blake2b_state blake_state;
uint8_t outlen_bytes[4 /* sizeof(uint32_t) */] = {0};
int ret = -1;
uint8_t outlen_bytes[4 /* sizeof(uint32_t) */] = { 0 };
int ret = -1;
if (outlen > UINT32_MAX) {
goto fail; /* LCOV_EXCL_LINE */
}
/* Ensure little-endian byte order! */
STORE32_LE(outlen_bytes, (uint32_t)outlen);
STORE32_LE(outlen_bytes, (uint32_t) outlen);
#define TRY(statement) \
do { \
ret = statement; \
if (ret < 0) { \
goto fail; \
} \
} while ((void)0, 0)
#define TRY(statement) \
do { \
ret = statement; \
if (ret < 0) { \
goto fail; \
} \
} while ((void) 0, 0)
if (outlen <= crypto_generichash_blake2b_BYTES_MAX) {
TRY(crypto_generichash_blake2b_init(&blake_state, NULL, 0U, outlen));
TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes,
sizeof(outlen_bytes)));
TRY(crypto_generichash_blake2b_update(&blake_state,
(const unsigned char *) in,
inlen));
TRY(crypto_generichash_blake2b_update(
&blake_state, (const unsigned char *) in, inlen));
TRY(crypto_generichash_blake2b_final(&blake_state, out, outlen));
} else {
uint32_t toproduce;
uint8_t out_buffer[crypto_generichash_blake2b_BYTES_MAX];
uint8_t in_buffer[crypto_generichash_blake2b_BYTES_MAX];
TRY(crypto_generichash_blake2b_init(&blake_state, NULL, 0U,
crypto_generichash_blake2b_BYTES_MAX));
uint8_t out_buffer[crypto_generichash_blake2b_BYTES_MAX];
uint8_t in_buffer[crypto_generichash_blake2b_BYTES_MAX];
TRY(crypto_generichash_blake2b_init(
&blake_state, NULL, 0U, crypto_generichash_blake2b_BYTES_MAX));
TRY(crypto_generichash_blake2b_update(&blake_state, outlen_bytes,
sizeof(outlen_bytes)));
TRY(crypto_generichash_blake2b_update(&blake_state,
(const unsigned char *) in,
inlen));
TRY(crypto_generichash_blake2b_final(&blake_state, out_buffer,
crypto_generichash_blake2b_BYTES_MAX));
TRY(crypto_generichash_blake2b_update(
&blake_state, (const unsigned char *) in, inlen));
TRY(crypto_generichash_blake2b_final(
&blake_state, out_buffer, crypto_generichash_blake2b_BYTES_MAX));
memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2);
out += crypto_generichash_blake2b_BYTES_MAX / 2;
toproduce = (uint32_t)outlen - crypto_generichash_blake2b_BYTES_MAX / 2;
toproduce =
(uint32_t) outlen - crypto_generichash_blake2b_BYTES_MAX / 2;
while (toproduce > crypto_generichash_blake2b_BYTES_MAX) {
memcpy(in_buffer, out_buffer, crypto_generichash_blake2b_BYTES_MAX);
TRY(crypto_generichash_blake2b(out_buffer, crypto_generichash_blake2b_BYTES_MAX,
in_buffer,
crypto_generichash_blake2b_BYTES_MAX,
NULL, 0U));
TRY(crypto_generichash_blake2b(
out_buffer, crypto_generichash_blake2b_BYTES_MAX, in_buffer,
crypto_generichash_blake2b_BYTES_MAX, NULL, 0U));
memcpy(out, out_buffer, crypto_generichash_blake2b_BYTES_MAX / 2);
out += crypto_generichash_blake2b_BYTES_MAX / 2;
toproduce -= crypto_generichash_blake2b_BYTES_MAX / 2;
@@ -4,35 +4,37 @@
#include "private/common.h"
/*designed by the Lyra PHC team */
static inline uint64_t fBlaMka(uint64_t x, uint64_t y) {
const uint64_t m = UINT64_C(0xFFFFFFFF);
static inline uint64_t
fBlaMka(uint64_t x, uint64_t y)
{
const uint64_t m = UINT64_C(0xFFFFFFFF);
const uint64_t xy = (x & m) * (y & m);
return x + y + 2 * xy;
}
#define G(a, b, c, d) \
do { \
a = fBlaMka(a, b); \
d = ROTR64(d ^ a, 32); \
c = fBlaMka(c, d); \
b = ROTR64(b ^ c, 24); \
a = fBlaMka(a, b); \
d = ROTR64(d ^ a, 16); \
c = fBlaMka(c, d); \
b = ROTR64(b ^ c, 63); \
} while ((void)0, 0)
#define G(a, b, c, d) \
do { \
a = fBlaMka(a, b); \
d = ROTR64(d ^ a, 32); \
c = fBlaMka(c, d); \
b = ROTR64(b ^ c, 24); \
a = fBlaMka(a, b); \
d = ROTR64(d ^ a, 16); \
c = fBlaMka(c, d); \
b = ROTR64(b ^ c, 63); \
} while ((void) 0, 0)
#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
v12, v13, v14, v15) \
do { \
G(v0, v4, v8, v12); \
G(v1, v5, v9, v13); \
G(v2, v6, v10, v14); \
G(v3, v7, v11, v15); \
G(v0, v5, v10, v15); \
G(v1, v6, v11, v12); \
G(v2, v7, v8, v13); \
G(v3, v4, v9, v14); \
} while ((void)0, 0)
#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
v12, v13, v14, v15) \
do { \
G(v0, v4, v8, v12); \
G(v1, v5, v9, v13); \
G(v2, v6, v10, v14); \
G(v3, v7, v11, v15); \
G(v0, v5, v10, v15); \
G(v1, v6, v11, v12); \
G(v2, v7, v8, v13); \
G(v3, v4, v9, v14); \
} while ((void) 0, 0)
#endif
@@ -3,115 +3,117 @@
#include "private/common.h"
#define r16 \
#define r16 \
(_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
#define r24 \
#define r24 \
(_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
#define _mm_roti_epi64(x, c) \
(-(c) == 32) \
? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
: (-(c) == 24) \
? _mm_shuffle_epi8((x), r24) \
: (-(c) == 16) \
? _mm_shuffle_epi8((x), r16) \
: (-(c) == 63) \
? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_add_epi64((x), (x))) \
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
#define _mm_roti_epi64(x, c) \
(-(c) == 32) \
? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
: (-(c) == 24) \
? _mm_shuffle_epi8((x), r24) \
: (-(c) == 16) \
? _mm_shuffle_epi8((x), r16) \
: (-(c) == 63) \
? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_add_epi64((x), (x))) \
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
_mm_slli_epi64((x), 64 - (-(c))))
static inline __m128i fBlaMka(__m128i x, __m128i y) {
static inline __m128i
fBlaMka(__m128i x, __m128i y)
{
const __m128i z = _mm_mul_epu32(x, y);
return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
}
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -32); \
D1 = _mm_roti_epi64(D1, -32); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -24); \
B1 = _mm_roti_epi64(B1, -24); \
} while ((void)0, 0)
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -32); \
D1 = _mm_roti_epi64(D1, -32); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -24); \
B1 = _mm_roti_epi64(B1, -24); \
} while ((void) 0, 0)
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -16); \
D1 = _mm_roti_epi64(D1, -16); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -63); \
B1 = _mm_roti_epi64(B1, -63); \
} while ((void)0, 0)
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
A0 = fBlaMka(A0, B0); \
A1 = fBlaMka(A1, B1); \
\
D0 = _mm_xor_si128(D0, A0); \
D1 = _mm_xor_si128(D1, A1); \
\
D0 = _mm_roti_epi64(D0, -16); \
D1 = _mm_roti_epi64(D1, -16); \
\
C0 = fBlaMka(C0, D0); \
C1 = fBlaMka(C1, D1); \
\
B0 = _mm_xor_si128(B0, C0); \
B1 = _mm_xor_si128(B1, C1); \
\
B0 = _mm_roti_epi64(B0, -63); \
B1 = _mm_roti_epi64(B1, -63); \
} while ((void) 0, 0)
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
__m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D1, D0, 8); \
t1 = _mm_alignr_epi8(D0, D1, 8); \
D0 = t1; \
D1 = t0; \
} while ((void)0, 0)
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
__m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D1, D0, 8); \
t1 = _mm_alignr_epi8(D0, D1, 8); \
D0 = t1; \
D1 = t0; \
} while ((void) 0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
__m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D0, D1, 8); \
t1 = _mm_alignr_epi8(D1, D0, 8); \
D0 = t1; \
D1 = t0; \
} while ((void)0, 0)
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
do { \
__m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
__m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
B0 = t0; \
B1 = t1; \
\
t0 = C0; \
C0 = C1; \
C1 = t0; \
\
t0 = _mm_alignr_epi8(D0, D1, 8); \
t1 = _mm_alignr_epi8(D1, D0, 8); \
D0 = t1; \
D1 = t0; \
} while ((void) 0, 0)
#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
\
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
} while ((void)0, 0)
#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
do { \
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
\
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
\
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
} while ((void) 0, 0)
#endif
@@ -5,8 +5,8 @@
#include <stdint.h>
#include <string.h>
#include "argon2.h"
#include "argon2-core.h"
#include "argon2.h"
#include "crypto_pwhash_argon2i.h"
#include "randombytes.h"
#include "utils.h"
@@ -55,7 +55,7 @@ crypto_pwhash_argon2i_strbytes(void)
return crypto_pwhash_argon2i_STRBYTES;
}
const char *
const char*
crypto_pwhash_argon2i_strprefix(void)
{
return crypto_pwhash_argon2i_STRPREFIX;
@@ -122,13 +122,10 @@ crypto_pwhash_argon2i_memlimit_sensitive(void)
}
int
crypto_pwhash_argon2i(unsigned char * const out,
unsigned long long outlen,
const char * const passwd,
unsigned long long passwdlen,
const unsigned char * const salt,
unsigned long long opslimit,
size_t memlimit, int alg)
crypto_pwhash_argon2i(unsigned char* const out, unsigned long long outlen,
const char* const passwd, unsigned long long passwdlen,
const unsigned char* const salt,
unsigned long long opslimit, size_t memlimit, int alg)
{
memset(out, 0, outlen);
if (alg != crypto_pwhash_argon2i_ALG_ARGON2I13) {
@@ -146,40 +143,39 @@ crypto_pwhash_argon2i(unsigned char * const out,
return -1;
}
if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) memlimit,
(uint32_t) 1U, passwd, (size_t) passwdlen,
salt, (size_t) crypto_pwhash_argon2i_SALTBYTES,
out, (size_t) outlen) != ARGON2_OK) {
(uint32_t) 1U, passwd, (size_t) passwdlen, salt,
(size_t) crypto_pwhash_argon2i_SALTBYTES, out,
(size_t) outlen) != ARGON2_OK) {
return -1; /* LCOV_EXCL_LINE */
}
return 0;
}
int
crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
const char * const passwd,
crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
const char* const passwd,
unsigned long long passwdlen,
unsigned long long opslimit,
size_t memlimit)
unsigned long long opslimit, size_t memlimit)
{
unsigned char salt[crypto_pwhash_argon2i_SALTBYTES];
memset(out, 0, crypto_pwhash_argon2i_STRBYTES);
memlimit /= 1024U;
if (passwdlen > ARGON2_MAX_PWD_LENGTH ||
opslimit > ARGON2_MAX_TIME || memlimit > ARGON2_MAX_MEMORY) {
if (passwdlen > ARGON2_MAX_PWD_LENGTH || opslimit > ARGON2_MAX_TIME ||
memlimit > ARGON2_MAX_MEMORY) {
errno = EFBIG;
return -1;
}
if (passwdlen < ARGON2_MIN_PWD_LENGTH ||
opslimit < ARGON2_MIN_TIME || memlimit < ARGON2_MIN_MEMORY) {
if (passwdlen < ARGON2_MIN_PWD_LENGTH || opslimit < ARGON2_MIN_TIME ||
memlimit < ARGON2_MIN_MEMORY) {
errno = EINVAL;
return -1;
}
randombytes_buf(salt, sizeof salt);
if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) memlimit,
(uint32_t) 1U, passwd, (size_t) passwdlen,
salt, sizeof salt, STR_HASHBYTES,
out, crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) {
(uint32_t) 1U, passwd, (size_t) passwdlen, salt,
sizeof salt, STR_HASHBYTES, out,
crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) {
return -1; /* LCOV_EXCL_LINE */
}
return 0;
@@ -187,19 +183,19 @@ crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
int
crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
const char * const passwd,
const char* const passwd,
unsigned long long passwdlen)
{
if (passwdlen > ARGON2_MAX_PWD_LENGTH) {
errno = EFBIG;
return -1;
}
/* LCOV_EXCL_START */
/* LCOV_EXCL_START */
if (passwdlen < ARGON2_MIN_PWD_LENGTH) {
errno = EINVAL;
return -1;
}
/* LCOV_EXCL_STOP */
/* LCOV_EXCL_STOP */
if (argon2i_verify(str, passwd, (size_t) passwdlen) != ARGON2_OK) {
return -1;
}