Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/providers/implementations/kdfs/scrypt.c
Line
Count
Source
1
/*
2
 * Copyright 2017-2025 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
/* clang-format off */
10
11
/* clang-format on */
12
13
#include <stdlib.h>
14
#include <stdarg.h>
15
#include <string.h>
16
#include <openssl/evp.h>
17
#include <openssl/kdf.h>
18
#include <openssl/err.h>
19
#include <openssl/core_names.h>
20
#include <openssl/proverr.h>
21
#include "crypto/evp.h"
22
#include "internal/common.h"
23
#include "internal/numbers.h"
24
#include "prov/implementations.h"
25
#include "prov/provider_ctx.h"
26
#include "prov/providercommon.h"
27
#include "prov/provider_util.h"
28
29
#ifndef OPENSSL_NO_SCRYPT
30
31
static OSSL_FUNC_kdf_newctx_fn kdf_scrypt_new;
32
static OSSL_FUNC_kdf_dupctx_fn kdf_scrypt_dup;
33
static OSSL_FUNC_kdf_freectx_fn kdf_scrypt_free;
34
static OSSL_FUNC_kdf_reset_fn kdf_scrypt_reset;
35
static OSSL_FUNC_kdf_derive_fn kdf_scrypt_derive;
36
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_scrypt_settable_ctx_params;
37
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_scrypt_set_ctx_params;
38
static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_scrypt_gettable_ctx_params;
39
static OSSL_FUNC_kdf_get_ctx_params_fn kdf_scrypt_get_ctx_params;
40
41
static int scrypt_alg(const char *pass, size_t passlen,
42
    const unsigned char *salt, size_t saltlen,
43
    uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
44
    unsigned char *key, size_t keylen, EVP_MD *sha256,
45
    OSSL_LIB_CTX *libctx, const char *propq);
46
47
typedef struct {
48
    OSSL_LIB_CTX *libctx;
49
    char *propq;
50
    unsigned char *pass;
51
    size_t pass_len;
52
    unsigned char *salt;
53
    size_t salt_len;
54
    uint64_t N;
55
    uint64_t r, p;
56
    uint64_t maxmem_bytes;
57
    EVP_MD *sha256;
58
} KDF_SCRYPT;
59
60
static void kdf_scrypt_init(KDF_SCRYPT *ctx);
61
62
static void *kdf_scrypt_new_inner(OSSL_LIB_CTX *libctx)
63
89
{
64
89
    KDF_SCRYPT *ctx;
65
66
89
    if (!ossl_prov_is_running())
67
0
        return NULL;
68
69
89
    ctx = OPENSSL_zalloc(sizeof(*ctx));
70
89
    if (ctx == NULL)
71
0
        return NULL;
72
89
    ctx->libctx = libctx;
73
89
    kdf_scrypt_init(ctx);
74
89
    return ctx;
75
89
}
76
77
static void *kdf_scrypt_new(void *provctx)
78
89
{
79
89
    return kdf_scrypt_new_inner(PROV_LIBCTX_OF(provctx));
80
89
}
81
82
static void kdf_scrypt_free(void *vctx)
83
89
{
84
89
    KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
85
86
89
    if (ctx != NULL) {
87
89
        OPENSSL_free(ctx->propq);
88
89
        EVP_MD_free(ctx->sha256);
89
89
        kdf_scrypt_reset(ctx);
90
89
        OPENSSL_free(ctx);
91
89
    }
92
89
}
93
94
static void kdf_scrypt_reset(void *vctx)
95
89
{
96
89
    KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
97
98
89
    OPENSSL_free(ctx->salt);
99
89
    ctx->salt = NULL;
100
89
    OPENSSL_clear_free(ctx->pass, ctx->pass_len);
101
89
    ctx->pass = NULL;
102
89
    kdf_scrypt_init(ctx);
103
89
}
104
105
static void *kdf_scrypt_dup(void *vctx)
106
0
{
107
0
    const KDF_SCRYPT *src = (const KDF_SCRYPT *)vctx;
108
0
    KDF_SCRYPT *dest;
109
110
0
    dest = kdf_scrypt_new_inner(src->libctx);
111
0
    if (dest != NULL) {
112
0
        if (src->sha256 != NULL && !EVP_MD_up_ref(src->sha256))
113
0
            goto err;
114
0
        if (src->propq != NULL) {
115
0
            dest->propq = OPENSSL_strdup(src->propq);
116
0
            if (dest->propq == NULL)
117
0
                goto err;
118
0
        }
119
0
        if (!ossl_prov_memdup(src->salt, src->salt_len,
120
0
                &dest->salt, &dest->salt_len)
121
0
            || !ossl_prov_memdup(src->pass, src->pass_len,
122
0
                &dest->pass, &dest->pass_len))
123
0
            goto err;
124
0
        dest->N = src->N;
125
0
        dest->r = src->r;
126
0
        dest->p = src->p;
127
0
        dest->maxmem_bytes = src->maxmem_bytes;
128
0
        dest->sha256 = src->sha256;
129
0
    }
130
0
    return dest;
131
132
0
err:
133
0
    kdf_scrypt_free(dest);
134
0
    return NULL;
135
0
}
136
137
static void kdf_scrypt_init(KDF_SCRYPT *ctx)
138
178
{
139
    /* Default values are the most conservative recommendation given in the
140
     * original paper of C. Percival. Derivation uses roughly 1 GiB of memory
141
     * for this parameter choice (approx. 128 * r * N * p bytes).
142
     */
143
178
    ctx->N = 1 << 20;
144
178
    ctx->r = 8;
145
178
    ctx->p = 1;
146
178
    ctx->maxmem_bytes = 1025 * 1024 * 1024;
147
178
}
148
149
static int scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
150
    const OSSL_PARAM *p)
