123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560 |
- /*
- * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- *
- * RFC 9106 Argon2 (see https://www.rfc-editor.org/rfc/rfc9106.txt)
- *
- */
- #include <stdlib.h>
- #include <stddef.h>
- #include <stdarg.h>
- #include <string.h>
- #include <openssl/e_os2.h>
- #include <openssl/evp.h>
- #include <openssl/objects.h>
- #include <openssl/crypto.h>
- #include <openssl/kdf.h>
- #include <openssl/err.h>
- #include <openssl/core_names.h>
- #include <openssl/params.h>
- #include <openssl/thread.h>
- #include <openssl/proverr.h>
- #include "internal/thread.h"
- #include "internal/numbers.h"
- #include "internal/endian.h"
- #include "crypto/evp.h"
- #include "prov/implementations.h"
- #include "prov/provider_ctx.h"
- #include "prov/providercommon.h"
- #include "prov/blake2.h"
- #if defined(OPENSSL_NO_DEFAULT_THREAD_POOL) && defined(OPENSSL_NO_THREAD_POOL)
- # define ARGON2_NO_THREADS
- #endif
- #if !defined(OPENSSL_THREADS)
- # define ARGON2_NO_THREADS
- #endif
- #ifndef OPENSSL_NO_ARGON2
- # define ARGON2_MIN_LANES 1u
- # define ARGON2_MAX_LANES 0xFFFFFFu
- # define ARGON2_MIN_THREADS 1u
- # define ARGON2_MAX_THREADS 0xFFFFFFu
- # define ARGON2_SYNC_POINTS 4u
- # define ARGON2_MIN_OUT_LENGTH 4u
- # define ARGON2_MAX_OUT_LENGTH 0xFFFFFFFFu
- # define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS)
- # define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
- # define ARGON2_MAX_MEMORY 0xFFFFFFFFu
- # define ARGON2_MIN_TIME 1u
- # define ARGON2_MAX_TIME 0xFFFFFFFFu
- # define ARGON2_MIN_PWD_LENGTH 0u
- # define ARGON2_MAX_PWD_LENGTH 0xFFFFFFFFu
- # define ARGON2_MIN_AD_LENGTH 0u
- # define ARGON2_MAX_AD_LENGTH 0xFFFFFFFFu
- # define ARGON2_MIN_SALT_LENGTH 8u
- # define ARGON2_MAX_SALT_LENGTH 0xFFFFFFFFu
- # define ARGON2_MIN_SECRET 0u
- # define ARGON2_MAX_SECRET 0xFFFFFFFFu
- # define ARGON2_BLOCK_SIZE 1024
- # define ARGON2_QWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 8)
- # define ARGON2_OWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 16)
- # define ARGON2_HWORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 32)
- # define ARGON2_512BIT_WORDS_IN_BLOCK ((ARGON2_BLOCK_SIZE) / 64)
- # define ARGON2_ADDRESSES_IN_BLOCK 128
- # define ARGON2_PREHASH_DIGEST_LENGTH 64
- # define ARGON2_PREHASH_SEED_LENGTH \
- (ARGON2_PREHASH_DIGEST_LENGTH + (2 * sizeof(uint32_t)))
- # define ARGON2_DEFAULT_OUTLEN 64u
- # define ARGON2_DEFAULT_T_COST 3u
- # define ARGON2_DEFAULT_M_COST ARGON2_MIN_MEMORY
- # define ARGON2_DEFAULT_LANES 1u
- # define ARGON2_DEFAULT_THREADS 1u
- # define ARGON2_DEFAULT_VERSION ARGON2_VERSION_NUMBER
- # undef G
- # define G(a, b, c, d) \
- do { \
- a = a + b + 2 * mul_lower(a, b); \
- d = rotr64(d ^ a, 32); \
- c = c + d + 2 * mul_lower(c, d); \
- b = rotr64(b ^ c, 24); \
- a = a + b + 2 * mul_lower(a, b); \
- d = rotr64(d ^ a, 16); \
- c = c + d + 2 * mul_lower(c, d); \
- b = rotr64(b ^ c, 63); \
- } while ((void)0, 0)
- # undef PERMUTATION_P
- # define PERMUTATION_P(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
- v12, v13, v14, v15) \
- do { \
- G(v0, v4, v8, v12); \
- G(v1, v5, v9, v13); \
- G(v2, v6, v10, v14); \
- G(v3, v7, v11, v15); \
- G(v0, v5, v10, v15); \
- G(v1, v6, v11, v12); \
- G(v2, v7, v8, v13); \
- G(v3, v4, v9, v14); \
- } while ((void)0, 0)
- # undef PERMUTATION_P_COLUMN
- # define PERMUTATION_P_COLUMN(x, i) \
- do { \
- uint64_t *base = &x[16 * i]; \
- PERMUTATION_P( \
- *base, *(base + 1), *(base + 2), *(base + 3), \
- *(base + 4), *(base + 5), *(base + 6), *(base + 7), \
- *(base + 8), *(base + 9), *(base + 10), *(base + 11), \
- *(base + 12), *(base + 13), *(base + 14), *(base + 15) \
- ); \
- } while ((void)0, 0)
- # undef PERMUTATION_P_ROW
- # define PERMUTATION_P_ROW(x, i) \
- do { \
- uint64_t *base = &x[2 * i]; \
- PERMUTATION_P( \
- *base, *(base + 1), *(base + 16), *(base + 17), \
- *(base + 32), *(base + 33), *(base + 48), *(base + 49), \
- *(base + 64), *(base + 65), *(base + 80), *(base + 81), \
- *(base + 96), *(base + 97), *(base + 112), *(base + 113) \
- ); \
- } while ((void)0, 0)
- typedef struct {
- uint64_t v[ARGON2_QWORDS_IN_BLOCK];
- } BLOCK;
- typedef enum {
- ARGON2_VERSION_10 = 0x10,
- ARGON2_VERSION_13 = 0x13,
- ARGON2_VERSION_NUMBER = ARGON2_VERSION_13
- } ARGON2_VERSION;
- typedef enum {
- ARGON2_D = 0,
- ARGON2_I = 1,
- ARGON2_ID = 2
- } ARGON2_TYPE;
- typedef struct {
- uint32_t pass;
- uint32_t lane;
- uint8_t slice;
- uint32_t index;
- } ARGON2_POS;
- typedef struct {
- void *provctx;
- uint32_t outlen;
- uint8_t *pwd;
- uint32_t pwdlen;
- uint8_t *salt;
- uint32_t saltlen;
- uint8_t *secret;
- uint32_t secretlen;
- uint8_t *ad;
- uint32_t adlen;
- uint32_t t_cost;
- uint32_t m_cost;
- uint32_t lanes;
- uint32_t threads;
- uint32_t version;
- uint32_t early_clean;
- ARGON2_TYPE type;
- BLOCK *memory;
- uint32_t passes;
- uint32_t memory_blocks;
- uint32_t segment_length;
- uint32_t lane_length;
- OSSL_LIB_CTX *libctx;
- EVP_MD *md;
- EVP_MAC *mac;
- char *propq;
- } KDF_ARGON2;
- typedef struct {
- ARGON2_POS pos;
- KDF_ARGON2 *ctx;
- } ARGON2_THREAD_DATA;
- static OSSL_FUNC_kdf_newctx_fn kdf_argon2i_new;
- static OSSL_FUNC_kdf_newctx_fn kdf_argon2d_new;
- static OSSL_FUNC_kdf_newctx_fn kdf_argon2id_new;
- static OSSL_FUNC_kdf_freectx_fn kdf_argon2_free;
- static OSSL_FUNC_kdf_reset_fn kdf_argon2_reset;
- static OSSL_FUNC_kdf_derive_fn kdf_argon2_derive;
- static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_argon2_settable_ctx_params;
- static OSSL_FUNC_kdf_set_ctx_params_fn kdf_argon2_set_ctx_params;
- static void kdf_argon2_init(KDF_ARGON2 *ctx, ARGON2_TYPE t);
- static void *kdf_argon2d_new(void *provctx);
- static void *kdf_argon2i_new(void *provctx);
- static void *kdf_argon2id_new(void *provctx);
- static void kdf_argon2_free(void *vctx);
- static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,
- const OSSL_PARAM params[]);
- static void kdf_argon2_reset(void *vctx);
- static int kdf_argon2_ctx_set_threads(KDF_ARGON2 *ctx, uint32_t threads);
- static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes);
- static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost);
- static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost);
- static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen);
- static int kdf_argon2_ctx_set_secret(KDF_ARGON2 *ctx, const OSSL_PARAM *p);
- static int kdf_argon2_ctx_set_pwd(KDF_ARGON2 *ctx, const OSSL_PARAM *p);
- static int kdf_argon2_ctx_set_salt(KDF_ARGON2 *ctx, const OSSL_PARAM *p);
- static int kdf_argon2_ctx_set_ad(KDF_ARGON2 *ctx, const OSSL_PARAM *p);
- static int kdf_argon2_set_ctx_params(void *vctx, const OSSL_PARAM params[]);
- static int kdf_argon2_get_ctx_params(void *vctx, OSSL_PARAM params[]);
- static int kdf_argon2_ctx_set_version(KDF_ARGON2 *ctx, uint32_t version);
- static const OSSL_PARAM *kdf_argon2_settable_ctx_params(ossl_unused void *ctx,
- ossl_unused void *p_ctx);
- static const OSSL_PARAM *kdf_argon2_gettable_ctx_params(ossl_unused void *ctx,
- ossl_unused void *p_ctx);
- static ossl_inline uint64_t load64(const uint8_t *src);
- static ossl_inline void store32(uint8_t *dst, uint32_t w);
- static ossl_inline void store64(uint8_t *dst, uint64_t w);
- static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c);
- static ossl_inline uint64_t mul_lower(uint64_t x, uint64_t y);
- static void init_block_value(BLOCK *b, uint8_t in);
- static void copy_block(BLOCK *dst, const BLOCK *src);
- static void xor_block(BLOCK *dst, const BLOCK *src);
- static void load_block(BLOCK *dst, const void *input);
- static void store_block(void *output, const BLOCK *src);
- static void fill_first_blocks(uint8_t *blockhash, const KDF_ARGON2 *ctx);
- static void fill_block(const BLOCK *prev, const BLOCK *ref, BLOCK *next,
- int with_xor);
- static void next_addresses(BLOCK *address_block, BLOCK *input_block,
- const BLOCK *zero_block);
- static int data_indep_addressing(const KDF_ARGON2 *ctx, uint32_t pass,
- uint8_t slice);
- static uint32_t index_alpha(const KDF_ARGON2 *ctx, uint32_t pass,
- uint8_t slice, uint32_t index,
- uint32_t pseudo_rand, int same_lane);
- static void fill_segment(const KDF_ARGON2 *ctx, uint32_t pass, uint32_t lane,
- uint8_t slice);
- # if !defined(ARGON2_NO_THREADS)
- static uint32_t fill_segment_thr(void *thread_data);
- static int fill_mem_blocks_mt(KDF_ARGON2 *ctx);
- # endif
- static int fill_mem_blocks_st(KDF_ARGON2 *ctx);
- static ossl_inline int fill_memory_blocks(KDF_ARGON2 *ctx);
- static void initial_hash(uint8_t *blockhash, KDF_ARGON2 *ctx);
- static int initialize(KDF_ARGON2 *ctx);
- static void finalize(const KDF_ARGON2 *ctx, void *out);
- static int blake2b(EVP_MD *md, EVP_MAC *mac, void *out, size_t outlen,
- const void *in, size_t inlen, const void *key,
- size_t keylen);
- static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,
- size_t outlen, const void *in, size_t inlen);
- static ossl_inline uint64_t load64(const uint8_t *src)
- {
- return
- (((uint64_t)src[0]) << 0)
- | (((uint64_t)src[1]) << 8)
- | (((uint64_t)src[2]) << 16)
- | (((uint64_t)src[3]) << 24)
- | (((uint64_t)src[4]) << 32)
- | (((uint64_t)src[5]) << 40)
- | (((uint64_t)src[6]) << 48)
- | (((uint64_t)src[7]) << 56);
- }
- static ossl_inline void store32(uint8_t *dst, uint32_t w)
- {
- dst[0] = (uint8_t)(w >> 0);
- dst[1] = (uint8_t)(w >> 8);
- dst[2] = (uint8_t)(w >> 16);
- dst[3] = (uint8_t)(w >> 24);
- }
- static ossl_inline void store64(uint8_t *dst, uint64_t w)
- {
- dst[0] = (uint8_t)(w >> 0);
- dst[1] = (uint8_t)(w >> 8);
- dst[2] = (uint8_t)(w >> 16);
- dst[3] = (uint8_t)(w >> 24);
- dst[4] = (uint8_t)(w >> 32);
- dst[5] = (uint8_t)(w >> 40);
- dst[6] = (uint8_t)(w >> 48);
- dst[7] = (uint8_t)(w >> 56);
- }
- static ossl_inline uint64_t rotr64(const uint64_t w, const unsigned int c)
- {
- return (w >> c) | (w << (64 - c));
- }
- static ossl_inline uint64_t mul_lower(uint64_t x, uint64_t y)
- {
- const uint64_t m = 0xFFFFFFFFUL;
- return (x & m) * (y & m);
- }
- static void init_block_value(BLOCK *b, uint8_t in)
- {
- memset(b->v, in, sizeof(b->v));
- }
- static void copy_block(BLOCK *dst, const BLOCK *src)
- {
- memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
- }
- static void xor_block(BLOCK *dst, const BLOCK *src)
- {
- int i;
- for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)
- dst->v[i] ^= src->v[i];
- }
- static void load_block(BLOCK *dst, const void *input)
- {
- unsigned i;
- for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)
- dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
- }
- static void store_block(void *output, const BLOCK *src)
- {
- unsigned i;
- for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i)
- store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
- }
- static void fill_first_blocks(uint8_t *blockhash, const KDF_ARGON2 *ctx)
- {
- uint32_t l;
- uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
- /*
- * Make the first and second block in each lane as G(H0||0||i)
- * or G(H0||1||i).
- */
- for (l = 0; l < ctx->lanes; ++l) {
- store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
- store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
- blake2b_long(ctx->md, ctx->mac, blockhash_bytes, ARGON2_BLOCK_SIZE,
- blockhash, ARGON2_PREHASH_SEED_LENGTH);
- load_block(&ctx->memory[l * ctx->lane_length + 0],
- blockhash_bytes);
- store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
- blake2b_long(ctx->md, ctx->mac, blockhash_bytes, ARGON2_BLOCK_SIZE,
- blockhash, ARGON2_PREHASH_SEED_LENGTH);
- load_block(&ctx->memory[l * ctx->lane_length + 1],
- blockhash_bytes);
- }
- OPENSSL_cleanse(blockhash_bytes, ARGON2_BLOCK_SIZE);
- }
- static void fill_block(const BLOCK *prev, const BLOCK *ref,
- BLOCK *next, int with_xor)
- {
- BLOCK blockR, tmp;
- unsigned i;
- copy_block(&blockR, ref);
- xor_block(&blockR, prev);
- copy_block(&tmp, &blockR);
- if (with_xor)
- xor_block(&tmp, next);
- for (i = 0; i < 8; ++i)
- PERMUTATION_P_COLUMN(blockR.v, i);
- for (i = 0; i < 8; ++i)
- PERMUTATION_P_ROW(blockR.v, i);
- copy_block(next, &tmp);
- xor_block(next, &blockR);
- }
- static void next_addresses(BLOCK *address_block, BLOCK *input_block,
- const BLOCK *zero_block)
- {
- input_block->v[6]++;
- fill_block(zero_block, input_block, address_block, 0);
- fill_block(zero_block, address_block, address_block, 0);
- }
- static int data_indep_addressing(const KDF_ARGON2 *ctx, uint32_t pass,
- uint8_t slice)
- {
- switch (ctx->type) {
- case ARGON2_I:
- return 1;
- case ARGON2_ID:
- return (pass == 0) && (slice < ARGON2_SYNC_POINTS / 2);
- case ARGON2_D:
- default:
- return 0;
- }
- }
- /*
- * Pass 0 (pass = 0):
- * This lane: all already finished segments plus already constructed blocks
- * in this segment
- * Other lanes: all already finished segments
- *
- * Pass 1+:
- * This lane: (SYNC_POINTS - 1) last segments plus already constructed
- * blocks in this segment
- * Other lanes: (SYNC_POINTS - 1) last segments
- */
- static uint32_t index_alpha(const KDF_ARGON2 *ctx, uint32_t pass,
- uint8_t slice, uint32_t index,
- uint32_t pseudo_rand, int same_lane)
- {
- uint32_t ref_area_sz;
- uint64_t rel_pos;
- uint32_t start_pos, abs_pos;
- start_pos = 0;
- switch (pass) {
- case 0:
- if (slice == 0)
- ref_area_sz = index - 1;
- else if (same_lane)
- ref_area_sz = slice * ctx->segment_length + index - 1;
- else
- ref_area_sz = slice * ctx->segment_length +
- ((index == 0) ? (-1) : 0);
- break;
- default:
- if (same_lane)
- ref_area_sz = ctx->lane_length - ctx->segment_length + index - 1;
- else
- ref_area_sz = ctx->lane_length - ctx->segment_length +
- ((index == 0) ? (-1) : 0);
- if (slice != ARGON2_SYNC_POINTS - 1)
- start_pos = (slice + 1) * ctx->segment_length;
- break;
- }
- rel_pos = pseudo_rand;
- rel_pos = rel_pos * rel_pos >> 32;
- rel_pos = ref_area_sz - 1 - (ref_area_sz * rel_pos >> 32);
- abs_pos = (start_pos + rel_pos) % ctx->lane_length;
- return abs_pos;
- }
- static void fill_segment(const KDF_ARGON2 *ctx, uint32_t pass, uint32_t lane,
- uint8_t slice)
- {
- BLOCK *ref_block = NULL, *curr_block = NULL;
- BLOCK address_block, input_block, zero_block;
- uint64_t rnd, ref_index, ref_lane;
- uint32_t prev_offset;
- uint32_t start_idx;
- uint32_t j;
- uint32_t curr_offset; /* Offset of the current block */
- memset(&input_block, 0, sizeof(BLOCK));
- if (ctx == NULL)
- return;
- if (data_indep_addressing(ctx, pass, slice)) {
- init_block_value(&zero_block, 0);
- init_block_value(&input_block, 0);
- input_block.v[0] = pass;
- input_block.v[1] = lane;
- input_block.v[2] = slice;
- input_block.v[3] = ctx->memory_blocks;
- input_block.v[4] = ctx->passes;
- input_block.v[5] = ctx->type;
- }
- start_idx = 0;
- /* We've generated the first two blocks. Generate the 1st block of addrs. */
- if ((pass == 0) && (slice == 0)) {
- start_idx = 2;
- if (data_indep_addressing(ctx, pass, slice))
- next_addresses(&address_block, &input_block, &zero_block);
- }
- curr_offset = lane * ctx->lane_length + slice * ctx->segment_length
- + start_idx;
- if ((curr_offset % ctx->lane_length) == 0)
- prev_offset = curr_offset + ctx->lane_length - 1;
- else
- prev_offset = curr_offset - 1;
- for (j = start_idx; j < ctx->segment_length; ++j, ++curr_offset, ++prev_offset) {
- if (curr_offset % ctx->lane_length == 1)
- prev_offset = curr_offset - 1;
- /* Taking pseudo-random value from the previous block. */
- if (data_indep_addressing(ctx, pass, slice)) {
- if (j % ARGON2_ADDRESSES_IN_BLOCK == 0)
- next_addresses(&address_block, &input_block, &zero_block);
- rnd = address_block.v[j % ARGON2_ADDRESSES_IN_BLOCK];
- } else {
- rnd = ctx->memory[prev_offset].v[0];
- }
- /* Computing the lane of the reference block */
- ref_lane = ((rnd >> 32)) % ctx->lanes;
- /* Can not reference other lanes yet */
- if ((pass == 0) && (slice == 0))
- ref_lane = lane;
- /* Computing the number of possible reference block within the lane. */
- ref_index = index_alpha(ctx, pass, slice, j, rnd & 0xFFFFFFFF,
- ref_lane == lane);
- /* Creating a new block */
- ref_block = ctx->memory + ctx->lane_length * ref_lane + ref_index;
- curr_block = ctx->memory + curr_offset;
- if (ARGON2_VERSION_10 == ctx->version) {
- /* Version 1.2.1 and earlier: overwrite, not XOR */
- fill_block(ctx->memory + prev_offset, ref_block, curr_block, 0);
- continue;
- }
- fill_block(ctx->memory + prev_offset, ref_block, curr_block,
- pass == 0 ? 0 : 1);
- }
- }
- # if !defined(ARGON2_NO_THREADS)
- static uint32_t fill_segment_thr(void *thread_data)
- {
- ARGON2_THREAD_DATA *my_data;
- my_data = (ARGON2_THREAD_DATA *) thread_data;
- fill_segment(my_data->ctx, my_data->pos.pass, my_data->pos.lane,
- my_data->pos.slice);
- return 0;
- }
- static int fill_mem_blocks_mt(KDF_ARGON2 *ctx)
- {
- uint32_t r, s, l, ll;
- void **t;
- ARGON2_THREAD_DATA *t_data;
- t = OPENSSL_zalloc(sizeof(void *)*ctx->lanes);
- t_data = OPENSSL_zalloc(ctx->lanes * sizeof(ARGON2_THREAD_DATA));
- if (t == NULL || t_data == NULL)
- goto fail;
- for (r = 0; r < ctx->passes; ++r) {
- for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
- for (l = 0; l < ctx->lanes; ++l) {
- ARGON2_POS p;
- if (l >= ctx->threads) {
- if (ossl_crypto_thread_join(t[l - ctx->threads], NULL) == 0)
- goto fail;
- if (ossl_crypto_thread_clean(t[l - ctx->threads]) == 0)
- goto fail;
- t[l] = NULL;
- }
- p.pass = r;
- p.lane = l;
- p.slice = (uint8_t)s;
- p.index = 0;
- t_data[l].ctx = ctx;
- memcpy(&(t_data[l].pos), &p, sizeof(ARGON2_POS));
- t[l] = ossl_crypto_thread_start(ctx->libctx, &fill_segment_thr,
- (void *) &t_data[l]);
- if (t[l] == NULL) {
- for (ll = 0; ll < l; ++ll) {
- if (ossl_crypto_thread_join(t[ll], NULL) == 0)
- goto fail;
- if (ossl_crypto_thread_clean(t[ll]) == 0)
- goto fail;
- t[ll] = NULL;
- }
- goto fail;
- }
- }
- for (l = ctx->lanes - ctx->threads; l < ctx->lanes; ++l) {
- if (ossl_crypto_thread_join(t[l], NULL) == 0)
- goto fail;
- if (ossl_crypto_thread_clean(t[l]) == 0)
- goto fail;
- t[l] = NULL;
- }
- }
- }
- OPENSSL_free(t_data);
- OPENSSL_free(t);
- return 1;
- fail:
- if (t_data != NULL)
- OPENSSL_free(t_data);
- if (t != NULL)
- OPENSSL_free(t);
- return 0;
- }
- # endif /* !defined(ARGON2_NO_THREADS) */
- static int fill_mem_blocks_st(KDF_ARGON2 *ctx)
- {
- uint32_t r, s, l;
- for (r = 0; r < ctx->passes; ++r)
- for (s = 0; s < ARGON2_SYNC_POINTS; ++s)
- for (l = 0; l < ctx->lanes; ++l)
- fill_segment(ctx, r, l, s);
- return 1;
- }
- static ossl_inline int fill_memory_blocks(KDF_ARGON2 *ctx)
- {
- # if !defined(ARGON2_NO_THREADS)
- return ctx->threads == 1 ? fill_mem_blocks_st(ctx) : fill_mem_blocks_mt(ctx);
- # else
- return ctx->threads == 1 ? fill_mem_blocks_st(ctx) : 0;
- # endif
- }
- static void initial_hash(uint8_t *blockhash, KDF_ARGON2 *ctx)
- {
- EVP_MD_CTX *mdctx;
- uint8_t value[sizeof(uint32_t)];
- unsigned int tmp;
- uint32_t args[7];
- if (ctx == NULL || blockhash == NULL)
- return;
- args[0] = ctx->lanes;
- args[1] = ctx->outlen;
- args[2] = ctx->m_cost;
- args[3] = ctx->t_cost;
- args[4] = ctx->version;
- args[5] = (uint32_t) ctx->type;
- args[6] = ctx->pwdlen;
- mdctx = EVP_MD_CTX_create();
- if (mdctx == NULL || EVP_DigestInit_ex(mdctx, ctx->md, NULL) != 1)
- goto fail;
- for (tmp = 0; tmp < sizeof(args) / sizeof(uint32_t); ++tmp) {
- store32((uint8_t *) &value, args[tmp]);
- if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)
- goto fail;
- }
- if (ctx->pwd != NULL) {
- if (EVP_DigestUpdate(mdctx, ctx->pwd, ctx->pwdlen) != 1)
- goto fail;
- if (ctx->early_clean) {
- OPENSSL_cleanse(ctx->pwd, ctx->pwdlen);
- ctx->pwdlen = 0;
- }
- }
- store32((uint8_t *) &value, ctx->saltlen);
- if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)
- goto fail;
- if (ctx->salt != NULL)
- if (EVP_DigestUpdate(mdctx, ctx->salt, ctx->saltlen) != 1)
- goto fail;
- store32((uint8_t *) &value, ctx->secretlen);
- if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)
- goto fail;
- if (ctx->secret != NULL) {
- if (EVP_DigestUpdate(mdctx, ctx->secret, ctx->secretlen) != 1)
- goto fail;
- if (ctx->early_clean) {
- OPENSSL_cleanse(ctx->secret, ctx->secretlen);
- ctx->secretlen = 0;
- }
- }
- store32((uint8_t *) &value, ctx->adlen);
- if (EVP_DigestUpdate(mdctx, &value, sizeof(value)) != 1)
- goto fail;
- if (ctx->ad != NULL)
- if (EVP_DigestUpdate(mdctx, ctx->ad, ctx->adlen) != 1)
- goto fail;
- tmp = ARGON2_PREHASH_DIGEST_LENGTH;
- if (EVP_DigestFinal_ex(mdctx, blockhash, &tmp) != 1)
- goto fail;
- fail:
- EVP_MD_CTX_destroy(mdctx);
- }
- static int initialize(KDF_ARGON2 *ctx)
- {
- uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
- if (ctx == NULL)
- return 0;
- if (ctx->memory_blocks * sizeof(BLOCK) / sizeof(BLOCK) != ctx->memory_blocks)
- return 0;
- if (ctx->type != ARGON2_D)
- ctx->memory = OPENSSL_secure_zalloc(ctx->memory_blocks *
- sizeof(BLOCK));
- else
- ctx->memory = OPENSSL_zalloc(ctx->memory_blocks *
- sizeof(BLOCK));
- if (ctx->memory == NULL) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE,
- "cannot allocate required memory");
- return 0;
- }
- initial_hash(blockhash, ctx);
- OPENSSL_cleanse(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
- ARGON2_PREHASH_SEED_LENGTH - ARGON2_PREHASH_DIGEST_LENGTH);
- fill_first_blocks(blockhash, ctx);
- OPENSSL_cleanse(blockhash, ARGON2_PREHASH_SEED_LENGTH);
- return 1;
- }
- static void finalize(const KDF_ARGON2 *ctx, void *out)
- {
- BLOCK blockhash;
- uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
- uint32_t last_block_in_lane;
- uint32_t l;
- if (ctx == NULL)
- return;
- copy_block(&blockhash, ctx->memory + ctx->lane_length - 1);
- /* XOR the last blocks */
- for (l = 1; l < ctx->lanes; ++l) {
- last_block_in_lane = l * ctx->lane_length + (ctx->lane_length - 1);
- xor_block(&blockhash, ctx->memory + last_block_in_lane);
- }
- /* Hash the result */
- store_block(blockhash_bytes, &blockhash);
- blake2b_long(ctx->md, ctx->mac, out, ctx->outlen, blockhash_bytes,
- ARGON2_BLOCK_SIZE);
- OPENSSL_cleanse(blockhash.v, ARGON2_BLOCK_SIZE);
- OPENSSL_cleanse(blockhash_bytes, ARGON2_BLOCK_SIZE);
- if (ctx->type != ARGON2_D)
- OPENSSL_secure_clear_free(ctx->memory,
- ctx->memory_blocks * sizeof(BLOCK));
- else
- OPENSSL_clear_free(ctx->memory,
- ctx->memory_blocks * sizeof(BLOCK));
- }
- static int blake2b_mac(EVP_MAC *mac, void *out, size_t outlen, const void *in,
- size_t inlen, const void *key, size_t keylen)
- {
- int ret = 0;
- size_t par_n = 0, out_written;
- EVP_MAC_CTX *ctx = NULL;
- OSSL_PARAM par[3];
- if ((ctx = EVP_MAC_CTX_new(mac)) == NULL)
- goto fail;
- par[par_n++] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
- (void *) key, keylen);
- par[par_n++] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &outlen);
- par[par_n++] = OSSL_PARAM_construct_end();
- ret = EVP_MAC_CTX_set_params(ctx, par) == 1
- && EVP_MAC_init(ctx, NULL, 0, NULL) == 1
- && EVP_MAC_update(ctx, in, inlen) == 1
- && EVP_MAC_final(ctx, out, (size_t *) &out_written, outlen) == 1;
- fail:
- EVP_MAC_CTX_free(ctx);
- return ret;
- }
- static int blake2b_md(EVP_MD *md, void *out, size_t outlen, const void *in,
- size_t inlen)
- {
- int ret = 0;
- EVP_MD_CTX *ctx = NULL;
- OSSL_PARAM par[2];
- if ((ctx = EVP_MD_CTX_create()) == NULL)
- return 0;
- par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen);
- par[1] = OSSL_PARAM_construct_end();
- ret = EVP_DigestInit_ex2(ctx, md, par) == 1
- && EVP_DigestUpdate(ctx, in, inlen) == 1
- && EVP_DigestFinal_ex(ctx, out, NULL) == 1;
- EVP_MD_CTX_free(ctx);
- return ret;
- }
- static int blake2b(EVP_MD *md, EVP_MAC *mac, void *out, size_t outlen,
- const void *in, size_t inlen, const void *key, size_t keylen)
- {
- if (out == NULL || outlen == 0)
- return 0;
- if (key == NULL || keylen == 0)
- return blake2b_md(md, out, outlen, in, inlen);
- return blake2b_mac(mac, out, outlen, in, inlen, key, keylen);
- }
- static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,
- size_t outlen, const void *in, size_t inlen)
- {
- int ret = 0;
- EVP_MD_CTX *ctx = NULL;
- uint32_t outlen_curr;
- uint8_t outbuf[BLAKE2B_OUTBYTES];
- uint8_t inbuf[BLAKE2B_OUTBYTES];
- uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
- OSSL_PARAM par[2];
- size_t outlen_md;
- if (out == NULL || outlen == 0)
- return 0;
- /* Ensure little-endian byte order */
- store32(outlen_bytes, (uint32_t)outlen);
- if ((ctx = EVP_MD_CTX_create()) == NULL)
- return 0;
- outlen_md = (outlen <= BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES;
- par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen_md);
- par[1] = OSSL_PARAM_construct_end();
- ret = EVP_DigestInit_ex2(ctx, md, par) == 1
- && EVP_DigestUpdate(ctx, outlen_bytes, sizeof(outlen_bytes)) == 1
- && EVP_DigestUpdate(ctx, in, inlen) == 1
- && EVP_DigestFinal_ex(ctx, (outlen > BLAKE2B_OUTBYTES) ? outbuf : out,
- NULL) == 1;
- if (ret == 0)
- goto fail;
- if (outlen > BLAKE2B_OUTBYTES) {
- memcpy(out, outbuf, BLAKE2B_OUTBYTES / 2);
- out += BLAKE2B_OUTBYTES / 2;
- outlen_curr = (uint32_t) outlen - BLAKE2B_OUTBYTES / 2;
- while (outlen_curr > BLAKE2B_OUTBYTES) {
- memcpy(inbuf, outbuf, BLAKE2B_OUTBYTES);
- if (blake2b(md, mac, outbuf, BLAKE2B_OUTBYTES, inbuf,
- BLAKE2B_OUTBYTES, NULL, 0) != 1)
- goto fail;
- memcpy(out, outbuf, BLAKE2B_OUTBYTES / 2);
- out += BLAKE2B_OUTBYTES / 2;
- outlen_curr -= BLAKE2B_OUTBYTES / 2;
- }
- memcpy(inbuf, outbuf, BLAKE2B_OUTBYTES);
- if (blake2b(md, mac, outbuf, outlen_curr, inbuf, BLAKE2B_OUTBYTES,
- NULL, 0) != 1)
- goto fail;
- memcpy(out, outbuf, outlen_curr);
- }
- ret = 1;
- fail:
- EVP_MD_CTX_free(ctx);
- return ret;
- }
- static void kdf_argon2_init(KDF_ARGON2 *c, ARGON2_TYPE type)
- {
- OSSL_LIB_CTX *libctx;
- libctx = c->libctx;
- memset(c, 0, sizeof(*c));
- c->libctx = libctx;
- c->outlen = ARGON2_DEFAULT_OUTLEN;
- c->t_cost = ARGON2_DEFAULT_T_COST;
- c->m_cost = ARGON2_DEFAULT_M_COST;
- c->lanes = ARGON2_DEFAULT_LANES;
- c->threads = ARGON2_DEFAULT_THREADS;
- c->version = ARGON2_DEFAULT_VERSION;
- c->type = type;
- }
- static void *kdf_argon2d_new(void *provctx)
- {
- KDF_ARGON2 *ctx;
- if (!ossl_prov_is_running())
- return NULL;
- ctx = OPENSSL_zalloc(sizeof(*ctx));
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- ctx->libctx = PROV_LIBCTX_OF(provctx);
- kdf_argon2_init(ctx, ARGON2_D);
- return ctx;
- }
- static void *kdf_argon2i_new(void *provctx)
- {
- KDF_ARGON2 *ctx;
- if (!ossl_prov_is_running())
- return NULL;
- ctx = OPENSSL_zalloc(sizeof(*ctx));
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- ctx->libctx = PROV_LIBCTX_OF(provctx);
- kdf_argon2_init(ctx, ARGON2_I);
- return ctx;
- }
- static void *kdf_argon2id_new(void *provctx)
- {
- KDF_ARGON2 *ctx;
- if (!ossl_prov_is_running())
- return NULL;
- ctx = OPENSSL_zalloc(sizeof(*ctx));
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- ctx->libctx = PROV_LIBCTX_OF(provctx);
- kdf_argon2_init(ctx, ARGON2_ID);
- return ctx;
- }
- static void kdf_argon2_free(void *vctx)
- {
- KDF_ARGON2 *ctx = (KDF_ARGON2 *)vctx;
- if (ctx == NULL)
- return;
- if (ctx->pwd != NULL)
- OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);
- if (ctx->salt != NULL)
- OPENSSL_clear_free(ctx->salt, ctx->saltlen);
- if (ctx->secret != NULL)
- OPENSSL_clear_free(ctx->secret, ctx->secretlen);
- if (ctx->ad != NULL)
- OPENSSL_clear_free(ctx->ad, ctx->adlen);
- EVP_MD_free(ctx->md);
- EVP_MAC_free(ctx->mac);
- OPENSSL_free(ctx->propq);
- memset(ctx, 0, sizeof(*ctx));
- OPENSSL_free(ctx);
- }
- static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,
- const OSSL_PARAM params[])
- {
- KDF_ARGON2 *ctx;
- uint32_t memory_blocks, segment_length;
- ctx = (KDF_ARGON2 *)vctx;
- if (!ossl_prov_is_running() || !kdf_argon2_set_ctx_params(vctx, params))
- return 0;
- if (ctx->mac == NULL)
- ctx->mac = EVP_MAC_fetch(ctx->libctx, "blake2bmac", ctx->propq);
- if (ctx->mac == NULL) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_MISSING_MAC,
- "cannot fetch blake2bmac");
- return 0;
- }
- if (ctx->md == NULL)
- ctx->md = EVP_MD_fetch(ctx->libctx, "blake2b512", ctx->propq);
- if (ctx->md == NULL) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST,
- "cannot fetch blake2b512");
- return 0;
- }
- if (ctx->salt == NULL || ctx->saltlen == 0) {
- ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
- return 0;
- }
- if (outlen != ctx->outlen) {
- if (OSSL_PARAM_locate((OSSL_PARAM *)params, "size") != NULL) {
- ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
- return 0;
- }
- if (!kdf_argon2_ctx_set_out_length(ctx, (uint32_t) outlen))
- return 0;
- }
- switch (ctx->type) {
- case ARGON2_D:
- case ARGON2_I:
- case ARGON2_ID:
- break;
- default:
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MODE, "invalid Argon2 type");
- return 0;
- }
- if (ctx->threads > 1) {
- # ifdef ARGON2_NO_THREADS
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
- "requested %u threads, single-threaded mode supported only",
- ctx->threads);
- return 0;
- # else
- if (ctx->threads > ossl_get_avail_threads(ctx->libctx)) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
- "requested %u threads, available: 1",
- ossl_get_avail_threads(ctx->libctx));
- return 0;
- }
- # endif
- if (ctx->threads > ctx->lanes) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
- "requested more threads (%u) than lanes (%u)",
- ctx->threads, ctx->lanes);
- return 0;
- }
- }
- if (ctx->m_cost < 8 * ctx->lanes) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE,
- "m_cost must be greater or equal than 8 times the number of lanes");
- return 0;
- }
- memory_blocks = ctx->m_cost;
- if (memory_blocks < 2 * ARGON2_SYNC_POINTS * ctx->lanes)
- memory_blocks = 2 * ARGON2_SYNC_POINTS * ctx->lanes;
- /* Ensure that all segments have equal length */
- segment_length = memory_blocks / (ctx->lanes * ARGON2_SYNC_POINTS);
- memory_blocks = segment_length * (ctx->lanes * ARGON2_SYNC_POINTS);
- ctx->memory = NULL;
- ctx->memory_blocks = memory_blocks;
- ctx->segment_length = segment_length;
- ctx->passes = ctx->t_cost;
- ctx->lane_length = segment_length * ARGON2_SYNC_POINTS;
- if (initialize(ctx) != 1)
- return 0;
- if (fill_memory_blocks(ctx) != 1)
- return 0;
- finalize(ctx, out);
- return 1;
- }
- static void kdf_argon2_reset(void *vctx)
- {
- OSSL_LIB_CTX *libctx;
- KDF_ARGON2 *ctx;
- ARGON2_TYPE type;
- ctx = (KDF_ARGON2 *) vctx;
- type = ctx->type;
- libctx = ctx->libctx;
- EVP_MD_free(ctx->md);
- EVP_MAC_free(ctx->mac);
- OPENSSL_free(ctx->propq);
- if (ctx->pwd != NULL)
- OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);
- if (ctx->salt != NULL)
- OPENSSL_clear_free(ctx->salt, ctx->saltlen);
- if (ctx->secret != NULL)
- OPENSSL_clear_free(ctx->secret, ctx->secretlen);
- if (ctx->ad != NULL)
- OPENSSL_clear_free(ctx->ad, ctx->adlen);
- memset(ctx, 0, sizeof(*ctx));
- ctx->libctx = libctx;
- kdf_argon2_init(ctx, type);
- }
- static int kdf_argon2_ctx_set_threads(KDF_ARGON2 *ctx, uint32_t threads)
- {
- if (threads < ARGON2_MIN_THREADS) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
- "min threads: %u", ARGON2_MIN_THREADS);
- return 0;
- }
- if (threads > ARGON2_MAX_THREADS) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_THREAD_POOL_SIZE,
- "max threads: %u", ARGON2_MAX_THREADS);
- return 0;
- }
- ctx->threads = threads;
- return 1;
- }
- static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes)
- {
- if (lanes > ARGON2_MAX_LANES) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER,
- "max lanes: %u", ARGON2_MAX_LANES);
- return 0;
- }
- if (lanes < ARGON2_MIN_LANES) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER,
- "min lanes: %u", ARGON2_MIN_LANES);
- return 0;
- }
- ctx->lanes = lanes;
- return 1;
- }
- static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost)
- {
- /* ARGON2_MAX_MEMORY == max m_cost value, so skip check */
- if (t_cost < ARGON2_MIN_TIME) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT,
- "min: %u", ARGON2_MIN_TIME);
- return 0;
- }
- ctx->t_cost = t_cost;
- return 1;
- }
- static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost)
- {
- /* ARGON2_MAX_MEMORY == max m_cost value, so skip check */
- if (m_cost < ARGON2_MIN_MEMORY) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE, "min: %u",
- ARGON2_MIN_MEMORY);
- return 0;
- }
- ctx->m_cost = m_cost;
- return 1;
- }
- static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen)
- {
- /*
- * ARGON2_MAX_OUT_LENGTH == max outlen value, so upper bounds checks
- * are always satisfied; to suppress compiler if statement tautology
- * warnings, these checks are skipped.
- */
- if (outlen < ARGON2_MIN_OUT_LENGTH) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH, "min: %u",
- ARGON2_MIN_OUT_LENGTH);
- return 0;
- }
- ctx->outlen = outlen;
- return 1;
- }
- static int kdf_argon2_ctx_set_secret(KDF_ARGON2 *ctx, const OSSL_PARAM *p)
- {
- size_t buflen;
- if (p->data == NULL)
- return 0;
- if (ctx->secret != NULL) {
- OPENSSL_clear_free(ctx->secret, ctx->secretlen);
- ctx->secret = NULL;
- ctx->secretlen = 0U;
- }
- if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->secret, 0, &buflen))
- return 0;
- if (buflen > ARGON2_MAX_SECRET) {
- OPENSSL_free(ctx->secret);
- ctx->secret = NULL;
- ctx->secretlen = 0U;
- return 0;
- }
- ctx->secretlen = (uint32_t) buflen;
- return 1;
- }
- static int kdf_argon2_ctx_set_pwd(KDF_ARGON2 *ctx, const OSSL_PARAM *p)
- {
- size_t buflen;
- if (p->data == NULL)
- return 0;
- if (ctx->pwd != NULL) {
- OPENSSL_clear_free(ctx->pwd, ctx->pwdlen);
- ctx->pwd = NULL;
- ctx->pwdlen = 0U;
- }
- if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pwd, 0, &buflen))
- return 0;
- if (buflen > ARGON2_MAX_PWD_LENGTH) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "max: %u",
- ARGON2_MAX_PWD_LENGTH);
- goto fail;
- }
- ctx->pwdlen = (uint32_t) buflen;
- return 1;
- fail:
- OPENSSL_free(ctx->pwd);
- ctx->pwd = NULL;
- ctx->pwdlen = 0U;
- return 0;
- }
- static int kdf_argon2_ctx_set_salt(KDF_ARGON2 *ctx, const OSSL_PARAM *p)
- {
- size_t buflen;
- if (p->data == NULL)
- return 0;
- if (ctx->salt != NULL) {
- OPENSSL_clear_free(ctx->salt, ctx->saltlen);
- ctx->salt = NULL;
- ctx->saltlen = 0U;
- }
- if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0, &buflen))
- return 0;
- if (buflen < ARGON2_MIN_SALT_LENGTH) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "min: %u",
- ARGON2_MIN_SALT_LENGTH);
- goto fail;
- }
- if (buflen > ARGON2_MAX_SALT_LENGTH) {
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH, "max: %u",
- ARGON2_MAX_SALT_LENGTH);
- goto fail;
- }
- ctx->saltlen = (uint32_t) buflen;
- return 1;
- fail:
- OPENSSL_free(ctx->salt);
- ctx->salt = NULL;
- ctx->saltlen = 0U;
- return 0;
- }
- static int kdf_argon2_ctx_set_ad(KDF_ARGON2 *ctx, const OSSL_PARAM *p)
- {
- size_t buflen;
- if (p->data == NULL)
- return 0;
- if (ctx->ad != NULL) {
- OPENSSL_clear_free(ctx->ad, ctx->adlen);
- ctx->ad = NULL;
- ctx->adlen = 0U;
- }
- if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->ad, 0, &buflen))
- return 0;
- if (buflen > ARGON2_MAX_AD_LENGTH) {
- OPENSSL_free(ctx->ad);
- ctx->ad = NULL;
- ctx->adlen = 0U;
- return 0;
- }
- ctx->adlen = (uint32_t) buflen;
- return 1;
- }
- static void kdf_argon2_ctx_set_flag_early_clean(KDF_ARGON2 *ctx, uint32_t f)
- {
- ctx->early_clean = !!(f);
- }
- static int kdf_argon2_ctx_set_version(KDF_ARGON2 *ctx, uint32_t version)
- {
- switch (version) {
- case ARGON2_VERSION_10:
- case ARGON2_VERSION_13:
- ctx->version = version;
- return 1;
- default:
- ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MODE,
- "invalid Argon2 version");
- return 0;
- }
- }
- static int set_property_query(KDF_ARGON2 *ctx, const char *propq)
- {
- OPENSSL_free(ctx->propq);
- ctx->propq = NULL;
- if (propq != NULL) {
- ctx->propq = OPENSSL_strdup(propq);
- if (ctx->propq == NULL)
- return 0;
- }
- EVP_MD_free(ctx->md);
- ctx->md = NULL;
- EVP_MAC_free(ctx->mac);
- ctx->mac = NULL;
- return 1;
- }
- static int kdf_argon2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
- {
- const OSSL_PARAM *p;
- KDF_ARGON2 *ctx;
- uint32_t u32_value;
- if (params == NULL)
- return 1;
- ctx = (KDF_ARGON2 *) vctx;
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
- if (!kdf_argon2_ctx_set_pwd(ctx, p))
- return 0;
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
- if (!kdf_argon2_ctx_set_salt(ctx, p))
- return 0;
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL)
- if (!kdf_argon2_ctx_set_secret(ctx, p))
- return 0;
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_AD)) != NULL)
- if (!kdf_argon2_ctx_set_ad(ctx, p))
- return 0;
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
- if (!OSSL_PARAM_get_uint32(p, &u32_value))
- return 0;
- if (!kdf_argon2_ctx_set_out_length(ctx, u32_value))
- return 0;
- }
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL) {
- if (!OSSL_PARAM_get_uint32(p, &u32_value))
- return 0;
- if (!kdf_argon2_ctx_set_t_cost(ctx, u32_value))
- return 0;
- }
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_THREADS)) != NULL) {
- if (!OSSL_PARAM_get_uint32(p, &u32_value))
- return 0;
- if (!kdf_argon2_ctx_set_threads(ctx, u32_value))
- return 0;
- }
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_LANES)) != NULL) {
- if (!OSSL_PARAM_get_uint32(p, &u32_value))
- return 0;
- if (!kdf_argon2_ctx_set_lanes(ctx, u32_value))
- return 0;
- }
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_MEMCOST)) != NULL) {
- if (!OSSL_PARAM_get_uint32(p, &u32_value))
- return 0;
- if (!kdf_argon2_ctx_set_m_cost(ctx, u32_value))
- return 0;
- }
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_EARLY_CLEAN)) != NULL) {
- if (!OSSL_PARAM_get_uint32(p, &u32_value))
- return 0;
- kdf_argon2_ctx_set_flag_early_clean(ctx, u32_value);
- }
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ARGON2_VERSION)) != NULL) {
- if (!OSSL_PARAM_get_uint32(p, &u32_value))
- return 0;
- if (!kdf_argon2_ctx_set_version(ctx, u32_value))
- return 0;
- }
- if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES)) != NULL) {
- if (p->data_type != OSSL_PARAM_UTF8_STRING
- || !set_property_query(ctx, p->data))
- return 0;
- }
- return 1;
- }
- static const OSSL_PARAM *kdf_argon2_settable_ctx_params(ossl_unused void *ctx,
- ossl_unused void *p_ctx)
- {
- static const OSSL_PARAM known_settable_ctx_params[] = {
- OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
- OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
- OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
- OSSL_PARAM_octet_string(OSSL_KDF_PARAM_ARGON2_AD, NULL, 0),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_SIZE, NULL),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_ITER, NULL),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_THREADS, NULL),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_LANES, NULL),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, NULL),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_EARLY_CLEAN, NULL),
- OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_VERSION, NULL),
- OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
- OSSL_PARAM_END
- };
- return known_settable_ctx_params;
- }
- static int kdf_argon2_get_ctx_params(void *vctx, OSSL_PARAM params[])
- {
- OSSL_PARAM *p;
- (void) vctx;
- if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
- return OSSL_PARAM_set_size_t(p, SIZE_MAX);
- return -2;
- }
- static const OSSL_PARAM *kdf_argon2_gettable_ctx_params(ossl_unused void *ctx,
- ossl_unused void *p_ctx)
- {
- static const OSSL_PARAM known_gettable_ctx_params[] = {
- OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
- OSSL_PARAM_END
- };
- return known_gettable_ctx_params;
- }
- const OSSL_DISPATCH ossl_kdf_argon2i_functions[] = {
- { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2i_new },
- { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },
- { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },
- { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },
- { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
- (void(*)(void))kdf_argon2_settable_ctx_params },
- { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },
- { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
- (void(*)(void))kdf_argon2_gettable_ctx_params },
- { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },
- OSSL_DISPATCH_END
- };
- const OSSL_DISPATCH ossl_kdf_argon2d_functions[] = {
- { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2d_new },
- { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },
- { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },
- { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },
- { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
- (void(*)(void))kdf_argon2_settable_ctx_params },
- { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },
- { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
- (void(*)(void))kdf_argon2_gettable_ctx_params },
- { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },
- OSSL_DISPATCH_END
- };
- const OSSL_DISPATCH ossl_kdf_argon2id_functions[] = {
- { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_argon2id_new },
- { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_argon2_free },
- { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_argon2_reset },
- { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_argon2_derive },
- { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
- (void(*)(void))kdf_argon2_settable_ctx_params },
- { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_argon2_set_ctx_params },
- { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
- (void(*)(void))kdf_argon2_gettable_ctx_params },
- { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_argon2_get_ctx_params },
- OSSL_DISPATCH_END
- };
- #endif
|