xref: /netbsd-src/external/mpl/bind/dist/lib/isc/md.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
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