xref: /netbsd-src/external/mpl/bind/dist/lib/isc/md.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: md.c,v 1.7 2025/01/26 16:25:37 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
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 #include <stdio.h>
17 
18 #include <openssl/err.h>
19 #include <openssl/evp.h>
20 #include <openssl/opensslv.h>
21 
22 #include <isc/md.h>
23 #include <isc/util.h>
24 
25 #include "openssl_shim.h"
26 
27 isc_md_t *
28 isc_md_new(void) {
29 	isc_md_t *md = EVP_MD_CTX_new();
30 	RUNTIME_CHECK(md != NULL);
31 	return md;
32 }
33 
34 void
35 isc_md_free(isc_md_t *md) {
36 	if (md == NULL) {
37 		return;
38 	}
39 
40 	EVP_MD_CTX_free(md);
41 }
42 
43 isc_result_t
44 isc_md_init(isc_md_t *md, const isc_md_type_t *md_type) {
45 	REQUIRE(md != NULL);
46 
47 	if (md_type == NULL) {
48 		return ISC_R_NOTIMPLEMENTED;
49 	}
50 
51 	if (EVP_DigestInit_ex(md, md_type, NULL) != 1) {
52 		ERR_clear_error();
53 		return ISC_R_CRYPTOFAILURE;
54 	}
55 
56 	return ISC_R_SUCCESS;
57 }
58 
59 isc_result_t
60 isc_md_reset(isc_md_t *md) {
61 	REQUIRE(md != NULL);
62 
63 	if (EVP_MD_CTX_reset(md) != 1) {
64 		ERR_clear_error();
65 		return ISC_R_CRYPTOFAILURE;
66 	}
67 
68 	return ISC_R_SUCCESS;
69 }
70 
71 isc_result_t
72 isc_md_update(isc_md_t *md, const unsigned char *buf, const size_t len) {
73 	REQUIRE(md != NULL);
74 
75 	if (buf == NULL || len == 0) {
76 		return ISC_R_SUCCESS;
77 	}
78 
79 	if (EVP_DigestUpdate(md, buf, len) != 1) {
80 		ERR_clear_error();
81 		return ISC_R_CRYPTOFAILURE;
82 	}
83 
84 	return ISC_R_SUCCESS;
85 }
86 
87 isc_result_t
88 isc_md_final(isc_md_t *md, unsigned char *digest, unsigned int *digestlen) {
89 	REQUIRE(md != NULL);
90 	REQUIRE(digest != NULL);
91 
92 	if (EVP_DigestFinal_ex(md, digest, digestlen) != 1) {
93 		ERR_clear_error();
94 		return ISC_R_CRYPTOFAILURE;
95 	}
96 
97 	return ISC_R_SUCCESS;
98 }
99 
100 const isc_md_type_t *
101 isc_md_get_md_type(isc_md_t *md) {
102 	REQUIRE(md != NULL);
103 
104 	return EVP_MD_CTX_get0_md(md);
105 }
106 
107 size_t
108 isc_md_get_size(isc_md_t *md) {
109 	REQUIRE(md != NULL);
110 
111 	return EVP_MD_CTX_size(md);
112 }
113 
114 size_t
115 isc_md_get_block_size(isc_md_t *md) {
116 	REQUIRE(md != NULL);
117 
118 	return EVP_MD_CTX_block_size(md);
119 }
120 
121 size_t
122 isc_md_type_get_size(const isc_md_type_t *md_type) {
123 	STATIC_ASSERT(ISC_MAX_MD_SIZE >= EVP_MAX_MD_SIZE,
124 		      "Change ISC_MAX_MD_SIZE to be greater than or equal to "
125 		      "EVP_MAX_MD_SIZE");
126 	if (md_type != NULL) {
127 		return (size_t)EVP_MD_size(md_type);
128 	}
129 
130 	return ISC_MAX_MD_SIZE;
131 }
132 
133 size_t
134 isc_md_type_get_block_size(const isc_md_type_t *md_type) {
135 	STATIC_ASSERT(ISC_MAX_MD_SIZE >= EVP_MAX_MD_SIZE,
136 		      "Change ISC_MAX_MD_SIZE to be greater than or equal to "
137 		      "EVP_MAX_MD_SIZE");
138 	if (md_type != NULL) {
139 		return (size_t)EVP_MD_block_size(md_type);
140 	}
141 
142 	return ISC_MAX_MD_SIZE;
143 }
144 
145 isc_result_t
146 isc_md(const isc_md_type_t *md_type, const unsigned char *buf, const size_t len,
147        unsigned char *digest, unsigned int *digestlen) {
148 	isc_md_t *md;
149 	isc_result_t res;
150 
151 	md = isc_md_new();
152 
153 	res = isc_md_init(md, md_type);
154 	if (res != ISC_R_SUCCESS) {
155 		goto end;
156 	}
157 
158 	res = isc_md_update(md, buf, len);
159 	if (res != ISC_R_SUCCESS) {
160 		goto end;
161 	}
162 
163 	res = isc_md_final(md, digest, digestlen);
164 	if (res != ISC_R_SUCCESS) {
165 		goto end;
166 	}
167 end:
168 	isc_md_free(md);
169 
170 	return res;
171 }
172 
173 #ifndef UNIT_TESTING
174 const isc_md_type_t *isc__md_md5 = NULL;
175 const isc_md_type_t *isc__md_sha1 = NULL;
176 const isc_md_type_t *isc__md_sha224 = NULL;
177 const isc_md_type_t *isc__md_sha256 = NULL;
178 const isc_md_type_t *isc__md_sha384 = NULL;
179 const isc_md_type_t *isc__md_sha512 = NULL;
180 
181 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
182 #define md_register_algorithm(alg, algname)                        \
183 	{                                                          \
184 		REQUIRE(isc__md_##alg == NULL);                    \
185 		isc__md_##alg = EVP_MD_fetch(NULL, algname, NULL); \
186 		if (isc__md_##alg == NULL) {                       \
187 			ERR_clear_error();                         \
188 		}                                                  \
189 	}
190 
191 #define md_unregister_algorithm(alg)                                    \
192 	{                                                               \
193 		if (isc__md_##alg != NULL) {                            \
194 			EVP_MD_free(*(isc_md_type_t **)&isc__md_##alg); \
195 			isc__md_##alg = NULL;                           \
196 		}                                                       \
197 	}
198 
199 #else
200 #define md_register_algorithm(alg, algname)  \
201 	{                                    \
202 		isc__md_##alg = EVP_##alg(); \
203 		if (isc__md_##alg == NULL) { \
204 			ERR_clear_error();   \
205 		}                            \
206 	}
207 #define md_unregister_algorithm(alg)
208 #endif
209 
210 void
211 isc__md_initialize(void) {
212 	md_register_algorithm(md5, "MD5");
213 	md_register_algorithm(sha1, "SHA1");
214 	md_register_algorithm(sha224, "SHA224");
215 	md_register_algorithm(sha256, "SHA256");
216 	md_register_algorithm(sha384, "SHA384");
217 	md_register_algorithm(sha512, "SHA512");
218 }
219 
220 void
221 isc__md_shutdown(void) {
222 	md_unregister_algorithm(sha512);
223 	md_unregister_algorithm(sha384);
224 	md_unregister_algorithm(sha256);
225 	md_unregister_algorithm(sha224);
226 	md_unregister_algorithm(sha1);
227 	md_unregister_algorithm(md5);
228 }
229 
230 #endif /* UNIT_TESTING */
231