Exemple #1
0
/*!
 * Generate new key with parameters from KASP policy and add it into zone.
 */
int generate_key(dnssec_event_ctx_t *ctx, bool ksk, dnssec_kasp_key_t **key_ptr)
{
	assert(ctx);
	assert(ctx->zone);
	assert(ctx->keystore);
	assert(ctx->policy);

	dnssec_key_algorithm_t algorithm = ctx->policy->algorithm;
	unsigned size = ksk ? ctx->policy->ksk_size : ctx->policy->zsk_size;

	// generate key in the keystore

	_cleanup_free_ char *id = NULL;
	int r = dnssec_keystore_generate_key(ctx->keystore, algorithm, size, &id);
	if (r != DNSSEC_EOK) {
		return r;
	}

	// create KASP key

	dnssec_key_t *dnskey = NULL;
	r = dnssec_key_new(&dnskey);
	if (r != DNSSEC_EOK) {
		return r;
	}

	r = dnssec_key_set_dname(dnskey, ctx->zone->dname);
	if (r != DNSSEC_EOK) {
		dnssec_key_free(dnskey);
		return r;
	}

	dnssec_key_set_flags(dnskey, dnskey_flags(ksk));

	r = dnssec_key_import_keystore(dnskey, ctx->keystore, id, algorithm);
	if (r != DNSSEC_EOK) {
		dnssec_key_free(dnskey);
		return r;
	}

	dnssec_kasp_key_t *key = calloc(1, sizeof(*key));
	if (!key) {
		dnssec_key_free(dnskey);
		return DNSSEC_ENOMEM;
	}

	key->key = dnskey;
	key->timing.created = ctx->now;

	// add into KASP zone

	dnssec_list_t *keys = dnssec_kasp_zone_get_keys(ctx->zone);
	dnssec_list_append(keys, key);

	if (key_ptr) {
		*key_ptr = key;
	}

	return DNSSEC_EOK;
}
Exemple #2
0
int kr_dnssec_key_match(const uint8_t *key_a_rdata, size_t key_a_rdlen,
                        const uint8_t *key_b_rdata, size_t key_b_rdlen)
{
	dnssec_key_t *key_a = NULL, *key_b = NULL;
	int ret = kr_dnssec_key_from_rdata((struct dseckey **)&key_a, NULL, key_a_rdata, key_a_rdlen);
	if (ret != 0) {
		return ret;
	}
	ret = kr_dnssec_key_from_rdata((struct dseckey **)&key_b, NULL, key_b_rdata, key_b_rdlen);
	if (ret != 0) {
		dnssec_key_free(key_a);
		return ret;
	}
	/* If the algorithm and the public key match, we can be sure
	 * that they are the same key. */
	ret = kr_error(ENOENT);
	dnssec_binary_t pk_a, pk_b;
	if (dnssec_key_get_algorithm(key_a) == dnssec_key_get_algorithm(key_b) &&
	    dnssec_key_get_pubkey(key_a, &pk_a) == DNSSEC_EOK &&
	    dnssec_key_get_pubkey(key_b, &pk_b) == DNSSEC_EOK) {
		if (pk_a.size == pk_b.size && memcmp(pk_a.data, pk_b.data, pk_a.size) == 0) {
			ret = 0;
		}
	}
	dnssec_key_free(key_a);
	dnssec_key_free(key_b);
	return ret;
}
Exemple #3
0
/*!
 * Create DNSKEY from parameters.
 */
