Coverage Report

Created: 2025-08-26 06:59

/src/bind9/lib/isc/hmac.c
Line
Count
Source (jump to first uncovered line)
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
179
isc_hmac_new(void) {
30
179
  EVP_MD_CTX *hmac_st = EVP_MD_CTX_new();
31
179
  RUNTIME_CHECK(hmac_st != NULL);
32
179
  return (isc_hmac_t *)hmac_st;
33
179
}
34
35
void
36
179
isc_hmac_free(isc_hmac_t *hmac_st) {
37
179
  if (hmac_st == NULL) {
38
0
    return;
39
0
  }
40
41
179
  EVP_MD_CTX_free((EVP_MD_CTX *)hmac_st);
42
179
}
43
44
isc_result_t
45
isc_hmac_init(isc_hmac_t *hmac_st, const void *key, const size_t keylen,
46
179
        const isc_md_type_t *md_type) {
47
179
  EVP_PKEY *pkey;
48
49
179
  REQUIRE(hmac_st != NULL);
50
179
  REQUIRE(key != NULL);
51
179
  REQUIRE(keylen <= INT_MAX);
52
53
179
  if (md_type == NULL) {
54
0
    return ISC_R_NOTIMPLEMENTED;
55
0
  }
56
57
179
  pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, keylen);
58
179
  if (pkey == NULL) {
59
0
    ERR_clear_error();
60
0
    return ISC_R_CRYPTOFAILURE;
61
0
  }
62
63
179
  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
179
  EVP_PKEY_free(pkey);
70
71
179
  return ISC_R_SUCCESS;
72
179
}
73
74
isc_result_t
75
47
isc_hmac_reset(isc_hmac_t *hmac_st) {
76
47
  REQUIRE(hmac_st != NULL);
77
78
47
  if (EVP_MD_CTX_reset(hmac_st) != 1) {
79
0
    ERR_clear_error();
80
0
    return ISC_R_CRYPTOFAILURE;
81
0
  }
82
83
47
  return ISC_R_SUCCESS;
84
47
}
85
86
isc_result_t
87
isc_hmac_update(isc_hmac_t *hmac_st, const unsigned char *buf,
88
321
    const size_t len) {
89
321
  REQUIRE(hmac_st != NULL);
90
91
321
  if (buf == NULL || len == 0) {
92
0
    return ISC_R_SUCCESS;
93
0
  }
94
95
321
  if (EVP_DigestSignUpdate(hmac_st, buf, len) != 1) {
96
0
    ERR_clear_error();
97
0
    return ISC_R_CRYPTOFAILURE;
98
0
  }
99
100
321
  return ISC_R_SUCCESS;
101
321
}
102
103
isc_result_t
104
isc_hmac_final(isc_hmac_t *hmac_st, unsigned char *digest,
105
47
         unsigned int *digestlen) {
106
47
  REQUIRE(hmac_st != NULL);
107
47
  REQUIRE(digest != NULL);
108
47
  REQUIRE(digestlen != NULL);
109
110
47
  size_t len = *digestlen;
111
112
47
  if (EVP_DigestSignFinal(hmac_st, digest, &len) != 1) {
113
0
    ERR_clear_error();
114
0
    return ISC_R_CRYPTOFAILURE;
115
0
  }
116
117
47
  *digestlen = (unsigned int)len;
118
119
47
  return ISC_R_SUCCESS;
120
47
}
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
}