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