#include "sort-util.h"
#include "string-table.h"
+#if PREFER_OPENSSL
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(RSA*, RSA_free, NULL);
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL);
+# pragma GCC diagnostic pop
+#endif
+
#define VERIFY_RRS_MAX 256
#define MAX_KEY_SIZE (32*1024)
const void *data, size_t data_size,
const void *exponent, size_t exponent_size,
const void *modulus, size_t modulus_size) {
+ int r;
#if PREFER_OPENSSL
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
_cleanup_(RSA_freep) RSA *rpubkey = NULL;
_cleanup_(EVP_PKEY_freep) EVP_PKEY *epubkey = NULL;
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = NULL;
_cleanup_(BN_freep) BIGNUM *e = NULL, *m = NULL;
- int r;
assert(hash_algorithm);
if (!rpubkey)
return -ENOMEM;
- if (RSA_set0_key(rpubkey, BN_dup(m), BN_dup(e), NULL) <= 0)
+ if (RSA_set0_key(rpubkey, m, e, NULL) <= 0)
return -EIO;
+ e = m = NULL;
assert((size_t) RSA_size(rpubkey) == signature_size);
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Signature verification failed: 0x%lx", ERR_get_error());
- return r;
-
+# pragma GCC diagnostic pop
#else
gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
gcry_mpi_t n = NULL, e = NULL, s = NULL;
gcry_error_t ge;
- int r;
assert(hash_algorithm);
gcry_sexp_release(signature_sexp);
if (data_sexp)
gcry_sexp_release(data_sexp);
-
- return r;
#endif
+ return r;
}
static int dnssec_rsa_verify(
const void *signature_s, size_t signature_s_size,
const void *data, size_t data_size,
const void *key, size_t key_size) {
+ int k;
#if PREFER_OPENSSL
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
_cleanup_(EC_GROUP_freep) EC_GROUP *ec_group = NULL;
_cleanup_(EC_POINT_freep) EC_POINT *p = NULL;
_cleanup_(EC_KEY_freep) EC_KEY *eckey = NULL;
_cleanup_(BN_CTX_freep) BN_CTX *bctx = NULL;
_cleanup_(BN_freep) BIGNUM *r = NULL, *s = NULL;
_cleanup_(ECDSA_SIG_freep) ECDSA_SIG *sig = NULL;
- int k;
assert(hash_algorithm);
if (!sig)
return -ENOMEM;
- if (ECDSA_SIG_set0(sig, BN_dup(r), BN_dup(s)) <= 0)
+ if (ECDSA_SIG_set0(sig, r, s) <= 0)
return -EIO;
+ r = s = NULL;
k = ECDSA_do_verify(data, data_size, sig, eckey);
if (k < 0)
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Signature verification failed: 0x%lx", ERR_get_error());
- return k;
-
+# pragma GCC diagnostic pop
#else
gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
gcry_mpi_t q = NULL, r = NULL, s = NULL;
gcry_error_t ge;
- int k;
assert(hash_algorithm);
gcry_sexp_release(signature_sexp);
if (data_sexp)
gcry_sexp_release(data_sexp);
-
- return k;
#endif
+ return k;
}
static int dnssec_ecdsa_verify(
return 0;
}
-static int nsec3_hash_to_gcrypt_md(uint8_t algorithm) {
+static hash_md_t nsec3_hash_to_hash_md(uint8_t algorithm) {
- /* Translates a DNSSEC NSEC3 hash algorithm into a gcrypt digest identifier */
+ /* Translates a DNSSEC NSEC3 hash algorithm into an openssl/gcrypt digest identifier */
switch (algorithm) {
case NSEC3_ALGORITHM_SHA1:
- return GCRY_MD_SHA1;
+ return OPENSSL_OR_GCRYPT(EVP_sha1(), GCRY_MD_SHA1);
default:
- return -EOPNOTSUPP;
+ return OPENSSL_OR_GCRYPT(NULL, -EOPNOTSUPP);
}
}
int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX];
- _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
- gcry_error_t err;
- size_t hash_size;
- int algorithm;
- void *result;
int r;
assert(nsec3);
"Ignoring NSEC3 RR %s with excessive number of iterations.",
dns_resource_record_to_string(nsec3));
- algorithm = nsec3_hash_to_gcrypt_md(nsec3->nsec3.algorithm);
+ hash_md_t algorithm = nsec3_hash_to_hash_md(nsec3->nsec3.algorithm);
+#if PREFER_OPENSSL
+ if (!algorithm)
+ return -EOPNOTSUPP;
+
+ size_t hash_size = EVP_MD_size(algorithm);
+ assert(hash_size > 0);
+
+ if (nsec3->nsec3.next_hashed_name_size != hash_size)
+ return -EINVAL;
+
+ _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ return -ENOMEM;
+
+ if (EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0)
+ return -EIO;
+
+ r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
+ if (r < 0)
+ return r;
+
+ if (EVP_DigestUpdate(ctx, wire_format, r) <= 0)
+ return -EIO;
+ if (EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0)
+ return -EIO;
+
+ uint8_t result[EVP_MAX_MD_SIZE];
+ if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0)
+ return -EIO;
+
+ for (unsigned k = 0; k < nsec3->nsec3.iterations; k++) {
+ if (EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0)
+ return -EIO;
+ if (EVP_DigestUpdate(ctx, result, hash_size) <= 0)
+ return -EIO;
+ if (EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0)
+ return -EIO;
+
+ if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0)
+ return -EIO;
+ }
+#else
if (algorithm < 0)
return algorithm;
initialize_libgcrypt(false);
- hash_size = gcry_md_get_algo_dlen(algorithm);
+ unsigned hash_size = gcry_md_get_algo_dlen(algorithm);
assert(hash_size > 0);
if (nsec3->nsec3.next_hashed_name_size != hash_size)
if (r < 0)
return r;
- err = gcry_md_open(&md, algorithm, 0);
+ _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL;
+ gcry_error_t err = gcry_md_open(&md, algorithm, 0);
if (gcry_err_code(err) != GPG_ERR_NO_ERROR || !md)
return -EIO;
gcry_md_write(md, wire_format, r);
gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
- result = gcry_md_read(md, 0);
+ void *result = gcry_md_read(md, 0);
if (!result)
return -EIO;
if (!result)
return -EIO;
}
+#endif
memcpy(ret, result, hash_size);
return (int) hash_size;
return 0;
/* Ignore NSEC3 RRs whose algorithm we don't know */
- if (nsec3_hash_to_gcrypt_md(rr->nsec3.algorithm) < 0)
+#if PREFER_OPENSSL
+ if (!nsec3_hash_to_hash_md(rr->nsec3.algorithm))
return 0;
+#else
+ if (nsec3_hash_to_hash_md(rr->nsec3.algorithm) < 0)
+ return 0;
+#endif
+
/* Ignore NSEC3 RRs with an excessive number of required iterations */
if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX)
return 0;