isaacpittman-hitachi / rpms / openssl

Forked from rpms/openssl 2 years ago
Clone

Blame SOURCES/0062-fips-Expose-a-FIPS-indicator.patch

22d461
From e3d6fca1af033d00c47bcd8f9ba28fcf1aa476aa Mon Sep 17 00:00:00 2001
22d461
From: Clemens Lang <cllang@redhat.com>
22d461
Date: Tue, 7 Jun 2022 12:02:49 +0200
22d461
Subject: [PATCH] fips: Expose a FIPS indicator
22d461
22d461
FIPS 140-3 requires us to indicate whether an operation was using
22d461
approved services or not. The FIPS 140-3 implementation guidelines
22d461
provide two basic approaches to doing this: implicit indicators, and
22d461
explicit indicators.
22d461
22d461
Implicit indicators are basically the concept of "if the operation
22d461
passes, it was approved". We were originally aiming for implicit
22d461
indicators in our copy of OpenSSL. However, this proved to be a problem,
22d461
because we wanted to certify a signature service, and FIPS 140-3
22d461
requires that a signature service computes the digest to be signed
22d461
within the boundaries of the FIPS module. Since we were planning to
22d461
certify fips.so only, this means that EVP_PKEY_sign/EVP_PKEY_verify
22d461
would have to be blocked. Unfortunately, EVP_SignFinal uses
22d461
EVP_PKEY_sign internally, but outside of fips.so and thus outside of the
22d461
FIPS module boundary. This means that using implicit indicators in
22d461
combination with certifying only fips.so would require us to block both
22d461
EVP_PKEY_sign and EVP_SignFinal, which are the two APIs currently used
22d461
by most users of OpenSSL for signatures.
22d461
22d461
EVP_DigestSign would be acceptable, but has only been added in 3.0 and
22d461
is thus not yet widely used.
22d461
22d461
As a consequence, we've decided to introduce explicit indicators so that
22d461
EVP_PKEY_sign and EVP_SignFinal can continue to work for now, but
22d461
FIPS-aware applications can query the explicit indicator to check
22d461
whether the operation was approved.
22d461
22d461
To avoid affecting the ABI and public API too much, this is implemented
22d461
as an exported symbol in fips.so and a private header, so applications
22d461
that wish to use this will have to dlopen(3) fips.so, locate the
22d461
function using dlsym(3), and then call it. These applications will have
22d461
to build against the private header in order to use the returned
22d461
pointer.
22d461
22d461
Modify util/mkdef.pl to support exposing a symbol only for a specific
22d461
provider identified by its name and path.
22d461
22d461
Signed-off-by: Clemens Lang <cllang@redhat.com>
22d461
---
22d461
 doc/build.info                      |   6 ++
22d461
 doc/man7/fips_module_indicators.pod | 154 ++++++++++++++++++++++++++++
22d461
 providers/fips/fipsprov.c           |  71 +++++++++++++
22d461
 providers/fips/indicator.h          |  66 ++++++++++++
22d461
 util/mkdef.pl                       |  25 ++++-
22d461
 util/providers.num                  |   1 +
22d461
 6 files changed, 322 insertions(+), 1 deletion(-)
22d461
 create mode 100644 doc/man7/fips_module_indicators.pod
22d461
 create mode 100644 providers/fips/indicator.h
22d461
22d461
diff --git a/doc/build.info b/doc/build.info
22d461
index b0aa4297a4..af235113bb 100644
22d461
--- a/doc/build.info
22d461
+++ b/doc/build.info
22d461
@@ -4389,6 +4389,10 @@ DEPEND[html/man7/fips_module.html]=man7/fips_module.pod
22d461
 GENERATE[html/man7/fips_module.html]=man7/fips_module.pod
22d461
 DEPEND[man/man7/fips_module.7]=man7/fips_module.pod
22d461
 GENERATE[man/man7/fips_module.7]=man7/fips_module.pod
