[openssl] master update

Dr. Paul Dale pauli at openssl.org
Fri Aug 14 08:15:51 UTC 2020


The branch master has been updated
       via  0e53cd5207615038de8496684d9aa3a18d50c388 (commit)
       via  b7466c1303b2e16815092ae4ef6c97ae1f0f347d (commit)
      from  c19e6da9a345b1e14caca23c50a0c7690309e0e4 (commit)


- Log -----------------------------------------------------------------
commit 0e53cd5207615038de8496684d9aa3a18d50c388
Author: Pauli <paul.dale at oracle.com>
Date:   Tue Aug 11 13:19:40 2020 +1000

    PKCS#12 KDF: don't run tests with the FIPS provider.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12624)

commit b7466c1303b2e16815092ae4ef6c97ae1f0f347d
Author: Pauli <paul.dale at oracle.com>
Date:   Tue Aug 11 10:29:02 2020 +1000

    Move PKCS#12 KDF to provider.
    
    This KDF is defined in RFC7292 in appendix B.  It is widely used in PKCS#12
    and should be provided.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/12624)

-----------------------------------------------------------------------

Summary of changes:
 crypto/err/openssl.txt                             |   1 +
 crypto/pkcs12/p12_key.c                            | 124 +++------
 .../{EVP_KDF-PBKDF2.pod => EVP_KDF-PKCS12KDF.pod}  |  42 +--
 doc/man7/OSSL_PROVIDER-default.pod                 |   2 +
 include/openssl/core_names.h                       |   1 +
 providers/common/include/prov/providercommonerr.h  |   1 +
 providers/common/provider_err.c                    |   2 +
 providers/defltprov.c                              |   1 +
 .../implementations/include/prov/implementations.h |   1 +
 providers/implementations/kdfs/build.info          |   3 +
 providers/implementations/kdfs/pkcs12kdf.c         | 285 +++++++++++++++++++++
 test/recipes/30-test_evp.t                         |   2 +-
 12 files changed, 351 insertions(+), 114 deletions(-)
 copy doc/man7/{EVP_KDF-PBKDF2.pod => EVP_KDF-PKCS12KDF.pod} (59%)
 create mode 100644 providers/implementations/kdfs/pkcs12kdf.c

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 2fa2af529a..c07eee6e7e 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2874,6 +2874,7 @@ PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length
 PROV_R_INVALID_DATA:115:invalid data
 PROV_R_INVALID_DIGEST:122:invalid digest
 PROV_R_INVALID_DIGEST_LENGTH:166:invalid digest length
+PROV_R_INVALID_DIGEST_SIZE:218:invalid digest size
 PROV_R_INVALID_ITERATION_COUNT:123:invalid iteration count
 PROV_R_INVALID_IVLEN:116:invalid ivlen
 PROV_R_INVALID_IV_LENGTH:109:invalid iv length
diff --git a/crypto/pkcs12/p12_key.c b/crypto/pkcs12/p12_key.c
index 4849cbd5bc..a40ae4cbe8 100644
--- a/crypto/pkcs12/p12_key.c
+++ b/crypto/pkcs12/p12_key.c
@@ -12,11 +12,9 @@
 #include <openssl/pkcs12.h>
 #include <openssl/bn.h>
 #include <openssl/trace.h>
-
-/* PKCS12 compatible key/IV generation */
-#ifndef min
-# define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include "internal/provider.h"
 
 int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
                        int saltlen, int id, int iter, int n,
