Esempio n. 1
0
/*!
 * Export GnuTLS X.509 private key to PEM binary.
 */
int pem_gnutls_x509_export(gnutls_x509_privkey_t key, dnssec_binary_t *pem_ptr)
{
	assert(key);
	assert(pem_ptr);

	dnssec_binary_t pem = { 0 };
	int r = try_export_pem(key, &pem);
	if (r != GNUTLS_E_SHORT_MEMORY_BUFFER || pem.size == 0) {
		return DNSSEC_KEY_EXPORT_ERROR;
	}

	r = dnssec_binary_alloc(&pem, pem.size);
	if (r != DNSSEC_EOK) {
		return r;
	}

	r = try_export_pem(key, &pem);
	if (r != GNUTLS_E_SUCCESS) {
		dnssec_binary_free(&pem);
		return DNSSEC_KEY_EXPORT_ERROR;
	}

	*pem_ptr = pem;

	return DNSSEC_EOK;
}
Esempio n. 2
0
/*!
 * Free allocated key parameters and clear the structure.
 */
static void key_params_free(key_params_t *params)
{
	assert(params);

	free(params->id);
	dnssec_binary_free(&params->public_key);

	clear_struct(params);
}
Esempio n. 3
0
static int pkcs8_dir_read(void *_handle, const char *id, dnssec_binary_t *pem)
{
	if (!_handle || !id || !pem) {
		return DNSSEC_EINVAL;
	}

	pkcs8_dir_handle_t *handle = _handle;

	// open file and get it's size

	_cleanup_close_ int file = 0;
	int result = key_open_read(handle->dir_name, id, &file);
	if (result != DNSSEC_EOK) {
		return result;
	}

	size_t size = 0;
	result = file_size(file, &size);
	if (result != DNSSEC_EOK) {
		return result;
	}

	if (size == 0) {
		return DNSSEC_MALFORMED_DATA;
	}

	// read the stored data

	dnssec_binary_t read_pem = { 0 };
	result = dnssec_binary_alloc(&read_pem, size);
	if (result != DNSSEC_EOK) {
		return result;
	}

	ssize_t read_count = read(file, read_pem.data, read_pem.size);
	if (read_count == -1) {
		dnssec_binary_free(&read_pem);
		return dnssec_errno_to_error(errno);
	}

	assert(read_count == read_pem.size);
	*pem = read_pem;

	return DNSSEC_EOK;
}
Esempio n. 4
0
static int authenticate_ds(const dnssec_key_t *key, dnssec_binary_t *ds_rdata, uint8_t digest_type)
{
	/* Compute DS RDATA from the DNSKEY. */
	dnssec_binary_t computed_ds = {0, };
	int ret = dnssec_key_create_ds(key, digest_type, &computed_ds);
	if (ret != DNSSEC_EOK) {
		ret = kr_error(ENOMEM);
		goto fail;
	}

	/* DS records contain algorithm, key tag and the digest.
	 * Therefore the comparison of the two DS is sufficient.
	 */
	ret = (ds_rdata->size == computed_ds.size) &&
	    (memcmp(ds_rdata->data, computed_ds.data, ds_rdata->size) == 0);
	ret = ret ? kr_ok() : kr_error(ENOENT);

fail:
	dnssec_binary_free(&computed_ds);
	return ret;
}
Esempio n. 5
0
/*!
 * Generate new key and export it in the PEM format.
 */
