add GOST algorithm support

The other `#ifdef HAVE_*` were moved in switches,
so that they don't rely on being the last before `default:`

The tests needed fixing up cases of using GOST as invalid values.
parent 5e0d4939
......@@ -163,6 +163,12 @@ PKG_CHECK_MODULES([gnutls], [gnutls >= 3.3], [
[enable_ed25519=no],
[#include <gnutls/gnutls.h>])
AC_CHECK_DECL([GNUTLS_PK_GOST_01],
[AC_DEFINE([HAVE_GOST], [1], [GnuTLS GOST support available])
enable_gost=yes],
[enable_gost=no],
[#include <gnutls/gnutls.h>])
AC_CHECK_FUNC([gnutls_privkey_sign_data2],
[AC_DEFINE([HAVE_SIGN_DATA2], [1], [gnutls_privkey_sign_data2 available])])
......@@ -673,6 +679,7 @@ result_msg_base=" Knot DNS $VERSION
POSIX capabilities ${enable_cap_ng}
PKCS #11 support: ${enable_pkcs11}
Ed25519 support: ${enable_ed25519}
GOST support: ${enable_gost}
Code coverage: ${enable_code_coverage}
Sanitizer: ${with_sanitizer}
LibFuzzer: ${with_fuzzer}
......
......@@ -86,6 +86,7 @@ typedef enum dnssec_key_algorithm {
DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3 = 7,
DNSSEC_KEY_ALGORITHM_RSA_SHA256 = 8,
DNSSEC_KEY_ALGORITHM_RSA_SHA512 = 10,
DNSSEC_KEY_ALGORITHM_ECC_GOST = 12,
DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256 = 13,
DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384 = 14,
DNSSEC_KEY_ALGORITHM_ED25519 = 15,
......@@ -293,6 +294,7 @@ typedef enum dnssec_key_digest {
DNSSEC_KEY_DIGEST_INVALID = 0,
DNSSEC_KEY_DIGEST_SHA1 = 1,
DNSSEC_KEY_DIGEST_SHA256 = 2,
DNSSEC_DIGEST_GOSTR_94 = 3,
DNSSEC_KEY_DIGEST_SHA384 = 4,
} dnssec_key_digest_t;
......
......@@ -62,6 +62,12 @@ static const struct limits *get_limits(dnssec_key_algorithm_t algorithm)
.def = 456,
};
static const struct limits GOST = {
.min = 512,
.max = 512,
.def = 512,
};
switch (algorithm) {
case DNSSEC_KEY_ALGORITHM_RSA_SHA1:
case DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3:
......@@ -76,6 +82,8 @@ static const struct limits *get_limits(dnssec_key_algorithm_t algorithm)
return &ED25519;
case DNSSEC_KEY_ALGORITHM_ED448:
return &ED448;
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return &GOST;
default:
return NULL;
}
......@@ -94,9 +102,13 @@ gnutls_pk_algorithm_t algorithm_to_gnutls(dnssec_key_algorithm_t dnssec)
case DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256:
case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384:
return GNUTLS_PK_EC;
case DNSSEC_KEY_ALGORITHM_ED25519:
#ifdef HAVE_ED25519
case DNSSEC_KEY_ALGORITHM_ED25519:
return GNUTLS_PK_EDDSA_ED25519;
#endif
#ifdef HAVE_GOST
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return GNUTLS_PK_GOST_01;
#endif
case DNSSEC_KEY_ALGORITHM_ED448:
default:
......
......@@ -189,6 +189,42 @@ static int eddsa_pubkey_to_rdata(gnutls_pubkey_t key, dnssec_binary_t *rdata)
}
#endif
#ifdef HAVE_GOST
static inline void memcpy_reverse(uint8_t *dest, const uint8_t *src, size_t len)
{
for (size_t i = 0; i < len; ++i) {
dest[len - 1 - i] = src[i];
}
}
static int gost_pubkey_to_rdata(gnutls_pubkey_t key, dnssec_binary_t *rdata)
{
assert(key);
assert(rdata);
int result = dnssec_binary_alloc(rdata, 64);
if (result != DNSSEC_EOK) {
return result;
}
_cleanup_datum_ gnutls_datum_t point_x = { .data = NULL, .size = 0 },
point_y = { .data = NULL, .size = 0 };
/* Note: we might possibly verify the curve and digest IDs returned. */
result = gnutls_pubkey_export_gost_raw2(key, NULL, NULL, NULL,
&point_x, &point_y, 0);
if (result != GNUTLS_E_SUCCESS) {
return DNSSEC_KEY_EXPORT_ERROR;
}
assert(point_x.size == 32 && point_y.size == 32);
/* We need to reverse byte order of the two points. */
memcpy_reverse(rdata->data, point_x.data, 32);
memcpy_reverse(rdata->data + 32, point_y.data, 32);
return DNSSEC_EOK;
}
#endif
/* -- crypto to DNSSEC ------------------------------------------------------*/
/*!
......@@ -322,6 +358,32 @@ static int eddsa_rdata_to_pubkey(const dnssec_binary_t *rdata, gnutls_pubkey_t k
}
#endif
#ifdef HAVE_GOST
static int gost_rdata_to_pubkey(const dnssec_binary_t *rdata, gnutls_pubkey_t key)
{
assert(rdata);
assert(key);
/* Unfortunately we have to reverse the byte order of the two points. */
uint8_t buf[2][32];
assert(rdata->size == sizeof(buf));
const gnutls_datum_t point_x = { .data = buf[0], .size = 32 };
const gnutls_datum_t point_y = { .data = buf[1], .size = 32 };
memcpy_reverse(point_x.data, rdata->data, 32);
memcpy_reverse(point_y.data, rdata->data + 32, 32);
int result = gnutls_pubkey_import_gost_raw(key, GNUTLS_PK_GOST_01,
GNUTLS_DIG_GOSTR_94, GNUTLS_GOST_PARAMSET_UNKNOWN,
&point_x, &point_y);
if (result != GNUTLS_E_SUCCESS) {
return DNSSEC_KEY_IMPORT_ERROR;
}
return DNSSEC_EOK;
}
#endif
/* -- internal API --------------------------------------------------------- */
/*!
......@@ -345,6 +407,9 @@ int convert_pubkey_to_dnskey(gnutls_pubkey_t key, dnssec_binary_t *rdata)
#endif
#ifdef HAVE_ED448
case GNUTLS_PK_EDDSA_ED448: return eddsa_pubkey_to_rdata(key, rdata);
#endif
#ifdef HAVE_GOST
case GNUTLS_PK_GOST_01: return gost_pubkey_to_rdata(key, rdata);
#endif
default: return DNSSEC_INVALID_KEY_ALGORITHM;
}
......@@ -369,6 +434,9 @@ int convert_dnskey_to_pubkey(uint8_t algorithm, const dnssec_binary_t *rdata,
#endif
#ifdef HAVE_ED448
case GNUTLS_PK_EDDSA_ED448: return eddsa_rdata_to_pubkey(rdata, key);
#endif
#ifdef HAVE_GOST
case GNUTLS_PK_GOST_01: return gost_rdata_to_pubkey(rdata, key);
#endif
default: return DNSSEC_INVALID_KEY_ALGORITHM;
}
......
......@@ -34,6 +34,9 @@ static gnutls_digest_algorithm_t lookup_algorithm(dnssec_key_digest_t algorithm)
case DNSSEC_KEY_DIGEST_SHA1: return GNUTLS_DIG_SHA1;
case DNSSEC_KEY_DIGEST_SHA256: return GNUTLS_DIG_SHA256;
case DNSSEC_KEY_DIGEST_SHA384: return GNUTLS_DIG_SHA384;
#ifdef HAVE_GOST
case DNSSEC_DIGEST_GOSTR_94: return GNUTLS_DIG_GOSTR_94;
#endif
default:
return GNUTLS_DIG_UNKNOWN;
};
......
......@@ -179,6 +179,12 @@ static const algorithm_functions_t eddsa_functions = {
.dnssec_to_x509 = eddsa_copy_signature,
};
#define gost_copy_signature rsa_copy_signature
static const algorithm_functions_t gost_functions = {
.x509_to_dnssec = gost_copy_signature,
.dnssec_to_x509 = gost_copy_signature,
};
/* -- crypto helper functions --------------------------------------------- */
static const algorithm_functions_t *get_functions(const dnssec_key_t *key)
......@@ -197,6 +203,8 @@ static const algorithm_functions_t *get_functions(const dnssec_key_t *key)
case DNSSEC_KEY_ALGORITHM_ED25519:
case DNSSEC_KEY_ALGORITHM_ED448:
return &eddsa_functions;
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return &gost_functions;
default:
return NULL;
}
......@@ -223,6 +231,10 @@ static gnutls_digest_algorithm_t get_digest_algorithm(const dnssec_key_t *key)
return GNUTLS_DIG_SHA384;
case DNSSEC_KEY_ALGORITHM_ED25519:
return GNUTLS_DIG_SHA512;
#ifdef HAVE_GOST
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return GNUTLS_DIG_GOSTR_94;
#endif
case DNSSEC_KEY_ALGORITHM_ED448:
default:
return GNUTLS_DIG_UNKNOWN;
......@@ -246,13 +258,17 @@ static gnutls_sign_algorithm_t get_sign_algorithm(const dnssec_key_t *key)
return GNUTLS_SIGN_RSA_SHA512;
case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384:
return GNUTLS_SIGN_ECDSA_SHA384;
case DNSSEC_KEY_ALGORITHM_ED25519:
#ifdef HAVE_ED25519
case DNSSEC_KEY_ALGORITHM_ED25519:
return GNUTLS_SIGN_EDDSA_ED25519;
#endif
case DNSSEC_KEY_ALGORITHM_ED448:
#ifdef HAVE_ED448
case DNSSEC_KEY_ALGORITHM_ED448:
return GNUTLS_SIGN_EDDSA_ED448;
#endif
#ifdef HAVE_GOST
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return GNUTLS_SIGN_GOST_94;
#endif
default:
return GNUTLS_SIGN_UNKNOWN;
......
......@@ -2,7 +2,7 @@
deleg.example.com. 3600 IN NS deleg.example.com.
3600 A 192.0.2.1
3600 IN DS 60485 5 3 ( 2BB183AF5F22588179A53B0A
3600 IN DS 60485 5 13 ( 2BB183AF5F22588179A53B0A
98631FAD1A292118 )
3600 IN DS 60485 5 7 ( 2BB183AF5F22588179A53B0A
98631FAD1A292118 )
......
......@@ -83,7 +83,7 @@ static void test_errors(const struct key_parameters *params)
r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, NULL);
is_int(DNSSEC_EINVAL, r, "dnssec_key_create_ds() no RDATA buffer");
r = dnssec_key_create_ds(key, 3, &ds);
r = dnssec_key_create_ds(key, 13, &ds);
is_int(DNSSEC_INVALID_DS_ALGORITHM, r, "dnssec_key_create_ds() unsupported algorithm");
r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, &ds);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment