Path: blob/main/sys/contrib/openzfs/module/icp/api/kcf_cipher.c
48531 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/21/*22* Copyright 2007 Sun Microsystems, Inc. All rights reserved.23* Use is subject to license terms.24*/2526#include <sys/zfs_context.h>27#include <sys/crypto/common.h>28#include <sys/crypto/impl.h>29#include <sys/crypto/api.h>30#include <sys/crypto/spi.h>31#include <sys/crypto/sched_impl.h>3233/*34* Encryption and decryption routines.35*/363738/*39* crypto_encrypt()40*41* Arguments:42* sid: session id43* mech: crypto_mechanism_t pointer.44* mech_type is a valid value previously returned by45* crypto_mech2id();46* When the mech's parameter is not NULL, its definition depends47* on the standard definition of the mechanism.48* key: pointer to a crypto_key_t structure.49* plaintext: The message to be encrypted50* ciphertext: Storage for the encrypted message. The length needed51* depends on the mechanism, and the plaintext's size.52* tmpl: a crypto_ctx_template_t, opaque template of a context of an53* encryption with the 'mech' using 'key'. 'tmpl' is created by54* a previous call to crypto_create_ctx_template().55*56* Description:57* Asynchronously submits a request for, or synchronously performs a58* single-part encryption of 'plaintext' with the mechanism 'mech', using59* the key 'key'.60* When complete and successful, 'ciphertext' will contain the encrypted61* message.62* Relies on the KCF scheduler to pick a provider.63*64* Returns:65* See comment in the beginning of the file.66*/67int68crypto_encrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext,69crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *ciphertext)70{71int error;72kcf_mech_entry_t *me;73kcf_provider_desc_t *pd;74kcf_ctx_template_t *ctx_tmpl;75crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;76kcf_prov_tried_t *list = NULL;7778retry:79/* pd is returned held */80if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,81list, CRYPTO_FG_ENCRYPT_ATOMIC)) == NULL) {82if (list != NULL)83kcf_free_triedlist(list);84return (error);85}8687if (((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL))88spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;8990crypto_mechanism_t lmech = *mech;91KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);92error = KCF_PROV_ENCRYPT_ATOMIC(pd, &lmech, key,93plaintext, ciphertext, spi_ctx_tmpl);9495if (error != CRYPTO_SUCCESS && IS_RECOVERABLE(error)) {96/* Add pd to the linked list of providers tried. */97if (kcf_insert_triedlist(&list, pd, KM_SLEEP) != NULL)98goto retry;99}100101if (list != NULL)102kcf_free_triedlist(list);103104KCF_PROV_REFRELE(pd);105return (error);106}107108/*109* crypto_decrypt_prov()110*111* Arguments:112* pd: provider descriptor113* sid: session id114* mech: crypto_mechanism_t pointer.115* mech_type is a valid value previously returned by116* crypto_mech2id();117* When the mech's parameter is not NULL, its definition depends118* on the standard definition of the mechanism.119* key: pointer to a crypto_key_t structure.120* ciphertext: The message to be encrypted121* plaintext: Storage for the encrypted message. The length needed122* depends on the mechanism, and the plaintext's size.123* tmpl: a crypto_ctx_template_t, opaque template of a context of an124* encryption with the 'mech' using 'key'. 'tmpl' is created by125* a previous call to crypto_create_ctx_template().126*127* Description:128* Asynchronously submits a request for, or synchronously performs a129* single-part decryption of 'ciphertext' with the mechanism 'mech', using130* the key 'key'.131* When complete and successful, 'plaintext' will contain the decrypted132* message.133* Relies on the KCF scheduler to choose a provider.134*135* Returns:136* See comment in the beginning of the file.137*/138int139crypto_decrypt(crypto_mechanism_t *mech, crypto_data_t *ciphertext,140crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *plaintext)141{142int error;143kcf_mech_entry_t *me;144kcf_provider_desc_t *pd;145kcf_ctx_template_t *ctx_tmpl;146crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;147kcf_prov_tried_t *list = NULL;148149retry:150/* pd is returned held */151if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,152list, CRYPTO_FG_DECRYPT_ATOMIC)) == NULL) {153if (list != NULL)154kcf_free_triedlist(list);155return (error);156}157158if (((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL))159spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;160161crypto_mechanism_t lmech = *mech;162KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);163164error = KCF_PROV_DECRYPT_ATOMIC(pd, &lmech, key,165ciphertext, plaintext, spi_ctx_tmpl);166167if (error != CRYPTO_SUCCESS && IS_RECOVERABLE(error)) {168/* Add pd to the linked list of providers tried. */169if (kcf_insert_triedlist(&list, pd, KM_SLEEP) != NULL)170goto retry;171}172173if (list != NULL)174kcf_free_triedlist(list);175176KCF_PROV_REFRELE(pd);177return (error);178}179180#if defined(_KERNEL)181EXPORT_SYMBOL(crypto_encrypt);182EXPORT_SYMBOL(crypto_decrypt);183#endif184185186