Add default property API's to enable and test for fips
authorShane Lontis <shane.lontis@oracle.com>
Sat, 2 May 2020 04:17:54 +0000 (14:17 +1000)
committerShane Lontis <shane.lontis@oracle.com>
Sat, 2 May 2020 04:17:54 +0000 (14:17 +1000)
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/11239)

12 files changed:
crypto/err/openssl.txt
crypto/evp/evp_cnf.c
crypto/evp/evp_err.c
crypto/evp/evp_fetch.c
crypto/property/property.c
crypto/property/property_parse.c
doc/man3/EVP_set_default_properties.pod
include/internal/property.h
include/openssl/evp.h
include/openssl/evperr.h
test/property_test.c
util/libcrypto.num

index 4978ce7a8cfcb1aeccfc59210426e9eebd696d24..9eeb9c8008e095c895645d352c40570161559211 100644 (file)
@@ -2572,6 +2572,7 @@ EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\
 EVP_R_PRIVATE_KEY_DECODE_ERROR:145:private key decode error
 EVP_R_PRIVATE_KEY_ENCODE_ERROR:146:private key encode error
 EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa
+EVP_R_SET_DEFAULT_PROPERTY_FAILURE:208:set default property failure
 EVP_R_TOO_MANY_RECORDS:183:too many records
 EVP_R_UNKNOWN_CIPHER:160:unknown cipher
 EVP_R_UNKNOWN_DIGEST:161:unknown digest
index fa35fd168c3499b56b0b199d03be652e3385358d..7798c4fcfae8d4bb0c31c9c5411198134954f971 100644 (file)
@@ -19,7 +19,6 @@ DEFINE_STACK_OF(CONF_VALUE)
 
 /* Algorithm configuration module. */
 
-/* TODO(3.0): the config module functions should be passed a library context */
 static int alg_module_init(CONF_IMODULE *md, const CONF *cnf)
 {
     int i;
@@ -46,14 +45,17 @@ static int alg_module_init(CONF_IMODULE *md, const CONF *cnf)
             }
             /*
              * fips_mode is deprecated and should not be used in new
-             * configurations.  Old configurations are likely to ONLY
-             * have this, so we assume that no default properties have
-             * been set before this.
+             * configurations.
              */
-            if (m > 0)
-                EVP_set_default_properties(NULL, "fips=yes");
+            if (!EVP_default_properties_enable_fips(cnf->libctx, m > 0)) {
+                EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_SET_DEFAULT_PROPERTY_FAILURE);
+                return 0;
+            }
         } else if (strcmp(oval->name, "default_properties") == 0) {
-            EVP_set_default_properties(NULL, oval->value);
+            if (!EVP_set_default_properties(cnf->libctx, oval->value)) {
+                EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_SET_DEFAULT_PROPERTY_FAILURE);
+                return 0;
+            }
         } else {
             EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_UNKNOWN_OPTION);
             ERR_add_error_data(4, "name=", oval->name,
index 5b7b4b586c801b5ad9af532020e067f532eb3a91..0908b1ca160fb3106b686add251601629349ce6b 100644 (file)
@@ -133,6 +133,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PRIVATE_KEY_ENCODE_ERROR),
     "private key encode error"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PUBLIC_KEY_NOT_RSA), "public key not rsa"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SET_DEFAULT_PROPERTY_FAILURE),
+    "set default property failure"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_TOO_MANY_RECORDS), "too many records"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_CIPHER), "unknown cipher"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "unknown digest"},
index 3176aa6b599be8e57b9a0db6c2d60416b55f30fd..be5ab111aaf01fdb35003b89bb652496a8565340 100644 (file)
@@ -367,10 +367,42 @@ int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq)
 
     if (store != NULL)
         return ossl_method_store_set_global_properties(store, propq);
-    EVPerr(EVP_F_EVP_SET_DEFAULT_PROPERTIES, ERR_R_INTERNAL_ERROR);
+    EVPerr(0, ERR_R_INTERNAL_ERROR);
     return 0;
 }
 
