1 /* $NetBSD: md.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 <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 (ISC_UNLIKELY(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 return (ISC_R_CRYPTOFAILURE); 53 } 54 55 return (ISC_R_SUCCESS); 56 } 57 58 isc_result_t 59 isc_md_reset(isc_md_t *md) { 60 REQUIRE(md != NULL); 61 62 if (EVP_MD_CTX_reset(md) != 1) { 63 return (ISC_R_CRYPTOFAILURE); 64 } 65 66 return (ISC_R_SUCCESS); 67 } 68 69 isc_result_t 70 isc_md_update(isc_md_t *md, const unsigned char *buf, const size_t len) { 71 REQUIRE(md != NULL); 72 73 if (ISC_UNLIKELY(buf == NULL || len == 0)) { 74 return (ISC_R_SUCCESS); 75 } 76 77 if (EVP_DigestUpdate(md, buf, len) != 1) { 78 return (ISC_R_CRYPTOFAILURE); 79 } 80 81 return (ISC_R_SUCCESS); 82 } 83 84 isc_result_t 85 isc_md_final(isc_md_t *md, unsigned char *digest, unsigned int *digestlen) { 86 REQUIRE(md != NULL); 87 REQUIRE(digest != NULL); 88 89 if (EVP_DigestFinal_ex(md, digest, digestlen) != 1) { 90 return (ISC_R_CRYPTOFAILURE); 91 } 92 93 return (ISC_R_SUCCESS); 94 } 95 96 const isc_md_type_t * 97 isc_md_get_md_type(isc_md_t *md) { 98 REQUIRE(md != NULL); 99 100 return (EVP_MD_CTX_md(md)); 101 } 102 103 size_t 104 isc_md_get_size(isc_md_t *md) { 105 REQUIRE(md != NULL); 106 107 return (EVP_MD_CTX_size(md)); 108 } 109 110 size_t 111 isc_md_get_block_size(isc_md_t *md) { 112 REQUIRE(md != NULL); 113 114 return (EVP_MD_CTX_block_size(md)); 115 } 116 117 size_t 118 isc_md_type_get_size(const isc_md_type_t *md_type) { 119 STATIC_ASSERT(ISC_MAX_MD_SIZE >= EVP_MAX_MD_SIZE, 120 "Change ISC_MAX_MD_SIZE to be greater than or equal to " 121 "EVP_MAX_MD_SIZE"); 122 if (md_type != NULL) { 123 return ((size_t)EVP_MD_size(md_type)); 124 } 125 126 return (ISC_MAX_MD_SIZE); 127 } 128 129 size_t 130 isc_md_type_get_block_size(const isc_md_type_t *md_type) { 131 STATIC_ASSERT(ISC_MAX_MD_SIZE >= EVP_MAX_MD_SIZE, 132 "Change ISC_MAX_MD_SIZE to be greater than or equal to " 133 "EVP_MAX_MD_SIZE"); 134 if (md_type != NULL) { 135 return ((size_t)EVP_MD_block_size(md_type)); 136 } 137 138 return (ISC_MAX_MD_SIZE); 139 } 140 141 isc_result_t 142 isc_md(const isc_md_type_t *md_type, const unsigned char *buf, const size_t len, 143 unsigned char *digest, unsigned int *digestlen) { 144 isc_md_t *md; 145 isc_result_t res; 146 147 md = isc_md_new(); 148 149 res = isc_md_init(md, md_type); 150 if (res != ISC_R_SUCCESS) { 151 goto end; 152 } 153 154 res = isc_md_update(md, buf, len); 155 if (res != ISC_R_SUCCESS) { 156 goto end; 157 } 158 159 res = isc_md_final(md, digest, digestlen); 160 if (res != ISC_R_SUCCESS) { 161 goto end; 162 } 163 end: 164 isc_md_free(md); 165 166 return (res); 167 } 168 169 #define md_register_algorithm(alg) \ 170 const isc_md_type_t *isc__md_##alg(void) { return (EVP_##alg()); } 171 172 md_register_algorithm(md5); 173 md_register_algorithm(sha1); 174 md_register_algorithm(sha224); 175 md_register_algorithm(sha256); 176 md_register_algorithm(sha384); 177 md_register_algorithm(sha512); 178