@@ -68,16 +66,37 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
                        int saltlen, int id, int iter, int n,
                        unsigned char *out, const EVP_MD *md_type)
 {
-    unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
-    int Slen, Plen, Ilen;
-    int i, j, u, v;
-    int ret = 0;
-    EVP_MD_CTX *ctx = NULL;
-    unsigned char *tmpout = out;
-    int tmpn = n;
+    int res = 0;
+    EVP_KDF *kdf;
+    EVP_KDF_CTX *ctx;
+    OSSL_PARAM params[6], *p = params;
+
+    if (n <= 0)
+        return 0;
 
-    ctx = EVP_MD_CTX_new();
+    /*
+     * The parameter query isn't available but the library context can be
+     * extracted from the passed digest.
+     */
+    kdf = EVP_KDF_fetch(ossl_provider_library_context(EVP_MD_provider(md_type)),
+                        "PKCS12KDF", NULL);
+    if (kdf == NULL)
+        return 0;
+    ctx = EVP_KDF_CTX_new(kdf);
+    EVP_KDF_free(kdf);
     if (ctx == NULL)
+        return 0;
+
+    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+                                            (char *)EVP_MD_name(md_type), 0);
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+                                             pass, passlen);
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+                                             salt, saltlen);
+    *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS12_ID, &id);
+    *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter);
+    *p = OSSL_PARAM_construct_end();
+    if (!EVP_KDF_CTX_set_params(ctx, params))
         goto err;
 
     OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
@@ -89,77 +108,16 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
         BIO_hex_string(trc_out, 0, saltlen, salt, saltlen);
         BIO_printf(trc_out, "\n");
     } OSSL_TRACE_END(PKCS12_KEYGEN);
-    v = EVP_MD_block_size(md_type);
-    u = EVP_MD_size(md_type);
-    if (u < 0 || v <= 0)
-        goto err;
-    D = OPENSSL_malloc(v);
-    Ai = OPENSSL_malloc(u);
-    B = OPENSSL_malloc(v + 1);
-    Slen = v * ((saltlen + v - 1) / v);
-    if (passlen)
-        Plen = v * ((passlen + v - 1) / v);
-    else
-        Plen = 0;
-    Ilen = Slen + Plen;
-    I = OPENSSL_malloc(Ilen);
-    if (D == NULL || Ai == NULL || B == NULL || I == NULL)
-        goto err;
-    for (i = 0; i < v; i++)
-        D[i] = id;
-    p = I;
-    for (i = 0; i < Slen; i++)
-        *p++ = salt[i % saltlen];
-    for (i = 0; i < Plen; i++)
-        *p++ = pass[i % passlen];
-    for (;;) {
-        if (!EVP_DigestInit_ex(ctx, md_type, NULL)
-            || !EVP_DigestUpdate(ctx, D, v)
-            || !EVP_DigestUpdate(ctx, I, Ilen)
-            || !EVP_DigestFinal_ex(ctx, Ai, NULL))
-            goto err;
-        for (j = 1; j < iter; j++) {
-            if (!EVP_DigestInit_ex(ctx, md_type, NULL)
-                || !EVP_DigestUpdate(ctx, Ai, u)
-                || !EVP_DigestFinal_ex(ctx, Ai, NULL))
-                goto err;
-        }
-        memcpy(out, Ai, min(n, u));
-        if (u >= n) {
-            OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
-                BIO_printf(trc_out, "Output KEY (length %d)\n", tmpn);
-                BIO_hex_string(trc_out, 0, tmpn, tmpout, tmpn);
-                BIO_printf(trc_out, "\n");
-            } OSSL_TRACE_END(PKCS12_KEYGEN);
-            ret = 1;
-            goto end;
-        }
-        n -= u;
-        out += u;
-        for (j = 0; j < v; j++)
-            B[j] = Ai[j % u];
-        for (j = 0; j < Ilen; j += v) {
-            int k;
-            unsigned char *Ij = I + j;
-            uint16_t c = 1;
 
-            /* Work out Ij = Ij + B + 1 */
-            for (k = v - 1; k >= 0; k--) {
-                c += Ij[k] + B[k];
-                Ij[k] = (unsigned char)c;
-                c >>= 8;
-            }
-        }
+    if (EVP_KDF_derive(ctx, out, (size_t)n)) {
+        res = 1;
+        OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
+            BIO_printf(trc_out, "Output KEY (length %d)\n", n);
+            BIO_hex_string(trc_out, 0, n, out, n);
+            BIO_printf(trc_out, "\n");
+        } OSSL_TRACE_END(PKCS12_KEYGEN);
     }
