xref: /netbsd-src/external/mpl/bind/dist/lib/isc/hmac.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: hmac.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 <openssl/err.h>
17 #include <openssl/evp.h>
18 #include <openssl/opensslv.h>
19 
20 #include <isc/assertions.h>
21 #include <isc/hmac.h>
22 #include <isc/md.h>
23 #include <isc/safe.h>
24 #include <isc/string.h>
25 #include <isc/types.h>
26 #include <isc/util.h>
27 
28 #include "openssl_shim.h"
29 
30 isc_hmac_t *
31 isc_hmac_new(void) {
32 	EVP_MD_CTX *hmac_st = EVP_MD_CTX_new();
33 	RUNTIME_CHECK(hmac_st != NULL);
34 	return (isc_hmac_t *)hmac_st;
35 }
36 
37 void
38 isc_hmac_free(isc_hmac_t *hmac_st) {
39 	if (hmac_st == NULL) {
40 		return;
41 	}
42 
43 	EVP_MD_CTX_free((EVP_MD_CTX *)hmac_st);
44 }
45 
46 isc_result_t
47 isc_hmac_init(isc_hmac_t *hmac_st, const void *key, const size_t keylen,
48 	      const isc_md_type_t *md_type) {
49 	EVP_PKEY *pkey;
50 
51 	REQUIRE(hmac_st != NULL);
52 	REQUIRE(key != NULL);
53 	REQUIRE(keylen <= INT_MAX);
54 
55 	if (md_type == NULL) {
56 		return ISC_R_NOTIMPLEMENTED;
57 	}
58 
59 	pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, keylen);
60 	if (pkey == NULL) {
61 		ERR_clear_error();
62 		return ISC_R_CRYPTOFAILURE;
63 	}
64 
65 	if (EVP_DigestSignInit(hmac_st, NULL, md_type, NULL, pkey) != 1) {
66 		EVP_PKEY_free(pkey);
67 		ERR_clear_error();
68 		return ISC_R_CRYPTOFAILURE;
69 	}
70 
71 	EVP_PKEY_free(pkey);
72 
73 	return ISC_R_SUCCESS;
74 }
75 
76 isc_result_t
77 isc_hmac_reset(isc_hmac_t *hmac_st) {
78 	REQUIRE(hmac_st != NULL);
79 
80 	if (EVP_MD_CTX_reset(hmac_st) != 1) {
81 		ERR_clear_error();
82 		return ISC_R_CRYPTOFAILURE;
83 	}
84 
85 	return ISC_R_SUCCESS;
86 }
87 
88 isc_result_t
89 isc_hmac_update(isc_hmac_t *hmac_st, const unsigned char *buf,
90 		const size_t len) {
91 	REQUIRE(hmac_st != NULL);
92 
93 	if (buf == NULL || len == 0) {
94 		return ISC_R_SUCCESS;
95 	}
96 
97 	if (EVP_DigestSignUpdate(hmac_st, buf, len) != 1) {
98 		ERR_clear_error();
99 		return ISC_R_CRYPTOFAILURE;
100 	}
101 
102 	return ISC_R_SUCCESS;
103 }
104 
105 isc_result_t
106 isc_hmac_final(isc_hmac_t *hmac_st, unsigned char *digest,
107 	       unsigned int *digestlen) {
108 	REQUIRE(hmac_st != NULL);
109 	REQUIRE(digest != NULL);
110 	REQUIRE(digestlen != NULL);
111 
112 	size_t len = *digestlen;
113 
114 	if (EVP_DigestSignFinal(hmac_st, digest, &len) != 1) {
115 		ERR_clear_error();
116 		return ISC_R_CRYPTOFAILURE;
117 	}
118 
119 	*digestlen = (unsigned int)len;
120 
121 	return ISC_R_SUCCESS;
122 }
123 
124 const isc_md_type_t *
125 isc_hmac_get_md_type(isc_hmac_t *hmac_st) {
126 	REQUIRE(hmac_st != NULL);
127 
128 	return EVP_MD_CTX_get0_md(hmac_st);
129 }
130 
131 size_t
132 isc_hmac_get_size(isc_hmac_t *hmac_st) {
133 	REQUIRE(hmac_st != NULL);
134 
135 	return (size_t)EVP_MD_CTX_size(hmac_st);
136 }
137 
138 int
139 isc_hmac_get_block_size(isc_hmac_t *hmac_st) {
140 	REQUIRE(hmac_st != NULL);
141 
142 	return EVP_MD_CTX_block_size(hmac_st);
143 }
144 
145 isc_result_t
146 isc_hmac(const isc_md_type_t *type, const void *key, const size_t keylen,
147 	 const unsigned char *buf, const size_t len, unsigned char *digest,
148 	 unsigned int *digestlen) {
149 	isc_result_t res;
150 	isc_hmac_t *hmac_st = isc_hmac_new();
151 
152 	res = isc_hmac_init(hmac_st, key, keylen, type);
153 	if (res != ISC_R_SUCCESS) {
154 		goto end;
155 	}
156 
157 	res = isc_hmac_update(hmac_st, buf, len);
158 	if (res != ISC_R_SUCCESS) {
159 		goto end;
160 	}
161 
162 	res = isc_hmac_final(hmac_st, digest, digestlen);
163 	if (res != ISC_R_SUCCESS) {
164 		goto end;
165 	}
166 end:
167 	isc_hmac_free(hmac_st);
168 
169 	return res;
170 }
171