+
+static int evp_default_properties_merge(OPENSSL_CTX *libctx, const char *propq)
+{
+    OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
+
+    if (store != NULL)
+        return ossl_method_store_merge_global_properties(store, propq);
+    EVPerr(0, ERR_R_INTERNAL_ERROR);
+    return 0;
+}
+
+static int evp_default_property_is_enabled(OPENSSL_CTX *libctx,
+                                           const char *prop_name)
+{
+    OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
+
+    return ossl_method_store_global_property_is_enabled(store, prop_name);
+}
+
+int EVP_default_properties_is_fips_enabled(OPENSSL_CTX *libctx)
+{
+    return evp_default_property_is_enabled(libctx, "fips");
+}
+
+int EVP_default_properties_enable_fips(OPENSSL_CTX *libctx, int enable)
+{
+    const char *query = (enable != 0) ? "fips=yes" : "-fips";
+
+    return evp_default_properties_merge(libctx, query);
+}
+
+
 struct do_all_data_st {
     void (*user_fn)(void *method, void *arg);
     void *user_arg;
index 2bcbc85813459e4c23ac0bcb1dc038bfcd3b3aca..93df1bb679e0917f3f468f817534ee24a1d067a9 100644 (file)
@@ -362,8 +362,24 @@ fin:
     return ret;
 }
 
