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