151
178
{
152
178
    OPENSSL_clear_free(*buffer, *buflen);
153
178
    *buffer = NULL;
154
178
    *buflen = 0;
155
156
178
    if (p->data_size == 0) {
157
60
        if ((*buffer = OPENSSL_malloc(1)) == NULL)
158
0
            return 0;
159
118
    } else if (p->data != NULL) {
160
118
        if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
161
0
            return 0;
162
118
    }
163
178
    return 1;
164
178
}
165
166
static int set_digest(KDF_SCRYPT *ctx)
167
0
{
168
0
    EVP_MD_free(ctx->sha256);
169
0
    ctx->sha256 = EVP_MD_fetch(ctx->libctx, "sha256", ctx->propq);
170
0
    if (ctx->sha256 == NULL) {
171
0
        ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA256);
172
0
        return 0;
173
0
    }
174
0
    return 1;
175
0
}
176
177
static int set_property_query(KDF_SCRYPT *ctx, const char *propq)
178
0
{
179
0
    OPENSSL_free(ctx->propq);
180
0
    ctx->propq = NULL;
181
0
    if (propq != NULL) {
182
0
        ctx->propq = OPENSSL_strdup(propq);
183
0
        if (ctx->propq == NULL)
184
0
            return 0;
185
0
    }
186
0
    return 1;
187
0
}
188
189
static int kdf_scrypt_derive(void *vctx, unsigned char *key, size_t keylen,
190
    const OSSL_PARAM params[])
191
0
{
192
0
    KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx;
193
194
0
    if (!ossl_prov_is_running() || !kdf_scrypt_set_ctx_params(ctx, params))
195
0
        return 0;
196
197
0
    if (ctx->pass == NULL) {
198
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
199
0
        return 0;
200
0
    }
201
202
0
    if (ctx->salt == NULL) {
203
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
204
0
        return 0;
205
0
    }
206
207
0
    if (ctx->sha256 == NULL && !set_digest(ctx))
208
0
        return 0;
209
210
0
    return scrypt_alg((char *)ctx->pass, ctx->pass_len, ctx->salt,
211
0
        ctx->salt_len, ctx->N, ctx->r, ctx->p,
212
0
        ctx->maxmem_bytes, key, keylen, ctx->sha256,
213
0
        ctx->libctx, ctx->propq);
214
0
}
215
216
static int is_power_of_two(uint64_t value)
217
0
{
218
0
    return (value != 0) && ((value & (value - 1)) == 0);
219
0
}
220
221
/* clang-format off */
222
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
223
#ifndef scrypt_set_ctx_params_list
224
static const OSSL_PARAM scrypt_set_ctx_params_list[] = {
225
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
226
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
227
    OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_N, NULL),
