Home | History | Annotate | Line # | Download | only in isc
      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