1 1.1 christos /* $NetBSD: md.c,v 1.1 2024/02/18 20:57:49 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * SPDX-License-Identifier: MPL-2.0 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos #include <stdio.h> 17 1.1 christos 18 1.1 christos #include <openssl/err.h> 19 1.1 christos #include <openssl/evp.h> 20 1.1 christos #include <openssl/opensslv.h> 21 1.1 christos 22 1.1 christos #include <isc/md.h> 23 1.1 christos #include <isc/util.h> 24 1.1 christos 25 1.1 christos #include "openssl_shim.h" 26 1.1 christos 27 1.1 christos isc_md_t * 28 1.1 christos isc_md_new(void) { 29 1.1 christos isc_md_t *md = EVP_MD_CTX_new(); 30 1.1 christos RUNTIME_CHECK(md != NULL); 31 1.1 christos return (md); 32 1.1 christos } 33 1.1 christos 34 1.1 christos void 35 1.1 christos isc_md_free(isc_md_t *md) { 36 1.1 christos if (ISC_UNLIKELY(md == NULL)) { 37 1.1 christos return; 38 1.1 christos } 39 1.1 christos 40 1.1 christos EVP_MD_CTX_free(md); 41 1.1 christos } 42 1.1 christos 43 1.1 christos isc_result_t 44 1.1 christos isc_md_init(isc_md_t *md, const isc_md_type_t *md_type) { 45 1.1 christos REQUIRE(md != NULL); 46 1.1 christos 47 1.1 christos if (md_type == NULL) { 48 1.1 christos return (ISC_R_NOTIMPLEMENTED); 49 1.1 christos } 50 1.1 christos 51 1.1 christos if (EVP_DigestInit_ex(md, md_type, NULL) != 1) { 52 1.1 christos return (ISC_R_CRYPTOFAILURE); 53 1.1 christos } 54 1.1 christos 55 1.1 christos return (ISC_R_SUCCESS); 56 1.1 christos } 57 1.1 christos 58 1.1 christos isc_result_t 59 1.1 christos isc_md_reset(isc_md_t *md) { 60 1.1 christos REQUIRE(md != NULL); 61 1.1 christos 62 1.1 christos if (EVP_MD_CTX_reset(md) != 1) { 63 1.1 christos return (ISC_R_CRYPTOFAILURE); 64 1.1 christos } 65 1.1 christos 66 1.1 christos return (ISC_R_SUCCESS); 67 1.1 christos } 68 1.1 christos 69 1.1 christos isc_result_t 70 1.1 christos isc_md_update(isc_md_t *md, const unsigned char *buf, const size_t len) { 71 1.1 christos REQUIRE(md != NULL); 72 1.1 christos 73 1.1 christos if (ISC_UNLIKELY(buf == NULL || len == 0)) { 74 1.1 christos return (ISC_R_SUCCESS); 75 1.1 christos } 76 1.1 christos 77 1.1 christos if (EVP_DigestUpdate(md, buf, len) != 1) { 78 1.1 christos return (ISC_R_CRYPTOFAILURE); 79 1.1 christos } 80 1.1 christos 81 1.1 christos return (ISC_R_SUCCESS); 82 1.1 christos } 83 1.1 christos 84 1.1 christos isc_result_t 85 1.1 christos isc_md_final(isc_md_t *md, unsigned char *digest, unsigned int *digestlen) { 86 1.1 christos REQUIRE(md != NULL); 87 1.1 christos REQUIRE(digest != NULL); 88 1.1 christos 89 1.1 christos if (EVP_DigestFinal_ex(md, digest, digestlen) != 1) { 90 1.1 christos return (ISC_R_CRYPTOFAILURE); 91 1.1 christos } 92 1.1 christos 93 1.1 christos return (ISC_R_SUCCESS); 94 1.1 christos } 95 1.1 christos 96 1.1 christos const isc_md_type_t * 97 1.1 christos isc_md_get_md_type(isc_md_t *md) { 98 1.1 christos REQUIRE(md != NULL); 99 1.1 christos 100 1.1 christos return (EVP_MD_CTX_md(md)); 101 1.1 christos } 102 1.1 christos 103 1.1 christos size_t 104 1.1 christos isc_md_get_size(isc_md_t *md) { 105 1.1 christos REQUIRE(md != NULL); 106 1.1 christos 107 1.1 christos return (EVP_MD_CTX_size(md)); 108 1.1 christos } 109 1.1 christos 110 1.1 christos size_t 111 1.1 christos isc_md_get_block_size(isc_md_t *md) { 112 1.1 christos REQUIRE(md != NULL); 113 1.1 christos 114 1.1 christos return (EVP_MD_CTX_block_size(md)); 115 1.1 christos } 116 1.1 christos 117 1.1 christos size_t 118 1.1 christos isc_md_type_get_size(const isc_md_type_t *md_type) { 119 1.1 christos STATIC_ASSERT(ISC_MAX_MD_SIZE >= EVP_MAX_MD_SIZE, 120 1.1 christos "Change ISC_MAX_MD_SIZE to be greater than or equal to " 121 1.1 christos "EVP_MAX_MD_SIZE"); 122 1.1 christos if (md_type != NULL) { 123 1.1 christos return ((size_t)EVP_MD_size(md_type)); 124 1.1 christos } 125 1.1 christos 126 1.1 christos return (ISC_MAX_MD_SIZE); 127 1.1 christos } 128 1.1 christos 129 1.1 christos size_t 130 1.1 christos isc_md_type_get_block_size(const isc_md_type_t *md_type) { 131 1.1 christos STATIC_ASSERT(ISC_MAX_MD_SIZE >= EVP_MAX_MD_SIZE, 132 1.1 christos "Change ISC_MAX_MD_SIZE to be greater than or equal to " 133 1.1 christos "EVP_MAX_MD_SIZE"); 134 1.1 christos if (md_type != NULL) { 135 1.1 christos return ((size_t)EVP_MD_block_size(md_type)); 136 1.1 christos } 137 1.1 christos 138 1.1 christos return (ISC_MAX_MD_SIZE); 139 1.1 christos } 140 1.1 christos 141 1.1 christos isc_result_t 142 1.1 christos isc_md(const isc_md_type_t *md_type, const unsigned char *buf, const size_t len, 143 1.1 christos unsigned char *digest, unsigned int *digestlen) { 144 1.1 christos isc_md_t *md; 145 1.1 christos isc_result_t res; 146 1.1 christos 147 1.1 christos md = isc_md_new(); 148 1.1 christos 149 1.1 christos res = isc_md_init(md, md_type); 150 1.1 christos if (res != ISC_R_SUCCESS) { 151 1.1 christos goto end; 152 1.1 christos } 153 1.1 christos 154 1.1 christos res = isc_md_update(md, buf, len); 155 1.1 christos if (res != ISC_R_SUCCESS) { 156 1.1 christos goto end; 157 1.1 christos } 158 1.1 christos 159 1.1 christos res = isc_md_final(md, digest, digestlen); 160 1.1 christos if (res != ISC_R_SUCCESS) { 161 1.1 christos goto end; 162 1.1 christos } 163 1.1 christos end: 164 1.1 christos isc_md_free(md); 165 1.1 christos 166 1.1 christos return (res); 167 1.1 christos } 168 1.1 christos 169 1.1 christos #define md_register_algorithm(alg) \ 170 1.1 christos const isc_md_type_t *isc__md_##alg(void) { return (EVP_##alg()); } 171 1.1 christos 172 1.1 christos md_register_algorithm(md5); 173 1.1 christos md_register_algorithm(sha1); 174 1.1 christos md_register_algorithm(sha224); 175 1.1 christos md_register_algorithm(sha256); 176 1.1 christos md_register_algorithm(sha384); 177 1.1 christos md_register_algorithm(sha512); 178