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