228
    OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_R, NULL),
229
    OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_P, NULL),
230
    OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, NULL),
231
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
232
    OSSL_PARAM_END
233
};
234
#endif
235
236
#ifndef scrypt_set_ctx_params_st
237
struct scrypt_set_ctx_params_st {
238
    OSSL_PARAM *maxmem;
239
    OSSL_PARAM *n;
240
    OSSL_PARAM *p;
241
    OSSL_PARAM *propq;
242
    OSSL_PARAM *pw;
243
    OSSL_PARAM *r;
244
    OSSL_PARAM *salt;
245
};
246
#endif
247
248
#ifndef scrypt_set_ctx_params_decoder
249
static int scrypt_set_ctx_params_decoder
250
    (const OSSL_PARAM *p, struct scrypt_set_ctx_params_st *r)
251
33
{
252
33
    const char *s;
253
254
33
    memset(r, 0, sizeof(*r));
255
33
    if (p != NULL)
256
264
        for (; (s = p->key) != NULL; p++)
257
231
            switch(s[0]) {
258
0
            default:
259
0
                break;
260
33
            case 'm':
261
33
                if (ossl_likely(strcmp("axmem_bytes", s + 1) == 0)) {
262
                    /* OSSL_KDF_PARAM_SCRYPT_MAXMEM */
263
33
                    if (ossl_unlikely(r->maxmem != NULL)) {
264
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
265
0
                                       "param %s is repeated", s);
266
0
                        return 0;
267
0
                    }
268
33
                    r->maxmem = (OSSL_PARAM *)p;
269
33
                }
270
33
                break;
271
33
            case 'n':
272
33
                switch(s[1]) {
273
0
                default:
274
0
                    break;
275
33
                case '\0':
276
33
                    if (ossl_unlikely(r->n != NULL)) {
277
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
278
0
                                       "param %s is repeated", s);
279
0
                        return 0;
280
0
                    }
281
33
                    r->n = (OSSL_PARAM *)p;
282
33
                }
283
33
                break;
284
99
            case 'p':
285
99
                switch(s[1]) {
286
0
                default:
287
0
                    break;
288
33
                case 'a':
289
33
                    if (ossl_likely(strcmp("ss", s + 2) == 0)) {
290
                        /* OSSL_KDF_PARAM_PASSWORD */
291
33
                        if (ossl_unlikely(r->pw != NULL)) {
292
0
                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
293
0
                                           "param %s is repeated", s);
294
0
                            return 0;
295
0
                        }
296
33
                        r->pw = (OSSL_PARAM *)p;
297
33
                    }
298
33
                    break;
299
33
                case 'r':
300
33
                    if (ossl_likely(strcmp("operties", s + 2) == 0)) {
301
                        /* OSSL_KDF_PARAM_PROPERTIES */
302
33
                        if (ossl_unlikely(r->propq != NULL)) {
303
0
                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
304
0
                                           "param %s is repeated", s);
305
0
                            return 0;
306
0
                        }
307
33
                        r->propq = (OSSL_PARAM *)p;
308
33
                    }
309
33
                    break;
310
33
                case '\0':
311
33
                    if (ossl_unlikely(r->p != NULL)) {
312
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
313
0
                                       "param %s is repeated", s);
314
0
                        return 0;
315
0
                    }
316
33
                    r->p = (OSSL_PARAM *)p;
317
99
                }