+int ossl_method_store_global_property_is_enabled(OSSL_METHOD_STORE *store,
+                                                 const char *prop_name)
+{
+    int ret = 0;
+
+    if (store == NULL)
+        return 0;
+
+    ossl_property_read_lock(store);
+    ret = ossl_property_is_enabled(store->ctx, prop_name,
+                                   store->global_properties);
+    ossl_property_unlock(store);
+    return ret;
+}
+
 int ossl_method_store_set_global_properties(OSSL_METHOD_STORE *store,
-                                            const char *prop_query) {
+                                            const char *prop_query)
+{
     int ret = 0;
 
     if (store == NULL)
@@ -371,9 +387,11 @@ int ossl_method_store_set_global_properties(OSSL_METHOD_STORE *store,
 
     ossl_property_write_lock(store);
     ossl_method_cache_flush_all(store);
+
+    ossl_property_free(store->global_properties);
+    store->global_properties = NULL;
+
     if (prop_query == NULL) {
-        ossl_property_free(store->global_properties);
-        store->global_properties = NULL;
         ossl_property_unlock(store);
         return 1;
     }
@@ -383,6 +401,45 @@ int ossl_method_store_set_global_properties(OSSL_METHOD_STORE *store,
     return ret;
 }
 
+int ossl_method_store_merge_global_properties(OSSL_METHOD_STORE *store,
+                                              const char *prop_query)
+{
+    int ret = 0;
+    OSSL_PROPERTY_LIST *prop = NULL, *global;
+
+    if (store == NULL)
+        return 1;
+
+    ossl_property_write_lock(store);
+    ossl_method_cache_flush_all(store);
+    if (prop_query == NULL) {
+        ossl_property_free(store->global_properties);
+        store->global_properties = NULL;
+        goto success;
+    }
+    prop = ossl_parse_query(store->ctx, prop_query);
+    if (prop == NULL)
+        goto end;
+
+    if (store->global_properties == NULL) {
+        store->global_properties = prop;
+        prop = NULL;
+        goto success;
+    }
+    global = ossl_property_merge(prop, store->global_properties);
+    if (global == NULL)
+        goto end;
+    ossl_property_free(store->global_properties);
+    store->global_properties = global;
+ success:
+    ret = 1;
+ end:
+    ossl_property_unlock(store);
+    ossl_property_free(prop);
+    return ret;
+}
+
+
 static void impl_cache_flush_alg(ossl_uintmax_t idx, ALGORITHM *alg)
 {
     lh_QUERY_doall(alg->cache, &impl_cache_free);
index eee76abc2c03f5012f95753970eb3414f9be58b3..21f78c02e2f4efaf750227b779f7f3b9022d39b3 100644 (file)
@@ -453,6 +453,35 @@ int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query)
     return query->has_optional ? 1 : 0;
 }
 
+int ossl_property_is_enabled(OPENSSL_CTX *ctx,  const char *property_name,
+                             const OSSL_PROPERTY_LIST *prop_list)
+{
+    int i;
+    OSSL_PROPERTY_IDX name_id;
+    const PROPERTY_DEFINITION *prop = NULL;
+
+    if (prop_list == NULL)
+        return 0;
+
+    if (!parse_name(ctx, &property_name, 0, &name_id))
+        return 0;
+
+    prop = prop_list->properties;
+    for (i = 0; i < prop_list->n; ++i) {
+        if (prop[i].name_idx == name_id) {
+            /* Do a separate check for override as it does not set type */
+            if (prop[i].optional || prop[i].oper == PROPERTY_OVERRIDE)
+                return 0;
+            return (prop[i].type == PROPERTY_TYPE_STRING
+                    && ((prop[i].oper == PROPERTY_OPER_EQ
+                             && prop[i].v.str_val == ossl_property_true)
+                         || (prop[i].oper == PROPERTY_OPER_NE
+                             && prop[i].v.str_val != ossl_property_true)));
+        }
+    }
+    return 0;
+}
+
 /*
  * Compare a query against a definition.
  * Return the number of clauses matched or -1 if a mandatory clause is false.
index 6231fde6277f2a500895c40e56c8bac2098ee0d7..1981ff12c19a77bbf86a7290f8fc36230c1082ce 100644 (file)
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-EVP_set_default_properties
+EVP_set_default_properties, EVP_default_properties_enable_fips,
+EVP_default_properties_is_fips_enabled
 - Set default properties for future algorithm fetches
 
 =head1 SYNOPSIS
@@ -10,6 +11,8 @@ EVP_set_default_properties
  #include <openssl/evp.h>
 
  int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq);
+ int EVP_default_properties_enable_fips(OPENSSL_CTX *libctx, int enable);
+ int EVP_default_properties_is_fips_enabled(OPENSSL_CTX *libctx);
 
 =head1 DESCRIPTION
 
@@ -27,10 +30,22 @@ given with I<libctx> (NULL signifies the default library context).
 Any previous default property for the specified library context will
 be dropped.
 
+EVP_default_properties_enable_fips() sets the 'fips=yes' to be a default property
+if I<enable> is non zero, otherwise it clears 'fips' from the default property
+query for the given I<libctx>. It merges the fips default property query with any
+existing query strings that have been set via EVP_set_default_properties().
+
+EVP_default_properties_is_fips_enabled() indicates if 'fips=yes' is a default
+property for the given I<libctx>.
+
 =head1 RETURN VALUES
 
-EVP_set_default_properties() returns 1 on success, or 0 on failure.
-The latter adds an error on the error stack.
+EVP_set_default_properties() and  EVP_default_properties_enable_fips() return 1
+on success, or 0 on failure. An error is placed on the the error stack if a
+failure occurs.
+
+EVP_default_properties_is_fips_enabled() returns 1 if the 'fips=true' default
+property is set for the given I<libctx>, otherwise it returns 0.
 
 =head1 SEE ALSO
 
@@ -42,7 +57,7 @@ The functions described here were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-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
index 5e23dabab050e04348d89e86c9c10a52dee083b4..2b2332b237c1371167cfa533211d5dc4378bd83c 100644 (file)
@@ -26,6 +26,8 @@ OSSL_PROPERTY_LIST *ossl_parse_query(OPENSSL_CTX *ctx, const char *s);
 /* Property checker of query vs definition */
 int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
                               const OSSL_PROPERTY_LIST *defn);
+int ossl_property_is_enabled(OPENSSL_CTX *ctx,  const char *property_name,
+                             const OSSL_PROPERTY_LIST *prop_list);
 /* Free a parsed property list */
 void ossl_property_free(OSSL_PROPERTY_LIST *p);
 
@@ -43,6 +45,10 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
                             const char *prop_query, void **result);
 int ossl_method_store_set_global_properties(OSSL_METHOD_STORE *store,
                                             const char *prop_query);
+int ossl_method_store_merge_global_properties(OSSL_METHOD_STORE *store,
+                                              const char *prop_query);
+int ossl_method_store_global_property_is_enabled(OSSL_METHOD_STORE *store,
+                                                 const char *prop_name);
 
 /* property query cache functions */
 int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid,
