Coverage Report

Created: 2025-11-11 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/isc/hmac.c
Line
Count
Source
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
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 https://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 <openssl/err.h>
15
#include <openssl/evp.h>
16
#include <openssl/opensslv.h>
17
18
#include <isc/assertions.h>
19
#include <isc/hmac.h>
20
#include <isc/md.h>
21
#include <isc/safe.h>
22
#include <isc/string.h>
23
#include <isc/types.h>
24
#include <isc/util.h>
25
26
#include "openssl_shim.h"
27
28
isc_hmac_t *
29
12
isc_hmac_new(void) {
30
12
  EVP_MD_CTX *hmac_st = EVP_MD_CTX_new();
31
12
  RUNTIME_CHECK(hmac_st != NULL);
32
12
  return (isc_hmac_t *)hmac_st;
33
12
}
34
35
void
36
12
isc_hmac_free(isc_hmac_t *hmac_st) {
37
12
  if (hmac_st == NULL) {
38
0
    return;
39
0
  }
40
41
12
  EVP_MD_CTX_free((EVP_MD_CTX *)hmac_st);
42
12
}
43
44
isc_result_t
45
isc_hmac_init(isc_hmac_t *hmac_st, const void *key, const size_t keylen,
46
12
        const isc_md_type_t *md_type) {
47
12
  EVP_PKEY *pkey;
48
49
12
  REQUIRE(hmac_st != NULL);
50
12
  REQUIRE(key != NULL);
51
12
  REQUIRE(keylen <= INT_MAX);
52
53
12
  if (md_type == NULL) {
54
0
    return ISC_R_NOTIMPLEMENTED;
55
0
  }
56
57
12
  pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, keylen);
58
12
  if (pkey == NULL) {
59
0
    ERR_clear_error();
60
0
    return ISC_R_CRYPTOFAILURE;
61
0
  }
62
63
12
  if (EVP_DigestSignInit(hmac_st, NULL, md_type, NULL, pkey) != 1) {
64
0
    EVP_PKEY_free(pkey);
65
0
    ERR_clear_error();
66
0
    return ISC_R_CRYPTOFAILURE;
67
0
  }
68
69
12
  EVP_PKEY_free(pkey);
70
71
12
  return ISC_R_SUCCESS;
72
12
}
73
74
isc_result_t
75
0
isc_hmac_reset(isc_hmac_t *hmac_st) {
76
0
  REQUIRE(hmac_st != NULL);
77
78
0
  if (EVP_MD_CTX_reset(hmac_st) != 1) {
79
0
    ERR_clear_error();
80
0
    return ISC_R_CRYPTOFAILURE;
81
0
  }
82
83
0
  return ISC_R_SUCCESS;
84
0
}
85
86
isc_result_t
87
isc_hmac_update(isc_hmac_t *hmac_st, const unsigned char *buf,
88
0
    const size_t len) {
89
0
  REQUIRE(hmac_st != NULL);
90
91
0
  if (buf == NULL || len == 0) {
92
0
    return ISC_R_SUCCESS;
93
0
  }
94
95
0
  if (EVP_DigestSignUpdate(hmac_st, buf, len) != 1) {
96
0
    ERR_clear_error();
97
0
    return ISC_R_CRYPTOFAILURE;
98
0
  }
99
100
0
  return ISC_R_SUCCESS;
101
0
}
102
103
isc_result_t
104
isc_hmac_final(isc_hmac_t *hmac_st, unsigned char *digest,
105
0
         unsigned int *digestlen) {
106
0
  REQUIRE(hmac_st != NULL);
107
0
  REQUIRE(digest != NULL);
108
0
  REQUIRE(digestlen != NULL);
109
110
0
  size_t len = *digestlen;
111
112
0
  if (EVP_DigestSignFinal(hmac_st, digest, &len) != 1) {
113
0
    ERR_clear_error();
114
0
    return ISC_R_CRYPTOFAILURE;
115
0
  }
116
117
0
  *digestlen = (unsigned int)len;
118
119
0
  return ISC_R_SUCCESS;
120
0
}
121
122
const isc_md_type_t *
123
0
isc_hmac_get_md_type(isc_hmac_t *hmac_st) {
124
0
  REQUIRE(hmac_st != NULL);
125
126
0
  return EVP_MD_CTX_get0_md(hmac_st);
127
0
}
128
129
size_t
130
0
isc_hmac_get_size(isc_hmac_t *hmac_st) {
131
0
  REQUIRE(hmac_st != NULL);
132
133
0
  return (size_t)EVP_MD_CTX_size(hmac_st);
134
0
}
135
136
int
137
0
isc_hmac_get_block_size(isc_hmac_t *hmac_st) {
138
0
  REQUIRE(hmac_st != NULL);
139
140
0
  return EVP_MD_CTX_block_size(hmac_st);
141
0
}
142
143
isc_result_t
144
isc_hmac(const isc_md_type_t *type, const void *key, const size_t keylen,
145
   const unsigned char *buf, const size_t len, unsigned char *digest,
146
0
   unsigned int *digestlen) {
147
0
  isc_result_t res;
148
0
  isc_hmac_t *hmac_st = isc_hmac_new();
149
150
0
  res = isc_hmac_init(hmac_st, key, keylen, type);
151
0
  if (res != ISC_R_SUCCESS) {
152
0
    goto end;
153
0
  }
154
155
0
  res = isc_hmac_update(hmac_st, buf, len);
156
0
  if (res != ISC_R_SUCCESS) {
157
0
    goto end;
158
0
  }
159
160
0
  res = isc_hmac_final(hmac_st, digest, digestlen);
161
0
  if (res != ISC_R_SUCCESS) {
162
0
    goto end;
163
0
  }
164
0
end:
165
0
  isc_hmac_free(hmac_st);
166
167
0
  return res;
168
0
}