318
99
                break;
319
99
            case 'r':
320
33
                switch(s[1]) {
321
0
                default:
322
0
                    break;
323
33
                case '\0':
324
33
                    if (ossl_unlikely(r->r != NULL)) {
325
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
326
0
                                       "param %s is repeated", s);
327
0
                        return 0;
328
0
                    }
329
33
                    r->r = (OSSL_PARAM *)p;
330
33
                }
331
33
                break;
332
33
            case 's':
333
33
                if (ossl_likely(strcmp("alt", s + 1) == 0)) {
334
                    /* OSSL_KDF_PARAM_SALT */
335
33
                    if (ossl_unlikely(r->salt != NULL)) {
336
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
337
0
                                       "param %s is repeated", s);
338
0
                        return 0;
339
0
                    }
340
33
                    r->salt = (OSSL_PARAM *)p;
341
33
                }
342
231
            }
343
33
    return 1;
344
33
}
345
#endif
346
/* End of machine generated */
347
/* clang-format on */
348
349
static int kdf_scrypt_set_ctx_params(void *vctx, const OSSL_PARAM params[])
350
33
{
351
33
    struct scrypt_set_ctx_params_st p;
352
33
    KDF_SCRYPT *ctx = vctx;
353
33
    uint64_t u64_value;
354
355
33
    if (ctx == NULL || !scrypt_set_ctx_params_decoder(params, &p))
356
0
        return 0;
357
358
33
    if (p.pw != NULL && !scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p.pw))
359
0
        return 0;
360
361
33
    if (p.salt != NULL && !scrypt_set_membuf(&ctx->salt, &ctx->salt_len, p.salt))
362
0
        return 0;
363
364
33
    if (p.n != NULL) {
365
33
        if (!OSSL_PARAM_get_uint64(p.n, &u64_value)
366
33
            || u64_value <= 1
367
0
            || !is_power_of_two(u64_value))
368
33
            return 0;
369
0
        ctx->N = u64_value;
370
0
    }
371
372
0
    if (p.r != NULL) {
373
0
        if (!OSSL_PARAM_get_uint64(p.r, &u64_value) || u64_value < 1)
374
0
            return 0;
375
0
        ctx->r = u64_value;
376
0
    }
377
378
0
    if (p.p != NULL) {
379
0
        if (!OSSL_PARAM_get_uint64(p.p, &u64_value) || u64_value < 1)
380
0
            return 0;
381
0
        ctx->p = u64_value;
382
0
    }
383
384
0
    if (p.maxmem != NULL) {
385
0
        if (!OSSL_PARAM_get_uint64(p.maxmem, &u64_value) || u64_value < 1)
386
0
            return 0;
387
0
        ctx->maxmem_bytes = u64_value;
388
0
    }
389
390
0
    if (p.propq != NULL) {
391
0
        if (p.propq->data_type != OSSL_PARAM_UTF8_STRING
392
0
            || !set_property_query(ctx, p.propq->data)
393
0
            || !set_digest(ctx))
394
0
            return 0;
395
0
    }
396
0
    return 1;
397
0
}
398
399
static const OSSL_PARAM *kdf_scrypt_settable_ctx_params(ossl_unused void *ctx,
400
    ossl_unused void *p_ctx)
401
102
{
402
102
    return scrypt_set_ctx_params_list;
403
102
}
404
405
/* clang-format off */
406
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
407
#ifndef scrypt_get_ctx_params_list
408
static const OSSL_PARAM scrypt_get_ctx_params_list[] = {
409
    OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
410
    OSSL_PARAM_END
411
};
412
#endif
413
414
#ifndef scrypt_get_ctx_params_st
415
struct scrypt_get_ctx_params_st {
416
    OSSL_PARAM *size;
417
};
418
#endif
419
420
#ifndef scrypt_get_ctx_params_decoder
421
static int scrypt_get_ctx_params_decoder
422
    (const OSSL_PARAM *p, struct scrypt_get_ctx_params_st *r)