static int create_dnskey(const uint8_t *dname, key_params_t *params,
			 dnssec_key_t **key_ptr)
{
	assert(dname);
	assert(params);
	assert(key_ptr);

	int result = key_params_check(params);
	if (result != DNSSEC_EOK) {
		return result;
	}

	// create key

	dnssec_key_t *key = NULL;
	result = dnssec_key_new(&key);
	if (result != DNSSEC_EOK) {
		return result;
	}

	// set key parameters

	result = dnssec_key_set_dname(key, dname);
	if (result != DNSSEC_EOK) {
		dnssec_key_free(key);
		return result;
	}

	dnssec_key_set_algorithm(key, params->algorithm);

	uint16_t flags = dnskey_flags(params->is_ksk);
	dnssec_key_set_flags(key, flags);

	result = dnssec_key_set_pubkey(key, &params->public_key);
	if (result != DNSSEC_EOK) {
		dnssec_key_free(key);
		return result;
	}

	// validate key ID

	const char *key_id = dnssec_key_get_id(key);
	if (!key_id) {
		dnssec_key_free(key);
		return DNSSEC_INVALID_PUBLIC_KEY;
	}

	if (!dnssec_keyid_equal(params->id, key_id)) {
		dnssec_key_free(key);
		return DNSSEC_INVALID_KEY_ID;
	}

	*key_ptr = key;

	return DNSSEC_EOK;
}
Exemple #4
0
/*!
 * Parse DNSKEY record.
 *
 * \todo Currently, the function waits for the first DNSKEY record, and skips
 * the others. We should be more strict and report other records as errors.
 * However, there is currently no API to stop the scanner.
 */
static void parse_record(zs_scanner_t *scanner)
{
	assert(scanner);
	assert(scanner->data);

	dnssec_key_t *key = scanner->data;

	if (dnssec_key_get_dname(key) != NULL) {
		// skip till the the parser finishes
		return;
	}

	if (scanner->r_type != RTYPE_DNSKEY) {
		// should report error
		return;
	}

	dnssec_binary_t rdata = {
		.data = scanner->r_data,
		.size = scanner->r_data_length
	};
	dnssec_key_set_dname(key, scanner->dname);
	dnssec_key_set_rdata(key, &rdata);
}

int legacy_pubkey_parse(const char *filename, dnssec_key_t **key_ptr)
{
	assert(filename);
	assert(key_ptr);

	dnssec_key_t *key = NULL;
	int result = dnssec_key_new(&key);
	if (result != DNSSEC_EOK) {
		return result;
	}

	uint16_t cls = CLASS_IN;
	uint32_t ttl = 0;
	zs_scanner_t *scanner = zs_scanner_create(".", cls, ttl,
						  parse_record, NULL, key);
	if (!scanner) {
		dnssec_key_free(key);
		return DNSSEC_NOT_FOUND;
	}

	result = zs_scanner_parse_file(scanner, filename);
	zs_scanner_free(scanner);
	if (result != 0 || dnssec_key_get_dname(key) == NULL) {
		dnssec_key_free(key);
		return DNSSEC_INVALID_PUBLIC_KEY;
	}

	*key_ptr = key;
	return DNSSEC_EOK;
}
Exemple #5
0
/*!
 * Load zone keys.
 */
