1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <stdlib.h>
11e1051a39Sopenharmony_ci#include <stdarg.h>
12e1051a39Sopenharmony_ci#include <string.h>
13e1051a39Sopenharmony_ci#include <openssl/evp.h>
14e1051a39Sopenharmony_ci#include <openssl/kdf.h>
15e1051a39Sopenharmony_ci#include <openssl/err.h>
16e1051a39Sopenharmony_ci#include <openssl/core_names.h>
17e1051a39Sopenharmony_ci#include <openssl/proverr.h>
18e1051a39Sopenharmony_ci#include "crypto/evp.h"
19e1051a39Sopenharmony_ci#include "internal/numbers.h"
20e1051a39Sopenharmony_ci#include "prov/implementations.h"
21e1051a39Sopenharmony_ci#include "prov/provider_ctx.h"
22e1051a39Sopenharmony_ci#include "prov/providercommon.h"
23e1051a39Sopenharmony_ci#include "prov/implementations.h"
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SCRYPT
26e1051a39Sopenharmony_ci
27e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_newctx_fn kdf_scrypt_new;
28e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_freectx_fn kdf_scrypt_free;
29e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_reset_fn kdf_scrypt_reset;
30e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_derive_fn kdf_scrypt_derive;
31e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_settable_ctx_params_fn kdf_scrypt_settable_ctx_params;
32e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_set_ctx_params_fn kdf_scrypt_set_ctx_params;
33e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_scrypt_gettable_ctx_params;
34e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_get_ctx_params_fn kdf_scrypt_get_ctx_params;
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_cistatic int scrypt_alg(const char *pass, size_t passlen,
37e1051a39Sopenharmony_ci                      const unsigned char *salt, size_t saltlen,
38e1051a39Sopenharmony_ci                      uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
39e1051a39Sopenharmony_ci                      unsigned char *key, size_t keylen, EVP_MD *sha256,
40e1051a39Sopenharmony_ci                      OSSL_LIB_CTX *libctx, const char *propq);
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_citypedef struct {
43e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx;
44e1051a39Sopenharmony_ci    char *propq;
45e1051a39Sopenharmony_ci    unsigned char *pass;
46e1051a39Sopenharmony_ci    size_t pass_len;
47e1051a39Sopenharmony_ci    unsigned char *salt;
48e1051a39Sopenharmony_ci    size_t salt_len;
49e1051a39Sopenharmony_ci    uint64_t N;
50e1051a39Sopenharmony_ci    uint64_t r, p;
51e1051a39Sopenharmony_ci    uint64_t maxmem_bytes;
52e1051a39Sopenharmony_ci    EVP_MD *sha256;
53e1051a39Sopenharmony_ci} KDF_SCRYPT;
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_cistatic void kdf_scrypt_init(KDF_SCRYPT *ctx);
56e1051a39Sopenharmony_ci
57e1051a39Sopenharmony_cistatic void *kdf_scrypt_new(void *provctx)
58e1051a39Sopenharmony_ci{
59e1051a39Sopenharmony_ci    KDF_SCRYPT *ctx;
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
62e1051a39Sopenharmony_ci        return NULL;
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci    ctx = OPENSSL_zalloc(sizeof(*ctx));
65e1051a39Sopenharmony_ci    if (ctx == NULL) {
66e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
67e1051a39Sopenharmony_ci        return NULL;
68e1051a39Sopenharmony_ci    }
69e1051a39Sopenharmony_ci    ctx->libctx = PROV_LIBCTX_OF(provctx);
70e1051a39Sopenharmony_ci    kdf_scrypt_init(ctx);
71e1051a39Sopenharmony_ci    return ctx;
72e1051a39Sopenharmony_ci}
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_cistatic void kdf_scrypt_free(void *vctx)
75e1051a39Sopenharmony_ci{
76e1051a39Sopenharmony_ci    KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
77e1051a39Sopenharmony_ci
78e1051a39Sopenharmony_ci    if (ctx != NULL) {
79e1051a39Sopenharmony_ci        OPENSSL_free(ctx->propq);
80e1051a39Sopenharmony_ci        EVP_MD_free(ctx->sha256);
81e1051a39Sopenharmony_ci        kdf_scrypt_reset(ctx);
82e1051a39Sopenharmony_ci        OPENSSL_free(ctx);
83e1051a39Sopenharmony_ci    }
84e1051a39Sopenharmony_ci}
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_cistatic void kdf_scrypt_reset(void *vctx)
87e1051a39Sopenharmony_ci{
88e1051a39Sopenharmony_ci    KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci    OPENSSL_free(ctx->salt);
91e1051a39Sopenharmony_ci    OPENSSL_clear_free(ctx->pass, ctx->pass_len);
92e1051a39Sopenharmony_ci    kdf_scrypt_init(ctx);
93e1051a39Sopenharmony_ci}
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_cistatic void kdf_scrypt_init(KDF_SCRYPT *ctx)
96e1051a39Sopenharmony_ci{
97e1051a39Sopenharmony_ci    /* Default values are the most conservative recommendation given in the
98e1051a39Sopenharmony_ci     * original paper of C. Percival. Derivation uses roughly 1 GiB of memory
99e1051a39Sopenharmony_ci     * for this parameter choice (approx. 128 * r * N * p bytes).
100e1051a39Sopenharmony_ci     */
101e1051a39Sopenharmony_ci    ctx->N = 1 << 20;
102e1051a39Sopenharmony_ci    ctx->r = 8;
103e1051a39Sopenharmony_ci    ctx->p = 1;
104e1051a39Sopenharmony_ci    ctx->maxmem_bytes = 1025 * 1024 * 1024;
105e1051a39Sopenharmony_ci}
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_cistatic int scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
108e1051a39Sopenharmony_ci                             const OSSL_PARAM *p)
109e1051a39Sopenharmony_ci{
110e1051a39Sopenharmony_ci    OPENSSL_clear_free(*buffer, *buflen);
111e1051a39Sopenharmony_ci    *buffer = NULL;
112e1051a39Sopenharmony_ci    *buflen = 0;
113e1051a39Sopenharmony_ci
114e1051a39Sopenharmony_ci    if (p->data_size == 0) {
115e1051a39Sopenharmony_ci        if ((*buffer = OPENSSL_malloc(1)) == NULL) {
116e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
117e1051a39Sopenharmony_ci            return 0;
118e1051a39Sopenharmony_ci        }
119e1051a39Sopenharmony_ci    } else if (p->data != NULL) {
120e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
121e1051a39Sopenharmony_ci            return 0;
122e1051a39Sopenharmony_ci    }
123e1051a39Sopenharmony_ci    return 1;
124e1051a39Sopenharmony_ci}
125e1051a39Sopenharmony_ci
126e1051a39Sopenharmony_cistatic int set_digest(KDF_SCRYPT *ctx)
127e1051a39Sopenharmony_ci{
128e1051a39Sopenharmony_ci    EVP_MD_free(ctx->sha256);
129e1051a39Sopenharmony_ci    ctx->sha256 = EVP_MD_fetch(ctx->libctx, "sha256", ctx->propq);
130e1051a39Sopenharmony_ci    if (ctx->sha256 == NULL) {
131e1051a39Sopenharmony_ci        OPENSSL_free(ctx);
132e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA256);
133e1051a39Sopenharmony_ci        return 0;
134e1051a39Sopenharmony_ci    }
135e1051a39Sopenharmony_ci    return 1;
136e1051a39Sopenharmony_ci}
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_cistatic int set_property_query(KDF_SCRYPT *ctx, const char *propq)
139e1051a39Sopenharmony_ci{
140e1051a39Sopenharmony_ci    OPENSSL_free(ctx->propq);
141e1051a39Sopenharmony_ci    ctx->propq = NULL;
142e1051a39Sopenharmony_ci    if (propq != NULL) {
143e1051a39Sopenharmony_ci        ctx->propq = OPENSSL_strdup(propq);
144e1051a39Sopenharmony_ci        if (ctx->propq == NULL) {
145e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
146e1051a39Sopenharmony_ci            return 0;
147e1051a39Sopenharmony_ci        }
148e1051a39Sopenharmony_ci    }
149e1051a39Sopenharmony_ci    return 1;
150e1051a39Sopenharmony_ci}
151e1051a39Sopenharmony_ci
152e1051a39Sopenharmony_cistatic int kdf_scrypt_derive(void *vctx, unsigned char *key, size_t keylen,
153e1051a39Sopenharmony_ci                             const OSSL_PARAM params[])
154e1051a39Sopenharmony_ci{
155e1051a39Sopenharmony_ci    KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || !kdf_scrypt_set_ctx_params(ctx, params))
158e1051a39Sopenharmony_ci        return 0;
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci    if (ctx->pass == NULL) {
161e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
162e1051a39Sopenharmony_ci        return 0;
163e1051a39Sopenharmony_ci    }
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_ci    if (ctx->salt == NULL) {
166e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
167e1051a39Sopenharmony_ci        return 0;
168e1051a39Sopenharmony_ci    }
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ci    if (ctx->sha256 == NULL && !set_digest(ctx))
171e1051a39Sopenharmony_ci        return 0;
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci    return scrypt_alg((char *)ctx->pass, ctx->pass_len, ctx->salt,
174e1051a39Sopenharmony_ci                      ctx->salt_len, ctx->N, ctx->r, ctx->p,
175e1051a39Sopenharmony_ci                      ctx->maxmem_bytes, key, keylen, ctx->sha256,
176e1051a39Sopenharmony_ci                      ctx->libctx, ctx->propq);
177e1051a39Sopenharmony_ci}
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_cistatic int is_power_of_two(uint64_t value)
180e1051a39Sopenharmony_ci{
181e1051a39Sopenharmony_ci    return (value != 0) && ((value & (value - 1)) == 0);
182e1051a39Sopenharmony_ci}
183e1051a39Sopenharmony_ci
184e1051a39Sopenharmony_cistatic int kdf_scrypt_set_ctx_params(void *vctx, const OSSL_PARAM params[])
185e1051a39Sopenharmony_ci{
186e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
187e1051a39Sopenharmony_ci    KDF_SCRYPT *ctx = vctx;
188e1051a39Sopenharmony_ci    uint64_t u64_value;
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_ci    if (params == NULL)
191e1051a39Sopenharmony_ci        return 1;
192e1051a39Sopenharmony_ci
193e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
194e1051a39Sopenharmony_ci        if (!scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p))
195e1051a39Sopenharmony_ci            return 0;
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
198e1051a39Sopenharmony_ci        if (!scrypt_set_membuf(&ctx->salt, &ctx->salt_len, p))
199e1051a39Sopenharmony_ci            return 0;
200e1051a39Sopenharmony_ci
201e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_N))
202e1051a39Sopenharmony_ci        != NULL) {
203e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_uint64(p, &u64_value)
204e1051a39Sopenharmony_ci            || u64_value <= 1
205e1051a39Sopenharmony_ci            || !is_power_of_two(u64_value))
206e1051a39Sopenharmony_ci            return 0;
207e1051a39Sopenharmony_ci        ctx->N = u64_value;
208e1051a39Sopenharmony_ci    }
209e1051a39Sopenharmony_ci
210e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_R))
211e1051a39Sopenharmony_ci        != NULL) {
212e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
213e1051a39Sopenharmony_ci            return 0;
214e1051a39Sopenharmony_ci        ctx->r = u64_value;
215e1051a39Sopenharmony_ci    }
216e1051a39Sopenharmony_ci
217e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_P))
218e1051a39Sopenharmony_ci        != NULL) {
219e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
220e1051a39Sopenharmony_ci            return 0;
221e1051a39Sopenharmony_ci        ctx->p = u64_value;
222e1051a39Sopenharmony_ci    }
223e1051a39Sopenharmony_ci
224e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_MAXMEM))
225e1051a39Sopenharmony_ci        != NULL) {
226e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1)
227e1051a39Sopenharmony_ci            return 0;
228e1051a39Sopenharmony_ci        ctx->maxmem_bytes = u64_value;
229e1051a39Sopenharmony_ci    }
230e1051a39Sopenharmony_ci
231e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
232e1051a39Sopenharmony_ci    if (p != NULL) {
233e1051a39Sopenharmony_ci        if (p->data_type != OSSL_PARAM_UTF8_STRING
234e1051a39Sopenharmony_ci            || !set_property_query(ctx, p->data)
235e1051a39Sopenharmony_ci            || !set_digest(ctx))
236e1051a39Sopenharmony_ci            return 0;
237e1051a39Sopenharmony_ci    }
238e1051a39Sopenharmony_ci    return 1;
239e1051a39Sopenharmony_ci}
240e1051a39Sopenharmony_ci
241e1051a39Sopenharmony_cistatic const OSSL_PARAM *kdf_scrypt_settable_ctx_params(ossl_unused void *ctx,
242e1051a39Sopenharmony_ci                                                        ossl_unused void *p_ctx)
243e1051a39Sopenharmony_ci{
244e1051a39Sopenharmony_ci    static const OSSL_PARAM known_settable_ctx_params[] = {
245e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
246e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
247e1051a39Sopenharmony_ci        OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_N, NULL),
248e1051a39Sopenharmony_ci        OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_R, NULL),
249e1051a39Sopenharmony_ci        OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_P, NULL),
250e1051a39Sopenharmony_ci        OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, NULL),
251e1051a39Sopenharmony_ci        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
252e1051a39Sopenharmony_ci        OSSL_PARAM_END
253e1051a39Sopenharmony_ci    };
254e1051a39Sopenharmony_ci    return known_settable_ctx_params;
255e1051a39Sopenharmony_ci}
256e1051a39Sopenharmony_ci
257e1051a39Sopenharmony_cistatic int kdf_scrypt_get_ctx_params(void *vctx, OSSL_PARAM params[])
258e1051a39Sopenharmony_ci{
259e1051a39Sopenharmony_ci    OSSL_PARAM *p;
260e1051a39Sopenharmony_ci
261e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
262e1051a39Sopenharmony_ci        return OSSL_PARAM_set_size_t(p, SIZE_MAX);
263e1051a39Sopenharmony_ci    return -2;
264e1051a39Sopenharmony_ci}
265e1051a39Sopenharmony_ci
266e1051a39Sopenharmony_cistatic const OSSL_PARAM *kdf_scrypt_gettable_ctx_params(ossl_unused void *ctx,
267e1051a39Sopenharmony_ci                                                        ossl_unused void *p_ctx)
268e1051a39Sopenharmony_ci{
269e1051a39Sopenharmony_ci    static const OSSL_PARAM known_gettable_ctx_params[] = {
270e1051a39Sopenharmony_ci        OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
271e1051a39Sopenharmony_ci        OSSL_PARAM_END
272e1051a39Sopenharmony_ci    };
273e1051a39Sopenharmony_ci    return known_gettable_ctx_params;
274e1051a39Sopenharmony_ci}
275e1051a39Sopenharmony_ci
276e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kdf_scrypt_functions[] = {
277e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_scrypt_new },
278e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_scrypt_free },
279e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_scrypt_reset },
280e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_scrypt_derive },
281e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
282e1051a39Sopenharmony_ci      (void(*)(void))kdf_scrypt_settable_ctx_params },
283e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_scrypt_set_ctx_params },
284e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
285e1051a39Sopenharmony_ci      (void(*)(void))kdf_scrypt_gettable_ctx_params },
286e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_scrypt_get_ctx_params },
287e1051a39Sopenharmony_ci    { 0, NULL }
288e1051a39Sopenharmony_ci};
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ci#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
291e1051a39Sopenharmony_cistatic void salsa208_word_specification(uint32_t inout[16])
292e1051a39Sopenharmony_ci{
293e1051a39Sopenharmony_ci    int i;
294e1051a39Sopenharmony_ci    uint32_t x[16];
295e1051a39Sopenharmony_ci
296e1051a39Sopenharmony_ci    memcpy(x, inout, sizeof(x));
297e1051a39Sopenharmony_ci    for (i = 8; i > 0; i -= 2) {
298e1051a39Sopenharmony_ci        x[4] ^= R(x[0] + x[12], 7);
299e1051a39Sopenharmony_ci        x[8] ^= R(x[4] + x[0], 9);
300e1051a39Sopenharmony_ci        x[12] ^= R(x[8] + x[4], 13);
301e1051a39Sopenharmony_ci        x[0] ^= R(x[12] + x[8], 18);
302e1051a39Sopenharmony_ci        x[9] ^= R(x[5] + x[1], 7);
303e1051a39Sopenharmony_ci        x[13] ^= R(x[9] + x[5], 9);
304e1051a39Sopenharmony_ci        x[1] ^= R(x[13] + x[9], 13);
305e1051a39Sopenharmony_ci        x[5] ^= R(x[1] + x[13], 18);
306e1051a39Sopenharmony_ci        x[14] ^= R(x[10] + x[6], 7);
307e1051a39Sopenharmony_ci        x[2] ^= R(x[14] + x[10], 9);
308e1051a39Sopenharmony_ci        x[6] ^= R(x[2] + x[14], 13);
309e1051a39Sopenharmony_ci        x[10] ^= R(x[6] + x[2], 18);
310e1051a39Sopenharmony_ci        x[3] ^= R(x[15] + x[11], 7);
311e1051a39Sopenharmony_ci        x[7] ^= R(x[3] + x[15], 9);
312e1051a39Sopenharmony_ci        x[11] ^= R(x[7] + x[3], 13);
313e1051a39Sopenharmony_ci        x[15] ^= R(x[11] + x[7], 18);
314e1051a39Sopenharmony_ci        x[1] ^= R(x[0] + x[3], 7);
315e1051a39Sopenharmony_ci        x[2] ^= R(x[1] + x[0], 9);
316e1051a39Sopenharmony_ci        x[3] ^= R(x[2] + x[1], 13);
317e1051a39Sopenharmony_ci        x[0] ^= R(x[3] + x[2], 18);
318e1051a39Sopenharmony_ci        x[6] ^= R(x[5] + x[4], 7);
319e1051a39Sopenharmony_ci        x[7] ^= R(x[6] + x[5], 9);
320e1051a39Sopenharmony_ci        x[4] ^= R(x[7] + x[6], 13);
321e1051a39Sopenharmony_ci        x[5] ^= R(x[4] + x[7], 18);
322e1051a39Sopenharmony_ci        x[11] ^= R(x[10] + x[9], 7);
323e1051a39Sopenharmony_ci        x[8] ^= R(x[11] + x[10], 9);
324e1051a39Sopenharmony_ci        x[9] ^= R(x[8] + x[11], 13);
325e1051a39Sopenharmony_ci        x[10] ^= R(x[9] + x[8], 18);
326e1051a39Sopenharmony_ci        x[12] ^= R(x[15] + x[14], 7);
327e1051a39Sopenharmony_ci        x[13] ^= R(x[12] + x[15], 9);
328e1051a39Sopenharmony_ci        x[14] ^= R(x[13] + x[12], 13);
329e1051a39Sopenharmony_ci        x[15] ^= R(x[14] + x[13], 18);
330e1051a39Sopenharmony_ci    }
331e1051a39Sopenharmony_ci    for (i = 0; i < 16; ++i)
332e1051a39Sopenharmony_ci        inout[i] += x[i];
333e1051a39Sopenharmony_ci    OPENSSL_cleanse(x, sizeof(x));
334e1051a39Sopenharmony_ci}
335e1051a39Sopenharmony_ci
336e1051a39Sopenharmony_cistatic void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
337e1051a39Sopenharmony_ci{
338e1051a39Sopenharmony_ci    uint64_t i, j;
339e1051a39Sopenharmony_ci    uint32_t X[16], *pB;
340e1051a39Sopenharmony_ci
341e1051a39Sopenharmony_ci    memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
342e1051a39Sopenharmony_ci    pB = B;
343e1051a39Sopenharmony_ci    for (i = 0; i < r * 2; i++) {
344e1051a39Sopenharmony_ci        for (j = 0; j < 16; j++)
345e1051a39Sopenharmony_ci            X[j] ^= *pB++;
346e1051a39Sopenharmony_ci        salsa208_word_specification(X);
347e1051a39Sopenharmony_ci        memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
348e1051a39Sopenharmony_ci    }
349e1051a39Sopenharmony_ci    OPENSSL_cleanse(X, sizeof(X));
350e1051a39Sopenharmony_ci}
351e1051a39Sopenharmony_ci
352e1051a39Sopenharmony_cistatic void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
353e1051a39Sopenharmony_ci                        uint32_t *X, uint32_t *T, uint32_t *V)
354e1051a39Sopenharmony_ci{
355e1051a39Sopenharmony_ci    unsigned char *pB;
356e1051a39Sopenharmony_ci    uint32_t *pV;
357e1051a39Sopenharmony_ci    uint64_t i, k;
358e1051a39Sopenharmony_ci
359e1051a39Sopenharmony_ci    /* Convert from little endian input */
360e1051a39Sopenharmony_ci    for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
361e1051a39Sopenharmony_ci        *pV = *pB++;
362e1051a39Sopenharmony_ci        *pV |= *pB++ << 8;
363e1051a39Sopenharmony_ci        *pV |= *pB++ << 16;
364e1051a39Sopenharmony_ci        *pV |= (uint32_t)*pB++ << 24;
365e1051a39Sopenharmony_ci    }
366e1051a39Sopenharmony_ci
367e1051a39Sopenharmony_ci    for (i = 1; i < N; i++, pV += 32 * r)
368e1051a39Sopenharmony_ci        scryptBlockMix(pV, pV - 32 * r, r);
369e1051a39Sopenharmony_ci
370e1051a39Sopenharmony_ci    scryptBlockMix(X, V + (N - 1) * 32 * r, r);
371e1051a39Sopenharmony_ci
372e1051a39Sopenharmony_ci    for (i = 0; i < N; i++) {
373e1051a39Sopenharmony_ci        uint32_t j;
374e1051a39Sopenharmony_ci        j = X[16 * (2 * r - 1)] % N;
375e1051a39Sopenharmony_ci        pV = V + 32 * r * j;
376e1051a39Sopenharmony_ci        for (k = 0; k < 32 * r; k++)
377e1051a39Sopenharmony_ci            T[k] = X[k] ^ *pV++;
378e1051a39Sopenharmony_ci        scryptBlockMix(X, T, r);
379e1051a39Sopenharmony_ci    }
380e1051a39Sopenharmony_ci    /* Convert output to little endian */
381e1051a39Sopenharmony_ci    for (i = 0, pB = B; i < 32 * r; i++) {
382e1051a39Sopenharmony_ci        uint32_t xtmp = X[i];
383e1051a39Sopenharmony_ci        *pB++ = xtmp & 0xff;
384e1051a39Sopenharmony_ci        *pB++ = (xtmp >> 8) & 0xff;
385e1051a39Sopenharmony_ci        *pB++ = (xtmp >> 16) & 0xff;
386e1051a39Sopenharmony_ci        *pB++ = (xtmp >> 24) & 0xff;
387e1051a39Sopenharmony_ci    }
388e1051a39Sopenharmony_ci}
389e1051a39Sopenharmony_ci
390e1051a39Sopenharmony_ci#ifndef SIZE_MAX
391e1051a39Sopenharmony_ci# define SIZE_MAX    ((size_t)-1)
392e1051a39Sopenharmony_ci#endif
393e1051a39Sopenharmony_ci
394e1051a39Sopenharmony_ci/*
395e1051a39Sopenharmony_ci * Maximum power of two that will fit in uint64_t: this should work on
396e1051a39Sopenharmony_ci * most (all?) platforms.
397e1051a39Sopenharmony_ci */
398e1051a39Sopenharmony_ci
399e1051a39Sopenharmony_ci#define LOG2_UINT64_MAX         (sizeof(uint64_t) * 8 - 1)
400e1051a39Sopenharmony_ci
401e1051a39Sopenharmony_ci/*
402e1051a39Sopenharmony_ci * Maximum value of p * r:
403e1051a39Sopenharmony_ci * p <= ((2^32-1) * hLen) / MFLen =>
404e1051a39Sopenharmony_ci * p <= ((2^32-1) * 32) / (128 * r) =>
405e1051a39Sopenharmony_ci * p * r <= (2^30-1)
406e1051a39Sopenharmony_ci */
407e1051a39Sopenharmony_ci
408e1051a39Sopenharmony_ci#define SCRYPT_PR_MAX   ((1 << 30) - 1)
409e1051a39Sopenharmony_ci
410e1051a39Sopenharmony_cistatic int scrypt_alg(const char *pass, size_t passlen,
411e1051a39Sopenharmony_ci                      const unsigned char *salt, size_t saltlen,
412e1051a39Sopenharmony_ci                      uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
413e1051a39Sopenharmony_ci                      unsigned char *key, size_t keylen, EVP_MD *sha256,
414e1051a39Sopenharmony_ci                      OSSL_LIB_CTX *libctx, const char *propq)
415e1051a39Sopenharmony_ci{
416e1051a39Sopenharmony_ci    int rv = 0;
417e1051a39Sopenharmony_ci    unsigned char *B;
418e1051a39Sopenharmony_ci    uint32_t *X, *V, *T;
419e1051a39Sopenharmony_ci    uint64_t i, Blen, Vlen;
420e1051a39Sopenharmony_ci
421e1051a39Sopenharmony_ci    /* Sanity check parameters */
422e1051a39Sopenharmony_ci    /* initial check, r,p must be non zero, N >= 2 and a power of 2 */
423e1051a39Sopenharmony_ci    if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
424e1051a39Sopenharmony_ci        return 0;
425e1051a39Sopenharmony_ci    /* Check p * r < SCRYPT_PR_MAX avoiding overflow */
426e1051a39Sopenharmony_ci    if (p > SCRYPT_PR_MAX / r) {
427e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
428e1051a39Sopenharmony_ci        return 0;
429e1051a39Sopenharmony_ci    }
430e1051a39Sopenharmony_ci
431e1051a39Sopenharmony_ci    /*
432e1051a39Sopenharmony_ci     * Need to check N: if 2^(128 * r / 8) overflows limit this is
433e1051a39Sopenharmony_ci     * automatically satisfied since N <= UINT64_MAX.
434e1051a39Sopenharmony_ci     */
435e1051a39Sopenharmony_ci
436e1051a39Sopenharmony_ci    if (16 * r <= LOG2_UINT64_MAX) {
437e1051a39Sopenharmony_ci        if (N >= (((uint64_t)1) << (16 * r))) {
438e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
439e1051a39Sopenharmony_ci            return 0;
440e1051a39Sopenharmony_ci        }
441e1051a39Sopenharmony_ci    }
442e1051a39Sopenharmony_ci
443e1051a39Sopenharmony_ci    /* Memory checks: check total allocated buffer size fits in uint64_t */
444e1051a39Sopenharmony_ci
445e1051a39Sopenharmony_ci    /*
446e1051a39Sopenharmony_ci     * B size in section 5 step 1.S
447e1051a39Sopenharmony_ci     * Note: we know p * 128 * r < UINT64_MAX because we already checked
448e1051a39Sopenharmony_ci     * p * r < SCRYPT_PR_MAX
449e1051a39Sopenharmony_ci     */
450e1051a39Sopenharmony_ci    Blen = p * 128 * r;
451e1051a39Sopenharmony_ci    /*
452e1051a39Sopenharmony_ci     * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
453e1051a39Sopenharmony_ci     * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
454e1051a39Sopenharmony_ci     */
455e1051a39Sopenharmony_ci    if (Blen > INT_MAX) {
456e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
457e1051a39Sopenharmony_ci        return 0;
458e1051a39Sopenharmony_ci    }
459e1051a39Sopenharmony_ci
460e1051a39Sopenharmony_ci    /*
461e1051a39Sopenharmony_ci     * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
462e1051a39Sopenharmony_ci     * This is combined size V, X and T (section 4)
463e1051a39Sopenharmony_ci     */
464e1051a39Sopenharmony_ci    i = UINT64_MAX / (32 * sizeof(uint32_t));
465e1051a39Sopenharmony_ci    if (N + 2 > i / r) {
466e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
467e1051a39Sopenharmony_ci        return 0;
468e1051a39Sopenharmony_ci    }
469e1051a39Sopenharmony_ci    Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
470e1051a39Sopenharmony_ci
471e1051a39Sopenharmony_ci    /* check total allocated size fits in uint64_t */
472e1051a39Sopenharmony_ci    if (Blen > UINT64_MAX - Vlen) {
473e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
474e1051a39Sopenharmony_ci        return 0;
475e1051a39Sopenharmony_ci    }
476e1051a39Sopenharmony_ci
477e1051a39Sopenharmony_ci    /* Check that the maximum memory doesn't exceed a size_t limits */
478e1051a39Sopenharmony_ci    if (maxmem > SIZE_MAX)
479e1051a39Sopenharmony_ci        maxmem = SIZE_MAX;
480e1051a39Sopenharmony_ci
481e1051a39Sopenharmony_ci    if (Blen + Vlen > maxmem) {
482e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
483e1051a39Sopenharmony_ci        return 0;
484e1051a39Sopenharmony_ci    }
485e1051a39Sopenharmony_ci
486e1051a39Sopenharmony_ci    /* If no key return to indicate parameters are OK */
487e1051a39Sopenharmony_ci    if (key == NULL)
488e1051a39Sopenharmony_ci        return 1;
489e1051a39Sopenharmony_ci
490e1051a39Sopenharmony_ci    B = OPENSSL_malloc((size_t)(Blen + Vlen));
491e1051a39Sopenharmony_ci    if (B == NULL) {
492e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
493e1051a39Sopenharmony_ci        return 0;
494e1051a39Sopenharmony_ci    }
495e1051a39Sopenharmony_ci    X = (uint32_t *)(B + Blen);
496e1051a39Sopenharmony_ci    T = X + 32 * r;
497e1051a39Sopenharmony_ci    V = T + 32 * r;
498e1051a39Sopenharmony_ci    if (ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, salt, saltlen, 1, sha256,
499e1051a39Sopenharmony_ci                                  (int)Blen, B, libctx, propq) == 0)
500e1051a39Sopenharmony_ci        goto err;
501e1051a39Sopenharmony_ci
502e1051a39Sopenharmony_ci    for (i = 0; i < p; i++)
503e1051a39Sopenharmony_ci        scryptROMix(B + 128 * r * i, r, N, X, T, V);
504e1051a39Sopenharmony_ci
505e1051a39Sopenharmony_ci    if (ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, B, (int)Blen, 1, sha256,
506e1051a39Sopenharmony_ci                                  keylen, key, libctx, propq) == 0)
507e1051a39Sopenharmony_ci        goto err;
508e1051a39Sopenharmony_ci    rv = 1;
509e1051a39Sopenharmony_ci err:
510e1051a39Sopenharmony_ci    if (rv == 0)
511e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_PBKDF2_ERROR);
512e1051a39Sopenharmony_ci
513e1051a39Sopenharmony_ci    OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
514e1051a39Sopenharmony_ci    return rv;
515e1051a39Sopenharmony_ci}
516e1051a39Sopenharmony_ci
517e1051a39Sopenharmony_ci#endif
518