[openssl] master update

Dr. Paul Dale pauli at openssl.org
Fri Feb 12 02:31:16 UTC 2021


The branch master has been updated
       via  1eaf1fc353729ce696ac2528471d551d51175b8e (commit)
       via  2b248f4e3f53b97a745865a7f9e3984bb7acee17 (commit)
       via  ca2c778c26d488bd923121d7e4718b580fd283f2 (commit)
       via  7dd5a00f410206974d4ee134bb0ca05bf0f42061 (commit)
       via  b5873b31761e68015f4943ab137fc5e63323342e (commit)
       via  aea01d13135565680c7b1bc74222f5b2bf3f66c4 (commit)
       via  7dce37e2ec3d580eccce65c32f8d60dea600a28a (commit)
       via  499f2ae9e989015b75c5a3895994f26bc0a7334a (commit)
       via  31f7ff37b403f5ed50cf2e1e828a2e63576dac58 (commit)
      from  22040fb790c854cefb04bed98ed38ea6357daf83 (commit)


- Log -----------------------------------------------------------------
commit 1eaf1fc353729ce696ac2528471d551d51175b8e
Author: Pauli <ppzgs1 at gmail.com>
Date:   Wed Feb 10 21:53:57 2021 +1000

    Add a configure time option to disable the fetch cache.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

commit 2b248f4e3f53b97a745865a7f9e3984bb7acee17
Author: Pauli <ppzgs1 at gmail.com>
Date:   Tue Feb 9 16:58:38 2021 +1000

    test: add import and export key management hooks for the TLS provider.
    
    Without these hooks, if the TLS provider isn't matched in the fetch cache, a test
    failure will occur in the TLS API tests.  Without allowing import and export, an
    existing key can not move to a new key manager even if it is really the same.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

commit ca2c778c26d488bd923121d7e4718b580fd283f2
Author: Pauli <ppzgs1 at gmail.com>
Date:   Tue Feb 9 11:55:59 2021 +1000

    test: filter provider honours the no_cache setting.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

commit 7dd5a00f410206974d4ee134bb0ca05bf0f42061
Author: Pauli <ppzgs1 at gmail.com>
Date:   Mon Feb 8 13:09:49 2021 +1000

    changes: add a CHANGES.md entry for the OSSL_FORCE_NO_CACHE_FETCH option.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

commit b5873b31761e68015f4943ab137fc5e63323342e
Author: Pauli <ppzgs1 at gmail.com>
Date:   Mon Feb 8 12:01:20 2021 +1000

    test: fix no-cache problem with the quality comparison for KDFs.
    
    In a caching world, it's fine to compare the pointers directly.  In a
    non-caching world, the names and providers need to be compared.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

commit aea01d13135565680c7b1bc74222f5b2bf3f66c4
Author: Pauli <ppzgs1 at gmail.com>
Date:   Mon Feb 8 11:38:21 2021 +1000

    EVP: fix reference counting for EVP_CIPHER.
    
    Under some circumstances, the reference count for a cipher wasn't updated
    properly.  This shows up best when fetches are not being queried but would be
    possible if the cache flushed at a bad time.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

commit 7dce37e2ec3d580eccce65c32f8d60dea600a28a
Author: Pauli <ppzgs1 at gmail.com>
Date:   Mon Feb 8 11:03:01 2021 +1000

    Prov: add an option to force provider fetches to not be cached.
    
    If the macro OSSL_FORCE_NO_CACHE_FETCH is defined, no provider will have its
    fetches cached.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

commit 499f2ae9e989015b75c5a3895994f26bc0a7334a
Author: Pauli <ppzgs1 at gmail.com>
Date:   Mon Feb 8 11:02:52 2021 +1000

    CI: add a non-caching CI loop
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

commit 31f7ff37b403f5ed50cf2e1e828a2e63576dac58
Author: Pauli <ppzgs1 at gmail.com>
Date:   Mon Feb 8 10:54:52 2021 +1000

    EVP: fix reference counting for digest operations.
    
    The reference count wasn't being incremented but the EVP_MD pointer was being
    held.  In a no cache build, this resulted in a failure on update in some
    circumstances.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14126)

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

