From cefa762ee5c28359986c6af5bf4db4e901f75846 Mon Sep 17 00:00:00 2001 From: Johannes Bauer Date: Sat, 22 Jul 2017 20:04:55 +0200 Subject: [PATCH] Add interface to the scrypt KDF by means of PKEY_METHOD Add an interface that allows accessing the scrypt KDF as a PKEY_METHOD. This fixes #4021 (at least for the scrypt portion of the issue). Reviewed-by: Paul Dale Reviewed-by: Stephen Henson (Merged from https://github.com/openssl/openssl/pull/4026) --- crypto/err/openssl.txt | 7 + crypto/evp/pmeth_lib.c | 10 + crypto/include/internal/evp_int.h | 1 + crypto/kdf/build.info | 2 +- crypto/kdf/kdf_err.c | 10 + crypto/kdf/scrypt.c | 258 +++++++++++++++++++++++ crypto/objects/obj_dat.h | 4 +- crypto/objects/objects.txt | 3 +- include/openssl/evp.h | 3 + include/openssl/kdf.h | 31 +++ include/openssl/kdferr.h | 7 + include/openssl/obj_mac.h | 1 + test/recipes/30-test_evp_data/evpkdf.txt | 50 +++++ util/libcrypto.num | 1 + 14 files changed, 384 insertions(+), 4 deletions(-) create mode 100644 crypto/kdf/scrypt.c diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 6d7ac4ef8e..cbbbdaee5f 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -703,6 +703,9 @@ EVP_F_RC5_CTRL:125:rc5_ctrl EVP_F_UPDATE:173:update KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive +KDF_F_PKEY_SCRYPT_CTRL_STR:104:pkey_scrypt_ctrl_str +KDF_F_PKEY_SCRYPT_CTRL_UINT64:105:pkey_scrypt_ctrl_uint64 +KDF_F_PKEY_SCRYPT_DERIVE:109:pkey_scrypt_derive KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object @@ -1966,12 +1969,16 @@ EVP_R_UNSUPPORTED_SALT_TYPE:126:unsupported salt type EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length KDF_R_INVALID_DIGEST:100:invalid digest +KDF_R_MISSING_ITERATION_COUNT:109:missing iteration count KDF_R_MISSING_KEY:104:missing key KDF_R_MISSING_MESSAGE_DIGEST:105:missing message digest KDF_R_MISSING_PARAMETER:101:missing parameter +KDF_R_MISSING_PASS:110:missing pass +KDF_R_MISSING_SALT:111:missing salt KDF_R_MISSING_SECRET:107:missing secret KDF_R_MISSING_SEED:106:missing seed KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type +KDF_R_VALUE_ERROR:108:value error KDF_R_VALUE_MISSING:102:value missing OBJ_R_OID_EXISTS:102:oid exists OBJ_R_UNKNOWN_NID:101:unknown nid diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index b317e41399..322fdb4aa8 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -21,6 +21,7 @@ typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; +/* This array needs to be in order of NIDs */ static const EVP_PKEY_METHOD *standard_methods[] = { #ifndef OPENSSL_NO_RSA &rsa_pkey_meth, @@ -43,6 +44,9 @@ static const EVP_PKEY_METHOD *standard_methods[] = { #endif #ifndef OPENSSL_NO_DH &dhx_pkey_meth, +#endif +#ifndef OPENSSL_NO_SCRYPT + &scrypt_pkey_meth, #endif &tls1_prf_pkey_meth, #ifndef OPENSSL_NO_EC @@ -355,6 +359,12 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, } +int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, uint64_t value) +{ + return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, &value); +} + int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *name, const char *value) { diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h index 635e7b5b87..be1b9be926 100644 --- a/crypto/include/internal/evp_int.h +++ b/crypto/include/internal/evp_int.h @@ -91,6 +91,7 @@ extern const EVP_PKEY_METHOD ed25519_pkey_meth; extern const EVP_PKEY_METHOD hmac_pkey_meth; extern const EVP_PKEY_METHOD rsa_pkey_meth; extern const EVP_PKEY_METHOD rsa_pss_pkey_meth; +extern const EVP_PKEY_METHOD scrypt_pkey_meth; extern const EVP_PKEY_METHOD tls1_prf_pkey_meth; extern const EVP_PKEY_METHOD hkdf_pkey_meth; extern const EVP_PKEY_METHOD poly1305_pkey_meth; diff --git a/crypto/kdf/build.info b/crypto/kdf/build.info index cbe2080ed7..c166399d0c 100644 --- a/crypto/kdf/build.info +++ b/crypto/kdf/build.info @@ -1,3 +1,3 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ - tls1_prf.c kdf_err.c hkdf.c + tls1_prf.c kdf_err.c hkdf.c scrypt.c diff --git a/crypto/kdf/kdf_err.c b/crypto/kdf/kdf_err.c index 8d2727217d..c7b84b0f51 100644 --- a/crypto/kdf/kdf_err.c +++ b/crypto/kdf/kdf_err.c @@ -16,6 +16,11 @@ static const ERR_STRING_DATA KDF_str_functs[] = { {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_CTRL_STR, 0), "pkey_hkdf_ctrl_str"}, {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_DERIVE, 0), "pkey_hkdf_derive"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_CTRL_STR, 0), + "pkey_scrypt_ctrl_str"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_CTRL_UINT64, 0), + "pkey_scrypt_ctrl_uint64"}, + {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_SCRYPT_DERIVE, 0), "pkey_scrypt_derive"}, {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_CTRL_STR, 0), "pkey_tls1_prf_ctrl_str"}, {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_DERIVE, 0), @@ -25,14 +30,19 @@ static const ERR_STRING_DATA KDF_str_functs[] = { static const ERR_STRING_DATA KDF_str_reasons[] = { {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_INVALID_DIGEST), "invalid digest"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_ITERATION_COUNT), + "missing iteration count"}, {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_KEY), "missing key"}, {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_MESSAGE_DIGEST), "missing message digest"}, {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_PARAMETER), "missing parameter"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_PASS), "missing pass"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SALT), "missing salt"}, {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SECRET), "missing secret"}, {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_MISSING_SEED), "missing seed"}, {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_UNKNOWN_PARAMETER_TYPE), "unknown parameter type"}, + {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_ERROR), "value error"}, {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_MISSING), "value missing"}, {0, NULL} }; diff --git a/crypto/kdf/scrypt.c b/crypto/kdf/scrypt.c new file mode 100644 index 0000000000..c7aa823e49 --- /dev/null +++ b/crypto/kdf/scrypt.c @@ -0,0 +1,258 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (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 + */ + +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/evp_int.h" + +static int atou64(const char *nptr, uint64_t *result); + +typedef struct { + unsigned char *pass; + size_t pass_len; + unsigned char *salt; + size_t salt_len; + uint64_t N, r, p; + uint64_t maxmem_bytes; +} SCRYPT_PKEY_CTX; + +/* Custom uint64_t parser since we do not have strtoull */ +static int atou64(const char *nptr, uint64_t *result) +{ + uint64_t value = 0; + + while (*nptr) { + unsigned int digit; + uint64_t new_value; + + if ((*nptr < '0') || (*nptr > '9')) { + return 0; + } + digit = (unsigned int)(*nptr - '0'); + new_value = (value * 10) + digit; + if ((new_value < digit) || ((new_value - digit) / 10 != value)) { + /* Overflow */ + return 0; + } + value = new_value; + nptr++; + } + *result = value; + return 1; +} + +static int pkey_scrypt_init(EVP_PKEY_CTX *ctx) +{ + SCRYPT_PKEY_CTX *kctx; + + kctx = OPENSSL_zalloc(sizeof(*kctx)); + if (kctx == NULL) + return 0; + + /* Default values are the most conservative recommendation given in the + * original paper of C. Percival. Derivation uses roughly 1 GiB of memory + * for this parameter choice (approx. 128 * r * (N + p) bytes). + */ + kctx->N = 1 << 20; + kctx->r = 8; + kctx->p = 1; + kctx->maxmem_bytes = 1025 * 1024 * 1024; + + ctx->data = kctx; + + return 1; +} + +static void pkey_scrypt_cleanup(EVP_PKEY_CTX *ctx) +{ + SCRYPT_PKEY_CTX *kctx = ctx->data; + + OPENSSL_clear_free(kctx->salt, kctx->salt_len); + OPENSSL_clear_free(kctx->pass, kctx->pass_len); + OPENSSL_free(kctx); +} + +static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen, + const unsigned char *new_buffer, + const int new_buflen) +{ + if (new_buffer == NULL) + return 1; + + if (new_buflen < 0) + return 0; + + if (*buffer != NULL) + OPENSSL_clear_free(*buffer, *buflen); + + if (new_buflen > 0) { + *buffer = OPENSSL_memdup(new_buffer, new_buflen); + } else { + *buffer = OPENSSL_malloc(1); + } + if (*buffer == NULL) + return 0; + + *buflen = new_buflen; + return 1; +} + +static int is_power_of_two(uint64_t value) +{ + return (value != 0) && ((value & (value - 1)) == 0); +} + +static int pkey_scrypt_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + SCRYPT_PKEY_CTX *kctx = ctx->data; + uint64_t u64_value; + + switch (type) { + case EVP_PKEY_CTRL_PASS: + return pkey_scrypt_set_membuf(&kctx->pass, &kctx->pass_len, p2, p1); + + case EVP_PKEY_CTRL_SCRYPT_SALT: + return pkey_scrypt_set_membuf(&kctx->salt, &kctx->salt_len, p2, p1); + + case EVP_PKEY_CTRL_SCRYPT_N: + u64_value = *((uint64_t *)p2); + if ((u64_value <= 1) || !is_power_of_two(u64_value)) + return 0; + kctx->N = u64_value; + return 1; + + case EVP_PKEY_CTRL_SCRYPT_R: + u64_value = *((uint64_t *)p2); + if (u64_value < 1) + return 0; + kctx->r = u64_value; + return 1; + + case EVP_PKEY_CTRL_SCRYPT_P: + u64_value = *((uint64_t *)p2); + if (u64_value < 1) + return 0; + kctx->p = u64_value; + return 1; + + case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES: + u64_value = *((uint64_t *)p2); + if (u64_value < 1) + return 0; + kctx->maxmem_bytes = u64_value; + return 1; + + default: + return -2; + + } +} + +static int pkey_scrypt_ctrl_uint64(EVP_PKEY_CTX *ctx, int type, + const char *value) +{ + uint64_t int_value; + + if (!atou64(value, &int_value)) { + KDFerr(KDF_F_PKEY_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR); + return 0; + } + return pkey_scrypt_ctrl(ctx, type, 0, &int_value); +} + +static int pkey_scrypt_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value) +{ + if (value == NULL) { + KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING); + return 0; + } + + if (strcmp(type, "pass") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_PASS, value); + + if (strcmp(type, "hexpass") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_PASS, value); + + if (strcmp(type, "salt") == 0) + return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value); + + if (strcmp(type, "hexsalt") == 0) + return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value); + + if (strcmp(type, "N") == 0) + return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_N, value); + + if (strcmp(type, "r") == 0) + return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_R, value); + + if (strcmp(type, "p") == 0) + return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_P, value); + + if (strcmp(type, "maxmem_bytes") == 0) + return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, + value); + + KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE); + return -2; +} + +static int pkey_scrypt_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + SCRYPT_PKEY_CTX *kctx = ctx->data; + + if (kctx->pass == NULL) { + KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_PASS); + return 0; + } + + if (kctx->salt == NULL) { + KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_SALT); + return 0; + } + + return EVP_PBE_scrypt((char *)kctx->pass, kctx->pass_len, kctx->salt, + kctx->salt_len, kctx->N, kctx->r, kctx->p, + kctx->maxmem_bytes, key, *keylen); +} + +const EVP_PKEY_METHOD scrypt_pkey_meth = { + EVP_PKEY_SCRYPT, + 0, + pkey_scrypt_init, + 0, + pkey_scrypt_cleanup, + + 0, 0, + 0, 0, + + 0, + 0, + + 0, + 0, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, + pkey_scrypt_derive, + pkey_scrypt_ctrl, + pkey_scrypt_ctrl_str +}; diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 3de3110b53..9647e31677 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -1987,7 +1987,7 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { {"CAMELLIA-256-CCM", "camellia-256-ccm", NID_camellia_256_ccm, 8, &so[6330]}, {"CAMELLIA-256-CTR", "camellia-256-ctr", NID_camellia_256_ctr, 8, &so[6338]}, {"CAMELLIA-256-CMAC", "camellia-256-cmac", NID_camellia_256_cmac, 8, &so[6346]}, - {"id-scrypt", "id-scrypt", NID_id_scrypt, 9, &so[6354]}, + {"id-scrypt", "scrypt", NID_id_scrypt, 9, &so[6354]}, {"id-tc26", "id-tc26", NID_id_tc26, 5, &so[6363]}, {"gost89-cnt-12", "gost89-cnt-12", NID_gost89_cnt_12}, {"gost-mac-12", "gost-mac-12", NID_gost_mac_12}, @@ -3883,7 +3883,6 @@ static const unsigned int ln_objs[NUM_LN] = { 314, /* "id-regInfo" */ 322, /* "id-regInfo-certReq" */ 321, /* "id-regInfo-utf8Pairs" */ - 973, /* "id-scrypt" */ 191, /* "id-smime-aa" */ 215, /* "id-smime-aa-contentHint" */ 218, /* "id-smime-aa-contentIdentifier" */ @@ -4135,6 +4134,7 @@ static const unsigned int ln_objs[NUM_LN] = { 291, /* "sbgp-autonomousSysNum" */ 290, /* "sbgp-ipAddrBlock" */ 292, /* "sbgp-routerIdentifier" */ + 973, /* "scrypt" */ 159, /* "sdsiCertificate" */ 859, /* "searchGuide" */ 704, /* "secp112r1" */ diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 8f17cc4a44..7464d670e9 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -1524,7 +1524,8 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme 1 3 6 1 4 1 311 60 2 1 3 : jurisdictionC : jurisdictionCountryName # SCRYPT algorithm -1 3 6 1 4 1 11591 4 11 : id-scrypt +!Cname id-scrypt +1 3 6 1 4 1 11591 4 11 : id-scrypt : scrypt # NID for TLS1 PRF : TLS1-PRF : tls1-prf diff --git a/include/openssl/evp.h b/include/openssl/evp.h index af7043b2ea..dd02077e05 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -52,6 +52,7 @@ # define EVP_PKEY_EC NID_X9_62_id_ecPublicKey # define EVP_PKEY_HMAC NID_hmac # define EVP_PKEY_CMAC NID_cmac +# define EVP_PKEY_SCRYPT NID_id_scrypt # define EVP_PKEY_TLS1_PRF NID_tls1_prf # define EVP_PKEY_HKDF NID_hkdf # define EVP_PKEY_POLY1305 NID_poly1305 @@ -1275,6 +1276,8 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2); int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value); +int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, uint64_t value); int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str); int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex); diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h index bd7451566f..26380ca479 100644 --- a/include/openssl/kdf.h +++ b/include/openssl/kdf.h @@ -23,6 +23,12 @@ extern "C" { # define EVP_PKEY_CTRL_HKDF_KEY (EVP_PKEY_ALG_CTRL + 5) # define EVP_PKEY_CTRL_HKDF_INFO (EVP_PKEY_ALG_CTRL + 6) # define EVP_PKEY_CTRL_HKDF_MODE (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_PASS (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_SCRYPT_SALT (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_SCRYPT_N (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_SCRYPT_R (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_SCRYPT_P (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES (EVP_PKEY_ALG_CTRL + 13) # define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0 # define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY 1 @@ -59,6 +65,31 @@ extern "C" { # define EVP_PKEY_CTX_hkdf_mode(pctx, mode) \ EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ EVP_PKEY_CTRL_HKDF_MODE, mode, NULL) + +# define EVP_PKEY_CTX_set1_pbe_pass(pctx, pass, passlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_PASS, passlen, (void *)(pass)) + +# define EVP_PKEY_CTX_set1_scrypt_salt(pctx, salt, saltlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_SALT, saltlen, (void *)(salt)) + +# define EVP_PKEY_CTX_set_scrypt_N(pctx, n) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_N, n) + +# define EVP_PKEY_CTX_set_scrypt_r(pctx, r) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_R, r) + +# define EVP_PKEY_CTX_set_scrypt_p(pctx, p) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_P, p) + +# define EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, maxmem_bytes) \ + EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, maxmem_bytes) + int ERR_load_KDF_strings(void); # ifdef __cplusplus diff --git a/include/openssl/kdferr.h b/include/openssl/kdferr.h index c01b735c24..8f045f06ce 100644 --- a/include/openssl/kdferr.h +++ b/include/openssl/kdferr.h @@ -24,6 +24,9 @@ int ERR_load_KDF_strings(void); */ # define KDF_F_PKEY_HKDF_CTRL_STR 103 # define KDF_F_PKEY_HKDF_DERIVE 102 +# define KDF_F_PKEY_SCRYPT_CTRL_STR 104 +# define KDF_F_PKEY_SCRYPT_CTRL_UINT64 105 +# define KDF_F_PKEY_SCRYPT_DERIVE 109 # define KDF_F_PKEY_TLS1_PRF_CTRL_STR 100 # define KDF_F_PKEY_TLS1_PRF_DERIVE 101 @@ -31,12 +34,16 @@ int ERR_load_KDF_strings(void); * KDF reason codes. */ # define KDF_R_INVALID_DIGEST 100 +# define KDF_R_MISSING_ITERATION_COUNT 109 # define KDF_R_MISSING_KEY 104 # define KDF_R_MISSING_MESSAGE_DIGEST 105 # define KDF_R_MISSING_PARAMETER 101 +# define KDF_R_MISSING_PASS 110 +# define KDF_R_MISSING_SALT 111 # define KDF_R_MISSING_SECRET 107 # define KDF_R_MISSING_SEED 106 # define KDF_R_UNKNOWN_PARAMETER_TYPE 103 +# define KDF_R_VALUE_ERROR 108 # define KDF_R_VALUE_MISSING 102 #endif diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index cd2c60b810..97511171ae 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -4735,6 +4735,7 @@ #define OBJ_jurisdictionCountryName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L #define SN_id_scrypt "id-scrypt" +#define LN_id_scrypt "scrypt" #define NID_id_scrypt 973 #define OBJ_id_scrypt 1L,3L,6L,1L,4L,1L,11591L,4L,11L diff --git a/test/recipes/30-test_evp_data/evpkdf.txt b/test/recipes/30-test_evp_data/evpkdf.txt index 4df8f8fe0a..9a6cc28385 100644 --- a/test/recipes/30-test_evp_data/evpkdf.txt +++ b/test/recipes/30-test_evp_data/evpkdf.txt @@ -252,4 +252,54 @@ Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c Ctrl.salt = salt: Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48 +Title = id-scrypt tests (from draft-josefsson-id-scrypt-kdf-03 and others) + +KDF = scrypt +Ctrl.pass = pass: +Ctrl.salt = salt: +Ctrl.N = N:16 +Ctrl.r = r:1 +Ctrl.p = p:1 +Output = 77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906 + +KDF = scrypt +Ctrl.pass = pass:password +Ctrl.salt = salt:NaCl +Ctrl.N = N:1024 +Ctrl.r = r:8 +Ctrl.p = p:16 +Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640 + +KDF = scrypt +Ctrl.hexpass = hexpass:70617373776f7264 +Ctrl.salt = salt:NaCl +Ctrl.N = N:1024 +Ctrl.r = r:8 +Ctrl.p = p:16 +Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640 + +KDF = scrypt +Ctrl.pass = pass:password +Ctrl.hexsalt = hexsalt:4e61436c +Ctrl.N = N:1024 +Ctrl.r = r:8 +Ctrl.p = p:16 +Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640 + +KDF = scrypt +Ctrl.pass = pass:pleaseletmein +Ctrl.salt = salt:SodiumChloride +Ctrl.N = N:16384 +Ctrl.r = r:8 +Ctrl.p = p:1 +Output = 7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887 + +# Out of memory +KDF = scrypt +Ctrl.pass = pass:pleaseletmein +Ctrl.salt = salt:SodiumChloride +Ctrl.N = N:1048576 +Ctrl.r = r:8 +Ctrl.p = p:1 +Result = INTERNAL_ERROR diff --git a/util/libcrypto.num b/util/libcrypto.num index fbfcb5c083..42284ec9ca 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4379,3 +4379,4 @@ BN_priv_rand_range 4322 1_1_1 EXIST::FUNCTION: ASN1_TIME_normalize 4323 1_1_1 EXIST::FUNCTION: ASN1_TIME_cmp_time_t 4324 1_1_1 EXIST::FUNCTION: ASN1_TIME_compare 4325 1_1_1 EXIST::FUNCTION: +EVP_PKEY_CTX_ctrl_uint64 4326 1_1_1 EXIST::FUNCTION: -- 2.39.2