Path: blob/main/crypto/openssl/providers/implementations/kdfs/argon2.c
48383 views
/*1* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*8* RFC 9106 Argon2 (see https://www.rfc-editor.org/rfc/rfc9106.txt)9*10*/1112#include <stdlib.h>13#include <stddef.h>14#include <stdarg.h>15#include <string.h>16#include <openssl/e_os2.h>17#include <openssl/evp.h>18#include <openssl/objects.h>19#include <openssl/crypto.h>20#include <openssl/kdf.h>21#include <openssl/err.h>22#include <openssl/core_names.h>23#include <openssl/params.h>24#include <openssl/thread.h>25#include <openssl/proverr.h>26#include "internal/thread.h"27#include "internal/numbers.h"28#include "internal/endian.h"29#include "crypto/evp.h"30#include "prov/implementations.h"31#include "prov/provider_ctx.h"32#include "prov/providercommon.h"33#include "prov/blake2.h"3435#if defined(OPENSSL_NO_DEFAULT_THREAD_POOL) && defined(OPENSSL_NO_THREAD_POOL)36# define ARGON2_NO_THREADS37#endif3839#if !defined(OPENSSL_THREADS)40# define ARGON2_NO_THREADS41#endif4243#ifndef OPENSSL_NO_ARGON24445# define ARGON2_MIN_LANES 1u46# define ARGON2_MAX_LANES 0xFFFFFFu47# define ARGON2_MIN_THREADS 1u48# define ARGON2_MAX_THREADS 0xFFFFFFu49# define ARGON2_SYNC_POINTS 4u50# define ARGON2_MIN_OUT_LENGTH 4u51# define ARGON2_MAX_OUT_LENGTH 0xFFFFFFFFu52# define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS)53# define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))54# define ARGON2_MAX_MEMORY 0xFFFFFFFFu55# define ARGON2_MIN_TIME 1u56# define ARGON2_MAX_TIME 0xFFFFFFFFu57# define ARGON2_MIN_PWD_LENGTH 0u58# define ARGON2_MAX_PWD_LENGTH 0xFFFFFFFFu59# define ARGON2_MIN_AD_LENGTH 0u60# define ARGON2_MAX_AD_LENGTH 0xFFFFFFFFu61# define ARGON2_MIN_SALT_LENGTH 8u62# define ARGON2_MAX_SALT_LENGTH 0xFFFFFFFFu63# define ARGON2_MIN_SECRET 0u64# define ARGON2_MAX_SECRET 0xFFFFFFFFu65# define ARGON2_BLOCK_SIZE 102466# define ARGON2_QWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 8)67# define ARGON2_OWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 16)68# define ARGON2_HWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 32)69# define ARGON2_512BIT_WORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 64)70# define ARGON2_ADDRESSES_IN_BLOCK 12871# define ARGON2_PREHASH_DIGEST_LENGTH 6472# define ARGON2_PREHASH_SEED_LENGTH \73(ARGON2_PREHASH_DIGEST_LENGTH + (2 * sizeof(uint32_t)))7475# define ARGON2_DEFAULT_OUTLEN 64u76# define ARGON2_DEFAULT_T_COST 3u77# define ARGON2_DEFAULT_M_COST ARGON2_MIN_MEMORY78# define ARGON2_DEFAULT_LANES 1u79# define ARGON2_DEFAULT_THREADS 1u80# define ARGON2_DEFAULT_VERSION ARGON2_VERSION_NUMBER8182# undef G83# define G(a, b, c, d) \84do { \85a = a + b + 2 * mul_lower(a, b); \86d = rotr64(d ^ a, 32); \87c = c + d + 2 * mul_lower(c, d); \88b = rotr64(b ^ c, 24); \89a = a + b + 2 * mul_lower(a, b); \90d = rotr64(d ^ a, 16); \91c = c + d + 2 * mul_lower(c, d); \92b = rotr64(b ^ c, 63); \93} while ((void)0, 0)9495# undef PERMUTATION_P96# define PERMUTATION_P(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \97v12, v13, v14, v15) \98do { \99G(v0, v4, v8, v12); \100G(v1, v5, v9, v13); \101G(v2, v6, v10, v14); \102G(v3, v7, v11, v15); \103G(v0, v5, v10, v15); \104G(v1, v6, v11, v12); \105G(v2, v7, v8, v13); \106G(v3, v4, v9, v14); \107} while ((void)0, 0)108109# undef PERMUTATION_P_COLUMN110# define PERMUTATION_P_COLUMN(x, i) \111do { \112uint64_t *base = &x[16 * i]; \113PERMUTATION_P( \114*base, *(base + 1), *(base + 2), *(base + 3), \115*(base + 4), *(base + 5), *(base + 6), *(base + 7), \116*(base + 8), *(base + 9), *(base + 10), *(base + 11), \117*(base + 12), *(base + 13), *(base + 14), *(base + 15) \118); \119} while ((void)0, 0)120121# undef PERMUTATION_P_ROW122# define PERMUTATION_P_ROW(x, i) \123do { \124uint64_t *base = &x[2 * i]; \125PERMUTATION_P( \126*base, *(base + 1), *(base + 16), *(base + 17), \127*(base + 32), *(base + 33), *(base + 48), *(base + 49), \128*(base + 64), *(base + 65), *(base + 80), *(base + 81), \129*(base + 96), *(base + 97), *(base + 112), *(base + 113) \130); \131} while ((void)0, 0)132133typedef struct {134uint64_t v[ARGON2_QWORDS_IN_BLOCK];135} BLOCK;136137typedef enum {138ARGON2_VERSION_10 = 0x10,139ARGON2_VERSION_13 = 0x13,140ARGON2_VERSION_NUMBER = ARGON2_VERSION_13141} ARGON2_VERSION;142143typedef enum {144ARGON2_D = 0,145ARGON2_I = 1,146ARGON2_ID = 2147} ARGON2_TYPE;148149typedef struct {150uint32_t pass;151uint32_t lane;152uint8_t slice;153uint32_t index;154} ARGON2_POS;155156typedef struct {157void *provctx;158uint32_t outlen;159uint8_t *pwd;160uint32_t pwdlen;161uint8_t *salt;162uint32_t saltlen;163uint8_t *secret;164uint32_t secretlen;165uint8_t *ad;166uint32_t adlen;167uint32_t t_cost;168uint32_t m_cost;169uint32_t lanes;170uint32_t threads;171uint32_t version;172uint32_t early_clean;173ARGON2_TYPE type;174BLOCK *memory;175uint32_t passes;176uint32_t memory_blocks;177uint32_t segment_length;178uint32_t lane_length;179OSSL_LIB_CTX *libctx;180EVP_MD *md;181EVP_MAC *mac;182char *propq;183} KDF_ARGON2;184185typedef struct {186ARGON2_POS pos;187KDF_ARGON2 *ctx;188} ARGON2_THREAD_DATA;189190static OSSL_FUNC_kdf_newctx_fn kdf_argon2i_new;191static OSSL_FUNC_kdf_newctx_fn kdf_argon2d_new;192static OSSL_FUNC_kdf_newctx_fn kdf_argon2id_new;193static OSSL_FUNC_kdf_freectx_fn kdf_argon2_free;194static OSSL_FUNC_kdf_reset_fn kdf_argon2_reset;195static OSSL_FUNC_kdf_derive_fn kdf_argon2_derive;196static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_argon2_settable_ctx_params;197static OSSL_FUNC_kdf_set_ctx_params_fn kdf_argon2_set_ctx_params;198199static void kdf_argon2_init(KDF_ARGON2 *ctx, ARGON2_TYPE t);200static void *kdf_argon2d_new(void *provctx);201static void *kdf_argon2i_new(void *provctx);202static void *kdf_argon2id_new(void *provctx);203static void kdf_argon2_free(void *vctx);204static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,205const OSSL_PARAM params[]);206static void kdf_argon2_reset(void *vctx);207static int kdf_argon2_ctx_set_threads(KDF_ARGON2 *ctx, uint32_t threads);208static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes);209static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost);210static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost);211static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen);212static int kdf_argon2_ctx_set_secret(KDF_ARGON2 *ctx, const OSSL_PARAM *p);213static int kdf_argon2_ctx_set_pwd(KDF_ARGON2 *ctx, const OSSL_PARAM *p);214static int kdf_argon2_ctx_set_salt(KDF_ARGON2 *ctx, const OSSL_PARAM *p);215static int kdf_argon2_ctx_set_ad(KDF_ARGON2 *ctx, const OSSL_PARAM *p);216static int kdf_argon2_set_ctx_params(void *vctx, const OSSL_PARAM params[]);217static int kdf_argon2_get_ctx_params(void *vctx, OSSL_PARAM params[]);218static int kdf_argon2_ctx_set_version(KDF_ARGON2 *ctx, uint32_t version);219static const OSSL_PARAM *kdf_argon2_settable_ctx_params(ossl_unused void *ctx,220ossl_unused void *p_ctx);221static const OSSL_PARAM *kdf_argon2_gettable_ctx_params(ossl_unused void *ctx,222ossl_unused void *p_ctx);223224static ossl_inline uint64_t load64(const uint8_t *src);225static ossl_inline void store32(uint8_t *dst, uint32_t w);226static ossl_inline void store64(uint8_t *dst, uint64_t w);227static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c);228static ossl_inline uint64_t mul_lower(uint64_t x, uint64_t y);229230static void init_block_value(BLOCK *b, uint8_t in);231static void copy_block(BLOCK *dst, const BLOCK *src);232static void xor_block(BLOCK *dst, const BLOCK *src);233static void load_block(BLOCK *dst, const void *input);234static void store_block(void *output, const BLOCK *src);235static void fill_first_blocks(uint8_t *blockhash, const KDF_ARGON2 *ctx);236static void fill_block(const BLOCK *prev, const BLOCK *ref, BLOCK *next,237int with_xor);238239static void next_addresses(BLOCK *address_block, BLOCK *input_block,240const BLOCK *zero_block);241static int data_indep_addressing(const KDF_ARGON2 *ctx, uint32_t pass,242uint8_t slice);243static uint32_t index_alpha(const KDF_ARGON2 *ctx, uint32_t pass,244uint8_t slice, uint32_t index,245uint32_t pseudo_rand, int same_lane);246247static void fill_segment(const KDF_ARGON2 *ctx, uint32_t pass, uint32_t lane,248uint8_t slice);249250# if !defined(ARGON2_NO_THREADS)251static uint32_t fill_segment_thr(void *thread_data);252static int fill_mem_blocks_mt(KDF_ARGON2 *ctx);253# endif254255static int fill_mem_blocks_st(KDF_ARGON2 *ctx);256static ossl_inline int fill_memory_blocks(KDF_ARGON2 *ctx);257258static void initial_hash(uint8_t *blockhash, KDF_ARGON2 *ctx);259static int initialize(KDF_ARGON2 *ctx);260static void finalize(const KDF_ARGON2 *ctx, void *out);261262static int blake2b(EVP_MD *md, EVP_MAC *mac, void *out, size_t outlen,263const void *in, size_t inlen, const void *key,264size_t keylen);265static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,266size_t outlen, const void *in, size_t inlen);267268static ossl_inline uint64_t load64(const uint8_t *src)269{270return271(((uint64_t)src[0]) << 0)272| (((uint64_t)src[1]) << 8)273| (((uint64_t)src[2]) << 16)274| (((uint64_t)src[3]) << 24)275| (((uint64_t)src[4]) << 32)276| (((uint64_t)src[5]) << 40)277| (((uint64_t)src[6]) << 48)278| (((uint64_t)src[7]) << 56);279}280281static ossl_inline void store32(uint8_t *dst, uint32_t w)282{283dst[0] = (uint8_t)(w >> 0);284dst[1] = (uint8_t)(w >> 8);285dst[2] = (uint8_t)(w >> 16);286dst[3] = (uint8_t)(w >> 24);287}288289static ossl_inline void store64(uint8_t *dst, uint64_t w)290{291dst[0] = (uint8_t)(w >> 0);292dst[1] = (uint8_t)(w >> 8);293dst[2] = (uint8_t)(w >> 16);294dst[3] = (uint8_t)(w >> 24);295dst[4] = (uint8_t)(w >> 32);296dst[5] = (uint8_t)(w >> 40);297dst[6] = (uint8_t)(w >> 48);298dst[7] = (uint8_t)(w >> 56);299}300301static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c)302{303return (w >> c) | (w << (64 - c));304}305306static ossl_inline uint64_t mul_lower(uint64_t x, uint64_t y)307{308const uint64_t m = 0xFFFFFFFFUL;309return (x & m) * (y & m);310}311312static void init_block_value(BLOCK *b, uint8_t in)313{314memset(b->v, in, sizeof(b->v));315}316317static void copy_block(BLOCK *dst, const BLOCK *src)318{319memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);320}321322static void xor_block(BLOCK *dst, const BLOCK *src)323{324int i;325326for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)327dst->v[i] ^= src->v[i];328}329330static void load_block(BLOCK *dst, const void *input)331{332unsigned i;333334for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)335dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));336}337338static void store_block(void *output, const BLOCK *src)339{340unsigned i;341342for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)343store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);344}345346static void fill_first_blocks(uint8_t *blockhash, const KDF_ARGON2 *ctx)347{348uint32_t l;349uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];350351/*352* Make the first and second block in each lane as G(H0||0||i)353* or G(H0||1||i).354*/355for (l = 0; l < ctx->lanes; ++l) {356store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);357store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);358blake2b_long(ctx->md, ctx->mac, blockhash_bytes, ARGON2_BLOCK_SIZE,359blockhash, ARGON2_PREHASH_SEED_LENGTH);360load_block(&ctx->memory[l * ctx->lane_length + 0],361blockhash_bytes);362store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);363blake2b_long(ctx->md, ctx->mac, blockhash_bytes, ARGON2_BLOCK_SIZE,364blockhash, ARGON2_PREHASH_SEED_LENGTH);365load_block(&ctx->memory[l * ctx->lane_length + 1],366blockhash_bytes);367}368OPENSSL_cleanse(blockhash_bytes, ARGON2_BLOCK_SIZE);369}370371static void fill_block(const BLOCK *prev, const BLOCK *ref,372BLOCK *next, int with_xor)373{374BLOCK blockR, tmp;375unsigned i;376377copy_block(&blockR, ref);378xor_block(&blockR, prev);379copy_block(&tmp, &blockR);380381if (with_xor)382xor_block(&tmp, next);383384for (i = 0; i < 8; ++i)385PERMUTATION_P_COLUMN(blockR.v, i);386387for (i = 0; i < 8; ++i)388PERMUTATION_P_ROW(blockR.v, i);389390copy_block(next, &tmp);391xor_block(next, &blockR);392}393394static void next_addresses(BLOCK *address_block, BLOCK *input_block,395const BLOCK *zero_block)396{397input_block->v[6]++;398fill_block(zero_block, input_block, address_block, 0);399fill_block(zero_block, address_block, address_block, 0);400}401402static int data_indep_addressing(const KDF_ARGON2 *ctx, uint32_t pass,403uint8_t slice)404{405switch (ctx->type) {406case ARGON2_I:407return 1;408case ARGON2_ID:409return (pass == 0) && (slice < ARGON2_SYNC_POINTS / 2);410case ARGON2_D:411default:412return 0;413}414}415416/*417* Pass 0 (pass = 0):418* This lane: all already finished segments plus already constructed blocks419* in this segment420* Other lanes: all already finished segments421*422* Pass 1+:423* This lane: (SYNC_POINTS - 1) last segments plus already constructed424* blocks in this segment425* Other lanes: (SYNC_POINTS - 1) last segments426*/427static uint32_t index_alpha(const KDF_ARGON2 *ctx, uint32_t pass,428uint8_t slice, uint32_t index,429uint32_t pseudo_rand, int same_lane)430{431uint32_t ref_area_sz;432uint64_t rel_pos;433uint32_t start_pos, abs_pos;434435start_pos = 0;436switch (pass) {437case 0:438if (slice == 0)439ref_area_sz = index - 1;440else if (same_lane)441ref_area_sz = slice * ctx->segment_length + index - 1;442else443ref_area_sz = slice * ctx->segment_length +444((index == 0) ? (-1) : 0);445break;446default:447if (same_lane)448ref_area_sz = ctx->lane_length - ctx->segment_length + index - 1;449else450ref_area_sz = ctx->lane_length - ctx->segment_length +451((index == 0) ? (-1) : 0);452if (slice != ARGON2_SYNC_POINTS - 1)453start_pos = (slice + 1) * ctx->segment_length;454break;455}456457rel_pos = pseudo_rand;458rel_pos = rel_pos * rel_pos >> 32;459rel_pos = ref_area_sz - 1 - (ref_area_sz * rel_pos >> 32);460abs_pos = (start_pos + rel_pos) % ctx->lane_length;461462return abs_pos;463}464465static void fill_segment(const KDF_ARGON2 *ctx, uint32_t pass, uint32_t lane,466uint8_t slice)467{468BLOCK *ref_block = NULL, *curr_block = NULL;469BLOCK address_block, input_block, zero_block;470uint64_t rnd, ref_index, ref_lane;471uint32_t prev_offset;472uint32_t start_idx;473uint32_t j;474uint32_t curr_offset; /* Offset of the current block */475476memset(&input_block, 0, sizeof(BLOCK));477478if (ctx == NULL)479return;480481if (data_indep_addressing(ctx, pass, slice)) {482init_block_value(&zero_block, 0);483init_block_value(&input_block, 0);484485input_block.v[0] = pass;486input_block.v[1] = lane;487input_block.v[2] = slice;488input_block.v[3] = ctx->memory_blocks;489input_block.v[4] = ctx->passes;490input_block.v[5] = ctx->type;491}492493start_idx = 0;494495/* We've generated the first two blocks. Generate the 1st block of addrs. */496if ((pass == 0) && (slice == 0)) {497start_idx = 2;498if (data_indep_addressing(ctx, pass, slice))499next_addresses(&address_block, &input_block, &zero_block);500}501502curr_offset = lane * ctx->lane_length + slice * ctx->segment_length503+ start_idx;504505if ((curr_offset % ctx->lane_length) == 0)506prev_offset = curr_offset + ctx->lane_length - 1;507else508prev_offset = curr_offset - 1;509510for (j = start_idx; j < ctx->segment_length; ++j, ++curr_offset, ++prev_offset) {511if (curr_offset % ctx->lane_length == 1)512prev_offset = curr_offset - 1;513514/* Taking pseudo-random value from the previous block. */515if (data_indep_addressing(ctx, pass, slice)) {516if (j % ARGON2_ADDRESSES_IN_BLOCK == 0)517next_addresses(&address_block, &input_block, &zero_block);518rnd = address_block.v[j % ARGON2_ADDRESSES_IN_BLOCK];519} else {520rnd = ctx->memory[prev_offset].v[0];521}522523/* Computing the lane of the reference block */524ref_lane = ((rnd >> 32)) % ctx->lanes;525/* Can not reference other lanes yet */526if ((pass == 0) && (slice == 0))527ref_lane = lane;528529/* Computing the number of possible reference block within the lane. */530ref_index = index_alpha(ctx, pass, slice, j, rnd & 0xFFFFFFFF,531ref_lane == lane);532533/* Creating a new block */534ref_block = ctx->memory + ctx->lane_length * ref_lane + ref_index;535curr_block = ctx->memory + curr_offset;536if (ARGON2_VERSION_10 == ctx->version) {537/* Version 1.2.1 and earlier: overwrite, not XOR */538fill_block(ctx->memory + prev_offset, ref_block, curr_block, 0);539continue;540}541542fill_block(ctx->memory + prev_offset, ref_block, curr_block,543pass == 0 ? 0 : 1);544}545}546547# if !defined(ARGON2_NO_THREADS)548549static uint32_t fill_segment_thr(void *thread_data)550{551ARGON2_THREAD_DATA *my_data;552553my_data = (ARGON2_THREAD_DATA *) thread_data;554fill_segment(my_data->ctx, my_data->pos.pass, my_data->pos.lane,555my_data->pos.slice);556557return 0;558}559560static int fill_mem_blocks_mt(KDF_ARGON2 *ctx)561{562uint32_t r, s, l, ll;563void **t;564ARGON2_THREAD_DATA *t_data;565566t = OPENSSL_zalloc(sizeof(void *)*ctx->lanes);567t_data = OPENSSL_zalloc(ctx->lanes * sizeof(ARGON2_THREAD_DATA));568569if (t == NULL || t_data == NULL)570goto fail;571572for (r = 0; r < ctx->passes; ++r) {573for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {574for (l = 0; l < ctx->lanes; ++l) {575ARGON2_POS p;576if (l >= ctx->threads) {577if (ossl_crypto_thread_join(t[l - ctx->threads], NULL) == 0)578goto fail;579if (ossl_crypto_thread_clean(t[l - ctx->threads]) == 0)580goto fail;581t[l] = NULL;582}583584p.pass = r;585p.lane = l;586p.slice = (uint8_t)s;587p.index = 0;588589t_data[l].ctx = ctx;590memcpy(&(t_data[l].pos), &p, sizeof(ARGON2_POS));591t[l] = ossl_crypto_thread_start(ctx->libctx, &fill_segment_thr,592(void *) &t_data[l]);593if (t[l] == NULL) {594for (ll = 0; ll < l; ++ll) {595if (ossl_crypto_thread_join(t[ll], NULL) == 0)596goto fail;597if (ossl_crypto_thread_clean(t[ll]) == 0)598goto fail;599t[ll] = NULL;600}601goto fail;602}603}604for (l = ctx->lanes - ctx->threads; l < ctx->lanes; ++l) {605if (ossl_crypto_thread_join(t[l], NULL) == 0)606goto fail;607if (ossl_crypto_thread_clean(t[l]) == 0)608goto fail;609t[l] = NULL;610}611}612}613614OPENSSL_free(t_data);615OPENSSL_free(t);616617return 1;618619fail:620if (t_data != NULL)621OPENSSL_free(t_data);622if (t != NULL)623OPENSSL_free(t);624return 0;625}626627# endif /* !defined(ARGON2_NO_THREADS) */628629static int fill_mem_blocks_st(KDF_ARGON2 *ctx)630{631uint32_t r, s, l;632633for (r = 0; r < ctx->passes; ++r)634for (s = 0; s < ARGON2_SYNC_POINTS; ++s)635for (l = 0; l < ctx->lanes; ++l)636fill_segment(ctx, r, l, s);637return 1;638}639640static ossl_inline int fill_memory_blocks(KDF_ARGON2 *ctx)641{642# if !defined(ARGON2_NO_THREADS)643return ctx->threads == 1 ? fill_mem_blocks_st(ctx) : fill_mem_blocks_mt(ctx);644# else645return ctx->threads == 1 ? fill_mem_blocks_st(ctx) : 0;646# endif647}648649static void initial_hash(uint8_t *blockhash, KDF_ARGON2 *ctx)650{651EVP_MD_CTX *mdctx;652uint8_t value[sizeof(uint32_t)];653unsigned int tmp;654uint32_t args[7];655656if (ctx == NULL || blockhash == NULL)657return;658659args[0] = ctx->lanes;660args[1] = ctx->outlen;661args[2] = ctx->m_cost;662args[3] = ctx->t_cost;663args[4] = ctx->version;664args[5] = (uint32_t) ctx->type;665args[6] = ctx->pwdlen;666667mdctx = EVP_MD_CTX_create();668if (mdctx == NULL || EVP_DigestInit_ex(mdctx, ctx->md, NULL) != 1)669goto fail;670671for (tmp = 0; tmp < sizeof(args) / sizeof(uint32_t); ++tmp) {672store32((uint8_t *) &value, args[tmp]);673if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)674goto fail;675}676677if (ctx->pwd != NULL) {678if (EVP_DigestUpdate(mdctx, ctx->pwd, ctx->pwdlen) != 1)679goto fail;680if (ctx->early_clean) {681OPENSSL_cleanse(ctx->pwd, ctx->pwdlen);682ctx->pwdlen = 0;683}684}685686store32((uint8_t *) &value, ctx->saltlen);687688if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)689goto fail;690691if (ctx->salt != NULL)692if (EVP_DigestUpdate(mdctx, ctx->salt, ctx->saltlen) != 1)693goto fail;694695store32((uint8_t *) &value, ctx->secretlen);696if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)697goto fail;698699if (ctx->secret != NULL) {700if (EVP_DigestUpdate(mdctx, ctx->secret, ctx->secretlen) != 1)701goto fail;702if (ctx->early_clean) {703OPENSSL_cleanse(ctx->secret, ctx->secretlen);704ctx->secretlen = 0;705}706}707708store32((uint8_t *) &value, ctx->adlen);709if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)710goto fail;711712if (ctx->ad != NULL)713if (EVP_DigestUpdate(mdctx, ctx->ad, ctx->adlen) != 1)714goto fail;715716tmp = ARGON2_PREHASH_DIGEST_LENGTH;717if (EVP_DigestFinal_ex(mdctx, blockhash, &tmp) != 1)718goto fail;719720fail:721EVP_MD_CTX_destroy(mdctx);722}723724static int initialize(KDF_ARGON2 *ctx)725{726uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];727728if (ctx == NULL)729return 0;730731if (ctx->memory_blocks * sizeof(BLOCK) / sizeof(BLOCK) != ctx->memory_blocks)732return 0;733734if (ctx->type != ARGON2_D)735ctx->memory = OPENSSL_secure_zalloc(ctx->memory_blocks *736sizeof(BLOCK));737else738ctx->memory = OPENSSL_zalloc(ctx->memory_blocks *739sizeof(BLOCK));740741if (ctx->memory == NULL) {742ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE,743"cannot allocate required memory");744return 0;745}746747initial_hash(blockhash, ctx);748OPENSSL_cleanse(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,749ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);750fill_first_blocks(blockhash, ctx);751OPENSSL_cleanse(blockhash, ARGON2_PREHASH_SEED_LENGTH);752753return 1;754}755756static void finalize(const KDF_ARGON2 *ctx, void *out)757{758BLOCK blockhash;759uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];760uint32_t last_block_in_lane;761uint32_t l;762763if (ctx == NULL)764return;765766copy_block(&blockhash, ctx->memory + ctx->lane_length - 1);767768/* XOR the last blocks */769for (l = 1; l < ctx->lanes; ++l) {770last_block_in_lane = l * ctx->lane_length + (ctx->lane_length - 1);771xor_block(&blockhash, ctx->memory + last_block_in_lane);772}773774/* Hash the result */775store_block(blockhash_bytes, &blockhash);776blake2b_long(ctx->md, ctx->mac, out, ctx->outlen, blockhash_bytes,777ARGON2_BLOCK_SIZE);778OPENSSL_cleanse(blockhash.v, ARGON2_BLOCK_SIZE);779OPENSSL_cleanse(blockhash_bytes, ARGON2_BLOCK_SIZE);780781if (ctx->type != ARGON2_D)782OPENSSL_secure_clear_free(ctx->memory,783ctx->memory_blocks * sizeof(BLOCK));784else785OPENSSL_clear_free(ctx->memory,786ctx->memory_blocks * sizeof(BLOCK));787}788789static int blake2b_mac(EVP_MAC *mac, void *out, size_t outlen, const void *in,790size_t inlen, const void *key, size_t keylen)791{792int ret = 0;793size_t par_n = 0, out_written;794EVP_MAC_CTX *ctx = NULL;795OSSL_PARAM par[3];796797if ((ctx = EVP_MAC_CTX_new(mac)) == NULL)798goto fail;799800par[par_n++] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,801(void *) key, keylen);802par[par_n++] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &outlen);803par[par_n++] = OSSL_PARAM_construct_end();804805ret = EVP_MAC_CTX_set_params(ctx, par) == 1806&& EVP_MAC_init(ctx, NULL, 0, NULL) == 1807&& EVP_MAC_update(ctx, in, inlen) == 1808&& EVP_MAC_final(ctx, out, (size_t *) &out_written, outlen) == 1;809810fail:811EVP_MAC_CTX_free(ctx);812return ret;813}814815static int blake2b_md(EVP_MD *md, void *out, size_t outlen, const void *in,816size_t inlen)817{818int ret = 0;819EVP_MD_CTX *ctx = NULL;820OSSL_PARAM par[2];821822if ((ctx = EVP_MD_CTX_create()) == NULL)823return 0;824825par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen);826par[1] = OSSL_PARAM_construct_end();827828ret = EVP_DigestInit_ex2(ctx, md, par) == 1829&& EVP_DigestUpdate(ctx, in, inlen) == 1830&& EVP_DigestFinal_ex(ctx, out, NULL) == 1;831832EVP_MD_CTX_free(ctx);833return ret;834}835836static int blake2b(EVP_MD *md, EVP_MAC *mac, void *out, size_t outlen,837const void *in, size_t inlen, const void *key, size_t keylen)838{839if (out == NULL || outlen == 0)840return 0;841842if (key == NULL || keylen == 0)843return blake2b_md(md, out, outlen, in, inlen);844845return blake2b_mac(mac, out, outlen, in, inlen, key, keylen);846}847848static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,849size_t outlen, const void *in, size_t inlen)850{851int ret = 0;852EVP_MD_CTX *ctx = NULL;853uint32_t outlen_curr;854uint8_t outbuf[BLAKE2B_OUTBYTES];855uint8_t inbuf[BLAKE2B_OUTBYTES];856uint8_t outlen_bytes[sizeof(uint32_t)] = {0};857OSSL_PARAM par[2];858size_t outlen_md;859860if (out == NULL || outlen == 0)861return 0;862863/* Ensure little-endian byte order */864store32(outlen_bytes, (uint32_t)outlen);865866if ((ctx = EVP_MD_CTX_create()) == NULL)867return 0;868869outlen_md = (outlen <= BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES;870par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen_md);871par[1] = OSSL_PARAM_construct_end();872873ret = EVP_DigestInit_ex2(ctx, md, par) == 1874&& EVP_DigestUpdate(ctx, outlen_bytes, sizeof(outlen_bytes)) == 1875&& EVP_DigestUpdate(ctx, in, inlen) == 1876&& EVP_DigestFinal_ex(ctx, (outlen > BLAKE2B_OUTBYTES) ? outbuf : out,877NULL) == 1;878879if (ret == 0)880goto fail;881882if (outlen > BLAKE2B_OUTBYTES) {883memcpy(out, outbuf, BLAKE2B_OUTBYTES / 2);884out += BLAKE2B_OUTBYTES / 2;885outlen_curr = (uint32_t) outlen - BLAKE2B_OUTBYTES / 2;886887while (outlen_curr > BLAKE2B_OUTBYTES) {888memcpy(inbuf, outbuf, BLAKE2B_OUTBYTES);889if (blake2b(md, mac, outbuf, BLAKE2B_OUTBYTES, inbuf,890BLAKE2B_OUTBYTES, NULL, 0) != 1)891goto fail;892memcpy(out, outbuf, BLAKE2B_OUTBYTES / 2);893out += BLAKE2B_OUTBYTES / 2;894outlen_curr -= BLAKE2B_OUTBYTES / 2;895}896897memcpy(inbuf, outbuf, BLAKE2B_OUTBYTES);898if (blake2b(md, mac, outbuf, outlen_curr, inbuf, BLAKE2B_OUTBYTES,899NULL, 0) != 1)900goto fail;901memcpy(out, outbuf, outlen_curr);902}903ret = 1;904905fail:906EVP_MD_CTX_free(ctx);907return ret;908}909910static void kdf_argon2_init(KDF_ARGON2 *c, ARGON2_TYPE type)911{912OSSL_LIB_CTX *libctx;913914libctx = c->libctx;915memset(c, 0, sizeof(*c));916917c->libctx = libctx;918c->outlen = ARGON2_DEFAULT_OUTLEN;919c->t_cost = ARGON2_DEFAULT_T_COST;920c->m_cost = ARGON2_DEFAULT_M_COST;921c->lanes = ARGON2_DEFAULT_LANES;922c->threads = ARGON2_DEFAULT_THREADS;923c->version = ARGON2_DEFAULT_VERSION;924c->type = type;925}926927static void *kdf_argon2d_new(void *provctx)928{929KDF_ARGON2 *ctx;930931if (!ossl_prov_is_running())932return NULL;933934ctx = OPENSSL_zalloc(sizeof(*ctx));935if (ctx == NULL) {936ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);937return NULL;938}939940ctx->libctx = PROV_LIBCTX_OF(provctx);941942kdf_argon2_init(ctx, ARGON2_D);943return ctx;944}945946static void *kdf_argon2i_new(void *provctx)947{948KDF_ARGON2 *ctx;949950if (!ossl_prov_is_running())951return NULL;952953ctx = OPENSSL_zalloc(sizeof(*ctx));954if (ctx == NULL) {955ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);956return NULL;957}958959ctx->libctx = PROV_LIBCTX_OF(provctx);960961kdf_argon2_init(ctx, ARGON2_I);962return ctx;963}964965static void *kdf_argon2id_new(void *provctx)966{967KDF_ARGON2 *ctx;968969if (!ossl_prov_is_running())970return NULL;971972ctx = OPENSSL_zalloc(sizeof(*ctx));973if (ctx == NULL) {974ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);975return NULL;976}977978ctx->libctx = PROV_LIBCTX_OF(provctx);979980kdf_argon2_init(ctx, ARGON2_ID);981return ctx;982}983984static void kdf_argon2_free(void *vctx)985{986KDF_ARGON2 *ctx = (KDF_ARGON2 *)vctx;987988if (ctx == NULL)989return;990991if (ctx->pwd != NULL)992OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);993994if (ctx->salt != NULL)995OPENSSL_clear_free(ctx->salt, ctx->saltlen);996997if (ctx->secret != NULL)998OPENSSL_clear_free(ctx->secret, ctx->secretlen);9991000if (ctx->ad != NULL)1001OPENSSL_clear_free(ctx->ad, ctx->adlen);10021003EVP_MD_free(ctx->md);1004EVP_MAC_free(ctx->mac);10051006OPENSSL_free(ctx->propq);10071008memset(ctx, 0, sizeof(*ctx));10091010OPENSSL_free(ctx);1011}10121013static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,1014const OSSL_PARAM params[])1015{1016KDF_ARGON2 *ctx;1017uint32_t memory_blocks, segment_length;10181019ctx = (KDF_ARGON2 *)vctx;10201021if (!ossl_prov_is_running() || !kdf_argon2_set_ctx_params(vctx, params))1022return 0;10231024if (ctx->mac == NULL)1025ctx->mac = EVP_MAC_fetch(ctx->libctx, "blake2bmac", ctx->propq);1026if (ctx->mac == NULL) {1027ERR_raise_data(ERR_LIB_PROV, PROV_R_MISSING_MAC,1028"cannot fetch blake2bmac");1029return 0;1030}10311032if (ctx->md == NULL)1033ctx->md = EVP_MD_fetch(ctx->libctx, "blake2b512", ctx->propq);1034if (ctx->md == NULL) {1035ERR_raise_data(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST,1036"cannot fetch blake2b512");1037return 0;1038}10391040if (ctx->salt == NULL || ctx->saltlen == 0) {1041ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);1042return 0;1043}10441045if (outlen != ctx->outlen) {1046if (OSSL_PARAM_locate((OSSL_PARAM *)params, "size") != NULL) {1047ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);1048return 0;1049}1050if (!kdf_argon2_ctx_set_out_length(ctx, (uint32_t) outlen))1051return 0;1052}10531054switch (ctx->type) {1055case ARGON2_D:1056case ARGON2_I:1057case ARGON2_ID:1058break;1059default:1060ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MODE, "invalid Argon2 type");1061return 0;1062}10631064if (ctx->threads > 1) {1065# ifdef ARGON2_NO_THREADS1066ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1067"requested %u threads, single-threaded mode supported only",1068ctx->threads);1069return 0;1070# else1071if (ctx->threads > ossl_get_avail_threads(ctx->libctx)) {1072ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1073"requested %u threads, available: %u",1074ctx->threads, ossl_get_avail_threads(ctx->libctx));1075return 0;1076}1077# endif1078if (ctx->threads > ctx->lanes) {1079ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1080"requested more threads (%u) than lanes (%u)",1081ctx->threads, ctx->lanes);1082return 0;1083}1084}10851086if (ctx->m_cost < 8 * ctx->lanes) {1087ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE,1088"m_cost must be greater or equal than 8 times the number of lanes");1089return 0;1090}10911092memory_blocks = ctx->m_cost;1093if (memory_blocks < 2 * ARGON2_SYNC_POINTS * ctx->lanes)1094memory_blocks = 2 * ARGON2_SYNC_POINTS * ctx->lanes;10951096/* Ensure that all segments have equal length */1097segment_length = memory_blocks / (ctx->lanes * ARGON2_SYNC_POINTS);1098memory_blocks = segment_length * (ctx->lanes * ARGON2_SYNC_POINTS);10991100ctx->memory = NULL;1101ctx->memory_blocks = memory_blocks;1102ctx->segment_length = segment_length;1103ctx->passes = ctx->t_cost;1104ctx->lane_length = segment_length * ARGON2_SYNC_POINTS;11051106if (initialize(ctx) != 1)1107return 0;11081109if (fill_memory_blocks(ctx) != 1)1110return 0;11111112finalize(ctx, out);11131114return 1;1115}11161117static void kdf_argon2_reset(void *vctx)1118{1119OSSL_LIB_CTX *libctx;1120KDF_ARGON2 *ctx;1121ARGON2_TYPE type;11221123ctx = (KDF_ARGON2 *) vctx;1124type = ctx->type;1125libctx = ctx->libctx;11261127EVP_MD_free(ctx->md);1128EVP_MAC_free(ctx->mac);11291130OPENSSL_free(ctx->propq);11311132if (ctx->pwd != NULL)1133OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);11341135if (ctx->salt != NULL)1136OPENSSL_clear_free(ctx->salt, ctx->saltlen);11371138if (ctx->secret != NULL)1139OPENSSL_clear_free(ctx->secret, ctx->secretlen);11401141if (ctx->ad != NULL)1142OPENSSL_clear_free(ctx->ad, ctx->adlen);11431144memset(ctx, 0, sizeof(*ctx));1145ctx->libctx = libctx;1146kdf_argon2_init(ctx, type);1147}11481149static int kdf_argon2_ctx_set_threads(KDF_ARGON2 *ctx, uint32_t threads)1150{1151if (threads < ARGON2_MIN_THREADS) {1152ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1153"min threads: %u", ARGON2_MIN_THREADS);1154return 0;1155}11561157if (threads > ARGON2_MAX_THREADS) {1158ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1159"max threads: %u", ARGON2_MAX_THREADS);1160return 0;1161}11621163ctx->threads = threads;1164return 1;1165}11661167static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes)1168{1169if (lanes > ARGON2_MAX_LANES) {1170ERR_raise_data(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER,1171"max lanes: %u", ARGON2_MAX_LANES);1172return 0;1173}11741175if (lanes < ARGON2_MIN_LANES) {1176ERR_raise_data(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER,1177"min lanes: %u", ARGON2_MIN_LANES);1178return 0;1179}11801181ctx->lanes = lanes;1182return 1;1183}11841185static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost)1186{1187/* ARGON2_MAX_MEMORY == max m_cost value, so skip check */11881189if (t_cost < ARGON2_MIN_TIME) {1190ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT,1191"min: %u", ARGON2_MIN_TIME);1192return 0;1193}11941195ctx->t_cost = t_cost;1196return 1;1197}11981199static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost)1200{1201/* ARGON2_MAX_MEMORY == max m_cost value, so skip check */12021203if (m_cost < ARGON2_MIN_MEMORY) {1204ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE, "min: %u",1205ARGON2_MIN_MEMORY);1206return 0;1207}12081209ctx->m_cost = m_cost;1210return 1;1211}12121213static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen)1214{1215/*1216* ARGON2_MAX_OUT_LENGTH == max outlen value, so upper bounds checks1217* are always satisfied; to suppress compiler if statement tautology1218* warnings, these checks are skipped.1219*/12201221if (outlen < ARGON2_MIN_OUT_LENGTH) {1222ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH, "min: %u",1223ARGON2_MIN_OUT_LENGTH);1224return 0;1225}12261227ctx->outlen = outlen;1228return 1;1229}12301231static int kdf_argon2_ctx_set_secret(KDF_ARGON2 *ctx, const OSSL_PARAM *p)1232{1233size_t buflen;12341235if (p->data == NULL)1236return 0;12371238if (ctx->secret != NULL) {1239OPENSSL_clear_free(ctx->secret, ctx->secretlen);1240ctx->secret = NULL;1241ctx->secretlen = 0U;1242}12431244if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->secret, 0, &buflen))1245return 0;12461247if (buflen > ARGON2_MAX_SECRET) {1248OPENSSL_free(ctx->secret);1249ctx->secret = NULL;1250ctx->secretlen = 0U;1251return 0;1252}12531254ctx->secretlen = (uint32_t) buflen;1255return 1;1256}12571258static int kdf_argon2_ctx_set_pwd(KDF_ARGON2 *ctx, const OSSL_PARAM *p)1259{1260size_t buflen;12611262if (p->data == NULL)1263return 0;12641265if (ctx->pwd != NULL) {1266OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);1267ctx->pwd = NULL;1268ctx->pwdlen = 0U;1269}12701271if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pwd, 0, &buflen))1272return 0;12731274if (buflen > ARGON2_MAX_PWD_LENGTH) {1275ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "max: %u",1276ARGON2_MAX_PWD_LENGTH);1277goto fail;1278}12791280ctx->pwdlen = (uint32_t) buflen;1281return 1;12821283fail:1284OPENSSL_free(ctx->pwd);1285ctx->pwd = NULL;1286ctx->pwdlen = 0U;1287return 0;1288}12891290static int kdf_argon2_ctx_set_salt(KDF_ARGON2 *ctx, const OSSL_PARAM *p)1291{1292size_t buflen;12931294if (p->data == NULL)1295return 0;12961297if (ctx->salt != NULL) {1298OPENSSL_clear_free(ctx->salt, ctx->saltlen);1299ctx->salt = NULL;1300ctx->saltlen = 0U;1301}13021303if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0, &buflen))1304return 0;13051306if (buflen < ARGON2_MIN_SALT_LENGTH) {1307ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "min: %u",1308ARGON2_MIN_SALT_LENGTH);1309goto fail;1310}13111312if (buflen > ARGON2_MAX_SALT_LENGTH) {1313ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "max: %u",1314ARGON2_MAX_SALT_LENGTH);1315goto fail;1316}13171318ctx->saltlen = (uint32_t) buflen;1319return 1;13201321fail:1322OPENSSL_free(ctx->salt);1323ctx->salt = NULL;1324ctx->saltlen = 0U;1325return 0;1326}13271328static int kdf_argon2_ctx_set_ad(KDF_ARGON2 *ctx, const OSSL_PARAM *p)1329{1330size_t buflen;13311332if (p->data == NULL)1333return 0;13341335if (ctx->ad != NULL) {1336OPENSSL_clear_free(ctx->ad, ctx->adlen);1337ctx->ad = NULL;1338ctx->adlen = 0U;1339}13401341if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->ad, 0, &buflen))1342return 0;13431344if (buflen > ARGON2_MAX_AD_LENGTH) {1345OPENSSL_free(ctx->ad);1346ctx->ad = NULL;1347ctx->adlen = 0U;1348return 0;1349}13501351ctx->adlen = (uint32_t) buflen;1352return 1;1353}13541355static void kdf_argon2_ctx_set_flag_early_clean(KDF_ARGON2 *ctx, uint32_t f)1356{1357ctx->early_clean = !!(f);1358}13591360static int kdf_argon2_ctx_set_version(KDF_ARGON2 *ctx, uint32_t version)1361{1362switch (version) {1363case ARGON2_VERSION_10:1364case ARGON2_VERSION_13:1365ctx->version = version;1366return 1;1367default:1368ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MODE,1369"invalid Argon2 version");1370return 0;1371}1372}13731374static int set_property_query(KDF_ARGON2 *ctx, const char *propq)1375{1376OPENSSL_free(ctx->propq);1377ctx->propq = NULL;1378if (propq != NULL) {1379ctx->propq = OPENSSL_strdup(propq);1380if (ctx->propq == NULL)1381return 0;1382}1383EVP_MD_free(ctx->md);1384ctx->md = NULL;1385EVP_MAC_free(ctx->mac);1386ctx->mac = NULL;1387return 1;1388}13891390static int kdf_argon2_set_ctx_params(void *vctx, const OSSL_PARAM params[])1391{1392const OSSL_PARAM *p;1393KDF_ARGON2 *ctx;1394uint32_t u32_value;13951396if (ossl_param_is_empty(params))1397return 1;13981399ctx = (KDF_ARGON2 *) vctx;1400if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)1401if (!kdf_argon2_ctx_set_pwd(ctx, p))1402return 0;14031404if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)1405if (!kdf_argon2_ctx_set_salt(ctx, p))1406return 0;14071408if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL)1409if (!kdf_argon2_ctx_set_secret(ctx, p))1410return 0;14111412if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_AD)) != NULL)1413if (!kdf_argon2_ctx_set_ad(ctx, p))1414return 0;14151416if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SIZE)) != NULL) {1417if (!OSSL_PARAM_get_uint32(p, &u32_value))1418return 0;1419if (!kdf_argon2_ctx_set_out_length(ctx, u32_value))1420return 0;1421}14221423if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL) {1424if (!OSSL_PARAM_get_uint32(p, &u32_value))1425return 0;1426if (!kdf_argon2_ctx_set_t_cost(ctx, u32_value))1427return 0;1428}14291430if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_THREADS)) != NULL) {1431if (!OSSL_PARAM_get_uint32(p, &u32_value))1432return 0;1433if (!kdf_argon2_ctx_set_threads(ctx, u32_value))1434return 0;1435}14361437if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_LANES)) != NULL) {1438if (!OSSL_PARAM_get_uint32(p, &u32_value))1439return 0;1440if (!kdf_argon2_ctx_set_lanes(ctx, u32_value))1441return 0;1442}14431444if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_MEMCOST)) != NULL) {1445if (!OSSL_PARAM_get_uint32(p, &u32_value))1446return 0;1447if (!kdf_argon2_ctx_set_m_cost(ctx, u32_value))1448return 0;1449}14501451if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_EARLY_CLEAN)) != NULL) {1452if (!OSSL_PARAM_get_uint32(p, &u32_value))1453return 0;1454kdf_argon2_ctx_set_flag_early_clean(ctx, u32_value);1455}14561457if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_VERSION)) != NULL) {1458if (!OSSL_PARAM_get_uint32(p, &u32_value))1459return 0;1460if (!kdf_argon2_ctx_set_version(ctx, u32_value))1461return 0;1462}14631464if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES)) != NULL) {1465if (p->data_type != OSSL_PARAM_UTF8_STRING1466|| !set_property_query(ctx, p->data))1467return 0;1468}14691470return 1;1471}14721473static const OSSL_PARAM *kdf_argon2_settable_ctx_params(ossl_unused void *ctx,1474ossl_unused void *p_ctx)1475{1476static const OSSL_PARAM known_settable_ctx_params[] = {1477OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),1478OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),1479OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),1480OSSL_PARAM_octet_string(OSSL_KDF_PARAM_ARGON2_AD, NULL, 0),1481OSSL_PARAM_uint32(OSSL_KDF_PARAM_SIZE, NULL),1482OSSL_PARAM_uint32(OSSL_KDF_PARAM_ITER, NULL),1483OSSL_PARAM_uint32(OSSL_KDF_PARAM_THREADS, NULL),1484OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_LANES, NULL),1485OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, NULL),1486OSSL_PARAM_uint32(OSSL_KDF_PARAM_EARLY_CLEAN, NULL),1487OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_VERSION, NULL),1488OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),1489OSSL_PARAM_END1490};14911492return known_settable_ctx_params;1493}14941495static int kdf_argon2_get_ctx_params(void *vctx, OSSL_PARAM params[])1496{1497OSSL_PARAM *p;14981499(void) vctx;1500if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)1501return OSSL_PARAM_set_size_t(p, SIZE_MAX);15021503return -2;1504}15051506static const OSSL_PARAM *kdf_argon2_gettable_ctx_params(ossl_unused void *ctx,1507ossl_unused void *p_ctx)1508{1509static const OSSL_PARAM known_gettable_ctx_params[] = {1510OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),1511OSSL_PARAM_END1512};15131514return known_gettable_ctx_params;1515}15161517const OSSL_DISPATCH ossl_kdf_argon2i_functions[] = {1518{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2i_new },1519{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },1520{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },1521{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },1522{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,1523(void(*)(void))kdf_argon2_settable_ctx_params },1524{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },1525{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,1526(void(*)(void))kdf_argon2_gettable_ctx_params },1527{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },1528OSSL_DISPATCH_END1529};15301531const OSSL_DISPATCH ossl_kdf_argon2d_functions[] = {1532{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2d_new },1533{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },1534{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },1535{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },1536{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,1537(void(*)(void))kdf_argon2_settable_ctx_params },1538{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },1539{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,1540(void(*)(void))kdf_argon2_gettable_ctx_params },1541{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },1542OSSL_DISPATCH_END1543};15441545const OSSL_DISPATCH ossl_kdf_argon2id_functions[] = {1546{ OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2id_new },1547{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },1548{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },1549{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },1550{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,1551(void(*)(void))kdf_argon2_settable_ctx_params },1552{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },1553{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,1554(void(*)(void))kdf_argon2_gettable_ctx_params },1555{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },1556OSSL_DISPATCH_END1557};15581559#endif156015611562