Summary of changes:
 .github/workflows/ci.yml | 11 +++++++
 CHANGES.md               |  6 ++++
 Configure                |  1 +
 INSTALL.md               |  8 +++++
 crypto/evp/digest.c      | 12 ++++++-
 crypto/evp/evp_enc.c     |  8 +++++
 crypto/provider_core.c   | 13 ++++++--
 test/evp_kdf_test.c      | 21 ++++++++++--
 test/filterprov.c        |  8 ++---
 test/tls-provider.c      | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 162 insertions(+), 11 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b057eb1d5b..67ec2541b3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -80,6 +80,17 @@ jobs:
     - name: make test
       run: make test HARNESS_JOBS=${HARNESS_JOBS:-4}
 
+  non-caching:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout at v2
+    - name: config
+      run: ./config enable-asan enable-ubsan no-cached-fetch && perl configdata.pm --dump
+    - name: make
+      run: make -s -j4
+    - name: make test
+      run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} OPENSSL_TEST_RAND_ORDER=0 TESTS="-test_fuzz* -test_ssl_* -test_evp -test_cmp_http -test_store -test_enc -[01][0-9]"
+
   sanitizers:
     runs-on: ubuntu-latest
     steps:
diff --git a/CHANGES.md b/CHANGES.md
index 380cd07886..b846746204 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -23,6 +23,12 @@ OpenSSL 3.0
 
 ### Changes between 1.1.1 and 3.0 [xx XXX xxxx]
 
+ * Add a compile time option to prevent the caching of provider fetched
+   algorithms.  This is enabled by including the no-cached-fetch option
+   at configuration time.
+
+   *Paul Dale*
+
  * Combining the Configure options no-ec and no-dh no longer disables TLSv1.3.
    Typically if OpenSSL has no EC or DH algorithms then it cannot support
    connections with TLSv1.3. However OpenSSL now supports "pluggable" groups
