xref: /illumos-gate/usr/src/uts/common/crypto/api/kcf_cipher.c (revision a07094369b21309434206d9b3601d162693466fc)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/errno.h>
30 #include <sys/types.h>
31 #include <sys/kmem.h>
32 #include <sys/sysmacros.h>
33 #include <sys/crypto/common.h>
34 #include <sys/crypto/impl.h>
35 #include <sys/crypto/api.h>
36 #include <sys/crypto/spi.h>
37 #include <sys/crypto/sched_impl.h>
38 
39 #define	CRYPTO_OPS_OFFSET(f)		offsetof(crypto_ops_t, co_##f)
40 #define	CRYPTO_CIPHER_OFFSET(f)		offsetof(crypto_cipher_ops_t, f)
41 
42 /*
43  * Encryption and decryption routines.
44  */
45 
46 /*
47  * The following are the possible returned values common to all the routines
48  * below. The applicability of some of these return values depends on the
49  * presence of the arguments.
50  *
51  *	CRYPTO_SUCCESS:	The operation completed successfully.
52  *	CRYPTO_QUEUED:	A request was submitted successfully. The callback
53  *			routine will be called when the operation is done.
54  *	CRYPTO_INVALID_MECH_NUMBER, CRYPTO_INVALID_MECH_PARAM, or
55  *	CRYPTO_INVALID_MECH for problems with the 'mech'.
56  *	CRYPTO_INVALID_DATA for bogus 'data'
57  *	CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work.
58  *	CRYPTO_INVALID_CONTEXT: Not a valid context.
59  *	CRYPTO_BUSY:	Cannot process the request now. Schedule a
60  *			crypto_bufcall(), or try later.
61  *	CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED: No provider is
62  *			capable of a function or a mechanism.
63  *	CRYPTO_INVALID_KEY: bogus 'key' argument.
64  *	CRYPTO_INVALID_PLAINTEXT: bogus 'plaintext' argument.
65  *	CRYPTO_INVALID_CIPHERTEXT: bogus 'ciphertext' argument.
66  */
67 
68 /*
69  * crypto_cipher_init_prov()
70  *
71  * Arguments:
72  *
73  *	pd:	provider descriptor
74  *	sid:	session id
75  *	mech:	crypto_mechanism_t pointer.
76  *		mech_type is a valid value previously returned by
77  *		crypto_mech2id();
78  *		When the mech's parameter is not NULL, its definition depends
79  *		on the standard definition of the mechanism.
80  *	key:	pointer to a crypto_key_t structure.
81  *	tmpl:	a crypto_ctx_template_t, opaque template of a context of an
82  *		encryption  or decryption with the 'mech' using 'key'.
83  *		'tmpl' is created by a previous call to
84  *		crypto_create_ctx_template().
85  *	ctxp:	Pointer to a crypto_context_t.
86  *	func:	CRYPTO_FG_ENCRYPT or CRYPTO_FG_DECRYPT.
87  *	cr:	crypto_call_req_t calling conditions and call back info.
88  *
89  * Description:
90  *	This is a common function invoked internally by both
91  *	crypto_encrypt_init() and crypto_decrypt_init().
92  *	Asynchronously submits a request for, or synchronously performs the
93  *	initialization of an encryption or a decryption operation.
94  *	When possible and applicable, will internally use the pre-expanded key
95  *	schedule from the context template, tmpl.
96  *	When complete and successful, 'ctxp' will contain a crypto_context_t
97  *	valid for later calls to encrypt_update() and encrypt_final(), or
98  *	decrypt_update() and decrypt_final().
99  *	The caller should hold a reference on the specified provider
100  *	descriptor before calling this function.
101  *
102  * Context:
103  *	Process or interrupt, according to the semantics dictated by the 'cr'.
104  *
105  * Returns:
106  *	See comment in the beginning of the file.
107  */
108 static int
109 crypto_cipher_init_prov(crypto_provider_t provider, crypto_session_id_t sid,
110     crypto_mechanism_t *mech, crypto_key_t *key,
111     crypto_spi_ctx_template_t tmpl, crypto_context_t *ctxp,
112     crypto_call_req_t *crq, crypto_func_group_t func)
113 {
114 	int error;
115 	crypto_ctx_t *ctx;
116 	kcf_req_params_t params;
117 	kcf_provider_desc_t *pd = provider;
118 	kcf_provider_desc_t *real_provider = pd;
119 
120 	ASSERT(KCF_PROV_REFHELD(pd));
121 
122 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
123 		if (func == CRYPTO_FG_ENCRYPT) {
124 			error = kcf_get_hardware_provider(mech->cm_type,
125 			    CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(cipher_ops),
126 			    CRYPTO_CIPHER_OFFSET(encrypt_init),
127 			    CHECK_RESTRICT(crq), pd, &real_provider);
128 		} else {
129 			error = kcf_get_hardware_provider(mech->cm_type,
130 			    CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(cipher_ops),
131 			    CRYPTO_CIPHER_OFFSET(decrypt_init),
132 			    CHECK_RESTRICT(crq), pd, &real_provider);
133 		}
134 
135 		if (error != CRYPTO_SUCCESS)
136 			return (error);
137 	}
138 
139 	/* Allocate and initialize the canonical context */
140 	if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
141 		if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
142 			KCF_PROV_REFRELE(real_provider);
143 		return (CRYPTO_HOST_MEMORY);
144 	}
145 
146 	/* The fast path for SW providers. */
147 	if (CHECK_FASTPATH(crq, pd)) {
148 		crypto_mechanism_t lmech;
149 
150 		lmech = *mech;
151 		KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
152 
153 		if (func == CRYPTO_FG_ENCRYPT)
154 			error = KCF_PROV_ENCRYPT_INIT(real_provider, ctx,
155 			    &lmech, key, tmpl, KCF_SWFP_RHNDL(crq));
156 		else {
157 			ASSERT(func == CRYPTO_FG_DECRYPT);
158 
159 			error = KCF_PROV_DECRYPT_INIT(real_provider, ctx,
160 			    &lmech, key, tmpl, KCF_SWFP_RHNDL(crq));
161 		}
162 		KCF_PROV_INCRSTATS(pd, error);
163 	} else {
164 		if (func == CRYPTO_FG_ENCRYPT) {
165 			KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_INIT, sid,
166 			    mech, key, NULL, NULL, tmpl);
167 		} else {
168 			ASSERT(func == CRYPTO_FG_DECRYPT);
169 			KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_INIT, sid,
170 			    mech, key, NULL, NULL, tmpl);
171 		}
172 
173 		error = kcf_submit_request(real_provider, ctx, crq, &params,
174 		    B_FALSE);
175 	}
176 
177 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
178 		KCF_PROV_REFRELE(real_provider);
179 
180 	if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
181 		*ctxp = (crypto_context_t)ctx;
182 	else {
183 		/* Release the hold done in kcf_new_ctx(). */
184 		KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
185 	}
186 
187 	return (error);
188 }
189 
190 /*
191  * Same as crypto_cipher_init_prov(), but relies on the scheduler to pick
192  * an appropriate provider. See crypto_cipher_init_prov() comments for more
193  * details.
194  */
195 static int
196 crypto_cipher_init(crypto_mechanism_t *mech, crypto_key_t *key,
197     crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
198     crypto_call_req_t *crq, crypto_func_group_t func)
199 {
200 	int error;
201 	kcf_mech_entry_t *me;
202 	kcf_provider_desc_t *pd;
203 	kcf_ctx_template_t *ctx_tmpl;
204 	crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
205 	kcf_prov_tried_t *list = NULL;
206 
207 retry:
208 	/* pd is returned held */
209 	if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,
210 	    list, func, CHECK_RESTRICT(crq), 0)) == NULL) {
211 		if (list != NULL)
212 			kcf_free_triedlist(list);
213 		return (error);
214 	}
215 
216 	/*
217 	 * For SW providers, check the validity of the context template
218 	 * It is very rare that the generation number mis-matches, so
219 	 * is acceptable to fail here, and let the consumer recover by
220 	 * freeing this tmpl and create a new one for the key and new SW
221 	 * provider
222 	 */
223 	if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) &&
224 	    ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) {
225 		if (ctx_tmpl->ct_generation != me->me_gen_swprov) {
226 			if (list != NULL)
227 				kcf_free_triedlist(list);
228 			KCF_PROV_REFRELE(pd);
229 			return (CRYPTO_OLD_CTX_TEMPLATE);
230 		} else {
231 			spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
232 		}
233 	}
234 
235 	error = crypto_cipher_init_prov(pd, pd->pd_sid, mech, key,
236 	    spi_ctx_tmpl, ctxp, crq, func);
237 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
238 	    IS_RECOVERABLE(error)) {
239 		/* Add pd to the linked list of providers tried. */
240 		if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
241 			goto retry;
242 	}
243 
244 	if (list != NULL)
245 		kcf_free_triedlist(list);
246 
247 	KCF_PROV_REFRELE(pd);
248 	return (error);
249 }
250 
251 /*
252  * crypto_encrypt_prov()
253  *
254  * Arguments:
255  *	pd:	provider descriptor
256  *	sid:	session id
257  *	mech:	crypto_mechanism_t pointer.
258  *		mech_type is a valid value previously returned by
259  *		crypto_mech2id();
260  *		When the mech's parameter is not NULL, its definition depends
261  *		on the standard definition of the mechanism.
262  *	key:	pointer to a crypto_key_t structure.
263  *	plaintext: The message to be encrypted
264  *	ciphertext: Storage for the encrypted message. The length needed
265  *		depends on the mechanism, and the plaintext's size.
266  *	tmpl:	a crypto_ctx_template_t, opaque template of a context of an
267  *		encryption with the 'mech' using 'key'. 'tmpl' is created by
268  *		a previous call to crypto_create_ctx_template().
269  *	cr:	crypto_call_req_t calling conditions and call back info.
270  *
271  * Description:
272  *	Asynchronously submits a request for, or synchronously performs a
273  *	single-part encryption of 'plaintext' with the mechanism 'mech', using
274  *	the key 'key'.
275  *	When complete and successful, 'ciphertext' will contain the encrypted
276  *	message.
277  *
278  * Context:
279  *	Process or interrupt, according to the semantics dictated by the 'cr'.
280  *
281  * Returns:
282  *	See comment in the beginning of the file.
283  */
284 int
285 crypto_encrypt_prov(crypto_provider_t provider, crypto_session_id_t sid,
286     crypto_mechanism_t *mech, crypto_data_t *plaintext, crypto_key_t *key,
287     crypto_ctx_template_t tmpl, crypto_data_t *ciphertext,
288     crypto_call_req_t *crq)
289 {
290 	kcf_req_params_t params;
291 	kcf_provider_desc_t *pd = provider;
292 	kcf_provider_desc_t *real_provider = pd;
293 	int error;
294 
295 	ASSERT(KCF_PROV_REFHELD(pd));
296 
297 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
298 		error = kcf_get_hardware_provider(mech->cm_type,
299 		    CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(cipher_ops),
300 		    CRYPTO_CIPHER_OFFSET(encrypt_atomic),
301 		    CHECK_RESTRICT(crq), pd, &real_provider);
302 
303 		if (error != CRYPTO_SUCCESS)
304 			return (error);
305 	}
306 
307 	KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC, sid, mech, key,
308 	    plaintext, ciphertext, tmpl);
309 
310 	error = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
311 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
312 		KCF_PROV_REFRELE(real_provider);
313 
314 	return (error);
315 }
316 
317 /*
318  * Same as crypto_encrypt_prov(), but relies on the scheduler to pick
319  * a provider. See crypto_encrypt_prov() for more details.
320  */
321 int
322 crypto_encrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext,
323     crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *ciphertext,
324     crypto_call_req_t *crq)
325 {
326 	int error;
327 	kcf_mech_entry_t *me;
328 	kcf_req_params_t params;
329 	kcf_provider_desc_t *pd;
330 	kcf_ctx_template_t *ctx_tmpl;
331 	crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
332 	kcf_prov_tried_t *list = NULL;
333 
334 retry:
335 	/* pd is returned held */
336 	if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,
337 	    list, CRYPTO_FG_ENCRYPT_ATOMIC, CHECK_RESTRICT(crq),
338 	    plaintext->cd_length)) == NULL) {
339 		if (list != NULL)
340 			kcf_free_triedlist(list);
341 		return (error);
342 	}
343 
344 	/*
345 	 * For SW providers, check the validity of the context template
346 	 * It is very rare that the generation number mis-matches, so
347 	 * is acceptable to fail here, and let the consumer recover by
348 	 * freeing this tmpl and create a new one for the key and new SW
349 	 * provider
350 	 */
351 	if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) &&
352 	    ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) {
353 		if (ctx_tmpl->ct_generation != me->me_gen_swprov) {
354 			if (list != NULL)
355 				kcf_free_triedlist(list);
356 			KCF_PROV_REFRELE(pd);
357 			return (CRYPTO_OLD_CTX_TEMPLATE);
358 		} else {
359 			spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
360 		}
361 	}
362 
363 	/* The fast path for SW providers. */
364 	if (CHECK_FASTPATH(crq, pd)) {
365 		crypto_mechanism_t lmech;
366 
367 		lmech = *mech;
368 		KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
369 
370 		error = KCF_PROV_ENCRYPT_ATOMIC(pd, pd->pd_sid, &lmech, key,
371 		    plaintext, ciphertext, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq));
372 		KCF_PROV_INCRSTATS(pd, error);
373 	} else {
374 		KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC, pd->pd_sid,
375 		    mech, key, plaintext, ciphertext, spi_ctx_tmpl);
376 		error = kcf_submit_request(pd, NULL, crq, &params, B_FALSE);
377 	}
378 
379 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
380 	    IS_RECOVERABLE(error)) {
381 		/* Add pd to the linked list of providers tried. */
382 		if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
383 			goto retry;
384 	}
385 
386 	if (list != NULL)
387 		kcf_free_triedlist(list);
388 
389 	KCF_PROV_REFRELE(pd);
390 	return (error);
391 }
392 
393 /*
394  * crypto_encrypt_init_prov()
395  *
396  * Calls crypto_cipher_init_prov() to initialize an encryption operation.
397  */
398 int
399 crypto_encrypt_init_prov(crypto_provider_t pd, crypto_session_id_t sid,
400     crypto_mechanism_t *mech, crypto_key_t *key,
401     crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
402     crypto_call_req_t *crq)
403 {
404 	return (crypto_cipher_init_prov(pd, sid, mech, key, tmpl, ctxp, crq,
405 	    CRYPTO_FG_ENCRYPT));
406 }
407 
408 /*
409  * crypto_encrypt_init()
410  *
411  * Calls crypto_cipher_init() to initialize an encryption operation
412  */
413 int
414 crypto_encrypt_init(crypto_mechanism_t *mech, crypto_key_t *key,
415     crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
416     crypto_call_req_t *crq)
417 {
418 	return (crypto_cipher_init(mech, key, tmpl, ctxp, crq,
419 	    CRYPTO_FG_ENCRYPT));
420 }
421 
422 /*
423  * crypto_encrypt_update()
424  *
425  * Arguments:
426  *	context: A crypto_context_t initialized by encrypt_init().
427  *	plaintext: The message part to be encrypted
428  *	ciphertext: Storage for the encrypted message part.
429  *	cr:	crypto_call_req_t calling conditions and call back info.
430  *
431  * Description:
432  *	Asynchronously submits a request for, or synchronously performs a
433  *	part of an encryption operation.
434  *
435  * Context:
436  *	Process or interrupt, according to the semantics dictated by the 'cr'.
437  *
438  * Returns:
439  *	See comment in the beginning of the file.
440  */
441 int
442 crypto_encrypt_update(crypto_context_t context, crypto_data_t *plaintext,
443     crypto_data_t *ciphertext, crypto_call_req_t *cr)
444 {
445 	crypto_ctx_t *ctx = (crypto_ctx_t *)context;
446 	kcf_context_t *kcf_ctx;
447 	kcf_provider_desc_t *pd;
448 	int error;
449 	kcf_req_params_t params;
450 
451 	if ((ctx == NULL) ||
452 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
453 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
454 		return (CRYPTO_INVALID_CONTEXT);
455 	}
456 
457 	ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
458 	KCF_PROV_REFHOLD(pd);
459 
460 	/* The fast path for SW providers. */
461 	if (CHECK_FASTPATH(cr, pd)) {
462 		error = KCF_PROV_ENCRYPT_UPDATE(pd, ctx, plaintext,
463 		    ciphertext, NULL);
464 		KCF_PROV_INCRSTATS(pd, error);
465 	} else {
466 		KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
467 		    ctx->cc_session, NULL, NULL, plaintext, ciphertext, NULL);
468 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
469 	}
470 
471 	KCF_PROV_REFRELE(pd);
472 	return (error);
473 }
474 
475 /*
476  * crypto_encrypt_final()
477  *
478  * Arguments:
479  *	context: A crypto_context_t initialized by encrypt_init().
480  *	ciphertext: Storage for the last part of encrypted message
481  *	cr:	crypto_call_req_t calling conditions and call back info.
482  *
483  * Description:
484  *	Asynchronously submits a request for, or synchronously performs the
485  *	final part of an encryption operation.
486  *
487  * Context:
488  *	Process or interrupt, according to the semantics dictated by the 'cr'.
489  *
490  * Returns:
491  *	See comment in the beginning of the file.
492  */
493 int
494 crypto_encrypt_final(crypto_context_t context, crypto_data_t *ciphertext,
495     crypto_call_req_t *cr)
496 {
497 	crypto_ctx_t *ctx = (crypto_ctx_t *)context;
498 	kcf_context_t *kcf_ctx;
499 	kcf_provider_desc_t *pd;
500 	int error;
501 	kcf_req_params_t params;
502 
503 	if ((ctx == NULL) ||
504 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
505 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
506 		return (CRYPTO_INVALID_CONTEXT);
507 	}
508 
509 	ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
510 	KCF_PROV_REFHOLD(pd);
511 
512 	/* The fast path for SW providers. */
513 	if (CHECK_FASTPATH(cr, pd)) {
514 		error = KCF_PROV_ENCRYPT_FINAL(pd, ctx, ciphertext, NULL);
515 		KCF_PROV_INCRSTATS(pd, error);
516 	} else {
517 		KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
518 		    ctx->cc_session, NULL, NULL, NULL, ciphertext, NULL);
519 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
520 	}
521 
522 	KCF_PROV_REFRELE(pd);
523 	/* Release the hold done in kcf_new_ctx() during init step. */
524 	KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
525 	return (error);
526 }
527 
528 /*
529  * crypto_decrypt_prov()
530  *
531  * Arguments:
532  *	pd:	provider descriptor
533  *	sid:	session id
534  *	mech:	crypto_mechanism_t pointer.
535  *		mech_type is a valid value previously returned by
536  *		crypto_mech2id();
537  *		When the mech's parameter is not NULL, its definition depends
538  *		on the standard definition of the mechanism.
539  *	key:	pointer to a crypto_key_t structure.
540  *	ciphertext: The message to be encrypted
541  *	plaintext: Storage for the encrypted message. The length needed
542  *		depends on the mechanism, and the plaintext's size.
543  *	tmpl:	a crypto_ctx_template_t, opaque template of a context of an
544  *		encryption with the 'mech' using 'key'. 'tmpl' is created by
545  *		a previous call to crypto_create_ctx_template().
546  *	cr:	crypto_call_req_t calling conditions and call back info.
547  *
548  * Description:
549  *	Asynchronously submits a request for, or synchronously performs a
550  *	single-part decryption of 'ciphertext' with the mechanism 'mech', using
551  *	the key 'key'.
552  *	When complete and successful, 'plaintext' will contain the decrypted
553  *	message.
554  *
555  * Context:
556  *	Process or interrupt, according to the semantics dictated by the 'cr'.
557  *
558  * Returns:
559  *	See comment in the beginning of the file.
560  */
561 int
562 crypto_decrypt_prov(crypto_provider_t provider, crypto_session_id_t sid,
563     crypto_mechanism_t *mech, crypto_data_t *ciphertext, crypto_key_t *key,
564     crypto_ctx_template_t tmpl, crypto_data_t *plaintext,
565     crypto_call_req_t *crq)
566 {
567 	kcf_req_params_t params;
568 	kcf_provider_desc_t *pd = provider;
569 	kcf_provider_desc_t *real_provider = pd;
570 	int rv;
571 
572 	ASSERT(KCF_PROV_REFHELD(pd));
573 
574 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
575 		rv = kcf_get_hardware_provider(mech->cm_type,
576 		    CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(cipher_ops),
577 		    CRYPTO_CIPHER_OFFSET(decrypt_atomic),
578 		    CHECK_RESTRICT(crq), pd, &real_provider);
579 
580 		if (rv != CRYPTO_SUCCESS)
581 			return (rv);
582 	}
583 
584 	KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC, sid, mech, key,
585 	    ciphertext, plaintext, tmpl);
586 
587 	rv = kcf_submit_request(real_provider, NULL, crq, &params, B_FALSE);
588 	if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
589 		KCF_PROV_REFRELE(real_provider);
590 
591 	return (rv);
592 }
593 
594 /*
595  * Same as crypto_decrypt_prov(), but relies on the KCF scheduler to
596  * choose a provider. See crypto_decrypt_prov() comments for more
597  * information.
598  */
599 int
600 crypto_decrypt(crypto_mechanism_t *mech, crypto_data_t *ciphertext,
601     crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *plaintext,
602     crypto_call_req_t *crq)
603 {
604 	int error;
605 	kcf_mech_entry_t *me;
606 	kcf_req_params_t params;
607 	kcf_provider_desc_t *pd;
608 	kcf_ctx_template_t *ctx_tmpl;
609 	crypto_spi_ctx_template_t spi_ctx_tmpl = NULL;
610 	kcf_prov_tried_t *list = NULL;
611 
612 retry:
613 	/* pd is returned held */
614 	if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error,
615 	    list, CRYPTO_FG_DECRYPT_ATOMIC, CHECK_RESTRICT(crq),
616 	    ciphertext->cd_length)) == NULL) {
617 		if (list != NULL)
618 			kcf_free_triedlist(list);
619 		return (error);
620 	}
621 
622 	/*
623 	 * For SW providers, check the validity of the context template
624 	 * It is very rare that the generation number mis-matches, so
625 	 * is acceptable to fail here, and let the consumer recover by
626 	 * freeing this tmpl and create a new one for the key and new SW
627 	 * provider
628 	 */
629 	if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) &&
630 	    ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) {
631 		if (ctx_tmpl->ct_generation != me->me_gen_swprov) {
632 			if (list != NULL)
633 				kcf_free_triedlist(list);
634 			KCF_PROV_REFRELE(pd);
635 			return (CRYPTO_OLD_CTX_TEMPLATE);
636 		} else {
637 			spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl;
638 		}
639 	}
640 
641 	/* The fast path for SW providers. */
642 	if (CHECK_FASTPATH(crq, pd)) {
643 		crypto_mechanism_t lmech;
644 
645 		lmech = *mech;
646 		KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
647 
648 		error = KCF_PROV_DECRYPT_ATOMIC(pd, pd->pd_sid, &lmech, key,
649 		    ciphertext, plaintext, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq));
650 		KCF_PROV_INCRSTATS(pd, error);
651 	} else {
652 		KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_ATOMIC, pd->pd_sid,
653 		    mech, key, ciphertext, plaintext, spi_ctx_tmpl);
654 		error = kcf_submit_request(pd, NULL, crq, &params, B_FALSE);
655 	}
656 
657 	if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
658 	    IS_RECOVERABLE(error)) {
659 		/* Add pd to the linked list of providers tried. */
660 		if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
661 			goto retry;
662 	}
663 
664 	if (list != NULL)
665 		kcf_free_triedlist(list);
666 
667 	KCF_PROV_REFRELE(pd);
668 	return (error);
669 }
670 
671 /*
672  * crypto_decrypt_init_prov()
673  *
674  * Calls crypto_cipher_init_prov() to initialize a decryption operation
675  */
676 int
677 crypto_decrypt_init_prov(crypto_provider_t pd, crypto_session_id_t sid,
678     crypto_mechanism_t *mech, crypto_key_t *key,
679     crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
680     crypto_call_req_t *crq)
681 {
682 	return (crypto_cipher_init_prov(pd, sid, mech, key, tmpl, ctxp, crq,
683 	    CRYPTO_FG_DECRYPT));
684 }
685 
686 /*
687  * crypto_decrypt_init()
688  *
689  * Calls crypto_cipher_init() to initialize a decryption operation
690  */
691 int
692 crypto_decrypt_init(crypto_mechanism_t *mech, crypto_key_t *key,
693     crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
694     crypto_call_req_t *crq)
695 {
696 	return (crypto_cipher_init(mech, key, tmpl, ctxp, crq,
697 	    CRYPTO_FG_DECRYPT));
698 }
699 
700 /*
701  * crypto_decrypt_update()
702  *
703  * Arguments:
704  *	context: A crypto_context_t initialized by decrypt_init().
705  *	ciphertext: The message part to be decrypted
706  *	plaintext: Storage for the decrypted message part.
707  *	cr:	crypto_call_req_t calling conditions and call back info.
708  *
709  * Description:
710  *	Asynchronously submits a request for, or synchronously performs a
711  *	part of an decryption operation.
712  *
713  * Context:
714  *	Process or interrupt, according to the semantics dictated by the 'cr'.
715  *
716  * Returns:
717  *	See comment in the beginning of the file.
718  */
719 int
720 crypto_decrypt_update(crypto_context_t context, crypto_data_t *ciphertext,
721     crypto_data_t *plaintext, crypto_call_req_t *cr)
722 {
723 	crypto_ctx_t *ctx = (crypto_ctx_t *)context;
724 	kcf_context_t *kcf_ctx;
725 	kcf_provider_desc_t *pd;
726 	int error;
727 	kcf_req_params_t params;
728 
729 	if ((ctx == NULL) ||
730 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
731 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
732 		return (CRYPTO_INVALID_CONTEXT);
733 	}
734 
735 	ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
736 	KCF_PROV_REFHOLD(pd);
737 
738 	/* The fast path for SW providers. */
739 	if (CHECK_FASTPATH(cr, pd)) {
740 		error = KCF_PROV_DECRYPT_UPDATE(pd, ctx, ciphertext,
741 		    plaintext, NULL);
742 		KCF_PROV_INCRSTATS(pd, error);
743 	} else {
744 		KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_UPDATE,
745 		    ctx->cc_session, NULL, NULL, ciphertext, plaintext, NULL);
746 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
747 	}
748 
749 	KCF_PROV_REFRELE(pd);
750 	return (error);
751 }
752 
753 /*
754  * crypto_decrypt_final()
755  *
756  * Arguments:
757  *	context: A crypto_context_t initialized by decrypt_init().
758  *	plaintext: Storage for the last part of the decrypted message
759  *	cr:	crypto_call_req_t calling conditions and call back info.
760  *
761  * Description:
762  *	Asynchronously submits a request for, or synchronously performs the
763  *	final part of a decryption operation.
764  *
765  * Context:
766  *	Process or interrupt, according to the semantics dictated by the 'cr'.
767  *
768  * Returns:
769  *	See comment in the beginning of the file.
770  */
771 int
772 crypto_decrypt_final(crypto_context_t context, crypto_data_t *plaintext,
773     crypto_call_req_t *cr)
774 {
775 	crypto_ctx_t *ctx = (crypto_ctx_t *)context;
776 	kcf_context_t *kcf_ctx;
777 	kcf_provider_desc_t *pd;
778 	int error;
779 	kcf_req_params_t params;
780 
781 	if ((ctx == NULL) ||
782 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
783 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
784 		return (CRYPTO_INVALID_CONTEXT);
785 	}
786 
787 	ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
788 	KCF_PROV_REFHOLD(pd);
789 
790 	/* The fast path for SW providers. */
791 	if (CHECK_FASTPATH(cr, pd)) {
792 		error = KCF_PROV_DECRYPT_FINAL(pd, ctx, plaintext,
793 		    NULL);
794 		KCF_PROV_INCRSTATS(pd, error);
795 	} else {
796 		KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_FINAL,
797 		    ctx->cc_session, NULL, NULL, NULL, plaintext, NULL);
798 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
799 	}
800 
801 	KCF_PROV_REFRELE(pd);
802 	/* Release the hold done in kcf_new_ctx() during init step. */
803 	KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
804 	return (error);
805 }
806 
807 /*
808  * See comments for crypto_encrypt_update().
809  */
810 int
811 crypto_encrypt_single(crypto_context_t context, crypto_data_t *plaintext,
812     crypto_data_t *ciphertext, crypto_call_req_t *cr)
813 {
814 	crypto_ctx_t *ctx = (crypto_ctx_t *)context;
815 	kcf_context_t *kcf_ctx;
816 	kcf_provider_desc_t *pd;
817 	int error;
818 	kcf_req_params_t params;
819 
820 	if ((ctx == NULL) ||
821 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
822 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
823 		return (CRYPTO_INVALID_CONTEXT);
824 	}
825 
826 	KCF_PROV_REFHOLD(pd);
827 
828 	/* The fast path for SW providers. */
829 	if (CHECK_FASTPATH(cr, pd)) {
830 		error = KCF_PROV_ENCRYPT(pd, ctx, plaintext,
831 		    ciphertext, NULL);
832 		KCF_PROV_INCRSTATS(pd, error);
833 	} else {
834 		KCF_WRAP_ENCRYPT_OPS_PARAMS(&params, KCF_OP_SINGLE, pd->pd_sid,
835 		    NULL, NULL, plaintext, ciphertext, NULL);
836 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
837 	}
838 
839 	KCF_PROV_REFRELE(pd);
840 	/* Release the hold done in kcf_new_ctx() during init step. */
841 	KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
842 	return (error);
843 }
844 
845 /*
846  * See comments for crypto_decrypt_update().
847  */
848 int
849 crypto_decrypt_single(crypto_context_t context, crypto_data_t *ciphertext,
850     crypto_data_t *plaintext, crypto_call_req_t *cr)
851 {
852 	crypto_ctx_t *ctx = (crypto_ctx_t *)context;
853 	kcf_context_t *kcf_ctx;
854 	kcf_provider_desc_t *pd;
855 	int error;
856 	kcf_req_params_t params;
857 
858 	if ((ctx == NULL) ||
859 	    ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
860 	    ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
861 		return (CRYPTO_INVALID_CONTEXT);
862 	}
863 
864 	KCF_PROV_REFHOLD(pd);
865 
866 	/* The fast path for SW providers. */
867 	if (CHECK_FASTPATH(cr, pd)) {
868 		error = KCF_PROV_DECRYPT(pd, ctx, ciphertext,
869 		    plaintext, NULL);
870 		KCF_PROV_INCRSTATS(pd, error);
871 	} else {
872 		KCF_WRAP_DECRYPT_OPS_PARAMS(&params, KCF_OP_SINGLE, pd->pd_sid,
873 		    NULL, NULL, ciphertext, plaintext, NULL);
874 		error = kcf_submit_request(pd, ctx, cr, &params, B_FALSE);
875 	}
876 
877 	KCF_PROV_REFRELE(pd);
878 	/* Release the hold done in kcf_new_ctx() during init step. */
879 	KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
880 	return (error);
881 }
882