Blob Blame History Raw
diff -rupN --no-dereference openssl-3.0.9/doc/build.info openssl-3.0.9-new/doc/build.info
--- openssl-3.0.9/doc/build.info	2023-05-30 14:31:57.000000000 +0200
+++ openssl-3.0.9-new/doc/build.info	2023-05-31 14:33:16.925112941 +0200
@@ -4461,6 +4461,10 @@ DEPEND[html/man7/fips_module.html]=man7/
 GENERATE[html/man7/fips_module.html]=man7/fips_module.pod
 DEPEND[man/man7/fips_module.7]=man7/fips_module.pod
 GENERATE[man/man7/fips_module.7]=man7/fips_module.pod
+DEPEND[html/man7/fips_module_indicators.html]=man7/fips_module_indicators.pod
+GENERATE[html/man7/fips_module_indicators.html]=man7/fips_module_indicators.pod
+DEPEND[man/man7/fips_module_indicators.7]=man7/fips_module_indicators.pod
+GENERATE[man/man7/fips_module_indicators.7]=man7/fips_module_indicators.pod
 DEPEND[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod
 GENERATE[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod
 DEPEND[man/man7/life_cycle-cipher.7]=man7/life_cycle-cipher.pod
@@ -4706,6 +4710,7 @@ html/man7/ct.html \
 html/man7/des_modes.html \
 html/man7/evp.html \
 html/man7/fips_module.html \
+html/man7/fips_module_indicators.html \
 html/man7/life_cycle-cipher.html \
 html/man7/life_cycle-digest.html \
 html/man7/life_cycle-kdf.html \
@@ -4832,6 +4837,7 @@ man/man7/ct.7 \
 man/man7/des_modes.7 \
 man/man7/evp.7 \
 man/man7/fips_module.7 \
+man/man7/fips_module_indicators.7 \
 man/man7/life_cycle-cipher.7 \
 man/man7/life_cycle-digest.7 \
 man/man7/life_cycle-kdf.7 \
diff -rupN --no-dereference openssl-3.0.9/doc/man7/fips_module_indicators.pod openssl-3.0.9-new/doc/man7/fips_module_indicators.pod
--- openssl-3.0.9/doc/man7/fips_module_indicators.pod	1970-01-01 01:00:00.000000000 +0100
+++ openssl-3.0.9-new/doc/man7/fips_module_indicators.pod	2023-05-31 14:33:16.925112941 +0200
@@ -0,0 +1,154 @@
+=pod
+
+=head1 NAME
+
+fips_module_indicators - Red Hat OpenSSL FIPS module indicators guide
+
+=head1 DESCRIPTION
+
+This guide documents how the Red Hat Enterprise Linux 9 OpenSSL FIPS provider
+implements Approved Security Service Indicators according to the FIPS 140-3
+Implementation Guidelines, section 2.4.C. See
+L<https://csrc.nist.gov/CSRC/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf>
+for the FIPS 140-3 Implementation Guidelines.
+
+For all approved services except signatures, the Red Hat OpenSSL FIPS provider
+uses the return code as the indicator as understood by FIPS 140-3. That means
+that every operation that succeeds denotes use of an approved security service.
+Operations that do not succeed may not have been approved security services, or
+may have been used incorrectly.
+
+For signatures, an explicit indicator API is available to determine whether
+a selected operation is an approved security service, in combination with the
+return code of the operation. For a signature operation to be approved, the
+explicit indicator must claim it as approved, and it must succeed.
+
+=head2 Querying the explicit indicator
+
+The Red Hat OpenSSL FIPS provider exports a symbol named
+I<redhat_ossl_query_fipsindicator> that provides information on which signature
+operations are approved security functions. To use this function, either link
+against I<fips.so> directly, or load it at runtime using dlopen(3) and
+dlsym(3).
+
+    #include <openssl/core_dispatch.h>
+    #include "providers/fips/indicator.h"
+
+    void *provider = dlopen("/usr/lib64/ossl-modules/fips.so", RTLD_LAZY);
+    if (provider == NULL) {
+        fprintf(stderr, "%s\n", dlerror());
+        // handle error
+    }
+
+    const OSSL_RH_FIPSINDICATOR_ALORITHM *(*redhat_ossl_query_fipsindicator)(int) \
+        = dlsym(provider, "redhat_ossl_query_fipsindicator");
+    if (redhat_ossl_query_fipsindicator == NULL) {
+        fprintf(stderr, "%s\n", dlerror());
+        fprintf(stderr, "Does your copy of fips.so have the required Red Hat"
+                        " patches?\n");
+        // handle error
+    }
+
+Note that this uses the I<providers/fips/indicator.h> header, which is not
+public. Install the I<openssl-debugsource> package from the I<BaseOS-debuginfo>
+repository using I<dnf debuginfo-install openssl> and include
+I</usr/src/debug/openssl-3.*/> in the compiler's include path.
+
+I<redhat_ossl_query_fipsindicator> expects an operation ID as its only
+argument. Currently, the only supported operation ID is I<OSSL_OP_SIGNATURE> to
+obtain the indicators for signature operations. On success, the return value is
+a pointer to an array of I<OSSL_RH_FIPSINDICATOR_STRUCT>s. On failure, NULL is
+returned. The last entry in the array is indicated by I<algorithm_names> being
+NULL.
+
+    typedef struct ossl_rh_fipsindicator_algorithm_st {
+        const char *algorithm_names;     /* key */
+        const char *property_definition; /* key */
+        const OSSL_RH_FIPSINDICATOR_DISPATCH *indicators;
+    } OSSL_RH_FIPSINDICATOR_ALGORITHM;
+
+    typedef struct ossl_rh_fipsindicator_dispatch_st {
+        int function_id;
+        int approved;
+    } OSSL_RH_FIPSINDICATOR_DISPATCH;
+
+The I<algorithm_names> field is a colon-separated list of algorithm names from
+one of the I<PROV_NAMES_...> constants, e.g., I<PROV_NAMES_RSA>. strtok(3) can
+be used to locate the appropriate entry. See the example below, where
+I<algorithm> contains the algorithm name to search for:
+
+    const OSSL_RH_FIPSINDICATOR_DISPATCH *indicator_dispatch = NULL;
+    const OSSL_RH_FIPSINDICATOR_ALGORITHM *indicator =
+        redhat_ossl_query_fipsindicator(operation_id);
+    if (indicator == NULL) {
+        fprintf(stderr, "No indicator for operation, probably using implicit"
+                        " indicators.\n");
+        // handle error
+    }
+
+    for (; indicator->algorithm_names != NULL; ++indicator) {
+        char *algorithm_names = strdup(indicator->algorithm_names);
+        if (algorithm_names == NULL) {
+            perror("strdup(3)");
+            // handle error
+        }
+
+        const char *algorithm_name = strtok(algorithm_names, ":");
+        for (; algorithm_name != NULL; algorithm_name = strtok(NULL, ":")) {
+            if (strcasecmp(algorithm_name, algorithm) == 0) {
+                indicator_dispatch = indicator->indicators;
+                free(algorithm_names);
+                algorithm_names = NULL;
+                break;
+            }
+        }
+        free(algorithm_names);
+    }
+    if (indicator_dispatch == NULL) {
+        fprintf(stderr, "No indicator for algorithm %s.\n", algorithm);
+        // handle error
+    }
+
+If an appropriate I<OSSL_RH_FIPSINDICATOR_DISPATCH> array is available for the
+given algorithm name, it maps function IDs to their approval status. The last
+entry is indicated by a zero I<function_id>. I<approved> is
+I<OSSL_RH_FIPSINDICATOR_APPROVED> if the operation is an approved security
+service, or part of an approved security service, or
+I<OSSL_RH_FIPSINDICATOR_UNAPPROVED> otherwise. Any other value is invalid.
+Function IDs are I<OSSL_FUNC_*> constants from I<openssl/core_dispatch.h>,
+e.g., I<OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE> or I<OSSL_FUNC_SIGNATURE_SIGN>.
+
+Assuming I<function_id> is the function in question, the following code can be
+used to query the approval status:
+
+    for (; indicator_dispatch->function_id != 0; ++indicator_dispatch) {
+        if (indicator_dispatch->function_id == function_id) {
+            switch (indicator_dispatch->approved) {
+                case OSSL_RH_FIPSINDICATOR_APPROVED:
+                    // approved security service
+                    break;
+                case OSSL_RH_FIPSINDICATOR_UNAPPROVED:
+                    // unapproved security service
+                    break;
+                default:
+                    // invalid result
+                    break;
+            }
+            break;
+        }
+    }
+
+=head1 SEE ALSO
+
+L<fips_module(7)>, L<provider(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2022 Red Hat, Inc. 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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff -rupN --no-dereference openssl-3.0.9/providers/fips/fipsprov.c openssl-3.0.9-new/providers/fips/fipsprov.c
--- openssl-3.0.9/providers/fips/fipsprov.c	2023-05-31 14:33:14.351114053 +0200
+++ openssl-3.0.9-new/providers/fips/fipsprov.c	2023-05-31 14:33:16.925112941 +0200
@@ -23,6 +23,7 @@
 #include "prov/seeding.h"
 #include "self_test.h"
 #include "internal/core.h"
+#include "indicator.h"
 
 static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes";
 static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no";
@@ -409,6 +410,68 @@ static const OSSL_ALGORITHM fips_signatu
     { NULL, NULL, NULL }
 };
 
+static const OSSL_RH_FIPSINDICATOR_DISPATCH redhat_rsa_signature_indicators[] = {
+    { OSSL_FUNC_SIGNATURE_NEWCTX, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SIGN_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_SIGN, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_VERIFY, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_FREECTX, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DUPCTX, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { 0, OSSL_RH_FIPSINDICATOR_UNAPPROVED }
+};
+
+static const OSSL_RH_FIPSINDICATOR_DISPATCH redhat_ecdsa_signature_indicators[] = {
+    { OSSL_FUNC_SIGNATURE_NEWCTX, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SIGN_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_SIGN, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_VERIFY, OSSL_RH_FIPSINDICATOR_UNAPPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_FREECTX, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_DUPCTX, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED },
+    { 0, OSSL_RH_FIPSINDICATOR_UNAPPROVED }
+};
+
+static const OSSL_RH_FIPSINDICATOR_ALGORITHM redhat_indicator_fips_signature[] = {
+    { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES,
+        redhat_rsa_signature_indicators },
+#ifndef OPENSSL_NO_EC
+    { PROV_NAMES_ECDSA, FIPS_DEFAULT_PROPERTIES,
+        redhat_ecdsa_signature_indicators },
+#endif
+    { NULL, NULL, NULL }
+};
+
 static const OSSL_ALGORITHM fips_asym_cipher[] = {
     { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ossl_rsa_asym_cipher_functions },
     { NULL, NULL, NULL }
@@ -493,6 +556,14 @@ static const OSSL_ALGORITHM *fips_query(
     }
     return NULL;
 }
+
+const OSSL_RH_FIPSINDICATOR_ALGORITHM *redhat_ossl_query_fipsindicator(int operation_id) {
+    switch (operation_id) {
+    case OSSL_OP_SIGNATURE:
+        return redhat_indicator_fips_signature;
+    }
+    return NULL;
+}
 
 static void fips_teardown(void *provctx)
 {
diff -rupN --no-dereference openssl-3.0.9/providers/fips/indicator.h openssl-3.0.9-new/providers/fips/indicator.h
--- openssl-3.0.9/providers/fips/indicator.h	1970-01-01 01:00:00.000000000 +0100
+++ openssl-3.0.9-new/providers/fips/indicator.h	2023-05-31 14:33:16.926112941 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019-2021 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
+ */
+
+#ifndef OPENSSL_FIPS_INDICATOR_H
+# define OPENSSL_FIPS_INDICATOR_H
+# pragma once
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define OSSL_RH_FIPSINDICATOR_UNAPPROVED (0)
+# define OSSL_RH_FIPSINDICATOR_APPROVED (1)
+
+/*
+ * FIPS indicator dispatch table element.  function_id numbers and the
+ * functions are defined in core_dispatch.h, see macros with
+ * 'OSSL_CORE_MAKE_FUNC' in their names.
+ *
+ * An array of these is always terminated by function_id == 0
+ */
+typedef struct ossl_rh_fipsindicator_dispatch_st {
+    int function_id;
+    int approved;
+} OSSL_RH_FIPSINDICATOR_DISPATCH;
+
+/*
+ * Type to tie together algorithm names, property definition string and the
+ * algorithm implementation's FIPS indicator status in the form of a FIPS
+ * indicator dispatch table.
+ *
+ * An array of these is always terminated by algorithm_names == NULL
+ */
+typedef struct ossl_rh_fipsindicator_algorithm_st {
+    const char *algorithm_names;     /* key */
+    const char *property_definition; /* key */
+    const OSSL_RH_FIPSINDICATOR_DISPATCH *indicators;
+} OSSL_RH_FIPSINDICATOR_ALGORITHM;
+
+/**
+ * Query FIPS indicator status for the given operation.  Possible values for
+ * 'operation_id' are currently only OSSL_OP_SIGNATURE, as all other algorithms
+ * use implicit indicators.  The return value is an array of
+ * OSSL_RH_FIPSINDICATOR_ALGORITHMs, terminated by an entry with
+ * algorithm_names == NULL.  'algorithm_names' is a colon-separated list of
+ * algorithm names, 'property_definition' a comma-separated list of properties,
+ * and 'indicators' is a list of OSSL_RH_FIPSINDICATOR_DISPATCH structs.  This
+ * list is terminated by function_id == 0.  'function_id' is one of the
+ * OSSL_FUNC_* constants, e.g., OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL.
+ *
+ * If there is no entry in the returned struct for the given operation_id,
+ * algorithm name, or function_id, the algorithm is unapproved.
+ */
+const OSSL_RH_FIPSINDICATOR_ALGORITHM *redhat_ossl_query_fipsindicator(int operation_id);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff -rupN --no-dereference openssl-3.0.9/util/mkdef.pl openssl-3.0.9-new/util/mkdef.pl
--- openssl-3.0.9/util/mkdef.pl	2023-05-30 14:31:57.000000000 +0200
+++ openssl-3.0.9-new/util/mkdef.pl	2023-05-31 14:33:16.926112941 +0200
@@ -153,7 +153,8 @@ $ordinal_opts{filter} =
         return
             $item->exists()
             && platform_filter($item)
-            && feature_filter($item);
+            && feature_filter($item)
+            && fips_filter($item, $name);
     };
 my $ordinals = OpenSSL::Ordinals->new(from => $ordinals_file);
 
@@ -209,6 +210,28 @@ sub feature_filter {
     return $verdict;
 }
 
+sub fips_filter {
+    my $item = shift;
+    my $name = uc(shift);
+    my @features = ( $item->features() );
+
+    # True if no features are defined
+    return 1 if scalar @features == 0;
+
+    my @matches = grep(/^ONLY_.*$/, @features);
+    if (@matches) {
+        # There is at least one only_* flag on this symbol, check if any of
+        # them match the name
+        for (@matches) {
+            if ($_ eq "ONLY_${name}") {
+                return 1;
+            }
+        }
+        return 0;
+    }
+    return 1;
+}
+
 sub sorter_unix {
     my $by_name = OpenSSL::Ordinals::by_name();
     my %weight = (
diff -rupN --no-dereference openssl-3.0.9/util/providers.num openssl-3.0.9-new/util/providers.num
--- openssl-3.0.9/util/providers.num	2023-05-30 14:31:57.000000000 +0200
+++ openssl-3.0.9-new/util/providers.num	2023-05-31 14:33:16.926112941 +0200
@@ -1 +1,2 @@
 OSSL_provider_init                     1	*	EXIST::FUNCTION:
+redhat_ossl_query_fipsindicator        1	*	EXIST::FUNCTION:ONLY_PROVIDERS/FIPS