WIP: Add SQISign support to BIND 9
This commit is contained in:
committed by
Ondřej Surý
parent
18f5b23116
commit
a301d74483
@@ -43,7 +43,7 @@ Options
|
||||
|
||||
This option selects the cryptographic algorithm. The value of ``algorithm`` must
|
||||
be one of RSASHA1, NSEC3RSASHA1, RSASHA256, RSASHA512,
|
||||
ECDSAP256SHA256, ECDSAP384SHA384, ED25519, or ED448.
|
||||
ECDSAP256SHA256, ECDSAP384SHA384, ED25519, ED448, or SQISIGN.
|
||||
|
||||
These values are case-insensitive. In some cases, abbreviations are
|
||||
supported, such as ECDSA256 for ECDSAP256SHA256 and ECDSA384 for
|
||||
|
||||
@@ -152,6 +152,7 @@ usage(void) {
|
||||
fprintf(stderr, " RSASHA256 | RSASHA512 |\n");
|
||||
fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n");
|
||||
fprintf(stderr, " ED25519 | ED448\n");
|
||||
fprintf(stderr, " SQISIGN\n");
|
||||
fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
|
||||
fprintf(stderr, " -b <key size in bits>:\n");
|
||||
if (!isc_crypto_fips_mode()) {
|
||||
@@ -166,6 +167,7 @@ usage(void) {
|
||||
fprintf(stderr, " ECDSAP384SHA384:\tignored\n");
|
||||
fprintf(stderr, " ED25519:\tignored\n");
|
||||
fprintf(stderr, " ED448:\tignored\n");
|
||||
fprintf(stderr, " SQISIGN:\tignored\n");
|
||||
fprintf(stderr, " (key size defaults are set according to\n"
|
||||
" algorithm and usage (ZSK or KSK)\n");
|
||||
fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | "
|
||||
@@ -306,6 +308,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
||||
case DST_ALG_ECDSA384:
|
||||
case DST_ALG_ED25519:
|
||||
case DST_ALG_ED448:
|
||||
case DST_ALG_SQISIGN:
|
||||
break;
|
||||
default:
|
||||
fatal("algorithm %s is incompatible with NSEC3"
|
||||
@@ -356,6 +359,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
||||
case DST_ALG_ECDSA384:
|
||||
case DST_ALG_ED25519:
|
||||
case DST_ALG_ED448:
|
||||
case DST_ALG_SQISIGN:
|
||||
break;
|
||||
default:
|
||||
fatal("key size not specified (-b option)");
|
||||
@@ -520,6 +524,9 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
||||
case DST_ALG_ED448:
|
||||
ctx->size = 456;
|
||||
break;
|
||||
case DST_ALG_SQISIGN:
|
||||
ctx->size = 512;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctx->nametype == NULL) {
|
||||
@@ -587,6 +594,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
||||
case DST_ALG_ECDSA384:
|
||||
case DST_ALG_ED25519:
|
||||
case DST_ALG_ED448:
|
||||
case DST_ALG_SQISIGN:
|
||||
show_progress = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ Options
|
||||
|
||||
This option selects the cryptographic algorithm. For DNSSEC keys, the value of
|
||||
``algorithm`` must be one of RSASHA1, NSEC3RSASHA1, RSASHA256,
|
||||
RSASHA512, ECDSAP256SHA256, ECDSAP384SHA384, ED25519, or ED448.
|
||||
RSASHA512, ECDSAP256SHA256, ECDSAP384SHA384, ED25519, ED448, or SQISIGN.
|
||||
|
||||
These values are case-insensitive. In some cases, abbreviations are
|
||||
supported, such as ECDSA256 for ECDSAP256SHA256 and ECDSA384 for
|
||||
@@ -92,7 +92,7 @@ Options
|
||||
This option specifies the key size in bits. For the algorithms RSASHA1, NSEC3RSASA1, RSASHA256, and
|
||||
RSASHA512 the key size must be between 1024 and 4096 bits; DH size is between 128
|
||||
and 4096 bits. This option is ignored for algorithms ECDSAP256SHA256,
|
||||
ECDSAP384SHA384, ED25519, and ED448.
|
||||
ECDSAP384SHA384, ED25519, ED448, and SQISIGN.
|
||||
|
||||
.. option:: -f flag
|
||||
|
||||
|
||||
@@ -387,6 +387,9 @@ create_key(ksr_ctx_t *ksr, dns_kasp_t *kasp, dns_kasp_key_t *kaspkey,
|
||||
case DST_ALG_ED448:
|
||||
ksr->size = 456;
|
||||
break;
|
||||
case DST_ALG_SQISIGN:
|
||||
ksr->size = 512;
|
||||
break;
|
||||
default:
|
||||
show_progress = false;
|
||||
break;
|
||||
|
||||
26
configure.ac
26
configure.ac
@@ -690,6 +690,32 @@ AX_RESTORE_FLAGS([openssl])
|
||||
AC_SUBST([OPENSSL_CFLAGS])
|
||||
AC_SUBST([OPENSSL_LIBS])
|
||||
|
||||
AC_ARG_WITH([sqisign],
|
||||
[AS_HELP_STRING([--with-sqisign=PATH],
|
||||
[Build with SQISign support (auto|yes|no|path) [default=auto]])],
|
||||
[], [with_sqisign="/usr/local"])
|
||||
|
||||
AS_CASE([$with_sqisign],
|
||||
[no],[:],
|
||||
[auto],[AC_MSG_ERROR([not implemented yet])],
|
||||
[yes],[AC_MSG_ERROR([not implemented yet])],
|
||||
[ # default
|
||||
AX_SAVE_FLAGS([sqisign])
|
||||
SQISIGN_CFLAGS="-I$with_sqisign/include"
|
||||
SQISIGN_LIBS="-L$with_sqisign/lib"
|
||||
CFLAGS="$CFLAGS $SQISIGN_CFLAGS"
|
||||
LIBS="$LIBS $SQISIGN_LIBS"
|
||||
AC_SEARCH_LIBS([sqisign_lvl1_ref_sqisign_keypair], [sqisign_lvl1],
|
||||
[
|
||||
SQISIGN_LIBS="$SQISIGN_LIBS $ac_cv_search_sqisign_lvl1_ref_sqisign_keypair"
|
||||
],[
|
||||
AC_MSG_ERROR([SQISign libraries not found])
|
||||
])
|
||||
])
|
||||
|
||||
AC_SUBST([SQISIGN_CFLAGS])
|
||||
AC_SUBST([SQISIGN_LIBS])
|
||||
|
||||
AC_CHECK_FUNCS([clock_gettime])
|
||||
|
||||
# [pairwise: --with-gssapi=yes, --with-gssapi=auto, --without-gssapi]
|
||||
|
||||
@@ -239,6 +239,7 @@ libdns_la_SOURCES = \
|
||||
sdlz.c \
|
||||
skr.c \
|
||||
soa.c \
|
||||
sqisignhd_link.c \
|
||||
ssu.c \
|
||||
ssu_external.c \
|
||||
stats.c \
|
||||
@@ -270,23 +271,23 @@ endif
|
||||
|
||||
libdns_la_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
-I/Users/ondrej/.local/usr/include/ \
|
||||
$(LIBDNS_CFLAGS) \
|
||||
$(LIBISC_CFLAGS) \
|
||||
$(LIBURCU_CFLAGS) \
|
||||
$(LIBUV_CFLAGS) \
|
||||
$(OPENSSL_CFLAGS)
|
||||
$(OPENSSL_CFLAGS) \
|
||||
$(SQISIGN_CFLAGS)
|
||||
|
||||
libdns_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-release "$(PACKAGE_VERSION)"
|
||||
|
||||
libdns_la_LIBADD = \
|
||||
/usr/local/lib/libsqisign_lvl1.a \
|
||||
$(LIBISC_LIBS) \
|
||||
$(LIBURCU_LIBS) \
|
||||
$(LIBUV_LIBS) \
|
||||
$(OPENSSL_LIBS)
|
||||
$(OPENSSL_LIBS) \
|
||||
$(SQISIGN_LIBS)
|
||||
|
||||
if HAVE_JSON_C
|
||||
libdns_la_CPPFLAGS += \
|
||||
|
||||
@@ -213,6 +213,8 @@ dst__lib_initialize(void) {
|
||||
dst__openssleddsa_init(&dst_t_func[DST_ALG_ED448], DST_ALG_ED448);
|
||||
#endif /* ifdef HAVE_OPENSSL_ED448 */
|
||||
|
||||
dst__sqisign_init(&dst_t_func[DST_ALG_SQISIGN], DST_ALG_SQISIGN);
|
||||
|
||||
#if HAVE_GSSAPI
|
||||
dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]);
|
||||
#endif /* HAVE_GSSAPI */
|
||||
@@ -1347,6 +1349,9 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
|
||||
case DST_ALG_ED448:
|
||||
*n = DNS_SIG_ED448SIZE;
|
||||
break;
|
||||
case DST_ALG_SQISIGN:
|
||||
*n = DNS_SIG_SQISIGNSIZE;
|
||||
break;
|
||||
case DST_ALG_HMACMD5:
|
||||
*n = isc_md_type_get_size(ISC_MD_MD5);
|
||||
break;
|
||||
@@ -1832,6 +1837,7 @@ issymmetric(const dst_key_t *key) {
|
||||
case DST_ALG_ECDSA384:
|
||||
case DST_ALG_ED25519:
|
||||
case DST_ALG_ED448:
|
||||
case DST_ALG_SQISIGN:
|
||||
return false;
|
||||
case DST_ALG_HMACMD5:
|
||||
case DST_ALG_HMACSHA1:
|
||||
|
||||
@@ -98,6 +98,10 @@ struct dst_key {
|
||||
EVP_PKEY *pub;
|
||||
EVP_PKEY *priv;
|
||||
} pkeypair;
|
||||
struct {
|
||||
uint8_t *pub;
|
||||
uint8_t *priv;
|
||||
} keypair;
|
||||
} keydata; /*%< pointer to key in crypto pkg fmt */
|
||||
|
||||
isc_stdtime_t times[DST_MAX_TIMES + 1]; /*%< timing metadata */
|
||||
@@ -203,6 +207,8 @@ dst__openssleddsa_init(struct dst_func **funcp, unsigned char algorithm);
|
||||
void
|
||||
dst__gssapi_init(struct dst_func **funcp);
|
||||
#endif /* HAVE_GSSAPI*/
|
||||
void
|
||||
dst__sqisign_init(dst_func_t **funcp, unsigned char algorithm);
|
||||
|
||||
/*%
|
||||
* Secure private file handling
|
||||
|
||||
@@ -90,6 +90,9 @@ static struct parse_map map[] = { { TAG_RSA_MODULUS, "Modulus:" },
|
||||
{ TAG_EDDSA_ENGINE, "Engine:" },
|
||||
{ TAG_EDDSA_LABEL, "Label:" },
|
||||
|
||||
{ TAG_SQISIGN_PUBLICKEY, "PublicKey:" },
|
||||
{ TAG_SQISIGN_SECRETKEY, "SecretKey:" },
|
||||
|
||||
{ TAG_HMACMD5_KEY, "Key:" },
|
||||
{ TAG_HMACMD5_BITS, "Bits:" },
|
||||
|
||||
@@ -160,19 +163,24 @@ find_numericdata(const char *s) {
|
||||
return find_metadata(s, numerictags, NUMERIC_NTAGS);
|
||||
}
|
||||
|
||||
static int
|
||||
check_rsa(const dst_private_t *priv, bool external) {
|
||||
int i, j;
|
||||
bool have[RSA_NTAGS];
|
||||
bool ok;
|
||||
unsigned int mask;
|
||||
|
||||
if (external) {
|
||||
return (priv->nelements == 0) ? 0 : -1;
|
||||
static isc_result_t
|
||||
check_external(const dst_private_t *priv) {
|
||||
if (priv->nelements == 0) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
for (i = 0; i < RSA_NTAGS; i++) {
|
||||
have[i] = false;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
check_rsa(const dst_private_t *priv, bool external) {
|
||||
int i, j;
|
||||
bool have[RSA_NTAGS] = { 0 };
|
||||
bool ok;
|
||||
unsigned int mask = (1ULL << TAG_SHIFT) - 1;
|
||||
|
||||
if (external) {
|
||||
return check_external(priv);
|
||||
}
|
||||
|
||||
for (j = 0; j < priv->nelements; j++) {
|
||||
@@ -182,13 +190,11 @@ check_rsa(const dst_private_t *priv, bool external) {
|
||||
}
|
||||
}
|
||||
if (i == RSA_NTAGS) {
|
||||
return -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
have[i] = true;
|
||||
}
|
||||
|
||||
mask = (1ULL << TAG_SHIFT) - 1;
|
||||
|
||||
if (have[TAG_RSA_LABEL & mask]) {
|
||||
ok = have[TAG_RSA_MODULUS & mask] &&
|
||||
have[TAG_RSA_PUBLICEXPONENT & mask];
|
||||
@@ -202,23 +208,23 @@ check_rsa(const dst_private_t *priv, bool external) {
|
||||
have[TAG_RSA_EXPONENT2 & mask] &&
|
||||
have[TAG_RSA_COEFFICIENT & mask];
|
||||
}
|
||||
return ok ? 0 : -1;
|
||||
if (!ok) {
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
check_ecdsa(const dst_private_t *priv, bool external) {
|
||||
int i, j;
|
||||
bool have[ECDSA_NTAGS];
|
||||
bool ok;
|
||||
unsigned int mask;
|
||||
bool have[ECDSA_NTAGS] = { 0 };
|
||||
unsigned int mask = (1ULL << TAG_SHIFT) - 1;
|
||||
|
||||
if (external) {
|
||||
return (priv->nelements == 0) ? 0 : -1;
|
||||
return check_external(priv);
|
||||
}
|
||||
|
||||
for (i = 0; i < ECDSA_NTAGS; i++) {
|
||||
have[i] = false;
|
||||
}
|
||||
for (j = 0; j < priv->nelements; j++) {
|
||||
for (i = 0; i < ECDSA_NTAGS; i++) {
|
||||
if (priv->elements[j].tag == TAG(DST_ALG_ECDSA256, i)) {
|
||||
@@ -226,27 +232,26 @@ check_ecdsa(const dst_private_t *priv, bool external) {
|
||||
}
|
||||
}
|
||||
if (i == ECDSA_NTAGS) {
|
||||
return -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
have[i] = true;
|
||||
}
|
||||
|
||||
mask = (1ULL << TAG_SHIFT) - 1;
|
||||
if (have[TAG_ECDSA_LABEL & mask] || have[TAG_ECDSA_PRIVATEKEY & mask]) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
ok = have[TAG_ECDSA_LABEL & mask] || have[TAG_ECDSA_PRIVATEKEY & mask];
|
||||
|
||||
return ok ? 0 : -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
|
||||
static int
|
||||
check_eddsa(const dst_private_t *priv, bool external) {
|
||||
int i, j;
|
||||
bool have[EDDSA_NTAGS];
|
||||
bool ok;
|
||||
unsigned int mask;
|
||||
|
||||
if (external) {
|
||||
return (priv->nelements == 0) ? 0 : -1;
|
||||
return check_external(priv);
|
||||
}
|
||||
|
||||
for (i = 0; i < EDDSA_NTAGS; i++) {
|
||||
@@ -259,16 +264,51 @@ check_eddsa(const dst_private_t *priv, bool external) {
|
||||
}
|
||||
}
|
||||
if (i == EDDSA_NTAGS) {
|
||||
return -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
have[i] = true;
|
||||
}
|
||||
|
||||
mask = (1ULL << TAG_SHIFT) - 1;
|
||||
|
||||
ok = have[TAG_EDDSA_LABEL & mask] || have[TAG_EDDSA_PRIVATEKEY & mask];
|
||||
if (have[TAG_EDDSA_LABEL & mask] || have[TAG_EDDSA_PRIVATEKEY & mask]) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
return ok ? 0 : -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
|
||||
static int
|
||||
check_sqisignhd(const dst_private_t *priv, bool external) {
|
||||
bool have[SQISIGN_NTAGS] = { 0 };
|
||||
unsigned int mask;
|
||||
|
||||
if (external) {
|
||||
return check_external(priv);
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < priv->nelements; j++) {
|
||||
size_t i;
|
||||
for (i = 0; i < SQISIGN_NTAGS; i++) {
|
||||
if (priv->elements[j].tag == TAG(DST_ALG_SQISIGN, i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == SQISIGN_NTAGS) {
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
have[i] = true;
|
||||
}
|
||||
|
||||
mask = (1ULL << TAG_SHIFT) - 1;
|
||||
|
||||
if (have[TAG_SQISIGN_PUBLICKEY & mask] &&
|
||||
have[TAG_SQISIGN_SECRETKEY & mask])
|
||||
{
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -283,9 +323,9 @@ check_hmac_md5(const dst_private_t *priv, bool old) {
|
||||
if (old && priv->nelements == OLD_HMACMD5_NTAGS &&
|
||||
priv->elements[0].tag == TAG_HMACMD5_KEY)
|
||||
{
|
||||
return 0;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
return -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
/*
|
||||
* We must be new format at this point.
|
||||
@@ -297,10 +337,10 @@ check_hmac_md5(const dst_private_t *priv, bool old) {
|
||||
}
|
||||
}
|
||||
if (j == priv->nelements) {
|
||||
return -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -308,7 +348,7 @@ check_hmac_sha(const dst_private_t *priv, unsigned int ntags,
|
||||
unsigned int alg) {
|
||||
unsigned int i, j;
|
||||
if (priv->nelements != ntags) {
|
||||
return -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
for (i = 0; i < ntags; i++) {
|
||||
for (j = 0; j < priv->nelements; j++) {
|
||||
@@ -317,13 +357,13 @@ check_hmac_sha(const dst_private_t *priv, unsigned int ntags,
|
||||
}
|
||||
}
|
||||
if (j == priv->nelements) {
|
||||
return -1;
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
static isc_result_t
|
||||
check_data(const dst_private_t *priv, const unsigned int alg, bool old,
|
||||
bool external) {
|
||||
switch (alg) {
|
||||
@@ -339,6 +379,8 @@ check_data(const dst_private_t *priv, const unsigned int alg, bool old,
|
||||
case DST_ALG_ED25519:
|
||||
case DST_ALG_ED448:
|
||||
return check_eddsa(priv, external);
|
||||
case DST_ALG_SQISIGN:
|
||||
return check_sqisignhd(priv, external);
|
||||
case DST_ALG_HMACMD5:
|
||||
return check_hmac_md5(priv, old);
|
||||
case DST_ALG_HMACSHA1:
|
||||
@@ -382,7 +424,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
unsigned char *data = NULL;
|
||||
unsigned int opt = ISC_LEXOPT_EOL;
|
||||
isc_stdtime_t when;
|
||||
isc_result_t ret;
|
||||
isc_result_t result;
|
||||
bool external = false;
|
||||
|
||||
REQUIRE(priv != NULL);
|
||||
@@ -390,20 +432,22 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
priv->nelements = 0;
|
||||
memset(priv->elements, 0, sizeof(priv->elements));
|
||||
|
||||
#define NEXTTOKEN(lex, opt, token) \
|
||||
do { \
|
||||
ret = isc_lex_gettoken(lex, opt, token); \
|
||||
if (ret != ISC_R_SUCCESS) \
|
||||
goto fail; \
|
||||
#define NEXTTOKEN(lex, opt, token) \
|
||||
do { \
|
||||
result = isc_lex_gettoken(lex, opt, token); \
|
||||
if (result != ISC_R_SUCCESS) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define READLINE(lex, opt, token) \
|
||||
do { \
|
||||
ret = isc_lex_gettoken(lex, opt, token); \
|
||||
if (ret == ISC_R_EOF) \
|
||||
break; \
|
||||
else if (ret != ISC_R_SUCCESS) \
|
||||
goto fail; \
|
||||
#define READLINE(lex, opt, token) \
|
||||
do { \
|
||||
result = isc_lex_gettoken(lex, opt, token); \
|
||||
if (result == ISC_R_EOF) { \
|
||||
break; \
|
||||
} else if (result != ISC_R_SUCCESS) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while ((*token).type != isc_tokentype_eol)
|
||||
|
||||
/*
|
||||
@@ -413,23 +457,23 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
if (token.type != isc_tokentype_string ||
|
||||
strcmp(DST_AS_STR(token), PRIVATE_KEY_STR) != 0)
|
||||
{
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
NEXTTOKEN(lex, opt, &token);
|
||||
if (token.type != isc_tokentype_string || (DST_AS_STR(token))[0] != 'v')
|
||||
{
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
if (sscanf(DST_AS_STR(token), "v%d.%d", &major, &minor) != 2) {
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (major > DST_MAJOR_VERSION) {
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -447,7 +491,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
if (token.type != isc_tokentype_string ||
|
||||
strcmp(DST_AS_STR(token), ALGORITHM_STR) != 0)
|
||||
{
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -455,7 +499,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
if (token.type != isc_tokentype_number ||
|
||||
token.value.as_ulong != (unsigned long)dst_key_alg(key))
|
||||
{
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -468,17 +512,17 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
int tag;
|
||||
isc_region_t r;
|
||||
do {
|
||||
ret = isc_lex_gettoken(lex, opt, &token);
|
||||
if (ret == ISC_R_EOF) {
|
||||
result = isc_lex_gettoken(lex, opt, &token);
|
||||
if (result == ISC_R_EOF) {
|
||||
goto done;
|
||||
}
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto fail;
|
||||
}
|
||||
} while (token.type == isc_tokentype_eol);
|
||||
|
||||
if (token.type != isc_tokentype_string) {
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -494,7 +538,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
|
||||
NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
|
||||
if (token.type != isc_tokentype_number) {
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -509,12 +553,12 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
|
||||
NEXTTOKEN(lex, opt, &token);
|
||||
if (token.type != isc_tokentype_string) {
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = dns_time32_fromtext(DST_AS_STR(token), &when);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
result = dns_time32_fromtext(DST_AS_STR(token), &when);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -528,7 +572,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
if (tag < 0 && minor > DST_MINOR_VERSION) {
|
||||
goto next;
|
||||
} else if (tag < 0) {
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -537,8 +581,8 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
data = isc_mem_get(mctx, MAXFIELDSIZE);
|
||||
|
||||
isc_buffer_init(&b, data, MAXFIELDSIZE);
|
||||
ret = isc_base64_tobuffer(lex, &b, -1);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
result = isc_base64_tobuffer(lex, &b, -1);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -554,16 +598,13 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
|
||||
|
||||
done:
|
||||
if (external && priv->nelements != 0) {
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
check = check_data(priv, alg, true, external);
|
||||
if (check < 0) {
|
||||
ret = DST_R_INVALIDPRIVATEKEY;
|
||||
goto fail;
|
||||
} else if (check != ISC_R_SUCCESS) {
|
||||
ret = check;
|
||||
if (check != ISC_R_SUCCESS) {
|
||||
result = check;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -577,7 +618,7 @@ fail:
|
||||
isc_mem_put(mctx, data, MAXFIELDSIZE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return result;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
@@ -596,15 +637,13 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
|
||||
isc_region_t r;
|
||||
int major, minor;
|
||||
mode_t mode;
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
REQUIRE(priv != NULL);
|
||||
|
||||
ret = check_data(priv, dst_key_alg(key), false, key->external);
|
||||
if (ret < 0) {
|
||||
return DST_R_INVALIDPRIVATEKEY;
|
||||
} else if (ret != ISC_R_SUCCESS) {
|
||||
return ret;
|
||||
result = check_data(priv, dst_key_alg(key), false, key->external);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
isc_buffer_init(&fileb, filename, sizeof(filename));
|
||||
@@ -676,6 +715,9 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
|
||||
case DST_ALG_ED448:
|
||||
fprintf(fp, "(ED448)\n");
|
||||
break;
|
||||
case DST_ALG_SQISIGN:
|
||||
fprintf(fp, "(SQISIGN)\n");
|
||||
break;
|
||||
case DST_ALG_HMACMD5:
|
||||
fprintf(fp, "(HMAC_MD5)\n");
|
||||
break;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#define MAXFIELDSIZE 512
|
||||
#define MAXFIELDSIZE 1025
|
||||
|
||||
/*
|
||||
* Maximum number of fields in a private file is 18 (12 algorithm-
|
||||
@@ -67,6 +67,10 @@
|
||||
#define TAG_EDDSA_ENGINE ((DST_ALG_ED25519 << TAG_SHIFT) + 1)
|
||||
#define TAG_EDDSA_LABEL ((DST_ALG_ED25519 << TAG_SHIFT) + 2)
|
||||
|
||||
#define SQISIGN_NTAGS 3
|
||||
#define TAG_SQISIGN_PUBLICKEY ((DST_ALG_SQISIGN << TAG_SHIFT) + 0)
|
||||
#define TAG_SQISIGN_SECRETKEY ((DST_ALG_SQISIGN << TAG_SHIFT) + 1)
|
||||
|
||||
#define OLD_HMACMD5_NTAGS 1
|
||||
#define HMACMD5_NTAGS 2
|
||||
#define TAG_HMACMD5_KEY ((DST_ALG_HMACMD5 << TAG_SHIFT) + 0)
|
||||
|
||||
@@ -63,13 +63,11 @@ struct dst_gssapi_signverifyctx {
|
||||
* or verifying.
|
||||
*/
|
||||
static isc_result_t
|
||||
gssapi_create_signverify_ctx(dst_key_t *key, dst_context_t *dctx) {
|
||||
dst_gssapi_signverifyctx_t *ctx;
|
||||
|
||||
UNUSED(key);
|
||||
|
||||
ctx = isc_mem_get(dctx->mctx, sizeof(dst_gssapi_signverifyctx_t));
|
||||
ctx->buffer = NULL;
|
||||
gssapi_create_signverify_ctx(dst_key_t *key ISC_ATTR_UNUSED,
|
||||
dst_context_t *dctx) {
|
||||
dst_gssapi_signverifyctx_t *ctx =
|
||||
isc_mem_get(dctx->mctx, sizeof(dst_gssapi_signverifyctx_t));
|
||||
*ctx = (dst_gssapi_signverifyctx_t){ 0 };
|
||||
isc_buffer_allocate(dctx->mctx, &ctx->buffer, INITIAL_BUFFER_SIZE);
|
||||
|
||||
dctx->ctxdata.gssctx = ctx;
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#define DNS_KEYALG_ECDSA384 14
|
||||
#define DNS_KEYALG_ED25519 15
|
||||
#define DNS_KEYALG_ED448 16
|
||||
#define DNS_KEYALG_SQISIGN 17
|
||||
#define DNS_KEYALG_INDIRECT 252
|
||||
#define DNS_KEYALG_PRIVATEDNS 253
|
||||
#define DNS_KEYALG_PRIVATEOID 254 /*%< Key begins with OID giving alg */
|
||||
@@ -102,3 +103,7 @@
|
||||
|
||||
#define DNS_KEY_ED25519SIZE 32
|
||||
#define DNS_KEY_ED448SIZE 57
|
||||
|
||||
#define DNS_SIG_SQISIGNSIZE 148
|
||||
#define DNS_KEY_SQISIGNSIZE 65
|
||||
#define DNS_SEC_SQISIGNSIZE 353
|
||||
|
||||
@@ -93,6 +93,7 @@ typedef enum dst_algorithm {
|
||||
DST_ALG_ECDSA384 = 14,
|
||||
DST_ALG_ED25519 = 15,
|
||||
DST_ALG_ED448 = 16,
|
||||
DST_ALG_SQISIGN = 17, /* FIXME: should be experimental */
|
||||
|
||||
/*
|
||||
* Do not renumber HMAC algorithms as they are used externally to named
|
||||
|
||||
@@ -470,6 +470,9 @@ dns_kasp_key_size(dns_kasp_key_t *key) {
|
||||
case DNS_KEYALG_ED448:
|
||||
size = 456;
|
||||
break;
|
||||
case DNS_KEYALG_SQISIGN:
|
||||
size = 512;
|
||||
break;
|
||||
default:
|
||||
/* unsupported */
|
||||
break;
|
||||
|
||||
@@ -675,13 +675,12 @@ opensslecdsa_extract_private_key(const dst_key_t *key, unsigned char *buf,
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
|
||||
opensslecdsa_createctx(dst_key_t *key ISC_ATTR_UNUSED, dst_context_t *dctx) {
|
||||
isc_result_t ret = ISC_R_SUCCESS;
|
||||
EVP_MD_CTX *evp_md_ctx;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
const EVP_MD *type = NULL;
|
||||
|
||||
UNUSED(key);
|
||||
REQUIRE(opensslecdsa_valid_key_alg(dctx->key->key_alg));
|
||||
REQUIRE(dctx->use == DO_SIGN || dctx->use == DO_VERIFY);
|
||||
|
||||
|
||||
@@ -108,14 +108,14 @@ static isc_result_t
|
||||
openssleddsa_fromlabel(dst_key_t *key, const char *label, const char *pin);
|
||||
|
||||
static isc_result_t
|
||||
openssleddsa_createctx(dst_key_t *key, dst_context_t *dctx) {
|
||||
openssleddsa_createctx(dst_key_t *key ISC_ATTR_UNUSED, dst_context_t *dctx) {
|
||||
isc_buffer_t *buf = NULL;
|
||||
const eddsa_alginfo_t *alginfo =
|
||||
openssleddsa_alg_info(dctx->key->key_alg);
|
||||
|
||||
UNUSED(key);
|
||||
REQUIRE(alginfo != NULL);
|
||||
|
||||
/* The 64 constant here is suspicious */
|
||||
isc_buffer_allocate(dctx->mctx, &buf, 64);
|
||||
dctx->ctxdata.generic = buf;
|
||||
|
||||
@@ -138,27 +138,13 @@ openssleddsa_destroyctx(dst_context_t *dctx) {
|
||||
static isc_result_t
|
||||
openssleddsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
|
||||
isc_buffer_t *buf = (isc_buffer_t *)dctx->ctxdata.generic;
|
||||
isc_buffer_t *nbuf = NULL;
|
||||
isc_region_t r;
|
||||
unsigned int length;
|
||||
isc_result_t result;
|
||||
const eddsa_alginfo_t *alginfo =
|
||||
openssleddsa_alg_info(dctx->key->key_alg);
|
||||
|
||||
REQUIRE(alginfo != NULL);
|
||||
|
||||
result = isc_buffer_copyregion(buf, data);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
length = isc_buffer_length(buf) + data->length + 64;
|
||||
isc_buffer_allocate(dctx->mctx, &nbuf, length);
|
||||
isc_buffer_usedregion(buf, &r);
|
||||
(void)isc_buffer_copyregion(nbuf, &r);
|
||||
(void)isc_buffer_copyregion(nbuf, data);
|
||||
isc_buffer_free(&buf);
|
||||
dctx->ctxdata.generic = nbuf;
|
||||
isc_result_t result = isc_buffer_copyregion(buf, data);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -159,11 +159,10 @@ opensslrsa_valid_key_alg(unsigned int key_alg) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
|
||||
opensslrsa_createctx(dst_key_t *key ISC_ATTR_UNUSED, dst_context_t *dctx) {
|
||||
EVP_MD_CTX *evp_md_ctx;
|
||||
const EVP_MD *type = NULL;
|
||||
|
||||
UNUSED(key);
|
||||
REQUIRE(dctx != NULL && dctx->key != NULL);
|
||||
REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg));
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
{ DNS_KEYALG_ECDSA384, "ECDSA384", 0 }, \
|
||||
{ DNS_KEYALG_ED25519, "ED25519", 0 }, \
|
||||
{ DNS_KEYALG_ED448, "ED448", 0 }, \
|
||||
{ DNS_KEYALG_SQISIGN, "SQISIGN", 0 }, \
|
||||
{ DNS_KEYALG_INDIRECT, "INDIRECT", 0 }, \
|
||||
{ DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \
|
||||
{ DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, { 0, NULL, 0 }
|
||||
|
||||
441
lib/dns/sqisignhd_link.c
Normal file
441
lib/dns/sqisignhd_link.c
Normal file
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* 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 https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#define ENABLE_SIGN
|
||||
|
||||
#define SQISIGN_BUILD_TYPE_REF 1
|
||||
#define SQISIGN_VARIANT lvl1
|
||||
|
||||
#include <sqisign/sig.h>
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/safe.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/keyvalues.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
#include "dst_parse.h"
|
||||
#include "isc/result.h"
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_createctx(dst_key_t *key ISC_ATTR_UNUSED, dst_context_t *dctx) {
|
||||
REQUIRE(dctx != NULL && dctx->key != NULL);
|
||||
REQUIRE(dctx->key->key_alg == DST_ALG_SQISIGN);
|
||||
|
||||
isc_buffer_t *buf = NULL;
|
||||
|
||||
isc_buffer_allocate(dctx->mctx, &buf, 64);
|
||||
dctx->ctxdata.generic = buf;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
dst__sqisign_destroyctx(dst_context_t *dctx) {
|
||||
REQUIRE(dctx != NULL && dctx->key != NULL);
|
||||
REQUIRE(dctx->key->key_alg == DST_ALG_SQISIGN);
|
||||
|
||||
isc_buffer_t *buf = dctx->ctxdata.generic;
|
||||
if (buf != NULL) {
|
||||
isc_buffer_free(&buf);
|
||||
dctx->ctxdata.generic = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_adddata(dst_context_t *dctx, const isc_region_t *data) {
|
||||
REQUIRE(dctx != NULL && dctx->key != NULL);
|
||||
REQUIRE(dctx->key->key_alg == DST_ALG_SQISIGN);
|
||||
|
||||
isc_buffer_t *buf = dctx->ctxdata.generic;
|
||||
isc_result_t result = isc_buffer_copyregion(buf, data);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_sign(dst_context_t *dctx, isc_buffer_t *sig) {
|
||||
REQUIRE(dctx != NULL && dctx->key != NULL);
|
||||
REQUIRE(dctx->key->key_alg == DST_ALG_SQISIGN);
|
||||
|
||||
isc_result_t result = ISC_R_UNSET;
|
||||
dst_key_t *key = dctx->key;
|
||||
isc_buffer_t *buf = dctx->ctxdata.generic;
|
||||
isc_region_t tbsreg;
|
||||
isc_region_t sigreg;
|
||||
unsigned long long siglen;
|
||||
uint8_t *sigbuf = NULL;
|
||||
|
||||
isc_buffer_availableregion(sig, &sigreg);
|
||||
if (sigreg.length < DNS_SIG_SQISIGNSIZE) {
|
||||
result = ISC_R_NOSPACE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
isc_buffer_usedregion(buf, &tbsreg);
|
||||
|
||||
sigbuf = isc_mem_get(dctx->mctx, DNS_SIG_SQISIGNSIZE + tbsreg.length);
|
||||
int status = sqisign_sign(sigbuf, &siglen, tbsreg.base, tbsreg.length,
|
||||
key->keydata.keypair.priv);
|
||||
if (status != 0) {
|
||||
result = DST_R_SIGNFAILURE;
|
||||
isc_log_write(dctx->category, DNS_LOGMODULE_CRYPTO,
|
||||
ISC_LOG_WARNING,
|
||||
"sqisign_sign (%s:%d) failed (%s)", __FILE__,
|
||||
__LINE__, isc_result_totext(result));
|
||||
goto done;
|
||||
}
|
||||
isc_buffer_putmem(sig, sigbuf, DNS_SIG_SQISIGNSIZE);
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
done:
|
||||
if (sigbuf != NULL) {
|
||||
isc_mem_put(dctx->mctx, sigbuf,
|
||||
DNS_SIG_SQISIGNSIZE + tbsreg.length);
|
||||
}
|
||||
isc_buffer_free(&buf);
|
||||
dctx->ctxdata.generic = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_verify(dst_context_t *dctx, int maxbits ISC_ATTR_UNUSED,
|
||||
const isc_region_t *sigreg) {
|
||||
REQUIRE(dctx != NULL && dctx->key != NULL);
|
||||
REQUIRE(dctx->key->key_alg == DST_ALG_SQISIGN);
|
||||
|
||||
isc_result_t result = ISC_R_UNSET;
|
||||
dst_key_t *key = dctx->key;
|
||||
isc_buffer_t *buf = dctx->ctxdata.generic;
|
||||
isc_region_t tbsreg;
|
||||
|
||||
if (sigreg->length != DNS_SIG_SQISIGNSIZE) {
|
||||
result = DST_R_VERIFYFAILURE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
isc_buffer_usedregion(buf, &tbsreg);
|
||||
|
||||
int status = sqisign_verify(tbsreg.base, tbsreg.length, sigreg->base,
|
||||
sigreg->length, key->keydata.keypair.pub);
|
||||
if (status != 0) {
|
||||
result = DST_R_VERIFYFAILURE;
|
||||
/* FIXME: Is it really a warning if the verification fails */
|
||||
isc_log_write(dctx->category, DNS_LOGMODULE_CRYPTO,
|
||||
ISC_LOG_WARNING,
|
||||
"sqisign_verify (%s:%d) failed (%s)", __FILE__,
|
||||
__LINE__, isc_result_totext(result));
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
done:
|
||||
isc_buffer_free(&buf);
|
||||
dctx->ctxdata.generic = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
dst__sqisign_compare(const dst_key_t *key1, const dst_key_t *key2) {
|
||||
uint8_t *pk1 = key1->keydata.keypair.pub;
|
||||
uint8_t *pk2 = key2->keydata.keypair.pub;
|
||||
|
||||
uint8_t *sk1 = key1->keydata.keypair.priv;
|
||||
uint8_t *sk2 = key2->keydata.keypair.priv;
|
||||
|
||||
if ((pk1 == pk2) && (sk1 == sk2)) {
|
||||
/* The keys are identical or all NULL */
|
||||
return true;
|
||||
} else if (pk1 == NULL || pk2 == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(pk1, pk2, DNS_KEY_SQISIGNSIZE) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sk1 == sk2) {
|
||||
/* The keys are identical or both NULL */
|
||||
return true;
|
||||
} else if (sk1 == NULL || sk1 == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(sk1, sk2, DNS_SEC_SQISIGNSIZE) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_generate(dst_key_t *key, int unused ISC_ATTR_UNUSED,
|
||||
void (*callback ISC_ATTR_UNUSED)(int)) {
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(key->key_alg == DST_ALG_SQISIGN);
|
||||
REQUIRE(key->keydata.keypair.pub == NULL &&
|
||||
key->keydata.keypair.priv == NULL);
|
||||
|
||||
isc_result_t result = ISC_R_UNSET;
|
||||
uint8_t *pk = isc_mem_get(key->mctx, DNS_KEY_SQISIGNSIZE);
|
||||
uint8_t *sk = isc_mem_get(key->mctx, DNS_SEC_SQISIGNSIZE);
|
||||
|
||||
int status = sqisign_keypair(pk, sk);
|
||||
if (status != 0) {
|
||||
result = DST_R_CRYPTOFAILURE;
|
||||
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_CRYPTO,
|
||||
ISC_LOG_WARNING,
|
||||
"sqisign_keypair (%s:%d) failed (%s)", __FILE__,
|
||||
__LINE__, isc_result_totext(result));
|
||||
goto done;
|
||||
}
|
||||
|
||||
key->keydata.keypair.pub = pk;
|
||||
key->keydata.keypair.priv = sk;
|
||||
key->key_size = DNS_KEY_SQISIGNSIZE * 8;
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
done:
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(key->mctx, pk, DNS_KEY_SQISIGNSIZE);
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_todns(const dst_key_t *key, isc_buffer_t *data) {
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(key->key_alg == DST_ALG_SQISIGN);
|
||||
|
||||
uint8_t *pk = key->keydata.keypair.pub;
|
||||
isc_region_t r;
|
||||
|
||||
isc_buffer_availableregion(data, &r);
|
||||
if (r.length < DNS_KEY_SQISIGNSIZE) {
|
||||
return ISC_R_NOSPACE;
|
||||
}
|
||||
|
||||
isc_buffer_putmem(data, pk, DNS_KEY_SQISIGNSIZE);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_fromdns(dst_key_t *key, isc_buffer_t *data) {
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(key->key_alg == DST_ALG_SQISIGN);
|
||||
REQUIRE(key->keydata.keypair.pub == NULL);
|
||||
|
||||
isc_region_t r;
|
||||
|
||||
isc_buffer_remainingregion(data, &r);
|
||||
if (r.length == 0) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
INSIST(r.length == DNS_KEY_SQISIGNSIZE);
|
||||
|
||||
key->keydata.keypair.pub = isc_mem_get(key->mctx, DNS_KEY_SQISIGNSIZE);
|
||||
memmove(key->keydata.keypair.pub, r.base, r.length);
|
||||
key->key_size = DNS_KEY_SQISIGNSIZE * 8;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static bool
|
||||
dst__sqisign_isprivate(const dst_key_t *key) {
|
||||
return key->keydata.keypair.priv != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dst__sqisign_destroy(dst_key_t *key) {
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(key->key_alg == DST_ALG_SQISIGN);
|
||||
REQUIRE(key->keydata.keypair.pub != NULL);
|
||||
|
||||
if (key->keydata.keypair.priv != NULL) {
|
||||
isc_mem_put(key->mctx, key->keydata.keypair.priv,
|
||||
DNS_SEC_SQISIGNSIZE);
|
||||
}
|
||||
|
||||
isc_mem_put(key->mctx, key->keydata.keypair.pub, DNS_KEY_SQISIGNSIZE);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_tofile(const dst_key_t *key, const char *directory) {
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(key->key_alg == DST_ALG_SQISIGN);
|
||||
|
||||
dst_private_t priv;
|
||||
int i = 0;
|
||||
|
||||
if (key->keydata.pkeypair.pub == NULL) {
|
||||
return DST_R_NULLKEY;
|
||||
}
|
||||
|
||||
INSIST(!key->external);
|
||||
|
||||
priv.elements[i].tag = TAG_SQISIGN_PUBLICKEY;
|
||||
priv.elements[i].length = DNS_KEY_SQISIGNSIZE;
|
||||
priv.elements[i].data = key->keydata.keypair.pub;
|
||||
i++;
|
||||
|
||||
if (dst_key_isprivate(key)) {
|
||||
priv.elements[i].tag = TAG_SQISIGN_SECRETKEY;
|
||||
priv.elements[i].length = DNS_SEC_SQISIGNSIZE;
|
||||
priv.elements[i].data = key->keydata.keypair.priv;
|
||||
i++;
|
||||
}
|
||||
|
||||
priv.nelements = i;
|
||||
|
||||
return dst__privstruct_writefile(key, &priv, directory);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
dst__sqisign_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
|
||||
REQUIRE(key != NULL);
|
||||
REQUIRE(key->key_alg == DST_ALG_SQISIGN);
|
||||
REQUIRE(key->keydata.keypair.pub == NULL &&
|
||||
key->keydata.keypair.priv == NULL);
|
||||
|
||||
isc_result_t result = ISC_R_UNSET;
|
||||
dst_private_t priv;
|
||||
uint8_t *pk = isc_mem_get(key->mctx, DNS_KEY_SQISIGNSIZE);
|
||||
uint8_t *sk = isc_mem_get(key->mctx, DNS_SEC_SQISIGNSIZE);
|
||||
|
||||
result = dst__privstruct_parse(key, DST_ALG_SQISIGN, lexer, key->mctx,
|
||||
&priv);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (key->external) {
|
||||
if (priv.nelements != 0 || pub == NULL) {
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
key->keydata.pkeypair.priv = pub->keydata.pkeypair.priv;
|
||||
key->keydata.pkeypair.pub = pub->keydata.pkeypair.pub;
|
||||
pub->keydata.pkeypair.priv = NULL;
|
||||
pub->keydata.pkeypair.pub = NULL;
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < priv.nelements; i++) {
|
||||
switch (priv.elements[i].tag) {
|
||||
case TAG_SQISIGN_PUBLICKEY:
|
||||
if (priv.elements[i].length != DNS_KEY_SQISIGNSIZE) {
|
||||
result = DST_R_INVALIDPUBLICKEY;
|
||||
goto done;
|
||||
}
|
||||
memmove(pk, priv.elements[i].data, DNS_KEY_SQISIGNSIZE);
|
||||
break;
|
||||
case TAG_SQISIGN_SECRETKEY:
|
||||
if (priv.elements[i].length != DNS_SEC_SQISIGNSIZE) {
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto done;
|
||||
}
|
||||
memmove(sk, priv.elements[i].data, DNS_SEC_SQISIGNSIZE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pk == NULL) {
|
||||
result = DST_R_INVALIDPUBLICKEY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sk == NULL) {
|
||||
result = DST_R_INVALIDPRIVATEKEY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
key->keydata.keypair.priv = sk;
|
||||
key->keydata.keypair.pub = pk;
|
||||
key->key_size = DNS_KEY_SQISIGNSIZE * 8;
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
done:
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_safe_memwipe(pk, DNS_KEY_SQISIGNSIZE);
|
||||
isc_mem_put(key->mctx, pk, DNS_KEY_SQISIGNSIZE);
|
||||
|
||||
isc_safe_memwipe(sk, DNS_SEC_SQISIGNSIZE);
|
||||
isc_mem_put(key->mctx, sk, DNS_SEC_SQISIGNSIZE);
|
||||
}
|
||||
|
||||
dst__privstruct_free(&priv, key->mctx);
|
||||
isc_safe_memwipe(&priv, sizeof(priv));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static dst_func_t dst__sqisign_functions = {
|
||||
dst__sqisign_createctx,
|
||||
dst__sqisign_destroyctx,
|
||||
dst__sqisign_adddata,
|
||||
dst__sqisign_sign,
|
||||
dst__sqisign_verify,
|
||||
dst__sqisign_compare,
|
||||
dst__sqisign_generate,
|
||||
dst__sqisign_isprivate,
|
||||
dst__sqisign_destroy,
|
||||
dst__sqisign_todns,
|
||||
dst__sqisign_fromdns,
|
||||
dst__sqisign_tofile,
|
||||
dst__sqisign_parse,
|
||||
NULL, /*%< fromlabel */
|
||||
NULL, /*%< dump */
|
||||
NULL, /*%< restore */
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
check_algorithm(unsigned char algorithm) {
|
||||
switch (algorithm) {
|
||||
case DST_ALG_SQISIGN:
|
||||
break;
|
||||
default:
|
||||
return ISC_R_NOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: check that we can verify SQISignHD signature
|
||||
* like we do with the other algorithms.
|
||||
*/
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
dst__sqisign_init(dst_func_t **funcp, unsigned char algorithm) {
|
||||
REQUIRE(funcp != NULL);
|
||||
|
||||
if (*funcp == NULL) {
|
||||
if (check_algorithm(algorithm) == ISC_R_SUCCESS) {
|
||||
*funcp = &dst__sqisign_functions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,6 +278,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
||||
case DNS_KEYALG_ECDSA384:
|
||||
case DNS_KEYALG_ED25519:
|
||||
case DNS_KEYALG_ED448:
|
||||
case DNS_KEYALG_SQISIGN:
|
||||
cfg_obj_log(obj, ISC_LOG_WARNING,
|
||||
"dnssec-policy: key algorithm %s "
|
||||
"has predefined length; ignoring "
|
||||
|
||||
Reference in New Issue
Block a user