index ec1103522e2a914bc7028022943e6ae874623546..23cf52df0fe2a0b6781479d4c8a4187b70f9a443 100644 (file)
@@ -78,6 +78,8 @@ extern "C" {
 #endif
 
 int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq);
+int EVP_default_properties_is_fips_enabled(OPENSSL_CTX *libctx);
+int EVP_default_properties_enable_fips(OPENSSL_CTX *libctx, int enable);
 
 # define EVP_PKEY_MO_SIGN        0x0001
 # define EVP_PKEY_MO_VERIFY      0x0002
index b8799a6f43f93d6194e30a2ca0fc84bfa98a135d..61848bbc0c36b1b4b1dcbfd8e785a7e7c9eef57b 100644 (file)
@@ -235,6 +235,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_PRIVATE_KEY_DECODE_ERROR                   145
 # define EVP_R_PRIVATE_KEY_ENCODE_ERROR                   146
 # define EVP_R_PUBLIC_KEY_NOT_RSA                         106
+# define EVP_R_SET_DEFAULT_PROPERTY_FAILURE               208
 # define EVP_R_TOO_MANY_RECORDS                           183
 # define EVP_R_UNKNOWN_CIPHER                             160
 # define EVP_R_UNKNOWN_DIGEST                             161
index ca407b2ba43a6d5786a92ad650e2c5d3d636659f..aad43b91841700f7e55170054b9c0b865c10b656 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <stdarg.h>
+#include <openssl/evp.h>
 #include "testutil.h"
 #include "internal/nelem.h"
 #include "internal/property.h"
@@ -383,6 +384,35 @@ err:
     return res;
 }
 
+static int test_fips_mode(void)
+{
+    int ret = 0;
+    OPENSSL_CTX *ctx = NULL;
+
+    if (!TEST_ptr(ctx = OPENSSL_CTX_new()))
+        goto err;
+
+    ret = TEST_true(EVP_set_default_properties(ctx, "default=yes,fips=yes"))
+          && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
+          && TEST_true(EVP_set_default_properties(ctx, "fips=no,default=yes"))
+          && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
+          && TEST_true(EVP_set_default_properties(ctx, "fips=no"))
+          && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
+          && TEST_true(EVP_set_default_properties(ctx, "fips!=no"))
+          && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
+          && TEST_true(EVP_set_default_properties(ctx, "fips=no"))
+          && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
+          && TEST_true(EVP_set_default_properties(ctx, "fips=no,default=yes"))
+          && TEST_true(EVP_default_properties_enable_fips(ctx, 1))
+          && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
+          && TEST_true(EVP_default_properties_enable_fips(ctx, 0))
+          && TEST_false(EVP_default_properties_is_fips_enabled(ctx));
+err:
+    OPENSSL_CTX_free(ctx);
+    return ret;
+}
+
+
 int setup_tests(void)
 {
     ADD_TEST(test_property_string);
@@ -393,5 +423,6 @@ int setup_tests(void)
     ADD_TEST(test_register_deregister);
     ADD_TEST(test_property);
     ADD_TEST(test_query_cache_stochastic);
+    ADD_TEST(test_fips_mode);
     return 1;
 }
index 6c7ce4c0c3ff40ff9e73adc923a6d6c0b83014a5..ec0e6a171bc0cf0ab0bcef7eb4cade7b86ef39af 100644 (file)
@@ -5079,3 +5079,5 @@ X509_REQ_set0_signature                 ? 3_0_0   EXIST::FUNCTION:
 X509_REQ_set1_signature_algo            ?      3_0_0   EXIST::FUNCTION:
 OSSL_PARAM_modified                     ?      3_0_0   EXIST::FUNCTION:
 OSSL_PARAM_set_all_unmodified           ?      3_0_0   EXIST::FUNCTION:
+EVP_default_properties_is_fips_enabled  ?      3_0_0   EXIST::FUNCTION:
+EVP_default_properties_enable_fips      ?      3_0_0   EXIST::FUNCTION: