xref: /freebsd/sys/contrib/openzfs/module/icp/api/kcf_cipher.c (revision 22649d4dba730d46244fd2dff4fd174903c8379f)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * This file and its contents are supplied under the terms of the
4  * Common Development and Distribution License ("CDDL"), version 1.0.
5  * You may only use this file in accordance with the terms of version
6  * 1.0 of the CDDL.
7  *
8  * A full copy of the text of the CDDL should have accompanied this
9  * source.  A copy of the CDDL is also available via the Internet at
10  * https://opensource.org/license/CDDL-1.0.
11  */
12 /*
13  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
14  * Use is subject to license terms.
15  */
16 
17 #include <sys/zfs_context.h>
18 #include <sys/crypto/common.h>
19 #include <sys/crypto/impl.h>
20 #include <sys/crypto/api.h>
21 #include <sys/crypto/spi.h>
22 #include <sys/crypto/sched_impl.h>
23 
24 /*
25  * Encryption and decryption routines.
26  */
27 
28 
29 /*
30  * crypto_encrypt()
31  *
32  * Arguments:
33  *	sid:	session id
34  *	mech:	crypto_mechanism_t pointer.
35  *		mech_type is a valid value previously returned by
36  *		crypto_mech2id();
37  *		When the mech's parameter is not NULL, its definition depends
38  *		on the standard definition of the mechanism.
39  *	key:	pointer to a crypto_key_t structure.
40  *	plaintext: The message to be encrypted
41  *	ciphertext: Storage for the encrypted message. The length needed
42  *		depends on the mechanism, and the plaintext's size.
43  *	tmpl:	a crypto_ctx_template_t, opaque template of a context of an
44  *		encryption with the 'mech' using 'key'. 'tmpl' is created by
45  *		a previous call to crypto_create_ctx_template().
46  *
47  * Description:
48  *	Asynchronously submits a request for, or synchronously performs a
49  *	single-part encryption of 'plaintext' with the mechanism 'mech', using
50  *	the key 'key'.
51  *	When complete and successful, 'ciphertext' will contain the encrypted
52  *	message.
53  *	Relies on the KCF scheduler to pick a provider.
54  *
55  * Returns:
56  *	See comment in the beginning of the file.
57  */
58 int
crypto_encrypt(crypto_mechanism_t * mech,crypto_data_t * plaintext,crypto_key_t * key,crypto_ctx_template_t tmpl,crypto_data_t * ciphertext)59 crypto_encrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext,
60     crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *ciphertext)
61 {
62 	int error;
63 	kcf_mech_entry_t *me;
64 	kcf_provider_desc_t *pd;
65 	kcf_ctx_template_t *ctx_tmpl;
66 	crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
67 	kcf_prov_tried_t *list = NULL;
68 
69 retry:
70 	/* pd is returned held */
71 	if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,
72 	    list, CRYPTO_FG_ENCRYPT_ATOMIC)) == NULL) {
73 		if (list != NULL)
74 			kcf_free_triedlist(list);
75 		return (error);
76 	}
77 
78 	if (((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL))
79 		spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
80 
81 	crypto_mechanism_t lmech = *mech;
82 	KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
83 	error = KCF_PROV_ENCRYPT_ATOMIC(pd, &lmech, key,
84 	    plaintext, ciphertext, spi_ctx_tmpl);
85 
86 	if (error != CRYPTO_SUCCESS && IS_RECOVERABLE(error)) {
87 		/* Add pd to the linked list of providers tried. */
88 		if (kcf_insert_triedlist(&list, pd, KM_SLEEP) != NULL)
89 			goto retry;
90 	}
91 
92 	if (list != NULL)
93 		kcf_free_triedlist(list);
94 
95 	KCF_PROV_REFRELE(pd);
96 	return (error);
97 }
98 
99 /*
100  * crypto_decrypt_prov()
101  *
102  * Arguments:
103  *	pd:	provider descriptor
104  *	sid:	session id
105  *	mech:	crypto_mechanism_t pointer.
106  *		mech_type is a valid value previously returned by
107  *		crypto_mech2id();
108  *		When the mech's parameter is not NULL, its definition depends
109  *		on the standard definition of the mechanism.
110  *	key:	pointer to a crypto_key_t structure.
111  *	ciphertext: The message to be encrypted
112  *	plaintext: Storage for the encrypted message. The length needed
113  *		depends on the mechanism, and the plaintext's size.
114  *	tmpl:	a crypto_ctx_template_t, opaque template of a context of an
115  *		encryption with the 'mech' using 'key'. 'tmpl' is created by
116  *		a previous call to crypto_create_ctx_template().
117  *
118  * Description:
119  *	Asynchronously submits a request for, or synchronously performs a
120  *	single-part decryption of 'ciphertext' with the mechanism 'mech', using
121  *	the key 'key'.
122  *	When complete and successful, 'plaintext' will contain the decrypted
123  *	message.
124  *	Relies on the KCF scheduler to choose a provider.
125  *
126  * Returns:
127  *	See comment in the beginning of the file.
128  */
129 int
crypto_decrypt(crypto_mechanism_t * mech,crypto_data_t * ciphertext,crypto_key_t * key,crypto_ctx_template_t tmpl,crypto_data_t * plaintext)130 crypto_decrypt(crypto_mechanism_t *mech, crypto_data_t *ciphertext,
131     crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *plaintext)
132 {
133 	int error;
134 	kcf_mech_entry_t *me;
135 	kcf_provider_desc_t *pd;
136 	kcf_ctx_template_t *ctx_tmpl;
137 	crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
138 	kcf_prov_tried_t *list = NULL;
139 
140 retry:
141 	/* pd is returned held */
142 	if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,
143 	    list, CRYPTO_FG_DECRYPT_ATOMIC)) == NULL) {
144 		if (list != NULL)
145 			kcf_free_triedlist(list);
146 		return (error);
147 	}
148 
149 	if (((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL))
150 		spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
151 
152 	crypto_mechanism_t lmech = *mech;
153 	KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
154 
155 	error = KCF_PROV_DECRYPT_ATOMIC(pd, &lmech, key,
156 	    ciphertext, plaintext, spi_ctx_tmpl);
157 
158 	if (error != CRYPTO_SUCCESS && IS_RECOVERABLE(error)) {
159 		/* Add pd to the linked list of providers tried. */
160 		if (kcf_insert_triedlist(&list, pd, KM_SLEEP) != NULL)
161 			goto retry;
162 	}
163 
164 	if (list != NULL)
165 		kcf_free_triedlist(list);
166 
167 	KCF_PROV_REFRELE(pd);
168 	return (error);
169 }
170 
171 #if defined(_KERNEL)
172 EXPORT_SYMBOL(crypto_encrypt);
173 EXPORT_SYMBOL(crypto_decrypt);
174 #endif
175