xref: /openssl/providers/fips/fipsindicator.c (revision f6a296c3)
1 /*
2  * Copyright 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 #include <openssl/indicator.h>
11 #include <openssl/params.h>
12 #include <openssl/core_names.h>
13 #include "internal/common.h" /* for ossl_assert() */
14 #include "fips/fipsindicator.h"
15 
ossl_FIPS_IND_init(OSSL_FIPS_IND * ind)16 void ossl_FIPS_IND_init(OSSL_FIPS_IND *ind)
17 {
18     int i;
19 
20     ossl_FIPS_IND_set_approved(ind); /* Assume we are approved by default */
21     for (i = 0; i < OSSL_FIPS_IND_SETTABLE_MAX; i++)
22         ind->settable[i] = OSSL_FIPS_IND_STATE_UNKNOWN;
23 }
24 
ossl_FIPS_IND_set_approved(OSSL_FIPS_IND * ind)25 void ossl_FIPS_IND_set_approved(OSSL_FIPS_IND *ind)
26 {
27     ind->approved = 1;
28 }
29 
ossl_FIPS_IND_copy(OSSL_FIPS_IND * dst,const OSSL_FIPS_IND * src)30 void ossl_FIPS_IND_copy(OSSL_FIPS_IND *dst, const OSSL_FIPS_IND *src)
31 {
32     *dst = *src;
33 }
34 
ossl_FIPS_IND_set_settable(OSSL_FIPS_IND * ind,int id,int state)35 void ossl_FIPS_IND_set_settable(OSSL_FIPS_IND *ind, int id, int state)
36 {
37     if (!ossl_assert(id < OSSL_FIPS_IND_SETTABLE_MAX))
38         return;
39     if (!ossl_assert(state == OSSL_FIPS_IND_STATE_STRICT
40                      || state == OSSL_FIPS_IND_STATE_TOLERANT))
41         return;
42     ind->settable[id] = state;
43 }
44 
ossl_FIPS_IND_get_settable(const OSSL_FIPS_IND * ind,int id)45 int ossl_FIPS_IND_get_settable(const OSSL_FIPS_IND *ind, int id)
46 {
47     if (!ossl_assert(id < OSSL_FIPS_IND_SETTABLE_MAX))
48         return OSSL_FIPS_IND_STATE_UNKNOWN;
49     return ind->settable[id];
50 }
51 
52 /*
53  * This should only be called when a strict FIPS algorithm check fails.
54  * It assumes that we are in strict mode by default.
55  * If the logic here is not sufficient for all cases, then additional
56  * ossl_FIPS_IND_on_unapproved() functions may be required.
57  */
ossl_FIPS_IND_on_unapproved(OSSL_FIPS_IND * ind,int id,OSSL_LIB_CTX * libctx,const char * algname,const char * opname,OSSL_FIPS_IND_CHECK_CB * config_check_fn)58 int ossl_FIPS_IND_on_unapproved(OSSL_FIPS_IND *ind, int id,
59                                 OSSL_LIB_CTX *libctx,
60                                 const char *algname, const char *opname,
61                                 OSSL_FIPS_IND_CHECK_CB *config_check_fn)
62 {
63     /* Set to unapproved. Once unapproved mode is set this will not be reset */
64     ind->approved = 0;
65 
66     /*
67      * We only trigger the indicator callback if the ctx variable is cleared OR
68      * the configurable item is cleared. If the values are unknown they are
69      * assumed to be strict.
70      */
71     if (ossl_FIPS_IND_get_settable(ind, id) == OSSL_FIPS_IND_STATE_TOLERANT
72         || (config_check_fn != NULL
73             && config_check_fn(libctx) == OSSL_FIPS_IND_STATE_TOLERANT)) {
74         return ossl_FIPS_IND_callback(libctx, algname, opname);
75     }
76     /* Strict mode gets here: This returns an error */
77     return 0;
78 }
79 
ossl_FIPS_IND_set_ctx_param(OSSL_FIPS_IND * ind,int id,const OSSL_PARAM params[],const char * name)80 int ossl_FIPS_IND_set_ctx_param(OSSL_FIPS_IND *ind, int id,
81                                 const OSSL_PARAM params[], const char *name)
82 {
83     int in = 0;
84     const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, name);
85 
86     if (p != NULL) {
87         if (!OSSL_PARAM_get_int(p, &in))
88             return 0;
89         ossl_FIPS_IND_set_settable(ind, id, in);
90     }
91     return 1;
92 }
93 
ossl_FIPS_IND_get_ctx_param(const OSSL_FIPS_IND * ind,OSSL_PARAM params[])94 int ossl_FIPS_IND_get_ctx_param(const OSSL_FIPS_IND *ind, OSSL_PARAM params[])
95 {
96     OSSL_PARAM *p = OSSL_PARAM_locate(params, OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR);
97 
98     return p == NULL || OSSL_PARAM_set_int(p, ind->approved);
99 }
100 
101 /*
102  * Can be used during application testing to log that an indicator was
103  * triggered. The callback will return 1 if the application wants an error
104  * to occur based on the indicator type and description.
105  */
ossl_FIPS_IND_callback(OSSL_LIB_CTX * libctx,const char * type,const char * desc)106 int ossl_FIPS_IND_callback(OSSL_LIB_CTX *libctx, const char *type,
107                            const char *desc)
108 {
109     OSSL_INDICATOR_CALLBACK *cb = NULL;
110 
111     OSSL_INDICATOR_get_callback(libctx, &cb);
112     if (cb == NULL)
113         return 1;
114 
115     return cb(type, desc, NULL);
116 }
117