1*bcda20f6Schristos /* $NetBSD: md.c,v 1.7 2025/01/26 16:25:37 christos Exp $ */ 266331fe0Schristos 366331fe0Schristos /* 466331fe0Schristos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 566331fe0Schristos * 68596601aSchristos * SPDX-License-Identifier: MPL-2.0 78596601aSchristos * 866331fe0Schristos * This Source Code Form is subject to the terms of the Mozilla Public 966331fe0Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this 10fce770bdSchristos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 1166331fe0Schristos * 1266331fe0Schristos * See the COPYRIGHT file distributed with this work for additional 1366331fe0Schristos * information regarding copyright ownership. 1466331fe0Schristos */ 1566331fe0Schristos 1666331fe0Schristos #include <stdio.h> 1766331fe0Schristos 185606745fSchristos #include <openssl/err.h> 195606745fSchristos #include <openssl/evp.h> 205606745fSchristos #include <openssl/opensslv.h> 215606745fSchristos 2266331fe0Schristos #include <isc/md.h> 2366331fe0Schristos #include <isc/util.h> 2466331fe0Schristos 2566331fe0Schristos #include "openssl_shim.h" 2666331fe0Schristos 2766331fe0Schristos isc_md_t * 2866331fe0Schristos isc_md_new(void) { 2966331fe0Schristos isc_md_t *md = EVP_MD_CTX_new(); 3066331fe0Schristos RUNTIME_CHECK(md != NULL); 31*bcda20f6Schristos return md; 3266331fe0Schristos } 3366331fe0Schristos 3466331fe0Schristos void 3566331fe0Schristos isc_md_free(isc_md_t *md) { 36bb5aa156Schristos if (md == NULL) { 3766331fe0Schristos return; 3866331fe0Schristos } 3966331fe0Schristos 4066331fe0Schristos EVP_MD_CTX_free(md); 4166331fe0Schristos } 4266331fe0Schristos 4366331fe0Schristos isc_result_t 445606745fSchristos isc_md_init(isc_md_t *md, const isc_md_type_t *md_type) { 4566331fe0Schristos REQUIRE(md != NULL); 4666331fe0Schristos 4766331fe0Schristos if (md_type == NULL) { 48*bcda20f6Schristos return ISC_R_NOTIMPLEMENTED; 4966331fe0Schristos } 5066331fe0Schristos 5166331fe0Schristos if (EVP_DigestInit_ex(md, md_type, NULL) != 1) { 52bb5aa156Schristos ERR_clear_error(); 53*bcda20f6Schristos return ISC_R_CRYPTOFAILURE; 5466331fe0Schristos } 5566331fe0Schristos 56*bcda20f6Schristos return ISC_R_SUCCESS; 5766331fe0Schristos } 5866331fe0Schristos 5966331fe0Schristos isc_result_t 6066331fe0Schristos isc_md_reset(isc_md_t *md) { 6166331fe0Schristos REQUIRE(md != NULL); 6266331fe0Schristos 6366331fe0Schristos if (EVP_MD_CTX_reset(md) != 1) { 64bb5aa156Schristos ERR_clear_error(); 65*bcda20f6Schristos return ISC_R_CRYPTOFAILURE; 6666331fe0Schristos } 6766331fe0Schristos 68*bcda20f6Schristos return ISC_R_SUCCESS; 6966331fe0Schristos } 7066331fe0Schristos 7166331fe0Schristos isc_result_t 7266331fe0Schristos isc_md_update(isc_md_t *md, const unsigned char *buf, const size_t len) { 7366331fe0Schristos REQUIRE(md != NULL); 7466331fe0Schristos 75bb5aa156Schristos if (buf == NULL || len == 0) { 76*bcda20f6Schristos return ISC_R_SUCCESS; 7766331fe0Schristos } 7866331fe0Schristos 7966331fe0Schristos if (EVP_DigestUpdate(md, buf, len) != 1) { 80bb5aa156Schristos ERR_clear_error(); 81*bcda20f6Schristos return ISC_R_CRYPTOFAILURE; 8266331fe0Schristos } 8366331fe0Schristos 84*bcda20f6Schristos return ISC_R_SUCCESS; 8566331fe0Schristos } 8666331fe0Schristos 8766331fe0Schristos isc_result_t 8866331fe0Schristos isc_md_final(isc_md_t *md, unsigned char *digest, unsigned int *digestlen) { 8966331fe0Schristos REQUIRE(md != NULL); 9066331fe0Schristos REQUIRE(digest != NULL); 9166331fe0Schristos 9266331fe0Schristos if (EVP_DigestFinal_ex(md, digest, digestlen) != 1) { 93bb5aa156Schristos ERR_clear_error(); 94*bcda20f6Schristos return ISC_R_CRYPTOFAILURE; 9566331fe0Schristos } 9666331fe0Schristos 97*bcda20f6Schristos return ISC_R_SUCCESS; 9866331fe0Schristos } 9966331fe0Schristos 1005606745fSchristos const isc_md_type_t * 10166331fe0Schristos isc_md_get_md_type(isc_md_t *md) { 10266331fe0Schristos REQUIRE(md != NULL); 10366331fe0Schristos 104*bcda20f6Schristos return EVP_MD_CTX_get0_md(md); 10566331fe0Schristos } 10666331fe0Schristos 10766331fe0Schristos size_t 10866331fe0Schristos isc_md_get_size(isc_md_t *md) { 10966331fe0Schristos REQUIRE(md != NULL); 11066331fe0Schristos 111*bcda20f6Schristos return EVP_MD_CTX_size(md); 11266331fe0Schristos } 11366331fe0Schristos 11466331fe0Schristos size_t 11566331fe0Schristos isc_md_get_block_size(isc_md_t *md) { 11666331fe0Schristos REQUIRE(md != NULL); 11766331fe0Schristos 118*bcda20f6Schristos return EVP_MD_CTX_block_size(md); 11966331fe0Schristos } 12066331fe0Schristos 12166331fe0Schristos size_t 1225606745fSchristos isc_md_type_get_size(const isc_md_type_t *md_type) { 1235606745fSchristos STATIC_ASSERT(ISC_MAX_MD_SIZE >= EVP_MAX_MD_SIZE, 1245606745fSchristos "Change ISC_MAX_MD_SIZE to be greater than or equal to " 1255606745fSchristos "EVP_MAX_MD_SIZE"); 12666331fe0Schristos if (md_type != NULL) { 127*bcda20f6Schristos return (size_t)EVP_MD_size(md_type); 12866331fe0Schristos } 12966331fe0Schristos 130*bcda20f6Schristos return ISC_MAX_MD_SIZE; 13166331fe0Schristos } 13266331fe0Schristos 13366331fe0Schristos size_t 1345606745fSchristos isc_md_type_get_block_size(const isc_md_type_t *md_type) { 1355606745fSchristos STATIC_ASSERT(ISC_MAX_MD_SIZE >= EVP_MAX_MD_SIZE, 1365606745fSchristos "Change ISC_MAX_MD_SIZE to be greater than or equal to " 1375606745fSchristos "EVP_MAX_MD_SIZE"); 13866331fe0Schristos if (md_type != NULL) { 139*bcda20f6Schristos return (size_t)EVP_MD_block_size(md_type); 14066331fe0Schristos } 14166331fe0Schristos 142*bcda20f6Schristos return ISC_MAX_MD_SIZE; 14366331fe0Schristos } 14466331fe0Schristos 14566331fe0Schristos isc_result_t 1465606745fSchristos isc_md(const isc_md_type_t *md_type, const unsigned char *buf, const size_t len, 1475606745fSchristos unsigned char *digest, unsigned int *digestlen) { 14866331fe0Schristos isc_md_t *md; 14966331fe0Schristos isc_result_t res; 15066331fe0Schristos 15166331fe0Schristos md = isc_md_new(); 15266331fe0Schristos 15366331fe0Schristos res = isc_md_init(md, md_type); 15466331fe0Schristos if (res != ISC_R_SUCCESS) { 15566331fe0Schristos goto end; 15666331fe0Schristos } 15766331fe0Schristos 15866331fe0Schristos res = isc_md_update(md, buf, len); 15966331fe0Schristos if (res != ISC_R_SUCCESS) { 16066331fe0Schristos goto end; 16166331fe0Schristos } 16266331fe0Schristos 16366331fe0Schristos res = isc_md_final(md, digest, digestlen); 16466331fe0Schristos if (res != ISC_R_SUCCESS) { 16566331fe0Schristos goto end; 16666331fe0Schristos } 16766331fe0Schristos end: 16866331fe0Schristos isc_md_free(md); 16966331fe0Schristos 170*bcda20f6Schristos return res; 17166331fe0Schristos } 1725606745fSchristos 173*bcda20f6Schristos #ifndef UNIT_TESTING 174*bcda20f6Schristos const isc_md_type_t *isc__md_md5 = NULL; 175*bcda20f6Schristos const isc_md_type_t *isc__md_sha1 = NULL; 176*bcda20f6Schristos const isc_md_type_t *isc__md_sha224 = NULL; 177*bcda20f6Schristos const isc_md_type_t *isc__md_sha256 = NULL; 178*bcda20f6Schristos const isc_md_type_t *isc__md_sha384 = NULL; 179*bcda20f6Schristos const isc_md_type_t *isc__md_sha512 = NULL; 180*bcda20f6Schristos 181*bcda20f6Schristos #if OPENSSL_VERSION_NUMBER >= 0x30000000L 182*bcda20f6Schristos #define md_register_algorithm(alg, algname) \ 183*bcda20f6Schristos { \ 184*bcda20f6Schristos REQUIRE(isc__md_##alg == NULL); \ 185*bcda20f6Schristos isc__md_##alg = EVP_MD_fetch(NULL, algname, NULL); \ 186*bcda20f6Schristos if (isc__md_##alg == NULL) { \ 187bb5aa156Schristos ERR_clear_error(); \ 188bb5aa156Schristos } \ 189bb5aa156Schristos } 1905606745fSchristos 191*bcda20f6Schristos #define md_unregister_algorithm(alg) \ 192*bcda20f6Schristos { \ 193*bcda20f6Schristos if (isc__md_##alg != NULL) { \ 194*bcda20f6Schristos EVP_MD_free(*(isc_md_type_t **)&isc__md_##alg); \ 195*bcda20f6Schristos isc__md_##alg = NULL; \ 196*bcda20f6Schristos } \ 197*bcda20f6Schristos } 198*bcda20f6Schristos 199*bcda20f6Schristos #else 200*bcda20f6Schristos #define md_register_algorithm(alg, algname) \ 201*bcda20f6Schristos { \ 202*bcda20f6Schristos isc__md_##alg = EVP_##alg(); \ 203*bcda20f6Schristos if (isc__md_##alg == NULL) { \ 204*bcda20f6Schristos ERR_clear_error(); \ 205*bcda20f6Schristos } \ 206*bcda20f6Schristos } 207*bcda20f6Schristos #define md_unregister_algorithm(alg) 208*bcda20f6Schristos #endif 209*bcda20f6Schristos 210*bcda20f6Schristos void 211*bcda20f6Schristos isc__md_initialize(void) { 212*bcda20f6Schristos md_register_algorithm(md5, "MD5"); 213*bcda20f6Schristos md_register_algorithm(sha1, "SHA1"); 214*bcda20f6Schristos md_register_algorithm(sha224, "SHA224"); 215*bcda20f6Schristos md_register_algorithm(sha256, "SHA256"); 216*bcda20f6Schristos md_register_algorithm(sha384, "SHA384"); 217*bcda20f6Schristos md_register_algorithm(sha512, "SHA512"); 218*bcda20f6Schristos } 219*bcda20f6Schristos 220*bcda20f6Schristos void 221*bcda20f6Schristos isc__md_shutdown(void) { 222*bcda20f6Schristos md_unregister_algorithm(sha512); 223*bcda20f6Schristos md_unregister_algorithm(sha384); 224*bcda20f6Schristos md_unregister_algorithm(sha256); 225*bcda20f6Schristos md_unregister_algorithm(sha224); 226*bcda20f6Schristos md_unregister_algorithm(sha1); 227*bcda20f6Schristos md_unregister_algorithm(md5); 228*bcda20f6Schristos } 229*bcda20f6Schristos 230*bcda20f6Schristos #endif /* UNIT_TESTING */ 231