1/* $NetBSD: openssl_link.c,v 1.1 2024/02/18 20:57:32 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 AND ISC 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16/* 17 * Copyright (C) Network Associates, Inc. 18 * 19 * Permission to use, copy, modify, and/or distribute this software for any 20 * purpose with or without fee is hereby granted, provided that the above 21 * copyright notice and this permission notice appear in all copies. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 24 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 26 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 28 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 29 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 30 */ 31 32#include <isc/mem.h> 33#include <isc/mutex.h> 34#include <isc/mutexblock.h> 35#include <isc/platform.h> 36#include <isc/string.h> 37#include <isc/thread.h> 38#include <isc/util.h> 39 40#include <dns/log.h> 41 42#include <dst/result.h> 43 44#include "dst_internal.h" 45#include "dst_openssl.h" 46 47#if !defined(OPENSSL_NO_ENGINE) 48#include <openssl/engine.h> 49#endif /* if !defined(OPENSSL_NO_ENGINE) */ 50 51#if !defined(OPENSSL_NO_ENGINE) 52static ENGINE *e = NULL; 53#endif /* if !defined(OPENSSL_NO_ENGINE) */ 54 55static void 56enable_fips_mode(void) { 57#ifdef HAVE_FIPS_MODE 58 if (FIPS_mode() != 0) { 59 /* 60 * FIPS mode is already enabled. 61 */ 62 return; 63 } 64 65 if (FIPS_mode_set(1) == 0) { 66 dst__openssl_toresult2("FIPS_mode_set", DST_R_OPENSSLFAILURE); 67 exit(1); 68 } 69#endif /* HAVE_FIPS_MODE */ 70} 71 72isc_result_t 73dst__openssl_init(const char *engine) { 74 isc_result_t result = ISC_R_SUCCESS; 75 76 enable_fips_mode(); 77 78#if !defined(OPENSSL_NO_ENGINE) 79 if (engine != NULL && *engine == '\0') { 80 engine = NULL; 81 } 82 83 if (engine != NULL) { 84 e = ENGINE_by_id(engine); 85 if (e == NULL) { 86 result = DST_R_NOENGINE; 87 goto cleanup_rm; 88 } 89 /* This will init the engine. */ 90 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { 91 result = DST_R_NOENGINE; 92 goto cleanup_rm; 93 } 94 } 95 96 return (ISC_R_SUCCESS); 97cleanup_rm: 98 if (e != NULL) { 99 ENGINE_free(e); 100 } 101 e = NULL; 102#else 103 UNUSED(engine); 104#endif /* if !defined(OPENSSL_NO_ENGINE) */ 105 return (result); 106} 107 108void 109dst__openssl_destroy(void) { 110#if !defined(OPENSSL_NO_ENGINE) 111 if (e != NULL) { 112 ENGINE_free(e); 113 } 114 e = NULL; 115#endif /* if !defined(OPENSSL_NO_ENGINE) */ 116} 117 118static isc_result_t 119toresult(isc_result_t fallback) { 120 isc_result_t result = fallback; 121 unsigned long err = ERR_peek_error(); 122#if defined(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED) 123 int lib = ERR_GET_LIB(err); 124#endif /* if defined(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED) */ 125 int reason = ERR_GET_REASON(err); 126 127 switch (reason) { 128 /* 129 * ERR_* errors are globally unique; others 130 * are unique per sublibrary 131 */ 132 case ERR_R_MALLOC_FAILURE: 133 result = ISC_R_NOMEMORY; 134 break; 135 default: 136#if defined(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED) 137 if (lib == ERR_R_ECDSA_LIB && 138 reason == ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED) 139 { 140 result = ISC_R_NOENTROPY; 141 break; 142 } 143#endif /* if defined(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED) */ 144 break; 145 } 146 147 return (result); 148} 149 150isc_result_t 151dst__openssl_toresult(isc_result_t fallback) { 152 isc_result_t result; 153 154 result = toresult(fallback); 155 156 ERR_clear_error(); 157 return (result); 158} 159 160isc_result_t 161dst__openssl_toresult2(const char *funcname, isc_result_t fallback) { 162 return (dst__openssl_toresult3(DNS_LOGCATEGORY_GENERAL, funcname, 163 fallback)); 164} 165 166isc_result_t 167dst__openssl_toresult3(isc_logcategory_t *category, const char *funcname, 168 isc_result_t fallback) { 169 isc_result_t result; 170 unsigned long err; 171 const char *file, *data; 172 int line, flags; 173 char buf[256]; 174 175 result = toresult(fallback); 176 177 isc_log_write(dns_lctx, category, DNS_LOGMODULE_CRYPTO, ISC_LOG_WARNING, 178 "%s failed (%s)", funcname, isc_result_totext(result)); 179 180 if (result == ISC_R_NOMEMORY) { 181 goto done; 182 } 183 184 for (;;) { 185 err = ERR_get_error_line_data(&file, &line, &data, &flags); 186 if (err == 0U) { 187 goto done; 188 } 189 ERR_error_string_n(err, buf, sizeof(buf)); 190 isc_log_write(dns_lctx, category, DNS_LOGMODULE_CRYPTO, 191 ISC_LOG_INFO, "%s:%s:%d:%s", buf, file, line, 192 ((flags & ERR_TXT_STRING) != 0) ? data : ""); 193 } 194 195done: 196 ERR_clear_error(); 197 return (result); 198} 199 200#if !defined(OPENSSL_NO_ENGINE) 201ENGINE * 202dst__openssl_getengine(const char *engine) { 203 if (engine == NULL) { 204 return (NULL); 205 } 206 if (e == NULL) { 207 return (NULL); 208 } 209 if (strcmp(engine, ENGINE_get_id(e)) == 0) { 210 return (e); 211 } 212 return (NULL); 213} 214#endif /* if !defined(OPENSSL_NO_ENGINE) */ 215 216/*! \file */ 217