423
0
{
424
0
    const char *s;
425
426
0
    memset(r, 0, sizeof(*r));
427
0
    if (p != NULL)
428
0
        for (; (s = p->key) != NULL; p++)
429
0
            if (ossl_likely(strcmp("size", s + 0) == 0)) {
430
                /* OSSL_KDF_PARAM_SIZE */
431
0
                if (ossl_unlikely(r->size != NULL)) {
432
0
                    ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
433
0
                                   "param %s is repeated", s);
434
0
                    return 0;
435
0
                }
436
0
                r->size = (OSSL_PARAM *)p;
437
0
            }
438
0
    return 1;
439
0
}
440
#endif
441
/* End of machine generated */
442
/* clang-format on */
443
444
static int kdf_scrypt_get_ctx_params(void *vctx, OSSL_PARAM params[])
445
0
{
446
0
    struct scrypt_get_ctx_params_st p;
447
0
    KDF_SCRYPT *ctx = vctx;
448
449
0
    if (ctx == NULL || !scrypt_get_ctx_params_decoder(params, &p))
450
0
        return 0;
451
452
0
    if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, SIZE_MAX))
453
0
        return 0;
454
0
    return 1;
455
0
}
456
457
static const OSSL_PARAM *kdf_scrypt_gettable_ctx_params(ossl_unused void *ctx,
458
    ossl_unused void *p_ctx)
459
0
{
460
0
    return scrypt_get_ctx_params_list;
461
0
}
462
463
const OSSL_DISPATCH ossl_kdf_scrypt_functions[] = {
464
    { OSSL_FUNC_KDF_NEWCTX, (void (*)(void))kdf_scrypt_new },
465
    { OSSL_FUNC_KDF_DUPCTX, (void (*)(void))kdf_scrypt_dup },
466
    { OSSL_FUNC_KDF_FREECTX, (void (*)(void))kdf_scrypt_free },
467
    { OSSL_FUNC_KDF_RESET, (void (*)(void))kdf_scrypt_reset },
468
    { OSSL_FUNC_KDF_DERIVE, (void (*)(void))kdf_scrypt_derive },
469
    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
470
        (void (*)(void))kdf_scrypt_settable_ctx_params },
471
    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))kdf_scrypt_set_ctx_params },
472
    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
473
        (void (*)(void))kdf_scrypt_gettable_ctx_params },
474
    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))kdf_scrypt_get_ctx_params },
475
    OSSL_DISPATCH_END