int pem_generate(gnutls_pk_algorithm_t algorithm, unsigned bits,
		 dnssec_binary_t *pem_ptr, char **id_ptr)
{
	assert(pem_ptr);
	assert(id_ptr);

	// generate key

	_cleanup_x509_privkey_ gnutls_x509_privkey_t key = NULL;
	int r = gnutls_x509_privkey_init(&key);
	if (r != GNUTLS_E_SUCCESS) {
		return DNSSEC_ENOMEM;
	}

	r = gnutls_x509_privkey_generate(key, algorithm, bits, 0);
	if (r != GNUTLS_E_SUCCESS) {
		return DNSSEC_KEY_GENERATE_ERROR;
	}

	// convert to PEM and export the ID

	dnssec_binary_t pem = { 0 };
	r = pem_gnutls_x509_export(key, &pem);
	if (r != DNSSEC_EOK) {
		return r;
	}

	// export key ID

	char *id = gnutls_x509_privkey_hex_key_id(key);
	if (!id) {
		dnssec_binary_free(&pem);
		return DNSSEC_ENOMEM;
	}

	*pem_ptr = pem;
	*id_ptr = id;

	return DNSSEC_EOK;
}
Esempio n. 6
0
/*!
 * \brief Create NSEC3 owner name from regular owner name.
 *
 * \param owner      Node owner name.
 * \param zone_apex  Zone apex name.
 * \param params     Params for NSEC3 hashing function.
 *
 * \return NSEC3 owner name, NULL in case of error.
 */
knot_dname_t *knot_create_nsec3_owner(const knot_dname_t *owner,
                                      const knot_dname_t *zone_apex,
                                      const knot_nsec3_params_t *params)
{
	if (owner == NULL || zone_apex == NULL || params == NULL) {
		return NULL;
	}

	int owner_size = knot_dname_size(owner);
	if (owner_size < 0) {
		return NULL;
	}

	dnssec_binary_t data = { 0 };
	data.data = (uint8_t *)owner;
	data.size = owner_size;

	dnssec_binary_t hash = { 0 };
	dnssec_nsec3_params_t xparams = {
		.algorithm = params->algorithm,
		.flags = params->flags,
		.iterations = params->iterations,
		.salt = {
			.data = params->salt,
			.size = params->salt_length
		}
	};

	int r = dnssec_nsec3_hash(&data, &xparams, &hash);
	if (r != DNSSEC_EOK) {
		return NULL;
	}

	knot_dname_t *result = knot_nsec3_hash_to_dname(hash.data, hash.size, zone_apex);

	dnssec_binary_free(&hash);

	return result;
}
Esempio n. 7
0
/*!
 * \brief Parse NSEC3 parameters and fill structure with NSEC3 parameters.
 */
static bool parse_nsec3_params(dnssec_nsec3_params_t *params, const char *salt_str,
			       const char *algorithm_str, const char *iterations_str)
{
	uint8_t algorithm = 0;
	int r = str_to_u8(algorithm_str, &algorithm);
	if (r != DNSSEC_EOK) {
		error("Invalid algorithm number.");
		return false;
	}

	uint16_t iterations = 0;
	r = str_to_u16(iterations_str, &iterations);
	if (r != DNSSEC_EOK) {
		error("Invalid iteration count, %s.", dnssec_strerror(r));
		return false;
	}

	dnssec_binary_t salt = { 0 };
	r = str_to_salt(salt_str, &salt);
	if (r != DNSSEC_EOK) {
		error("Invalid salt, %s.", dnssec_strerror(r));
		return false;
	}

	if (salt.size > UINT8_MAX) {
		error("Invalid salt, maximum length is %d bytes.", UINT8_MAX);
		dnssec_binary_free(&salt);
		return false;
	}

	params->algorithm = algorithm;
	params->iterations = iterations;
	params->salt = salt;
	params->flags = 0;

	return true;
}
Esempio n. 8
0
/*!
 * \brief Entry point of 'knsec3hash'.
 */
