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 2004 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/systm.h>
32 #include <sys/kmem.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 /*
40  * Crypto contexts manipulation routines
41  */
42 
43 /*
44  * crypto_create_ctx_template()
45  *
46  * Arguments:
47  *
48  *	mech:	crypto_mechanism_t pointer.
49  *		mech_type is a valid value previously returned by
50  *		crypto_mech2id();
51  *		When the mech's parameter is not NULL, its definition depends
52  *		on the standard definition of the mechanism.
53  *	key:	pointer to a crypto_key_t structure.
54  *	ptmpl:	a storage for the opaque crypto_ctx_template_t, allocated and
55  *		initialized by the software provider this routine is
56  *		dispatched to.
57  *	kmflag:	KM_SLEEP/KM_NOSLEEP mem. alloc. flag.
58  *
59  * Description:
60  *	Redirects the call to the software provider of the specified
61  *	mechanism. That provider will allocate and pre-compute/pre-expand
62  *	the context template, reusable by later calls to crypto_xxx_init().
63  *	The size and address of that provider context template are stored
64  *	in an internal structure, kcf_ctx_template_t. The address of that
65  *	structure is given back to the caller in *ptmpl.
66  *
67  * Context:
68  *	Process or interrupt.
69  *
70  * Returns:
71  *	CRYPTO_SUCCESS when the context template is successfully created.
72  *	CRYPTO_HOST_MEMEORY: mem alloc failure
73  *	CRYPTO_ARGUMENTS_BAD: NULL storage for the ctx template.
74  *	RYPTO_MECHANISM_INVALID: invalid mechanism 'mech'.
75  */
76 int
77 crypto_create_ctx_template(crypto_mechanism_t *mech, crypto_key_t *key,
78     crypto_ctx_template_t *ptmpl, int kmflag)
79 {
80 	int error;
81 	kcf_mech_entry_t *me;
82 	kcf_prov_mech_desc_t *pm;
83 	kcf_provider_desc_t *pd;
84 	kcf_ctx_template_t *ctx_tmpl;
85 	crypto_mechanism_t prov_mech;
86 	kcf_ops_class_t class;
87 	int index;
88 
89 	/* A few args validation */
90 
91 	if (ptmpl == NULL)
92 		return (CRYPTO_ARGUMENTS_BAD);
93 
94 	if (mech == NULL)
95 		return (CRYPTO_MECHANISM_INVALID);
96 
97 	if (kcf_get_mech_entry(mech->cm_type, &me) != KCF_SUCCESS) {
98 		/* error is one of the KCF_INVALID_MECH_XXX's */
99 		return (CRYPTO_MECHANISM_INVALID);
100 	}
101 
102 	/*
103 	 * Get the software provider for the mech.
104 	 * Lock the mech_entry until we grab the 'pd'
105 	 */
106 	mutex_enter(&me->me_mutex);
107 
108 	if (((pm = me->me_sw_prov) == NULL) ||
109 	    ((pd = pm->pm_prov_desc) == NULL)) {
110 		mutex_exit(&me->me_mutex);
111 		return (CRYPTO_MECH_NOT_SUPPORTED);
112 	}
113 	KCF_PROV_REFHOLD(pd);
114 	mutex_exit(&me->me_mutex);
115 
116 	if ((ctx_tmpl = (kcf_ctx_template_t *)kmem_alloc(
117 	    sizeof (kcf_ctx_template_t), kmflag)) == NULL) {
118 		KCF_PROV_REFRELE(pd);
119 		return (CRYPTO_HOST_MEMORY);
120 	}
121 
122 	/* Pass a mechtype that the provider understands */
123 	class = KCF_MECH2CLASS(mech->cm_type);
124 	index = KCF_MECH2INDEX(mech->cm_type);
125 	prov_mech.cm_type = pd->pd_map_mechnums[class][index];
126 	prov_mech.cm_param = mech->cm_param;
127 	prov_mech.cm_param_len = mech->cm_param_len;
128 
129 	error = KCF_PROV_CREATE_CTX_TEMPLATE(pd, &prov_mech, key,
130 	    &(ctx_tmpl->ct_prov_tmpl), &(ctx_tmpl->ct_size), KCF_RHNDL(kmflag));
131 
132 	if (error == CRYPTO_SUCCESS) {
133 		ctx_tmpl->ct_generation = me->me_gen_swprov;
134 		*ptmpl = ctx_tmpl;
135 	} else {
136 		kmem_free(ctx_tmpl, sizeof (kcf_ctx_template_t));
137 	}
138 	KCF_PROV_REFRELE(pd);
139 
140 	return (error);
141 }
142 
143 /*
144  * crypto_destroy_ctx_template()
145  *
146  * Arguments:
147  *
148  *	tmpl:	an opaque crypto_ctx_template_t previously created by
149  *		crypto_create_ctx_template()
150  *
151  * Description:
152  *	Frees the inbedded crypto_spi_ctx_template_t, then the
153  *	kcf_ctx_template_t.
154  *
155  * Context:
156  *	Process or interrupt.
157  *
158  */
159 void
160 crypto_destroy_ctx_template(crypto_ctx_template_t tmpl)
161 {
162 	kcf_ctx_template_t *ctx_tmpl = (kcf_ctx_template_t *)tmpl;
163 
164 	if (ctx_tmpl == NULL)
165 		return;
166 
167 	ASSERT(ctx_tmpl->ct_prov_tmpl != NULL);
168 
169 	bzero(ctx_tmpl->ct_prov_tmpl, ctx_tmpl->ct_size);
170 	kmem_free(ctx_tmpl->ct_prov_tmpl, ctx_tmpl->ct_size);
171 	kmem_free(ctx_tmpl, sizeof (kcf_ctx_template_t));
172 }
173