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