Coverage Report

Created: 2023-12-02 06:37

/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
2
#define ISC_MD_md5    ISC_MD_MD5
49
2
#define ISC_MD_sha1   ISC_MD_SHA1
50
2
#define ISC_MD_sha224 ISC_MD_SHA224
51
43
#define ISC_MD_sha256 ISC_MD_SHA256
52
2
#define ISC_MD_sha384 ISC_MD_SHA384
53
2
#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
39
              dst_context_t *dctx) {       \
58
39
    return (hmac_createctx(ISC_MD_##alg, key, dctx));              \
59
39
  }                                                                      \
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
39
              dst_context_t *dctx) {       \
58
39
    return (hmac_createctx(ISC_MD_##alg, key, dctx));              \
59
39
  }                                                                      \
Unexecuted instantiation: hmac_link.c:hmacsha384_createctx
Unexecuted instantiation: hmac_link.c:hmacsha512_createctx
60
39
  static void hmac##alg##_destroyctx(dst_context_t *dctx) {              \
61
39
    hmac_destroyctx(dctx);                                         \
62
39
  }                                                                      \
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
39
  static void hmac##alg##_destroyctx(dst_context_t *dctx) {              \
61
39
    hmac_destroyctx(dctx);                                         \
62
39
  }                                                                      \
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
264
            const isc_region_t *data) {    \
65
264
    return (hmac_adddata(dctx, data));                             \
66
264
  }                                                                      \
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
264
            const isc_region_t *data) {    \
65
264
    return (hmac_adddata(dctx, data));                             \
66
264
  }                                                                      \
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
39
                 const isc_region_t *sig) {      \
73
39
    return (hmac_verify(dctx, sig));                               \
74
39
  }                                                                      \
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
39
                 const isc_region_t *sig) {      \
73
39
    return (hmac_verify(dctx, sig));                               \
74
39
  }                                                                      \
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_lctx, 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
    hmac##alg##_createctx,                                         \
117
    NULL, /*%< createctx2 */                                       \
118
    hmac##alg##_destroyctx,                                        \
119
    hmac##alg##_adddata,                                           \
120
    hmac##alg##_sign,                                              \
121
    hmac##alg##_verify,                                            \
122
    NULL, /*%< verify2 */                                          \
123
    NULL, /*%< computesecret */                                    \
124
    hmac##alg##_compare,                                           \
125
    NULL, /*%< paramcompare */                                     \
126
    hmac##alg##_generate,                                          \
127
    hmac##alg##_isprivate,                                         \
128
    hmac##alg##_destroy,                                           \
129
    hmac##alg##_todns,                                             \
130
    hmac##alg##_fromdns,                                           \
131
    hmac##alg##_tofile,                                            \
132
    hmac##alg##_parse,                                             \
133
    NULL, /*%< cleanup */                                          \
134
    NULL, /*%< fromlabel */                                        \
135
    NULL, /*%< dump */                                             \
136
    NULL, /*%< restore */                                          \
137
  };                                                                     \
138
12
  isc_result_t dst__hmac##alg##_init(dst_func_t **funcp) {               \
139
12
    REQUIRE(funcp != NULL);                                        \
140
12
    if (*funcp == NULL) {                                          \
141
12
      isc_hmac_t *ctx = isc_hmac_new();                      \
142
12
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
143
12
          ISC_R_SUCCESS)                                     \
144
12
      {                                                      \
145
12
        *funcp = &hmac##alg##_functions;               \
146
12
      }                                                      \
147
12
      isc_hmac_free(ctx);                                    \
148
12
    }                                                              \
149
12
    return (ISC_R_SUCCESS);                                        \
150
12
  }
dst__hmacmd5_init
Line
Count
Source
138
2
  isc_result_t dst__hmac##alg##_init(dst_func_t **funcp) {               \
139
2
    REQUIRE(funcp != NULL);                                        \
