1999-07-12 20:08:42 +00:00
|
|
|
/*
|
2018-03-15 18:32:45 -07:00
|
|
|
* Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2007-06-18 23:47:57 +00:00
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
2007-06-18 23:47:57 +00:00
|
|
|
*
|
2018-02-23 09:53:12 +01:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
|
|
|
*
|
|
|
|
* Portions Copyright (C) Network Associates, Inc.
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2007-08-28 07:20:43 +00:00
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
1999-07-12 20:08:42 +00:00
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2004-03-05 05:14:21 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
|
|
|
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
|
|
|
|
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
|
|
|
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
1999-07-12 20:08:42 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2018-10-25 20:52:24 +02:00
|
|
|
#ifndef WIN32
|
2018-03-20 17:20:50 +00:00
|
|
|
#include <arpa/inet.h>
|
2018-10-25 20:52:24 +02:00
|
|
|
#endif /* WIN32 */
|
2018-04-17 08:29:14 -07:00
|
|
|
|
2000-07-18 18:15:27 +00:00
|
|
|
#include <isc/buffer.h>
|
2018-03-20 17:20:50 +00:00
|
|
|
#include <isc/hmac.h>
|
|
|
|
#include <isc/md.h>
|
2018-05-28 15:22:23 +02:00
|
|
|
#include <isc/nonce.h>
|
2018-04-22 14:56:28 +02:00
|
|
|
#include <isc/random.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/mem.h>
|
2013-07-09 11:47:16 -07:00
|
|
|
#include <isc/safe.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/string.h>
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2016-08-19 08:02:51 +10:00
|
|
|
#include <pk11/site.h>
|
|
|
|
|
2000-05-02 03:54:17 +00:00
|
|
|
#include <dst/result.h>
|
|
|
|
|
1999-07-12 20:08:42 +00:00
|
|
|
#include "dst_internal.h"
|
2018-01-30 15:21:02 +11:00
|
|
|
#ifdef HAVE_FIPS_MODE
|
|
|
|
#include "dst_openssl.h" /* FIPS_mode() prototype */
|
|
|
|
#endif
|
1999-07-12 20:08:42 +00:00
|
|
|
#include "dst_parse.h"
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
#define ISC_MD_md5 ISC_MD_MD5
|
|
|
|
#define ISC_MD_sha1 ISC_MD_SHA1
|
|
|
|
#define ISC_MD_sha224 ISC_MD_SHA224
|
|
|
|
#define ISC_MD_sha256 ISC_MD_SHA256
|
|
|
|
#define ISC_MD_sha384 ISC_MD_SHA384
|
|
|
|
#define ISC_MD_sha512 ISC_MD_SHA512
|
|
|
|
|
|
|
|
#define hmac_register_algorithm(alg) \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_createctx(dst_key_t *key, \
|
|
|
|
dst_context_t *dctx) { \
|
|
|
|
return (hmac_createctx(ISC_MD_##alg, key, dctx)); \
|
|
|
|
} \
|
|
|
|
static void \
|
|
|
|
hmac##alg##_destroyctx(dst_context_t *dctx) { \
|
|
|
|
hmac_destroyctx(dctx); \
|
|
|
|
} \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_adddata(dst_context_t *dctx, \
|
|
|
|
const isc_region_t *data) { \
|
|
|
|
return (hmac_adddata(dctx, data)); \
|
|
|
|
} \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_sign(dst_context_t *dctx, \
|
|
|
|
isc_buffer_t *sig) { \
|
|
|
|
return (hmac_sign(dctx, sig)); \
|
|
|
|
} \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_verify(dst_context_t *dctx, \
|
|
|
|
const isc_region_t *sig) { \
|
|
|
|
return (hmac_verify(dctx, sig)); \
|
|
|
|
} \
|
|
|
|
static bool \
|
|
|
|
hmac##alg##_compare(const dst_key_t *key1, \
|
|
|
|
const dst_key_t *key2) { \
|
|
|
|
return (hmac_compare(ISC_MD_##alg, key1, key2)); \
|
|
|
|
} \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_generate(dst_key_t *key, \
|
|
|
|
int pseudorandom_ok, \
|
|
|
|
void (*callback)(int)) { \
|
|
|
|
UNUSED(pseudorandom_ok); \
|
|
|
|
UNUSED(callback); \
|
|
|
|
return (hmac_generate(ISC_MD_##alg, key)); \
|
|
|
|
} \
|
|
|
|
static bool \
|
|
|
|
hmac##alg##_isprivate(const dst_key_t *key) { \
|
|
|
|
return (hmac_isprivate(key)); \
|
|
|
|
} \
|
|
|
|
static void \
|
|
|
|
hmac##alg##_destroy(dst_key_t *key) { \
|
|
|
|
hmac_destroy(key); \
|
|
|
|
} \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_todns(const dst_key_t *key, isc_buffer_t *data) { \
|
|
|
|
return (hmac_todns(key, data)); \
|
|
|
|
} \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_fromdns(dst_key_t *key, isc_buffer_t *data) { \
|
|
|
|
return (hmac_fromdns(ISC_MD_##alg, key, data)); \
|
|
|
|
} \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_tofile(const dst_key_t *key, const char *directory) { \
|
|
|
|
return (hmac_tofile(ISC_MD_##alg, key, directory)); \
|
|
|
|
} \
|
|
|
|
static isc_result_t \
|
|
|
|
hmac##alg##_parse(dst_key_t *key, isc_lex_t *lexer, \
|
|
|
|
dst_key_t *pub) { \
|
|
|
|
return(hmac_parse(ISC_MD_##alg, key, lexer, pub)); \
|
|
|
|
} \
|
|
|
|
static dst_func_t hmac##alg##_functions = { \
|
|
|
|
hmac##alg##_createctx, \
|
|
|
|
NULL, /*%< createctx2 */ \
|
|
|
|
hmac##alg##_destroyctx, \
|
|
|
|
hmac##alg##_adddata, \
|
|
|
|
hmac##alg##_sign, \
|
|
|
|
hmac##alg##_verify, \
|
|
|
|
NULL, /*%< verify2 */ \
|
|
|
|
NULL, /*%< computesecret */ \
|
|
|
|
hmac##alg##_compare, \
|
|
|
|
NULL, /*%< paramcompare */ \
|
|
|
|
hmac##alg##_generate, \
|
|
|
|
hmac##alg##_isprivate, \
|
|
|
|
hmac##alg##_destroy, \
|
|
|
|
hmac##alg##_todns, \
|
|
|
|
hmac##alg##_fromdns, \
|
|
|
|
hmac##alg##_tofile, \
|
|
|
|
hmac##alg##_parse, \
|
|
|
|
NULL, /*%< cleanup */ \
|
|
|
|
NULL, /*%< fromlabel */ \
|
|
|
|
NULL, /*%< dump */ \
|
|
|
|
NULL, /*%< restore */ \
|
|
|
|
}; \
|
|
|
|
isc_result_t \
|
|
|
|
dst__hmac##alg##_init(dst_func_t **funcp) { \
|
|
|
|
REQUIRE(funcp != NULL); \
|
|
|
|
if (*funcp == NULL) { \
|
|
|
|
*funcp = &hmac##alg##_functions; \
|
|
|
|
} \
|
|
|
|
return (ISC_R_SUCCESS); \
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
hmac_fromdns(isc_md_type_t type, dst_key_t *key, isc_buffer_t *data);
|
2000-06-02 18:57:51 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
struct dst_hmac_key {
|
|
|
|
uint8_t key[ISC_MAX_BLOCK_SIZE];
|
2006-12-04 01:54:53 +00:00
|
|
|
};
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline isc_result_t
|
2006-01-27 02:35:15 +00:00
|
|
|
getkeybits(dst_key_t *key, struct dst_private_element *element) {
|
2018-03-20 17:20:50 +00:00
|
|
|
uint16_t *bits = (uint16_t *)element->data;
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (element->length != 2) {
|
2006-01-27 02:35:15 +00:00
|
|
|
return (DST_R_INVALIDPRIVATEKEY);
|
2000-06-07 17:22:31 +00:00
|
|
|
}
|
2000-05-02 03:54:17 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
key->key_bits = ntohs(*bits);
|
2000-06-02 18:57:51 +00:00
|
|
|
|
2000-06-07 17:22:31 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline isc_result_t
|
|
|
|
hmac_createctx(isc_md_type_t type, const dst_key_t *key,
|
|
|
|
dst_context_t *dctx)
|
2018-04-22 14:56:28 +02:00
|
|
|
{
|
2018-03-20 17:20:50 +00:00
|
|
|
isc_result_t result;
|
|
|
|
const dst_hmac_key_t *hkey = key->keydata.hmac_key;
|
|
|
|
isc_hmac_t *ctx = isc_hmac_new(); /* Either returns or abort()s */
|
|
|
|
|
|
|
|
result = isc_hmac_init(ctx, hkey->key,
|
|
|
|
isc_md_type_get_block_size(type), type);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (DST_R_UNSUPPORTEDALG);
|
2000-06-02 18:57:51 +00:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
dctx->ctxdata.hmac_ctx = ctx;
|
1999-10-20 22:14:15 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline void
|
|
|
|
hmac_destroyctx(dst_context_t *dctx) {
|
|
|
|
isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
|
|
|
|
REQUIRE(ctx != NULL);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
isc_hmac_free(ctx);
|
|
|
|
dctx->ctxdata.hmac_ctx = NULL;
|
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline isc_result_t
|
|
|
|
hmac_adddata(const dst_context_t *dctx, const isc_region_t *data) {
|
|
|
|
isc_result_t result;
|
|
|
|
isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
REQUIRE(ctx != NULL);
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
result = isc_hmac_update(ctx, data->base, data->length);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (DST_R_OPENSSLFAILURE);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
2000-07-31 19:44:21 +00:00
|
|
|
|
1999-10-20 22:14:15 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-12 20:08:42 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline isc_result_t
|
|
|
|
hmac_sign(const dst_context_t *dctx, isc_buffer_t *sig) {
|
|
|
|
isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
|
|
|
|
REQUIRE(ctx != NULL);
|
|
|
|
unsigned int digestlen;
|
|
|
|
unsigned char digest[ISC_MAX_MD_SIZE];
|
2014-01-30 17:48:10 -08:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (isc_hmac_final(ctx, digest, &digestlen) != ISC_R_SUCCESS) {
|
|
|
|
return (DST_R_OPENSSLFAILURE);
|
2006-01-27 02:35:15 +00:00
|
|
|
}
|
1999-07-12 20:08:42 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (isc_hmac_reset(ctx) != ISC_R_SUCCESS) {
|
|
|
|
return (DST_R_OPENSSLFAILURE);
|
2018-01-17 14:33:21 +01:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (isc_buffer_availablelength(sig) < digestlen) {
|
|
|
|
return (ISC_R_NOSPACE);
|
2006-01-27 02:35:15 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
isc_buffer_putmem(sig, digest, digestlen);
|
2006-01-27 02:35:15 +00:00
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline isc_result_t
|
|
|
|
hmac_verify(const dst_context_t *dctx, const isc_region_t *sig) {
|
|
|
|
isc_hmac_t *ctx = dctx->ctxdata.hmac_ctx;
|
|
|
|
unsigned int digestlen;
|
|
|
|
unsigned char digest[ISC_MAX_MD_SIZE];
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
REQUIRE(ctx != NULL);
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (isc_hmac_final(ctx, digest, &digestlen) != ISC_R_SUCCESS) {
|
|
|
|
return (DST_R_OPENSSLFAILURE);
|
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (isc_hmac_reset(ctx) != ISC_R_SUCCESS) {
|
|
|
|
return (DST_R_OPENSSLFAILURE);
|
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (sig->length > digestlen) {
|
2006-01-27 02:35:15 +00:00
|
|
|
return (DST_R_VERIFYFAILURE);
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
return (isc_safe_memequal(digest, sig->base, sig->length) ?
|
|
|
|
ISC_R_SUCCESS :
|
|
|
|
DST_R_VERIFYFAILURE);
|
2006-01-27 02:35:15 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline bool
|
|
|
|
hmac_compare(isc_md_type_t type, const dst_key_t *key1, const dst_key_t *key2) {
|
|
|
|
dst_hmac_key_t *hkey1, *hkey2;
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
hkey1 = key1->keydata.hmac_key;
|
|
|
|
hkey2 = key2->keydata.hmac_key;
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (hkey1 == NULL && hkey2 == NULL) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2018-03-20 17:20:50 +00:00
|
|
|
} else if (hkey1 == NULL || hkey2 == NULL) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
return (isc_safe_memequal(hkey1->key, hkey2->key,
|
|
|
|
isc_md_type_get_block_size(type)));
|
2006-01-27 02:35:15 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline isc_result_t
|
|
|
|
hmac_generate(isc_md_type_t type, dst_key_t *key) {
|
2006-01-27 02:35:15 +00:00
|
|
|
isc_buffer_t b;
|
|
|
|
isc_result_t ret;
|
2018-03-20 17:20:50 +00:00
|
|
|
unsigned int bytes, len;
|
|
|
|
unsigned char data[ISC_MAX_MD_SIZE] = { 0 };
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
len = isc_md_type_get_block_size(type);
|
2009-10-24 09:46:19 +00:00
|
|
|
|
2006-01-27 02:35:15 +00:00
|
|
|
bytes = (key->key_size + 7) / 8;
|
2018-03-20 17:20:50 +00:00
|
|
|
|
|
|
|
if (bytes > len) {
|
|
|
|
bytes = len;
|
|
|
|
key->key_size = len * 8;
|
2006-01-27 02:35:15 +00:00
|
|
|
}
|
|
|
|
|
2018-05-28 15:22:23 +02:00
|
|
|
isc_nonce_buf(data, bytes);
|
2006-01-27 02:35:15 +00:00
|
|
|
|
|
|
|
isc_buffer_init(&b, data, bytes);
|
|
|
|
isc_buffer_add(&b, bytes);
|
2018-03-20 17:20:50 +00:00
|
|
|
|
|
|
|
ret = hmac_fromdns(type, key, &b);
|
|
|
|
|
2017-09-19 16:16:45 +05:30
|
|
|
isc_safe_memwipe(data, sizeof(data));
|
2006-01-27 02:35:15 +00:00
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline bool
|
|
|
|
hmac_isprivate(const dst_key_t *key) {
|
2006-01-27 02:35:15 +00:00
|
|
|
UNUSED(key);
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2006-01-27 02:35:15 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline void
|
|
|
|
hmac_destroy(dst_key_t *key) {
|
|
|
|
dst_hmac_key_t *hkey = key->keydata.hmac_key;
|
2017-09-19 16:16:45 +05:30
|
|
|
isc_safe_memwipe(hkey, sizeof(*hkey));
|
|
|
|
isc_mem_put(key->mctx, hkey, sizeof(*hkey));
|
2018-03-20 17:20:50 +00:00
|
|
|
key->keydata.hmac_key = NULL;
|
2006-01-27 02:35:15 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline isc_result_t
|
|
|
|
hmac_todns(const dst_key_t *key, isc_buffer_t *data) {
|
|
|
|
dst_hmac_key_t *hkey = key->keydata.hmac_key;
|
2006-01-27 02:35:15 +00:00
|
|
|
unsigned int bytes;
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
REQUIRE(hkey != NULL);
|
2006-01-27 02:35:15 +00:00
|
|
|
|
|
|
|
bytes = (key->key_size + 7) / 8;
|
2018-03-20 17:20:50 +00:00
|
|
|
if (isc_buffer_availablelength(data) < bytes) {
|
2006-01-27 02:35:15 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
isc_buffer_putmem(data, hkey->key, bytes);
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline isc_result_t
|
|
|
|
hmac_fromdns(isc_md_type_t type, dst_key_t *key, isc_buffer_t *data) {
|
|
|
|
dst_hmac_key_t *hkey;
|
2018-06-01 09:31:59 +02:00
|
|
|
unsigned int keylen;
|
2006-01-27 02:35:15 +00:00
|
|
|
isc_region_t r;
|
|
|
|
|
|
|
|
isc_buffer_remainingregion(data, &r);
|
2018-03-20 17:20:50 +00:00
|
|
|
if (r.length == 0) {
|
2006-01-27 02:35:15 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
hkey = isc_mem_get(key->mctx, sizeof(dst_hmac_key_t));
|
|
|
|
if (hkey == NULL) {
|
2006-01-27 02:35:15 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
|
|
|
memset(hkey->key, 0, sizeof(hkey->key));
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
/* Hash the key if the key is longer then chosen MD block size */
|
|
|
|
if (r.length > (unsigned int)isc_md_type_get_block_size(type)) {
|
|
|
|
if (isc_md(type, r.base, r.length, hkey->key, &keylen)
|
|
|
|
!= ISC_R_SUCCESS) {
|
|
|
|
return (DST_R_OPENSSLFAILURE);
|
2018-06-01 09:31:59 +02:00
|
|
|
}
|
2014-01-08 16:27:10 -08:00
|
|
|
} else {
|
|
|
|
memmove(hkey->key, r.base, r.length);
|
2006-01-27 02:35:15 +00:00
|
|
|
keylen = r.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
key->key_size = keylen * 8;
|
2018-03-20 17:20:50 +00:00
|
|
|
key->keydata.hmac_key = hkey;
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2015-08-07 13:16:10 -07:00
|
|
|
isc_buffer_forward(data, r.length);
|
|
|
|
|
2006-01-27 02:35:15 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline int
|
|
|
|
hmac__get_tag_key(isc_md_type_t type) {
|
|
|
|
if (type == ISC_MD_MD5) {
|
|
|
|
return (TAG_HMACMD5_KEY);
|
|
|
|
} else if (type == ISC_MD_SHA1) {
|
|
|
|
return (TAG_HMACSHA1_KEY);
|
|
|
|
} else if (type == ISC_MD_SHA224) {
|
|
|
|
return (TAG_HMACSHA224_KEY);
|
|
|
|
} else if (type == ISC_MD_SHA256) {
|
|
|
|
return (TAG_HMACSHA256_KEY);
|
|
|
|
} else if (type == ISC_MD_SHA384) {
|
|
|
|
return (TAG_HMACSHA384_KEY);
|
|
|
|
} else if (type == ISC_MD_SHA512) {
|
|
|
|
return (TAG_HMACSHA512_KEY);
|
|
|
|
} else {
|
|
|
|
INSIST(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
hmac__get_tag_bits(isc_md_type_t type) {
|
|
|
|
if (type == ISC_MD_MD5) {
|
|
|
|
return (TAG_HMACMD5_BITS);
|
|
|
|
} else if (type == ISC_MD_SHA1) {
|
|
|
|
return (TAG_HMACSHA1_BITS);
|
|
|
|
} else if (type == ISC_MD_SHA224) {
|
|
|
|
return (TAG_HMACSHA224_BITS);
|
|
|
|
} else if (type == ISC_MD_SHA256) {
|
|
|
|
return (TAG_HMACSHA256_BITS);
|
|
|
|
} else if (type == ISC_MD_SHA384) {
|
|
|
|
return (TAG_HMACSHA384_BITS);
|
|
|
|
} else if (type == ISC_MD_SHA512) {
|
|
|
|
return (TAG_HMACSHA512_BITS);
|
|
|
|
} else {
|
|
|
|
INSIST(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline isc_result_t
|
|
|
|
hmac_tofile(isc_md_type_t type, const dst_key_t *key, const char *directory) {
|
|
|
|
dst_hmac_key_t *hkey;
|
2006-01-27 02:35:15 +00:00
|
|
|
dst_private_t priv;
|
|
|
|
int bytes = (key->key_size + 7) / 8;
|
2018-03-20 17:20:50 +00:00
|
|
|
uint16_t bits;
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (key->keydata.hmac_key == NULL) {
|
2006-01-27 02:35:15 +00:00
|
|
|
return (DST_R_NULLKEY);
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (key->external) {
|
2014-01-30 17:48:10 -08:00
|
|
|
return (DST_R_EXTERNALKEY);
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hkey = key->keydata.hmac_key;
|
2014-01-30 17:48:10 -08:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
priv.elements[0].tag = hmac__get_tag_key(type);
|
|
|
|
priv.elements[0].length = bytes;
|
|
|
|
priv.elements[0].data = hkey->key;
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
bits = htons(key->key_bits);
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
priv.elements[1].tag = hmac__get_tag_bits(type);
|
|
|
|
priv.elements[1].length = sizeof(bits);
|
|
|
|
priv.elements[1].data = (uint8_t *)&bits;
|
|
|
|
|
|
|
|
priv.nelements = 2;
|
2006-01-27 02:35:15 +00:00
|
|
|
|
|
|
|
return (dst__privstruct_writefile(key, &priv, directory));
|
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
static inline int
|
|
|
|
hmac__to_dst_alg(isc_md_type_t type) {
|
|
|
|
if (type == ISC_MD_MD5) {
|
|
|
|
return (DST_ALG_HMACMD5);
|
|
|
|
} else if (type == ISC_MD_SHA1) {
|
|
|
|
return (DST_ALG_HMACSHA1);
|
|
|
|
} else if (type == ISC_MD_SHA224) {
|
|
|
|
return (DST_ALG_HMACSHA224);
|
|
|
|
} else if (type == ISC_MD_SHA256) {
|
|
|
|
return (DST_ALG_HMACSHA256);
|
|
|
|
} else if (type == ISC_MD_SHA384) {
|
|
|
|
return (DST_ALG_HMACSHA384);
|
|
|
|
} else if (type == ISC_MD_SHA512) {
|
|
|
|
return (DST_ALG_HMACSHA512);
|
|
|
|
} else {
|
|
|
|
INSIST(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline isc_result_t
|
|
|
|
hmac_parse(isc_md_type_t type, dst_key_t *key,
|
|
|
|
isc_lex_t *lexer, dst_key_t *pub)
|
|
|
|
{
|
2006-01-27 02:35:15 +00:00
|
|
|
dst_private_t priv;
|
|
|
|
isc_result_t result, tresult;
|
|
|
|
isc_buffer_t b;
|
|
|
|
isc_mem_t *mctx = key->mctx;
|
|
|
|
unsigned int i;
|
|
|
|
|
2009-09-03 04:09:58 +00:00
|
|
|
UNUSED(pub);
|
2006-01-27 02:35:15 +00:00
|
|
|
/* read private key file */
|
2018-03-20 17:20:50 +00:00
|
|
|
result = dst__privstruct_parse(key, hmac__to_dst_alg(type), lexer, mctx,
|
2006-01-27 02:35:15 +00:00
|
|
|
&priv);
|
2018-03-20 17:20:50 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2006-01-27 02:35:15 +00:00
|
|
|
return (result);
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
if (key->external) {
|
2014-01-30 17:48:10 -08:00
|
|
|
result = DST_R_EXTERNALKEY;
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2014-01-30 17:48:10 -08:00
|
|
|
|
2006-01-27 02:35:15 +00:00
|
|
|
key->key_bits = 0;
|
2014-01-30 17:48:10 -08:00
|
|
|
for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
|
2006-01-27 02:35:15 +00:00
|
|
|
switch (priv.elements[i].tag) {
|
2018-03-20 17:20:50 +00:00
|
|
|
case TAG_HMACMD5_KEY:
|
2006-01-27 02:35:15 +00:00
|
|
|
case TAG_HMACSHA1_KEY:
|
2018-03-20 17:20:50 +00:00
|
|
|
case TAG_HMACSHA224_KEY:
|
|
|
|
case TAG_HMACSHA256_KEY:
|
|
|
|
case TAG_HMACSHA384_KEY:
|
|
|
|
case TAG_HMACSHA512_KEY:
|
2006-01-27 02:35:15 +00:00
|
|
|
isc_buffer_init(&b, priv.elements[i].data,
|
2008-04-01 23:47:10 +00:00
|
|
|
priv.elements[i].length);
|
2006-01-27 02:35:15 +00:00
|
|
|
isc_buffer_add(&b, priv.elements[i].length);
|
2018-03-20 17:20:50 +00:00
|
|
|
tresult = hmac_fromdns(type, key, &b);
|
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2006-01-27 02:35:15 +00:00
|
|
|
result = tresult;
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
break;
|
2018-03-20 17:20:50 +00:00
|
|
|
case TAG_HMACMD5_BITS:
|
2006-01-27 02:35:15 +00:00
|
|
|
case TAG_HMACSHA1_BITS:
|
2018-03-20 17:20:50 +00:00
|
|
|
case TAG_HMACSHA224_BITS:
|
|
|
|
case TAG_HMACSHA256_BITS:
|
|
|
|
case TAG_HMACSHA384_BITS:
|
|
|
|
case TAG_HMACSHA512_BITS:
|
2006-01-27 02:35:15 +00:00
|
|
|
tresult = getkeybits(key, &priv.elements[i]);
|
2018-03-20 17:20:50 +00:00
|
|
|
if (tresult != ISC_R_SUCCESS) {
|
2006-01-27 02:35:15 +00:00
|
|
|
result = tresult;
|
2018-03-20 17:20:50 +00:00
|
|
|
}
|
2006-01-27 02:35:15 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result = DST_R_INVALIDPRIVATEKEY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dst__privstruct_free(&priv, mctx);
|
2017-09-19 16:16:45 +05:30
|
|
|
isc_safe_memwipe(&priv, sizeof(priv));
|
2006-01-27 02:35:15 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2018-03-20 17:20:50 +00:00
|
|
|
hmac_register_algorithm(md5);
|
|
|
|
hmac_register_algorithm(sha1);
|
|
|
|
hmac_register_algorithm(sha224);
|
|
|
|
hmac_register_algorithm(sha256);
|
|
|
|
hmac_register_algorithm(sha384);
|
|
|
|
hmac_register_algorithm(sha512);
|
2006-01-27 02:35:15 +00:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|