static int load_zone_keys(const uint8_t *zone, dnssec_list_t **list_ptr, json_t *keys)
{
	if (!keys || !json_is_array(keys)) {
		return DNSSEC_CONFIG_MALFORMED;
	}

	dnssec_list_t *new_keys = dnssec_list_new();
	if (!new_keys) {
		return DNSSEC_ENOMEM;
	}

	int result = DNSSEC_EOK;

	int index;
	json_t *key;
	json_array_foreach(keys, index, key) {
		_cleanup_key_params_ key_params_t params = { 0 };

		result = decode_object(KEY_ATTRIBUTES, key, &params);
		if (result != DNSSEC_EOK) {
			break;
		}

		dnssec_key_t *dnskey = NULL;
		result = create_dnskey(zone, &params, &dnskey);
		if (result != DNSSEC_EOK) {
			break;
		}

		result = keyset_add_dnskey(new_keys, dnskey, &params.timing);
		if (result != DNSSEC_EOK) {
			dnssec_key_free(dnskey);
			break;
		}
	}
static void*
scheduler_queue_dnskey_create_thread(void* data_)
{
    scheduler_dnskey_create *data = (scheduler_dnskey_create*)data_;
    ya_result return_value;
    
    log_info("dnssec: key create (%{dnsname} %hd %hhd %hd)", data->zone->origin, data->flags, data->algorithm, data->size);

    char origin[MAX_DOMAIN_LENGTH];

    dnsname_to_cstr(origin, data->zone->origin);

    dnssec_key* key;
    
    if(ISOK(return_value = dnssec_key_createnew(DNSKEY_ALGORITHM_RSASHA1_NSEC3, data->size, data->flags, origin, &key)))
    {
        if(ISOK(return_value = dnssec_key_store_private(key)))
        {
            if(ISOK(return_value = dnssec_key_store_dnskey(key)))
            {
                log_info("dnssec: key created (%{dnsname} %hd %hhd %hd)", data->zone->origin, data->flags, data->algorithm, data->size);    
            }
            else
            {
                log_err("dnssec: key store public (%{dnsname} %hd %hhd %hd): %r", data->zone->origin, data->flags, data->algorithm, data->size, return_value);
            }
        }
        else
        {
            log_err("dnssec: key store private (%{dnsname} %hd %hhd %hd): %r", data->zone->origin, data->flags, data->algorithm, data->size, return_value);
        }
    }
    else
    {
        log_err("dnssec: key create failed (%{dnsname} %hd %hhd %hd): %r", data->zone->origin, data->flags, data->algorithm, data->size, return_value);
    }

    if(ISOK(return_value))
    {
        data->key = key;
    }
    else
    {
        dnssec_key_free(key);
        
        data->key = NULL;
    }
    
    scheduler_schedule_task(scheduler_queue_dnskey_create_callback, data);

    /* WARNING: From this point forward, 'data' cannot be used anymore */

    /*
     * The key is still in the keystore.
     *
     */

    return NULL;
}
Exemple #7
0
int kr_dnssec_key_from_rdata(struct dseckey **key, const knot_dname_t *kown, const uint8_t *rdata, size_t rdlen)
{
	if (!key || !rdata || rdlen == 0) {
		return kr_error(EINVAL);
	}

	dnssec_key_t *new_key = NULL;
	const dnssec_binary_t binary_key = {
		.size = rdlen,
		.data = (uint8_t *)rdata
	};

	int ret = dnssec_key_new(&new_key);
	if (ret != DNSSEC_EOK) {
		return kr_error(ENOMEM);
	}
	ret = dnssec_key_set_rdata(new_key, &binary_key);
	if (ret != DNSSEC_EOK) {
		dnssec_key_free(new_key);
		return kr_error(ENOMEM);
	}
	if (kown) {
		ret = dnssec_key_set_dname(new_key, kown);
		if (ret != DNSSEC_EOK) {
			dnssec_key_free(new_key);
			return kr_error(ENOMEM);
		}
	}

	*key = (struct dseckey *) new_key;
	return kr_ok();
}

void kr_dnssec_key_free(struct dseckey **key)
{
	assert(key);

	dnssec_key_free((dnssec_key_t *) *key);
	*key = NULL;
}
Exemple #8
0
Fichier : key.c Projet : idtek/knot
/*!
 * Parse legacy key files and get public key, private key, and key timing.
 */
int legacy_key_parse(const char *filename, dnssec_key_t **key_ptr,
		     dnssec_binary_t *pem_ptr, dnssec_kasp_key_timing_t *timing)
{
	if (!filename || !key_ptr || !pem_ptr || !timing) {
		return DNSSEC_EINVAL;
	}

	_cleanup_free_ char *filename_public = NULL;
	_cleanup_free_ char *filename_private = NULL;
	int result = get_key_names(filename, &filename_public, &filename_private);
	if (result != DNSSEC_EOK) {
		return result;
	}

	dnssec_key_t *key = NULL;
	result = legacy_pubkey_parse(filename_public, &key);
	if (result != DNSSEC_EOK) {
		return result;
	}

	legacy_privkey_t params = { 0 };
	result = legacy_privkey_parse(filename_private, &params);
	if (result != DNSSEC_EOK) {
		dnssec_key_free(key);
		return result;
	}

	dnssec_binary_t pem = { 0 };
	result = params_to_pem(key, &params, &pem);
	if (result != DNSSEC_EOK) {
		legacy_privkey_free(&params);
		return result;
	}

	*key_ptr = key;
	*pem_ptr = pem;
	params_to_timing(&params, timing);

	legacy_privkey_free(&params);

	return DNSSEC_EOK;
}
Exemple #9
0
/*!
 * Parse DNSKEY record.
 *
 * \todo Currently, the function waits for the first DNSKEY record, and skips
 * the others. We should be more strict and report other records as errors.
 */
static void parse_record(zs_scanner_t *scanner)
{
	assert(scanner);
	assert(scanner->process.data);

	dnssec_key_t *key = scanner->process.data;

	if (dnssec_key_get_dname(key) != NULL) {
		// should report error
		scanner->state = ZS_STATE_STOP;
		return;
	}

	if (scanner->r_type != RTYPE_DNSKEY) {
		// should report error
		scanner->state = ZS_STATE_STOP;
		return;
	}

	dnssec_binary_t rdata = {
		.data = scanner->r_data,
		.size = scanner->r_data_length
	};
	dnssec_key_set_dname(key, scanner->dname);
	dnssec_key_set_rdata(key, &rdata);
}

int legacy_pubkey_parse(const char *filename, dnssec_key_t **key_ptr)
{
	assert(filename);
	assert(key_ptr);

	dnssec_key_t *key = NULL;
	int result = dnssec_key_new(&key);
	if (result != DNSSEC_EOK) {
		return result;
	}

	uint16_t cls = CLASS_IN;
	uint32_t ttl = 0;
	zs_scanner_t *scanner = malloc(sizeof(zs_scanner_t));
	if (scanner == NULL) {
		dnssec_key_free(key);
		return DNSSEC_ENOMEM;
	}

	if (zs_init(scanner, ".", cls, ttl) != 0 ||
	    zs_set_input_file(scanner, filename) != 0 ||
	    zs_set_processing(scanner, parse_record, NULL, key) != 0 ||
	    zs_parse_all(scanner) != 0) {
		zs_deinit(scanner);
		free(scanner);
		dnssec_key_free(key);
		return DNSSEC_NOT_FOUND;
	}
	zs_deinit(scanner);
	free(scanner);

	if (dnssec_key_get_dname(key) == NULL) {
		dnssec_key_free(key);
		return DNSSEC_INVALID_PUBLIC_KEY;
	}

	*key_ptr = key;
	return DNSSEC_EOK;
}
Exemple #10
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);
}
Exemple #11
0
static int
tcl_addkey(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
{
    ya_result return_code;
    zdb_zone* zone;
    dnssec_key* key;
    u32 key_size;
    int argi = 1;
    u16 key_flags;

    if(FAIL(read_zone(argv, argc, &argi, &zone)))
    {
	return -1;
    }

    if(FAIL(read_u32(argv, argc, &argi, &key_size)))
    {
	return -2;
    }

    if(FAIL(read_u16(argv, argc, &argi, &key_flags)))
    {
	return -3;
    }

    /* argv[1] is always the origin */

    key = dnssec_key_createnew(DNSKEY_ALGORITHM_RSASHA1_NSEC3, key_size, key_flags, argv[1]);

    if(key == NULL)
    {
	fprintf(stdout, "Key generation error\n");
	fflush(stdout);
	return -4;
    }

    return_code = dnssec_key_store_private(key);

    if(FAIL(return_code))
    {
	fprintf(stdout, ERROR_CODE_HEX_DEC, return_code, return_code);
	fflush(stdout);

	dnssec_key_free(key);

	return -5;
    }

    return_code = dnssec_key_store_dnskey(key);

    if(FAIL(return_code))
    {
	fprintf(stdout, ERROR_CODE_HEX_DEC, return_code, return_code);
	fflush(stdout);

	dnssec_key_free(key);

	return -6;
    }

    dnssec_key_addrecord(zone, key);

    return TCL_OK;
}