[openssl] master update
Dr. Paul Dale
pauli at openssl.org
Mon May 24 05:23:48 UTC 2021
The branch master has been updated
via 094287551a31ba74eb9bfdb4a808d19f4553371b (commit)
via 8bb6fdfc9971557f3aaa4e5dfc4cab0e5e9220a6 (commit)
via 0f183675b8ea2490ca5e0b4e66baa27a3e6478ba (commit)
from d136db212ecaeb65e399de8d6b30e8b5ecc044d9 (commit)
- Log -----------------------------------------------------------------
commit 094287551a31ba74eb9bfdb4a808d19f4553371b
Author: Jon Spillett <jon.spillett at oracle.com>
Date: Wed May 19 14:52:16 2021 +1000
Add a test for PKCS5_PBE_keyivgen()
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
Reviewed-by: Paul Dale <pauli at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14326)
commit 8bb6fdfc9971557f3aaa4e5dfc4cab0e5e9220a6
Author: Jon Spillett <jon.spillett at oracle.com>
Date: Thu May 6 15:25:29 2021 +1000
Added PKCS5_PBE_keyivgen_ex() to allow PBKDF1 algorithms to be fetched for a specific library context
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
Reviewed-by: Paul Dale <pauli at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14326)
commit 0f183675b8ea2490ca5e0b4e66baa27a3e6478ba
Author: Jon Spillett <jon.spillett at oracle.com>
Date: Fri Feb 26 15:21:47 2021 +1000
Add PBKDF1 to the legacy provider
Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
Reviewed-by: Paul Dale <pauli at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14326)
-----------------------------------------------------------------------
Summary of changes:
CHANGES.md | 13 ++
crypto/evp/evp_pbe.c | 12 +-
crypto/evp/p5_crpt.c | 73 ++++---
doc/man3/PKCS5_PBE_keyivgen.pod | 11 +-
doc/man7/OSSL_PROVIDER-legacy.pod | 8 +
include/openssl/core_names.h | 1 +
include/openssl/evp.h | 4 +
providers/common/build.info | 3 +
.../implementations/include/prov/implementations.h | 1 +
providers/implementations/kdfs/build.info | 3 +
providers/implementations/kdfs/pbkdf1.c | 242 +++++++++++++++++++++
providers/legacyprov.c | 7 +
test/build.info | 6 +-
test/evp_kdf_test.c | 186 ++++++++++++----
test/pbetest.c | 139 ++++++++++++
.../{04-test_encoder_decoder.t => 05-test_pbe.t} | 13 +-
test/recipes/30-test_evp.t | 1 +
test/recipes/30-test_evp_data/evpkdf_pbkdf1.txt | 136 ++++++++++++
util/libcrypto.num | 1 +
19 files changed, 765 insertions(+), 95 deletions(-)
create mode 100644 providers/implementations/kdfs/pbkdf1.c
create mode 100644 test/pbetest.c
copy test/recipes/{04-test_encoder_decoder.t => 05-test_pbe.t} (65%)
create mode 100644 test/recipes/30-test_evp_data/evpkdf_pbkdf1.txt
diff --git a/CHANGES.md b/CHANGES.md
index b53216512f..82c027bc73 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -176,6 +176,19 @@ breaking changes, and mappings for the large list of deprecated functions.
*Matt Caswell*
+ * PKCS#5 PBKDF1 key derivation has been moved from PKCS5_PBE_keyivgen() into
+ the legacy crypto provider as an EVP_KDF. Applications requiring this KDF
+ will need to load the legacy crypto provider. This includes these PBE
+ algorithms which use this KDF:
+ - NID_pbeWithMD2AndDES_CBC
+ - NID_pbeWithMD5AndDES_CBC
+ - NID_pbeWithSHA1AndRC2_CBC
+ - NID_pbeWithMD2AndRC2_CBC
+ - NID_pbeWithMD5AndRC2_CBC
+ - NID_pbeWithSHA1AndDES_CBC
+
+ *Jon Spillett*
+
* Deprecated obsolete EVP_PKEY_CTX_get0_dh_kdf_ukm() and
EVP_PKEY_CTX_get0_ecdh_kdf_ukm() functions.
diff --git a/crypto/evp/evp_pbe.c b/crypto/evp/evp_pbe.c
index 7c73cfc501..6347a0635f 100644
--- a/crypto/evp/evp_pbe.c
+++ b/crypto/evp/evp_pbe.c
@@ -34,11 +34,11 @@ static STACK_OF(EVP_PBE_CTL) *pbe_algs;
static const EVP_PBE_CTL builtin_pbe[] = {
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndDES_CBC,
- NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen, NULL},
+ NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndDES_CBC,
- NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen, NULL},
+ NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndRC2_CBC,
- NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen, NULL},
+ NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen},
@@ -58,11 +58,11 @@ static const EVP_PBE_CTL builtin_pbe[] = {
{EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen, &PKCS5_v2_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndRC2_CBC,
- NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen, NULL},
+ NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndRC2_CBC,
- NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen, NULL},
+ NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndDES_CBC,
- NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen, NULL},
+ NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex},
{EVP_PBE_TYPE_PRF, NID_hmacWithSHA1, -1, NID_sha1, 0},
{EVP_PBE_TYPE_PRF, NID_hmac_md5, -1, NID_md5, 0},
diff --git a/crypto/evp/p5_crpt.c b/crypto/evp/p5_crpt.c
index 4d9e894f0f..abf153cb43 100644
--- a/crypto/evp/p5_crpt.c
+++ b/crypto/evp/p5_crpt.c
@@ -12,6 +12,8 @@
#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include <openssl/kdf.h>
/*
* Doesn't do anything now: Builtin PBE algorithms in static table.
@@ -21,19 +23,23 @@ void PKCS5_PBE_add(void)
{
}
-int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
- ASN1_TYPE *param, const EVP_CIPHER *cipher,
- const EVP_MD *md, int en_de)
+int PKCS5_PBE_keyivgen_ex(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
- EVP_MD_CTX *ctx;
unsigned char md_tmp[EVP_MAX_MD_SIZE];
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
- int i, ivl, kl;
- PBEPARAM *pbe;
+ int ivl, kl;
+ PBEPARAM *pbe = NULL;
int saltlen, iter;
unsigned char *salt;
int mdsize;
int rv = 0;
+ EVP_KDF *kdf;
+ EVP_KDF_CTX *kctx = NULL;
+ OSSL_PARAM params[5], *p = params;
+ const char *mdname = EVP_MD_name(md);
/* Extract useful info from parameter */
if (param == NULL || param->type != V_ASN1_SEQUENCE ||
@@ -51,14 +57,12 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
ivl = EVP_CIPHER_iv_length(cipher);
if (ivl < 0 || ivl > 16) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH);
- PBEPARAM_free(pbe);
- return 0;
+ goto err;
}
kl = EVP_CIPHER_key_length(cipher);
if (kl < 0 || kl > (int)sizeof(md_tmp)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH);
- PBEPARAM_free(pbe);
- return 0;
+ goto err;
}
if (pbe->iter == NULL)
@@ -73,33 +77,25 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
else if (passlen == -1)
passlen = strlen(pass);
- ctx = EVP_MD_CTX_new();
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ mdsize = EVP_MD_size(md);
+ if (mdsize < 0)
goto err;
- }
- if (!EVP_DigestInit_ex(ctx, md, NULL))
- goto err;
- if (!EVP_DigestUpdate(ctx, pass, passlen))
- goto err;
- if (!EVP_DigestUpdate(ctx, salt, saltlen))
+ kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF1, propq);
+ kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ if (kctx == NULL)
goto err;
- PBEPARAM_free(pbe);
- pbe = NULL;
- if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
- goto err;
- mdsize = EVP_MD_size(md);
- if (mdsize < 0)
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ (char *)pass, (size_t)passlen);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ salt, saltlen);
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ (char *)mdname, 0);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(kctx, md_tmp, mdsize, params) != 1)
goto err;
- for (i = 1; i < iter; i++) {
- if (!EVP_DigestInit_ex(ctx, md, NULL))
- goto err;
- if (!EVP_DigestUpdate(ctx, md_tmp, mdsize))
- goto err;
- if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
- goto err;
- }
memcpy(key, md_tmp, kl);
memcpy(iv, md_tmp + (16 - ivl), ivl);
if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de))
@@ -109,7 +105,16 @@ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
rv = 1;
err:
+ EVP_KDF_CTX_free(kctx);
PBEPARAM_free(pbe);
- EVP_MD_CTX_free(ctx);
return rv;
}
+
+int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de)
+{
+ return PKCS5_PBE_keyivgen_ex(cctx, pass, passlen, param, cipher, md, en_de,
+ NULL, NULL);
+}
+
diff --git a/doc/man3/PKCS5_PBE_keyivgen.pod b/doc/man3/PKCS5_PBE_keyivgen.pod
index 4515346407..72de3153b9 100644
--- a/doc/man3/PKCS5_PBE_keyivgen.pod
+++ b/doc/man3/PKCS5_PBE_keyivgen.pod
@@ -2,7 +2,7 @@
=head1 NAME
-PKCS5_PBE_keyivgen, PKCS5_pbe2_set, PKCS5_pbe2_set_iv,
+PKCS5_PBE_keyivgen, PKCS5_PBE_keyivgen_ex, PKCS5_pbe2_set, PKCS5_pbe2_set_iv,
PKCS5_pbe2_set_iv_ex, PKCS5_pbe_set, PKCS5_pbe_set_ex, PKCS5_pbe2_set_scrypt,
PKCS5_pbe_set0_algor, PKCS5_pbe_set0_algor_ex,
PKCS5_v2_PBE_keyivgen, PKCS5_v2_PBE_keyivgen_ex,
@@ -17,6 +17,10 @@ PKCS5_pbkdf2_set, PKCS5_pbkdf2_set_ex, EVP_PBE_scrypt, EVP_PBE_scrypt_ex
int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
ASN1_TYPE *param, const EVP_CIPHER *cipher,
const EVP_MD *md, int en_de);
+ int PKCS5_PBE_keyivgen_ex(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de, OSSL_LIB_CTX *libctx,
+ const char *propq);
int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
ASN1_TYPE *param, const EVP_CIPHER *cipher,
const EVP_MD *md, int en_de);
@@ -79,7 +83,7 @@ PKCS5_pbkdf2_set, PKCS5_pbkdf2_set_ex, EVP_PBE_scrypt, EVP_PBE_scrypt_ex
=head2 Key Derivation
-PKCS5_PBE_keyivgen() takes a password I<pass> of
+PKCS5_PBE_keyivgen() and PKCS5_PBE_keyivgen_ex() take a password I<pass> of
length I<passlen>, parameters I<param> and a message digest function I<md_type>
and performs a key derivation according to PKCS#5 PBES1. The resulting key is
then used to initialise the cipher context I<ctx> with a cipher I<cipher> for
@@ -158,6 +162,9 @@ PKCS5_v2_PBE_keyivgen_ex(), EVP_PBE_scrypt_ex(), PKCS5_v2_scrypt_keyivgen_ex(),
PKCS5_pbe_set0_algor_ex(), PKCS5_pbe_set_ex(), PKCS5_pbe2_set_iv_ex() and
PKCS5_pbkdf2_set_ex() were added in OpenSSL 3.0.
+From OpenSSL 3.0 the PBKDF1 algorithm used in PKCS5_PBE_keyivgen() and
+PKCS5_PBE_keyivgen_ex() has been moved to the legacy provider as an EVP_KDF.
+
=head1 COPYRIGHT
Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man7/OSSL_PROVIDER-legacy.pod b/doc/man7/OSSL_PROVIDER-legacy.pod
index 1fa86ab2cd..0e2965d618 100644
--- a/doc/man7/OSSL_PROVIDER-legacy.pod
+++ b/doc/man7/OSSL_PROVIDER-legacy.pod
@@ -79,6 +79,14 @@ Disabled by default. Use I<enable-rc5> config option to enable.
=back
+=head2 Key Derivation Function (KDF)
+
+=over 4
+
+=item PBKDF1
+
+=back
+
=begin comment
When algorithms for other operations start appearing, the
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index c01be930ab..36d9489e90 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -220,6 +220,7 @@ extern "C" {
/* Known KDF names */
#define OSSL_KDF_NAME_HKDF "HKDF"
+#define OSSL_KDF_NAME_PBKDF1 "PBKDF1"
#define OSSL_KDF_NAME_PBKDF2 "PBKDF2"
#define OSSL_KDF_NAME_SCRYPT "SCRYPT"
#define OSSL_KDF_NAME_SSHKDF "SSHKDF"
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 27e14d07b6..a793db6e0e 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1438,6 +1438,10 @@ int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
ASN1_TYPE *param, const EVP_CIPHER *cipher,
const EVP_MD *md, int en_de);
+int PKCS5_PBE_keyivgen_ex(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
+ ASN1_TYPE *param, const EVP_CIPHER *cipher,
+ const EVP_MD *md, int en_de, OSSL_LIB_CTX *libctx,
+ const char *propq);
int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
int keylen, unsigned char *out);
diff --git a/providers/common/build.info b/providers/common/build.info
index e23ff58855..a14bf09037 100644
--- a/providers/common/build.info
+++ b/providers/common/build.info
@@ -4,4 +4,7 @@ SOURCE[../libcommon.a]=provider_err.c provider_ctx.c
$FIPSCOMMON=provider_util.c capabilities.c bio_prov.c digest_to_nid.c\
securitycheck.c provider_seeding.c
SOURCE[../libdefault.a]=$FIPSCOMMON securitycheck_default.c
+IF[{- !$disabled{module} && !$disabled{shared} -}]
+ SOURCE[../liblegacy.a]=provider_util.c
+ENDIF
SOURCE[../libfips.a]=$FIPSCOMMON securitycheck_fips.c
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 6afea01df0..ae09ccd506 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -249,6 +249,7 @@ extern const OSSL_DISPATCH ossl_siphash_functions[];
extern const OSSL_DISPATCH ossl_poly1305_functions[];
/* KDFs / PRFs */
+extern const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[];
extern const OSSL_DISPATCH ossl_kdf_pbkdf2_functions[];
extern const OSSL_DISPATCH ossl_kdf_pkcs12_functions[];
#ifndef OPENSSL_NO_SCRYPT
diff --git a/providers/implementations/kdfs/build.info b/providers/implementations/kdfs/build.info
index 1711466e3f..f4620adce2 100644
--- a/providers/implementations/kdfs/build.info
+++ b/providers/implementations/kdfs/build.info
@@ -5,6 +5,7 @@ $TLS1_PRF_GOAL=../../libdefault.a ../../libfips.a
$HKDF_GOAL=../../libdefault.a ../../libfips.a
$KBKDF_GOAL=../../libdefault.a ../../libfips.a
$KRB5KDF_GOAL=../../libdefault.a
+$PBKDF1_GOAL=../../liblegacy.a
$PBKDF2_GOAL=../../libdefault.a ../../libfips.a
$PKCS12KDF_GOAL=../../libdefault.a
$SSKDF_GOAL=../../libdefault.a ../../libfips.a
@@ -20,6 +21,8 @@ SOURCE[$KBKDF_GOAL]=kbkdf.c
SOURCE[$KRB5KDF_GOAL]=krb5kdf.c
+SOURCE[$PBKDF1_GOAL]=pbkdf1.c
+
SOURCE[$PBKDF2_GOAL]=pbkdf2.c
# Extra code to satisfy the FIPS and non-FIPS separation.
# When the PBKDF2 moves to legacy, this can be removed.
diff --git a/providers/implementations/kdfs/pbkdf1.c b/providers/implementations/kdfs/pbkdf1.c
new file mode 100644
index 0000000000..af715efc91
--- /dev/null
+++ b/providers/implementations/kdfs/pbkdf1.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright 1999-2021 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/trace.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/proverr.h>
+#include "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommon.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+
+static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf1_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf1_free;
+static OSSL_FUNC_kdf_reset_fn kdf_pbkdf1_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_pbkdf1_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pbkdf1_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pbkdf1_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pbkdf1_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pbkdf1_get_ctx_params;
+
+typedef struct {
+ void *provctx;
+ PROV_DIGEST digest;
+ unsigned char *pass;
+ size_t pass_len;
+ unsigned char *salt;
+ size_t salt_len;
+ uint64_t iter;
+} KDF_PBKDF1;
+
+/*
+ * PKCS5 PBKDF1 compatible key/IV generation as specified in:
+ * https://tools.ietf.org/html/rfc8018#page-10
+ */
+
+static int kdf_pbkdf1_do_derive(const unsigned char *pass, size_t passlen,
+ const unsigned char *salt, size_t saltlen,
+ uint64_t iter, const EVP_MD *md_type,
+ unsigned char *out, size_t n)
+{
+ uint64_t i;
+ int mdsize, ret = 0;
+ unsigned char md_tmp[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX *ctx = NULL;
+
+ ctx = EVP_MD_CTX_new();
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestInit_ex(ctx, md_type, NULL)
+ || !EVP_DigestUpdate(ctx, pass, passlen)
+ || !EVP_DigestUpdate(ctx, salt, saltlen)
+ || !EVP_DigestFinal_ex(ctx, md_tmp, NULL))
+ goto err;
+ mdsize = EVP_MD_size(md_type);
+ if (mdsize < 0)
+ goto err;
+ for (i = 1; i < iter; i++) {
+ if (!EVP_DigestInit_ex(ctx, md_type, NULL))
+ goto err;
+ if (!EVP_DigestUpdate(ctx, md_tmp, mdsize))
+ goto err;
+ if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
+ goto err;
+ }
+
+ memcpy(out, md_tmp, n);
+ ret = 1;
+err:
+ EVP_MD_CTX_free(ctx);
+ return ret;
+}
+
+static void *kdf_pbkdf1_new(void *provctx)
+{
+ KDF_PBKDF1 *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ctx->provctx = provctx;
+ return ctx;
+}
+
+static void kdf_pbkdf1_cleanup(KDF_PBKDF1 *ctx)
+{
+ ossl_prov_digest_reset(&ctx->digest);
+ OPENSSL_free(ctx->salt);
+ OPENSSL_clear_free(ctx->pass, ctx->pass_len);
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+static void kdf_pbkdf1_free(void *vctx)
+{
+ KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
+
+ if (ctx != NULL) {
+ kdf_pbkdf1_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+static void kdf_pbkdf1_reset(void *vctx)
+{
+ KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
+ void *provctx = ctx->provctx;
+
+ kdf_pbkdf1_cleanup(ctx);
+ ctx->provctx = provctx;
+}
+
+static int kdf_pbkdf1_set_membuf(unsigned char **buffer, size_t *buflen,
+ const OSSL_PARAM *p)
+{
+ OPENSSL_clear_free(*buffer, *buflen);
+ if (p->data_size == 0) {
+ if ((*buffer = OPENSSL_malloc(1)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (p->data != NULL) {
+ *buffer = NULL;
+ if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
+ return 0;
+ }
+ return 1;
+}
+
+static int kdf_pbkdf1_derive(void *vctx, unsigned char *key, size_t keylen,
+ const OSSL_PARAM params[])
+{
+ KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
+ const EVP_MD *md;
+
+ if (!ossl_prov_is_running() || !kdf_pbkdf1_set_ctx_params(ctx, params))
+ return 0;
+
+ if (ctx->pass == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
+ return 0;
+ }
+
+ if (ctx->salt == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
+ return 0;
+ }
+
+ md = ossl_prov_digest_md(&ctx->digest);
+ return kdf_pbkdf1_do_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
+ ctx->iter, md, key, keylen);
+}
+
+static int kdf_pbkdf1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ const OSSL_PARAM *p;
+ KDF_PBKDF1 *ctx = vctx;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
+ if (!kdf_pbkdf1_set_membuf(&ctx->pass, &ctx->pass_len, p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
+ if (!kdf_pbkdf1_set_membuf(&ctx->salt, &ctx->salt_len,p))
+ return 0;
+
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL)
+ if (!OSSL_PARAM_get_uint64(p, &ctx->iter))
+ return 0;
+ return 1;
+}
+
+static const OSSL_PARAM *kdf_pbkdf1_settable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_settable_ctx_params[] = {
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
+ OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
+ OSSL_PARAM_END
+ };
+ return known_settable_ctx_params;
+}
+
+static int kdf_pbkdf1_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ OSSL_PARAM *p;
+
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
+ return OSSL_PARAM_set_size_t(p, SIZE_MAX);
+ return -2;
+}
+
+static const OSSL_PARAM *kdf_pbkdf1_gettable_ctx_params(ossl_unused void *ctx,
+ ossl_unused void *p_ctx)
+{
+ static const OSSL_PARAM known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
+ OSSL_PARAM_END
+ };
+ return known_gettable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[] = {
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf1_new },
+ { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf1_free },
+ { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf1_reset },
+ { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf1_derive },
+ { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_pbkdf1_settable_ctx_params },
+ { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_set_ctx_params },
+ { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+ (void(*)(void))kdf_pbkdf1_gettable_ctx_params },
+ { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_get_ctx_params },
+ { 0, NULL }
+};
diff --git a/providers/legacyprov.c b/providers/legacyprov.c
index 1f137a721f..b5fc5f523f 100644
--- a/providers/legacyprov.c
+++ b/providers/legacyprov.c
@@ -143,6 +143,11 @@ static const OSSL_ALGORITHM legacy_ciphers[] = {
{ NULL, NULL, NULL }
};
+static const OSSL_ALGORITHM legacy_kdfs[] = {
+ ALG("PBKDF1", ossl_kdf_pbkdf1_functions),
+ { NULL, NULL, NULL }
+};
+
static const OSSL_ALGORITHM *legacy_query(void *provctx, int operation_id,
int *no_cache)
{
@@ -152,6 +157,8 @@ static const OSSL_ALGORITHM *legacy_query(void *provctx, int operation_id,
return legacy_digests;
case OSSL_OP_CIPHER:
return legacy_ciphers;
+ case OSSL_OP_KDF:
+ return legacy_kdfs;
}
return NULL;
}
diff --git a/test/build.info b/test/build.info
index 183c972602..f91f7a49f5 100644
--- a/test/build.info
+++ b/test/build.info
@@ -32,7 +32,7 @@ IF[{- !$disabled{tests} -}]
sanitytest rsa_complex exdatatest bntest \
ecstresstest gmdifftest pbelutest \
destest mdc2test \
- exptest \
+ exptest pbetest \
evp_pkey_provided_test evp_test evp_extra_test evp_extra_test2 \
evp_fetch_prov_test evp_libctx_test ossl_store_test \
v3nametest v3ext \
@@ -121,6 +121,10 @@ IF[{- !$disabled{tests} -}]
INCLUDE[exptest]=../include ../apps/include
DEPEND[exptest]=../libcrypto libtestutil.a
+ SOURCE[pbetest]=pbetest.c
+ INCLUDE[pbetest]=../include ../apps/include
+ DEPEND[pbetest]=../libcrypto libtestutil.a
+
SOURCE[fatalerrtest]=fatalerrtest.c helpers/ssltestlib.c
INCLUDE[fatalerrtest]=../include ../apps/include
DEPEND[fatalerrtest]=../libcrypto ../libssl libtestutil.a
diff --git a/test/evp_kdf_test.c b/test/evp_kdf_test.c
index 1bed159227..1dea980f00 100644
--- a/test/evp_kdf_test.c
+++ b/test/evp_kdf_test.c
@@ -34,6 +34,9 @@ static OSSL_PARAM *construct_tls1_prf_params(const char *digest, const char *sec
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 4);
OSSL_PARAM *p = params;
+ if (params == NULL)
+ return NULL;
+
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)digest, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
@@ -60,8 +63,8 @@ static int test_kdf_tls1_prf(void)
params = construct_tls1_prf_params("sha256", "secret", "seed");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
@@ -78,8 +81,8 @@ static int test_kdf_tls1_prf_invalid_digest(void)
params = construct_tls1_prf_params("blah", "secret", "seed");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_false(EVP_KDF_CTX_set_params(kctx, params));
EVP_KDF_CTX_free(kctx);
@@ -97,8 +100,8 @@ static int test_kdf_tls1_prf_zero_output_size(void)
params = construct_tls1_prf_params("sha256", "secret", "seed");
/* Negative test - derive should fail */
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
&& TEST_int_eq(EVP_KDF_derive(kctx, out, 0, NULL), 0);
@@ -116,8 +119,8 @@ static int test_kdf_tls1_prf_empty_secret(void)
params = construct_tls1_prf_params("sha256", "", "seed");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
@@ -134,8 +137,8 @@ static int test_kdf_tls1_prf_1byte_secret(void)
params = construct_tls1_prf_params("sha256", "1", "seed");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
@@ -153,8 +156,8 @@ static int test_kdf_tls1_prf_empty_seed(void)
params = construct_tls1_prf_params("sha256", "secret", "");
/* Negative test - derive should fail */
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
&& TEST_int_eq(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0);
@@ -172,8 +175,8 @@ static int test_kdf_tls1_prf_1byte_seed(void)
params = construct_tls1_prf_params("sha256", "secret", "1");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_TLS1_PRF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
@@ -187,6 +190,9 @@ static OSSL_PARAM *construct_hkdf_params(char *digest, char *key,
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 5);
OSSL_PARAM *p = params;
+ if (params == NULL)
+ return NULL;
+
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
digest, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
@@ -203,7 +209,7 @@ static OSSL_PARAM *construct_hkdf_params(char *digest, char *key,
static int test_kdf_hkdf(void)
{
int ret;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
static const unsigned char expected[sizeof(out)] = {
@@ -212,8 +218,8 @@ static int test_kdf_hkdf(void)
params = construct_hkdf_params("sha256", "secret", 6, "salt", "label");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
&& TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
@@ -225,13 +231,13 @@ static int test_kdf_hkdf(void)
static int test_kdf_hkdf_invalid_digest(void)
{
int ret;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM *params;
params = construct_hkdf_params("blah", "secret", 6, "salt", "label");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_false(EVP_KDF_CTX_set_params(kctx, params));
EVP_KDF_CTX_free(kctx);
@@ -242,15 +248,15 @@ static int test_kdf_hkdf_invalid_digest(void)
static int test_kdf_hkdf_zero_output_size(void)
{
int ret;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
params = construct_hkdf_params("sha256", "secret", 6, "salt", "label");
/* Negative test - derive should fail */
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_true(EVP_KDF_CTX_set_params(kctx, params))
&& TEST_int_eq(EVP_KDF_derive(kctx, out, 0, NULL), 0);
@@ -262,14 +268,14 @@ static int test_kdf_hkdf_zero_output_size(void)
static int test_kdf_hkdf_empty_key(void)
{
int ret;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
params = construct_hkdf_params("sha256", "", 0, "salt", "label");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
@@ -280,14 +286,14 @@ static int test_kdf_hkdf_empty_key(void)
static int test_kdf_hkdf_1byte_key(void)
{
int ret;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
params = construct_hkdf_params("sha256", "1", 1, "salt", "label");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
@@ -298,14 +304,14 @@ static int test_kdf_hkdf_1byte_key(void)
static int test_kdf_hkdf_empty_salt(void)
{
int ret;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[10];
OSSL_PARAM *params;
params = construct_hkdf_params("sha256", "secret", 6, "", "label");
- ret =
- TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
+ ret = TEST_ptr(params)
+ && TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_HKDF))
&& TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0);
EVP_KDF_CTX_free(kctx);
@@ -313,12 +319,74 @@ static int test_kdf_hkdf_empty_salt(void)
return ret;
}
+static OSSL_PARAM *construct_pbkdf1_params(char *pass, char *digest, char *salt,
+ unsigned int *iter)
+{
+ OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 5);
+ OSSL_PARAM *p = params;
+
+ if (params == NULL)
+ return NULL;
+
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ (unsigned char *)pass, strlen(pass));
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+ (unsigned char *)salt, strlen(salt));
+ *p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_ITER, iter);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ digest, 0);
+ *p = OSSL_PARAM_construct_end();
+
+ return params;
+}
+
+static int test_kdf_pbkdf1(void)
+{
+ int ret = 0;
+ EVP_KDF_CTX *kctx = NULL;
+ unsigned char out[25];
+ unsigned int iterations = 4096;
+ OSSL_PARAM *params;
+ OSSL_PROVIDER *prov = NULL;
+ const unsigned char expected[sizeof(out)] = {
+ 0xfb, 0x83, 0x4d, 0x36, 0x6d, 0xbc, 0x53, 0x87, 0x35, 0x1b, 0x34, 0x75,
+ 0x95, 0x88, 0x32, 0x4f, 0x3e, 0x82, 0x81, 0x01, 0x21, 0x93, 0x64, 0x00,
+ 0xcc
+ };
+
+ /* PBKDF1 only available in the legacy provider */
+ prov = OSSL_PROVIDER_load(NULL, "legacy");
+ if (prov == NULL)
+ return TEST_skip("PBKDF1 only available in legacy provider");
+
+ params = construct_pbkdf1_params("passwordPASSWORDpassword", "sha256",
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ &iterations);
+
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF1))
+ || !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
+ || !TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0)
+ || !TEST_mem_eq(out, sizeof(out), expected, sizeof(expected)))
+ goto err;
+
+ ret = 1;
+err:
+ EVP_KDF_CTX_free(kctx);
+ OPENSSL_free(params);
+ OSSL_PROVIDER_unload(prov);
+ return ret;
+}
+
static OSSL_PARAM *construct_pbkdf2_params(char *pass, char *digest, char *salt,
unsigned int *iter, int *mode)
{
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 6);
OSSL_PARAM *p = params;
+ if (params == NULL)
+ return NULL;
+
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
(unsigned char *)pass, strlen(pass));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
@@ -335,7 +403,7 @@ static OSSL_PARAM *construct_pbkdf2_params(char *pass, char *digest, char *salt,
static int test_kdf_pbkdf2(void)
{
int ret = 0;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 4096;
int mode = 0;
@@ -351,7 +419,8 @@ static int test_kdf_pbkdf2(void)
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
- if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
|| !TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), params), 0)
|| !TEST_mem_eq(out, sizeof(out), expected, sizeof(expected)))
goto err;
@@ -366,7 +435,7 @@ err:
static int test_kdf_pbkdf2_small_output(void)
{
int ret = 0;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 4096;
int mode = 0;
@@ -376,7 +445,8 @@ static int test_kdf_pbkdf2_small_output(void)
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
- if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
/* A key length that is too small should fail */
|| !TEST_int_eq(EVP_KDF_derive(kctx, out, 112 / 8 - 1, NULL), 0))
@@ -392,7 +462,7 @@ err:
static int test_kdf_pbkdf2_large_output(void)
{
int ret = 0;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
size_t len = 0;
unsigned int iterations = 4096;
@@ -406,7 +476,8 @@ static int test_kdf_pbkdf2_large_output(void)
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
- if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* A key length that is too large should fail */
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|| (len != 0 && !TEST_int_eq(EVP_KDF_derive(kctx, out, len, NULL), 0)))
@@ -422,7 +493,7 @@ err:
static int test_kdf_pbkdf2_small_salt(void)
{
int ret = 0;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned int iterations = 4096;
int mode = 0;
OSSL_PARAM *params;
@@ -431,7 +502,8 @@ static int test_kdf_pbkdf2_small_salt(void)
"saltSALT",
&iterations, &mode);
- if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* A salt that is too small should fail */
|| !TEST_false(EVP_KDF_CTX_set_params(kctx, params)))
goto err;
@@ -446,7 +518,7 @@ err:
static int test_kdf_pbkdf2_small_iterations(void)
{
int ret = 0;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned int iterations = 1;
int mode = 0;
OSSL_PARAM *params;
@@ -455,7 +527,8 @@ static int test_kdf_pbkdf2_small_iterations(void)
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
- if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* An iteration count that is too small should fail */
|| !TEST_false(EVP_KDF_CTX_set_params(kctx, params)))
goto err;
@@ -470,7 +543,7 @@ err:
static int test_kdf_pbkdf2_small_salt_pkcs5(void)
{
int ret = 0;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 4096;
int mode = 1;
@@ -481,7 +554,8 @@ static int test_kdf_pbkdf2_small_salt_pkcs5(void)
"saltSALT",
&iterations, &mode);
- if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* A salt that is too small should pass in pkcs5 mode */
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|| !TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0))
@@ -506,7 +580,7 @@ err:
static int test_kdf_pbkdf2_small_iterations_pkcs5(void)
{
int ret = 0;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned char out[25];
unsigned int iterations = 1;
int mode = 1;
@@ -517,7 +591,8 @@ static int test_kdf_pbkdf2_small_iterations_pkcs5(void)
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
- if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* An iteration count that is too small will pass in pkcs5 mode */
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params))
|| !TEST_int_gt(EVP_KDF_derive(kctx, out, sizeof(out), NULL), 0))
@@ -542,7 +617,7 @@ err:
static int test_kdf_pbkdf2_invalid_digest(void)
{
int ret = 0;
- EVP_KDF_CTX *kctx;
+ EVP_KDF_CTX *kctx = NULL;
unsigned int iterations = 4096;
int mode = 0;
OSSL_PARAM *params;
@@ -551,7 +626,8 @@ static int test_kdf_pbkdf2_invalid_digest(void)
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
&iterations, &mode);
- if (!TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
+ if (!TEST_ptr(params)
+ || !TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_PBKDF2))
/* Unknown digest should fail */
|| !TEST_false(EVP_KDF_CTX_set_params(kctx, params)))
goto err;
@@ -831,6 +907,9 @@ static OSSL_PARAM *construct_kbkdf_params(char *digest, char *mac, unsigned char
OSSL_PARAM *params = OPENSSL_malloc(sizeof(OSSL_PARAM) * 7);
OSSL_PARAM *p = params;
+ if (params == NULL)
+ return NULL;
+
*p++ = OSSL_PARAM_construct_utf8_string(
OSSL_KDF_PARAM_DIGEST, digest, 0);
*p++ = OSSL_PARAM_construct_utf8_string(
@@ -857,6 +936,8 @@ static int test_kdf_kbkdf_invalid_digest(void)
static unsigned char key[] = {0x01};
params = construct_kbkdf_params("blah", "HMAC", key, 1, "prf", "test");
+ if (!TEST_ptr(params))
+ return 0;
/* Negative test case - set_params should fail */
kctx = get_kdfbyname("KBKDF");
@@ -877,6 +958,8 @@ static int test_kdf_kbkdf_invalid_mac(void)
static unsigned char key[] = {0x01};
params = construct_kbkdf_params("sha256", "blah", key, 1, "prf", "test");
+ if (!TEST_ptr(params))
+ return 0;
/* Negative test case - set_params should fail */
kctx = get_kdfbyname("KBKDF");
@@ -898,6 +981,8 @@ static int test_kdf_kbkdf_empty_key(void)
unsigned char result[32] = { 0 };
params = construct_kbkdf_params("sha256", "HMAC", key, 0, "prf", "test");
+ if (!TEST_ptr(params))
+ return 0;
/* Negative test case - derive should fail */
kctx = get_kdfbyname("KBKDF");
@@ -920,6 +1005,8 @@ static int test_kdf_kbkdf_1byte_key(void)
unsigned char result[32] = { 0 };
params = construct_kbkdf_params("sha256", "HMAC", key, 1, "prf", "test");
+ if (!TEST_ptr(params))
+ return 0;
kctx = get_kdfbyname("KBKDF");
ret = TEST_ptr(kctx)
@@ -940,6 +1027,8 @@ static int test_kdf_kbkdf_zero_output_size(void)
unsigned char result[32] = { 0 };
params = construct_kbkdf_params("sha256", "HMAC", key, 1, "prf", "test");
+ if (!TEST_ptr(params))
+ return 0;
/* Negative test case - derive should fail */
kctx = get_kdfbyname("KBKDF");
@@ -1394,6 +1483,7 @@ int setup_tests(void)
ADD_TEST(test_kdf_hkdf_empty_key);
ADD_TEST(test_kdf_hkdf_1byte_key);
ADD_TEST(test_kdf_hkdf_empty_salt);
+ ADD_TEST(test_kdf_pbkdf1);
ADD_TEST(test_kdf_pbkdf2);
ADD_TEST(test_kdf_pbkdf2_small_output);
ADD_TEST(test_kdf_pbkdf2_large_output);
diff --git a/test/pbetest.c b/test/pbetest.c
new file mode 100644
index 0000000000..81dbfc1388
--- /dev/null
+++ b/test/pbetest.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2021 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 <string.h>
+
+#include "testutil.h"
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+
+#if !defined OPENSSL_NO_RC4 && !defined OPENSSL_NO_MD5
+# if !defined OPENSSL_NO_DES && !defined OPENSSL_NO_SHA1
+
+static const char pbe_password[] = "MyVoiceIsMyPassport";
+
+static unsigned char pbe_salt[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+};
+
+static const int pbe_iter = 1000;
+
+static unsigned char pbe_plaintext[] = {
+ 0x57, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x73, 0x74, 0x61, 0x72, 0x73,
+};
+# endif
+#endif
+
+/* Expected output generated using OpenSSL 1.1.1 */
+
+#if !defined OPENSSL_NO_RC4 && !defined OPENSSL_NO_MD5
+static const unsigned char pbe_ciphertext_rc4_md5[] = {
+ 0x21, 0x90, 0xfa, 0xee, 0x95, 0x66, 0x59, 0x45,
+ 0xfa, 0x1e, 0x9f, 0xe2, 0x25, 0xd2, 0xf9, 0x71,
+ 0x94, 0xe4, 0x3d, 0xc9, 0x7c, 0xb0, 0x07, 0x23,
+};
+#endif
+
+#if !defined OPENSSL_NO_DES && !defined OPENSSL_NO_SHA1
+static const unsigned char pbe_ciphertext_des_sha1[] = {
+ 0xce, 0x4b, 0xb0, 0x0a, 0x7b, 0x48, 0xd7, 0xe3,
+ 0x9a, 0x9f, 0x46, 0xd6, 0x41, 0x42, 0x4b, 0x44,
+ 0x36, 0x45, 0x5f, 0x60, 0x8f, 0x3c, 0xd0, 0x55,
+ 0xd0, 0x8d, 0xa9, 0xab, 0x78, 0x5b, 0x63, 0xaf,
+};
+#endif
+
+#if !defined OPENSSL_NO_RC4 && !defined OPENSSL_NO_MD5
+# if !defined OPENSSL_NO_DES && !defined OPENSSL_NO_SHA1
+static int test_pkcs5_pbe(const EVP_CIPHER *cipher, const EVP_MD *md,
+ const unsigned char *exp, const int exp_len)
+{
+ int ret = 0;
+ EVP_CIPHER_CTX *ctx;
+ X509_ALGOR *algor = NULL;
+ int i, outlen;
+ unsigned char out[32];
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!TEST_ptr(ctx))
+ goto err;
+
+ algor = X509_ALGOR_new();
+ if (!TEST_ptr(algor))
+ goto err;
+
+ if (!TEST_true(PKCS5_pbe_set0_algor(algor, EVP_CIPHER_nid(cipher), pbe_iter,
+ pbe_salt, sizeof(pbe_salt)))
+ || !TEST_true(PKCS5_PBE_keyivgen(ctx, pbe_password, strlen(pbe_password),
+ algor->parameter, cipher, md, 1))
+ || !TEST_true(EVP_CipherUpdate(ctx, out, &i, pbe_plaintext,
+ sizeof(pbe_plaintext))))
+ goto err;
+ outlen = i;
+
+ if (!TEST_true(EVP_CipherFinal_ex(ctx, out + i, &i)))
+ goto err;
+ outlen += i;
+
+ if (!TEST_mem_eq(out, outlen, exp, exp_len))
+ goto err;
+
+ /* Decrypt */
+
+ if (!TEST_true(PKCS5_PBE_keyivgen(ctx, pbe_password, strlen(pbe_password),
+ algor->parameter, cipher, md, 0))
+ || !TEST_true(EVP_CipherUpdate(ctx, out, &i, exp, exp_len)))
+ goto err;
+
+ outlen = i;
+ if (!TEST_true(EVP_CipherFinal_ex(ctx, out + i, &i)))
+ goto err;
+
+ if (!TEST_mem_eq(out, outlen, pbe_plaintext, sizeof(pbe_plaintext)))
+ goto err;
+
+ ret = 1;
+err:
+ EVP_CIPHER_CTX_free(ctx);
+ X509_ALGOR_free(algor);
+ return ret;
+}
+# endif
+#endif
+
+#if !defined OPENSSL_NO_RC4 && !defined OPENSSL_NO_MD5
+static int test_pkcs5_pbe_rc4_md5(void)
+{
+ return test_pkcs5_pbe(EVP_rc4(), EVP_md5(), pbe_ciphertext_rc4_md5, sizeof(pbe_ciphertext_rc4_md5));
+}
+#endif
+
+#if !defined OPENSSL_NO_DES && !defined OPENSSL_NO_SHA1
+static int test_pkcs5_pbe_des_sha1(void)
+{
+ return test_pkcs5_pbe(EVP_des_cbc(), EVP_sha1(), pbe_ciphertext_des_sha1, sizeof(pbe_ciphertext_des_sha1));
+}
+#endif
+
+int setup_tests(void)
+{
+#if !defined OPENSSL_NO_RC4 && !defined OPENSSL_NO_MD5
+ ADD_TEST(test_pkcs5_pbe_rc4_md5);
+#endif
+#if !defined OPENSSL_NO_DES && !defined OPENSSL_NO_SHA1
+ ADD_TEST(test_pkcs5_pbe_des_sha1);
+#endif
+
+ return 1;
+}
diff --git a/test/recipes/04-test_encoder_decoder.t b/test/recipes/05-test_pbe.t
similarity index 65%
copy from test/recipes/04-test_encoder_decoder.t
copy to test/recipes/05-test_pbe.t
index 2041eb1fb9..76319f1151 100644
--- a/test/recipes/04-test_encoder_decoder.t
+++ b/test/recipes/05-test_pbe.t
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
-# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2021 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,14 +10,19 @@ use strict;
use warnings;
use OpenSSL::Test::Simple;
+use OpenSSL::Test;
+use OpenSSL::Test::Utils;
use OpenSSL::Test qw/:DEFAULT srctop_file bldtop_dir/;
use Cwd qw(abs_path);
-setup("test_encoder_decoder");
+setup("test_pbe");
+
+plan skip_all => "PKCS5 PBE only available in legacy provider"
+ if disabled("legacy");
plan tests => 1;
-$ENV{OPENSSL_MODULES} = abs_path(bldtop_dir("providers"));
$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default-and-legacy.cnf"));
-ok(run(test(["endecode_test"])));
+ok(run(test((["pbetest"])), "Running PBE test"));
+
diff --git a/test/recipes/30-test_evp.t b/test/recipes/30-test_evp.t
index 8a5c26629c..73077142cd 100644
--- a/test/recipes/30-test_evp.t
+++ b/test/recipes/30-test_evp.t
@@ -44,6 +44,7 @@ my @files = qw(
evpciph_aes_wrap.txt
evpciph_des3_common.txt
evpkdf_hkdf.txt
+ evpkdf_pbkdf1.txt
evpkdf_pbkdf2.txt
evpkdf_ss.txt
evpkdf_ssh.txt
diff --git a/test/recipes/30-test_evp_data/evpkdf_pbkdf1.txt b/test/recipes/30-test_evp_data/evpkdf_pbkdf1.txt
new file mode 100644
index 0000000000..1e362fdeb9
--- /dev/null
+++ b/test/recipes/30-test_evp_data/evpkdf_pbkdf1.txt
@@ -0,0 +1,136 @@
+#
+# Copyright 2021 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
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# Tests start with one of these keywords
+# Cipher Decrypt Derive Digest Encoding KDF MAC PBE
+# PrivPubKeyPair Sign Verify VerifyRecover
+# and continue until a blank line. Lines starting with a pound sign are ignored.
+
+Title = PBKDF1 tests
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:md2
+Output = 2C5DAEBD49984F34642ACC09BAD696D7
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:md5
+Output = FDBDF3419FFF98BDB0241390F62A9DB3
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:sha1
+Output = CAB86DD6261710891E8CB56EE3625691
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:2
+Ctrl.digest = digest:md2
+Output = FD7999A1AB54B01B4FC39389A5FE820D
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:2
+Ctrl.digest = digest:md5
+Output = 3D4A8D4FB4C6E8686B21D36142902966
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:2
+Ctrl.digest = digest:sha1
+Output = E3A8DFCF2EEA6DC81D2AD154274FAAE9
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:md2
+Output = 94E4671F438BD6C441C5B120C6CC79CA
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:md5
+Output = 3283ED8F8D037045157DA055BFF84A02
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:password
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha1
+Output = 3CB0C21E81127F5BFF2EEA2B5DC3F31D
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:passwordPASSWORDpassword
+Ctrl.salt = salt:saltSALT
+Ctrl.iter = iter:65537
+Ctrl.digest = digest:md2
+Output = 36DAA8DEB8B471B26AA8CE064A81E54F
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:passwordPASSWORDpassword
+Ctrl.salt = salt:saltSALT
+Ctrl.iter = iter:65537
+Ctrl.digest = digest:md5
+Output = 763F3BA457E3F9ED088B04B5361D7CCA
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:passwordPASSWORDpassword
+Ctrl.salt = salt:saltSALT
+Ctrl.iter = iter:65537
+Ctrl.digest = digest:sha1
+Output = B2B4635718AAAD9FEF23FE328EB83ECF
+
+Title = PBKDF1 tests for empty inputs
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:md2
+Output = 8ECD1C4C1D57C415295784CCD4686905
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:md5
+Output = F3D07DE5EFB5E2C3EAFC16B0CF7E07FA
+
+Availablein = legacy
+KDF = PBKDF1
+Ctrl.pass = pass:
+Ctrl.salt = salt:saltsalt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:sha1
+Output = 2C2ABACE4BD8BB19F67113DA146DBB8C
diff --git a/util/libcrypto.num b/util/libcrypto.num
index c0c9ee7024..0ac771216c 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5413,3 +5413,4 @@ BIO_get_line 5540 3_0_0 EXIST::FUNCTION:
OSSL_LIB_CTX_new_from_dispatch 5541 3_0_0 EXIST::FUNCTION:
OSSL_LIB_CTX_new_child 5542 3_0_0 EXIST::FUNCTION:
OSSL_PROVIDER_get0_dispatch 5543 3_0_0 EXIST::FUNCTION:
+PKCS5_PBE_keyivgen_ex 5544 3_0_0 EXIST::FUNCTION:
More information about the openssl-commits
mailing list