1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * This implemments a dummy key manager for legacy KDFs that still support the
12e1051a39Sopenharmony_ci * old way of performing a KDF via EVP_PKEY_derive(). New KDFs should not be
13e1051a39Sopenharmony_ci * implemented this way. In reality there is no key data for such KDFs, so this
14e1051a39Sopenharmony_ci * key manager does very little.
15e1051a39Sopenharmony_ci */
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h>
18e1051a39Sopenharmony_ci#include <openssl/core_names.h>
19e1051a39Sopenharmony_ci#include <openssl/err.h>
20e1051a39Sopenharmony_ci#include "prov/implementations.h"
21e1051a39Sopenharmony_ci#include "prov/providercommon.h"
22e1051a39Sopenharmony_ci#include "prov/provider_ctx.h"
23e1051a39Sopenharmony_ci#include "prov/kdfexchange.h"
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_new_fn kdf_newdata;
26e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_free_fn kdf_freedata;
27e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_has_fn kdf_has;
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_ciKDF_DATA *ossl_kdf_data_new(void *provctx)
30e1051a39Sopenharmony_ci{
31e1051a39Sopenharmony_ci    KDF_DATA *kdfdata;
32e1051a39Sopenharmony_ci
33e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
34e1051a39Sopenharmony_ci        return NULL;
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci    kdfdata = OPENSSL_zalloc(sizeof(*kdfdata));
37e1051a39Sopenharmony_ci    if (kdfdata == NULL)
38e1051a39Sopenharmony_ci        return NULL;
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_ci    kdfdata->lock = CRYPTO_THREAD_lock_new();
41e1051a39Sopenharmony_ci    if (kdfdata->lock == NULL) {
42e1051a39Sopenharmony_ci        OPENSSL_free(kdfdata);
43e1051a39Sopenharmony_ci        return NULL;
44e1051a39Sopenharmony_ci    }
45e1051a39Sopenharmony_ci    kdfdata->libctx = PROV_LIBCTX_OF(provctx);
46e1051a39Sopenharmony_ci    kdfdata->refcnt = 1;
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_ci    return kdfdata;
49e1051a39Sopenharmony_ci}
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_civoid ossl_kdf_data_free(KDF_DATA *kdfdata)
52e1051a39Sopenharmony_ci{
53e1051a39Sopenharmony_ci    int ref = 0;
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci    if (kdfdata == NULL)
56e1051a39Sopenharmony_ci        return;
57e1051a39Sopenharmony_ci
58e1051a39Sopenharmony_ci    CRYPTO_DOWN_REF(&kdfdata->refcnt, &ref, kdfdata->lock);
59e1051a39Sopenharmony_ci    if (ref > 0)
60e1051a39Sopenharmony_ci        return;
61e1051a39Sopenharmony_ci
62e1051a39Sopenharmony_ci    CRYPTO_THREAD_lock_free(kdfdata->lock);
63e1051a39Sopenharmony_ci    OPENSSL_free(kdfdata);
64e1051a39Sopenharmony_ci}
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ciint ossl_kdf_data_up_ref(KDF_DATA *kdfdata)
67e1051a39Sopenharmony_ci{
68e1051a39Sopenharmony_ci    int ref = 0;
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_ci    /* This is effectively doing a new operation on the KDF_DATA and should be
71e1051a39Sopenharmony_ci     * adequately guarded again modules' error states.  However, both current
72e1051a39Sopenharmony_ci     * calls here are guarded propery in exchange/kdf_exch.c.  Thus, it
73e1051a39Sopenharmony_ci     * could be removed here.  The concern is that something in the future
74e1051a39Sopenharmony_ci     * might call this function without adequate guards.  It's a cheap call,
75e1051a39Sopenharmony_ci     * it seems best to leave it even though it is currently redundant.
76e1051a39Sopenharmony_ci     */
77e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
78e1051a39Sopenharmony_ci        return 0;
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ci    CRYPTO_UP_REF(&kdfdata->refcnt, &ref, kdfdata->lock);
81e1051a39Sopenharmony_ci    return 1;
82e1051a39Sopenharmony_ci}
83e1051a39Sopenharmony_ci
84e1051a39Sopenharmony_cistatic void *kdf_newdata(void *provctx)
85e1051a39Sopenharmony_ci{
86e1051a39Sopenharmony_ci    return ossl_kdf_data_new(provctx);
87e1051a39Sopenharmony_ci}
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_cistatic void kdf_freedata(void *kdfdata)
90e1051a39Sopenharmony_ci{
91e1051a39Sopenharmony_ci    ossl_kdf_data_free(kdfdata);
92e1051a39Sopenharmony_ci}
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_cistatic int kdf_has(const void *keydata, int selection)
95e1051a39Sopenharmony_ci{
96e1051a39Sopenharmony_ci    return 1; /* nothing is missing */
97e1051a39Sopenharmony_ci}
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kdf_keymgmt_functions[] = {
100e1051a39Sopenharmony_ci    { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))kdf_newdata },
101e1051a39Sopenharmony_ci    { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))kdf_freedata },
102e1051a39Sopenharmony_ci    { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))kdf_has },
103e1051a39Sopenharmony_ci    { 0, NULL }
104e1051a39Sopenharmony_ci};
105