int main(int argc, char *argv[])
{
	struct option options[] = {
		{ "version", no_argument, 0, 'V' },
		{ "help",    no_argument, 0, 'h' },
		{ NULL }
	};

	int opt = 0;
	int li = 0;
	while ((opt = getopt_long(argc, argv, "hV", options, &li)) != -1) {
		switch(opt) {
		case 'V':
			printf("%s, version %s\n", PROGRAM_NAME, PACKAGE_VERSION);
			return 0;
		case 'h':
			usage(stdout);
			return 0;
		default:
			usage(stderr);
			return 1;
		}
	}

	// knsec3hash <salt> <algorithm> <iterations> <domain>
	if (argc != 5) {
		usage(stderr);
		return 1;
	}

	int exit_code = 1;
	dnssec_nsec3_params_t nsec3_params = { 0 };

	dnssec_binary_t dname = { 0 };
	dnssec_binary_t digest = { 0 };
	dnssec_binary_t digest_print = { 0 };

	if (!parse_nsec3_params(&nsec3_params, argv[1], argv[2], argv[3])) {
		goto fail;
	}

	dname.data = dname_from_ascii(argv[4]);
	dname.size = dname_length(dname.data);
	if (dname.data == NULL) {
		error("Cannot parse domain name.");
		goto fail;
	}

	dname_normalize(dname.data);

	int r = dnssec_nsec3_hash(&dname, &nsec3_params, &digest);
	if (r != DNSSEC_EOK) {
		error("Cannot compute NSEC3 hash, %s.", dnssec_strerror(r));
		goto fail;
	}

	r = base32hex_encode(&digest, &digest_print);
	if (r != DNSSEC_EOK) {
		error("Cannot encode computed hash, %s.", dnssec_strerror(r));
		goto fail;
	}

	exit_code = 0;

	printf("%.*s (salt=%s, hash=%d, iterations=%d)\n", (int)digest_print.size,
	       digest_print.data, argv[1], nsec3_params.algorithm,
	       nsec3_params.iterations);

fail:
	dnssec_nsec3_params_free(&nsec3_params);
	dnssec_binary_free(&dname);
	dnssec_binary_free(&digest);
	dnssec_binary_free(&digest_print);

	return exit_code;
}
Esempio n. 9
0
static void test_sign(dnssec_key_t *p11_key, dnssec_key_t *soft_key)
{
	int r;

	static const dnssec_binary_t input = {
		.data = (uint8_t *)"So Long, and Thanks for All the Fish.",
		.size = 37
	};

	dnssec_binary_t sign = { 0 };

	// usage constraints

	ok(dnssec_key_can_sign(p11_key),   MSG_PKCS11 " dnssec_key_can_sign()");
	ok(dnssec_key_can_verify(p11_key), MSG_PKCS11 " dnssec_key_can_verify()");

	ok(!dnssec_key_can_sign(soft_key),  MSG_SOFTWARE " dnssec_key_can_sign()");
	ok(dnssec_key_can_verify(soft_key), MSG_SOFTWARE " dnssec_key_can_verify()");

	// PKCS #11 key signature

	dnssec_sign_ctx_t *ctx = NULL;
	r = dnssec_sign_new(&ctx, p11_key);
	ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_init() ");

	r = dnssec_sign_add(ctx, &input);
	ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_add()");

	r = dnssec_sign_write(ctx, &sign);
	ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_write()");

	// PKCS #11 key verification

	r = dnssec_sign_init(ctx);
	ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_init()");

	r = dnssec_sign_add(ctx, &input);
	ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_add()");

	r = dnssec_sign_verify(ctx, &sign);
	ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_verify()");

	// software verification

	dnssec_sign_free(ctx);
	ctx = NULL;

	r = dnssec_sign_new(&ctx, soft_key);
	ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_init()");

	r = dnssec_sign_add(ctx, &input);
	ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_add()");

	r = dnssec_sign_verify(ctx, &sign);
	ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_verify()");

	dnssec_binary_free(&sign);
	dnssec_sign_free(ctx);
}

static void test_key_use(dnssec_keystore_t *store,
			 dnssec_key_algorithm_t algorithm,
			 const char *keyid)
{
	dnssec_key_t *p11_key = NULL;
	dnssec_key_t *soft_key = NULL;

	create_dnskeys(store, algorithm, keyid, &p11_key, &soft_key);
	test_sign(p11_key, soft_key);

	dnssec_key_free(p11_key);
	dnssec_key_free(soft_key);
}