476
};
477
478
0
#define R(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
479
static void salsa208_word_specification(uint32_t inout[16])
480
0
{
481
0
    int i;
482
0
    uint32_t x[16];
483
484
0
    memcpy(x, inout, sizeof(x));
485
0
    for (i = 8; i > 0; i -= 2) {
486
0
        x[4] ^= R(x[0] + x[12], 7);
487
0
        x[8] ^= R(x[4] + x[0], 9);
488
0
        x[12] ^= R(x[8] + x[4], 13);
489
0
        x[0] ^= R(x[12] + x[8], 18);
490
0
        x[9] ^= R(x[5] + x[1], 7);
491
0
        x[13] ^= R(x[9] + x[5], 9);
492
0
        x[1] ^= R(x[13] + x[9], 13);
493
0
        x[5] ^= R(x[1] + x[13], 18);
494
0
        x[14] ^= R(x[10] + x[6], 7);
495
0
        x[2] ^= R(x[14] + x[10], 9);
496
0
        x[6] ^= R(x[2] + x[14], 13);
497
0
        x[10] ^= R(x[6] + x[2], 18);
498
0
        x[3] ^= R(x[15] + x[11], 7);
499
0
        x[7] ^= R(x[3] + x[15], 9);
500
0
        x[11] ^= R(x[7] + x[3], 13);
501
0
        x[15] ^= R(x[11] + x[7], 18);
502
0
        x[1] ^= R(x[0] + x[3], 7);
503
0
        x[2] ^= R(x[1] + x[0], 9);
504
0
        x[3] ^= R(x[2] + x[1], 13);
505
0
        x[0] ^= R(x[3] + x[2], 18);
506
0
        x[6] ^= R(x[5] + x[4], 7);
507
0
        x[7] ^= R(x[6] + x[5], 9);
508
0
        x[4] ^= R(x[7] + x[6], 13);
509
0
        x[5] ^= R(x[4] + x[7], 18);
510
0
        x[11] ^= R(x[10] + x[9], 7);
511
0
        x[8] ^= R(x[11] + x[10], 9);
512
0
        x[9] ^= R(x[8] + x[11], 13);
513
0
        x[10] ^= R(x[9] + x[8], 18);
514
0
        x[12] ^= R(x[15] + x[14], 7);
515
0
        x[13] ^= R(x[12] + x[15], 9);
516
0
        x[14] ^= R(x[13] + x[12], 13);
517
0
        x[15] ^= R(x[14] + x[13], 18);
518
0
    }
519
0
    for (i = 0; i < 16; ++i)
520
0
        inout[i] += x[i];
521
0
    OPENSSL_cleanse(x, sizeof(x));
522
0
}
523
524
static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
525
0
{
526
0
    uint64_t i, j;
527
0
    uint32_t X[16], *pB;
528
529
0
    memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
530
0
    pB = B;
531
0
    for (i = 0; i < r * 2; i++) {
532
0
        for (j = 0; j < 16; j++)
533
0
            X[j] ^= *pB++;
534
0
        salsa208_word_specification(X);
535
0
        memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
536
0
    }
537
0
    OPENSSL_cleanse(X, sizeof(X));
538
0
}
539
540
static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
541
    uint32_t *X, uint32_t *T, uint32_t *V)
542
0
{
543
0
    unsigned char *pB;
544
0
    uint32_t *pV;
545
0
    uint64_t i, k;
546
547
    /* Convert from little endian input */
548
0
    for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
549
0
        *pV = *pB++;
550
0
        *pV |= *pB++ << 8;
551
0
        *pV |= *pB++ << 16;
552
0
        *pV |= (uint32_t)*pB++ << 24;
553
0
    }
554
555
0
    for (i = 1; i < N; i++, pV += 32 * r)
556
0
        scryptBlockMix(pV, pV - 32 * r, r);
557
558
0
    scryptBlockMix(X, V + (N - 1) * 32 * r, r);
559
560
0
    for (i = 0; i < N; i++) {
561
0
        uint32_t j;
562
0
        j = X[16 * (2 * r - 1)] % N;
563
0
        pV = V + 32 * r * j;
564
0
        for (k = 0; k < 32 * r; k++)
565
0
            T[k] = X[k] ^ *pV++;
566
0
        scryptBlockMix(X, T, r);
567
0
    }
568
    /* Convert output to little endian */
569
0
    for (i = 0, pB = B; i < 32 * r; i++) {
570
0
        uint32_t xtmp = X[i];
571
0
        *pB++ = xtmp & 0xff;
572
0
        *pB++ = (xtmp >> 8) & 0xff;
573
0
        *pB++ = (xtmp >> 16) & 0xff;
574
0
        *pB++ = (xtmp >> 24) & 0xff;
575
0
    }
576
0
}
577
578
#ifndef SIZE_MAX
579
#define SIZE_MAX ((size_t)-1)
580
#endif
581
582
/*
583
 * Maximum power of two that will fit in uint64_t: this should work on
584
 * most (all?) platforms.
585
 */
586
587
0
#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1)
588
589
/*
590
 * Maximum value of p * r:
591
 * p <= ((2^32-1) * hLen) / MFLen =>
592
 * p <= ((2^32-1) * 32) / (128 * r) =>
593
 * p * r <= (2^30-1)
594
 */
