From 69c6a41ffb878ef98c9378ed4b1634a404cfaa7f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 6 May 2024 02:53:35 +0200 Subject: Adding upstream version 2.7.6. Signed-off-by: Daniel Baumann --- src/libdnssec/keystore/pkcs8.c | 211 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/libdnssec/keystore/pkcs8.c (limited to 'src/libdnssec/keystore/pkcs8.c') diff --git a/src/libdnssec/keystore/pkcs8.c b/src/libdnssec/keystore/pkcs8.c new file mode 100644 index 0000000..f05eda0 --- /dev/null +++ b/src/libdnssec/keystore/pkcs8.c @@ -0,0 +1,211 @@ +/* Copyright (C) 2018 CZ.NIC, z.s.p.o. + + 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 + along with this program. If not, see . +*/ + +#include + +#include "libdnssec/error.h" +#include "libdnssec/key/algorithm.h" +#include "libdnssec/keyid.h" +#include "libdnssec/keystore.h" +#include "libdnssec/keystore/internal.h" +#include "libdnssec/shared/pem.h" +#include "libdnssec/shared/shared.h" + +/*! + * PKCS #8 key store context. + */ +typedef struct pkcs8_ctx { + /*! Storage implementation callbacks. */ + const dnssec_keystore_pkcs8_functions_t *functions; + /*! Implementation specific context data. */ + void *data; +} pkcs8_ctx_t; + +/* -- internal API --------------------------------------------------------- */ + +static int pkcs8_ctx_new(void **ctx_ptr, void *_functions) +{ + assert(ctx_ptr); + assert(_functions); + + pkcs8_ctx_t *ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + return DNSSEC_ENOMEM; + } + + ctx->functions = _functions; + + int r = ctx->functions->handle_new(&ctx->data); + if (r != DNSSEC_EOK) { + free(ctx); + return r; + } + + *ctx_ptr = ctx; + + return DNSSEC_EOK; +} + +static int pkcs8_ctx_free(void *_ctx) +{ + pkcs8_ctx_t *ctx = _ctx; + int r = ctx->functions->handle_free(ctx->data); + + free(ctx); + + return r; +} + +static int pkcs8_init(void *_ctx, const char *config) +{ + pkcs8_ctx_t *ctx = _ctx; + return ctx->functions->init(ctx->data, config); +} + +static int pkcs8_open(void *_ctx, const char *config) +{ + pkcs8_ctx_t *ctx = _ctx; + return ctx->functions->open(ctx->data, config); +} + +static int pkcs8_close(void *_ctx) +{ + pkcs8_ctx_t *ctx = _ctx; + return ctx->functions->close(ctx->data); +} + +static int pkcs8_list_keys(void *_ctx, dnssec_list_t **list) +{ + pkcs8_ctx_t *ctx = _ctx; + return ctx->functions->list(ctx->data, list); +} + +static int pkcs8_generate_key(void *_ctx, gnutls_pk_algorithm_t algorithm, + unsigned bits, char **id_ptr) +{ + assert(_ctx); + assert(id_ptr); + + pkcs8_ctx_t *ctx = _ctx; + + // generate key + + char *new_id = NULL; + _cleanup_binary_ dnssec_binary_t data = { 0 }; + int r = pem_generate(algorithm, bits, &data, &new_id); + if (r != DNSSEC_EOK) { + return r; + } + + // save key + + r = ctx->functions->write(ctx->data, new_id, &data); + if (r != DNSSEC_EOK) { + return r; + } + + // finish + + *id_ptr = new_id; + + return DNSSEC_EOK; +} + +static int pkcs8_import_key(void *_ctx, const dnssec_binary_t *pem, char **id_ptr) +{ + pkcs8_ctx_t *ctx = _ctx; + + // retrieve key ID + + char *id = NULL; + int r = pem_keyid(pem, &id); + if (r != DNSSEC_EOK) { + return r; + } + + // save the key + + r = ctx->functions->write(ctx->data, id, pem); + if (r != DNSSEC_EOK) { + free(id); + return r; + } + + *id_ptr = id; + + return DNSSEC_EOK; +} + +static int pkcs8_remove_key(void *_ctx, const char *id) +{ + pkcs8_ctx_t *ctx = _ctx; + return ctx->functions->remove(ctx->data, id); +} + +static int pkcs8_get_private(void *_ctx, const char *id, gnutls_privkey_t *key_ptr) +{ + assert(_ctx); + assert(id); + assert(key_ptr); + + pkcs8_ctx_t *ctx = _ctx; + + // load private key data + + _cleanup_binary_ dnssec_binary_t pem = { 0 }; + int r = ctx->functions->read(ctx->data, id, &pem); + if (r != DNSSEC_EOK) { + return r; + } + + // construct the key + + gnutls_privkey_t key = NULL; + r = pem_privkey(&pem, &key); + if (r != DNSSEC_EOK) { + return r; + } + + *key_ptr = key; + + return DNSSEC_EOK; +} + +static const keystore_functions_t PKCS8_FUNCTIONS = { + .ctx_new = pkcs8_ctx_new, + .ctx_free = pkcs8_ctx_free, + .init = pkcs8_init, + .open = pkcs8_open, + .close = pkcs8_close, + .list_keys = pkcs8_list_keys, + .generate_key = pkcs8_generate_key, + .import_key = pkcs8_import_key, + .remove_key = pkcs8_remove_key, + .get_private = pkcs8_get_private, +}; + +/* -- public API ----------------------------------------------------------- */ + +_public_ +int dnssec_keystore_init_pkcs8_custom(dnssec_keystore_t **store_ptr, + const dnssec_keystore_pkcs8_functions_t *store_functions) +{ + if (!store_ptr || !store_functions) { + return DNSSEC_EINVAL; + } + + return keystore_create(store_ptr, &PKCS8_FUNCTIONS, (void *)store_functions); +} -- cgit v1.2.3