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], [ ...@@ -163,6 +163,12 @@ PKG_CHECK_MODULES([gnutls], [gnutls >= 3.3], [
[enable_ed25519=no], [enable_ed25519=no],
[#include <gnutls/gnutls.h>]) [#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_CHECK_FUNC([gnutls_privkey_sign_data2],
[AC_DEFINE([HAVE_SIGN_DATA2], [1], [gnutls_privkey_sign_data2 available])]) [AC_DEFINE([HAVE_SIGN_DATA2], [1], [gnutls_privkey_sign_data2 available])])
...@@ -673,6 +679,7 @@ result_msg_base=" Knot DNS $VERSION ...@@ -673,6 +679,7 @@ result_msg_base=" Knot DNS $VERSION
POSIX capabilities ${enable_cap_ng} POSIX capabilities ${enable_cap_ng}
PKCS #11 support: ${enable_pkcs11} PKCS #11 support: ${enable_pkcs11}
Ed25519 support: ${enable_ed25519} Ed25519 support: ${enable_ed25519}
GOST support: ${enable_gost}
Code coverage: ${enable_code_coverage} Code coverage: ${enable_code_coverage}
Sanitizer: ${with_sanitizer} Sanitizer: ${with_sanitizer}
LibFuzzer: ${with_fuzzer} LibFuzzer: ${with_fuzzer}
......
...@@ -86,6 +86,7 @@ typedef enum dnssec_key_algorithm { ...@@ -86,6 +86,7 @@ typedef enum dnssec_key_algorithm {
DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3 = 7, DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3 = 7,
DNSSEC_KEY_ALGORITHM_RSA_SHA256 = 8, DNSSEC_KEY_ALGORITHM_RSA_SHA256 = 8,
DNSSEC_KEY_ALGORITHM_RSA_SHA512 = 10, DNSSEC_KEY_ALGORITHM_RSA_SHA512 = 10,
DNSSEC_KEY_ALGORITHM_ECC_GOST = 12,
DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256 = 13, DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256 = 13,
DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384 = 14, DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384 = 14,
DNSSEC_KEY_ALGORITHM_ED25519 = 15, DNSSEC_KEY_ALGORITHM_ED25519 = 15,
...@@ -293,6 +294,7 @@ typedef enum dnssec_key_digest { ...@@ -293,6 +294,7 @@ typedef enum dnssec_key_digest {
DNSSEC_KEY_DIGEST_INVALID = 0, DNSSEC_KEY_DIGEST_INVALID = 0,
DNSSEC_KEY_DIGEST_SHA1 = 1, DNSSEC_KEY_DIGEST_SHA1 = 1,
DNSSEC_KEY_DIGEST_SHA256 = 2, DNSSEC_KEY_DIGEST_SHA256 = 2,
DNSSEC_DIGEST_GOSTR_94 = 3,
DNSSEC_KEY_DIGEST_SHA384 = 4, DNSSEC_KEY_DIGEST_SHA384 = 4,
} dnssec_key_digest_t; } dnssec_key_digest_t;
......
...@@ -62,6 +62,12 @@ static const struct limits *get_limits(dnssec_key_algorithm_t algorithm) ...@@ -62,6 +62,12 @@ static const struct limits *get_limits(dnssec_key_algorithm_t algorithm)
.def = 456, .def = 456,
}; };
static const struct limits GOST = {
.min = 512,
.max = 512,
.def = 512,
};
switch (algorithm) { switch (algorithm) {
case DNSSEC_KEY_ALGORITHM_RSA_SHA1: case DNSSEC_KEY_ALGORITHM_RSA_SHA1:
case DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3: case DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3:
...@@ -76,6 +82,8 @@ static const struct limits *get_limits(dnssec_key_algorithm_t algorithm) ...@@ -76,6 +82,8 @@ static const struct limits *get_limits(dnssec_key_algorithm_t algorithm)
return &ED25519; return &ED25519;
case DNSSEC_KEY_ALGORITHM_ED448: case DNSSEC_KEY_ALGORITHM_ED448:
return &ED448; return &ED448;
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return &GOST;
default: default:
return NULL; return NULL;
} }
...@@ -94,9 +102,13 @@ gnutls_pk_algorithm_t algorithm_to_gnutls(dnssec_key_algorithm_t dnssec) ...@@ -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_P256_SHA256:
case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384: case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384:
return GNUTLS_PK_EC; return GNUTLS_PK_EC;
case DNSSEC_KEY_ALGORITHM_ED25519:
#ifdef HAVE_ED25519 #ifdef HAVE_ED25519
case DNSSEC_KEY_ALGORITHM_ED25519:
return GNUTLS_PK_EDDSA_ED25519; return GNUTLS_PK_EDDSA_ED25519;
#endif
#ifdef HAVE_GOST
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return GNUTLS_PK_GOST_01;
#endif #endif
case DNSSEC_KEY_ALGORITHM_ED448: case DNSSEC_KEY_ALGORITHM_ED448:
default: default:
......
...@@ -189,6 +189,42 @@ static int eddsa_pubkey_to_rdata(gnutls_pubkey_t key, dnssec_binary_t *rdata) ...@@ -189,6 +189,42 @@ static int eddsa_pubkey_to_rdata(gnutls_pubkey_t key, dnssec_binary_t *rdata)
} }
#endif #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 ------------------------------------------------------*/ /* -- crypto to DNSSEC ------------------------------------------------------*/
/*! /*!
...@@ -322,6 +358,32 @@ static int eddsa_rdata_to_pubkey(const dnssec_binary_t *rdata, gnutls_pubkey_t k ...@@ -322,6 +358,32 @@ static int eddsa_rdata_to_pubkey(const dnssec_binary_t *rdata, gnutls_pubkey_t k
} }
#endif #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 --------------------------------------------------------- */ /* -- internal API --------------------------------------------------------- */
/*! /*!
...@@ -345,6 +407,9 @@ int convert_pubkey_to_dnskey(gnutls_pubkey_t key, dnssec_binary_t *rdata) ...@@ -345,6 +407,9 @@ int convert_pubkey_to_dnskey(gnutls_pubkey_t key, dnssec_binary_t *rdata)
#endif #endif
#ifdef HAVE_ED448 #ifdef HAVE_ED448
case GNUTLS_PK_EDDSA_ED448: return eddsa_pubkey_to_rdata(key, rdata); 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 #endif
default: return DNSSEC_INVALID_KEY_ALGORITHM; default: return DNSSEC_INVALID_KEY_ALGORITHM;
} }
...@@ -369,6 +434,9 @@ int convert_dnskey_to_pubkey(uint8_t algorithm, const dnssec_binary_t *rdata, ...@@ -369,6 +434,9 @@ int convert_dnskey_to_pubkey(uint8_t algorithm, const dnssec_binary_t *rdata,
#endif #endif
#ifdef HAVE_ED448 #ifdef HAVE_ED448
case GNUTLS_PK_EDDSA_ED448: return eddsa_rdata_to_pubkey(rdata, key); 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 #endif
default: return DNSSEC_INVALID_KEY_ALGORITHM; default: return DNSSEC_INVALID_KEY_ALGORITHM;
} }
......
...@@ -34,6 +34,9 @@ static gnutls_digest_algorithm_t lookup_algorithm(dnssec_key_digest_t 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_SHA1: return GNUTLS_DIG_SHA1;
case DNSSEC_KEY_DIGEST_SHA256: return GNUTLS_DIG_SHA256; case DNSSEC_KEY_DIGEST_SHA256: return GNUTLS_DIG_SHA256;
case DNSSEC_KEY_DIGEST_SHA384: return GNUTLS_DIG_SHA384; case DNSSEC_KEY_DIGEST_SHA384: return GNUTLS_DIG_SHA384;
#ifdef HAVE_GOST
case DNSSEC_DIGEST_GOSTR_94: return GNUTLS_DIG_GOSTR_94;
#endif
default: default:
return GNUTLS_DIG_UNKNOWN; return GNUTLS_DIG_UNKNOWN;
}; };
......
...@@ -179,6 +179,12 @@ static const algorithm_functions_t eddsa_functions = { ...@@ -179,6 +179,12 @@ static const algorithm_functions_t eddsa_functions = {
.dnssec_to_x509 = eddsa_copy_signature, .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 --------------------------------------------- */ /* -- crypto helper functions --------------------------------------------- */
static const algorithm_functions_t *get_functions(const dnssec_key_t *key) 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) ...@@ -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_ED25519:
case DNSSEC_KEY_ALGORITHM_ED448: case DNSSEC_KEY_ALGORITHM_ED448:
return &eddsa_functions; return &eddsa_functions;
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return &gost_functions;
default: default:
return NULL; return NULL;
} }
...@@ -223,6 +231,10 @@ static gnutls_digest_algorithm_t get_digest_algorithm(const dnssec_key_t *key) ...@@ -223,6 +231,10 @@ static gnutls_digest_algorithm_t get_digest_algorithm(const dnssec_key_t *key)
return GNUTLS_DIG_SHA384; return GNUTLS_DIG_SHA384;
case DNSSEC_KEY_ALGORITHM_ED25519: case DNSSEC_KEY_ALGORITHM_ED25519:
return GNUTLS_DIG_SHA512; return GNUTLS_DIG_SHA512;
#ifdef HAVE_GOST
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return GNUTLS_DIG_GOSTR_94;
#endif
case DNSSEC_KEY_ALGORITHM_ED448: case DNSSEC_KEY_ALGORITHM_ED448:
default: default:
return GNUTLS_DIG_UNKNOWN; return GNUTLS_DIG_UNKNOWN;
...@@ -246,13 +258,17 @@ static gnutls_sign_algorithm_t get_sign_algorithm(const dnssec_key_t *key) ...@@ -246,13 +258,17 @@ static gnutls_sign_algorithm_t get_sign_algorithm(const dnssec_key_t *key)
return GNUTLS_SIGN_RSA_SHA512; return GNUTLS_SIGN_RSA_SHA512;
case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384: case DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384:
return GNUTLS_SIGN_ECDSA_SHA384; return GNUTLS_SIGN_ECDSA_SHA384;
case DNSSEC_KEY_ALGORITHM_ED25519:
#ifdef HAVE_ED25519 #ifdef HAVE_ED25519
case DNSSEC_KEY_ALGORITHM_ED25519:
return GNUTLS_SIGN_EDDSA_ED25519; return GNUTLS_SIGN_EDDSA_ED25519;
#endif #endif
case DNSSEC_KEY_ALGORITHM_ED448:
#ifdef HAVE_ED448 #ifdef HAVE_ED448
case DNSSEC_KEY_ALGORITHM_ED448:
return GNUTLS_SIGN_EDDSA_ED448; return GNUTLS_SIGN_EDDSA_ED448;
#endif
#ifdef HAVE_GOST
case DNSSEC_KEY_ALGORITHM_ECC_GOST:
return GNUTLS_SIGN_GOST_94;
#endif #endif
default: default:
return GNUTLS_SIGN_UNKNOWN; return GNUTLS_SIGN_UNKNOWN;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
deleg.example.com. 3600 IN NS deleg.example.com. deleg.example.com. 3600 IN NS deleg.example.com.
3600 A 192.0.2.1 3600 A 192.0.2.1
3600 IN DS 60485 5 3 ( 2BB183AF5F22588179A53B0A 3600 IN DS 60485 5 13 ( 2BB183AF5F22588179A53B0A
98631FAD1A292118 ) 98631FAD1A292118 )
3600 IN DS 60485 5 7 ( 2BB183AF5F22588179A53B0A 3600 IN DS 60485 5 7 ( 2BB183AF5F22588179A53B0A
98631FAD1A292118 ) 98631FAD1A292118 )
......
...@@ -83,7 +83,7 @@ static void test_errors(const struct key_parameters *params) ...@@ -83,7 +83,7 @@ static void test_errors(const struct key_parameters *params)
r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, NULL); r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, NULL);
is_int(DNSSEC_EINVAL, r, "dnssec_key_create_ds() no RDATA buffer"); 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"); is_int(DNSSEC_INVALID_DS_ALGORITHM, r, "dnssec_key_create_ds() unsupported algorithm");
r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, &ds); 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