140
2
    if (*funcp == NULL) {                                          \
141
2
      isc_hmac_t *ctx = isc_hmac_new();                      \
142
2
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
143
2
          ISC_R_SUCCESS)                                     \
144
2
      {                                                      \
145
2
        *funcp = &hmac##alg##_functions;               \
146
2
      }                                                      \
147
2
      isc_hmac_free(ctx);                                    \
148
2
    }                                                              \
149
2
    return (ISC_R_SUCCESS);                                        \
150
2
  }
dst__hmacsha1_init
Line
Count
Source
138
2
  isc_result_t dst__hmac##alg##_init(dst_func_t **funcp) {               \
139
2
    REQUIRE(funcp != NULL);                                        \
140
2
    if (*funcp == NULL) {                                          \
141
2
      isc_hmac_t *ctx = isc_hmac_new();                      \
142
2
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
143
2
          ISC_R_SUCCESS)                                     \
144
2
      {                                                      \
145
2
        *funcp = &hmac##alg##_functions;               \
146
2
      }                                                      \
147
2
      isc_hmac_free(ctx);                                    \
148
2
    }                                                              \
149
2
    return (ISC_R_SUCCESS);                                        \
150
2
  }
dst__hmacsha224_init
Line
Count
Source
138
2
  isc_result_t dst__hmac##alg##_init(dst_func_t **funcp) {               \
139
2
    REQUIRE(funcp != NULL);                                        \
140
2
    if (*funcp == NULL) {                                          \
141
2
      isc_hmac_t *ctx = isc_hmac_new();                      \
142
2
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
143
2
          ISC_R_SUCCESS)                                     \
144
2
      {                                                      \
145
2
        *funcp = &hmac##alg##_functions;               \
146
2
      }                                                      \
147
2
      isc_hmac_free(ctx);                                    \
148
2
    }                                                              \
149
2
    return (ISC_R_SUCCESS);                                        \
150
2
  }
dst__hmacsha256_init
Line
Count
Source
138
2
  isc_result_t dst__hmac##alg##_init(dst_func_t **funcp) {               \
139
2
    REQUIRE(funcp != NULL);                                        \
140
2
    if (*funcp == NULL) {                                          \
141
2
      isc_hmac_t *ctx = isc_hmac_new();                      \
142
2
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
143
2
          ISC_R_SUCCESS)                                     \
144
2
      {                                                      \
145
2
        *funcp = &hmac##alg##_functions;               \
146
2
      }                                                      \
147
2
      isc_hmac_free(ctx);                                    \
148
2
    }                                                              \
149
2
    return (ISC_R_SUCCESS);                                        \
150
2
  }
dst__hmacsha384_init
Line
Count
Source
138
2
  isc_result_t dst__hmac##alg##_init(dst_func_t **funcp) {               \
139
2
    REQUIRE(funcp != NULL);                                        \
140
2
    if (*funcp == NULL) {                                          \
141
2
      isc_hmac_t *ctx = isc_hmac_new();                      \
142
2
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
143
2
          ISC_R_SUCCESS)                                     \
144
2
      {                                                      \
145
2
        *funcp = &hmac##alg##_functions;               \
146
2
      }                                                      \
147
2
      isc_hmac_free(ctx);                                    \
148
2
    }                                                              \
149
2
    return (ISC_R_SUCCESS);                                        \
150
2
  }
dst__hmacsha512_init
Line
Count
Source
138
2
  isc_result_t dst__hmac##alg##_init(dst_func_t **funcp) {               \
139
2
    REQUIRE(funcp != NULL);                                        \
140
2
    if (*funcp == NULL) {                                          \
141
2
      isc_hmac_t *ctx = isc_hmac_new();                      \
142
2
      if (isc_hmac_init(ctx, "test", 4, ISC_MD_##alg) ==     \
143
2
          ISC_R_SUCCESS)                                     \
144
2
      {                                                      \
145
2
        *funcp = &hmac##alg##_functions;               \
146
2
      }                                                      \
147
2
      isc_hmac_free(ctx);                                    \
148
2
    }                                                              \
149
2
    return (ISC_R_SUCCESS);                                        \
150
2
  }
