1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <openssl/self_test.h>
11e1051a39Sopenharmony_ci#include <openssl/core_names.h>
12e1051a39Sopenharmony_ci#include <openssl/params.h>
13e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
14e1051a39Sopenharmony_ci
15e1051a39Sopenharmony_citypedef struct self_test_cb_st
16e1051a39Sopenharmony_ci{
17e1051a39Sopenharmony_ci    OSSL_CALLBACK *cb;
18e1051a39Sopenharmony_ci    void *cbarg;
19e1051a39Sopenharmony_ci} SELF_TEST_CB;
20e1051a39Sopenharmony_ci
21e1051a39Sopenharmony_cistruct ossl_self_test_st
22e1051a39Sopenharmony_ci{
23e1051a39Sopenharmony_ci    /* local state variables */
24e1051a39Sopenharmony_ci    const char *phase;
25e1051a39Sopenharmony_ci    const char *type;
26e1051a39Sopenharmony_ci    const char *desc;
27e1051a39Sopenharmony_ci    OSSL_CALLBACK *cb;
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_ci    /* callback related variables used to pass the state back to the user */
30e1051a39Sopenharmony_ci    OSSL_PARAM params[4];
31e1051a39Sopenharmony_ci    void *cb_arg;
32e1051a39Sopenharmony_ci};
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
35e1051a39Sopenharmony_cistatic void *self_test_set_callback_new(OSSL_LIB_CTX *ctx)
36e1051a39Sopenharmony_ci{
37e1051a39Sopenharmony_ci    SELF_TEST_CB *stcb;
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_ci    stcb = OPENSSL_zalloc(sizeof(*stcb));
40e1051a39Sopenharmony_ci    return stcb;
41e1051a39Sopenharmony_ci}
42e1051a39Sopenharmony_ci
43e1051a39Sopenharmony_cistatic void self_test_set_callback_free(void *stcb)
44e1051a39Sopenharmony_ci{
45e1051a39Sopenharmony_ci    OPENSSL_free(stcb);
46e1051a39Sopenharmony_ci}
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_cistatic const OSSL_LIB_CTX_METHOD self_test_set_callback_method = {
49e1051a39Sopenharmony_ci    OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
50e1051a39Sopenharmony_ci    self_test_set_callback_new,
51e1051a39Sopenharmony_ci    self_test_set_callback_free,
52e1051a39Sopenharmony_ci};
53e1051a39Sopenharmony_ci
54e1051a39Sopenharmony_cistatic SELF_TEST_CB *get_self_test_callback(OSSL_LIB_CTX *libctx)
55e1051a39Sopenharmony_ci{
56e1051a39Sopenharmony_ci    return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_SELF_TEST_CB_INDEX,
57e1051a39Sopenharmony_ci                                 &self_test_set_callback_method);
58e1051a39Sopenharmony_ci}
59e1051a39Sopenharmony_ci
60e1051a39Sopenharmony_civoid OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb,
61e1051a39Sopenharmony_ci                                 void *cbarg)
62e1051a39Sopenharmony_ci{
63e1051a39Sopenharmony_ci    SELF_TEST_CB *stcb = get_self_test_callback(libctx);
64e1051a39Sopenharmony_ci
65e1051a39Sopenharmony_ci    if (stcb != NULL) {
66e1051a39Sopenharmony_ci        stcb->cb = cb;
67e1051a39Sopenharmony_ci        stcb->cbarg = cbarg;
68e1051a39Sopenharmony_ci    }
69e1051a39Sopenharmony_ci}
70e1051a39Sopenharmony_ci
71e1051a39Sopenharmony_civoid OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb,
72e1051a39Sopenharmony_ci                                 void **cbarg)
73e1051a39Sopenharmony_ci{
74e1051a39Sopenharmony_ci    SELF_TEST_CB *stcb = get_self_test_callback(libctx);
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ci    if (cb != NULL)
77e1051a39Sopenharmony_ci        *cb = (stcb != NULL ? stcb->cb : NULL);
78e1051a39Sopenharmony_ci    if (cbarg != NULL)
79e1051a39Sopenharmony_ci        *cbarg = (stcb != NULL ? stcb->cbarg : NULL);
80e1051a39Sopenharmony_ci}
81e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_cistatic void self_test_setparams(OSSL_SELF_TEST *st)
84e1051a39Sopenharmony_ci{
85e1051a39Sopenharmony_ci    size_t n = 0;
86e1051a39Sopenharmony_ci
87e1051a39Sopenharmony_ci    if (st->cb != NULL) {
88e1051a39Sopenharmony_ci        st->params[n++] =
89e1051a39Sopenharmony_ci            OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_PHASE,
90e1051a39Sopenharmony_ci                                             (char *)st->phase, 0);
91e1051a39Sopenharmony_ci        st->params[n++] =
92e1051a39Sopenharmony_ci            OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_TYPE,
93e1051a39Sopenharmony_ci                                             (char *)st->type, 0);
94e1051a39Sopenharmony_ci        st->params[n++] =
95e1051a39Sopenharmony_ci            OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_DESC,
96e1051a39Sopenharmony_ci                                             (char *)st->desc, 0);
97e1051a39Sopenharmony_ci    }
98e1051a39Sopenharmony_ci    st->params[n++] = OSSL_PARAM_construct_end();
99e1051a39Sopenharmony_ci}
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ciOSSL_SELF_TEST *OSSL_SELF_TEST_new(OSSL_CALLBACK *cb, void *cbarg)
102e1051a39Sopenharmony_ci{
103e1051a39Sopenharmony_ci    OSSL_SELF_TEST *ret = OPENSSL_zalloc(sizeof(*ret));
104e1051a39Sopenharmony_ci
105e1051a39Sopenharmony_ci    if (ret == NULL)
106e1051a39Sopenharmony_ci        return NULL;
107e1051a39Sopenharmony_ci
108e1051a39Sopenharmony_ci    ret->cb = cb;
109e1051a39Sopenharmony_ci    ret->cb_arg = cbarg;
110e1051a39Sopenharmony_ci    ret->phase = "";
111e1051a39Sopenharmony_ci    ret->type = "";
112e1051a39Sopenharmony_ci    ret->desc = "";
113e1051a39Sopenharmony_ci    self_test_setparams(ret);
114e1051a39Sopenharmony_ci    return ret;
115e1051a39Sopenharmony_ci}
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_civoid OSSL_SELF_TEST_free(OSSL_SELF_TEST *st)
118e1051a39Sopenharmony_ci{
119e1051a39Sopenharmony_ci    OPENSSL_free(st);
120e1051a39Sopenharmony_ci}
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_ci/* Can be used during application testing to log that a test has started. */
123e1051a39Sopenharmony_civoid OSSL_SELF_TEST_onbegin(OSSL_SELF_TEST *st, const char *type,
124e1051a39Sopenharmony_ci                            const char *desc)
125e1051a39Sopenharmony_ci{
126e1051a39Sopenharmony_ci    if (st != NULL && st->cb != NULL) {
127e1051a39Sopenharmony_ci        st->phase = OSSL_SELF_TEST_PHASE_START;
128e1051a39Sopenharmony_ci        st->type = type;
129e1051a39Sopenharmony_ci        st->desc = desc;
130e1051a39Sopenharmony_ci        self_test_setparams(st);
131e1051a39Sopenharmony_ci        (void)st->cb(st->params, st->cb_arg);
132e1051a39Sopenharmony_ci    }
133e1051a39Sopenharmony_ci}
134e1051a39Sopenharmony_ci
135e1051a39Sopenharmony_ci/*
136e1051a39Sopenharmony_ci * Can be used during application testing to log that a test has either
137e1051a39Sopenharmony_ci * passed or failed.
138e1051a39Sopenharmony_ci */
139e1051a39Sopenharmony_civoid OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret)
140e1051a39Sopenharmony_ci{
141e1051a39Sopenharmony_ci    if (st != NULL && st->cb != NULL) {
142e1051a39Sopenharmony_ci        st->phase =
143e1051a39Sopenharmony_ci            (ret == 1 ? OSSL_SELF_TEST_PHASE_PASS : OSSL_SELF_TEST_PHASE_FAIL);
144e1051a39Sopenharmony_ci        self_test_setparams(st);
145e1051a39Sopenharmony_ci        (void)st->cb(st->params, st->cb_arg);
146e1051a39Sopenharmony_ci
147e1051a39Sopenharmony_ci        st->phase = OSSL_SELF_TEST_PHASE_NONE;
148e1051a39Sopenharmony_ci        st->type = OSSL_SELF_TEST_TYPE_NONE;
149e1051a39Sopenharmony_ci        st->desc = OSSL_SELF_TEST_DESC_NONE;
150e1051a39Sopenharmony_ci    }
151e1051a39Sopenharmony_ci}
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ci/*
154e1051a39Sopenharmony_ci * Used for failure testing.
155e1051a39Sopenharmony_ci *
156e1051a39Sopenharmony_ci * Call the applications SELF_TEST_cb() if it exists.
157e1051a39Sopenharmony_ci * If the application callback decides to return 0 then the first byte of 'bytes'
158e1051a39Sopenharmony_ci * is modified (corrupted). This is used to modify output signatures or
159e1051a39Sopenharmony_ci * ciphertext before they are verified or decrypted.
160e1051a39Sopenharmony_ci */
161e1051a39Sopenharmony_ciint OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes)
162e1051a39Sopenharmony_ci{
163e1051a39Sopenharmony_ci    if (st != NULL && st->cb != NULL) {
164e1051a39Sopenharmony_ci        st->phase = OSSL_SELF_TEST_PHASE_CORRUPT;
165e1051a39Sopenharmony_ci        self_test_setparams(st);
166e1051a39Sopenharmony_ci        if (!st->cb(st->params, st->cb_arg)) {
167e1051a39Sopenharmony_ci            bytes[0] ^= 1;
168e1051a39Sopenharmony_ci            return 1;
169e1051a39Sopenharmony_ci        }
170e1051a39Sopenharmony_ci    }
171e1051a39Sopenharmony_ci    return 0;
172e1051a39Sopenharmony_ci}
173