1*47e946e7SWyllys Ingersoll /*
2*47e946e7SWyllys Ingersoll * The Initial Developer of the Original Code is International
3*47e946e7SWyllys Ingersoll * Business Machines Corporation. Portions created by IBM
4*47e946e7SWyllys Ingersoll * Corporation are Copyright (C) 2005 International Business
5*47e946e7SWyllys Ingersoll * Machines Corporation. All Rights Reserved.
6*47e946e7SWyllys Ingersoll *
7*47e946e7SWyllys Ingersoll * This program is free software; you can redistribute it and/or modify
8*47e946e7SWyllys Ingersoll * it under the terms of the Common Public License as published by
9*47e946e7SWyllys Ingersoll * IBM Corporation; either version 1 of the License, or (at your option)
10*47e946e7SWyllys Ingersoll * any later version.
11*47e946e7SWyllys Ingersoll *
12*47e946e7SWyllys Ingersoll * This program is distributed in the hope that it will be useful,
13*47e946e7SWyllys Ingersoll * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*47e946e7SWyllys Ingersoll * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*47e946e7SWyllys Ingersoll * Common Public License for more details.
16*47e946e7SWyllys Ingersoll *
17*47e946e7SWyllys Ingersoll * You should have received a copy of the Common Public License
18*47e946e7SWyllys Ingersoll * along with this program; if not, a copy can be viewed at
19*47e946e7SWyllys Ingersoll * http://www.opensource.org/licenses/cpl1.0.php.
20*47e946e7SWyllys Ingersoll */
21*47e946e7SWyllys Ingersoll /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
22*47e946e7SWyllys Ingersoll /*
23*47e946e7SWyllys Ingersoll * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*47e946e7SWyllys Ingersoll * Use is subject to license terms.
25*47e946e7SWyllys Ingersoll */
26*47e946e7SWyllys Ingersoll
27*47e946e7SWyllys Ingersoll #include "tpmtok_int.h"
28*47e946e7SWyllys Ingersoll
29*47e946e7SWyllys Ingersoll static CK_BBOOL true = TRUE, false = FALSE;
30*47e946e7SWyllys Ingersoll
31*47e946e7SWyllys Ingersoll static CK_RV
key_mgr_get_private_key_type(CK_BYTE * keydata,CK_ULONG keylen,CK_KEY_TYPE * keytype)32*47e946e7SWyllys Ingersoll key_mgr_get_private_key_type(
33*47e946e7SWyllys Ingersoll CK_BYTE *keydata,
34*47e946e7SWyllys Ingersoll CK_ULONG keylen,
35*47e946e7SWyllys Ingersoll CK_KEY_TYPE *keytype)
36*47e946e7SWyllys Ingersoll {
37*47e946e7SWyllys Ingersoll CK_BYTE *alg = NULL;
38*47e946e7SWyllys Ingersoll CK_BYTE *priv_key = NULL;
39*47e946e7SWyllys Ingersoll CK_ULONG alg_len;
40*47e946e7SWyllys Ingersoll CK_RV rc;
41*47e946e7SWyllys Ingersoll
42*47e946e7SWyllys Ingersoll rc = ber_decode_PrivateKeyInfo(keydata, keylen, &alg,
43*47e946e7SWyllys Ingersoll &alg_len, &priv_key);
44*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
45*47e946e7SWyllys Ingersoll return (rc);
46*47e946e7SWyllys Ingersoll }
47*47e946e7SWyllys Ingersoll if (alg_len >= ber_rsaEncryptionLen) {
48*47e946e7SWyllys Ingersoll if (memcmp(alg, ber_rsaEncryption,
49*47e946e7SWyllys Ingersoll ber_rsaEncryptionLen) == 0) {
50*47e946e7SWyllys Ingersoll *keytype = CKK_RSA;
51*47e946e7SWyllys Ingersoll return (CKR_OK);
52*47e946e7SWyllys Ingersoll }
53*47e946e7SWyllys Ingersoll }
54*47e946e7SWyllys Ingersoll
55*47e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE);
56*47e946e7SWyllys Ingersoll }
57*47e946e7SWyllys Ingersoll
58*47e946e7SWyllys Ingersoll CK_RV
key_mgr_generate_key_pair(SESSION * sess,CK_MECHANISM * mech,CK_ATTRIBUTE * publ_tmpl,CK_ULONG publ_count,CK_ATTRIBUTE * priv_tmpl,CK_ULONG priv_count,CK_OBJECT_HANDLE * publ_key_handle,CK_OBJECT_HANDLE * priv_key_handle)59*47e946e7SWyllys Ingersoll key_mgr_generate_key_pair(SESSION * sess,
60*47e946e7SWyllys Ingersoll CK_MECHANISM * mech,
61*47e946e7SWyllys Ingersoll CK_ATTRIBUTE * publ_tmpl,
62*47e946e7SWyllys Ingersoll CK_ULONG publ_count,
63*47e946e7SWyllys Ingersoll CK_ATTRIBUTE * priv_tmpl,
64*47e946e7SWyllys Ingersoll CK_ULONG priv_count,
65*47e946e7SWyllys Ingersoll CK_OBJECT_HANDLE * publ_key_handle,
66*47e946e7SWyllys Ingersoll CK_OBJECT_HANDLE * priv_key_handle)
67*47e946e7SWyllys Ingersoll {
68*47e946e7SWyllys Ingersoll OBJECT * publ_key_obj = NULL;
69*47e946e7SWyllys Ingersoll OBJECT * priv_key_obj = NULL;
70*47e946e7SWyllys Ingersoll CK_ATTRIBUTE * attr = NULL;
71*47e946e7SWyllys Ingersoll CK_ATTRIBUTE * new_attr = NULL;
72*47e946e7SWyllys Ingersoll CK_ULONG i, keyclass, subclass = 0;
73*47e946e7SWyllys Ingersoll CK_BBOOL flag;
74*47e946e7SWyllys Ingersoll CK_RV rc;
75*47e946e7SWyllys Ingersoll
76*47e946e7SWyllys Ingersoll if (! sess || ! mech || ! publ_key_handle || ! priv_key_handle) {
77*47e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED);
78*47e946e7SWyllys Ingersoll }
79*47e946e7SWyllys Ingersoll if (! publ_tmpl && (publ_count != 0)) {
80*47e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED);
81*47e946e7SWyllys Ingersoll }
82*47e946e7SWyllys Ingersoll if (! priv_tmpl && (priv_count != 0)) {
83*47e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED);
84*47e946e7SWyllys Ingersoll }
85*47e946e7SWyllys Ingersoll
86*47e946e7SWyllys Ingersoll for (i = 0; i < publ_count; i++) {
87*47e946e7SWyllys Ingersoll if (publ_tmpl[i].type == CKA_CLASS) {
88*47e946e7SWyllys Ingersoll keyclass = *(CK_OBJECT_CLASS *)publ_tmpl[i].pValue;
89*47e946e7SWyllys Ingersoll if (keyclass != CKO_PUBLIC_KEY) {
90*47e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT);
91*47e946e7SWyllys Ingersoll }
92*47e946e7SWyllys Ingersoll }
93*47e946e7SWyllys Ingersoll
94*47e946e7SWyllys Ingersoll if (publ_tmpl[i].type == CKA_KEY_TYPE)
95*47e946e7SWyllys Ingersoll subclass = *(CK_ULONG *)publ_tmpl[i].pValue;
96*47e946e7SWyllys Ingersoll }
97*47e946e7SWyllys Ingersoll
98*47e946e7SWyllys Ingersoll
99*47e946e7SWyllys Ingersoll for (i = 0; i < priv_count; i++) {
100*47e946e7SWyllys Ingersoll if (priv_tmpl[i].type == CKA_CLASS) {
101*47e946e7SWyllys Ingersoll keyclass = *(CK_OBJECT_CLASS *)priv_tmpl[i].pValue;
102*47e946e7SWyllys Ingersoll if (keyclass != CKO_PRIVATE_KEY) {
103*47e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT);
104*47e946e7SWyllys Ingersoll }
105*47e946e7SWyllys Ingersoll }
106*47e946e7SWyllys Ingersoll
107*47e946e7SWyllys Ingersoll if (priv_tmpl[i].type == CKA_KEY_TYPE) {
108*47e946e7SWyllys Ingersoll CK_ULONG temp = *(CK_ULONG *)priv_tmpl[i].pValue;
109*47e946e7SWyllys Ingersoll if (temp != subclass) {
110*47e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT);
111*47e946e7SWyllys Ingersoll }
112*47e946e7SWyllys Ingersoll }
113*47e946e7SWyllys Ingersoll }
114*47e946e7SWyllys Ingersoll
115*47e946e7SWyllys Ingersoll
116*47e946e7SWyllys Ingersoll switch (mech->mechanism) {
117*47e946e7SWyllys Ingersoll case CKM_RSA_PKCS_KEY_PAIR_GEN:
118*47e946e7SWyllys Ingersoll if (subclass != 0 && subclass != CKK_RSA) {
119*47e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT);
120*47e946e7SWyllys Ingersoll }
121*47e946e7SWyllys Ingersoll
122*47e946e7SWyllys Ingersoll subclass = CKK_RSA;
123*47e946e7SWyllys Ingersoll break;
124*47e946e7SWyllys Ingersoll
125*47e946e7SWyllys Ingersoll default:
126*47e946e7SWyllys Ingersoll return (CKR_MECHANISM_INVALID);
127*47e946e7SWyllys Ingersoll }
128*47e946e7SWyllys Ingersoll
129*47e946e7SWyllys Ingersoll
130*47e946e7SWyllys Ingersoll rc = object_mgr_create_skel(sess,
131*47e946e7SWyllys Ingersoll publ_tmpl, publ_count, MODE_KEYGEN,
132*47e946e7SWyllys Ingersoll CKO_PUBLIC_KEY, subclass, &publ_key_obj);
133*47e946e7SWyllys Ingersoll
134*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
135*47e946e7SWyllys Ingersoll goto error;
136*47e946e7SWyllys Ingersoll }
137*47e946e7SWyllys Ingersoll rc = object_mgr_create_skel(sess,
138*47e946e7SWyllys Ingersoll priv_tmpl, priv_count, MODE_KEYGEN,
139*47e946e7SWyllys Ingersoll CKO_PRIVATE_KEY, subclass, &priv_key_obj);
140*47e946e7SWyllys Ingersoll
141*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
142*47e946e7SWyllys Ingersoll goto error;
143*47e946e7SWyllys Ingersoll }
144*47e946e7SWyllys Ingersoll
145*47e946e7SWyllys Ingersoll switch (mech->mechanism) {
146*47e946e7SWyllys Ingersoll case CKM_RSA_PKCS_KEY_PAIR_GEN:
147*47e946e7SWyllys Ingersoll rc = ckm_rsa_key_pair_gen(
148*47e946e7SWyllys Ingersoll sess->hContext,
149*47e946e7SWyllys Ingersoll publ_key_obj->template,
150*47e946e7SWyllys Ingersoll priv_key_obj->template);
151*47e946e7SWyllys Ingersoll break;
152*47e946e7SWyllys Ingersoll
153*47e946e7SWyllys Ingersoll default:
154*47e946e7SWyllys Ingersoll rc = CKR_MECHANISM_INVALID;
155*47e946e7SWyllys Ingersoll break;
156*47e946e7SWyllys Ingersoll }
157*47e946e7SWyllys Ingersoll
158*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
159*47e946e7SWyllys Ingersoll goto error;
160*47e946e7SWyllys Ingersoll }
161*47e946e7SWyllys Ingersoll
162*47e946e7SWyllys Ingersoll /*
163*47e946e7SWyllys Ingersoll * we can now set CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE
164*47e946e7SWyllys Ingersoll * to their appropriate values. this only applies to CKO_SECRET_KEY
165*47e946e7SWyllys Ingersoll * and CKO_PRIVATE_KEY objects
166*47e946e7SWyllys Ingersoll */
167*47e946e7SWyllys Ingersoll flag = template_attribute_find(priv_key_obj->template,
168*47e946e7SWyllys Ingersoll CKA_SENSITIVE, &attr);
169*47e946e7SWyllys Ingersoll if (flag == TRUE) {
170*47e946e7SWyllys Ingersoll flag = *(CK_BBOOL *)attr->pValue;
171*47e946e7SWyllys Ingersoll
172*47e946e7SWyllys Ingersoll rc = build_attribute(CKA_ALWAYS_SENSITIVE, &flag,
173*47e946e7SWyllys Ingersoll sizeof (CK_BBOOL), &new_attr);
174*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
175*47e946e7SWyllys Ingersoll goto error;
176*47e946e7SWyllys Ingersoll }
177*47e946e7SWyllys Ingersoll (void) template_update_attribute(priv_key_obj->template,
178*47e946e7SWyllys Ingersoll new_attr);
179*47e946e7SWyllys Ingersoll
180*47e946e7SWyllys Ingersoll } else {
181*47e946e7SWyllys Ingersoll rc = CKR_FUNCTION_FAILED;
182*47e946e7SWyllys Ingersoll goto error;
183*47e946e7SWyllys Ingersoll }
184*47e946e7SWyllys Ingersoll
185*47e946e7SWyllys Ingersoll
186*47e946e7SWyllys Ingersoll flag = template_attribute_find(priv_key_obj->template,
187*47e946e7SWyllys Ingersoll CKA_EXTRACTABLE, &attr);
188*47e946e7SWyllys Ingersoll if (flag == TRUE) {
189*47e946e7SWyllys Ingersoll flag = *(CK_BBOOL *)attr->pValue;
190*47e946e7SWyllys Ingersoll
191*47e946e7SWyllys Ingersoll rc = build_attribute(CKA_NEVER_EXTRACTABLE, &true,
192*47e946e7SWyllys Ingersoll sizeof (CK_BBOOL), &new_attr);
193*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
194*47e946e7SWyllys Ingersoll goto error;
195*47e946e7SWyllys Ingersoll }
196*47e946e7SWyllys Ingersoll if (flag == TRUE)
197*47e946e7SWyllys Ingersoll *(CK_BBOOL *)new_attr->pValue = false;
198*47e946e7SWyllys Ingersoll
199*47e946e7SWyllys Ingersoll (void) template_update_attribute(priv_key_obj->template,
200*47e946e7SWyllys Ingersoll new_attr);
201*47e946e7SWyllys Ingersoll
202*47e946e7SWyllys Ingersoll } else {
203*47e946e7SWyllys Ingersoll rc = CKR_FUNCTION_FAILED;
204*47e946e7SWyllys Ingersoll goto error;
205*47e946e7SWyllys Ingersoll }
206*47e946e7SWyllys Ingersoll
207*47e946e7SWyllys Ingersoll rc = object_mgr_create_final(sess, publ_key_obj, publ_key_handle);
208*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
209*47e946e7SWyllys Ingersoll goto error;
210*47e946e7SWyllys Ingersoll }
211*47e946e7SWyllys Ingersoll rc = object_mgr_create_final(sess, priv_key_obj, priv_key_handle);
212*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
213*47e946e7SWyllys Ingersoll (void) object_mgr_destroy_object(sess, *publ_key_handle);
214*47e946e7SWyllys Ingersoll publ_key_obj = NULL;
215*47e946e7SWyllys Ingersoll goto error;
216*47e946e7SWyllys Ingersoll }
217*47e946e7SWyllys Ingersoll return (rc);
218*47e946e7SWyllys Ingersoll
219*47e946e7SWyllys Ingersoll error:
220*47e946e7SWyllys Ingersoll if (publ_key_obj)
221*47e946e7SWyllys Ingersoll (void) object_free(publ_key_obj);
222*47e946e7SWyllys Ingersoll if (priv_key_obj)
223*47e946e7SWyllys Ingersoll (void) object_free(priv_key_obj);
224*47e946e7SWyllys Ingersoll
225*47e946e7SWyllys Ingersoll *publ_key_handle = 0;
226*47e946e7SWyllys Ingersoll *priv_key_handle = 0;
227*47e946e7SWyllys Ingersoll
228*47e946e7SWyllys Ingersoll return (rc);
229*47e946e7SWyllys Ingersoll }
230*47e946e7SWyllys Ingersoll
231*47e946e7SWyllys Ingersoll CK_RV
key_mgr_wrap_key(SESSION * sess,CK_BBOOL length_only,CK_MECHANISM * mech,CK_OBJECT_HANDLE h_wrapping_key,CK_OBJECT_HANDLE h_key,CK_BYTE * wrapped_key,CK_ULONG * wrapped_key_len)232*47e946e7SWyllys Ingersoll key_mgr_wrap_key(SESSION * sess,
233*47e946e7SWyllys Ingersoll CK_BBOOL length_only,
234*47e946e7SWyllys Ingersoll CK_MECHANISM * mech,
235*47e946e7SWyllys Ingersoll CK_OBJECT_HANDLE h_wrapping_key,
236*47e946e7SWyllys Ingersoll CK_OBJECT_HANDLE h_key,
237*47e946e7SWyllys Ingersoll CK_BYTE * wrapped_key,
238*47e946e7SWyllys Ingersoll CK_ULONG * wrapped_key_len) {
239*47e946e7SWyllys Ingersoll ENCR_DECR_CONTEXT * ctx = NULL;
240*47e946e7SWyllys Ingersoll OBJECT * key1_obj = NULL;
241*47e946e7SWyllys Ingersoll OBJECT * key2_obj = NULL;
242*47e946e7SWyllys Ingersoll CK_ATTRIBUTE * attr = NULL;
243*47e946e7SWyllys Ingersoll CK_BYTE * data = NULL;
244*47e946e7SWyllys Ingersoll CK_ULONG data_len;
245*47e946e7SWyllys Ingersoll CK_OBJECT_CLASS class;
246*47e946e7SWyllys Ingersoll CK_KEY_TYPE keytype;
247*47e946e7SWyllys Ingersoll CK_BBOOL flag;
248*47e946e7SWyllys Ingersoll CK_RV rc;
249*47e946e7SWyllys Ingersoll
250*47e946e7SWyllys Ingersoll if (! sess || ! wrapped_key_len) {
251*47e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED);
252*47e946e7SWyllys Ingersoll }
253*47e946e7SWyllys Ingersoll
254*47e946e7SWyllys Ingersoll rc = object_mgr_find_in_map1(sess->hContext, h_wrapping_key, &key1_obj);
255*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
256*47e946e7SWyllys Ingersoll return (CKR_WRAPPING_KEY_HANDLE_INVALID);
257*47e946e7SWyllys Ingersoll }
258*47e946e7SWyllys Ingersoll rc = object_mgr_find_in_map1(sess->hContext, h_key, &key2_obj);
259*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
260*47e946e7SWyllys Ingersoll return (CKR_KEY_HANDLE_INVALID);
261*47e946e7SWyllys Ingersoll }
262*47e946e7SWyllys Ingersoll
263*47e946e7SWyllys Ingersoll rc = template_attribute_find(key2_obj->template,
264*47e946e7SWyllys Ingersoll CKA_EXTRACTABLE, &attr);
265*47e946e7SWyllys Ingersoll if (rc == FALSE) {
266*47e946e7SWyllys Ingersoll return (CKR_KEY_NOT_WRAPPABLE);
267*47e946e7SWyllys Ingersoll } else {
268*47e946e7SWyllys Ingersoll flag = *(CK_BBOOL *)attr->pValue;
269*47e946e7SWyllys Ingersoll if (flag == FALSE) {
270*47e946e7SWyllys Ingersoll return (CKR_KEY_NOT_WRAPPABLE);
271*47e946e7SWyllys Ingersoll }
272*47e946e7SWyllys Ingersoll }
273*47e946e7SWyllys Ingersoll
274*47e946e7SWyllys Ingersoll rc = template_attribute_find(key2_obj->template, CKA_CLASS, &attr);
275*47e946e7SWyllys Ingersoll if (rc == FALSE) {
276*47e946e7SWyllys Ingersoll return (CKR_KEY_NOT_WRAPPABLE);
277*47e946e7SWyllys Ingersoll } else
278*47e946e7SWyllys Ingersoll class = *(CK_OBJECT_CLASS *)attr->pValue;
279*47e946e7SWyllys Ingersoll
280*47e946e7SWyllys Ingersoll switch (mech->mechanism) {
281*47e946e7SWyllys Ingersoll case CKM_RSA_PKCS:
282*47e946e7SWyllys Ingersoll if (class != CKO_SECRET_KEY) {
283*47e946e7SWyllys Ingersoll return (CKR_KEY_NOT_WRAPPABLE);
284*47e946e7SWyllys Ingersoll }
285*47e946e7SWyllys Ingersoll break;
286*47e946e7SWyllys Ingersoll
287*47e946e7SWyllys Ingersoll default:
288*47e946e7SWyllys Ingersoll return (CKR_KEY_NOT_WRAPPABLE);
289*47e946e7SWyllys Ingersoll }
290*47e946e7SWyllys Ingersoll
291*47e946e7SWyllys Ingersoll rc = template_attribute_find(key2_obj->template,
292*47e946e7SWyllys Ingersoll CKA_KEY_TYPE, &attr);
293*47e946e7SWyllys Ingersoll if (rc == FALSE)
294*47e946e7SWyllys Ingersoll return (CKR_KEY_NOT_WRAPPABLE);
295*47e946e7SWyllys Ingersoll else
296*47e946e7SWyllys Ingersoll keytype = *(CK_KEY_TYPE *)attr->pValue;
297*47e946e7SWyllys Ingersoll
298*47e946e7SWyllys Ingersoll switch (keytype) {
299*47e946e7SWyllys Ingersoll case CKK_RSA:
300*47e946e7SWyllys Ingersoll rc = rsa_priv_wrap_get_data(key2_obj->template, length_only,
301*47e946e7SWyllys Ingersoll &data, &data_len);
302*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
303*47e946e7SWyllys Ingersoll return (rc);
304*47e946e7SWyllys Ingersoll }
305*47e946e7SWyllys Ingersoll break;
306*47e946e7SWyllys Ingersoll
307*47e946e7SWyllys Ingersoll case CKK_GENERIC_SECRET:
308*47e946e7SWyllys Ingersoll rc = generic_secret_wrap_get_data(key2_obj->template,
309*47e946e7SWyllys Ingersoll length_only, &data, &data_len);
310*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
311*47e946e7SWyllys Ingersoll return (rc);
312*47e946e7SWyllys Ingersoll }
313*47e946e7SWyllys Ingersoll break;
314*47e946e7SWyllys Ingersoll default:
315*47e946e7SWyllys Ingersoll return (CKR_KEY_NOT_WRAPPABLE);
316*47e946e7SWyllys Ingersoll }
317*47e946e7SWyllys Ingersoll
318*47e946e7SWyllys Ingersoll switch (mech->mechanism) {
319*47e946e7SWyllys Ingersoll case CKM_RSA_PKCS:
320*47e946e7SWyllys Ingersoll break;
321*47e946e7SWyllys Ingersoll
322*47e946e7SWyllys Ingersoll default:
323*47e946e7SWyllys Ingersoll return (CKR_KEY_NOT_WRAPPABLE);
324*47e946e7SWyllys Ingersoll }
325*47e946e7SWyllys Ingersoll
326*47e946e7SWyllys Ingersoll ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof (ENCR_DECR_CONTEXT));
327*47e946e7SWyllys Ingersoll if (! ctx) {
328*47e946e7SWyllys Ingersoll return (CKR_HOST_MEMORY);
329*47e946e7SWyllys Ingersoll }
330*47e946e7SWyllys Ingersoll (void) memset(ctx, 0x0, sizeof (ENCR_DECR_CONTEXT));
331*47e946e7SWyllys Ingersoll
332*47e946e7SWyllys Ingersoll rc = encr_mgr_init(sess, ctx, OP_WRAP, mech, h_wrapping_key);
333*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
334*47e946e7SWyllys Ingersoll return (rc);
335*47e946e7SWyllys Ingersoll }
336*47e946e7SWyllys Ingersoll rc = encr_mgr_encrypt(sess, length_only,
337*47e946e7SWyllys Ingersoll ctx, data, data_len, wrapped_key, wrapped_key_len);
338*47e946e7SWyllys Ingersoll
339*47e946e7SWyllys Ingersoll if (data != NULL) {
340*47e946e7SWyllys Ingersoll free(data);
341*47e946e7SWyllys Ingersoll }
342*47e946e7SWyllys Ingersoll (void) encr_mgr_cleanup(ctx);
343*47e946e7SWyllys Ingersoll free(ctx);
344*47e946e7SWyllys Ingersoll
345*47e946e7SWyllys Ingersoll return (rc);
346*47e946e7SWyllys Ingersoll }
347*47e946e7SWyllys Ingersoll
348*47e946e7SWyllys Ingersoll CK_RV
key_mgr_unwrap_key(SESSION * sess,CK_MECHANISM * mech,CK_ATTRIBUTE * attributes,CK_ULONG attrib_count,CK_BYTE * wrapped_key,CK_ULONG wrapped_key_len,CK_OBJECT_HANDLE h_unwrapping_key,CK_OBJECT_HANDLE * h_unwrapped_key)349*47e946e7SWyllys Ingersoll key_mgr_unwrap_key(SESSION * sess,
350*47e946e7SWyllys Ingersoll CK_MECHANISM * mech,
351*47e946e7SWyllys Ingersoll CK_ATTRIBUTE * attributes,
352*47e946e7SWyllys Ingersoll CK_ULONG attrib_count,
353*47e946e7SWyllys Ingersoll CK_BYTE * wrapped_key,
354*47e946e7SWyllys Ingersoll CK_ULONG wrapped_key_len,
355*47e946e7SWyllys Ingersoll CK_OBJECT_HANDLE h_unwrapping_key,
356*47e946e7SWyllys Ingersoll CK_OBJECT_HANDLE * h_unwrapped_key)
357*47e946e7SWyllys Ingersoll {
358*47e946e7SWyllys Ingersoll ENCR_DECR_CONTEXT * ctx = NULL;
359*47e946e7SWyllys Ingersoll OBJECT * key_obj = NULL;
360*47e946e7SWyllys Ingersoll CK_BYTE * data = NULL;
361*47e946e7SWyllys Ingersoll CK_ULONG data_len;
362*47e946e7SWyllys Ingersoll CK_ULONG keyclass, keytype;
363*47e946e7SWyllys Ingersoll CK_ULONG i;
364*47e946e7SWyllys Ingersoll CK_BBOOL found_class, found_type, fromend;
365*47e946e7SWyllys Ingersoll CK_RV rc;
366*47e946e7SWyllys Ingersoll
367*47e946e7SWyllys Ingersoll
368*47e946e7SWyllys Ingersoll if (! sess || ! wrapped_key || ! h_unwrapped_key) {
369*47e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED);
370*47e946e7SWyllys Ingersoll }
371*47e946e7SWyllys Ingersoll
372*47e946e7SWyllys Ingersoll rc = object_mgr_find_in_map1(sess->hContext, h_unwrapping_key,
373*47e946e7SWyllys Ingersoll &key_obj);
374*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
375*47e946e7SWyllys Ingersoll return (CKR_WRAPPING_KEY_HANDLE_INVALID);
376*47e946e7SWyllys Ingersoll }
377*47e946e7SWyllys Ingersoll
378*47e946e7SWyllys Ingersoll found_class = FALSE;
379*47e946e7SWyllys Ingersoll found_type = FALSE;
380*47e946e7SWyllys Ingersoll
381*47e946e7SWyllys Ingersoll switch (mech->mechanism) {
382*47e946e7SWyllys Ingersoll case CKM_RSA_PKCS:
383*47e946e7SWyllys Ingersoll keyclass = CKO_SECRET_KEY;
384*47e946e7SWyllys Ingersoll found_class = TRUE;
385*47e946e7SWyllys Ingersoll break;
386*47e946e7SWyllys Ingersoll }
387*47e946e7SWyllys Ingersoll
388*47e946e7SWyllys Ingersoll for (i = 0; i < attrib_count; i++) {
389*47e946e7SWyllys Ingersoll switch (attributes[i].type) {
390*47e946e7SWyllys Ingersoll case CKA_CLASS:
391*47e946e7SWyllys Ingersoll keyclass = *(CK_OBJECT_CLASS *)attributes[i].pValue;
392*47e946e7SWyllys Ingersoll found_class = TRUE;
393*47e946e7SWyllys Ingersoll break;
394*47e946e7SWyllys Ingersoll
395*47e946e7SWyllys Ingersoll case CKA_KEY_TYPE:
396*47e946e7SWyllys Ingersoll keytype = *(CK_KEY_TYPE *)attributes[i].pValue;
397*47e946e7SWyllys Ingersoll found_type = TRUE;
398*47e946e7SWyllys Ingersoll break;
399*47e946e7SWyllys Ingersoll }
400*47e946e7SWyllys Ingersoll }
401*47e946e7SWyllys Ingersoll
402*47e946e7SWyllys Ingersoll if (found_class == FALSE || (found_type == FALSE && keyclass !=
403*47e946e7SWyllys Ingersoll CKO_PRIVATE_KEY)) {
404*47e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE);
405*47e946e7SWyllys Ingersoll }
406*47e946e7SWyllys Ingersoll
407*47e946e7SWyllys Ingersoll switch (mech->mechanism) {
408*47e946e7SWyllys Ingersoll case CKM_RSA_PKCS:
409*47e946e7SWyllys Ingersoll if (keyclass != CKO_SECRET_KEY) {
410*47e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT);
411*47e946e7SWyllys Ingersoll }
412*47e946e7SWyllys Ingersoll break;
413*47e946e7SWyllys Ingersoll default:
414*47e946e7SWyllys Ingersoll return (CKR_MECHANISM_INVALID);
415*47e946e7SWyllys Ingersoll }
416*47e946e7SWyllys Ingersoll
417*47e946e7SWyllys Ingersoll
418*47e946e7SWyllys Ingersoll ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof (ENCR_DECR_CONTEXT));
419*47e946e7SWyllys Ingersoll if (! ctx) {
420*47e946e7SWyllys Ingersoll return (CKR_HOST_MEMORY);
421*47e946e7SWyllys Ingersoll }
422*47e946e7SWyllys Ingersoll (void) memset(ctx, 0x0, sizeof (ENCR_DECR_CONTEXT));
423*47e946e7SWyllys Ingersoll
424*47e946e7SWyllys Ingersoll rc = decr_mgr_init(sess, ctx, OP_UNWRAP, mech, h_unwrapping_key);
425*47e946e7SWyllys Ingersoll if (rc != CKR_OK)
426*47e946e7SWyllys Ingersoll return (rc);
427*47e946e7SWyllys Ingersoll
428*47e946e7SWyllys Ingersoll rc = decr_mgr_decrypt(sess,
429*47e946e7SWyllys Ingersoll TRUE, ctx, wrapped_key, wrapped_key_len,
430*47e946e7SWyllys Ingersoll data, &data_len);
431*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
432*47e946e7SWyllys Ingersoll goto error;
433*47e946e7SWyllys Ingersoll }
434*47e946e7SWyllys Ingersoll data = (CK_BYTE *)malloc(data_len);
435*47e946e7SWyllys Ingersoll if (! data) {
436*47e946e7SWyllys Ingersoll rc = CKR_HOST_MEMORY;
437*47e946e7SWyllys Ingersoll goto error;
438*47e946e7SWyllys Ingersoll }
439*47e946e7SWyllys Ingersoll
440*47e946e7SWyllys Ingersoll rc = decr_mgr_decrypt(sess,
441*47e946e7SWyllys Ingersoll FALSE, ctx, wrapped_key, wrapped_key_len,
442*47e946e7SWyllys Ingersoll data, &data_len);
443*47e946e7SWyllys Ingersoll
444*47e946e7SWyllys Ingersoll (void) decr_mgr_cleanup(ctx);
445*47e946e7SWyllys Ingersoll free(ctx);
446*47e946e7SWyllys Ingersoll
447*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
448*47e946e7SWyllys Ingersoll goto error;
449*47e946e7SWyllys Ingersoll }
450*47e946e7SWyllys Ingersoll /*
451*47e946e7SWyllys Ingersoll * if we use X.509, the data will be padded from the front with zeros.
452*47e946e7SWyllys Ingersoll * PKCS #11 specifies that for this mechanism, CK_VALUE is to be read
453*47e946e7SWyllys Ingersoll * from the end of the data.
454*47e946e7SWyllys Ingersoll *
455*47e946e7SWyllys Ingersoll * Note: the PKCS #11 reference implementation gets this wrong.
456*47e946e7SWyllys Ingersoll */
457*47e946e7SWyllys Ingersoll if (mech->mechanism == CKM_RSA_X_509)
458*47e946e7SWyllys Ingersoll fromend = TRUE;
459*47e946e7SWyllys Ingersoll else
460*47e946e7SWyllys Ingersoll fromend = FALSE;
461*47e946e7SWyllys Ingersoll
462*47e946e7SWyllys Ingersoll if (keyclass == CKO_PRIVATE_KEY) {
463*47e946e7SWyllys Ingersoll rc = key_mgr_get_private_key_type(data, data_len, &keytype);
464*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
465*47e946e7SWyllys Ingersoll goto error;
466*47e946e7SWyllys Ingersoll }
467*47e946e7SWyllys Ingersoll }
468*47e946e7SWyllys Ingersoll
469*47e946e7SWyllys Ingersoll rc = object_mgr_create_skel(sess,
470*47e946e7SWyllys Ingersoll attributes, attrib_count,
471*47e946e7SWyllys Ingersoll MODE_UNWRAP, keyclass, keytype,
472*47e946e7SWyllys Ingersoll &key_obj);
473*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
474*47e946e7SWyllys Ingersoll goto error;
475*47e946e7SWyllys Ingersoll }
476*47e946e7SWyllys Ingersoll switch (keyclass) {
477*47e946e7SWyllys Ingersoll case CKO_SECRET_KEY:
478*47e946e7SWyllys Ingersoll rc = secret_key_unwrap(key_obj->template, keytype, data,
479*47e946e7SWyllys Ingersoll data_len, fromend);
480*47e946e7SWyllys Ingersoll break;
481*47e946e7SWyllys Ingersoll
482*47e946e7SWyllys Ingersoll case CKO_PRIVATE_KEY:
483*47e946e7SWyllys Ingersoll rc = priv_key_unwrap(key_obj->template, keytype,
484*47e946e7SWyllys Ingersoll data, data_len);
485*47e946e7SWyllys Ingersoll break;
486*47e946e7SWyllys Ingersoll
487*47e946e7SWyllys Ingersoll default:
488*47e946e7SWyllys Ingersoll rc = CKR_WRAPPED_KEY_INVALID;
489*47e946e7SWyllys Ingersoll break;
490*47e946e7SWyllys Ingersoll }
491*47e946e7SWyllys Ingersoll
492*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
493*47e946e7SWyllys Ingersoll goto error;
494*47e946e7SWyllys Ingersoll }
495*47e946e7SWyllys Ingersoll rc = object_mgr_create_final(sess, key_obj, h_unwrapped_key);
496*47e946e7SWyllys Ingersoll if (rc != CKR_OK) {
497*47e946e7SWyllys Ingersoll goto error;
498*47e946e7SWyllys Ingersoll }
499*47e946e7SWyllys Ingersoll if (data) free(data);
500*47e946e7SWyllys Ingersoll return (rc);
501*47e946e7SWyllys Ingersoll
502*47e946e7SWyllys Ingersoll error:
503*47e946e7SWyllys Ingersoll if (key_obj) (void) object_free(key_obj);
504*47e946e7SWyllys Ingersoll if (data) free(data);
505*47e946e7SWyllys Ingersoll
506*47e946e7SWyllys Ingersoll return (rc);
507*47e946e7SWyllys Ingersoll }
508