151
152
static isc_result_t
153
hmac_fromdns(const isc_md_type_t *type, dst_key_t *key, isc_buffer_t *data);
154
155
struct dst_hmac_key {
156
  uint8_t key[ISC_MAX_BLOCK_SIZE];
157
};
158
159
static isc_result_t
160
0
getkeybits(dst_key_t *key, struct dst_private_element *element) {
161
0
  uint16_t *bits = (uint16_t *)element->data;
162
163
0
  if (element->length != 2) {
164
0
    return (DST_R_INVALIDPRIVATEKEY);
165
0
  }
166
167
0
  key->key_bits = ntohs(*bits);
168
169
0
  return (ISC_R_SUCCESS);
170
0
}
171
172
static isc_result_t
173
hmac_createctx(const isc_md_type_t *type, const dst_key_t *key,
174
39
         dst_context_t *dctx) {
175
39
  isc_result_t result;
176
39
  const dst_hmac_key_t *hkey = key->keydata.hmac_key;
177
39
  isc_hmac_t *ctx = isc_hmac_new(); /* Either returns or abort()s */
178
179
39
  result = isc_hmac_init(ctx, hkey->key, isc_md_type_get_block_size(type),
180
39
             type);
181
39
  if (result != ISC_R_SUCCESS) {
182
0
    isc_hmac_free(ctx);
183
0
    return (DST_R_UNSUPPORTEDALG);
184
0
  }
185
186
39
  dctx->ctxdata.hmac_ctx = ctx;
187
39
  return (ISC_R_SUCCESS);
188
39
}
189
190
static void
191
39
hmac_destroyctx(dst_context_t *dctx) {
192
39
  isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
193
39
  REQUIRE(ctx != NULL);
194
195
39
  isc_hmac_free(ctx);
196
39
  dctx->ctxdata.hmac_ctx = NULL;
197
39
}
198
199
static isc_result_t
200
264
hmac_adddata(const dst_context_t *dctx, const isc_region_t *data) {
201
264
  isc_result_t result;
202
264
  isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
203
204
264
  REQUIRE(ctx != NULL);
205
206
264
  result = isc_hmac_update(ctx, data->base, data->length);
207
264
  if (result != ISC_R_SUCCESS) {
208
0
    return (DST_R_OPENSSLFAILURE);
209
0
  }
210
211
264
  return (ISC_R_SUCCESS);
212
264
}
213
214
static isc_result_t
215
0
hmac_sign(const dst_context_t *dctx, isc_buffer_t *sig) {
216
0
  isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
217
0
  REQUIRE(ctx != NULL);
218
0
  unsigned char digest[ISC_MAX_MD_SIZE];
219
0
  unsigned int digestlen = sizeof(digest);
220
221
0
  if (isc_hmac_final(ctx, digest, &digestlen) != ISC_R_SUCCESS) {
222
0
    return (DST_R_OPENSSLFAILURE);
223
0
  }
224
225
0
  if (isc_hmac_reset(ctx) != ISC_R_SUCCESS) {
226
0
    return (DST_R_OPENSSLFAILURE);
227
0
  }
228
229
0
  if (isc_buffer_availablelength(sig) < digestlen) {
230
0
    return (ISC_R_NOSPACE);
231
0
  }
232
233
0
  isc_buffer_putmem(sig, digest, digestlen);
234
235
0
  return (ISC_R_SUCCESS);
236
0
}
237
238
static isc_result_t
239
39
hmac_verify(const dst_context_t *dctx, const isc_region_t *sig) {
240
39
  isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
241
39
  unsigned char digest[ISC_MAX_MD_SIZE];
242
39
  unsigned int digestlen = sizeof(digest);
243
244
39
  REQUIRE(ctx != NULL);
245
246
39
  if (isc_hmac_final(ctx, digest, &digestlen) != ISC_R_SUCCESS) {
247
0
    return (DST_R_OPENSSLFAILURE);
248
0
  }
249
250
39
  if (isc_hmac_reset(ctx) != ISC_R_SUCCESS) {
251
0
    return (DST_R_OPENSSLFAILURE);
252
0
  }
253
254
39
  if (sig->length > digestlen) {
255
0
    return (DST_R_VERIFYFAILURE);
256
0
  }
257
258
39
  return (isc_safe_memequal(digest, sig->base, sig->length)
259
39
      ? ISC_R_SUCCESS
260
39
      : DST_R_VERIFYFAILURE);
261
39
}
262
263
static bool
264
hmac_compare(const isc_md_type_t *type, const dst_key_t *key1,
265
0
       const dst_key_t *key2) {
266
0
  dst_hmac_key_t *hkey1, *hkey2;
267
268
0
  hkey1 = key1->keydata.hmac_key;
269
0
  hkey2 = key2->keydata.hmac_key;
270
271
0
  if (hkey1 == NULL && hkey2 == NULL) {
272
0
    return (true);
273
0
  } else if (hkey1 == NULL || hkey2 == NULL) {
274
0
    return (false);
275
0
  }
276
277
0
  return (isc_safe_memequal(hkey1->key, hkey2->key,
278
0
          isc_md_type_get_block_size(type)));
279
0
}
280
281
static isc_result_t
282
0
hmac_generate(const isc_md_type_t *type, dst_key_t *key) {
283
0
  isc_buffer_t b;
284
0
  isc_result_t ret;
285
0
  unsigned int bytes, len;
286
0
  unsigned char data[ISC_MAX_MD_SIZE] = { 0 };
287
288
0
  len = isc_md_type_get_block_size(type);
289
290
0
  bytes = (key->key_size + 7) / 8;
291
292
0
  if (bytes > len) {
293
0
    bytes = len;
294
0
    key->key_size = len * 8;
295
0
  }
296
297
0
  isc_nonce_buf(data, bytes);
298
299
0
  isc_buffer_init(&b, data, bytes);
300
0
  isc_buffer_add(&b, bytes);
301
302
0
  ret = hmac_fromdns(type, key, &b);
303
304
0
  isc_safe_memwipe(data, sizeof(data));
305
306
0
  return (ret);
307
0
}
308
309
static bool
310
0
hmac_isprivate(const dst_key_t *key) {
311
0
  UNUSED(key);
312
0
  return (true);
313
0
}
314
315
static void
316
0
hmac_destroy(dst_key_t *key) {
317
0
  dst_hmac_key_t *hkey = key->keydata.hmac_key;
318
0
  isc_safe_memwipe(hkey, sizeof(*hkey));
319
0
  isc_mem_put(key->mctx, hkey, sizeof(*hkey));
320
0
  key->keydata.hmac_key = NULL;
321
0
}
322
323
static isc_result_t
324
2
hmac_todns(const dst_key_t *key, isc_buffer_t *data) {
325
2
  REQUIRE(key != NULL && key->keydata.hmac_key != NULL);
326
2
  dst_hmac_key_t *hkey = key->keydata.hmac_key;
327
2
  unsigned int bytes;
328
329
2
  bytes = (key->key_size + 7) / 8;
330
2
  if (isc_buffer_availablelength(data) < bytes) {
331
0
    return (ISC_R_NOSPACE);
332
0
  }
333
2
  isc_buffer_putmem(data, hkey->key, bytes);
334
335
2
  return (ISC_R_SUCCESS);
336
2
}
337
338
static isc_result_t
339
2
hmac_fromdns(const isc_md_type_t *type, dst_key_t *key, isc_buffer_t *data) {
340
2
  dst_hmac_key_t *hkey;
341
2
  unsigned int keylen;
342
2
  isc_region_t r;
343
344
2
  isc_buffer_remainingregion(data, &r);
345
2
  if (r.length == 0) {
346
0
    return (ISC_R_SUCCESS);
347
0
  }
348
349
2
  hkey = isc_mem_get(key->mctx, sizeof(dst_hmac_key_t));
350
351
2
  memset(hkey->key, 0, sizeof(hkey->key));
352
353
  /* Hash the key if the key is longer then chosen MD block size */
354
2
  if (r.length > (unsigned int)isc_md_type_get_block_size(type)) {
355
0
    if (isc_md(type, r.base, r.length, hkey->key, &keylen) !=
356
0
        ISC_R_SUCCESS)
357
0
    {
358
0
      isc_mem_put(key->mctx, hkey, sizeof(dst_hmac_key_t));
359
0
      return (DST_R_OPENSSLFAILURE);
360
0
    }
361
2
  } else {
362
2
    memmove(hkey->key, r.base, r.length);
363
2
    keylen = r.length;
364
2
  }
365
366
2
  key->key_size = keylen * 8;
367
2
  key->keydata.hmac_key = hkey;
368
369
2
  isc_buffer_forward(data, r.length);
370
371
2
  return (ISC_R_SUCCESS);
372
2
}
373
374
static int
375
0
hmac__get_tag_key(const isc_md_type_t *type) {
376
0
  if (type == ISC_MD_MD5) {
377
0
    return (TAG_HMACMD5_KEY);
378
0
  } else if (type == ISC_MD_SHA1) {
379
0
    return (TAG_HMACSHA1_KEY);
380
0
  } else if (type == ISC_MD_SHA224) {
381
0
    return (TAG_HMACSHA224_KEY);
382
0
  } else if (type == ISC_MD_SHA256) {
383
0
    return (TAG_HMACSHA256_KEY);
384
0
  } else if (type == ISC_MD_SHA384) {
385
0
    return (TAG_HMACSHA384_KEY);
386
0
  } else if (type == ISC_MD_SHA512) {
387
0
    return (TAG_HMACSHA512_KEY);
388
0
  } else {
389
0
    UNREACHABLE();
390
0
  }
391
0
}
392
393
static int
394
0
hmac__get_tag_bits(const isc_md_type_t *type) {
395
0
  if (type == ISC_MD_MD5) {
396
0
    return (TAG_HMACMD5_BITS);
397
0
  } else if (type == ISC_MD_SHA1) {
398
0
    return (TAG_HMACSHA1_BITS);
399
0
  } else if (type == ISC_MD_SHA224) {
400
0
    return (TAG_HMACSHA224_BITS);
401
0
  } else if (type == ISC_MD_SHA256) {
402
0
    return (TAG_HMACSHA256_BITS);
403
0
  } else if (type == ISC_MD_SHA384) {
404
0
    return (TAG_HMACSHA384_BITS);
405
0
  } else if (type == ISC_MD_SHA512) {
406
0
    return (TAG_HMACSHA512_BITS);
407
0
  } else {
408
0
    UNREACHABLE();
409
0
  }
410
0
}
411
412
static isc_result_t
413
hmac_tofile(const isc_md_type_t *type, const dst_key_t *key,
414
0
      const char *directory) {
415
0
  dst_hmac_key_t *hkey;
416
0
  dst_private_t priv;
417
0
  int bytes = (key->key_size + 7) / 8;
418
0
  uint16_t bits;
419
420
0
  if (key->keydata.hmac_key == NULL) {
421
0
    return (DST_R_NULLKEY);
422
0
  }
423
424
0
  if (key->external) {
425
0
    return (DST_R_EXTERNALKEY);
426
0
  }
427
428
0
  hkey = key->keydata.hmac_key;
429
430
0
  priv.elements[0].tag = hmac__get_tag_key(type);
431
0
  priv.elements[0].length = bytes;
432
0
  priv.elements[0].data = hkey->key;
433
434
0
  bits = htons(key->key_bits);
435
436
0
  priv.elements[1].tag = hmac__get_tag_bits(type);
437
0
  priv.elements[1].length = sizeof(bits);
438
0
  priv.elements[1].data = (uint8_t *)&bits;
439
440
0
  priv.nelements = 2;
441
442
0
  return (dst__privstruct_writefile(key, &priv, directory));
443
0
}
444
445
static int
446
0
hmac__to_dst_alg(const isc_md_type_t *type) {
447
0
  if (type == ISC_MD_MD5) {
448
0
    return (DST_ALG_HMACMD5);
449
0
  } else if (type == ISC_MD_SHA1) {
450
0
    return (DST_ALG_HMACSHA1);
451
0
  } else if (type == ISC_MD_SHA224) {
452
0
    return (DST_ALG_HMACSHA224);
453
0
  } else if (type == ISC_MD_SHA256) {
454
0
    return (DST_ALG_HMACSHA256);
455
0
  } else if (type == ISC_MD_SHA384) {
456
0
    return (DST_ALG_HMACSHA384);
457
0
  } else if (type == ISC_MD_SHA512) {
458
0
    return (DST_ALG_HMACSHA512);
459
0
  } else {
460
0
    UNREACHABLE();
461
0
  }
462
0
}
463
464
static isc_result_t
465
hmac_parse(const isc_md_type_t *type, dst_key_t *key, isc_lex_t *lexer,
466
0
     dst_key_t *pub) {
467
0
  dst_private_t priv;
468
0
  isc_result_t result, tresult;
469
0
  isc_buffer_t b;
470
0
  isc_mem_t *mctx = key->mctx;
471
0
  unsigned int i;
472
473
0
  UNUSED(pub);
474
  /* read private key file */
475
0
  result = dst__privstruct_parse(key, hmac__to_dst_alg(type), lexer, mctx,
476
0
               &priv);
477
0
  if (result != ISC_R_SUCCESS) {
478
0
    return (result);
479
0
  }
480
481
0
  if (key->external) {
482
0
    result = DST_R_EXTERNALKEY;
483
0
  }
484
485
0
  key->key_bits = 0;
486
0
  for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
487
0
    switch (priv.elements[i].tag) {
488
0
    case TAG_HMACMD5_KEY:
489
0
    case TAG_HMACSHA1_KEY:
490
0
    case TAG_HMACSHA224_KEY:
491
0
    case TAG_HMACSHA256_KEY:
492
0
    case TAG_HMACSHA384_KEY:
493
0
    case TAG_HMACSHA512_KEY:
494
0
      isc_buffer_init(&b, priv.elements[i].data,
495
0
          priv.elements[i].length);
496
0
      isc_buffer_add(&b, priv.elements[i].length);
497
0
      tresult = hmac_fromdns(type, key, &b);
498
0
      if (tresult != ISC_R_SUCCESS) {
499
0
        result = tresult;
500
0
      }
501
0
      break;
502
0
    case TAG_HMACMD5_BITS:
503
0
    case TAG_HMACSHA1_BITS:
504
0
    case TAG_HMACSHA224_BITS:
505
0
    case TAG_HMACSHA256_BITS:
506
0
    case TAG_HMACSHA384_BITS:
507
0
    case TAG_HMACSHA512_BITS:
508
0
      tresult = getkeybits(key, &priv.elements[i]);
509
0
      if (tresult != ISC_R_SUCCESS) {
510
0
        result = tresult;
511
0
      }
512
0
      break;
513
0
    default:
514
0
      result = DST_R_INVALIDPRIVATEKEY;
515
0
      break;
516
0
    }
517
0
  }
518
0
  dst__privstruct_free(&priv, mctx);
519
0
  isc_safe_memwipe(&priv, sizeof(priv));
520
0
  return (result);
521
0
}
522
523
hmac_register_algorithm(md5);
524
hmac_register_algorithm(sha1);
525
hmac_register_algorithm(sha224);
526
hmac_register_algorithm(sha256);
527
hmac_register_algorithm(sha384);
528
hmac_register_algorithm(sha512);
529
530
/*! \file */