22d461
+DEPEND[html/man7/fips_module_indicators.html]=man7/fips_module_indicators.pod
22d461
+GENERATE[html/man7/fips_module_indicators.html]=man7/fips_module_indicators.pod
22d461
+DEPEND[man/man7/fips_module_indicators.7]=man7/fips_module_indicators.pod
22d461
+GENERATE[man/man7/fips_module_indicators.7]=man7/fips_module_indicators.pod
22d461
 DEPEND[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod
22d461
 GENERATE[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod
22d461
 DEPEND[man/man7/life_cycle-cipher.7]=man7/life_cycle-cipher.pod
22d461
@@ -4631,6 +4635,7 @@ html/man7/ct.html \
22d461
 html/man7/des_modes.html \
22d461
 html/man7/evp.html \
22d461
 html/man7/fips_module.html \
22d461
+html/man7/fips_module_indicators.html \
22d461
 html/man7/life_cycle-cipher.html \
22d461
 html/man7/life_cycle-digest.html \
22d461
 html/man7/life_cycle-kdf.html \
22d461
@@ -4754,6 +4759,7 @@ man/man7/ct.7 \
22d461
 man/man7/des_modes.7 \
22d461
 man/man7/evp.7 \
22d461
 man/man7/fips_module.7 \
22d461
+man/man7/fips_module_indicators.7 \
22d461
 man/man7/life_cycle-cipher.7 \
22d461
 man/man7/life_cycle-digest.7 \
22d461
 man/man7/life_cycle-kdf.7 \
22d461
diff --git a/doc/man7/fips_module_indicators.pod b/doc/man7/fips_module_indicators.pod
22d461
new file mode 100644
22d461
index 0000000000..23db2b395c
22d461
--- /dev/null
22d461
+++ b/doc/man7/fips_module_indicators.pod
22d461
@@ -0,0 +1,154 @@
22d461
+=pod
22d461
+
22d461
+=head1 NAME
22d461
+
22d461
+fips_module_indicators - Red Hat OpenSSL FIPS module indicators guide
22d461
+
22d461
+=head1 DESCRIPTION
22d461
+
22d461
+This guide documents how the Red Hat Enterprise Linux 9 OpenSSL FIPS provider
22d461
+implements Approved Security Service Indicators according to the FIPS 140-3
22d461
+Implementation Guidelines, section 2.4.C. See
22d461
+L<https://csrc.nist.gov/CSRC/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf>
22d461
+for the FIPS 140-3 Implementation Guidelines.
22d461
+
22d461
+For all approved services except signatures, the Red Hat OpenSSL FIPS provider
22d461
+uses the return code as the indicator as understood by FIPS 140-3. That means
22d461
+that every operation that succeeds denotes use of an approved security service.
22d461
+Operations that do not succeed may not have been approved security services, or
22d461
+may have been used incorrectly.
22d461
+
22d461
+For signatures, an explicit indicator API is available to determine whether
22d461
+a selected operation is an approved security service, in combination with the
22d461
+return code of the operation. For a signature operation to be approved, the
22d461
+explicit indicator must claim it as approved, and it must succeed.
22d461
+
22d461
+=head2 Querying the explicit indicator
22d461
+
22d461
+The Red Hat OpenSSL FIPS provider exports a symbol named
22d461
+I<redhat_ossl_query_fipsindicator> that provides information on which signature
22d461
+operations are approved security functions. To use this function, either link
22d461
+against I<fips.so> directly, or load it at runtime using dlopen(3) and
22d461
+dlsym(3).
22d461
+
22d461
+    #include <openssl/core_dispatch.h>
22d461
+    #include "providers/fips/indicator.h"
22d461
+
22d461
+    void *provider = dlopen("/usr/lib64/ossl-modules/fips.so", RTLD_LAZY);
22d461
+    if (provider == NULL) {
22d461
+        fprintf(stderr, "%s\n", dlerror());
22d461
+        // handle error
22d461
+    }
22d461
+
22d461
+    const OSSL_RH_FIPSINDICATOR_ALORITHM *(*redhat_ossl_query_fipsindicator)(int) \
22d461
+        = dlsym(provider, "redhat_ossl_query_fipsindicator");
22d461
+    if (redhat_ossl_query_fipsindicator == NULL) {
22d461
+        fprintf(stderr, "%s\n", dlerror());
22d461
+        fprintf(stderr, "Does your copy of fips.so have the required Red Hat"
22d461
+                        " patches?\n");
22d461
+        // handle error
22d461
+    }
22d461
+
22d461
+Note that this uses the I<providers/fips/indicator.h> header, which is not
22d461
+public. Install the I<openssl-debugsource> package from the I<BaseOS-debuginfo>
22d461
+repository using I<dnf debuginfo-install openssl> and include
22d461
+I</usr/src/debug/openssl-3.*/> in the compiler's include path.
22d461
+
22d461
+I<redhat_ossl_query_fipsindicator> expects an operation ID as its only
22d461
+argument. Currently, the only supported operation ID is I<OSSL_OP_SIGNATURE> to
22d461
+obtain the indicators for signature operations. On success, the return value is
22d461
+a pointer to an array of I<OSSL_RH_FIPSINDICATOR_STRUCT>s. On failure, NULL is
22d461
+returned. The last entry in the array is indicated by I<algorithm_names> being
22d461
+NULL.
22d461
+
22d461
+    typedef struct ossl_rh_fipsindicator_algorithm_st {
22d461
+        const char *algorithm_names;     /* key */
22d461
+        const char *property_definition; /* key */
22d461
+        const OSSL_RH_FIPSINDICATOR_DISPATCH *indicators;
22d461
+    } OSSL_RH_FIPSINDICATOR_ALGORITHM;
22d461
+
22d461
+    typedef struct ossl_rh_fipsindicator_dispatch_st {
22d461
+        int function_id;
22d461
+        int approved;
22d461
+    } OSSL_RH_FIPSINDICATOR_DISPATCH;
22d461
+
22d461
+The I<algorithm_names> field is a colon-separated list of algorithm names from
22d461
+one of the I<PROV_NAMES_...> constants, e.g., I<PROV_NAMES_RSA>. strtok(3) can
22d461
+be used to locate the appropriate entry. See the example below, where
22d461
+I<algorithm> contains the algorithm name to search for:
22d461
+
22d461
+    const OSSL_RH_FIPSINDICATOR_DISPATCH *indicator_dispatch = NULL;
22d461
+    const OSSL_RH_FIPSINDICATOR_ALGORITHM *indicator =
22d461
+        redhat_ossl_query_fipsindicator(operation_id);
22d461
+    if (indicator == NULL) {
22d461
+        fprintf(stderr, "No indicator for operation, probably using implicit"
22d461
+                        " indicators.\n");
22d461
+        // handle error
22d461
+    }
22d461
+
22d461
+    for (; indicator->algorithm_names != NULL; ++indicator) {
22d461
+        char *algorithm_names = strdup(indicator->algorithm_names);
22d461
+        if (algorithm_names == NULL) {
22d461
+            perror("strdup(3)");
22d461
+            // handle error
22d461
+        }
22d461
+
22d461
+        const char *algorithm_name = strtok(algorithm_names, ":");
22d461
+        for (; algorithm_name != NULL; algorithm_name = strtok(NULL, ":")) {
22d461
+            if (strcasecmp(algorithm_name, algorithm) == 0) {
22d461
+                indicator_dispatch = indicator->indicators;
22d461
+                free(algorithm_names);
22d461
+                algorithm_names = NULL;
22d461
+                break;
22d461
+            }
22d461
+        }
22d461
+        free(algorithm_names);
22d461
+    }
22d461
+    if (indicator_dispatch == NULL) {
22d461
+        fprintf(stderr, "No indicator for algorithm %s.\n", algorithm);
22d461
+        // handle error
22d461
+    }
22d461
+
22d461
+If an appropriate I<OSSL_RH_FIPSINDICATOR_DISPATCH> array is available for the
22d461
+given algorithm name, it maps function IDs to their approval status. The last
22d461
+entry is indicated by a zero I<function_id>. I<approved> is
22d461
+I<OSSL_RH_FIPSINDICATOR_APPROVED> if the operation is an approved security
22d461
+service, or part of an approved security service, or
22d461
+I<OSSL_RH_FIPSINDICATOR_UNAPPROVED> otherwise. Any other value is invalid.
22d461
+Function IDs are I<OSSL_FUNC_*> constants from I<openssl/core_dispatch.h>,
22d461
+e.g., I<OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE> or I<OSSL_FUNC_SIGNATURE_SIGN>.
22d461
+
22d461
+Assuming I<function_id> is the function in question, the following code can be
22d461
+used to query the approval status:
22d461
+
22d461
+    for (; indicator_dispatch->function_id != 0; ++indicator_dispatch) {
22d461
+        if (indicator_dispatch->function_id == function_id) {
22d461
+            switch (indicator_dispatch->approved) {
22d461
+                case OSSL_RH_FIPSINDICATOR_APPROVED:
22d461
+                    // approved security service
22d461
+                    break;
22d461
+                case OSSL_RH_FIPSINDICATOR_UNAPPROVED:
22d461
+                    // unapproved security service
22d461
+                    break;
22d461
+                default:
22d461
+                    // invalid result
22d461
+                    break;
22d461
+            }
22d461
+            break;
22d461
+        }
22d461
+    }
22d461
+
22d461
+=head1 SEE ALSO
22d461
+
22d461
+L<fips_module(7)>, L<provider(7)>
22d461
+
22d461
+=head1 COPYRIGHT
22d461
+
22d461
+Copyright 2022 Red Hat, Inc. All Rights Reserved.
22d461
+
22d461
+Licensed under the Apache License 2.0 (the "License").  You may not use
22d461
+this file except in compliance with the License.  You can obtain a copy
22d461
+in the file LICENSE in the source distribution or at
22d461
+L<https://www.openssl.org/source/license.html>.
22d461
+
22d461
+=cut
22d461
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
22d461
index de391ce067..1cfd71c5cf 100644
22d461
--- a/providers/fips/fipsprov.c
22d461
+++ b/providers/fips/fipsprov.c
22d461
@@ -23,6 +23,7 @@
22d461
 #include "prov/seeding.h"
22d461
 #include "self_test.h"
22d461
 #include "internal/core.h"
22d461
+#include "indicator.h"
22d461
 
22d461
 static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes";
22d461
 static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no";
22d461
@@ -425,6 +426,68 @@ static const OSSL_ALGORITHM fips_signature[] = {
22d461
     { NULL, NULL, NULL }
22d461
 };
22d461
 
22d461
+static const OSSL_RH_FIPSINDICATOR_DISPATCH redhat_rsa_signature_indicators[] = {
22d461
+    { OSSL_FUNC_SIGNATURE_NEWCTX, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SIGN_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SIGN, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_VERIFY, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_FREECTX, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DUPCTX, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { 0, OSSL_RH_FIPSINDICATOR_UNAPPROVED }
22d461
+};
22d461
+
22d461
+static const OSSL_RH_FIPSINDICATOR_DISPATCH redhat_ecdsa_signature_indicators[] = {
22d461
+    { OSSL_FUNC_SIGNATURE_NEWCTX, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SIGN_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SIGN, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_VERIFY, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_FREECTX, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_DUPCTX, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
22d461
+    { 0, OSSL_RH_FIPSINDICATOR_UNAPPROVED }
22d461
+};
22d461
+
22d461
+static const OSSL_RH_FIPSINDICATOR_ALGORITHM redhat_indicator_fips_signature[] = {
22d461
+    { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES,
22d461
+        redhat_rsa_signature_indicators },
22d461
+#ifndef OPENSSL_NO_EC
22d461
+    { PROV_NAMES_ECDSA, FIPS_DEFAULT_PROPERTIES,
22d461
+        redhat_ecdsa_signature_indicators },
22d461
+#endif
22d461
+    { NULL, NULL, NULL }
22d461
+};
22d461
+
22d461
 static const OSSL_ALGORITHM fips_asym_cipher[] = {
22d461
     { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ossl_rsa_asym_cipher_functions },
22d461
     { NULL, NULL, NULL }
22d461
@@ -527,6 +590,14 @@ static void fips_deinit_casecmp(void) {
22d461
     freelocale(loc);
22d461
 }
22d461
 
22d461
+const OSSL_RH_FIPSINDICATOR_ALGORITHM *redhat_ossl_query_fipsindicator(int operation_id) {
22d461
+    switch (operation_id) {
22d461
+    case OSSL_OP_SIGNATURE:
22d461
+        return redhat_indicator_fips_signature;
22d461
+    }
22d461
+    return NULL;
22d461
+}
22d461
+
22d461
 static void fips_teardown(void *provctx)
22d461
 {
22d461
     OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx));
22d461
diff --git a/providers/fips/indicator.h b/providers/fips/indicator.h
22d461
new file mode 100644
22d461
index 0000000000..b323efe44c
22d461
--- /dev/null
22d461
+++ b/providers/fips/indicator.h
22d461
@@ -0,0 +1,66 @@
22d461
+/*
22d461
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
22d461
+ *
22d461
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
22d461
+ * this file except in compliance with the License.  You can obtain a copy
22d461
+ * in the file LICENSE in the source distribution or at
22d461
+ * https://www.openssl.org/source/license.html
22d461
+ */
22d461
+
22d461
+#ifndef OPENSSL_FIPS_INDICATOR_H
22d461
+# define OPENSSL_FIPS_INDICATOR_H
22d461
+# pragma once
22d461
+
22d461
+# ifdef __cplusplus
22d461
+extern "C" {
22d461
+# endif
22d461
+
22d461
+# define OSSL_RH_FIPSINDICATOR_UNAPPROVED (0)
22d461
+# define OSSL_RH_FIPSINDICATOR_APPROVED (1)
22d461
+
22d461
+/*
22d461
+ * FIPS indicator dispatch table element.  function_id numbers and the
22d461
+ * functions are defined in core_dispatch.h, see macros with
22d461
+ * 'OSSL_CORE_MAKE_FUNC' in their names.
22d461
+ *
22d461
+ * An array of these is always terminated by function_id == 0
22d461
+ */
22d461
+typedef struct ossl_rh_fipsindicator_dispatch_st {
22d461
+    int function_id;
22d461
+    int approved;
22d461
+} OSSL_RH_FIPSINDICATOR_DISPATCH;
22d461
+
22d461
+/*
22d461
+ * Type to tie together algorithm names, property definition string and the
22d461
+ * algorithm implementation's FIPS indicator status in the form of a FIPS
22d461
+ * indicator dispatch table.
22d461
+ *
22d461
+ * An array of these is always terminated by algorithm_names == NULL
22d461
+ */
22d461
+typedef struct ossl_rh_fipsindicator_algorithm_st {
22d461
+    const char *algorithm_names;     /* key */
22d461
+    const char *property_definition; /* key */
22d461
+    const OSSL_RH_FIPSINDICATOR_DISPATCH *indicators;
22d461
+} OSSL_RH_FIPSINDICATOR_ALGORITHM;
22d461
+
22d461
+/**
22d461
+ * Query FIPS indicator status for the given operation.  Possible values for
22d461
+ * 'operation_id' are currently only OSSL_OP_SIGNATURE, as all other algorithms
22d461
+ * use implicit indicators.  The return value is an array of
22d461
+ * OSSL_RH_FIPSINDICATOR_ALGORITHMs, terminated by an entry with
22d461
+ * algorithm_names == NULL.  'algorithm_names' is a colon-separated list of
22d461
+ * algorithm names, 'property_definition' a comma-separated list of properties,
22d461
+ * and 'indicators' is a list of OSSL_RH_FIPSINDICATOR_DISPATCH structs.  This
22d461
+ * list is terminated by function_id == 0.  'function_id' is one of the
22d461
+ * OSSL_FUNC_* constants, e.g., OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL.
22d461
+ *
22d461
+ * If there is no entry in the returned struct for the given operation_id,
22d461
+ * algorithm name, or function_id, the algorithm is unapproved.
22d461
+ */
22d461
+const OSSL_RH_FIPSINDICATOR_ALGORITHM *redhat_ossl_query_fipsindicator(int operation_id);
22d461
+
22d461
+# ifdef __cplusplus
22d461
+}
22d461
+# endif
22d461
+
22d461
+#endif
22d461
diff --git a/util/mkdef.pl b/util/mkdef.pl
22d461
index a1c76f7c97..eda39b71ee 100755
22d461
--- a/util/mkdef.pl
22d461
+++ b/util/mkdef.pl
22d461
@@ -149,7 +149,8 @@ $ordinal_opts{filter} =
22d461
         return
22d461
             $item->exists()
22d461
             && platform_filter($item)
22d461
-            && feature_filter($item);
22d461
+            && feature_filter($item)
22d461
+            && fips_filter($item, $name);
22d461
     };
22d461
 my $ordinals = OpenSSL::Ordinals->new(from => $ordinals_file);
22d461
 
22d461
@@ -205,6 +206,28 @@ sub feature_filter {
22d461
     return $verdict;
22d461
 }
22d461
 
22d461
+sub fips_filter {
22d461
+    my $item = shift;
22d461
+    my $name = uc(shift);
22d461
+    my @features = ( $item->features() );
22d461
+
22d461
+    # True if no features are defined
22d461
+    return 1 if scalar @features == 0;
22d461
+
22d461
+    my @matches = grep(/^ONLY_.*$/, @features);
22d461
+    if (@matches) {
22d461
+        # There is at least one only_* flag on this symbol, check if any of
22d461
+        # them match the name
22d461
+        for (@matches) {
22d461
+            if ($_ eq "ONLY_${name}") {
22d461
+                return 1;
22d461
+            }
22d461
+        }
22d461
+        return 0;
22d461
+    }
22d461
+    return 1;
22d461
+}
22d461
+
22d461
 sub sorter_unix {
22d461
     my $by_name = OpenSSL::Ordinals::by_name();
22d461
     my %weight = (
22d461
diff --git a/util/providers.num b/util/providers.num
22d461
index 4e2fa81b98..77879d0e5f 100644
22d461
--- a/util/providers.num
22d461
+++ b/util/providers.num
22d461
@@ -1 +1,2 @@
22d461
 OSSL_provider_init                     1	*	EXIST::FUNCTION:
22d461
+redhat_ossl_query_fipsindicator        1	*	EXIST::FUNCTION:ONLY_PROVIDERS/FIPS
22d461
-- 
22d461
2.35.3
22d461