-
  err:
-    PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI, ERR_R_MALLOC_FAILURE);
-
- end:
-    OPENSSL_free(Ai);
-    OPENSSL_free(B);
-    OPENSSL_free(D);
-    OPENSSL_free(I);
-    EVP_MD_CTX_free(ctx);
-    return ret;
+    EVP_KDF_CTX_free(ctx);
+    return res;
 }
diff --git a/doc/man7/EVP_KDF-PBKDF2.pod b/doc/man7/EVP_KDF-PKCS12KDF.pod
similarity index 59%
copy from doc/man7/EVP_KDF-PBKDF2.pod
copy to doc/man7/EVP_KDF-PKCS12KDF.pod
index b0b7ac1d65..68f987b050 100644
--- a/doc/man7/EVP_KDF-PBKDF2.pod
+++ b/doc/man7/EVP_KDF-PKCS12KDF.pod
@@ -2,20 +2,21 @@
 
 =head1 NAME
 
-EVP_KDF-PBKDF2 - The PBKDF2 EVP_KDF implementation
+EVP_KDF-PKCS12KDF - The PKCS#12 EVP_KDF implementation
 
 =head1 DESCRIPTION
 
-Support for computing the B<PBKDF2> password-based KDF through the B<EVP_KDF>
+Support for computing the B<PKCS#12> password-based KDF through the B<EVP_KDF>
 API.
 
-The EVP_KDF-PBKDF2 algorithm implements the PBKDF2 password-based key
-derivation function, as described in SP800-132; it derives a key from a password
-using a salt and iteration count.
+The EVP_KDF-PKCS12KDF algorithm implements the PKCS#12 password-based key
+derivation function, as described in appendix B of RFC 7292 (PKCS #12:
+Personal Information Exchange Syntax); it derives a key from a password
+using a salt, iteration count and the intended usage.
 
 =head2 Identity
 
-"PBKDF2" is the name for this implementation; it
+"PKCS12KDF" is the name for this implementation; it
 can be used with the EVP_KDF_fetch() function.
 
 =head2 Supported parameters
@@ -30,35 +31,16 @@ The supported parameters are:
 
 =item "iter" (B<OSSL_KDF_PARAM_ITER>) <unsigned integer>
 
-This parameter has a default value of 2048.
-
 =item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string>
 
 =item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string>
 
 These parameters work as described in L<EVP_KDF(3)/PARAMETERS>.
 
-=item "pkcs5" (B<OSSL_KDF_PARAM_PKCS5>) <integer>
-
-This parameter can be used to enable or disable SP800-132 compliance checks.
-Setting the mode to 0 enables the compliance checks.
-
-The checks performed are:
-
-=over 4
-
-=item - the iteration count is at least 1000.
-
-=item - the salt length is at least 128 bits.
-
-=item - the derived key length is at least 112 bits.
-
-=back
-
-The default provider uses a default mode of 1 for backwards compatibility,
-and the fips provider uses a default mode of 0.
+=item "id" (B<OSSL_KDF_PARAM_PKCS12_ID>) <integer>
 
-The value string is expected to be a decimal number 0 or 1.
+This parameter is used to specify the intended usage of the output bits, as per
+RFC 7292 section B.3.
 
 =back
 
@@ -77,7 +59,7 @@ byte sequence.
 
 =head1 CONFORMING TO
 
-SP800-132
+RFC7292
 
 =head1 SEE ALSO
 
@@ -94,7 +76,7 @@ This functionality was added to OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2020 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
diff --git a/doc/man7/OSSL_PROVIDER-default.pod b/doc/man7/OSSL_PROVIDER-default.pod
index 5fe7dbde8c..f82f8d8551 100644
--- a/doc/man7/OSSL_PROVIDER-default.pod
+++ b/doc/man7/OSSL_PROVIDER-default.pod
@@ -124,6 +124,8 @@ The OpenSSL default provider supports these operations and algorithms:
 
 =item PBKDF2, see L<EVP_KDF-PBKDF2(7)>
 