595
596
0
#define SCRYPT_PR_MAX ((1 << 30) - 1)
597
598
static int scrypt_alg(const char *pass, size_t passlen,
599
    const unsigned char *salt, size_t saltlen,
600
    uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
601
    unsigned char *key, size_t keylen, EVP_MD *sha256,
602
    OSSL_LIB_CTX *libctx, const char *propq)
603
0
{
604
0
    int rv = 0;
605
0
    unsigned char *B;
606
0
    uint32_t *X, *V, *T;
607
0
    uint64_t i, Blen, Vlen;
608
609
    /* Sanity check parameters */
610
    /* initial check, r,p must be non zero, N >= 2 and a power of 2 */
611
0
    if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
612
0
        return 0;
613
    /* Check p * r < SCRYPT_PR_MAX avoiding overflow */
614
0
    if (p > SCRYPT_PR_MAX / r) {
615
0
        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
616
0
        return 0;
617
0
    }
618
619
    /*
620
     * Need to check N: if 2^(128 * r / 8) overflows limit this is
621
     * automatically satisfied since N <= UINT64_MAX.
622
     */
623
624
0
    if (16 * r <= LOG2_UINT64_MAX) {
625
0
        if (N >= (((uint64_t)1) << (16 * r))) {
626
0
            ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
627
0
            return 0;
628
0
        }
629
0
    }
630
631
    /* Memory checks: check total allocated buffer size fits in uint64_t */
632
633
    /*
634
     * B size in section 5 step 1.S
635
     * Note: we know p * 128 * r < UINT64_MAX because we already checked
636
     * p * r < SCRYPT_PR_MAX
637
     */
638
0
    Blen = p * 128 * r;
639
    /*
640
     * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
641
     * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
642
     */
643
0
    if (Blen > INT_MAX) {
644
0
        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
645
0
        return 0;
646
0
    }
647
648
    /*
649
     * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
650
     * This is combined size V, X and T (section 4)
651
     */
652
0
    i = UINT64_MAX / (32 * sizeof(uint32_t));
653
0
    if (N + 2 > i / r) {
654
0
        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
655
0
        return 0;
656
0
    }
657
0
    Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
658
659
    /* check total allocated size fits in uint64_t */
660
0
    if (Blen > UINT64_MAX - Vlen) {
661
0
        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
662
0
        return 0;
663
0
    }
664
665
    /* Check that the maximum memory doesn't exceed a size_t limits */
666
0
    if (maxmem > SIZE_MAX)
667
0
        maxmem = SIZE_MAX;
668
669
0
    if (Blen + Vlen > maxmem) {
670
0
        ERR_raise(ERR_LIB_EVP, EVP_R_MEMORY_LIMIT_EXCEEDED);
671
0
        return 0;
672
0
    }
673
674
    /* If no key return to indicate parameters are OK */
675
0
    if (key == NULL)
676
0
        return 1;
677
678
0
    B = OPENSSL_malloc((size_t)(Blen + Vlen));
679
0
    if (B == NULL)
680
0
        return 0;
681
0
    X = (uint32_t *)(B + Blen);
682
0
    T = X + 32 * r;
683
0
    V = T + 32 * r;
684
0
    if (ossl_pkcs5_pbkdf2_hmac_ex(pass, (int)passlen, salt, (int)saltlen, 1,
685
0
            sha256, (int)Blen, B, libctx, propq)
686
0
        == 0)
687
0
        goto err;
688
689
0
    for (i = 0; i < p; i++)
690
0
        scryptROMix(B + 128 * r * i, r, N, X, T, V);
691
692
0
    if (ossl_pkcs5_pbkdf2_hmac_ex(pass, (int)passlen, B, (int)Blen, 1, sha256,
693
0
            (int)keylen, key, libctx, propq)
694
0
        == 0)
695
0
        goto err;
696
0
    rv = 1;
697
0
err:
698
0
    if (rv == 0)
699
0
        ERR_raise(ERR_LIB_EVP, EVP_R_PBKDF2_ERROR);
700
701
0
    OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
702
0
    return rv;
703
0
}
704
705
#endif