Path: blob/main/crypto/openssl/providers/implementations/kdfs/argon2.c
106879 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} while ((void)0, 0)119120#undef PERMUTATION_P_ROW121#define PERMUTATION_P_ROW(x, i) \122do { \123uint64_t *base = &x[2 * i]; \124PERMUTATION_P( \125*base, *(base + 1), *(base + 16), *(base + 17), \126*(base + 32), *(base + 33), *(base + 48), *(base + 49), \127*(base + 64), *(base + 65), *(base + 80), *(base + 81), \128*(base + 96), *(base + 97), *(base + 112), *(base + 113)); \129} while ((void)0, 0)130131typedef struct {132uint64_t v[ARGON2_QWORDS_IN_BLOCK];133} BLOCK;134135typedef enum {136ARGON2_VERSION_10 = 0x10,137ARGON2_VERSION_13 = 0x13,138ARGON2_VERSION_NUMBER = ARGON2_VERSION_13139} ARGON2_VERSION;140141typedef enum {142ARGON2_D = 0,143ARGON2_I = 1,144ARGON2_ID = 2145} ARGON2_TYPE;146147typedef struct {148uint32_t pass;149uint32_t lane;150uint8_t slice;151uint32_t index;152} ARGON2_POS;153154typedef struct {155void *provctx;156uint32_t outlen;157uint8_t *pwd;158uint32_t pwdlen;159uint8_t *salt;160uint32_t saltlen;161uint8_t *secret;162uint32_t secretlen;163uint8_t *ad;164uint32_t adlen;165uint32_t t_cost;166uint32_t m_cost;167uint32_t lanes;168uint32_t threads;169uint32_t version;170uint32_t early_clean;171ARGON2_TYPE type;172BLOCK *memory;173uint32_t passes;174uint32_t memory_blocks;175uint32_t segment_length;176uint32_t lane_length;177OSSL_LIB_CTX *libctx;178EVP_MD *md;179EVP_MAC *mac;180char *propq;181} KDF_ARGON2;182183typedef struct {184ARGON2_POS pos;185KDF_ARGON2 *ctx;186} ARGON2_THREAD_DATA;187188static OSSL_FUNC_kdf_newctx_fn kdf_argon2i_new;189static OSSL_FUNC_kdf_newctx_fn kdf_argon2d_new;190static OSSL_FUNC_kdf_newctx_fn kdf_argon2id_new;191static OSSL_FUNC_kdf_freectx_fn kdf_argon2_free;192static OSSL_FUNC_kdf_reset_fn kdf_argon2_reset;193static OSSL_FUNC_kdf_derive_fn kdf_argon2_derive;194static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_argon2_settable_ctx_params;195static OSSL_FUNC_kdf_set_ctx_params_fn kdf_argon2_set_ctx_params;196197static void kdf_argon2_init(KDF_ARGON2 *ctx, ARGON2_TYPE t);198static void *kdf_argon2d_new(void *provctx);199static void *kdf_argon2i_new(void *provctx);200static void *kdf_argon2id_new(void *provctx);201static void kdf_argon2_free(void *vctx);202static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,203const OSSL_PARAM params[]);204static void kdf_argon2_reset(void *vctx);205static int kdf_argon2_ctx_set_threads(KDF_ARGON2 *ctx, uint32_t threads);206static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes);207static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost);208static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost);209static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen);210static int kdf_argon2_ctx_set_secret(KDF_ARGON2 *ctx, const OSSL_PARAM *p);211static int kdf_argon2_ctx_set_pwd(KDF_ARGON2 *ctx, const OSSL_PARAM *p);212static int kdf_argon2_ctx_set_salt(KDF_ARGON2 *ctx, const OSSL_PARAM *p);213static int kdf_argon2_ctx_set_ad(KDF_ARGON2 *ctx, const OSSL_PARAM *p);214static int kdf_argon2_set_ctx_params(void *vctx, const OSSL_PARAM params[]);215static int kdf_argon2_get_ctx_params(void *vctx, OSSL_PARAM params[]);216static int kdf_argon2_ctx_set_version(KDF_ARGON2 *ctx, uint32_t version);217static const OSSL_PARAM *kdf_argon2_settable_ctx_params(ossl_unused void *ctx,218ossl_unused void *p_ctx);219static const OSSL_PARAM *kdf_argon2_gettable_ctx_params(ossl_unused void *ctx,220ossl_unused void *p_ctx);221222static ossl_inline uint64_t load64(const uint8_t *src);223static ossl_inline void store32(uint8_t *dst, uint32_t w);224static ossl_inline void store64(uint8_t *dst, uint64_t w);225static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c);226static ossl_inline uint64_t mul_lower(uint64_t x, uint64_t y);227228static void init_block_value(BLOCK *b, uint8_t in);229static void copy_block(BLOCK *dst, const BLOCK *src);230static void xor_block(BLOCK *dst, const BLOCK *src);231static void load_block(BLOCK *dst, const void *input);232static void store_block(void *output, const BLOCK *src);233static void fill_first_blocks(uint8_t *blockhash, const KDF_ARGON2 *ctx);234static void fill_block(const BLOCK *prev, const BLOCK *ref, BLOCK *next,235int with_xor);236237static void next_addresses(BLOCK *address_block, BLOCK *input_block,238const BLOCK *zero_block);239static int data_indep_addressing(const KDF_ARGON2 *ctx, uint32_t pass,240uint8_t slice);241static uint32_t index_alpha(const KDF_ARGON2 *ctx, uint32_t pass,242uint8_t slice, uint32_t index,243uint32_t pseudo_rand, int same_lane);244245static void fill_segment(const KDF_ARGON2 *ctx, uint32_t pass, uint32_t lane,246uint8_t slice);247248#if !defined(ARGON2_NO_THREADS)249static uint32_t fill_segment_thr(void *thread_data);250static int fill_mem_blocks_mt(KDF_ARGON2 *ctx);251#endif252253static int fill_mem_blocks_st(KDF_ARGON2 *ctx);254static ossl_inline int fill_memory_blocks(KDF_ARGON2 *ctx);255256static void initial_hash(uint8_t *blockhash, KDF_ARGON2 *ctx);257static int initialize(KDF_ARGON2 *ctx);258static void finalize(const KDF_ARGON2 *ctx, void *out);259260static int blake2b(EVP_MD *md, EVP_MAC *mac, void *out, size_t outlen,261const void *in, size_t inlen, const void *key,262size_t keylen);263static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,264size_t outlen, const void *in, size_t inlen);265266static ossl_inline uint64_t load64(const uint8_t *src)267{268return (((uint64_t)src[0]) << 0)269| (((uint64_t)src[1]) << 8)270| (((uint64_t)src[2]) << 16)271| (((uint64_t)src[3]) << 24)272| (((uint64_t)src[4]) << 32)273| (((uint64_t)src[5]) << 40)274| (((uint64_t)src[6]) << 48)275| (((uint64_t)src[7]) << 56);276}277278static ossl_inline void store32(uint8_t *dst, uint32_t w)279{280dst[0] = (uint8_t)(w >> 0);281dst[1] = (uint8_t)(w >> 8);282dst[2] = (uint8_t)(w >> 16);283dst[3] = (uint8_t)(w >> 24);284}285286static ossl_inline void store64(uint8_t *dst, uint64_t w)287{288dst[0] = (uint8_t)(w >> 0);289dst[1] = (uint8_t)(w >> 8);290dst[2] = (uint8_t)(w >> 16);291dst[3] = (uint8_t)(w >> 24);292dst[4] = (uint8_t)(w >> 32);293dst[5] = (uint8_t)(w >> 40);294dst[6] = (uint8_t)(w >> 48);295dst[7] = (uint8_t)(w >> 56);296}297298static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c)299{300return (w >> c) | (w << (64 - c));301}302303static ossl_inline uint64_t mul_lower(uint64_t x, uint64_t y)304{305const uint64_t m = 0xFFFFFFFFUL;306return (x & m) * (y & m);307}308309static void init_block_value(BLOCK *b, uint8_t in)310{311memset(b->v, in, sizeof(b->v));312}313314static void copy_block(BLOCK *dst, const BLOCK *src)315{316memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);317}318319static void xor_block(BLOCK *dst, const BLOCK *src)320{321int i;322323for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)324dst->v[i] ^= src->v[i];325}326327static void load_block(BLOCK *dst, const void *input)328{329unsigned i;330331for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)332dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));333}334335static void store_block(void *output, const BLOCK *src)336{337unsigned i;338339for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)340store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);341}342343static void fill_first_blocks(uint8_t *blockhash, const KDF_ARGON2 *ctx)344{345uint32_t l;346uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];347348/*349* Make the first and second block in each lane as G(H0||0||i)350* or G(H0||1||i).351*/352for (l = 0; l < ctx->lanes; ++l) {353store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);354store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);355blake2b_long(ctx->md, ctx->mac, blockhash_bytes, ARGON2_BLOCK_SIZE,356blockhash, ARGON2_PREHASH_SEED_LENGTH);357load_block(&ctx->memory[l * ctx->lane_length + 0],358blockhash_bytes);359store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);360blake2b_long(ctx->md, ctx->mac, blockhash_bytes, ARGON2_BLOCK_SIZE,361blockhash, ARGON2_PREHASH_SEED_LENGTH);362load_block(&ctx->memory[l * ctx->lane_length + 1],363blockhash_bytes);364}365OPENSSL_cleanse(blockhash_bytes, ARGON2_BLOCK_SIZE);366}367368static void fill_block(const BLOCK *prev, const BLOCK *ref,369BLOCK *next, int with_xor)370{371BLOCK blockR, tmp;372unsigned i;373374copy_block(&blockR, ref);375xor_block(&blockR, prev);376copy_block(&tmp, &blockR);377378if (with_xor)379xor_block(&tmp, next);380381for (i = 0; i < 8; ++i)382PERMUTATION_P_COLUMN(blockR.v, i);383384for (i = 0; i < 8; ++i)385PERMUTATION_P_ROW(blockR.v, i);386387copy_block(next, &tmp);388xor_block(next, &blockR);389}390391static void next_addresses(BLOCK *address_block, BLOCK *input_block,392const BLOCK *zero_block)393{394input_block->v[6]++;395fill_block(zero_block, input_block, address_block, 0);396fill_block(zero_block, address_block, address_block, 0);397}398399static int data_indep_addressing(const KDF_ARGON2 *ctx, uint32_t pass,400uint8_t slice)401{402switch (ctx->type) {403case ARGON2_I:404return 1;405case ARGON2_ID:406return (pass == 0) && (slice < ARGON2_SYNC_POINTS / 2);407case ARGON2_D:408default:409return 0;410}411}412413/*414* Pass 0 (pass = 0):415* This lane: all already finished segments plus already constructed blocks416* in this segment417* Other lanes: all already finished segments418*419* Pass 1+:420* This lane: (SYNC_POINTS - 1) last segments plus already constructed421* blocks in this segment422* Other lanes: (SYNC_POINTS - 1) last segments423*/424static uint32_t index_alpha(const KDF_ARGON2 *ctx, uint32_t pass,425uint8_t slice, uint32_t index,426uint32_t pseudo_rand, int same_lane)427{428uint32_t ref_area_sz;429uint64_t rel_pos;430uint32_t start_pos, abs_pos;431432start_pos = 0;433switch (pass) {434case 0:435if (slice == 0)436ref_area_sz = index - 1;437else if (same_lane)438ref_area_sz = slice * ctx->segment_length + index - 1;439else440ref_area_sz = slice * ctx->segment_length + ((index == 0) ? (-1) : 0);441break;442default:443if (same_lane)444ref_area_sz = ctx->lane_length - ctx->segment_length + index - 1;445else446ref_area_sz = ctx->lane_length - ctx->segment_length + ((index == 0) ? (-1) : 0);447if (slice != ARGON2_SYNC_POINTS - 1)448start_pos = (slice + 1) * ctx->segment_length;449break;450}451452rel_pos = pseudo_rand;453rel_pos = rel_pos * rel_pos >> 32;454rel_pos = ref_area_sz - 1 - (ref_area_sz * rel_pos >> 32);455abs_pos = (start_pos + rel_pos) % ctx->lane_length;456457return abs_pos;458}459460static void fill_segment(const KDF_ARGON2 *ctx, uint32_t pass, uint32_t lane,461uint8_t slice)462{463BLOCK *ref_block = NULL, *curr_block = NULL;464BLOCK address_block, input_block, zero_block;465uint64_t rnd, ref_index, ref_lane;466uint32_t prev_offset;467uint32_t start_idx;468uint32_t j;469uint32_t curr_offset; /* Offset of the current block */470471memset(&input_block, 0, sizeof(BLOCK));472473if (ctx == NULL)474return;475476if (data_indep_addressing(ctx, pass, slice)) {477init_block_value(&zero_block, 0);478init_block_value(&input_block, 0);479480input_block.v[0] = pass;481input_block.v[1] = lane;482input_block.v[2] = slice;483input_block.v[3] = ctx->memory_blocks;484input_block.v[4] = ctx->passes;485input_block.v[5] = ctx->type;486}487488start_idx = 0;489490/* We've generated the first two blocks. Generate the 1st block of addrs. */491if ((pass == 0) && (slice == 0)) {492start_idx = 2;493if (data_indep_addressing(ctx, pass, slice))494next_addresses(&address_block, &input_block, &zero_block);495}496497curr_offset = lane * ctx->lane_length + slice * ctx->segment_length498+ start_idx;499500if ((curr_offset % ctx->lane_length) == 0)501prev_offset = curr_offset + ctx->lane_length - 1;502else503prev_offset = curr_offset - 1;504505for (j = start_idx; j < ctx->segment_length; ++j, ++curr_offset, ++prev_offset) {506if (curr_offset % ctx->lane_length == 1)507prev_offset = curr_offset - 1;508509/* Taking pseudo-random value from the previous block. */510if (data_indep_addressing(ctx, pass, slice)) {511if (j % ARGON2_ADDRESSES_IN_BLOCK == 0)512next_addresses(&address_block, &input_block, &zero_block);513rnd = address_block.v[j % ARGON2_ADDRESSES_IN_BLOCK];514} else {515rnd = ctx->memory[prev_offset].v[0];516}517518/* Computing the lane of the reference block */519ref_lane = ((rnd >> 32)) % ctx->lanes;520/* Can not reference other lanes yet */521if ((pass == 0) && (slice == 0))522ref_lane = lane;523524/* Computing the number of possible reference block within the lane. */525ref_index = index_alpha(ctx, pass, slice, j, rnd & 0xFFFFFFFF,526ref_lane == lane);527528/* Creating a new block */529ref_block = ctx->memory + ctx->lane_length * ref_lane + ref_index;530curr_block = ctx->memory + curr_offset;531if (ARGON2_VERSION_10 == ctx->version) {532/* Version 1.2.1 and earlier: overwrite, not XOR */533fill_block(ctx->memory + prev_offset, ref_block, curr_block, 0);534continue;535}536537fill_block(ctx->memory + prev_offset, ref_block, curr_block,538pass == 0 ? 0 : 1);539}540}541542#if !defined(ARGON2_NO_THREADS)543544static uint32_t fill_segment_thr(void *thread_data)545{546ARGON2_THREAD_DATA *my_data;547548my_data = (ARGON2_THREAD_DATA *)thread_data;549fill_segment(my_data->ctx, my_data->pos.pass, my_data->pos.lane,550my_data->pos.slice);551552return 0;553}554555static int fill_mem_blocks_mt(KDF_ARGON2 *ctx)556{557uint32_t r, s, l, ll;558void **t;559ARGON2_THREAD_DATA *t_data;560561t = OPENSSL_zalloc(sizeof(void *) * ctx->lanes);562t_data = OPENSSL_zalloc(ctx->lanes * sizeof(ARGON2_THREAD_DATA));563564if (t == NULL || t_data == NULL)565goto fail;566567for (r = 0; r < ctx->passes; ++r) {568for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {569for (l = 0; l < ctx->lanes; ++l) {570ARGON2_POS p;571if (l >= ctx->threads) {572if (ossl_crypto_thread_join(t[l - ctx->threads], NULL) == 0)573goto fail;574if (ossl_crypto_thread_clean(t[l - ctx->threads]) == 0)575goto fail;576t[l] = NULL;577}578579p.pass = r;580p.lane = l;581p.slice = (uint8_t)s;582p.index = 0;583584t_data[l].ctx = ctx;585memcpy(&(t_data[l].pos), &p, sizeof(ARGON2_POS));586t[l] = ossl_crypto_thread_start(ctx->libctx, &fill_segment_thr,587(void *)&t_data[l]);588if (t[l] == NULL) {589for (ll = 0; ll < l; ++ll) {590if (ossl_crypto_thread_join(t[ll], NULL) == 0)591goto fail;592if (ossl_crypto_thread_clean(t[ll]) == 0)593goto fail;594t[ll] = NULL;595}596goto fail;597}598}599for (l = ctx->lanes - ctx->threads; l < ctx->lanes; ++l) {600if (ossl_crypto_thread_join(t[l], NULL) == 0)601goto fail;602if (ossl_crypto_thread_clean(t[l]) == 0)603goto fail;604t[l] = NULL;605}606}607}608609OPENSSL_free(t_data);610OPENSSL_free(t);611612return 1;613614fail:615if (t_data != NULL)616OPENSSL_free(t_data);617if (t != NULL)618OPENSSL_free(t);619return 0;620}621622#endif /* !defined(ARGON2_NO_THREADS) */623624static int fill_mem_blocks_st(KDF_ARGON2 *ctx)625{626uint32_t r, s, l;627628for (r = 0; r < ctx->passes; ++r)629for (s = 0; s < ARGON2_SYNC_POINTS; ++s)630for (l = 0; l < ctx->lanes; ++l)631fill_segment(ctx, r, l, s);632return 1;633}634635static ossl_inline int fill_memory_blocks(KDF_ARGON2 *ctx)636{637#if !defined(ARGON2_NO_THREADS)638return ctx->threads == 1 ? fill_mem_blocks_st(ctx) : fill_mem_blocks_mt(ctx);639#else640return ctx->threads == 1 ? fill_mem_blocks_st(ctx) : 0;641#endif642}643644static void initial_hash(uint8_t *blockhash, KDF_ARGON2 *ctx)645{646EVP_MD_CTX *mdctx;647uint8_t value[sizeof(uint32_t)];648unsigned int tmp;649uint32_t args[7];650651if (ctx == NULL || blockhash == NULL)652return;653654args[0] = ctx->lanes;655args[1] = ctx->outlen;656args[2] = ctx->m_cost;657args[3] = ctx->t_cost;658args[4] = ctx->version;659args[5] = (uint32_t)ctx->type;660args[6] = ctx->pwdlen;661662mdctx = EVP_MD_CTX_create();663if (mdctx == NULL || EVP_DigestInit_ex(mdctx, ctx->md, NULL) != 1)664goto fail;665666for (tmp = 0; tmp < sizeof(args) / sizeof(uint32_t); ++tmp) {667store32((uint8_t *)&value, args[tmp]);668if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)669goto fail;670}671672if (ctx->pwd != NULL) {673if (EVP_DigestUpdate(mdctx, ctx->pwd, ctx->pwdlen) != 1)674goto fail;675if (ctx->early_clean) {676OPENSSL_cleanse(ctx->pwd, ctx->pwdlen);677ctx->pwdlen = 0;678}679}680681store32((uint8_t *)&value, ctx->saltlen);682683if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)684goto fail;685686if (ctx->salt != NULL)687if (EVP_DigestUpdate(mdctx, ctx->salt, ctx->saltlen) != 1)688goto fail;689690store32((uint8_t *)&value, ctx->secretlen);691if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)692goto fail;693694if (ctx->secret != NULL) {695if (EVP_DigestUpdate(mdctx, ctx->secret, ctx->secretlen) != 1)696goto fail;697if (ctx->early_clean) {698OPENSSL_cleanse(ctx->secret, ctx->secretlen);699ctx->secretlen = 0;700}701}702703store32((uint8_t *)&value, ctx->adlen);704if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)705goto fail;706707if (ctx->ad != NULL)708if (EVP_DigestUpdate(mdctx, ctx->ad, ctx->adlen) != 1)709goto fail;710711tmp = ARGON2_PREHASH_DIGEST_LENGTH;712if (EVP_DigestFinal_ex(mdctx, blockhash, &tmp) != 1)713goto fail;714715fail:716EVP_MD_CTX_destroy(mdctx);717}718719static int initialize(KDF_ARGON2 *ctx)720{721uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];722723if (ctx == NULL)724return 0;725726if (ctx->memory_blocks * sizeof(BLOCK) / sizeof(BLOCK) != ctx->memory_blocks)727return 0;728729if (ctx->type != ARGON2_D)730ctx->memory = OPENSSL_secure_zalloc(ctx->memory_blocks * sizeof(BLOCK));731else732ctx->memory = OPENSSL_zalloc(ctx->memory_blocks * sizeof(BLOCK));733734if (ctx->memory == NULL) {735ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE,736"cannot allocate required memory");737return 0;738}739740initial_hash(blockhash, ctx);741OPENSSL_cleanse(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,742ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);743fill_first_blocks(blockhash, ctx);744OPENSSL_cleanse(blockhash, ARGON2_PREHASH_SEED_LENGTH);745746return 1;747}748749static void finalize(const KDF_ARGON2 *ctx, void *out)750{751BLOCK blockhash;752uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];753uint32_t last_block_in_lane;754uint32_t l;755756if (ctx == NULL)757return;758759copy_block(&blockhash, ctx->memory + ctx->lane_length - 1);760761/* XOR the last blocks */762for (l = 1; l < ctx->lanes; ++l) {763last_block_in_lane = l * ctx->lane_length + (ctx->lane_length - 1);764xor_block(&blockhash, ctx->memory + last_block_in_lane);765}766767/* Hash the result */768store_block(blockhash_bytes, &blockhash);769blake2b_long(ctx->md, ctx->mac, out, ctx->outlen, blockhash_bytes,770ARGON2_BLOCK_SIZE);771OPENSSL_cleanse(blockhash.v, ARGON2_BLOCK_SIZE);772OPENSSL_cleanse(blockhash_bytes, ARGON2_BLOCK_SIZE);773774if (ctx->type != ARGON2_D)775OPENSSL_secure_clear_free(ctx->memory,776ctx->memory_blocks * sizeof(BLOCK));777else778OPENSSL_clear_free(ctx->memory,779ctx->memory_blocks * sizeof(BLOCK));780}781782static int blake2b_mac(EVP_MAC *mac, void *out, size_t outlen, const void *in,783size_t inlen, const void *key, size_t keylen)784{785int ret = 0;786size_t par_n = 0, out_written;787EVP_MAC_CTX *ctx = NULL;788OSSL_PARAM par[3];789790if ((ctx = EVP_MAC_CTX_new(mac)) == NULL)791goto fail;792793par[par_n++] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,794(void *)key, keylen);795par[par_n++] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &outlen);796par[par_n++] = OSSL_PARAM_construct_end();797798ret = EVP_MAC_CTX_set_params(ctx, par) == 1799&& EVP_MAC_init(ctx, NULL, 0, NULL) == 1800&& EVP_MAC_update(ctx, in, inlen) == 1801&& EVP_MAC_final(ctx, out, (size_t *)&out_written, outlen) == 1;802803fail:804EVP_MAC_CTX_free(ctx);805return ret;806}807808static int blake2b_md(EVP_MD *md, void *out, size_t outlen, const void *in,809size_t inlen)810{811int ret = 0;812EVP_MD_CTX *ctx = NULL;813OSSL_PARAM par[2];814815if ((ctx = EVP_MD_CTX_create()) == NULL)816return 0;817818par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen);819par[1] = OSSL_PARAM_construct_end();820821ret = EVP_DigestInit_ex2(ctx, md, par) == 1822&& EVP_DigestUpdate(ctx, in, inlen) == 1823&& EVP_DigestFinal_ex(ctx, out, NULL) == 1;824825EVP_MD_CTX_free(ctx);826return ret;827}828829static int blake2b(EVP_MD *md, EVP_MAC *mac, void *out, size_t outlen,830const void *in, size_t inlen, const void *key, size_t keylen)831{832if (out == NULL || outlen == 0)833return 0;834835if (key == NULL || keylen == 0)836return blake2b_md(md, out, outlen, in, inlen);837838return blake2b_mac(mac, out, outlen, in, inlen, key, keylen);839}840841static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,842size_t outlen, const void *in, size_t inlen)843{844int ret = 0;845EVP_MD_CTX *ctx = NULL;846uint32_t outlen_curr;847uint8_t outbuf[BLAKE2B_OUTBYTES];848uint8_t inbuf[BLAKE2B_OUTBYTES];849uint8_t outlen_bytes[sizeof(uint32_t)] = { 0 };850OSSL_PARAM par[2];851size_t outlen_md;852853if (out == NULL || outlen == 0)854return 0;855856/* Ensure little-endian byte order */857store32(outlen_bytes, (uint32_t)outlen);858859if ((ctx = EVP_MD_CTX_create()) == NULL)860return 0;861862outlen_md = (outlen <= BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES;863par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen_md);864par[1] = OSSL_PARAM_construct_end();865866ret = EVP_DigestInit_ex2(ctx, md, par) == 1867&& EVP_DigestUpdate(ctx, outlen_bytes, sizeof(outlen_bytes)) == 1868&& EVP_DigestUpdate(ctx, in, inlen) == 1869&& EVP_DigestFinal_ex(ctx, (outlen > BLAKE2B_OUTBYTES) ? outbuf : out,870NULL)871== 1;872873if (ret == 0)874goto fail;875876if (outlen > BLAKE2B_OUTBYTES) {877memcpy(out, outbuf, BLAKE2B_OUTBYTES / 2);878out += BLAKE2B_OUTBYTES / 2;879outlen_curr = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;880881while (outlen_curr > BLAKE2B_OUTBYTES) {882memcpy(inbuf, outbuf, BLAKE2B_OUTBYTES);883if (blake2b(md, mac, outbuf, BLAKE2B_OUTBYTES, inbuf,884BLAKE2B_OUTBYTES, NULL, 0)885!= 1)886goto fail;887memcpy(out, outbuf, BLAKE2B_OUTBYTES / 2);888out += BLAKE2B_OUTBYTES / 2;889outlen_curr -= BLAKE2B_OUTBYTES / 2;890}891892memcpy(inbuf, outbuf, BLAKE2B_OUTBYTES);893if (blake2b(md, mac, outbuf, outlen_curr, inbuf, BLAKE2B_OUTBYTES,894NULL, 0)895!= 1)896goto fail;897memcpy(out, outbuf, outlen_curr);898}899ret = 1;900901fail:902EVP_MD_CTX_free(ctx);903return ret;904}905906static void kdf_argon2_init(KDF_ARGON2 *c, ARGON2_TYPE type)907{908OSSL_LIB_CTX *libctx;909910libctx = c->libctx;911memset(c, 0, sizeof(*c));912913c->libctx = libctx;914c->outlen = ARGON2_DEFAULT_OUTLEN;915c->t_cost = ARGON2_DEFAULT_T_COST;916c->m_cost = ARGON2_DEFAULT_M_COST;917c->lanes = ARGON2_DEFAULT_LANES;918c->threads = ARGON2_DEFAULT_THREADS;919c->version = ARGON2_DEFAULT_VERSION;920c->type = type;921}922923static void *kdf_argon2d_new(void *provctx)924{925KDF_ARGON2 *ctx;926927if (!ossl_prov_is_running())928return NULL;929930ctx = OPENSSL_zalloc(sizeof(*ctx));931if (ctx == NULL) {932ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);933return NULL;934}935936ctx->libctx = PROV_LIBCTX_OF(provctx);937938kdf_argon2_init(ctx, ARGON2_D);939return ctx;940}941942static void *kdf_argon2i_new(void *provctx)943{944KDF_ARGON2 *ctx;945946if (!ossl_prov_is_running())947return NULL;948949ctx = OPENSSL_zalloc(sizeof(*ctx));950if (ctx == NULL) {951ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);952return NULL;953}954955ctx->libctx = PROV_LIBCTX_OF(provctx);956957kdf_argon2_init(ctx, ARGON2_I);958return ctx;959}960961static void *kdf_argon2id_new(void *provctx)962{963KDF_ARGON2 *ctx;964965if (!ossl_prov_is_running())966return NULL;967968ctx = OPENSSL_zalloc(sizeof(*ctx));969if (ctx == NULL) {970ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);971return NULL;972}973974ctx->libctx = PROV_LIBCTX_OF(provctx);975976kdf_argon2_init(ctx, ARGON2_ID);977return ctx;978}979980static void kdf_argon2_free(void *vctx)981{982KDF_ARGON2 *ctx = (KDF_ARGON2 *)vctx;983984if (ctx == NULL)985return;986987if (ctx->pwd != NULL)988OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);989990if (ctx->salt != NULL)991OPENSSL_clear_free(ctx->salt, ctx->saltlen);992993if (ctx->secret != NULL)994OPENSSL_clear_free(ctx->secret, ctx->secretlen);995996if (ctx->ad != NULL)997OPENSSL_clear_free(ctx->ad, ctx->adlen);998999EVP_MD_free(ctx->md);1000EVP_MAC_free(ctx->mac);10011002OPENSSL_free(ctx->propq);10031004memset(ctx, 0, sizeof(*ctx));10051006OPENSSL_free(ctx);1007}10081009static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,1010const OSSL_PARAM params[])1011{1012KDF_ARGON2 *ctx;1013uint32_t memory_blocks, segment_length;10141015ctx = (KDF_ARGON2 *)vctx;10161017if (!ossl_prov_is_running() || !kdf_argon2_set_ctx_params(vctx, params))1018return 0;10191020if (ctx->mac == NULL)1021ctx->mac = EVP_MAC_fetch(ctx->libctx, "blake2bmac", ctx->propq);1022if (ctx->mac == NULL) {1023ERR_raise_data(ERR_LIB_PROV, PROV_R_MISSING_MAC,1024"cannot fetch blake2bmac");1025return 0;1026}10271028if (ctx->md == NULL)1029ctx->md = EVP_MD_fetch(ctx->libctx, "blake2b512", ctx->propq);1030if (ctx->md == NULL) {1031ERR_raise_data(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST,1032"cannot fetch blake2b512");1033return 0;1034}10351036if (ctx->salt == NULL || ctx->saltlen == 0) {1037ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);1038return 0;1039}10401041if (outlen != ctx->outlen) {1042if (OSSL_PARAM_locate((OSSL_PARAM *)params, "size") != NULL) {1043ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);1044return 0;1045}1046if (!kdf_argon2_ctx_set_out_length(ctx, (uint32_t)outlen))1047return 0;1048}10491050switch (ctx->type) {1051case ARGON2_D:1052case ARGON2_I:1053case ARGON2_ID:1054break;1055default:1056ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MODE, "invalid Argon2 type");1057return 0;1058}10591060if (ctx->threads > 1) {1061#ifdef ARGON2_NO_THREADS1062ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1063"requested %u threads, single-threaded mode supported only",1064ctx->threads);1065return 0;1066#else1067if (ctx->threads > ossl_get_avail_threads(ctx->libctx)) {1068ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1069"requested %u threads, available: %u",1070ctx->threads, ossl_get_avail_threads(ctx->libctx));1071return 0;1072}1073#endif1074if (ctx->threads > ctx->lanes) {1075ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1076"requested more threads (%u) than lanes (%u)",1077ctx->threads, ctx->lanes);1078return 0;1079}1080}10811082if (ctx->m_cost < 8 * ctx->lanes) {1083ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE,1084"m_cost must be greater or equal than 8 times the number of lanes");1085return 0;1086}10871088memory_blocks = ctx->m_cost;1089if (memory_blocks < 2 * ARGON2_SYNC_POINTS * ctx->lanes)1090memory_blocks = 2 * ARGON2_SYNC_POINTS * ctx->lanes;10911092/* Ensure that all segments have equal length */1093segment_length = memory_blocks / (ctx->lanes * ARGON2_SYNC_POINTS);1094memory_blocks = segment_length * (ctx->lanes * ARGON2_SYNC_POINTS);10951096ctx->memory = NULL;1097ctx->memory_blocks = memory_blocks;1098ctx->segment_length = segment_length;1099ctx->passes = ctx->t_cost;1100ctx->lane_length = segment_length * ARGON2_SYNC_POINTS;11011102if (initialize(ctx) != 1)1103return 0;11041105if (fill_memory_blocks(ctx) != 1)1106return 0;11071108finalize(ctx, out);11091110return 1;1111}11121113static void kdf_argon2_reset(void *vctx)1114{1115OSSL_LIB_CTX *libctx;1116KDF_ARGON2 *ctx;1117ARGON2_TYPE type;11181119ctx = (KDF_ARGON2 *)vctx;1120type = ctx->type;1121libctx = ctx->libctx;11221123EVP_MD_free(ctx->md);1124EVP_MAC_free(ctx->mac);11251126OPENSSL_free(ctx->propq);11271128if (ctx->pwd != NULL)1129OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);11301131if (ctx->salt != NULL)1132OPENSSL_clear_free(ctx->salt, ctx->saltlen);11331134if (ctx->secret != NULL)1135OPENSSL_clear_free(ctx->secret, ctx->secretlen);11361137if (ctx->ad != NULL)1138OPENSSL_clear_free(ctx->ad, ctx->adlen);11391140memset(ctx, 0, sizeof(*ctx));1141ctx->libctx = libctx;1142kdf_argon2_init(ctx, type);1143}11441145static int kdf_argon2_ctx_set_threads(KDF_ARGON2 *ctx, uint32_t threads)1146{1147if (threads < ARGON2_MIN_THREADS) {1148ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1149"min threads: %u", ARGON2_MIN_THREADS);1150return 0;1151}11521153if (threads > ARGON2_MAX_THREADS) {1154ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,1155"max threads: %u", ARGON2_MAX_THREADS);1156return 0;1157}11581159ctx->threads = threads;1160return 1;1161}11621163static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes)1164{1165if (lanes > ARGON2_MAX_LANES) {1166ERR_raise_data(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER,1167"max lanes: %u", ARGON2_MAX_LANES);1168return 0;1169}11701171if (lanes < ARGON2_MIN_LANES) {1172ERR_raise_data(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER,1173"min lanes: %u", ARGON2_MIN_LANES);1174return 0;1175}11761177ctx->lanes = lanes;1178return 1;1179}11801181static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost)1182{1183/* ARGON2_MAX_MEMORY == max m_cost value, so skip check */11841185if (t_cost < ARGON2_MIN_TIME) {1186ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT,1187"min: %u", ARGON2_MIN_TIME);1188return 0;1189}11901191ctx->t_cost = t_cost;1192return 1;1193}11941195static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost)1196{1197/* ARGON2_MAX_MEMORY == max m_cost value, so skip check */11981199if (m_cost < ARGON2_MIN_MEMORY) {1200ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE, "min: %u",1201ARGON2_MIN_MEMORY);1202return 0;1203}12041205ctx->m_cost = m_cost;1206return 1;1207}12081209static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen)1210{1211/*1212* ARGON2_MAX_OUT_LENGTH == max outlen value, so upper bounds checks1213* are always satisfied; to suppress compiler if statement tautology1214* warnings, these checks are skipped.1215*/12161217if (outlen < ARGON2_MIN_OUT_LENGTH) {1218ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH, "min: %u",1219ARGON2_MIN_OUT_LENGTH);1220return 0;1221}12221223ctx->outlen = outlen;1224return 1;1225}12261227static int kdf_argon2_ctx_set_secret(KDF_ARGON2 *ctx, const OSSL_PARAM *p)1228{1229size_t buflen;12301231if (p->data == NULL)1232return 0;12331234if (ctx->secret != NULL) {1235OPENSSL_clear_free(ctx->secret, ctx->secretlen);1236ctx->secret = NULL;1237ctx->secretlen = 0U;1238}12391240if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->secret, 0, &buflen))1241return 0;12421243if (buflen > ARGON2_MAX_SECRET) {1244OPENSSL_free(ctx->secret);1245ctx->secret = NULL;1246ctx->secretlen = 0U;1247return 0;1248}12491250ctx->secretlen = (uint32_t)buflen;1251return 1;1252}12531254static int kdf_argon2_ctx_set_pwd(KDF_ARGON2 *ctx, const OSSL_PARAM *p)1255{1256size_t buflen;12571258if (p->data == NULL)1259return 0;12601261if (ctx->pwd != NULL) {1262OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);1263ctx->pwd = NULL;1264ctx->pwdlen = 0U;1265}12661267if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pwd, 0, &buflen))1268return 0;12691270if (buflen > ARGON2_MAX_PWD_LENGTH) {1271ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "max: %u",1272ARGON2_MAX_PWD_LENGTH);1273goto fail;1274}12751276ctx->pwdlen = (uint32_t)buflen;1277return 1;12781279fail:1280OPENSSL_free(ctx->pwd);1281ctx->pwd = NULL;1282ctx->pwdlen = 0U;1283return 0;1284}12851286static int kdf_argon2_ctx_set_salt(KDF_ARGON2 *ctx, const OSSL_PARAM *p)1287{1288size_t buflen;12891290if (p->data == NULL)1291return 0;12921293if (ctx->salt != NULL) {1294OPENSSL_clear_free(ctx->salt, ctx->saltlen);1295ctx->salt = NULL;1296ctx->saltlen = 0U;1297}12981299if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0, &buflen))1300return 0;13011302if (buflen < ARGON2_MIN_SALT_LENGTH) {1303ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "min: %u",1304ARGON2_MIN_SALT_LENGTH);1305goto fail;1306}13071308if (buflen > ARGON2_MAX_SALT_LENGTH) {1309ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "max: %u",1310ARGON2_MAX_SALT_LENGTH);1311goto fail;1312}13131314ctx->saltlen = (uint32_t)buflen;1315return 1;13161317fail:1318OPENSSL_free(ctx->salt);1319ctx->salt = NULL;1320ctx->saltlen = 0U;1321return 0;1322}13231324static int kdf_argon2_ctx_set_ad(KDF_ARGON2 *ctx, const OSSL_PARAM *p)1325{1326size_t buflen;13271328if (p->data == NULL)1329return 0;13301331if (ctx->ad != NULL) {1332OPENSSL_clear_free(ctx->ad, ctx->adlen);1333ctx->ad = NULL;1334ctx->adlen = 0U;1335}13361337if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->ad, 0, &buflen))1338return 0;13391340if (buflen > ARGON2_MAX_AD_LENGTH) {1341OPENSSL_free(ctx->ad);1342ctx->ad = NULL;1343ctx->adlen = 0U;1344return 0;1345}13461347ctx->adlen = (uint32_t)buflen;1348return 1;1349}13501351static void kdf_argon2_ctx_set_flag_early_clean(KDF_ARGON2 *ctx, uint32_t f)1352{1353ctx->early_clean = !!(f);1354}13551356static int kdf_argon2_ctx_set_version(KDF_ARGON2 *ctx, uint32_t version)1357{1358switch (version) {1359case ARGON2_VERSION_10:1360case ARGON2_VERSION_13:1361ctx->version = version;1362return 1;1363default:1364ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MODE,1365"invalid Argon2 version");1366return 0;1367}1368}13691370static int set_property_query(KDF_ARGON2 *ctx, const char *propq)1371{1372OPENSSL_free(ctx->propq);1373ctx->propq = NULL;1374if (propq != NULL) {1375ctx->propq = OPENSSL_strdup(propq);1376if (ctx->propq == NULL)1377return 0;1378}1379EVP_MD_free(ctx->md);1380ctx->md = NULL;1381EVP_MAC_free(ctx->mac);1382ctx->mac = NULL;1383return 1;1384}13851386static int kdf_argon2_set_ctx_params(void *vctx, const OSSL_PARAM params[])1387{1388const OSSL_PARAM *p;1389KDF_ARGON2 *ctx;1390uint32_t u32_value;13911392if (ossl_param_is_empty(params))1393return 1;13941395ctx = (KDF_ARGON2 *)vctx;1396if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)1397if (!kdf_argon2_ctx_set_pwd(ctx, p))1398return 0;13991400if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)1401if (!kdf_argon2_ctx_set_salt(ctx, p))1402return 0;14031404if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL)1405if (!kdf_argon2_ctx_set_secret(ctx, p))1406return 0;14071408if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_AD)) != NULL)1409if (!kdf_argon2_ctx_set_ad(ctx, p))1410return 0;14111412if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SIZE)) != NULL) {1413if (!OSSL_PARAM_get_uint32(p, &u32_value))1414return 0;1415if (!kdf_argon2_ctx_set_out_length(ctx, u32_value))1416return 0;1417}14181419if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL) {1420if (!OSSL_PARAM_get_uint32(p, &u32_value))1421return 0;1422if (!kdf_argon2_ctx_set_t_cost(ctx, u32_value))1423return 0;1424}14251426if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_THREADS)) != NULL) {1427if (!OSSL_PARAM_get_uint32(p, &u32_value))1428return 0;1429if (!kdf_argon2_ctx_set_threads(ctx, u32_value))1430return 0;1431}14321433if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_LANES)) != NULL) {1434if (!OSSL_PARAM_get_uint32(p, &u32_value))1435return 0;1436if (!kdf_argon2_ctx_set_lanes(ctx, u32_value))1437return 0;1438}14391440if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_MEMCOST)) != NULL) {1441if (!OSSL_PARAM_get_uint32(p, &u32_value))1442return 0;1443if (!kdf_argon2_ctx_set_m_cost(ctx, u32_value))1444return 0;1445}14461447if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_EARLY_CLEAN)) != NULL) {1448if (!OSSL_PARAM_get_uint32(p, &u32_value))1449return 0;1450kdf_argon2_ctx_set_flag_early_clean(ctx, u32_value);1451}14521453if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_VERSION)) != NULL) {1454if (!OSSL_PARAM_get_uint32(p, &u32_value))1455return 0;1456if (!kdf_argon2_ctx_set_version(ctx, u32_value))1457return 0;1458}14591460if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES)) != NULL) {1461if (p->data_type != OSSL_PARAM_UTF8_STRING1462|| !set_property_query(ctx, p->data))1463return 0;1464}14651466return 1;1467}14681469static const OSSL_PARAM *kdf_argon2_settable_ctx_params(ossl_unused void *ctx,1470ossl_unused void *p_ctx)1471{1472static const OSSL_PARAM known_settable_ctx_params[] = {1473OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),1474OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),1475OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),1476OSSL_PARAM_octet_string(OSSL_KDF_PARAM_ARGON2_AD, NULL, 0),1477OSSL_PARAM_uint32(OSSL_KDF_PARAM_SIZE, NULL),1478OSSL_PARAM_uint32(OSSL_KDF_PARAM_ITER, NULL),1479OSSL_PARAM_uint32(OSSL_KDF_PARAM_THREADS, NULL),1480OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_LANES, NULL),1481OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, NULL),1482OSSL_PARAM_uint32(OSSL_KDF_PARAM_EARLY_CLEAN, NULL),1483OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_VERSION, NULL),1484OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),1485OSSL_PARAM_END1486};14871488return known_settable_ctx_params;1489}14901491static int kdf_argon2_get_ctx_params(void *vctx, OSSL_PARAM params[])1492{1493OSSL_PARAM *p;14941495(void)vctx;1496if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)1497return OSSL_PARAM_set_size_t(p, SIZE_MAX);14981499return -2;1500}15011502static const OSSL_PARAM *kdf_argon2_gettable_ctx_params(ossl_unused void *ctx,1503ossl_unused void *p_ctx)1504{1505static const OSSL_PARAM known_gettable_ctx_params[] = {1506OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),1507OSSL_PARAM_END1508};15091510return known_gettable_ctx_params;1511}15121513const OSSL_DISPATCH ossl_kdf_argon2i_functions[] = {1514{ OSSL_FUNC_KDF_NEWCTX, (void (*)(void))kdf_argon2i_new },1515{ OSSL_FUNC_KDF_FREECTX, (void (*)(void))kdf_argon2_free },1516{ OSSL_FUNC_KDF_RESET, (void (*)(void))kdf_argon2_reset },1517{ OSSL_FUNC_KDF_DERIVE, (void (*)(void))kdf_argon2_derive },1518{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,1519(void (*)(void))kdf_argon2_settable_ctx_params },1520{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))kdf_argon2_set_ctx_params },1521{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,1522(void (*)(void))kdf_argon2_gettable_ctx_params },1523{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))kdf_argon2_get_ctx_params },1524OSSL_DISPATCH_END1525};15261527const OSSL_DISPATCH ossl_kdf_argon2d_functions[] = {1528{ OSSL_FUNC_KDF_NEWCTX, (void (*)(void))kdf_argon2d_new },1529{ OSSL_FUNC_KDF_FREECTX, (void (*)(void))kdf_argon2_free },1530{ OSSL_FUNC_KDF_RESET, (void (*)(void))kdf_argon2_reset },1531{ OSSL_FUNC_KDF_DERIVE, (void (*)(void))kdf_argon2_derive },1532{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,1533(void (*)(void))kdf_argon2_settable_ctx_params },1534{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))kdf_argon2_set_ctx_params },1535{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,1536(void (*)(void))kdf_argon2_gettable_ctx_params },1537{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))kdf_argon2_get_ctx_params },1538OSSL_DISPATCH_END1539};15401541const OSSL_DISPATCH ossl_kdf_argon2id_functions[] = {1542{ OSSL_FUNC_KDF_NEWCTX, (void (*)(void))kdf_argon2id_new },1543{ OSSL_FUNC_KDF_FREECTX, (void (*)(void))kdf_argon2_free },1544{ OSSL_FUNC_KDF_RESET, (void (*)(void))kdf_argon2_reset },1545{ OSSL_FUNC_KDF_DERIVE, (void (*)(void))kdf_argon2_derive },1546{ OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,1547(void (*)(void))kdf_argon2_settable_ctx_params },1548{ OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))kdf_argon2_set_ctx_params },1549{ OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,1550(void (*)(void))kdf_argon2_gettable_ctx_params },1551{ OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))kdf_argon2_get_ctx_params },1552OSSL_DISPATCH_END1553};15541555#endif155615571558