+=item PKCS12KDF, see L<EVP_KDF-PKCS12KDF(7)>
+
 =item SSHKDF, see L<EVP_KDF-SSHKDF(7)>
 
 =item TLS1-PRF, see L<EVP_KDF-TLS1_PRF(7)>
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index 53e68e778b..97c4d65949 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -178,6 +178,7 @@ extern "C" {
 #define OSSL_KDF_PARAM_SIZE         "size"      /* size_t */
 #define OSSL_KDF_PARAM_CIPHER       OSSL_ALG_PARAM_CIPHER     /* utf8 string */
 #define OSSL_KDF_PARAM_CONSTANT     "constant"  /* octet string */
+#define OSSL_KDF_PARAM_PKCS12_ID    "id"        /* int */
 
 /* Known KDF names */
 #define OSSL_KDF_NAME_HKDF          "HKDF"
diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h
index bdc39e4121..3f3c39ba52 100644
--- a/providers/common/include/prov/providercommonerr.h
+++ b/providers/common/include/prov/providercommonerr.h
@@ -88,6 +88,7 @@ int ERR_load_PROV_strings(void);
 # define PROV_R_INVALID_DATA                              115
 # define PROV_R_INVALID_DIGEST                            122
 # define PROV_R_INVALID_DIGEST_LENGTH                     166
+# define PROV_R_INVALID_DIGEST_SIZE                       218
 # define PROV_R_INVALID_ITERATION_COUNT                   123
 # define PROV_R_INVALID_IVLEN                             116
 # define PROV_R_INVALID_IV_LENGTH                         109
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
index e65ce96471..ad7ae57157 100644
--- a/providers/common/provider_err.c
+++ b/providers/common/provider_err.c
@@ -79,6 +79,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST), "invalid digest"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_LENGTH),
     "invalid digest length"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_SIZE),
+    "invalid digest size"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT),
     "invalid iteration count"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_IVLEN), "invalid ivlen"},
