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