diff --git a/Configure b/Configure
index 9a96a7f0c0..cd11b2e393 100755
--- a/Configure
+++ b/Configure
@@ -392,6 +392,7 @@ my @disablables = (
     "blake2",
     "buildtest-c++",
     "bulk",
+    "cached-fetch",
     "camellia",
     "capieng",
     "cast",
diff --git a/INSTALL.md b/INSTALL.md
index e005312bc0..d9aa5c47c2 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -582,6 +582,14 @@ alternative, you can use the language specific variables, `CFLAGS` and `CXXFLAGS
 Build only some minimal set of features.
 This is a developer option used internally for CI build tests of the project.
 
+### no-cached-fetch
+
+Never cache algorithms when they are fetched from a provider.  Normally, a
+provider indicates if the algorithms it supplies can be cached or not.  Using
+this option will reduce run-time memory usage but it also introduces a
+significant performance penalty.  This option is primarily designed to help
+with detecting incorrect reference counting.
+
 ### no-capieng
 
 Don't build the CAPI engine.
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 40aedae47b..3dfcfcda8e 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -235,8 +235,10 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 #else
         EVP_MD *provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
 
-        if (provmd == NULL)
+        if (provmd == NULL) {
+            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
             return 0;
+        }
         type = provmd;
         EVP_MD_free(ctx->fetched_digest);
         ctx->fetched_digest = provmd;
@@ -248,6 +250,14 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
             ctx->digest->freectx(ctx->provctx);
         ctx->provctx = NULL;
     }
+    if (type->prov != NULL && ctx->fetched_digest != type) {
+        if (!EVP_MD_up_ref((EVP_MD *)type)) {
+            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+        EVP_MD_free(ctx->fetched_digest);
+        ctx->fetched_digest = (EVP_MD *)type;
+    }
     ctx->digest = type;
     if (ctx->provctx == NULL) {
         ctx->provctx = ctx->digest->newctx(ossl_provider_ctx(type->prov));
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index eb8c0faf14..b804d74914 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -182,6 +182,14 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 #endif
     }
 
+    if (cipher->prov != NULL) {
+        if (!EVP_CIPHER_up_ref((EVP_CIPHER *)cipher)) {
+            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+        EVP_CIPHER_free(ctx->fetched_cipher);
+        ctx->fetched_cipher = (EVP_CIPHER *)cipher;
+    }
     ctx->cipher = cipher;
     if (ctx->provctx == NULL) {
         ctx->provctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index 5016d54d55..627ff384e1 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -914,8 +914,17 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
                                                     int operation_id,
                                                     int *no_cache)
 {
-    return prov->query_operation == NULL
-        ? NULL : prov->query_operation(prov->provctx, operation_id, no_cache);
+    const OSSL_ALGORITHM *res;
+
+    if (prov->query_operation == NULL)
+        return NULL;
+    res = prov->query_operation(prov->provctx, operation_id, no_cache);
+#if defined(OPENSSL_NO_CACHED_FETCH)
+    /* Forcing the non-caching of queries */
+    if (no_cache != NULL)
+        *no_cache = 1;
+#endif
+    return res;
 }
 
 int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum)
diff --git a/test/evp_kdf_test.c b/test/evp_kdf_test.c
index b0e8d2b5fb..37d4653577 100644
--- a/test/evp_kdf_test.c
+++ b/test/evp_kdf_test.c
@@ -1260,6 +1260,21 @@ static int test_kdf_sshkdf(void)
     return ret;
 }
 
+static int test_kdfs_same( EVP_KDF *kdf1, EVP_KDF *kdf2)
+{
+    /* Fast path in case the two are the same algorithm pointer */
+    if (kdf1 == kdf2)
+        return 1;
+    /*
+     * Compare their names and providers instead.
+     * This is necessary in a non-caching build (or a cache flush during fetch)
+     * because without the algorithm in the cache, fetching it a second time
+     * will result in a different pointer.
+     */
+    return TEST_ptr_eq(EVP_KDF_provider(kdf1), EVP_KDF_provider(kdf2))
+           && TEST_str_eq(EVP_KDF_name(kdf1), EVP_KDF_name(kdf2));
+}
+
 static int test_kdf_get_kdf(void)
 {
     EVP_KDF *kdf1 = NULL, *kdf2 = NULL;
@@ -1270,7 +1285,7 @@ static int test_kdf_get_kdf(void)
         || !TEST_ptr(kdf1 = EVP_KDF_fetch(NULL, OSSL_KDF_NAME_PBKDF2, NULL))
         || !TEST_ptr(kdf2 = EVP_KDF_fetch(NULL, OBJ_nid2sn(OBJ_obj2nid(obj)),
                                           NULL))
-        || !TEST_ptr_eq(kdf1, kdf2))
+        || !test_kdfs_same(kdf1, kdf2))
         ok = 0;
     EVP_KDF_free(kdf1);
     kdf1 = NULL;
@@ -1279,14 +1294,14 @@ static int test_kdf_get_kdf(void)
 
     if (!TEST_ptr(kdf1 = EVP_KDF_fetch(NULL, SN_tls1_prf, NULL))
         || !TEST_ptr(kdf2 = EVP_KDF_fetch(NULL, LN_tls1_prf, NULL))
-        || !TEST_ptr_eq(kdf1, kdf2))
+        || !test_kdfs_same(kdf1, kdf2))
         ok = 0;
     /* kdf1 is re-used below, so don't free it here */
     EVP_KDF_free(kdf2);
     kdf2 = NULL;
 
     if (!TEST_ptr(kdf2 = EVP_KDF_fetch(NULL, OBJ_nid2sn(NID_tls1_prf), NULL))
-        || !TEST_ptr_eq(kdf1, kdf2))
+        || !test_kdfs_same(kdf1, kdf2))
         ok = 0;
     EVP_KDF_free(kdf1);
     kdf1 = NULL;
diff --git a/test/filterprov.c b/test/filterprov.c
index 3cfb095ae5..93ebca70ae 100644
--- a/test/filterprov.c
+++ b/test/filterprov.c
@@ -33,6 +33,7 @@ struct filter_prov_globals_st {
         OSSL_ALGORITHM alg[MAX_ALG_FILTERS + 1];
     } dispatch[MAX_FILTERS];
     int num_dispatch;
+    int no_cache;
 };
 
 static struct filter_prov_globals_st ourglobals;
@@ -83,7 +84,7 @@ static const OSSL_ALGORITHM *filter_query(void *provctx,
 
     for (i = 0; i < globs->num_dispatch; i++) {
         if (globs->dispatch[i].operation == operation_id) {
-            *no_cache = 0;
+            *no_cache = globs->no_cache;
             return globs->dispatch[i].alg;
         }
     }
@@ -156,10 +157,6 @@ int filter_provider_set_filter(int operation, const char *filterstr)
     if (filterstrtmp == NULL)
         goto err;
 
-    /* We don't support no_cache */
-    if (no_cache)
-        goto err;
-
     /* Nothing to filter */
     if (provalgs == NULL)
         goto err;
@@ -199,6 +196,7 @@ int filter_provider_set_filter(int operation, const char *filterstr)
     }
 
     globs->dispatch[globs->num_dispatch].operation = operation;
+    globs->no_cache = no_cache;
     globs->num_dispatch++;
 
     ret = 1;
diff --git a/test/tls-provider.c b/test/tls-provider.c
index 184b926881..64c855f4a9 100644
--- a/test/tls-provider.c
+++ b/test/tls-provider.c
@@ -15,6 +15,11 @@
 /* For TLS1_3_VERSION */
 #include <openssl/ssl.h>
 
+static OSSL_FUNC_keymgmt_import_fn xor_import;
+static OSSL_FUNC_keymgmt_import_types_fn xor_import_types;
+static OSSL_FUNC_keymgmt_export_fn xor_export;
+static OSSL_FUNC_keymgmt_export_types_fn xor_export_types;
+
 int tls_provider_init(const OSSL_CORE_HANDLE *handle,
                       const OSSL_DISPATCH *in,
                       const OSSL_DISPATCH **out,
@@ -600,6 +605,82 @@ static void *xor_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
     return key;
 }
 
+/* IMPORT + EXPORT */
+
+static int xor_import(void *vkey, int select, const OSSL_PARAM params[])
+{
+    XORKEY *key = vkey;
+    const OSSL_PARAM *param_priv_key, *param_pub_key;
+    unsigned char privkey[XOR_KEY_SIZE];
+    unsigned char pubkey[XOR_KEY_SIZE];
+    void *pprivkey = privkey, *ppubkey = pubkey;
+    size_t priv_len = 0, pub_len = 0;
+    int res = 0;
+
+    if (key == NULL || (select & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+        return 0;
+
+    memset(privkey, 0, sizeof(privkey));
+    memset(pubkey, 0, sizeof(pubkey));
+    param_priv_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
+    param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
+
+    if ((param_priv_key != NULL
+         && !OSSL_PARAM_get_octet_string(param_priv_key, &pprivkey,
+                                         sizeof(privkey), &priv_len))
+        || (param_pub_key != NULL
+            && !OSSL_PARAM_get_octet_string(param_pub_key, &ppubkey,
+                                            sizeof(pubkey), &pub_len)))
+        goto err;
+
+    if (priv_len > 0) {
+        memcpy(key->privkey, privkey, priv_len);
+        key->hasprivkey = 1;
+    }
+    if (pub_len > 0) {
+        memcpy(key->pubkey, pubkey, pub_len);
+        key->haspubkey = 1;
+    }
+    res = 1;
+ err:
+    return res;
+}
+
+static int xor_export(void *vkey, int select, OSSL_CALLBACK *param_cb,
+                      void *cbarg)
+{
+    XORKEY *key = vkey;
+    OSSL_PARAM params[3], *p = params;
+
+    if (key == NULL || (select & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+        return 0;
+
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
+                                             key->privkey,
+                                             sizeof(key->privkey));
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
+                                             key->pubkey, sizeof(key->pubkey));
+    *p++ = OSSL_PARAM_construct_end();
+
+    return param_cb(params, cbarg);
+}
+
+static const OSSL_PARAM xor_key_types[] = {
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
+    OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
+    OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *xor_import_types(int select)
+{
+    return (select & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 ? xor_key_types : NULL;
+}
+
+static const OSSL_PARAM *xor_export_types(int select)
+{
+    return (select & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 ? xor_key_types : NULL;
+}
+
 static void xor_gen_cleanup(void *genctx)
 {
     OPENSSL_free(genctx);
@@ -620,6 +701,10 @@ static const OSSL_DISPATCH xor_keymgmt_functions[] = {
     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))xor_has },
     { OSSL_FUNC_KEYMGMT_COPY, (void (*)(void))xor_copy },
     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))xor_freedata },
+    { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))xor_import },
+    { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))xor_import_types },
+    { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))xor_export },
+    { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))xor_export_types },
     { 0, NULL }
 };
 


More information about the openssl-commits mailing list