Coverage Report

Created: 2025-07-18 07:03

/src/bind9/lib/dns/hmac_link.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 AND ISC
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
/*
15
 * Copyright (C) Network Associates, Inc.
16
 *
17
 * Permission to use, copy, modify, and/or distribute this software for any
18
 * purpose with or without fee is hereby granted, provided that the above
19
 * copyright notice and this permission notice appear in all copies.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
22
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
23
 * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
24
 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
26
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
27
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28
 */
29
30
#include <arpa/inet.h>
31
#include <stdbool.h>
32
33
#include <isc/buffer.h>
34
#include <isc/hmac.h>
35
#include <isc/lex.h>
36
#include <isc/md.h>
37
#include <isc/mem.h>
38
#include <isc/nonce.h>
39
#include <isc/random.h>
40
#include <isc/result.h>
41
#include <isc/safe.h>
42
#include <isc/string.h>
43
#include <isc/util.h>
44
45
#include "dst_internal.h"
46
#include "dst_parse.h"
47
48
22
#define ISC_MD_md5    ISC_MD_MD5
49
22
#define ISC_MD_sha1   ISC_MD_SHA1
50
22
#define ISC_MD_sha224 ISC_MD_SHA224
51
55
#define ISC_MD_sha256 ISC_MD_SHA256
52
22
#define ISC_MD_sha384 ISC_MD_SHA384
53
22
#define ISC_MD_sha512 ISC_MD_SHA512
54
55
#define hmac_register_algorithm(alg)                                           \
56
  static isc_result_t hmac##alg##_createctx(dst_key_t *key,              \
