CryptX
view release on metacpan or search on metacpan
src/ltc/misc/argon2/argon2.c view on Meta::CPAN
}
zeromem(blockhash_bytes, ARGON2_BLOCK_SIZE);
return CRYPT_OK;
}
/* Finalize: XOR last blocks, produce tag */
static int s_finalize(unsigned char *out, unsigned long outlen,
const argon2_instance *instance)
{
argon2_block blockhash;
unsigned char blockhash_bytes[ARGON2_BLOCK_SIZE];
ulong32 l;
int err;
s_block_copy(&blockhash, instance->memory + instance->lane_length - 1);
for (l = 1; l < instance->lanes; ++l) {
ulong32 last = l * instance->lane_length + (instance->lane_length - 1);
s_block_xor(&blockhash, instance->memory + last);
}
s_block_store(blockhash_bytes, &blockhash);
err = s_blake2b_long(out, outlen, blockhash_bytes, ARGON2_BLOCK_SIZE);
zeromem(blockhash.v, ARGON2_BLOCK_SIZE);
zeromem(blockhash_bytes, ARGON2_BLOCK_SIZE);
return err;
}
/* Fill the entire memory */
static void s_fill_memory(argon2_instance *instance)
{
ulong32 r, s, l;
for (r = 0; r < instance->passes; ++r) {
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
for (l = 0; l < instance->lanes; ++l) {
argon2_position position;
position.pass = r;
position.lane = l;
position.slice = (unsigned char)s;
position.index = 0;
s_fill_segment(instance, position);
}
}
}
}
/**
Hash a password with Argon2 (RFC 9106)
@param pwd Password (or message)
@param pwdlen Length of password
@param salt Salt
@param saltlen Length of salt
@param secret Optional secret value (may be NULL)
@param secretlen Length of secret
@param ad Optional associated data (may be NULL)
@param adlen Length of associated data
@param t_cost Number of passes (iterations), minimum 1
@param m_cost Memory size in KiB, minimum 8*parallelism
@param parallelism Degree of parallelism (number of lanes), minimum 1
@param type ARGON2_D, ARGON2_I, or ARGON2_ID
@param out [out] Output tag
@param outlen Desired output length (4..2^32-1)
@return CRYPT_OK on success
*/
int argon2_hash(const unsigned char *pwd, unsigned long pwdlen,
const unsigned char *salt, unsigned long saltlen,
const unsigned char *secret, unsigned long secretlen,
const unsigned char *ad, unsigned long adlen,
unsigned int t_cost, unsigned int m_cost,
unsigned int parallelism,
argon2_type type,
unsigned char *out, unsigned long outlen)
{
argon2_instance instance;
unsigned char blockhash[ARGON2_PREHASH_SEED_LEN];
ulong32 memory_blocks, segment_length;
int err;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen >= ARGON2_MIN_OUTLEN);
LTC_ARGCHK(pwd != NULL || pwdlen == 0);
LTC_ARGCHK(salt != NULL || saltlen == 0);
LTC_ARGCHK(secret != NULL || secretlen == 0);
LTC_ARGCHK(ad != NULL || adlen == 0);
LTC_ARGCHK(t_cost >= 1);
LTC_ARGCHK(parallelism >= 1);
LTC_ARGCHK(m_cost >= 8 * parallelism);
LTC_ARGCHK(type == ARGON2_D || type == ARGON2_I || type == ARGON2_ID);
/* Align memory: ensure memory_blocks is a multiple of 4*parallelism */
memory_blocks = (ulong32)m_cost;
if (memory_blocks < 2 * ARGON2_SYNC_POINTS * (ulong32)parallelism) {
memory_blocks = 2 * ARGON2_SYNC_POINTS * (ulong32)parallelism;
}
segment_length = memory_blocks / ((ulong32)parallelism * ARGON2_SYNC_POINTS);
memory_blocks = segment_length * ((ulong32)parallelism * ARGON2_SYNC_POINTS);
/* Set up instance */
instance.passes = (ulong32)t_cost;
instance.memory_blocks = memory_blocks;
instance.segment_length = segment_length;
instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
instance.lanes = (ulong32)parallelism;
instance.type = (int)type;
instance.memory = NULL;
/* Allocate memory */
{
unsigned long alloc_size = (unsigned long)memory_blocks * sizeof(argon2_block);
/* overflow check */
if (alloc_size / sizeof(argon2_block) != memory_blocks) {
return CRYPT_OVERFLOW;
}
instance.memory = XMALLOC(alloc_size);
if (instance.memory == NULL) {
return CRYPT_MEM;
}
( run in 0.442 second using v1.01-cache-2.11-cpan-71847e10f99 )