keystore.c 3.89 KB
Newer Older
1
/*  Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 3 4 5 6 7 8 9 10 11 12 13

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
14
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
15 16
*/

17 18 19
#include <assert.h>
#include <stdlib.h>

20 21 22 23 24 25 26 27 28 29
#include "libdnssec/error.h"
#include "libdnssec/key.h"
#include "libdnssec/key/algorithm.h"
#include "libdnssec/key/dnskey.h"
#include "libdnssec/key/internal.h"
#include "libdnssec/key/privkey.h"
#include "libdnssec/keyid.h"
#include "libdnssec/keystore.h"
#include "libdnssec/keystore/internal.h"
#include "libdnssec/shared/shared.h"
30

31
/* -- internal API --------------------------------------------------------- */
32 33

int keystore_create(dnssec_keystore_t **store_ptr,
34
		    const keystore_functions_t *functions)
35 36 37 38 39 40 41 42 43 44 45
{
	assert(store_ptr);
	assert(functions);

	dnssec_keystore_t *store = calloc(1, sizeof(*store));
	if (!store) {
		return DNSSEC_ENOMEM;
	}

	store->functions = functions;

46
	int result = functions->ctx_new(&store->ctx);
47
	if (result != DNSSEC_EOK) {
48 49 50 51 52 53 54 55 56 57
		free(store);
		return DNSSEC_ENOMEM;
	}

	*store_ptr = store;
	return DNSSEC_EOK;
}

/* -- public API ----------------------------------------------------------- */

58
_public_
59
int dnssec_keystore_deinit(dnssec_keystore_t *store)
60 61 62 63 64
{
	if (!store) {
		return DNSSEC_EINVAL;
	}

65
	dnssec_keystore_close(store);
66 67
	store->functions->ctx_free(store->ctx);

68 69 70 71 72
	free(store);

	return DNSSEC_EOK;
}

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
_public_
int dnssec_keystore_init(dnssec_keystore_t *store, const char *config)
{
	if (!store) {
		return DNSSEC_EINVAL;
	}

	return store->functions->init(store->ctx, config);
}

_public_
int dnssec_keystore_open(dnssec_keystore_t *store, const char *config)
{
	if (!store) {
		return DNSSEC_EINVAL;
	}

	return store->functions->open(store->ctx, config);
}

_public_
int dnssec_keystore_close(dnssec_keystore_t *store)
{
	if (!store) {
		return DNSSEC_EINVAL;
	}

	return store->functions->close(store->ctx);
}

103
_public_
104
int dnssec_keystore_generate_key(dnssec_keystore_t *store,
105
				 dnssec_key_algorithm_t _algorithm,
106
				 unsigned bits, char **id_ptr)
107
{
108
	if (!store || !_algorithm || !id_ptr) {
109 110 111
		return DNSSEC_EINVAL;
	}

112 113 114 115 116 117 118 119 120 121 122
	// prepare parameters

	gnutls_pk_algorithm_t algorithm = algorithm_to_gnutls(_algorithm);
	if (algorithm == GNUTLS_PK_UNKNOWN) {
		return DNSSEC_INVALID_KEY_ALGORITHM;
	}

	if (!dnssec_algorithm_key_size_check(_algorithm, bits)) {
		return DNSSEC_INVALID_KEY_SIZE;
	}

123
	return store->functions->generate_key(store->ctx, algorithm, bits, id_ptr);
124 125
}

126 127 128 129 130 131 132 133 134 135 136
_public_
int dnssec_keystore_import(dnssec_keystore_t *store, const dnssec_binary_t *pem,
			   char **id_ptr)
{
	if (!store || !pem || !id_ptr) {
		return DNSSEC_EINVAL;
	}

	return store->functions->import_key(store->ctx, pem, id_ptr);
}

137
_public_
138
int dnssec_keystore_remove_key(dnssec_keystore_t *store, const char *key_id)
139 140 141 142 143
{
	if (!store || !key_id) {
		return DNSSEC_EINVAL;
	}

144
	return store->functions->remove_key(store->ctx, key_id);
145
}
146 147

_public_
148
int dnssec_key_import_keystore(dnssec_key_t *key, dnssec_keystore_t *store,
149
			       const char *id)
150
{
151
	if (!key || !store || !id || dnssec_key_get_algorithm(key) == 0) {
152 153 154 155 156 157 158 159
		return DNSSEC_EINVAL;
	}

	if (key->private_key) {
		return DNSSEC_KEY_ALREADY_PRESENT;
	}

	gnutls_privkey_t privkey = NULL;
160
	int r = store->functions->get_private(store->ctx, id, &privkey);
161 162 163 164 165 166 167 168 169 170 171 172
	if (r != DNSSEC_EOK) {
		return r;
	}

	r = key_set_private_key(key, privkey);
	if (r != DNSSEC_EOK) {
		gnutls_privkey_deinit(privkey);
		return r;
	}

	return DNSSEC_EOK;
}