xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_tpm/common/key_mgr.c (revision 7a088f03b431bdffa96c3b2175964d4d38420caa)
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 
29 static CK_BBOOL true = TRUE, false = FALSE;
30 
31 static CK_RV
32 key_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 
58 CK_RV
59 key_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 
219 error:
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 
231 CK_RV
232 key_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 
348 CK_RV
349 key_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 
502 error:
503 	if (key_obj) (void) object_free(key_obj);
504 	if (data)    free(data);
505 
506 	return (rc);
507 }
508