diff options
author | David Makepeace <david.p.makepeace@oracle.com> | 2018-06-22 07:16:18 +1000 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2019-02-13 12:11:49 +0100 |
commit | 5a285addbf39f91d567f95f04b2b41764127950d (patch) | |
tree | 4cdf512d4217da5b6b959552a20a33b6a23a9aaa | |
parent | e0ae0585bee898184cbbe8144d2fa8ce25e8ca72 (diff) |
Added new EVP/KDF API.
Changed PKEY/KDF API to call the new API.
Added wrappers for PKCS5_PBKDF2_HMAC() and EVP_PBE_scrypt() to call the new EVP KDF APIs.
Documentation updated.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6674)
40 files changed, 3211 insertions, 809 deletions
@@ -9,6 +9,13 @@ Changes between 1.1.1 and 3.0.0 [xx XXX xxxx] + *) Added EVP_KDF, an EVP layer KDF API, to simplify adding KDF and PRF + implementations. This includes an EVP_PKEY to EVP_KDF bridge for + those algorithms that were already supported through the EVP_PKEY API + (scrypt, TLS1 PRF and HKDF). The low-level KDF functions for PBKDF2 + and scrypt are now wrappers that call EVP_KDF. + [David Makepeace] + *) Build devcrypto engine as a dynamic engine. [Eneas U de Queiroz] diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index aaea598ba7..a269ac688e 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -753,6 +753,9 @@ EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex EVP_F_EVP_ENCRYPTDECRYPTUPDATE:219:evp_EncryptDecryptUpdate EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate +EVP_F_EVP_KDF_CTRL:224:EVP_KDF_ctrl +EVP_F_EVP_KDF_CTRL_STR:225:EVP_KDF_ctrl_str +EVP_F_EVP_KDF_CTX_NEW_ID:226:EVP_KDF_CTX_new_id EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str EVP_F_EVP_MAC_CTX_COPY:211:EVP_MAC_CTX_copy @@ -823,6 +826,7 @@ EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen +EVP_F_PKEY_KDF_CTRL:227:pkey_kdf_ctrl EVP_F_PKEY_MAC_INIT:214:pkey_mac_init EVP_F_PKEY_SET_TYPE:158:pkey_set_type EVP_F_POLY1305_CTRL:216:poly1305_ctrl @@ -830,7 +834,25 @@ EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth EVP_F_RC5_CTRL:125:rc5_ctrl EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl EVP_F_S390X_AES_GCM_TLS_CIPHER:208:s390x_aes_gcm_tls_cipher +EVP_F_SCRYPT_ALG:228:scrypt_alg EVP_F_UPDATE:173:update +KDF_F_HKDF_EXTRACT:112:HKDF_Extract +KDF_F_KDF_HKDF_DERIVE:113:kdf_hkdf_derive +KDF_F_KDF_HKDF_NEW:114:kdf_hkdf_new +KDF_F_KDF_HKDF_SIZE:115:kdf_hkdf_size +KDF_F_KDF_MD2CTRL:116:kdf_md2ctrl +KDF_F_KDF_PBKDF2_CTRL_STR:117:kdf_pbkdf2_ctrl_str +KDF_F_KDF_PBKDF2_DERIVE:118:kdf_pbkdf2_derive +KDF_F_KDF_PBKDF2_NEW:119:kdf_pbkdf2_new +KDF_F_KDF_SCRYPT_CTRL_STR:120:kdf_scrypt_ctrl_str +KDF_F_KDF_SCRYPT_CTRL_UINT32:121:kdf_scrypt_ctrl_uint32 +KDF_F_KDF_SCRYPT_CTRL_UINT64:122:kdf_scrypt_ctrl_uint64 +KDF_F_KDF_SCRYPT_DERIVE:123:kdf_scrypt_derive +KDF_F_KDF_SCRYPT_NEW:124:kdf_scrypt_new +KDF_F_KDF_TLS1_PRF_CTRL_STR:125:kdf_tls1_prf_ctrl_str +KDF_F_KDF_TLS1_PRF_DERIVE:126:kdf_tls1_prf_derive +KDF_F_KDF_TLS1_PRF_NEW:127:kdf_tls1_prf_new +KDF_F_PBKDF2_SET_MEMBUF:128:pbkdf2_set_membuf KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive KDF_F_PKEY_HKDF_INIT:108:pkey_hkdf_init @@ -842,6 +864,7 @@ KDF_F_PKEY_SCRYPT_SET_MEMBUF:107:pkey_scrypt_set_membuf KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init +KDF_F_SCRYPT_SET_MEMBUF:129:scrypt_set_membuf KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid @@ -2284,6 +2307,7 @@ EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\ operation not supported for this keytype EVP_R_OPERATON_NOT_INITIALIZED:151:operaton not initialized +EVP_R_PARAMETER_TOO_LARGE:187:parameter too large EVP_R_PARTIALLY_OVERLAPPING:162:partially overlapping buffers EVP_R_PBKDF2_ERROR:181:pbkdf2 error EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\ @@ -2320,6 +2344,7 @@ 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 +KDF_R_WRONG_OUTPUT_BUFFER_SIZE:112:wrong output buffer size OBJ_R_OID_EXISTS:102:oid exists OBJ_R_UNKNOWN_NID:101:unknown nid OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error diff --git a/crypto/evp/build.info b/crypto/evp/build.info index 84193b096a..862afa836a 100644 --- a/crypto/evp/build.info +++ b/crypto/evp/build.info @@ -9,7 +9,8 @@ SOURCE[../../libcrypto]=\ p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \ bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \ c_allc.c c_alld.c evp_lib.c bio_ok.c \ - evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \ + evp_pkey.c kdf_lib.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \ + pkey_kdf.c \ e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \ e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \ e_chacha20_poly1305.c cmeth_lib.c \ diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c index 0d4612f314..e8a323f3be 100644 --- a/crypto/evp/e_chacha20_poly1305.c +++ b/crypto/evp/e_chacha20_poly1305.c @@ -14,8 +14,8 @@ # include <openssl/evp.h> # include <openssl/objects.h> -# include "evp_locl.h" # include "internal/evp_int.h" +# include "evp_locl.h" # include "internal/chacha.h" typedef struct { diff --git a/crypto/evp/encode.c b/crypto/evp/encode.c index 5a54a9fe87..3519e3b16c 100644 --- a/crypto/evp/encode.c +++ b/crypto/evp/encode.c @@ -11,8 +11,8 @@ #include <limits.h> #include "internal/cryptlib.h" #include <openssl/evp.h> -#include "evp_locl.h" #include "internal/evp_int.h" +#include "evp_locl.h" static unsigned char conv_ascii2bin(unsigned char a, const unsigned char *table); diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index a4dd97b53a..ef889b0a5c 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -60,6 +60,9 @@ static const ERR_STRING_DATA EVP_str_functs[] = { {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0), "EVP_EncryptFinal_ex"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL, 0), "EVP_KDF_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL_STR, 0), "EVP_KDF_ctrl_str"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTX_NEW_ID, 0), "EVP_KDF_CTX_new_id"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_COPY, 0), "EVP_MAC_CTX_copy"}, @@ -159,6 +162,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = { "PKCS5_v2_PBKDF2_keyivgen"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0), "PKCS5_v2_scrypt_keyivgen"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_KDF_CTRL, 0), "pkey_kdf_ctrl"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_POLY1305_CTRL, 0), "poly1305_ctrl"}, @@ -167,6 +171,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = { {ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_CTRL, 0), "s390x_aes_gcm_ctrl"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_TLS_CIPHER, 0), "s390x_aes_gcm_tls_cipher"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_SCRYPT_ALG, 0), "scrypt_alg"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_UPDATE, 0), "update"}, {0, NULL} }; @@ -254,6 +259,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { "operation not supported for this keytype"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATON_NOT_INITIALIZED), "operaton not initialized"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARAMETER_TOO_LARGE), + "parameter too large"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARTIALLY_OVERLAPPING), "partially overlapping buffers"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PBKDF2_ERROR), "pbkdf2 error"}, diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h index fe69067387..95a9d5c517 100644 --- a/crypto/evp/evp_locl.h +++ b/crypto/evp/evp_locl.h @@ -46,6 +46,11 @@ struct evp_mac_ctx_st { void *data; /* Individual method data */ } /* EVP_MAC_CTX */; +struct evp_kdf_ctx_st { + const EVP_KDF_METHOD *kmeth; + EVP_KDF_IMPL *impl; /* Algorithm-specific data */ +} /* EVP_KDF_CTX */ ; + int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, diff --git a/crypto/evp/evp_pbe.c b/crypto/evp/evp_pbe.c index eb099ab43e..8162a5e436 100644 --- a/crypto/evp/evp_pbe.c +++ b/crypto/evp/evp_pbe.c @@ -12,6 +12,7 @@ #include <openssl/evp.h> #include <openssl/pkcs12.h> #include <openssl/x509.h> +#include "internal/evp_int.h" #include "evp_locl.h" /* Password based encryption (PBE) functions */ diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c new file mode 100644 index 0000000000..05f5cec3a9 --- /dev/null +++ b/crypto/evp/kdf_lib.c @@ -0,0 +1,165 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <stdlib.h> +#include "internal/cryptlib.h" +#include <openssl/engine.h> +#include <openssl/evp.h> +#include <openssl/x509v3.h> +#include <openssl/kdf.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "internal/numbers.h" +#include "evp_locl.h" + +typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); + +/* This array needs to be in order of NIDs */ +static const EVP_KDF_METHOD *standard_methods[] = { + &pbkdf2_kdf_meth, +#ifndef OPENSSL_NO_SCRYPT + &scrypt_kdf_meth, +#endif + &tls1_prf_kdf_meth, + &hkdf_kdf_meth +}; + +DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *, + kmeth); + +static int kmeth_cmp(const EVP_KDF_METHOD *const *a, + const EVP_KDF_METHOD *const *b) +{ + return ((*a)->type - (*b)->type); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *, + kmeth); + +static const EVP_KDF_METHOD *kdf_meth_find(int type) +{ + EVP_KDF_METHOD tmp; + const EVP_KDF_METHOD *t = &tmp, **ret; + + tmp.type = type; + ret = OBJ_bsearch_kmeth(&t, standard_methods, + OSSL_NELEM(standard_methods)); + if (ret == NULL || *ret == NULL) + return NULL; + + return *ret; +} + +EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id) +{ + EVP_KDF_CTX *ret; + const EVP_KDF_METHOD *kmeth; + + kmeth = kdf_meth_find(id); + if (kmeth == NULL) { + EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, EVP_R_UNSUPPORTED_ALGORITHM); + return NULL; + } + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (kmeth->new != NULL && (ret->impl = kmeth->new()) == NULL) { + EVP_KDF_CTX_free(ret); + return NULL; + } + + ret->kmeth = kmeth; + return ret; +} + +void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx) +{ + if (ctx == NULL) + return; + + ctx->kmeth->free(ctx->impl); + OPENSSL_free(ctx); +} + +void EVP_KDF_reset(EVP_KDF_CTX *ctx) +{ + if (ctx == NULL) + return; + + if (ctx->kmeth->reset != NULL) + ctx->kmeth->reset(ctx->impl); +} + +int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...) +{ + int ret; + va_list args; + + va_start(args, cmd); + ret = EVP_KDF_vctrl(ctx, cmd, args); + va_end(args); + + if (ret == -2) + EVPerr(EVP_F_EVP_KDF_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); + + return ret; +} + +int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args) +{ + if (ctx == NULL) + return 0; + + return ctx->kmeth->ctrl(ctx->impl, cmd, args); +} + +int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value) +{ + int ret; + + if (ctx == NULL) + return 0; + + if (ctx->kmeth->ctrl_str == NULL) { + EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); + return -2; + } + + ret = ctx->kmeth->ctrl_str(ctx->impl, type, value); + if (ret == -2) + EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); + + return ret; +} + +size_t EVP_KDF_size(EVP_KDF_CTX *ctx) +{ + if (ctx == NULL) + return 0; + + if (ctx->kmeth->size == NULL) + return SIZE_MAX; + + return ctx->kmeth->size(ctx->impl); +} + +int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen) +{ + if (ctx == NULL) + return 0; + + return ctx->kmeth->derive(ctx->impl, key, keylen); +} + diff --git a/crypto/evp/p5_crpt2.c b/crypto/evp/p5_crpt2.c index a5a15599b5..4210e51678 100644 --- a/crypto/evp/p5_crpt2.c +++ b/crypto/evp/p5_crpt2.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,105 +10,51 @@ #include <stdio.h> #include <stdlib.h> #include "internal/cryptlib.h" -# include <openssl/x509.h> -# include <openssl/evp.h> -# include <openssl/hmac.h> -# include "evp_locl.h" +#include <openssl/x509.h> +#include <openssl/evp.h> +#include <openssl/kdf.h> +#include <openssl/hmac.h> +#include "internal/evp_int.h" +#include "evp_locl.h" /* set this to print out info about the keygen algorithm */ /* #define OPENSSL_DEBUG_PKCS5V2 */ -# ifdef OPENSSL_DEBUG_PKCS5V2 +#ifdef OPENSSL_DEBUG_PKCS5V2 static void h__dump(const unsigned char *p, int len); -# endif - -/* - * This is an implementation of PKCS#5 v2.0 password based encryption key - * derivation function PBKDF2. SHA1 version verified against test vectors - * posted by Peter Gutmann to the PKCS-TNG mailing list. - */ +#endif int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt, int saltlen, int iter, const EVP_MD *digest, int keylen, unsigned char *out) { const char *empty = ""; - unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; - int cplen, j, k, tkeylen, mdlen; - unsigned long i = 1; - HMAC_CTX *hctx_tpl = NULL, *hctx = NULL; - - mdlen = EVP_MD_size(digest); - if (mdlen < 0) - return 0; + int rv = 1; + EVP_KDF_CTX *kctx; - hctx_tpl = HMAC_CTX_new(); - if (hctx_tpl == NULL) - return 0; - p = out; - tkeylen = keylen; + /* Keep documented behaviour. */ if (pass == NULL) { pass = empty; passlen = 0; } else if (passlen == -1) { passlen = strlen(pass); } - if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) { - HMAC_CTX_free(hctx_tpl); - return 0; - } - hctx = HMAC_CTX_new(); - if (hctx == NULL) { - HMAC_CTX_free(hctx_tpl); + if (salt == NULL && saltlen == 0) + salt = (unsigned char *)empty; + + kctx = EVP_KDF_CTX_new_id(EVP_KDF_PBKDF2); + if (kctx == NULL) return 0; - } - while (tkeylen) { - if (tkeylen > mdlen) - cplen = mdlen; - else - cplen = tkeylen; - /* - * We are unlikely to ever use more than 256 blocks (5120 bits!) but - * just in case... - */ - itmp[0] = (unsigned char)((i >> 24) & 0xff); - itmp[1] = (unsigned char)((i >> 16) & 0xff); - itmp[2] = (unsigned char)((i >> 8) & 0xff); - itmp[3] = (unsigned char)(i & 0xff); - if (!HMAC_CTX_copy(hctx, hctx_tpl)) { - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return 0; - } - if (!HMAC_Update(hctx, salt, saltlen) - || !HMAC_Update(hctx, itmp, 4) - || !HMAC_Final(hctx, digtmp, NULL)) { - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return 0; - } - memcpy(p, digtmp, cplen); - for (j = 1; j < iter; j++) { - if (!HMAC_CTX_copy(hctx, hctx_tpl)) { - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return 0; - } - if (!HMAC_Update(hctx, digtmp, mdlen) - || !HMAC_Final(hctx, digtmp, NULL)) { - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return 0; - } - for (k = 0; k < cplen; k++) - p[k] ^= digtmp[k]; - } - tkeylen -= cplen; - i++; - p += cplen; - } - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); + if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, pass, (size_t)passlen) != 1 + || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, + salt, (size_t)saltlen) != 1 + || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_ITER, iter) != 1 + || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, digest) != 1 + || EVP_KDF_derive(kctx, out, keylen) != 1) + rv = 0; + + EVP_KDF_CTX_free(kctx); + # ifdef OPENSSL_DEBUG_PKCS5V2 fprintf(stderr, "Password:\n"); h__dump(pass, passlen); @@ -118,7 +64,7 @@ int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, fprintf(stderr, "Key:\n"); h__dump(out, keylen); # endif - return 1; + return rv; } int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, diff --git a/crypto/evp/pbe_scrypt.c b/crypto/evp/pbe_scrypt.c index 0a3943211c..f8ea1fab38 100644 --- a/crypto/evp/pbe_scrypt.c +++ b/crypto/evp/pbe_scrypt.c @@ -7,135 +7,12 @@ * https://www.openssl.org/source/license.html */ -#include <stddef.h> -#include <stdio.h> -#include <string.h> #include <openssl/evp.h> #include <openssl/err.h> -#include "internal/numbers.h" +#include <openssl/kdf.h> #ifndef OPENSSL_NO_SCRYPT -#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) -static void salsa208_word_specification(uint32_t inout[16]) -{ - int i; - uint32_t x[16]; - memcpy(x, inout, sizeof(x)); - for (i = 8; i > 0; i -= 2) { - x[4] ^= R(x[0] + x[12], 7); - x[8] ^= R(x[4] + x[0], 9); - x[12] ^= R(x[8] + x[4], 13); - x[0] ^= R(x[12] + x[8], 18); - x[9] ^= R(x[5] + x[1], 7); - x[13] ^= R(x[9] + x[5], 9); - x[1] ^= R(x[13] + x[9], 13); - x[5] ^= R(x[1] + x[13], 18); - x[14] ^= R(x[10] + x[6], 7); - x[2] ^= R(x[14] + x[10], 9); - x[6] ^= R(x[2] + x[14], 13); - x[10] ^= R(x[6] + x[2], 18); - x[3] ^= R(x[15] + x[11], 7); - x[7] ^= R(x[3] + x[15], 9); - x[11] ^= R(x[7] + x[3], 13); - x[15] ^= R(x[11] + x[7], 18); - x[1] ^= R(x[0] + x[3], 7); - x[2] ^= R(x[1] + x[0], 9); - x[3] ^= R(x[2] + x[1], 13); - x[0] ^= R(x[3] + x[2], 18); - x[6] ^= R(x[5] + x[4], 7); - x[7] ^= R(x[6] + x[5], 9); - x[4] ^= R(x[7] + x[6], 13); - x[5] ^= R(x[4] + x[7], 18); - x[11] ^= R(x[10] + x[9], 7); - x[8] ^= R(x[11] + x[10], 9); - x[9] ^= R(x[8] + x[11], 13); - x[10] ^= R(x[9] + x[8], 18); - x[12] ^= R(x[15] + x[14], 7); - x[13] ^= R(x[12] + x[15], 9); - x[14] ^= R(x[13] + x[12], 13); - x[15] ^= R(x[14] + x[13], 18); - } - for (i = 0; i < 16; ++i) - inout[i] += x[i]; - OPENSSL_cleanse(x, sizeof(x)); -} - -static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r) -{ - uint64_t i, j; - uint32_t X[16], *pB; - - memcpy(X, B + (r * 2 - 1) * 16, sizeof(X)); - pB = B; - for (i = 0; i < r * 2; i++) { - for (j = 0; j < 16; j++) - X[j] ^= *pB++; - salsa208_word_specification(X); - memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X)); - } - OPENSSL_cleanse(X, sizeof(X)); -} - -static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N, - uint32_t *X, uint32_t *T, uint32_t *V) -{ - unsigned char *pB; - uint32_t *pV; - uint64_t i, k; - - /* Convert from little endian input */ - for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) { - *pV = *pB++; - *pV |= *pB++ << 8; - *pV |= *pB++ << 16; - *pV |= (uint32_t)*pB++ << 24; - } - - for (i = 1; i < N; i++, pV += 32 * r) - scryptBlockMix(pV, pV - 32 * r, r); - - scryptBlockMix(X, V + (N - 1) * 32 * r, r); - - for (i = 0; i < N; i++) { - uint32_t j; - j = X[16 * (2 * r - 1)] % N; - pV = V + 32 * r * j; - for (k = 0; k < 32 * r; k++) - T[k] = X[k] ^ *pV++; - scryptBlockMix(X, T, r); - } - /* Convert output to little endian */ - for (i = 0, pB = B; i < 32 * r; i++) { - uint32_t xtmp = X[i]; - *pB++ = xtmp & 0xff; - *pB++ = (xtmp >> 8) & 0xff; - *pB++ = (xtmp >> 16) & 0xff; - *pB++ = (xtmp >> 24) & 0xff; - } -} - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t)-1) -#endif - -/* - * Maximum power of two that will fit in uint64_t: this should work on - * most (all?) platforms. - */ - -#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1) - -/* - * Maximum value of p * r: - * p <= ((2^32-1) * hLen) / MFLen => - * p <= ((2^32-1) * 32) / (128 * r) => - * p * r <= (2^30-1) - * - */ - -#define SCRYPT_PR_MAX ((1 << 30) - 1) - /* * Maximum permitted memory allow this to be overridden with Configuration * option: e.g. -DSCRYPT_MAX_MEM=0 for maximum possible. @@ -160,107 +37,38 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen, uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, unsigned char *key, size_t keylen) { - int rv = 0; - unsigned char *B; - uint32_t *X, *V, *T; - uint64_t i, Blen, Vlen; - - /* Sanity check parameters */ - /* initial check, r,p must be non zero, N >= 2 and a power of 2 */ - if (r == 0 || p == 0 || N < 2 || (N & (N - 1))) - return 0; - /* Check p * r < SCRYPT_PR_MAX avoiding overflow */ - if (p > SCRYPT_PR_MAX / r) { - EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } - - /* - * Need to check N: if 2^(128 * r / 8) overflows limit this is - * automatically satisfied since N <= UINT64_MAX. - */ - - if (16 * r <= LOG2_UINT64_MAX) { - if (N >= (((uint64_t)1) << (16 * r))) { - EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } + const char *empty = ""; + int rv = 1; + EVP_KDF_CTX *kctx; + + /* Maintain existing behaviour. */ + if (pass == NULL) { + pass = empty; + passlen = 0; } - - /* Memory checks: check total allocated buffer size fits in uint64_t */ - - /* - * B size in section 5 step 1.S - * Note: we know p * 128 * r < UINT64_MAX because we already checked - * p * r < SCRYPT_PR_MAX - */ - Blen = p * 128 * r; - /* - * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would - * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.] - */ - if (Blen > INT_MAX) { - EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } - - /* - * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t |