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