1 /* $NetBSD: hmac.c,v 1.4 2021/02/19 16:42:19 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14 #include <openssl/hmac.h> 15 #include <openssl/opensslv.h> 16 17 #include <isc/assertions.h> 18 #include <isc/hmac.h> 19 #include <isc/md.h> 20 #include <isc/platform.h> 21 #include <isc/safe.h> 22 #include <isc/string.h> 23 #include <isc/types.h> 24 #include <isc/util.h> 25 26 #include "openssl_shim.h" 27 28 isc_hmac_t * 29 isc_hmac_new(void) { 30 HMAC_CTX *hmac = HMAC_CTX_new(); 31 RUNTIME_CHECK(hmac != NULL); 32 return ((struct hmac *)hmac); 33 } 34 35 void 36 isc_hmac_free(isc_hmac_t *hmac) { 37 if (ISC_UNLIKELY(hmac == NULL)) { 38 return; 39 } 40 41 HMAC_CTX_free(hmac); 42 } 43 44 isc_result_t 45 isc_hmac_init(isc_hmac_t *hmac, const void *key, size_t keylen, 46 const isc_md_type_t *md_type) { 47 REQUIRE(hmac != NULL); 48 REQUIRE(key != NULL); 49 50 if (md_type == NULL) { 51 return (ISC_R_NOTIMPLEMENTED); 52 } 53 54 if (HMAC_Init_ex(hmac, key, keylen, md_type, NULL) != 1) { 55 return (ISC_R_CRYPTOFAILURE); 56 } 57 58 return (ISC_R_SUCCESS); 59 } 60 61 isc_result_t 62 isc_hmac_reset(isc_hmac_t *hmac) { 63 REQUIRE(hmac != NULL); 64 65 if (HMAC_CTX_reset(hmac) != 1) { 66 return (ISC_R_CRYPTOFAILURE); 67 } 68 69 return (ISC_R_SUCCESS); 70 } 71 72 isc_result_t 73 isc_hmac_update(isc_hmac_t *hmac, const unsigned char *buf, const size_t len) { 74 REQUIRE(hmac != NULL); 75 76 if (ISC_UNLIKELY(buf == NULL || len == 0)) { 77 return (ISC_R_SUCCESS); 78 } 79 80 if (HMAC_Update(hmac, buf, len) != 1) { 81 return (ISC_R_CRYPTOFAILURE); 82 } 83 84 return (ISC_R_SUCCESS); 85 } 86 87 isc_result_t 88 isc_hmac_final(isc_hmac_t *hmac, unsigned char *digest, 89 unsigned int *digestlen) { 90 REQUIRE(hmac != NULL); 91 REQUIRE(digest != NULL); 92 93 if (HMAC_Final(hmac, digest, digestlen) != 1) { 94 return (ISC_R_CRYPTOFAILURE); 95 } 96 97 return (ISC_R_SUCCESS); 98 } 99 100 const isc_md_type_t * 101 isc_hmac_get_md_type(isc_hmac_t *hmac) { 102 REQUIRE(hmac != NULL); 103 104 return (HMAC_CTX_get_md(hmac)); 105 } 106 107 size_t 108 isc_hmac_get_size(isc_hmac_t *hmac) { 109 REQUIRE(hmac != NULL); 110 111 return ((size_t)EVP_MD_size(HMAC_CTX_get_md(hmac))); 112 } 113 114 int 115 isc_hmac_get_block_size(isc_hmac_t *hmac) { 116 REQUIRE(hmac != NULL); 117 118 return (EVP_MD_block_size(HMAC_CTX_get_md(hmac))); 119 } 120 121 isc_result_t 122 isc_hmac(const isc_md_type_t *type, const void *key, const int keylen, 123 const unsigned char *buf, const size_t len, unsigned char *digest, 124 unsigned int *digestlen) { 125 isc_result_t res; 126 isc_hmac_t *hmac = isc_hmac_new(); 127 128 res = isc_hmac_init(hmac, key, keylen, type); 129 if (res != ISC_R_SUCCESS) { 130 goto end; 131 } 132 133 res = isc_hmac_update(hmac, buf, len); 134 if (res != ISC_R_SUCCESS) { 135 goto end; 136 } 137 138 res = isc_hmac_final(hmac, digest, digestlen); 139 if (res != ISC_R_SUCCESS) { 140 goto end; 141 } 142 end: 143 isc_hmac_free(hmac); 144 145 return (res); 146 } 147