57
31
              dst_context_t *dctx) {       \
58
31
    return (hmac_createctx(ISC_MD_##alg, key, dctx));              \
59
31
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_createctx
Unexecuted instantiation: hmac_link.c:hmacsha1_createctx
Unexecuted instantiation: hmac_link.c:hmacsha224_createctx
hmac_link.c:hmacsha256_createctx
Line
Count
Source
57
31
              dst_context_t *dctx) {       \
58
31
    return (hmac_createctx(ISC_MD_##alg, key, dctx));              \
59
31
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacsha384_createctx
Unexecuted instantiation: hmac_link.c:hmacsha512_createctx
60
31
  static void hmac##alg##_destroyctx(dst_context_t *dctx) {              \
61
31
    hmac_destroyctx(dctx);                                         \
62
31
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_destroyctx
Unexecuted instantiation: hmac_link.c:hmacsha1_destroyctx
Unexecuted instantiation: hmac_link.c:hmacsha224_destroyctx
hmac_link.c:hmacsha256_destroyctx
Line
Count
Source
60
31
  static void hmac##alg##_destroyctx(dst_context_t *dctx) {              \
61
31
    hmac_destroyctx(dctx);                                         \
62
31
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacsha384_destroyctx
Unexecuted instantiation: hmac_link.c:hmacsha512_destroyctx
63
  static isc_result_t hmac##alg##_adddata(dst_context_t *dctx,           \
64
215
            const isc_region_t *data) {    \
65
215
    return (hmac_adddata(dctx, data));                             \
66
215
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_adddata
Unexecuted instantiation: hmac_link.c:hmacsha1_adddata
Unexecuted instantiation: hmac_link.c:hmacsha224_adddata
hmac_link.c:hmacsha256_adddata
Line
Count
Source
64
215
            const isc_region_t *data) {    \
65
215
    return (hmac_adddata(dctx, data));                             \
66
215
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacsha384_adddata
Unexecuted instantiation: hmac_link.c:hmacsha512_adddata
67
  static isc_result_t hmac##alg##_sign(dst_context_t *dctx,              \
68
0
               isc_buffer_t *sig) {              \
69
0
    return (hmac_sign(dctx, sig));                                 \
70
0
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_sign
Unexecuted instantiation: hmac_link.c:hmacsha1_sign
Unexecuted instantiation: hmac_link.c:hmacsha224_sign
Unexecuted instantiation: hmac_link.c:hmacsha256_sign
Unexecuted instantiation: hmac_link.c:hmacsha384_sign
Unexecuted instantiation: hmac_link.c:hmacsha512_sign
71
  static isc_result_t hmac##alg##_verify(dst_context_t *dctx,            \
72
31
                 const isc_region_t *sig) {      \
73
31
    return (hmac_verify(dctx, sig));                               \
74
31
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_verify
Unexecuted instantiation: hmac_link.c:hmacsha1_verify
Unexecuted instantiation: hmac_link.c:hmacsha224_verify
hmac_link.c:hmacsha256_verify
Line
Count
Source
72
31
                 const isc_region_t *sig) {      \
73
31
    return (hmac_verify(dctx, sig));                               \
74
31
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacsha384_verify
Unexecuted instantiation: hmac_link.c:hmacsha512_verify
75
  static bool hmac##alg##_compare(const dst_key_t *key1,                 \
76
0
          const dst_key_t *key2) {               \
77
0
    return (hmac_compare(ISC_MD_##alg, key1, key2));               \
78
0
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_compare
Unexecuted instantiation: hmac_link.c:hmacsha1_compare
Unexecuted instantiation: hmac_link.c:hmacsha224_compare
Unexecuted instantiation: hmac_link.c:hmacsha256_compare
Unexecuted instantiation: hmac_link.c:hmacsha384_compare
Unexecuted instantiation: hmac_link.c:hmacsha512_compare
79
  static isc_result_t hmac##alg##_generate(                              \
80
0
    dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {  \
81
0
    UNUSED(pseudorandom_ok);                                       \
82
0
    UNUSED(callback);                                              \
83
0
    return (hmac_generate(ISC_MD_##alg, key));                     \
84
0
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_generate
Unexecuted instantiation: hmac_link.c:hmacsha1_generate
Unexecuted instantiation: hmac_link.c:hmacsha224_generate
Unexecuted instantiation: hmac_link.c:hmacsha256_generate
Unexecuted instantiation: hmac_link.c:hmacsha384_generate
Unexecuted instantiation: hmac_link.c:hmacsha512_generate
85
0
  static bool hmac##alg##_isprivate(const dst_key_t *key) {              \
86
0
    return (hmac_isprivate(key));                                  \
87
0
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_isprivate
Unexecuted instantiation: hmac_link.c:hmacsha1_isprivate
Unexecuted instantiation: hmac_link.c:hmacsha224_isprivate
Unexecuted instantiation: hmac_link.c:hmacsha256_isprivate
Unexecuted instantiation: hmac_link.c:hmacsha384_isprivate
Unexecuted instantiation: hmac_link.c:hmacsha512_isprivate
88
0
  static void hmac##alg##_destroy(dst_key_t *key) { hmac_destroy(key); } \
Unexecuted instantiation: hmac_link.c:hmacmd5_destroy
Unexecuted instantiation: hmac_link.c:hmacsha1_destroy
Unexecuted instantiation: hmac_link.c:hmacsha224_destroy
Unexecuted instantiation: hmac_link.c:hmacsha256_destroy
Unexecuted instantiation: hmac_link.c:hmacsha384_destroy
Unexecuted instantiation: hmac_link.c:hmacsha512_destroy
89
  static isc_result_t hmac##alg##_todns(const dst_key_t *key,            \
90
2
                isc_buffer_t *data) {            \
91
2
    return (hmac_todns(key, data));                                \
92
2
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_todns
Unexecuted instantiation: hmac_link.c:hmacsha1_todns
Unexecuted instantiation: hmac_link.c:hmacsha224_todns
hmac_link.c:hmacsha256_todns
Line
Count
Source
90
2
                isc_buffer_t *data) {            \
91
2
    return (hmac_todns(key, data));                                \
92
2
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacsha384_todns
Unexecuted instantiation: hmac_link.c:hmacsha512_todns
93
  static isc_result_t hmac##alg##_fromdns(dst_key_t *key,                \
94
2
            isc_buffer_t *data) {          \
95
2
    return (hmac_fromdns(ISC_MD_##alg, key, data));                \
96
2
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_fromdns
Unexecuted instantiation: hmac_link.c:hmacsha1_fromdns
Unexecuted instantiation: hmac_link.c:hmacsha224_fromdns
hmac_link.c:hmacsha256_fromdns
Line
Count
Source
94
2
            isc_buffer_t *data) {          \
95
2
    return (hmac_fromdns(ISC_MD_##alg, key, data));                \
96
2
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacsha384_fromdns
Unexecuted instantiation: hmac_link.c:hmacsha512_fromdns
97
  static isc_result_t hmac##alg##_tofile(const dst_key_t *key,           \
98
0
                 const char *directory) {        \
99
0
    return (hmac_tofile(ISC_MD_##alg, key, directory));            \
100
0
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_tofile
Unexecuted instantiation: hmac_link.c:hmacsha1_tofile
Unexecuted instantiation: hmac_link.c:hmacsha224_tofile
Unexecuted instantiation: hmac_link.c:hmacsha256_tofile
Unexecuted instantiation: hmac_link.c:hmacsha384_tofile
Unexecuted instantiation: hmac_link.c:hmacsha512_tofile
101
  static isc_result_t hmac##alg##_parse(                                 \
102
0
    dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {            \
103
0
    const char *file = isc_lex_getsourcename(lexer);               \
104
0
    isc_result_t result;                                           \
105
0
    result = hmac_parse(ISC_MD_##alg, key, lexer, pub);            \
106
0
    if (result == ISC_R_SUCCESS && file != NULL) {                 \
107
0
      isc_log_write(DNS_LOGCATEGORY_GENERAL,                 \
108
0
              DNS_LOGMODULE_CRYPTO, ISC_LOG_WARNING,   \
109
0
              "%s: Use of K* file pairs for HMAC is "  \
110
0
              "deprecated\n",                          \
111
0
              file);                                   \
112
0
    }                                                              \
113
0
    return (result);                                               \
114
0
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacmd5_parse
Unexecuted instantiation: hmac_link.c:hmacsha1_parse
Unexecuted instantiation: hmac_link.c:hmacsha224_parse
Unexecuted instantiation: hmac_link.c:hmacsha256_parse
Unexecuted instantiation: hmac_link.c:hmacsha384_parse
Unexecuted instantiation: hmac_link.c:hmacsha512_parse
115
  static dst_func_t hmac##alg##_functions = {                            \
116
    .createctx = hmac##alg##_createctx,                            \
117
    .destroyctx = hmac##alg##_destroyctx,                          \
118
    .adddata = hmac##alg##_adddata,                                \
119
    .sign = hmac##alg##_sign,                                      \
120
    .verify = hmac##alg##_verify,                                  \
121
    .compare = hmac##alg##_compare,                                \
122
    .generate = hmac##alg##_generate,                              \
123
    .isprivate = hmac##alg##_isprivate,                            \
124
    .destroy = hmac##alg##_destroy,                                \
125
    .todns = hmac##alg##_todns,                                    \
126
    .fromdns = hmac##alg##_fromdns,                                \
127
    .tofile = hmac##alg##_tofile,                                  \
128
    .parse = hmac##alg##_parse,                                    \
129
  };                                                                     \
130
132
  void dst__hmac##alg##_init(dst_func_t **funcp) {                       \
131
132
    REQUIRE(funcp != NULL);                                        \
132
132
    if (*funcp == NULL) {                                          \
133
132
      isc_hmac_t *ctx = isc_hmac_new();                      \
134
132
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
135
132
          ISC_R_SUCCESS)                                     \
136
132
      {                                                      \
137
132
        *funcp = &hmac##alg##_functions;               \
138
132
      }                                                      \
139
132
      isc_hmac_free(ctx);                                    \
140
132
    }                                                              \
141
132
  }
dst__hmacmd5_init
Line
Count
Source
130
22
  void dst__hmac##alg##_init(dst_func_t **funcp) {                       \
131
22
    REQUIRE(funcp != NULL);                                        \
132
22
    if (*funcp == NULL) {                                          \
133
22
      isc_hmac_t *ctx = isc_hmac_new();                      \
134
22
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
135
22
          ISC_R_SUCCESS)                                     \
136
22
      {                                                      \
137
22
        *funcp = &hmac##alg##_functions;               \
138
22
      }                                                      \
139
22
      isc_hmac_free(ctx);                                    \
140
22
    }                                                              \
141
22
  }
dst__hmacsha1_init
Line
Count
Source
130
22
  void dst__hmac##alg##_init(dst_func_t **funcp) {                       \
131
22
    REQUIRE(funcp != NULL);                                        \
132
22
    if (*funcp == NULL) {                                          \
133
22
      isc_hmac_t *ctx = isc_hmac_new();                      \
134
22
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
135
22
          ISC_R_SUCCESS)                                     \
136
22
      {                                                      \
137
22
        *funcp = &hmac##alg##_functions;               \
138
22
      }                                                      \
139
22
      isc_hmac_free(ctx);                                    \
140
22
    }                                                              \
141
22
  }
dst__hmacsha224_init
Line
Count
Source
130
22
  void dst__hmac##alg##_init(dst_func_t **funcp) {                       \
131
22
    REQUIRE(funcp != NULL);                                        \
132
22
    if (*funcp == NULL) {                                          \
133
22
      isc_hmac_t *ctx = isc_hmac_new();                      \
134
22
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
135
22
          ISC_R_SUCCESS)                                     \
136
22
      {                                                      \
137
22
        *funcp = &hmac##alg##_functions;               \
138
22
      }                                                      \
139
22
      isc_hmac_free(ctx);                                    \
140
22
    }                                                              \
141
22
  }
dst__hmacsha256_init
Line
Count
Source
130
22
  void dst__hmac##alg##_init(dst_func_t **funcp) {                       \
131
22
    REQUIRE(funcp != NULL);                                        \
132
22
    if (*funcp == NULL) {                                          \
133
22
      isc_hmac_t *ctx = isc_hmac_new();                      \
134
22
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
135
22
          ISC_R_SUCCESS)                                     \
136
22
      {                                                      \
137
22
        *funcp = &hmac##alg##_functions;               \
138
22
      }                                                      \
139
22
      isc_hmac_free(ctx);                                    \
140
22
    }                                                              \
141
22
  }
dst__hmacsha384_init
Line
Count
Source
130
22
  void dst__hmac##alg##_init(dst_func_t **funcp) {                       \
131
22
    REQUIRE(funcp != NULL);                                        \
132
22
    if (*funcp == NULL) {                                          \
133
22
      isc_hmac_t *ctx = isc_hmac_new();                      \
134
22
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
135
22
          ISC_R_SUCCESS)                                     \
136
22
      {                                                      \
137
22
        *funcp = &hmac##alg##_functions;               \
138
22
      }                                                      \
139
22
      isc_hmac_free(ctx);                                    \
140
22
    }                                                              \
141
22
  }
dst__hmacsha512_init
Line
Count
Source
130
22
  void dst__hmac##alg##_init(dst_func_t **funcp) {                       \
131
22
    REQUIRE(funcp != NULL);                                        \
132
22
    if (*funcp == NULL) {                                          \
133
22
      isc_hmac_t *ctx = isc_hmac_new();                      \
134
22
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
135
22
          ISC_R_SUCCESS)                                     \
136
22
      {                                                      \
137
22
        *funcp = &hmac##alg##_functions;               \
138
22
      }                                                      \
139
22
      isc_hmac_free(ctx);                                    \
140
22
    }                                                              \
141
22
  }
142
143
static isc_result_t
144
hmac_fromdns(const isc_md_type_t *type, dst_key_t *key, isc_buffer_t *data);
145
146
struct dst_hmac_key {
147
  uint8_t key[ISC_MAX_BLOCK_SIZE];
148
};
149
150
static isc_result_t
151
0
getkeybits(dst_key_t *key, struct dst_private_element *element) {
152
0
  uint16_t *bits = (uint16_t *)element->data;
153
154
0
  if (element->length != 2) {
155
0
    return DST_R_INVALIDPRIVATEKEY;
156
0
  }
157
158
0
  key->key_bits = ntohs(*bits);
159
160
0
  return ISC_R_SUCCESS;
161
0
}
162
163
static isc_result_t
164
hmac_createctx(const isc_md_type_t *type, const dst_key_t *key,
165
31
         dst_context_t *dctx) {
166
31
  isc_result_t result;
167
31
  const dst_hmac_key_t *hkey = key->keydata.hmac_key;
168
31
  isc_hmac_t *ctx = isc_hmac_new(); /* Either returns or abort()s */
169
170
31
  result = isc_hmac_init(ctx, hkey->key, isc_md_type_get_block_size(type),
171
31
             type);
172
31
  if (result != ISC_R_SUCCESS) {
173
0
    isc_hmac_free(ctx);
174
0
    return DST_R_UNSUPPORTEDALG;
175
0
  }
176
177
31
  dctx->ctxdata.hmac_ctx = ctx;
178
31
  return ISC_R_SUCCESS;
179
31
}
180
181
static void
182
31
hmac_destroyctx(dst_context_t *dctx) {
183
31
  isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
184
31
  REQUIRE(ctx != NULL);
185
186
31
  isc_hmac_free(ctx);
187
31
  dctx->ctxdata.hmac_ctx = NULL;
188
31
}
189
190
static isc_result_t
191
215
hmac_adddata(const dst_context_t *dctx, const isc_region_t *data) {
192
215
  isc_result_t result;
193
215
  isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
194
195
215
  REQUIRE(ctx != NULL);
196
197
215
  result = isc_hmac_update(ctx, data->base, data->length);
198
215
  if (result != ISC_R_SUCCESS) {
199
0
    return DST_R_OPENSSLFAILURE;
200
0
  }
201
202
215
  return ISC_R_SUCCESS;
203
215
}
204
205
static isc_result_t
206
0
hmac_sign(const dst_context_t *dctx, isc_buffer_t *sig) {
207
0
  isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
208
0
  REQUIRE(ctx != NULL);
209
0
  unsigned char digest[ISC_MAX_MD_SIZE];
210
0
  unsigned int digestlen = sizeof(digest);
211
212
0
  if (isc_hmac_final(ctx, digest, &digestlen) != ISC_R_SUCCESS) {
213
0
    return DST_R_OPENSSLFAILURE;
214
0
  }
215
216
0
  if (isc_hmac_reset(ctx) != ISC_R_SUCCESS) {
217
0
    return DST_R_OPENSSLFAILURE;
218
0
  }
219
220
0
  if (isc_buffer_availablelength(sig) < digestlen) {
221
0
    return ISC_R_NOSPACE;
222
0
  }
223
224
0
  isc_buffer_putmem(sig, digest, digestlen);
225
226
0
  return ISC_R_SUCCESS;
227
0
}
228
229
static isc_result_t
230
31
hmac_verify(const dst_context_t *dctx, const isc_region_t *sig) {
231
31
  isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
232
31
  unsigned char digest[ISC_MAX_MD_SIZE];
233
31
  unsigned int digestlen = sizeof(digest);
234
235
31
  REQUIRE(ctx != NULL);
236
237
31
  if (isc_hmac_final(ctx, digest, &digestlen) != ISC_R_SUCCESS) {
238
0
    return DST_R_OPENSSLFAILURE;
239
0
  }
240
241
31
  if (isc_hmac_reset(ctx) != ISC_R_SUCCESS) {
242
0
    return DST_R_OPENSSLFAILURE;
243
0
  }
244
245
31
  if (sig->length > digestlen) {
246
0
    return DST_R_VERIFYFAILURE;
247
0
  }
248
249
31
  return isc_safe_memequal(digest, sig->base, sig->length)
250
31
           ? ISC_R_SUCCESS
251
31
           : DST_R_VERIFYFAILURE;
252
31
}
253
254
static bool
255
hmac_compare(const isc_md_type_t *type, const dst_key_t *key1,
256
0
       const dst_key_t *key2) {
257
0
  dst_hmac_key_t *hkey1, *hkey2;
258
259
0
  hkey1 = key1->keydata.hmac_key;
260
0
  hkey2 = key2->keydata.hmac_key;
261
262
0
  if (hkey1 == NULL && hkey2 == NULL) {
263
0
    return true;
264
0
  } else if (hkey1 == NULL || hkey2 == NULL) {
265
0
    return false;
266
0
  }
267
268
0
  return isc_safe_memequal(hkey1->key, hkey2->key,
269
0
         isc_md_type_get_block_size(type));
270
0
}
271
272
static isc_result_t
273
0
hmac_generate(const isc_md_type_t *type, dst_key_t *key) {
274
0
  isc_buffer_t b;
275
0
  isc_result_t ret;
276
0
  unsigned int bytes, len;
277
0
  unsigned char data[ISC_MAX_MD_SIZE] = { 0 };
278
279
0
  len = isc_md_type_get_block_size(type);
280
281
0
  bytes = (key->key_size + 7) / 8;
282
283
0
  if (bytes > len) {
284
0
    bytes = len;
285
0
    key->key_size = len * 8;
286
0
  }
287
288
0
  isc_nonce_buf(data, bytes);
289
290
0
  isc_buffer_init(&b, data, bytes);
291
0
  isc_buffer_add(&b, bytes);
292
293
0
  ret = hmac_fromdns(type, key, &b);
294
295
0
  isc_safe_memwipe(data, sizeof(data));
296
297
0
  return ret;
298
0
}
299
300
static bool
301
0
hmac_isprivate(const dst_key_t *key) {
302
0
  UNUSED(key);
303
0
  return true;
304
0
}
305
306
static void
307
0
hmac_destroy(dst_key_t *key) {
308
0
  dst_hmac_key_t *hkey = key->keydata.hmac_key;
309
0
  isc_safe_memwipe(hkey, sizeof(*hkey));
310
0
  isc_mem_put(key->mctx, hkey, sizeof(*hkey));
311
0
  key->keydata.hmac_key = NULL;
312
0
}
313
314
static isc_result_t
315
2
hmac_todns(const dst_key_t *key, isc_buffer_t *data) {
316
2
  REQUIRE(key != NULL && key->keydata.hmac_key != NULL);
317
2
  dst_hmac_key_t *hkey = key->keydata.hmac_key;
318
2
  unsigned int bytes;
319
320
2
  bytes = (key->key_size + 7) / 8;
321
2
  if (isc_buffer_availablelength(data) < bytes) {
322
0
    return ISC_R_NOSPACE;
323
0
  }
324
2
  isc_buffer_putmem(data, hkey->key, bytes);
325
326
2
  return ISC_R_SUCCESS;
327
2
}
328
329
static isc_result_t
330
2
hmac_fromdns(const isc_md_type_t *type, dst_key_t *key, isc_buffer_t *data) {
331
2
  dst_hmac_key_t *hkey;
332
2
  unsigned int keylen;
333
2
  isc_region_t r;
334
335
2
  isc_buffer_remainingregion(data, &r);
336
2
  if (r.length == 0) {
337
0
    return ISC_R_SUCCESS;
338
0
  }
339
340
2
  hkey = isc_mem_get(key->mctx, sizeof(dst_hmac_key_t));
341
342
2
  memset(hkey->key, 0, sizeof(hkey->key));
343
344
  /* Hash the key if the key is longer then chosen MD block size */
345
2
  if (r.length > (unsigned int)isc_md_type_get_block_size(type)) {
346
0
    if (isc_md(type, r.base, r.length, hkey->key, &keylen) !=
347
0
        ISC_R_SUCCESS)
348
0
    {
349
0
      isc_mem_put(key->mctx, hkey, sizeof(dst_hmac_key_t));
350
0
      return DST_R_OPENSSLFAILURE;
351
0
    }
352
2
  } else {
353
2
    memmove(hkey->key, r.base, r.length);
354
2
    keylen = r.length;
355
2
  }
356
357
2
  key->key_size = keylen * 8;
358
2
  key->keydata.hmac_key = hkey;
359
360
2
  isc_buffer_forward(data, r.length);
361
362
2
  return ISC_R_SUCCESS;
363
2
}
364
365
static int
366
0
hmac__get_tag_key(const isc_md_type_t *type) {
367
0
  if (type == ISC_MD_MD5) {
368
0
    return TAG_HMACMD5_KEY;
369
0
  } else if (type == ISC_MD_SHA1) {
370
0
    return TAG_HMACSHA1_KEY;
371
0
  } else if (type == ISC_MD_SHA224) {
372
0
    return TAG_HMACSHA224_KEY;
373
0
  } else if (type == ISC_MD_SHA256) {
374
0
    return TAG_HMACSHA256_KEY;
375
0
  } else if (type == ISC_MD_SHA384) {
376
0
    return TAG_HMACSHA384_KEY;
377
0
  } else if (type == ISC_MD_SHA512) {
378
0
    return TAG_HMACSHA512_KEY;
379
0
  } else {
380
0
    UNREACHABLE();
381
0
  }
382
0
}
383
384
static int
385
0
hmac__get_tag_bits(const isc_md_type_t *type) {
386
0
  if (type == ISC_MD_MD5) {
387
0
    return TAG_HMACMD5_BITS;
388
0
  } else if (type == ISC_MD_SHA1) {
389
0
    return TAG_HMACSHA1_BITS;
390
0
  } else if (type == ISC_MD_SHA224) {
391
0
    return TAG_HMACSHA224_BITS;
392
0
  } else if (type == ISC_MD_SHA256) {
393
0
    return TAG_HMACSHA256_BITS;
394
0
  } else if (type == ISC_MD_SHA384) {
395
0
    return TAG_HMACSHA384_BITS;
396
0
  } else if (type == ISC_MD_SHA512) {
397
0
    return TAG_HMACSHA512_BITS;
398
0
  } else {
399
0
    UNREACHABLE();
400
0
  }
401
0
}
402
403
static isc_result_t
404
hmac_tofile(const isc_md_type_t *type, const dst_key_t *key,
405
0
      const char *directory) {
406
0
  dst_hmac_key_t *hkey;
407
0
  dst_private_t priv;
408
0
  int bytes = (key->key_size + 7) / 8;
409
0
  uint16_t bits;
410
411
0
  if (key->keydata.hmac_key == NULL) {
412
0
    return DST_R_NULLKEY;
413
0
  }
414
415
0
  if (key->external) {
416
0
    return DST_R_EXTERNALKEY;
417
0
  }
418
419
0
  hkey = key->keydata.hmac_key;
420
421
0
  priv.elements[0].tag = hmac__get_tag_key(type);
422
0
  priv.elements[0].length = bytes;
423
0
  priv.elements[0].data = hkey->key;
424
425
0
  bits = htons(key->key_bits);
426
427
0
  priv.elements[1].tag = hmac__get_tag_bits(type);
428
0
  priv.elements[1].length = sizeof(bits);
429
0
  priv.elements[1].data = (uint8_t *)&bits;
430
431
0
  priv.nelements = 2;
432
433
0
  return dst__privstruct_writefile(key, &priv, directory);
434
0
}
435
436
static int
437
0
hmac__to_dst_alg(const isc_md_type_t *type) {
438
0
  if (type == ISC_MD_MD5) {
439
0
    return DST_ALG_HMACMD5;
440
0
  } else if (type == ISC_MD_SHA1) {
441
0
    return DST_ALG_HMACSHA1;
442
0
  } else if (type == ISC_MD_SHA224) {
443
0
    return DST_ALG_HMACSHA224;
444
0
  } else if (type == ISC_MD_SHA256) {
445
0
    return DST_ALG_HMACSHA256;
446
0
  } else if (type == ISC_MD_SHA384) {
447
0
    return DST_ALG_HMACSHA384;
448
0
  } else if (type == ISC_MD_SHA512) {
449
0
    return DST_ALG_HMACSHA512;
450
0
  } else {
451
0
    UNREACHABLE();
452
0
  }
453
0
}
454
455
static isc_result_t
456
hmac_parse(const isc_md_type_t *type, dst_key_t *key, isc_lex_t *lexer,
457
0
     dst_key_t *pub) {
458
0
  dst_private_t priv;
459
0
  isc_result_t result, tresult;
460
0
  isc_buffer_t b;
461
0
  isc_mem_t *mctx = key->mctx;
462
0
  unsigned int i;
463
464
0
  UNUSED(pub);
465
  /* read private key file */
466
0
  result = dst__privstruct_parse(key, hmac__to_dst_alg(type), lexer, mctx,
467
0
               &priv);
468
0
  if (result != ISC_R_SUCCESS) {
469
0
    return result;
470
0
  }
471
472
0
  if (key->external) {
473
0
    result = DST_R_EXTERNALKEY;
474
0
  }
475
476
0
  key->key_bits = 0;
477
0
  for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
478
0
    switch (priv.elements[i].tag) {
479
0
    case TAG_HMACMD5_KEY:
480
0
    case TAG_HMACSHA1_KEY:
481
0
    case TAG_HMACSHA224_KEY:
482
0
    case TAG_HMACSHA256_KEY:
483
0
    case TAG_HMACSHA384_KEY:
484
0
    case TAG_HMACSHA512_KEY:
485
0
      isc_buffer_init(&b, priv.elements[i].data,
486
0
          priv.elements[i].length);
487
0
      isc_buffer_add(&b, priv.elements[i].length);
488
0
      tresult = hmac_fromdns(type, key, &b);
489
0
      if (tresult != ISC_R_SUCCESS) {
490
0
        result = tresult;
491
0
      }
492
0
      break;
493
0
    case TAG_HMACMD5_BITS:
494
0
    case TAG_HMACSHA1_BITS:
495
0
    case TAG_HMACSHA224_BITS:
496
0
    case TAG_HMACSHA256_BITS:
497
0
    case TAG_HMACSHA384_BITS:
498
0
    case TAG_HMACSHA512_BITS:
499
0
      tresult = getkeybits(key, &priv.elements[i]);
500
0
      if (tresult != ISC_R_SUCCESS) {
501
0
        result = tresult;
502
0
      }
503
0
      break;
504
0
    default:
505
0
      result = DST_R_INVALIDPRIVATEKEY;
506
0
      break;
507
0
    }
508
0
  }
509
0
  dst__privstruct_free(&priv, mctx);
510
0
  isc_safe_memwipe(&priv, sizeof(priv));
511
0
  return result;
512
0
}
513
514
hmac_register_algorithm(md5);
515
hmac_register_algorithm(sha1);
516
hmac_register_algorithm(sha224);
517
hmac_register_algorithm(sha256);
518
hmac_register_algorithm(sha384);
519
hmac_register_algorithm(sha512);
520
521
/*! \file */