1/* $NetBSD: hmac.c,v 1.1 2024/02/18 20:57:49 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/hmac.h> 17#include <openssl/opensslv.h> 18 19#include <isc/assertions.h> 20#include <isc/hmac.h> 21#include <isc/md.h> 22#include <isc/platform.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 30isc_hmac_t * 31isc_hmac_new(void) { 32 HMAC_CTX *hmac = HMAC_CTX_new(); 33 RUNTIME_CHECK(hmac != NULL); 34 return ((struct hmac *)hmac); 35} 36 37void 38isc_hmac_free(isc_hmac_t *hmac) { 39 if (ISC_UNLIKELY(hmac == NULL)) { 40 return; 41 } 42 43 HMAC_CTX_free(hmac); 44} 45 46isc_result_t 47isc_hmac_init(isc_hmac_t *hmac, const void *key, size_t keylen, 48 const isc_md_type_t *md_type) { 49 REQUIRE(hmac != NULL); 50 REQUIRE(key != NULL); 51 52 if (md_type == NULL) { 53 return (ISC_R_NOTIMPLEMENTED); 54 } 55 56 if (HMAC_Init_ex(hmac, key, keylen, md_type, NULL) != 1) { 57 return (ISC_R_CRYPTOFAILURE); 58 } 59 60 return (ISC_R_SUCCESS); 61} 62 63isc_result_t 64isc_hmac_reset(isc_hmac_t *hmac) { 65 REQUIRE(hmac != NULL); 66 67 if (HMAC_CTX_reset(hmac) != 1) { 68 return (ISC_R_CRYPTOFAILURE); 69 } 70 71 return (ISC_R_SUCCESS); 72} 73 74isc_result_t 75isc_hmac_update(isc_hmac_t *hmac, const unsigned char *buf, const size_t len) { 76 REQUIRE(hmac != NULL); 77 78 if (ISC_UNLIKELY(buf == NULL || len == 0)) { 79 return (ISC_R_SUCCESS); 80 } 81 82 if (HMAC_Update(hmac, buf, len) != 1) { 83 return (ISC_R_CRYPTOFAILURE); 84 } 85 86 return (ISC_R_SUCCESS); 87} 88 89isc_result_t 90isc_hmac_final(isc_hmac_t *hmac, unsigned char *digest, 91 unsigned int *digestlen) { 92 REQUIRE(hmac != NULL); 93 REQUIRE(digest != NULL); 94 95 if (HMAC_Final(hmac, digest, digestlen) != 1) { 96 return (ISC_R_CRYPTOFAILURE); 97 } 98 99 return (ISC_R_SUCCESS); 100} 101 102const isc_md_type_t * 103isc_hmac_get_md_type(isc_hmac_t *hmac) { 104 REQUIRE(hmac != NULL); 105 106 return (HMAC_CTX_get_md(hmac)); 107} 108 109size_t 110isc_hmac_get_size(isc_hmac_t *hmac) { 111 REQUIRE(hmac != NULL); 112 113 return ((size_t)EVP_MD_size(HMAC_CTX_get_md(hmac))); 114} 115 116int 117isc_hmac_get_block_size(isc_hmac_t *hmac) { 118 REQUIRE(hmac != NULL); 119 120 return (EVP_MD_block_size(HMAC_CTX_get_md(hmac))); 121} 122 123isc_result_t 124isc_hmac(const isc_md_type_t *type, const void *key, const int keylen, 125 const unsigned char *buf, const size_t len, unsigned char *digest, 126 unsigned int *digestlen) { 127 isc_result_t res; 128 isc_hmac_t *hmac = isc_hmac_new(); 129 130 res = isc_hmac_init(hmac, key, keylen, type); 131 if (res != ISC_R_SUCCESS) { 132 goto end; 133 } 134 135 res = isc_hmac_update(hmac, buf, len); 136 if (res != ISC_R_SUCCESS) { 137 goto end; 138 } 139 140 res = isc_hmac_final(hmac, digest, digestlen); 141 if (res != ISC_R_SUCCESS) { 142 goto end; 143 } 144end: 145 isc_hmac_free(hmac); 146 147 return (res); 148} 149