diff --git a/providers/defltprov.c b/providers/defltprov.c
index c34c539726..083373a066 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -316,6 +316,7 @@ static const OSSL_ALGORITHM deflt_kdfs[] = {
     { "HKDF", "provider=default", kdf_hkdf_functions },
     { "SSKDF", "provider=default", kdf_sskdf_functions },
     { "PBKDF2", "provider=default", kdf_pbkdf2_functions },
+    { "PKCS12KDF", "provider=default", kdf_pkcs12_functions },
     { "SSHKDF", "provider=default", kdf_sshkdf_functions },
     { "X963KDF", "provider=default", kdf_x963_kdf_functions },
     { "TLS1-PRF", "provider=default", kdf_tls1_prf_functions },
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 76053e22b0..f4c2a5adf5 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -244,6 +244,7 @@ extern const OSSL_DISPATCH poly1305_functions[];
 
 /* KDFs / PRFs */
 extern const OSSL_DISPATCH kdf_pbkdf2_functions[];
+extern const OSSL_DISPATCH kdf_pkcs12_functions[];
 #ifndef OPENSSL_NO_SCRYPT
 extern const OSSL_DISPATCH kdf_scrypt_functions[];
 #endif
diff --git a/providers/implementations/kdfs/build.info b/providers/implementations/kdfs/build.info
index 3b3884436a..459005def5 100644
--- a/providers/implementations/kdfs/build.info
+++ b/providers/implementations/kdfs/build.info
@@ -6,6 +6,7 @@ $HKDF_GOAL=../../libimplementations.a
 $KBKDF_GOAL=../../libimplementations.a
 $KRB5KDF_GOAL=../../libimplementations.a
 $PBKDF2_GOAL=../../libimplementations.a
+$PKCS12KDF_GOAL=../../libimplementations.a
 $SSKDF_GOAL=../../libimplementations.a
 $SCRYPT_GOAL=../../libimplementations.a
 $SSHKDF_GOAL=../../libimplementations.a
@@ -25,6 +26,8 @@ SOURCE[$PBKDF2_GOAL]=pbkdf2.c
 SOURCE[../../libfips.a]=pbkdf2_fips.c
 SOURCE[../../libnonfips.a]=pbkdf2_fips.c
 
+SOURCE[$PKCS12KDF_GOAL]=pkcs12kdf.c
+
 SOURCE[$SSKDF_GOAL]=sskdf.c
 
 SOURCE[$SCRYPT_GOAL]=scrypt.c
diff --git a/providers/implementations/kdfs/pkcs12kdf.c b/providers/implementations/kdfs/pkcs12kdf.c
new file mode 100644
index 0000000000..2cebc2d240
--- /dev/null
+++ b/providers/implementations/kdfs/pkcs12kdf.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright 1999-2020 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 "internal/cryptlib.h"
+#include "internal/numbers.h"
+#include "crypto/evp.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommonerr.h"
+#include "prov/implementations.h"
+#include "prov/provider_util.h"
+
+static OSSL_FUNC_kdf_newctx_fn kdf_pkcs12_new;
+static OSSL_FUNC_kdf_freectx_fn kdf_pkcs12_free;
+static OSSL_FUNC_kdf_reset_fn kdf_pkcs12_reset;
+static OSSL_FUNC_kdf_derive_fn kdf_pkcs12_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pkcs12_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pkcs12_set_ctx_params;
+static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pkcs12_gettable_ctx_params;
+static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pkcs12_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;
+    int id;
+} KDF_PKCS12;
+
+/* PKCS12 compatible key/IV generation */
+
+static int pkcs12kdf_derive(const unsigned char *pass, size_t passlen,
+                            const unsigned char *salt, size_t saltlen,
+                            int id, uint64_t iter, const EVP_MD *md_type,
+                            unsigned char *out, size_t n)
+{
+    unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
+    size_t Slen, Plen, Ilen;
+    size_t i, j, k, u, v;
+    uint64_t iter_cnt;
+    int ret = 0, ui, vi;
+    EVP_MD_CTX *ctx = NULL;
+
+    ctx = EVP_MD_CTX_new();
+    if (ctx == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+        goto end;
+    }
+    vi = EVP_MD_block_size(md_type);
+    ui = EVP_MD_size(md_type);
+    if (ui < 0 || vi <= 0) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE);
+        goto end;
+    }
+    u = (size_t)ui;
+    v = (size_t)vi;
+    D = OPENSSL_malloc(v);
+    Ai = OPENSSL_malloc(u);
+    B = OPENSSL_malloc(v + 1);
+    Slen = v * ((saltlen + v - 1) / v);
+    if (passlen != 0)
+        Plen = v * ((passlen + v - 1) / v);
+    else
+        Plen = 0;
+    Ilen = Slen + Plen;
+    I = OPENSSL_malloc(Ilen);
+    if (D == NULL || Ai == NULL || B == NULL || I == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+        goto end;
+    }
+    for (i = 0; i < v; i++)
+        D[i] = id;
+    p = I;
+    for (i = 0; i < Slen; i++)
+        *p++ = salt[i % saltlen];
+    for (i = 0; i < Plen; i++)
+        *p++ = pass[i % passlen];
+    for (;;) {
+        if (!EVP_DigestInit_ex(ctx, md_type, NULL)
+            || !EVP_DigestUpdate(ctx, D, v)
+            || !EVP_DigestUpdate(ctx, I, Ilen)
+            || !EVP_DigestFinal_ex(ctx, Ai, NULL))
+            goto end;
+        for (iter_cnt = 1; iter_cnt < iter; iter_cnt++) {
+            if (!EVP_DigestInit_ex(ctx, md_type, NULL)
+                || !EVP_DigestUpdate(ctx, Ai, u)
+                || !EVP_DigestFinal_ex(ctx, Ai, NULL))
+                goto end;
+        }
+        memcpy(out, Ai, n < u ? n : u);
+        if (u >= n) {
+            ret = 1;
+            break;
+        }
+        n -= u;
+        out += u;
+        for (j = 0; j < v; j++)
+            B[j] = Ai[j % u];
+        for (j = 0; j < Ilen; j += v) {
+            unsigned char *Ij = I + j;
+            uint16_t c = 1;
+
+            /* Work out Ij = Ij + B + 1 */
+            for (k = v; k > 0;) {
+                k--;
+                c += Ij[k] + B[k];
+                Ij[k] = (unsigned char)c;
+                c >>= 8;
+            }
+        }
+    }
+
+ end:
+    OPENSSL_free(Ai);
+    OPENSSL_free(B);
+    OPENSSL_free(D);
+    OPENSSL_free(I);
+    EVP_MD_CTX_free(ctx);
+    return ret;
+}
+
+static void *kdf_pkcs12_new(void *provctx)
+{
+    KDF_PKCS12 *ctx;
+
+    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_pkcs12_cleanup(KDF_PKCS12 *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_pkcs12_free(void *vctx)
+{
+    KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
+
+    if (ctx != NULL) {
+        kdf_pkcs12_cleanup(ctx);
+        OPENSSL_free(ctx);
+    }
+}
+
+static void kdf_pkcs12_reset(void *vctx)
+{
+    KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
+    void *provctx = ctx->provctx;
+
+    kdf_pkcs12_cleanup(ctx);
+    ctx->provctx = provctx;
+}
+
+static int pkcs12kdf_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_pkcs12_derive(void *vctx, unsigned char *key,
+                             size_t keylen)
+{
+    KDF_PKCS12 *ctx = (KDF_PKCS12 *)vctx;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
+
+    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;
+    }
+
+    return pkcs12kdf_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
+                            ctx->id, ctx->iter, md, key, keylen);
+}
+
+static int kdf_pkcs12_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    const OSSL_PARAM *p;
+    KDF_PKCS12 *ctx = vctx;
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
+
+    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+        return 0;
+
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL)
+        if (!pkcs12kdf_set_membuf(&ctx->pass, &ctx->pass_len, p))
+            return 0;
+
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL)
+        if (!pkcs12kdf_set_membuf(&ctx->salt, &ctx->salt_len,p))
+            return 0;
+
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS12_ID)) != NULL)
+        if (!OSSL_PARAM_get_int(p, &ctx->id))
+            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_pkcs12_settable_ctx_params(void *provctx)
+{
+    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_int(OSSL_KDF_PARAM_PKCS12_ID, NULL),
+        OSSL_PARAM_END
+    };
+    return known_settable_ctx_params;
+}
+
+static int kdf_pkcs12_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_pkcs12_gettable_ctx_params(void *provctx)
+{
+    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 kdf_pkcs12_functions[] = {
+    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pkcs12_new },
+    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pkcs12_free },
+    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pkcs12_reset },
+    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pkcs12_derive },
+    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+      (void(*)(void))kdf_pkcs12_settable_ctx_params },
+    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_set_ctx_params },
+    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+      (void(*)(void))kdf_pkcs12_gettable_ctx_params },
+    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pkcs12_get_ctx_params },
+    { 0, NULL }
+};
diff --git a/test/recipes/30-test_evp.t b/test/recipes/30-test_evp.t
index 29fb224e63..a49f4b50aa 100644
--- a/test/recipes/30-test_evp.t
+++ b/test/recipes/30-test_evp.t
@@ -46,7 +46,6 @@ my @files = qw(
                 evpmac_common.txt
                 evpmd_sha.txt
                 evppbe_pbkdf2.txt
-                evppbe_pkcs12.txt
                 evppkey_dsa.txt 
                 evppkey_ecc.txt
                 evppkey_ecdh.txt
@@ -93,6 +92,7 @@ my @defltfiles = qw(
                      evpmd_sm3.txt
                      evpmd_whirlpool.txt
                      evppbe_scrypt.txt
+                     evppbe_pkcs12.txt
                      evppkey_brainpool.txt
                      evppkey_kdf_scrypt.txt
                      evppkey_kdf_tls1_prf.txt


More information about the openssl-commits mailing list