1/*
2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 *
9 * RFC 9106 Argon2 (see https://www.rfc-editor.org/rfc/rfc9106.txt)
10 *
11 */
12{-
13use OpenSSL::paramnames qw(produce_param_decoder);
14-}
15
16#include <stdlib.h>
17#include <stddef.h>
18#include <stdarg.h>
19#include <string.h>
20#include <openssl/e_os2.h>
21#include <openssl/evp.h>
22#include <openssl/objects.h>
23#include <openssl/crypto.h>
24#include <openssl/kdf.h>
25#include <openssl/err.h>
26#include <openssl/core_names.h>
27#include <openssl/params.h>
28#include <openssl/thread.h>
29#include <openssl/proverr.h>
30#include "internal/thread.h"
31#include "internal/numbers.h"
32#include "internal/endian.h"
33#include "crypto/evp.h"
34#include "prov/implementations.h"
35#include "prov/provider_ctx.h"
36#include "prov/providercommon.h"
37#include "prov/blake2.h"
38
39#if defined(OPENSSL_NO_DEFAULT_THREAD_POOL) && defined(OPENSSL_NO_THREAD_POOL)
40# define ARGON2_NO_THREADS
41#endif
42
43#if !defined(OPENSSL_THREADS)
44# define ARGON2_NO_THREADS
45#endif
46
47#ifndef OPENSSL_NO_ARGON2
48
49# define ARGON2_MIN_LANES 1u
50# define ARGON2_MAX_LANES 0xFFFFFFu
51# define ARGON2_MIN_THREADS 1u
52# define ARGON2_MAX_THREADS 0xFFFFFFu
53# define ARGON2_SYNC_POINTS 4u
54# define ARGON2_MIN_OUT_LENGTH 4u
55# define ARGON2_MAX_OUT_LENGTH 0xFFFFFFFFu
56# define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS)
57# define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
58# define ARGON2_MAX_MEMORY 0xFFFFFFFFu
59# define ARGON2_MIN_TIME 1u
60# define ARGON2_MAX_TIME 0xFFFFFFFFu
61# define ARGON2_MIN_PWD_LENGTH 0u
62# define ARGON2_MAX_PWD_LENGTH 0xFFFFFFFFu
63# define ARGON2_MIN_AD_LENGTH 0u
64# define ARGON2_MAX_AD_LENGTH 0xFFFFFFFFu
65# define ARGON2_MIN_SALT_LENGTH 8u
66# define ARGON2_MAX_SALT_LENGTH 0xFFFFFFFFu
67# define ARGON2_MIN_SECRET 0u
68# define ARGON2_MAX_SECRET 0xFFFFFFFFu
69# define ARGON2_BLOCK_SIZE 1024
70# define ARGON2_QWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 8)
71# define ARGON2_OWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 16)
72# define ARGON2_HWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 32)
73# define ARGON2_512BIT_WORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 64)
74# define ARGON2_ADDRESSES_IN_BLOCK 128
75# define ARGON2_PREHASH_DIGEST_LENGTH 64
76# define ARGON2_PREHASH_SEED_LENGTH \
77    (ARGON2_PREHASH_DIGEST_LENGTH + (2 * sizeof(uint32_t)))
78
79# define ARGON2_DEFAULT_OUTLEN 64u
80# define ARGON2_DEFAULT_T_COST 3u
81# define ARGON2_DEFAULT_M_COST ARGON2_MIN_MEMORY
82# define ARGON2_DEFAULT_LANES  1u
83# define ARGON2_DEFAULT_THREADS 1u
84# define ARGON2_DEFAULT_VERSION ARGON2_VERSION_NUMBER
85
86# undef G
87# define G(a, b, c, d)                                                        \
88    do {                                                                      \
89        a = a + b + 2 * mul_lower(a, b);                                      \
90        d = rotr64(d ^ a, 32);                                                \
91        c = c + d + 2 * mul_lower(c, d);                                      \
92        b = rotr64(b ^ c, 24);                                                \
93        a = a + b + 2 * mul_lower(a, b);                                      \
94        d = rotr64(d ^ a, 16);                                                \
95        c = c + d + 2 * mul_lower(c, d);                                      \
96        b = rotr64(b ^ c, 63);                                                \
97    } while ((void)0, 0)
98
99# undef PERMUTATION_P
100# define PERMUTATION_P(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,      \
101                       v12, v13, v14, v15)                                    \
102    do {                                                                      \
103        G(v0, v4, v8, v12);                                                   \
104        G(v1, v5, v9, v13);                                                   \
105        G(v2, v6, v10, v14);                                                  \
106        G(v3, v7, v11, v15);                                                  \
107        G(v0, v5, v10, v15);                                                  \
108        G(v1, v6, v11, v12);                                                  \
109        G(v2, v7, v8, v13);                                                   \
110        G(v3, v4, v9, v14);                                                   \
111    } while ((void)0, 0)
112
113# undef PERMUTATION_P_COLUMN
114# define PERMUTATION_P_COLUMN(x, i)                                           \
115    do {                                                                      \
116        uint64_t *base = &x[16 * i];                                          \
117        PERMUTATION_P(                                                        \
118            *base,        *(base + 1),  *(base + 2),  *(base + 3),            \
119            *(base + 4),  *(base + 5),  *(base + 6),  *(base + 7),            \
120            *(base + 8),  *(base + 9),  *(base + 10), *(base + 11),           \
121            *(base + 12), *(base + 13), *(base + 14), *(base + 15)            \
122        );                                                                    \
123    } while ((void)0, 0)
124
125# undef PERMUTATION_P_ROW
126# define PERMUTATION_P_ROW(x, i)                                              \
127    do {                                                                      \
128        uint64_t *base = &x[2 * i];                                           \
129        PERMUTATION_P(                                                        \
130            *base,        *(base + 1),  *(base + 16),  *(base + 17),          \
131            *(base + 32), *(base + 33), *(base + 48),  *(base + 49),          \
132            *(base + 64), *(base + 65), *(base + 80),  *(base + 81),          \
133            *(base + 96), *(base + 97), *(base + 112), *(base + 113)          \
134        );                                                                    \
135    } while ((void)0, 0)
136
137typedef struct {
138    uint64_t v[ARGON2_QWORDS_IN_BLOCK];
139} BLOCK;
140
141typedef enum {
142    ARGON2_VERSION_10 = 0x10,
143    ARGON2_VERSION_13 = 0x13,
144    ARGON2_VERSION_NUMBER = ARGON2_VERSION_13
145} ARGON2_VERSION;
146
147typedef enum {
148    ARGON2_D  = 0,
149    ARGON2_I  = 1,
150    ARGON2_ID = 2
151} ARGON2_TYPE;
152
153typedef struct {
154    uint32_t pass;
155    uint32_t lane;
156    uint8_t slice;
157    uint32_t index;
158} ARGON2_POS;
159
160typedef struct {
161    void *provctx;
162    uint32_t outlen;
163    uint8_t *pwd;
164    uint32_t pwdlen;
165    uint8_t *salt;
166    uint32_t saltlen;
167    uint8_t *secret;
168    uint32_t secretlen;
169    uint8_t *ad;
170    uint32_t adlen;
171    uint32_t t_cost;
172    uint32_t m_cost;
173    uint32_t lanes;
174    uint32_t threads;
175    uint32_t version;
176    uint32_t early_clean;
177    ARGON2_TYPE type;
178    BLOCK *memory;
179    uint32_t passes;
180    uint32_t memory_blocks;
181    uint32_t segment_length;
182    uint32_t lane_length;
183    OSSL_LIB_CTX *libctx;
184    EVP_MD *md;
185    EVP_MAC *mac;
186    char *propq;
187} KDF_ARGON2;
188
189typedef struct {
190    ARGON2_POS pos;
191    KDF_ARGON2 *ctx;
192} ARGON2_THREAD_DATA;
193
194static OSSL_FUNC_kdf_newctx_fn kdf_argon2i_new;
195static OSSL_FUNC_kdf_newctx_fn kdf_argon2d_new;
196static OSSL_FUNC_kdf_newctx_fn kdf_argon2id_new;
197static OSSL_FUNC_kdf_freectx_fn kdf_argon2_free;
198static OSSL_FUNC_kdf_reset_fn kdf_argon2_reset;
199static OSSL_FUNC_kdf_derive_fn kdf_argon2_derive;
200static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_argon2_settable_ctx_params;
201static OSSL_FUNC_kdf_set_ctx_params_fn kdf_argon2_set_ctx_params;
202
203static void kdf_argon2_init(KDF_ARGON2 *ctx, ARGON2_TYPE t);
204static void *kdf_argon2d_new(void *provctx);
205static void *kdf_argon2i_new(void *provctx);
206static void *kdf_argon2id_new(void *provctx);
207static void kdf_argon2_free(void *vctx);
208static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,
209                             const OSSL_PARAM params[]);
210static void kdf_argon2_reset(void *vctx);
211static int kdf_argon2_ctx_set_threads(KDF_ARGON2 *ctx, uint32_t threads);
212static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes);
213static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost);
214static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost);
215static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen);
216static int kdf_argon2_ctx_set_secret(KDF_ARGON2 *ctx, const OSSL_PARAM *p);
217static int kdf_argon2_ctx_set_pwd(KDF_ARGON2 *ctx, const OSSL_PARAM *p);
218static int kdf_argon2_ctx_set_salt(KDF_ARGON2 *ctx, const OSSL_PARAM *p);
219static int kdf_argon2_ctx_set_ad(KDF_ARGON2 *ctx, const OSSL_PARAM *p);
220static int kdf_argon2_set_ctx_params(void *vctx, const OSSL_PARAM params[]);
221static int kdf_argon2_get_ctx_params(void *vctx, OSSL_PARAM params[]);
222static int kdf_argon2_ctx_set_version(KDF_ARGON2 *ctx, uint32_t version);
223static const OSSL_PARAM *kdf_argon2_settable_ctx_params(ossl_unused void *ctx,
224                                                        ossl_unused void *p_ctx);
225static const OSSL_PARAM *kdf_argon2_gettable_ctx_params(ossl_unused void *ctx,
226                                                        ossl_unused void *p_ctx);
227static int argon2_set_ctx_params(KDF_ARGON2 *ctx, const OSSL_PARAM params[],
228                                 OSSL_PARAM **size_param_ptr);
229
230static ossl_inline uint64_t load64(const uint8_t *src);
231static ossl_inline void store32(uint8_t *dst, uint32_t w);
232static ossl_inline void store64(uint8_t *dst, uint64_t w);
233static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c);
234static ossl_inline uint64_t mul_lower(uint64_t x, uint64_t y);
235
236static void init_block_value(BLOCK *b, uint8_t in);
237static void copy_block(BLOCK *dst, const BLOCK *src);
238static void xor_block(BLOCK *dst, const BLOCK *src);
239static void load_block(BLOCK *dst, const void *input);
240static void store_block(void *output, const BLOCK *src);
241static void fill_first_blocks(uint8_t *blockhash, const KDF_ARGON2 *ctx);
242static void fill_block(const BLOCK *prev, const BLOCK *ref, BLOCK *next,
243                       int with_xor);
244
245static void next_addresses(BLOCK *address_block, BLOCK *input_block,
246                           const BLOCK *zero_block);
247static int data_indep_addressing(const KDF_ARGON2 *ctx, uint32_t pass,
248                                 uint8_t slice);
249static uint32_t index_alpha(const KDF_ARGON2 *ctx, uint32_t pass,
250                            uint8_t slice, uint32_t index,
251                            uint32_t pseudo_rand, int same_lane);
252
253static void fill_segment(const KDF_ARGON2 *ctx, uint32_t pass, uint32_t lane,
254                         uint8_t slice);
255
256# if !defined(ARGON2_NO_THREADS)
257static uint32_t fill_segment_thr(void *thread_data);
258static int fill_mem_blocks_mt(KDF_ARGON2 *ctx);
259# endif
260
261static int fill_mem_blocks_st(KDF_ARGON2 *ctx);
262static ossl_inline int fill_memory_blocks(KDF_ARGON2 *ctx);
263
264static void initial_hash(uint8_t *blockhash, KDF_ARGON2 *ctx);
265static int initialize(KDF_ARGON2 *ctx);
266static void finalize(const KDF_ARGON2 *ctx, void *out);
267
268static int blake2b(EVP_MD *md, EVP_MAC *mac, void *out, size_t outlen,
269                   const void *in, size_t inlen, const void *key,
270                   size_t keylen);
271static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,
272                        size_t outlen, const void *in, size_t inlen);
273
274static ossl_inline uint64_t load64(const uint8_t *src)
275{
276    return
277      (((uint64_t)src[0]) << 0)
278    | (((uint64_t)src[1]) << 8)
279    | (((uint64_t)src[2]) << 16)
280    | (((uint64_t)src[3]) << 24)
281    | (((uint64_t)src[4]) << 32)
282    | (((uint64_t)src[5]) << 40)
283    | (((uint64_t)src[6]) << 48)
284    | (((uint64_t)src[7]) << 56);
285}
286
287static ossl_inline void store32(uint8_t *dst, uint32_t w)
288{
289    dst[0] = (uint8_t)(w >> 0);
290    dst[1] = (uint8_t)(w >> 8);
291    dst[2] = (uint8_t)(w >> 16);
292    dst[3] = (uint8_t)(w >> 24);
293}
294
295static ossl_inline void store64(uint8_t *dst, uint64_t w)
296{
297    dst[0] = (uint8_t)(w >> 0);
298    dst[1] = (uint8_t)(w >> 8);
299    dst[2] = (uint8_t)(w >> 16);
300    dst[3] = (uint8_t)(w >> 24);
301    dst[4] = (uint8_t)(w >> 32);
302    dst[5] = (uint8_t)(w >> 40);
303    dst[6] = (uint8_t)(w >> 48);
304    dst[7] = (uint8_t)(w >> 56);
305}
306
307static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c)
308{
309    return (w >> c) | (w << (64 - c));
310}
311
312static ossl_inline uint64_t mul_lower(uint64_t x, uint64_t y)
313{
314    const uint64_t m = 0xFFFFFFFFUL;
315    return (x & m) * (y & m);
316}
317
318static void init_block_value(BLOCK *b, uint8_t in)
319{
320    memset(b->v, in, sizeof(b->v));
321}
322
323static void copy_block(BLOCK *dst, const BLOCK *src)
324{
325    memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
326}
327
328static void xor_block(BLOCK *dst, const BLOCK *src)
329{
330    int i;
331
332    for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)
333        dst->v[i] ^= src->v[i];
334}
335
336static void load_block(BLOCK *dst, const void *input)
337{
338    unsigned i;
339
340    for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)
341        dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
342}
343
344static void store_block(void *output, const BLOCK *src)
345{
346    unsigned i;
347
348    for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)
349        store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
350}
351
352static void fill_first_blocks(uint8_t *blockhash, const KDF_ARGON2 *ctx)
353{
354    uint32_t l;
355    uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
356
357    /*
358     * Make the first and second block in each lane as G(H0||0||i)
359     * or G(H0||1||i).
360     */
361    for (l = 0; l < ctx->lanes; ++l) {
362        store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
363        store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
364        blake2b_long(ctx->md, ctx->mac, blockhash_bytes, ARGON2_BLOCK_SIZE,
365                     blockhash, ARGON2_PREHASH_SEED_LENGTH);
366        load_block(&ctx->memory[l * ctx->lane_length + 0],
367                   blockhash_bytes);
368        store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
369        blake2b_long(ctx->md, ctx->mac, blockhash_bytes, ARGON2_BLOCK_SIZE,
370                     blockhash, ARGON2_PREHASH_SEED_LENGTH);
371        load_block(&ctx->memory[l * ctx->lane_length + 1],
372                   blockhash_bytes);
373    }
374    OPENSSL_cleanse(blockhash_bytes, ARGON2_BLOCK_SIZE);
375}
376
377static void fill_block(const BLOCK *prev, const BLOCK *ref,
378                       BLOCK *next, int with_xor)
379{
380    BLOCK blockR, tmp;
381    unsigned i;
382
383    copy_block(&blockR, ref);
384    xor_block(&blockR, prev);
385    copy_block(&tmp, &blockR);
386
387    if (with_xor)
388        xor_block(&tmp, next);
389
390    for (i = 0; i < 8; ++i)
391        PERMUTATION_P_COLUMN(blockR.v, i);
392
393    for (i = 0; i < 8; ++i)
394        PERMUTATION_P_ROW(blockR.v, i);
395
396    copy_block(next, &tmp);
397    xor_block(next, &blockR);
398}
399
400static void next_addresses(BLOCK *address_block, BLOCK *input_block,
401                           const BLOCK *zero_block)
402{
403    input_block->v[6]++;
404    fill_block(zero_block, input_block, address_block, 0);
405    fill_block(zero_block, address_block, address_block, 0);
406}
407
408static int data_indep_addressing(const KDF_ARGON2 *ctx, uint32_t pass,
409                                 uint8_t slice)
410{
411    switch (ctx->type) {
412    case ARGON2_I:
413        return 1;
414    case ARGON2_ID:
415        return (pass == 0) && (slice < ARGON2_SYNC_POINTS / 2);
416    case ARGON2_D:
417    default:
418        return 0;
419    }
420}
421
422/*
423 * Pass 0 (pass = 0):
424 * This lane: all already finished segments plus already constructed blocks
425 *            in this segment
426 * Other lanes: all already finished segments
427 *
428 * Pass 1+:
429 * This lane: (SYNC_POINTS - 1) last segments plus already constructed
430 *            blocks in this segment
431 * Other lanes: (SYNC_POINTS - 1) last segments
432 */
433static uint32_t index_alpha(const KDF_ARGON2 *ctx, uint32_t pass,
434                            uint8_t slice, uint32_t index,
435                            uint32_t pseudo_rand, int same_lane)
436{
437    uint32_t ref_area_sz;
438    uint64_t rel_pos;
439    uint32_t start_pos, abs_pos;
440
441    start_pos = 0;
442    switch (pass) {
443    case 0:
444        if (slice == 0)
445            ref_area_sz = index - 1;
446        else if (same_lane)
447            ref_area_sz = slice * ctx->segment_length + index - 1;
448        else
449            ref_area_sz = slice * ctx->segment_length +
450                ((index == 0) ? (-1) : 0);
451        break;
452    default:
453        if (same_lane)
454            ref_area_sz = ctx->lane_length - ctx->segment_length + index - 1;
455        else
456            ref_area_sz = ctx->lane_length - ctx->segment_length +
457                ((index == 0) ? (-1) : 0);
458        if (slice != ARGON2_SYNC_POINTS - 1)
459            start_pos = (slice + 1) * ctx->segment_length;
460        break;
461    }
462
463    rel_pos = pseudo_rand;
464    rel_pos = rel_pos * rel_pos >> 32;
465    rel_pos = ref_area_sz - 1 - (ref_area_sz * rel_pos >> 32);
466    abs_pos = (start_pos + rel_pos) % ctx->lane_length;
467
468    return abs_pos;
469}
470
471static void fill_segment(const KDF_ARGON2 *ctx, uint32_t pass, uint32_t lane,
472                         uint8_t slice)
473{
474    BLOCK *ref_block = NULL, *curr_block = NULL;
475    BLOCK address_block, input_block, zero_block;
476    uint64_t rnd, ref_index, ref_lane;
477    uint32_t prev_offset;
478    uint32_t start_idx;
479    uint32_t j;
480    uint32_t curr_offset; /* Offset of the current block */
481
482    memset(&input_block, 0, sizeof(BLOCK));
483
484    if (ctx == NULL)
485        return;
486
487    if (data_indep_addressing(ctx, pass, slice)) {
488        init_block_value(&zero_block, 0);
489        init_block_value(&input_block, 0);
490
491        input_block.v[0] = pass;
492        input_block.v[1] = lane;
493        input_block.v[2] = slice;
494        input_block.v[3] = ctx->memory_blocks;
495        input_block.v[4] = ctx->passes;
496        input_block.v[5] = ctx->type;
497    }
498
499    start_idx = 0;
500
501    /* We've generated the first two blocks. Generate the 1st block of addrs. */
502    if ((pass == 0) && (slice == 0)) {
503        start_idx = 2;
504        if (data_indep_addressing(ctx, pass, slice))
505            next_addresses(&address_block, &input_block, &zero_block);
506    }
507
508    curr_offset = lane * ctx->lane_length + slice * ctx->segment_length
509        + start_idx;
510
511    if ((curr_offset % ctx->lane_length) == 0)
512        prev_offset = curr_offset + ctx->lane_length - 1;
513    else
514        prev_offset = curr_offset - 1;
515
516    for (j = start_idx; j < ctx->segment_length; ++j, ++curr_offset, ++prev_offset) {
517        if (curr_offset % ctx->lane_length == 1)
518            prev_offset = curr_offset - 1;
519
520        /* Taking pseudo-random value from the previous block. */
521        if (data_indep_addressing(ctx, pass, slice)) {
522            if (j % ARGON2_ADDRESSES_IN_BLOCK == 0)
523                next_addresses(&address_block, &input_block, &zero_block);
524            rnd = address_block.v[j % ARGON2_ADDRESSES_IN_BLOCK];
525        } else {
526            rnd = ctx->memory[prev_offset].v[0];
527        }
528
529        /* Computing the lane of the reference block */
530        ref_lane = ((rnd >> 32)) % ctx->lanes;
531        /* Can not reference other lanes yet */
532        if ((pass == 0) && (slice == 0))
533            ref_lane = lane;
534
535        /* Computing the number of possible reference block within the lane. */
536        ref_index = index_alpha(ctx, pass, slice, j, rnd & 0xFFFFFFFF,
537                                ref_lane == lane);
538
539        /* Creating a new block */
540        ref_block = ctx->memory + ctx->lane_length * ref_lane + ref_index;
541        curr_block = ctx->memory + curr_offset;
542        if (ARGON2_VERSION_10 == ctx->version) {
543            /* Version 1.2.1 and earlier: overwrite, not XOR */
544            fill_block(ctx->memory + prev_offset, ref_block, curr_block, 0);
545            continue;
546        }
547
548        fill_block(ctx->memory + prev_offset, ref_block, curr_block,
549                   pass == 0 ? 0 : 1);
550    }
551}
552
553# if !defined(ARGON2_NO_THREADS)
554
555static uint32_t fill_segment_thr(void *thread_data)
556{
557    ARGON2_THREAD_DATA *my_data;
558
559    my_data = (ARGON2_THREAD_DATA *) thread_data;
560    fill_segment(my_data->ctx, my_data->pos.pass, my_data->pos.lane,
561                 my_data->pos.slice);
562
563    return 0;
564}
565
566static int fill_mem_blocks_mt(KDF_ARGON2 *ctx)
567{
568    uint32_t r, s, l, ll;
569    void **t;
570    ARGON2_THREAD_DATA *t_data;
571
572    t = OPENSSL_calloc(ctx->lanes, sizeof(void *));
573    t_data = OPENSSL_calloc(ctx->lanes, sizeof(ARGON2_THREAD_DATA));
574
575    if (t == NULL || t_data == NULL)
576        goto fail;
577
578    for (r = 0; r < ctx->passes; ++r) {
579        for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
580            for (l = 0; l < ctx->lanes; ++l) {
581                ARGON2_POS p;
582                if (l >= ctx->threads) {
583                    if (ossl_crypto_thread_join(t[l - ctx->threads], NULL) == 0)
584                        goto fail;
585                    if (ossl_crypto_thread_clean(t[l - ctx->threads]) == 0)
586                        goto fail;
587                    t[l] = NULL;
588                }
589
590                p.pass = r;
591                p.lane = l;
592                p.slice = (uint8_t)s;
593                p.index = 0;
594
595                t_data[l].ctx = ctx;
596                memcpy(&(t_data[l].pos), &p, sizeof(ARGON2_POS));
597                t[l] = ossl_crypto_thread_start(ctx->libctx, &fill_segment_thr,
598                                                (void *) &t_data[l]);
599                if (t[l] == NULL) {
600                    for (ll = 0; ll < l; ++ll) {
601                        if (ossl_crypto_thread_join(t[ll], NULL) == 0)
602                            goto fail;
603                        if (ossl_crypto_thread_clean(t[ll]) == 0)
604                            goto fail;
605                        t[ll] = NULL;
606                    }
607                    goto fail;
608                }
609            }
610            for (l = ctx->lanes - ctx->threads; l < ctx->lanes; ++l) {
611                if (ossl_crypto_thread_join(t[l], NULL) == 0)
612                    goto fail;
613                if (ossl_crypto_thread_clean(t[l]) == 0)
614                    goto fail;
615                t[l] = NULL;
616            }
617        }
618    }
619
620    OPENSSL_free(t_data);
621    OPENSSL_free(t);
622
623    return 1;
624
625fail:
626    if (t_data != NULL)
627        OPENSSL_free(t_data);
628    if (t != NULL)
629        OPENSSL_free(t);
630    return 0;
631}
632
633# endif /* !defined(ARGON2_NO_THREADS) */
634
635static int fill_mem_blocks_st(KDF_ARGON2 *ctx)
636{
637    uint32_t r, s, l;
638
639    for (r = 0; r < ctx->passes; ++r)
640        for (s = 0; s < ARGON2_SYNC_POINTS; ++s)
641            for (l = 0; l < ctx->lanes; ++l)
642                fill_segment(ctx, r, l, s);
643    return 1;
644}
645
646static ossl_inline int fill_memory_blocks(KDF_ARGON2 *ctx)
647{
648# if !defined(ARGON2_NO_THREADS)
649    return ctx->threads == 1 ? fill_mem_blocks_st(ctx) : fill_mem_blocks_mt(ctx);
650# else
651    return ctx->threads == 1 ? fill_mem_blocks_st(ctx) : 0;
652# endif
653}
654
655static void initial_hash(uint8_t *blockhash, KDF_ARGON2 *ctx)
656{
657    EVP_MD_CTX *mdctx;
658    uint8_t value[sizeof(uint32_t)];
659    unsigned int tmp;
660    uint32_t args[7];
661
662    if (ctx == NULL || blockhash == NULL)
663        return;
664
665    args[0] = ctx->lanes;
666    args[1] = ctx->outlen;
667    args[2] = ctx->m_cost;
668    args[3] = ctx->t_cost;
669    args[4] = ctx->version;
670    args[5] = (uint32_t) ctx->type;
671    args[6] = ctx->pwdlen;
672
673    mdctx = EVP_MD_CTX_create();
674    if (mdctx == NULL || EVP_DigestInit_ex(mdctx, ctx->md, NULL) != 1)
675        goto fail;
676
677    for (tmp = 0; tmp < sizeof(args) / sizeof(uint32_t); ++tmp) {
678        store32((uint8_t *) &value, args[tmp]);
679        if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)
680            goto fail;
681    }
682
683    if (ctx->pwd != NULL) {
684        if (EVP_DigestUpdate(mdctx, ctx->pwd, ctx->pwdlen) != 1)
685            goto fail;
686        if (ctx->early_clean) {
687            OPENSSL_cleanse(ctx->pwd, ctx->pwdlen);
688            ctx->pwdlen = 0;
689        }
690    }
691
692    store32((uint8_t *) &value, ctx->saltlen);
693
694    if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)
695        goto fail;
696
697    if (ctx->salt != NULL)
698        if (EVP_DigestUpdate(mdctx, ctx->salt, ctx->saltlen) != 1)
699            goto fail;
700
701    store32((uint8_t *) &value, ctx->secretlen);
702    if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)
703        goto fail;
704
705    if (ctx->secret != NULL) {
706        if (EVP_DigestUpdate(mdctx, ctx->secret, ctx->secretlen) != 1)
707            goto fail;
708        if (ctx->early_clean) {
709            OPENSSL_cleanse(ctx->secret, ctx->secretlen);
710            ctx->secretlen = 0;
711        }
712    }
713
714    store32((uint8_t *) &value, ctx->adlen);
715    if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)
716        goto fail;
717
718    if (ctx->ad != NULL)
719        if (EVP_DigestUpdate(mdctx, ctx->ad, ctx->adlen) != 1)
720            goto fail;
721
722    tmp = ARGON2_PREHASH_DIGEST_LENGTH;
723    if (EVP_DigestFinal_ex(mdctx, blockhash, &tmp) != 1)
724        goto fail;
725
726fail:
727    EVP_MD_CTX_destroy(mdctx);
728}
729
730static int initialize(KDF_ARGON2 *ctx)
731{
732    uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
733
734    if (ctx == NULL)
735        return 0;
736
737    if (ctx->memory_blocks * sizeof(BLOCK) / sizeof(BLOCK) != ctx->memory_blocks)
738        return 0;
739
740    if (ctx->type != ARGON2_D)
741        ctx->memory = OPENSSL_secure_calloc(ctx->memory_blocks, sizeof(BLOCK));
742    else
743        ctx->memory = OPENSSL_calloc(ctx->memory_blocks, sizeof(BLOCK));
744
745    if (ctx->memory == NULL) {
746        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE,
747                       "cannot allocate required memory");
748        return 0;
749    }
750
751    initial_hash(blockhash, ctx);
752    OPENSSL_cleanse(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
753                    ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);
754    fill_first_blocks(blockhash, ctx);
755    OPENSSL_cleanse(blockhash, ARGON2_PREHASH_SEED_LENGTH);
756
757    return 1;
758}
759
760static void finalize(const KDF_ARGON2 *ctx, void *out)
761{
762    BLOCK blockhash;
763    uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
764    uint32_t last_block_in_lane;
765    uint32_t l;
766
767    if (ctx == NULL)
768        return;
769
770    copy_block(&blockhash, ctx->memory + ctx->lane_length - 1);
771
772    /* XOR the last blocks */
773    for (l = 1; l < ctx->lanes; ++l) {
774        last_block_in_lane = l * ctx->lane_length + (ctx->lane_length - 1);
775        xor_block(&blockhash, ctx->memory + last_block_in_lane);
776    }
777
778    /* Hash the result */
779    store_block(blockhash_bytes, &blockhash);
780    blake2b_long(ctx->md, ctx->mac, out, ctx->outlen, blockhash_bytes,
781                 ARGON2_BLOCK_SIZE);
782    OPENSSL_cleanse(blockhash.v, ARGON2_BLOCK_SIZE);
783    OPENSSL_cleanse(blockhash_bytes, ARGON2_BLOCK_SIZE);
784
785    if (ctx->type != ARGON2_D)
786        OPENSSL_secure_clear_free(ctx->memory,
787                                  ctx->memory_blocks * sizeof(BLOCK));
788    else
789        OPENSSL_clear_free(ctx->memory,
790                           ctx->memory_blocks * sizeof(BLOCK));
791}
792
793static int blake2b_mac(EVP_MAC *mac, void *out, size_t outlen, const void *in,
794                       size_t inlen, const void *key, size_t keylen)
795{
796    int ret = 0;
797    size_t par_n = 0, out_written;
798    EVP_MAC_CTX *ctx = NULL;
799    OSSL_PARAM par[3];
800
801    if ((ctx = EVP_MAC_CTX_new(mac)) == NULL)
802        goto fail;
803
804    par[par_n++] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
805                                                     (void *) key, keylen);
806    par[par_n++] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &outlen);
807    par[par_n++] = OSSL_PARAM_construct_end();
808
809    ret = EVP_MAC_CTX_set_params(ctx, par) == 1
810        && EVP_MAC_init(ctx, NULL, 0, NULL) == 1
811        && EVP_MAC_update(ctx, in, inlen) == 1
812        && EVP_MAC_final(ctx, out, (size_t *) &out_written, outlen) == 1;
813
814fail:
815    EVP_MAC_CTX_free(ctx);
816    return ret;
817}
818
819static int blake2b_md(EVP_MD *md, void *out, size_t outlen, const void *in,
820                      size_t inlen)
821{
822    int ret = 0;
823    EVP_MD_CTX *ctx = NULL;
824    OSSL_PARAM par[2];
825
826    if ((ctx = EVP_MD_CTX_create()) == NULL)
827        return 0;
828
829    par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen);
830    par[1] = OSSL_PARAM_construct_end();
831
832    ret = EVP_DigestInit_ex2(ctx, md, par) == 1
833        && EVP_DigestUpdate(ctx, in, inlen) == 1
834        && EVP_DigestFinal_ex(ctx, out, NULL) == 1;
835
836    EVP_MD_CTX_free(ctx);
837    return ret;
838}
839
840static int blake2b(EVP_MD *md, EVP_MAC *mac, void *out, size_t outlen,
841                   const void *in, size_t inlen, const void *key, size_t keylen)
842{
843    if (out == NULL || outlen == 0)
844        return 0;
845
846    if (key == NULL || keylen == 0)
847        return blake2b_md(md, out, outlen, in, inlen);
848
849    return blake2b_mac(mac, out, outlen, in, inlen, key, keylen);
850}
851
852static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,
853                        size_t outlen, const void *in, size_t inlen)
854{
855    int ret = 0;
856    EVP_MD_CTX *ctx = NULL;
857    uint32_t outlen_curr;
858    uint8_t outbuf[BLAKE2B_OUTBYTES];
859    uint8_t inbuf[BLAKE2B_OUTBYTES];
860    uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
861    OSSL_PARAM par[2];
862    size_t outlen_md;
863
864    if (out == NULL || outlen == 0)
865        return 0;
866
867    /* Ensure little-endian byte order */
868    store32(outlen_bytes, (uint32_t)outlen);
869
870    if ((ctx = EVP_MD_CTX_create()) == NULL)
871        return 0;
872
873    outlen_md = (outlen <= BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES;
874    par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen_md);
875    par[1] = OSSL_PARAM_construct_end();
876
877    ret = EVP_DigestInit_ex2(ctx, md, par) == 1
878        && EVP_DigestUpdate(ctx, outlen_bytes, sizeof(outlen_bytes)) == 1
879        && EVP_DigestUpdate(ctx, in, inlen) == 1
880        && EVP_DigestFinal_ex(ctx, (outlen > BLAKE2B_OUTBYTES) ? outbuf : out,
881                              NULL) == 1;
882
883    if (ret == 0)
884        goto fail;
885
886    if (outlen > BLAKE2B_OUTBYTES) {
887        memcpy(out, outbuf, BLAKE2B_OUTBYTES / 2);
888        out += BLAKE2B_OUTBYTES / 2;
889        outlen_curr = (uint32_t) outlen - BLAKE2B_OUTBYTES / 2;
890
891        while (outlen_curr > BLAKE2B_OUTBYTES) {
892            memcpy(inbuf, outbuf, BLAKE2B_OUTBYTES);
893            if (blake2b(md, mac, outbuf, BLAKE2B_OUTBYTES, inbuf,
894                        BLAKE2B_OUTBYTES, NULL, 0) != 1)
895                goto fail;
896            memcpy(out, outbuf, BLAKE2B_OUTBYTES / 2);
897            out += BLAKE2B_OUTBYTES / 2;
898            outlen_curr -= BLAKE2B_OUTBYTES / 2;
899        }
900
901        memcpy(inbuf, outbuf, BLAKE2B_OUTBYTES);
902        if (blake2b(md, mac, outbuf, outlen_curr, inbuf, BLAKE2B_OUTBYTES,
903                    NULL, 0) != 1)
904            goto fail;
905        memcpy(out, outbuf, outlen_curr);
906    }
907    ret = 1;
908
909fail:
910    EVP_MD_CTX_free(ctx);
911    return ret;
912}
913
914static void kdf_argon2_init(KDF_ARGON2 *c, ARGON2_TYPE type)
915{
916    OSSL_LIB_CTX *libctx;
917
918    libctx = c->libctx;
919    memset(c, 0, sizeof(*c));
920
921    c->libctx = libctx;
922    c->outlen = ARGON2_DEFAULT_OUTLEN;
923    c->t_cost = ARGON2_DEFAULT_T_COST;
924    c->m_cost = ARGON2_DEFAULT_M_COST;
925    c->lanes = ARGON2_DEFAULT_LANES;
926    c->threads = ARGON2_DEFAULT_THREADS;
927    c->version = ARGON2_DEFAULT_VERSION;
928    c->type = type;
929}
930
931static void *kdf_argon2d_new(void *provctx)
932{
933    KDF_ARGON2 *ctx;
934
935    if (!ossl_prov_is_running())
936        return NULL;
937
938    ctx = OPENSSL_zalloc(sizeof(*ctx));
939    if (ctx == NULL) {
940        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
941        return NULL;
942    }
943
944    ctx->libctx = PROV_LIBCTX_OF(provctx);
945
946    kdf_argon2_init(ctx, ARGON2_D);
947    return ctx;
948}
949
950static void *kdf_argon2i_new(void *provctx)
951{
952    KDF_ARGON2 *ctx;
953
954    if (!ossl_prov_is_running())
955        return NULL;
956
957    ctx = OPENSSL_zalloc(sizeof(*ctx));
958    if (ctx == NULL) {
959        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
960        return NULL;
961    }
962
963    ctx->libctx = PROV_LIBCTX_OF(provctx);
964
965    kdf_argon2_init(ctx, ARGON2_I);
966    return ctx;
967}
968
969static void *kdf_argon2id_new(void *provctx)
970{
971    KDF_ARGON2 *ctx;
972
973    if (!ossl_prov_is_running())
974        return NULL;
975
976    ctx = OPENSSL_zalloc(sizeof(*ctx));
977    if (ctx == NULL) {
978        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
979        return NULL;
980    }
981
982    ctx->libctx = PROV_LIBCTX_OF(provctx);
983
984    kdf_argon2_init(ctx, ARGON2_ID);
985    return ctx;
986}
987
988static void kdf_argon2_free(void *vctx)
989{
990    KDF_ARGON2 *ctx = (KDF_ARGON2 *)vctx;
991
992    if (ctx == NULL)
993        return;
994
995    if (ctx->pwd != NULL)
996        OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);
997
998    if (ctx->salt != NULL)
999        OPENSSL_clear_free(ctx->salt, ctx->saltlen);
1000
1001    if (ctx->secret != NULL)
1002        OPENSSL_clear_free(ctx->secret, ctx->secretlen);
1003
1004    if (ctx->ad != NULL)
1005        OPENSSL_clear_free(ctx->ad, ctx->adlen);
1006
1007    EVP_MD_free(ctx->md);
1008    EVP_MAC_free(ctx->mac);
1009
1010    OPENSSL_free(ctx->propq);
1011
1012    memset(ctx, 0, sizeof(*ctx));
1013
1014    OPENSSL_free(ctx);
1015}
1016
1017static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,
1018                             const OSSL_PARAM params[])
1019{
1020    KDF_ARGON2 *ctx;
1021    uint32_t memory_blocks, segment_length;
1022    OSSL_PARAM *size_param;
1023
1024    ctx = (KDF_ARGON2 *)vctx;
1025
1026    if (!ossl_prov_is_running()
1027            || !argon2_set_ctx_params(vctx, params, &size_param))
1028        return 0;
1029
1030    if (ctx->mac == NULL)
1031        ctx->mac = EVP_MAC_fetch(ctx->libctx, "blake2bmac", ctx->propq);
1032    if (ctx->mac == NULL) {
1033        ERR_raise_data(ERR_LIB_PROV, PROV_R_MISSING_MAC,
1034                       "cannot fetch blake2bmac");
1035        return 0;
1036    }
1037
1038    if (ctx->md == NULL)
1039        ctx->md = EVP_MD_fetch(ctx->libctx, "blake2b512", ctx->propq);
1040    if (ctx->md == NULL) {
1041        ERR_raise_data(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST,
1042                       "cannot fetch blake2b512");
1043        return 0;
1044    }
1045
1046    if (ctx->salt == NULL || ctx->saltlen == 0) {
1047        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
1048        return 0;
1049    }
1050
1051    if (outlen != ctx->outlen) {
1052        /* User set a size that was too short so raise an error */
1053        if (size_param != NULL) {
1054            ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
1055            return 0;
1056        }
1057        if (!kdf_argon2_ctx_set_out_length(ctx, (uint32_t) outlen))
1058            return 0;
1059    }
1060
1061    switch (ctx->type) {
1062    case ARGON2_D:
1063    case ARGON2_I:
1064    case ARGON2_ID:
1065        break;
1066    default:
1067        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MODE, "invalid Argon2 type");
1068        return 0;
1069    }
1070
1071    if (ctx->threads > 1) {
1072# ifdef ARGON2_NO_THREADS
1073        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
1074                       "requested %u threads, single-threaded mode supported only",
1075                       ctx->threads);
1076        return 0;
1077# else
1078        if (ctx->threads > ossl_get_avail_threads(ctx->libctx)) {
1079            ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
1080                           "requested %u threads, available: %u",
1081                           ctx->threads, ossl_get_avail_threads(ctx->libctx));
1082            return 0;
1083        }
1084# endif
1085        if (ctx->threads > ctx->lanes) {
1086            ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
1087                           "requested more threads (%u) than lanes (%u)",
1088                           ctx->threads, ctx->lanes);
1089            return 0;
1090        }
1091    }
1092
1093    if (ctx->m_cost < 8 * ctx->lanes) {
1094        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE,
1095                       "m_cost must be greater or equal than 8 times the number of lanes");
1096        return 0;
1097    }
1098
1099    memory_blocks = ctx->m_cost;
1100    if (memory_blocks < 2 * ARGON2_SYNC_POINTS * ctx->lanes)
1101        memory_blocks = 2 * ARGON2_SYNC_POINTS * ctx->lanes;
1102
1103    /* Ensure that all segments have equal length */
1104    segment_length = memory_blocks / (ctx->lanes * ARGON2_SYNC_POINTS);
1105    memory_blocks = segment_length * (ctx->lanes * ARGON2_SYNC_POINTS);
1106
1107    ctx->memory = NULL;
1108    ctx->memory_blocks = memory_blocks;
1109    ctx->segment_length = segment_length;
1110    ctx->passes = ctx->t_cost;
1111    ctx->lane_length = segment_length * ARGON2_SYNC_POINTS;
1112
1113    if (initialize(ctx) != 1)
1114        return 0;
1115
1116    if (fill_memory_blocks(ctx) != 1)
1117        return 0;
1118
1119    finalize(ctx, out);
1120
1121    return 1;
1122}
1123
1124static void kdf_argon2_reset(void *vctx)
1125{
1126    OSSL_LIB_CTX *libctx;
1127    KDF_ARGON2 *ctx;
1128    ARGON2_TYPE type;
1129
1130    ctx = (KDF_ARGON2 *) vctx;
1131    type = ctx->type;
1132    libctx = ctx->libctx;
1133
1134    EVP_MD_free(ctx->md);
1135    EVP_MAC_free(ctx->mac);
1136
1137    OPENSSL_free(ctx->propq);
1138
1139    if (ctx->pwd != NULL)
1140        OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);
1141
1142    if (ctx->salt != NULL)
1143        OPENSSL_clear_free(ctx->salt, ctx->saltlen);
1144
1145    if (ctx->secret != NULL)
1146        OPENSSL_clear_free(ctx->secret, ctx->secretlen);
1147
1148    if (ctx->ad != NULL)
1149        OPENSSL_clear_free(ctx->ad, ctx->adlen);
1150
1151    memset(ctx, 0, sizeof(*ctx));
1152    ctx->libctx = libctx;
1153    kdf_argon2_init(ctx, type);
1154}
1155
1156static int kdf_argon2_ctx_set_threads(KDF_ARGON2 *ctx, uint32_t threads)
1157{
1158    if (threads < ARGON2_MIN_THREADS) {
1159        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
1160                       "min threads: %u", ARGON2_MIN_THREADS);
1161        return 0;
1162    }
1163
1164    if (threads > ARGON2_MAX_THREADS) {
1165        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
1166                       "max threads: %u", ARGON2_MAX_THREADS);
1167        return 0;
1168    }
1169
1170    ctx->threads = threads;
1171    return 1;
1172}
1173
1174static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes)
1175{
1176    if (lanes > ARGON2_MAX_LANES) {
1177        ERR_raise_data(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER,
1178                       "max lanes: %u", ARGON2_MAX_LANES);
1179        return 0;
1180    }
1181
1182    if (lanes < ARGON2_MIN_LANES) {
1183        ERR_raise_data(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER,
1184                       "min lanes: %u", ARGON2_MIN_LANES);
1185        return 0;
1186    }
1187
1188    ctx->lanes = lanes;
1189    return 1;
1190}
1191
1192static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost)
1193{
1194    /* ARGON2_MAX_MEMORY == max m_cost value, so skip check  */
1195
1196    if (t_cost < ARGON2_MIN_TIME) {
1197        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT,
1198                       "min: %u", ARGON2_MIN_TIME);
1199        return 0;
1200    }
1201
1202    ctx->t_cost = t_cost;
1203    return 1;
1204}
1205
1206static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost)
1207{
1208    /* ARGON2_MAX_MEMORY == max m_cost value, so skip check */
1209
1210    if (m_cost < ARGON2_MIN_MEMORY) {
1211        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE, "min: %u",
1212                       ARGON2_MIN_MEMORY);
1213        return 0;
1214    }
1215
1216    ctx->m_cost = m_cost;
1217    return 1;
1218}
1219
1220static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen)
1221{
1222    /*
1223     * ARGON2_MAX_OUT_LENGTH == max outlen value, so upper bounds checks
1224     * are always satisfied; to suppress compiler if statement tautology
1225     * warnings, these checks are skipped.
1226     */
1227
1228    if (outlen < ARGON2_MIN_OUT_LENGTH) {
1229        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH, "min: %u",
1230                       ARGON2_MIN_OUT_LENGTH);
1231        return 0;
1232    }
1233
1234    ctx->outlen = outlen;
1235    return 1;
1236}
1237
1238static int kdf_argon2_ctx_set_secret(KDF_ARGON2 *ctx, const OSSL_PARAM *p)
1239{
1240    size_t buflen;
1241
1242    if (p->data == NULL)
1243        return 0;
1244
1245    if (ctx->secret != NULL) {
1246        OPENSSL_clear_free(ctx->secret, ctx->secretlen);
1247        ctx->secret = NULL;
1248        ctx->secretlen = 0U;
1249    }
1250
1251    if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->secret, 0, &buflen))
1252        return 0;
1253
1254    if (buflen > ARGON2_MAX_SECRET) {
1255        OPENSSL_free(ctx->secret);
1256        ctx->secret = NULL;
1257        ctx->secretlen = 0U;
1258        return 0;
1259    }
1260
1261    ctx->secretlen = (uint32_t) buflen;
1262    return 1;
1263}
1264
1265static int kdf_argon2_ctx_set_pwd(KDF_ARGON2 *ctx, const OSSL_PARAM *p)
1266{
1267    size_t buflen;
1268
1269    if (p->data == NULL)
1270        return 0;
1271
1272    if (ctx->pwd != NULL) {
1273        OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);
1274        ctx->pwd = NULL;
1275        ctx->pwdlen = 0U;
1276    }
1277
1278    if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pwd, 0, &buflen))
1279        return 0;
1280
1281    if (buflen > ARGON2_MAX_PWD_LENGTH) {
1282        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "max: %u",
1283                       ARGON2_MAX_PWD_LENGTH);
1284        goto fail;
1285    }
1286
1287    ctx->pwdlen = (uint32_t) buflen;
1288    return 1;
1289
1290fail:
1291    OPENSSL_free(ctx->pwd);
1292    ctx->pwd = NULL;
1293    ctx->pwdlen = 0U;
1294    return 0;
1295}
1296
1297static int kdf_argon2_ctx_set_salt(KDF_ARGON2 *ctx, const OSSL_PARAM *p)
1298{
1299    size_t buflen;
1300
1301    if (p->data == NULL)
1302        return 0;
1303
1304    if (ctx->salt != NULL) {
1305        OPENSSL_clear_free(ctx->salt, ctx->saltlen);
1306        ctx->salt = NULL;
1307        ctx->saltlen = 0U;
1308    }
1309
1310    if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0, &buflen))
1311        return 0;
1312
1313    if (buflen < ARGON2_MIN_SALT_LENGTH) {
1314        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "min: %u",
1315                       ARGON2_MIN_SALT_LENGTH);
1316        goto fail;
1317    }
1318
1319    if (buflen > ARGON2_MAX_SALT_LENGTH) {
1320        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "max: %u",
1321                       ARGON2_MAX_SALT_LENGTH);
1322        goto fail;
1323    }
1324
1325    ctx->saltlen = (uint32_t) buflen;
1326    return 1;
1327
1328fail:
1329    OPENSSL_free(ctx->salt);
1330    ctx->salt = NULL;
1331    ctx->saltlen = 0U;
1332    return 0;
1333}
1334
1335static int kdf_argon2_ctx_set_ad(KDF_ARGON2 *ctx, const OSSL_PARAM *p)
1336{
1337    size_t buflen;
1338
1339    if (p->data == NULL)
1340        return 0;
1341
1342    if (ctx->ad != NULL) {
1343        OPENSSL_clear_free(ctx->ad, ctx->adlen);
1344        ctx->ad = NULL;
1345        ctx->adlen = 0U;
1346    }
1347
1348    if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->ad, 0, &buflen))
1349        return 0;
1350
1351    if (buflen > ARGON2_MAX_AD_LENGTH) {
1352        OPENSSL_free(ctx->ad);
1353        ctx->ad = NULL;
1354        ctx->adlen = 0U;
1355        return 0;
1356    }
1357
1358    ctx->adlen = (uint32_t) buflen;
1359    return 1;
1360}
1361
1362static void kdf_argon2_ctx_set_flag_early_clean(KDF_ARGON2 *ctx, uint32_t f)
1363{
1364    ctx->early_clean = !!(f);
1365}
1366
1367static int kdf_argon2_ctx_set_version(KDF_ARGON2 *ctx, uint32_t version)
1368{
1369    switch (version) {
1370    case ARGON2_VERSION_10:
1371    case ARGON2_VERSION_13:
1372        ctx->version = version;
1373        return 1;
1374    default:
1375        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MODE,
1376                       "invalid Argon2 version");
1377        return 0;
1378    }
1379}
1380
1381static int set_property_query(KDF_ARGON2 *ctx, const char *propq)
1382{
1383    OPENSSL_free(ctx->propq);
1384    ctx->propq = NULL;
1385    if (propq != NULL) {
1386        ctx->propq = OPENSSL_strdup(propq);
1387        if (ctx->propq == NULL)
1388            return 0;
1389    }
1390    EVP_MD_free(ctx->md);
1391    ctx->md = NULL;
1392    EVP_MAC_free(ctx->mac);
1393    ctx->mac = NULL;
1394    return 1;
1395}
1396
1397{- produce_param_decoder('argon2_set_ctx_params',
1398                         (['KDF_PARAM_PASSWORD',       'pw',     'octet_string'],
1399                          ['KDF_PARAM_SALT',           'salt',   'octet_string'],
1400                          ['KDF_PARAM_SECRET',         'secret', 'octet_string'],
1401                          ['KDF_PARAM_ARGON2_AD',      'ad',     'octet_string'],
1402                          ['KDF_PARAM_SIZE',           'size',   'uint32'],
1403                          ['KDF_PARAM_ITER',           'iter',   'uint32'],
1404                          ['KDF_PARAM_THREADS',        'thrds',  'uint32'],
1405                          ['KDF_PARAM_ARGON2_LANES',   'lanes',  'uint32'],
1406                          ['KDF_PARAM_ARGON2_MEMCOST', 'mem',    'uint32'],
1407                          ['KDF_PARAM_EARLY_CLEAN',    'eclean', 'uint32'],
1408                          ['KDF_PARAM_ARGON2_VERSION', 'vers',   'uint32'],
1409                          ['KDF_PARAM_PROPERTIES',     'propq',  'utf8_string'],
1410                         )); -}
1411
1412static int argon2_set_ctx_params(KDF_ARGON2 *ctx, const OSSL_PARAM params[],
1413                                 OSSL_PARAM **size_param_ptr)
1414{
1415    struct argon2_set_ctx_params_st p;
1416    uint32_t u32_value;
1417
1418    if (ctx == NULL || !argon2_set_ctx_params_decoder(params, &p))
1419        return 0;
1420
1421    if (p.pw != NULL && !kdf_argon2_ctx_set_pwd(ctx, p.pw))
1422        return 0;
1423
1424    if (p.salt != NULL && !kdf_argon2_ctx_set_salt(ctx, p.salt))
1425        return 0;
1426
1427    if (p.secret != NULL && !kdf_argon2_ctx_set_secret(ctx, p.secret))
1428        return 0;
1429
1430    if (p.ad != NULL && !kdf_argon2_ctx_set_ad(ctx, p.ad))
1431        return 0;
1432
1433    if ((*size_param_ptr = p.size) != NULL) {
1434        if (!OSSL_PARAM_get_uint32(p.size, &u32_value))
1435            return 0;
1436        if (!kdf_argon2_ctx_set_out_length(ctx, u32_value))
1437            return 0;
1438    }
1439
1440    if (p.iter != NULL) {
1441        if (!OSSL_PARAM_get_uint32(p.iter, &u32_value))
1442            return 0;
1443        if (!kdf_argon2_ctx_set_t_cost(ctx, u32_value))
1444            return 0;
1445    }
1446
1447    if (p.thrds != NULL) {
1448        if (!OSSL_PARAM_get_uint32(p.thrds, &u32_value))
1449            return 0;
1450        if (!kdf_argon2_ctx_set_threads(ctx, u32_value))
1451            return 0;
1452    }
1453
1454    if (p.lanes != NULL) {
1455        if (!OSSL_PARAM_get_uint32(p.lanes, &u32_value))
1456            return 0;
1457        if (!kdf_argon2_ctx_set_lanes(ctx, u32_value))
1458            return 0;
1459    }
1460
1461    if (p.mem != NULL) {
1462        if (!OSSL_PARAM_get_uint32(p.mem, &u32_value))
1463            return 0;
1464        if (!kdf_argon2_ctx_set_m_cost(ctx, u32_value))
1465            return 0;
1466    }
1467
1468    if (p.eclean != NULL) {
1469        if (!OSSL_PARAM_get_uint32(p.eclean, &u32_value))
1470            return 0;
1471        kdf_argon2_ctx_set_flag_early_clean(ctx, u32_value);
1472    }
1473
1474    if (p.vers != NULL) {
1475        if (!OSSL_PARAM_get_uint32(p.vers, &u32_value))
1476            return 0;
1477        if (!kdf_argon2_ctx_set_version(ctx, u32_value))
1478            return 0;
1479    }
1480
1481    if (p.propq != NULL) {
1482        if (p.propq->data_type != OSSL_PARAM_UTF8_STRING
1483            || !set_property_query(ctx, p.propq->data))
1484            return 0;
1485    }
1486
1487    return 1;
1488}
1489
1490static int kdf_argon2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
1491{
1492    KDF_ARGON2 *ctx = (KDF_ARGON2 *) vctx;
1493    OSSL_PARAM *size_param;
1494
1495    return argon2_set_ctx_params(ctx, params, &size_param);
1496}
1497
1498static const OSSL_PARAM *kdf_argon2_settable_ctx_params(ossl_unused void *ctx,
1499                                                        ossl_unused void *p_ctx)
1500{
1501    return argon2_set_ctx_params_list;
1502}
1503
1504{- produce_param_decoder('argon2_get_ctx_params',
1505                         (['KDF_PARAM_SIZE',                    'size', 'size_t'],
1506                         )); -}
1507
1508static int kdf_argon2_get_ctx_params(void *vctx, OSSL_PARAM params[])
1509{
1510    struct argon2_get_ctx_params_st p;
1511    KDF_ARGON2 *ctx = (KDF_ARGON2 *) vctx;
1512
1513    if (ctx == NULL || !argon2_get_ctx_params_decoder(params, &p))
1514        return 0;
1515
1516    if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, SIZE_MAX))
1517        return 0;
1518
1519    return -2;
1520}
1521
1522static const OSSL_PARAM *kdf_argon2_gettable_ctx_params(ossl_unused void *ctx,
1523                                                        ossl_unused void *p_ctx)
1524{
1525    return argon2_get_ctx_params_list;
1526}
1527
1528const OSSL_DISPATCH ossl_kdf_argon2i_functions[] = {
1529    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2i_new },
1530    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },
1531    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },
1532    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },
1533    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
1534      (void(*)(void))kdf_argon2_settable_ctx_params },
1535    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },
1536    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
1537      (void(*)(void))kdf_argon2_gettable_ctx_params },
1538    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },
1539    OSSL_DISPATCH_END
1540};
1541
1542const OSSL_DISPATCH ossl_kdf_argon2d_functions[] = {
1543    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2d_new },
1544    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },
1545    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },
1546    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },
1547    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
1548      (void(*)(void))kdf_argon2_settable_ctx_params },
1549    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },
1550    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
1551      (void(*)(void))kdf_argon2_gettable_ctx_params },
1552    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },
1553    OSSL_DISPATCH_END
1554};
1555
1556const OSSL_DISPATCH ossl_kdf_argon2id_functions[] = {
1557    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2id_new },
1558    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },
1559    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },
1560    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },
1561    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
1562      (void(*)(void))kdf_argon2_settable_ctx_params },
1563    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },
1564    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
1565      (void(*)(void))kdf_argon2_gettable_ctx_params },
1566    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },
1567    OSSL_DISPATCH_END
1568};
1569
1570#endif
1571