1 /*
2  * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #ifdef FIPS_MODULE
11 
12 # include <openssl/core.h> /* OSSL_CALLBACK, OSSL_LIB_CTX */
13 # include <openssl/indicator.h>
14 # include "crypto/types.h"
15 # include <openssl/ec.h>
16 # include "fipscommon.h"
17 
18 /*
19  * There may be multiple settables associated with an algorithm that allow
20  * overriding the default status.
21  * We associate an id with each of these.
22  */
23 # define OSSL_FIPS_IND_SETTABLE0 0
24 # define OSSL_FIPS_IND_SETTABLE1 1
25 # define OSSL_FIPS_IND_SETTABLE2 2
26 # define OSSL_FIPS_IND_SETTABLE3 3
27 # define OSSL_FIPS_IND_SETTABLE4 4
28 # define OSSL_FIPS_IND_SETTABLE5 5
29 # define OSSL_FIPS_IND_SETTABLE6 6
30 # define OSSL_FIPS_IND_SETTABLE7 7
31 # define OSSL_FIPS_IND_SETTABLE_MAX (1 + OSSL_FIPS_IND_SETTABLE7)
32 
33 /* Each settable is in one of 3 states */
34 #define OSSL_FIPS_IND_STATE_UNKNOWN    -1  /* Initial unknown state */
35 #define OSSL_FIPS_IND_STATE_STRICT      1  /* Strict enforcement */
36 #define OSSL_FIPS_IND_STATE_TOLERANT    0  /* Relaxation of rules */
37 
38 /*
39  * For each algorithm context there may be multiple checks that determine if
40  * the algorithm is approved or not. These checks may be in different stages.
41  * To keep it simple it is assumed that the algorithm is initially approved,
42  * and may be unapproved when each check happens. Once unapproved the operation
43  * will remain unapproved (otherwise we need to maintain state for each check).
44  * The approved state should only be queried after the operation has completed
45  * e.g. A digest final, or a KDF derive.
46  *
47  * If a FIPS approved check fails then we must decide what to do in this case.
48  * In strict mode we would just return an error.
49  * To override strict mode we either need to have a settable variable or have a
50  * fips config flag that overrides strict mode.
51  * If there are multiple checks, each one could possible have a different
52  * configurable item. Each configurable item can be overridden by a different
53  * settable.
54  */
55 typedef struct ossl_fips_ind_st {
56     unsigned char approved;
57     signed char settable[OSSL_FIPS_IND_SETTABLE_MAX]; /* See OSSL_FIPS_IND_STATE */
58 } OSSL_FIPS_IND;
59 
60 typedef int (OSSL_FIPS_IND_CHECK_CB)(OSSL_LIB_CTX *libctx);
61 
62 int ossl_FIPS_IND_callback(OSSL_LIB_CTX *libctx, const char *type,
63                            const char *desc);
64 
65 void ossl_FIPS_IND_init(OSSL_FIPS_IND *ind);
66 void ossl_FIPS_IND_set_approved(OSSL_FIPS_IND *ind);
67 void ossl_FIPS_IND_set_settable(OSSL_FIPS_IND *ind, int id, int enable);
68 int ossl_FIPS_IND_get_settable(const OSSL_FIPS_IND *ind, int id);
69 int ossl_FIPS_IND_on_unapproved(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
70                                 const char *algname, const char *opname,
71                                 OSSL_FIPS_IND_CHECK_CB *config_check_fn);
72 int ossl_FIPS_IND_set_ctx_param(OSSL_FIPS_IND *ind, int id, const OSSL_PARAM *p);
73 int ossl_FIPS_IND_set_ctx_param_locate(OSSL_FIPS_IND *ind, int id,
74                                        const OSSL_PARAM params[],
75                                        const char *name);
76 int ossl_FIPS_IND_get_ctx_param(const OSSL_FIPS_IND *ind,
77                                 OSSL_PARAM *p);
78 int ossl_FIPS_IND_get_ctx_param_locate(const OSSL_FIPS_IND *ind,
79                                        OSSL_PARAM params[]);
80 void ossl_FIPS_IND_copy(OSSL_FIPS_IND *dst, const OSSL_FIPS_IND *src);
81 
82 /* Place this in the algorithm ctx structure */
83 # define OSSL_FIPS_IND_DECLARE OSSL_FIPS_IND indicator;
84 /* Call this to initialize the indicator */
85 # define OSSL_FIPS_IND_INIT(ctx) ossl_FIPS_IND_init(&ctx->indicator);
86 /*
87  * Use the copy if an algorithm has a dup function that does not copy the src to
88  * the dst.
89  */
90 # define OSSL_FIPS_IND_COPY(dst, src) ossl_FIPS_IND_copy(&dst->indicator, &src->indicator);
91 
92 /*
93  * Required for reset - since once something becomes unapproved it will remain
94  * unapproved unless this is used. This should be used in the init before
95  * params are set into the ctx & before any FIPS checks are done.
96  */
97 # define OSSL_FIPS_IND_SET_APPROVED(ctx) ossl_FIPS_IND_set_approved(&ctx->indicator);
98 /*
99  * This should be called if a FIPS check fails, to indicate the operation is not approved
100  * If there is more than 1 strict check flag per algorithm ctx, the id represents
101  * the index.
102  */
103 # define OSSL_FIPS_IND_ON_UNAPPROVED(ctx, id, libctx, algname, opname, config_check_fn) \
104     ossl_FIPS_IND_on_unapproved(&ctx->indicator, id, libctx, algname, opname, config_check_fn)
105 
106 # define OSSL_FIPS_IND_SETTABLE_CTX_PARAM(name) \
107     OSSL_PARAM_int(name, NULL),
108 
109 /*
110  * The id here must match the one used by OSSL_FIPS_IND_ON_UNAPPROVED
111  * The name must match the param used by OSSL_FIPS_IND_SETTABLE_CTX_PARAM
112  */
113 # define OSSL_FIPS_IND_SET_CTX_PARAM(ctx, id, params, name) \
114     ossl_FIPS_IND_set_ctx_param_locate(&((ctx)->indicator), id, params, name)
115 
116 # define OSSL_FIPS_IND_SET_CTX_FROM_PARAM(ctx, id, p) \
117     ossl_FIPS_IND_set_ctx_param(&((ctx)->indicator), id, p)
118 
119 # define OSSL_FIPS_IND_GETTABLE_CTX_PARAM() \
120     OSSL_PARAM_int(OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR, NULL),
121 
122 # define OSSL_FIPS_IND_GET_CTX_PARAM(ctx, prms) \
123     ossl_FIPS_IND_get_ctx_param_locate(&((ctx)->indicator), prms)
124 
125 # define OSSL_FIPS_IND_GET_CTX_FROM_PARAM(ctx, p) \
126     ossl_FIPS_IND_get_ctx_param(&((ctx)->indicator), p)
127 
128 # define OSSL_FIPS_IND_GET(ctx) (&((ctx)->indicator))
129 
130 # define OSSL_FIPS_IND_GET_PARAM(ctx, p, settable, id, name)                   \
131     *settable = ossl_FIPS_IND_get_settable(&((ctx)->indicator), id);           \
132     if (*settable != OSSL_FIPS_IND_STATE_UNKNOWN)                              \
133         *p = OSSL_PARAM_construct_int(name, settable);
134 
135 int ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
136                                 const RSA *rsa, const char *desc, int protect);
137 # ifndef OPENSSL_NO_EC
138 int ossl_fips_ind_ec_key_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
139                                const EC_GROUP *group, const char *desc,
140                                int protect);
141 # endif
142 int ossl_fips_ind_digest_exch_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
143                                     const EVP_MD *md, const char *desc);
144 int ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND *ind, int id,
145                                     OSSL_LIB_CTX *libctx,
146                                     int nid, int sha1_allowed,
147                                     const char *desc,
148                                     OSSL_FIPS_IND_CHECK_CB *config_check_f);
149 
150 #else
151 # define OSSL_FIPS_IND_DECLARE
152 # define OSSL_FIPS_IND_INIT(ctx)
153 # define OSSL_FIPS_IND_SET_APPROVED(ctx)
154 # define OSSL_FIPS_IND_ON_UNAPPROVED(ctx, id, libctx, algname, opname, configopt_fn)
155 # define OSSL_FIPS_IND_SETTABLE_CTX_PARAM(name)
156 # define OSSL_FIPS_IND_SET_CTX_PARAM(ctx, id, params, name) 1
157 # define OSSL_FIPS_IND_SET_CTX_FROM_PARAM(ctx, id, p) 1
158 # define OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
159 # define OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params) 1
160 # define OSSL_FIPS_IND_GET_CTX_FROM_PARAM(ctx, params) 1
161 # define OSSL_FIPS_IND_COPY(dst, src)
162 
163 #endif
164