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 CK_RV
30 ckm_rsa_key_pair_gen(TSS_HCONTEXT hContext,
31 	TEMPLATE  * publ_tmpl,
32 	TEMPLATE  * priv_tmpl)
33 {
34 	CK_RV		rc;
35 
36 	rc = token_specific.t_rsa_generate_keypair(
37 	    hContext, publ_tmpl, priv_tmpl);
38 
39 	return (rc);
40 }
41 
42 static CK_RV
43 ckm_rsa_encrypt(
44 	TSS_HCONTEXT hContext,
45 	CK_BYTE   * in_data,
46 	CK_ULONG    in_data_len,
47 	CK_BYTE   * out_data,
48 	CK_ULONG  * out_data_len,
49 	OBJECT    * key_obj)
50 {
51 	CK_ATTRIBUTE	* attr    = NULL;
52 	CK_OBJECT_CLASS	keyclass;
53 	CK_RV		rc;
54 
55 	rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
56 	if (rc == FALSE) {
57 		return (CKR_FUNCTION_FAILED);
58 	} else
59 		keyclass = *(CK_OBJECT_CLASS *)attr->pValue;
60 
61 	if (keyclass != CKO_PUBLIC_KEY) {
62 		return (CKR_FUNCTION_FAILED);
63 	}
64 
65 	rc = token_specific.t_rsa_encrypt(hContext,
66 	    in_data, in_data_len,
67 	    out_data, out_data_len, key_obj);
68 
69 	return (rc);
70 }
71 
72 static CK_RV
73 ckm_rsa_decrypt(
74 	TSS_HCONTEXT hContext,
75 	CK_BYTE   * in_data,
76 	CK_ULONG    in_data_len,
77 	CK_BYTE   * out_data,
78 	CK_ULONG  * out_data_len,
79 	OBJECT    * key_obj) {
80 	CK_ATTRIBUTE	* attr	= NULL;
81 	CK_OBJECT_CLASS	keyclass;
82 	CK_RV		rc;
83 
84 
85 	rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
86 	if (rc == FALSE) {
87 		return (CKR_FUNCTION_FAILED);
88 	}
89 	else
90 		keyclass = *(CK_OBJECT_CLASS *)attr->pValue;
91 
92 	// this had better be a private key
93 	//
94 	if (keyclass != CKO_PRIVATE_KEY) {
95 		return (CKR_FUNCTION_FAILED);
96 	}
97 	rc = token_specific.t_rsa_decrypt(hContext,
98 	    in_data, in_data_len,
99 	    out_data, out_data_len, key_obj);
100 
101 	return (rc);
102 }
103 
104 static CK_RV
105 ckm_rsa_sign(
106 	TSS_HCONTEXT hContext,
107 	CK_BYTE   * in_data,
108 	CK_ULONG    in_data_len,
109 	CK_BYTE   * out_data,
110 	CK_ULONG  * out_data_len,
111 	OBJECT    * key_obj) {
112 	CK_ATTRIBUTE	* attr	= NULL;
113 	CK_OBJECT_CLASS	keyclass;
114 	CK_RV		rc;
115 
116 
117 	rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
118 	if (rc == FALSE) {
119 		return (CKR_FUNCTION_FAILED);
120 	}
121 	else
122 		keyclass = *(CK_OBJECT_CLASS *)attr->pValue;
123 
124 	// this had better be a private key
125 	//
126 	if (keyclass != CKO_PRIVATE_KEY) {
127 		return (CKR_FUNCTION_FAILED);
128 	}
129 	rc = token_specific.t_rsa_sign(
130 	    hContext, in_data, in_data_len, out_data,
131 	    out_data_len, key_obj);
132 
133 	return (rc);
134 }
135 
136 static CK_RV
137 ckm_rsa_verify(
138 	TSS_HCONTEXT hContext,
139 	CK_BYTE   * in_data,
140 	CK_ULONG    in_data_len,
141 	CK_BYTE   * out_data,
142 	CK_ULONG    out_data_len,
143 	OBJECT    * key_obj) {
144 	CK_ATTRIBUTE	* attr	= NULL;
145 	CK_OBJECT_CLASS	keyclass;
146 	CK_RV		rc;
147 
148 
149 	rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
150 	if (rc == FALSE) {
151 		return (CKR_FUNCTION_FAILED);
152 	}
153 	else
154 		keyclass = *(CK_OBJECT_CLASS *)attr->pValue;
155 
156 	if (keyclass != CKO_PUBLIC_KEY) {
157 		return (CKR_FUNCTION_FAILED);
158 	}
159 	rc = token_specific.t_rsa_verify(hContext,
160 	    in_data, in_data_len, out_data,
161 	    out_data_len, key_obj);
162 
163 	return (rc);
164 }
165 
166 /*ARGSUSED*/
167 CK_RV
168 rsa_pkcs_encrypt(SESSION	   *sess,
169 	CK_BBOOL	   length_only,
170 	ENCR_DECR_CONTEXT *ctx,
171 	CK_BYTE	   *in_data,
172 	CK_ULONG	   in_data_len,
173 	CK_BYTE	   *out_data,
174 	CK_ULONG	  *out_data_len) {
175 	OBJECT	  *key_obj  = NULL;
176 	CK_ATTRIBUTE    *attr	= NULL;
177 	CK_ULONG	 modulus_bytes;
178 	CK_BBOOL	 flag;
179 	CK_RV	    rc;
180 
181 
182 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
183 	if (rc != CKR_OK) {
184 		return (rc);
185 	}
186 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
187 	if (flag == FALSE) {
188 		return (CKR_FUNCTION_FAILED);
189 	}
190 	else
191 		modulus_bytes = attr->ulValueLen;
192 
193 	if (in_data_len > (modulus_bytes - 11)) {
194 		return (CKR_DATA_LEN_RANGE);
195 	}
196 
197 	if (length_only == TRUE) {
198 		 *out_data_len = modulus_bytes;
199 		return (CKR_OK);
200 	}
201 
202 	if (*out_data_len < modulus_bytes) {
203 		 *out_data_len = modulus_bytes;
204 		return (CKR_BUFFER_TOO_SMALL);
205 	}
206 
207 	rc = ckm_rsa_encrypt(sess->hContext, in_data, in_data_len, out_data,
208 	    out_data_len, key_obj);
209 	return (rc);
210 }
211 
212 /*ARGSUSED*/
213 CK_RV
214 rsa_pkcs_decrypt(SESSION	   *sess,
215 	CK_BBOOL	   length_only,
216 	ENCR_DECR_CONTEXT *ctx,
217 	CK_BYTE	   *in_data,
218 	CK_ULONG	   in_data_len,
219 	CK_BYTE	   *out_data,
220 	CK_ULONG	  *out_data_len)
221 {
222 	OBJECT	  *key_obj  = NULL;
223 	CK_ATTRIBUTE    *attr	= NULL;
224 	CK_ULONG	 modulus_bytes;
225 	CK_BBOOL	 flag;
226 	CK_RV	    rc;
227 
228 
229 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
230 	if (rc != CKR_OK) {
231 		return (rc);
232 	}
233 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
234 	if (flag == FALSE)
235 		return (CKR_FUNCTION_FAILED);
236 	else
237 		modulus_bytes = attr->ulValueLen;
238 
239 	if (in_data_len != modulus_bytes) {
240 		return (CKR_ENCRYPTED_DATA_LEN_RANGE);
241 	}
242 	if (length_only == TRUE) {
243 		*out_data_len = modulus_bytes - 11;
244 		return (CKR_OK);
245 	}
246 
247 	rc = ckm_rsa_decrypt(sess->hContext, in_data,
248 	    modulus_bytes, out_data,
249 	    out_data_len, key_obj);
250 
251 	if (rc == CKR_DATA_LEN_RANGE) {
252 		return (CKR_ENCRYPTED_DATA_LEN_RANGE);
253 	}
254 	return (rc);
255 }
256 
257 CK_RV
258 rsa_pkcs_sign(SESSION		*sess,
259 	CK_BBOOL		length_only,
260 	SIGN_VERIFY_CONTEXT *ctx,
261 	CK_BYTE		*in_data,
262 	CK_ULONG		in_data_len,
263 	CK_BYTE		*out_data,
264 	CK_ULONG	    *out_data_len)
265 {
266 	OBJECT	  *key_obj   = NULL;
267 	CK_ATTRIBUTE    *attr	= NULL;
268 	CK_ULONG	 modulus_bytes;
269 	CK_BBOOL	 flag;
270 	CK_RV	    rc;
271 
272 
273 	if (! sess || ! ctx || ! out_data_len) {
274 		return (CKR_FUNCTION_FAILED);
275 	}
276 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
277 	if (rc != CKR_OK) {
278 		return (rc);
279 	}
280 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
281 	if (flag == FALSE)
282 		return (CKR_FUNCTION_FAILED);
283 	else
284 		modulus_bytes = attr->ulValueLen;
285 
286 	if (in_data_len > modulus_bytes - 11) {
287 		return (CKR_DATA_LEN_RANGE);
288 	}
289 	if (length_only == TRUE) {
290 		*out_data_len = modulus_bytes;
291 		return (CKR_OK);
292 	}
293 
294 	if (*out_data_len < modulus_bytes) {
295 		*out_data_len = modulus_bytes;
296 		return (CKR_BUFFER_TOO_SMALL);
297 	}
298 
299 	rc = ckm_rsa_sign(sess->hContext, in_data, in_data_len, out_data,
300 	    out_data_len, key_obj);
301 	return (rc);
302 }
303 
304 /*ARGSUSED*/
305 CK_RV
306 rsa_pkcs_verify(SESSION		* sess,
307 	SIGN_VERIFY_CONTEXT * ctx,
308 	CK_BYTE		* in_data,
309 	CK_ULONG		in_data_len,
310 	CK_BYTE		* signature,
311 	CK_ULONG		sig_len)
312 {
313 	OBJECT	  *key_obj  = NULL;
314 	CK_ATTRIBUTE    *attr	= NULL;
315 	CK_ULONG	 modulus_bytes;
316 	CK_BBOOL	 flag;
317 	CK_RV	    rc;
318 
319 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
320 	if (rc != CKR_OK) {
321 		return (rc);
322 	}
323 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
324 	if (flag == FALSE) {
325 		return (CKR_FUNCTION_FAILED);
326 	}
327 	else
328 		modulus_bytes = attr->ulValueLen;
329 
330 	// check input data length restrictions
331 	//
332 	if (sig_len != modulus_bytes) {
333 		return (CKR_SIGNATURE_LEN_RANGE);
334 	}
335 	// verify is a public key operation --> encrypt
336 	//
337 	rc = ckm_rsa_verify(sess->hContext, in_data, in_data_len, signature,
338 	    sig_len, key_obj);
339 
340 	return (rc);
341 }
342 
343 CK_RV
344 rsa_pkcs_verify_recover(SESSION		* sess,
345 	CK_BBOOL		length_only,
346 	SIGN_VERIFY_CONTEXT * ctx,
347 	CK_BYTE		* signature,
348 	CK_ULONG		sig_len,
349 	CK_BYTE		* out_data,
350 	CK_ULONG	    * out_data_len)
351 {
352 	OBJECT	  *key_obj  = NULL;
353 	CK_ATTRIBUTE    *attr	= NULL;
354 	CK_ULONG	 modulus_bytes;
355 	CK_BBOOL	 flag;
356 	CK_RV	    rc;
357 
358 	if (! sess || ! ctx || ! out_data_len) {
359 		return (CKR_FUNCTION_FAILED);
360 	}
361 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
362 	if (rc != CKR_OK) {
363 		return (rc);
364 	}
365 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
366 	if (flag == FALSE) {
367 		return (CKR_FUNCTION_FAILED);
368 	}
369 	else
370 		modulus_bytes = attr->ulValueLen;
371 
372 	if (sig_len != modulus_bytes) {
373 		return (CKR_SIGNATURE_LEN_RANGE);
374 	}
375 	if (length_only == TRUE) {
376 		*out_data_len = modulus_bytes;
377 		return (CKR_OK);
378 	}
379 
380 	rc = ckm_rsa_encrypt(sess->hContext, signature, modulus_bytes, out_data,
381 	    out_data_len, key_obj);
382 
383 	return (rc);
384 }
385 
386 CK_RV
387 rsa_hash_pkcs_sign(SESSION		* sess,
388 	CK_BBOOL		length_only,
389 	SIGN_VERIFY_CONTEXT  * ctx,
390 	CK_BYTE		* in_data,
391 	CK_ULONG		in_data_len,
392 	CK_BYTE		* signature,
393 	CK_ULONG		* sig_len)
394 {
395 	CK_BYTE	    * ber_data  = NULL;
396 	CK_BYTE	    * octet_str = NULL;
397 	CK_BYTE	    * oid	= NULL;
398 	CK_BYTE	    * tmp	= NULL;
399 
400 	CK_ULONG		buf1[16];
401 
402 	CK_BYTE		hash[SHA1_DIGEST_LENGTH];
403 	DIGEST_CONTEXT	digest_ctx;
404 	SIGN_VERIFY_CONTEXT  sign_ctx;
405 	CK_MECHANISM	 digest_mech;
406 	CK_MECHANISM	 sign_mech;
407 	CK_ULONG	ber_data_len, hash_len, octet_str_len, oid_len;
408 	CK_RV		rc;
409 
410 	if (! sess || ! ctx || ! in_data) {
411 		return (CKR_FUNCTION_FAILED);
412 	}
413 	(void) memset(&digest_ctx, 0x0, sizeof (digest_ctx));
414 	(void) memset(&sign_ctx,   0x0, sizeof (sign_ctx));
415 
416 	if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) {
417 		digest_mech.mechanism	= CKM_MD5;
418 		oid = ber_AlgMd5;
419 		oid_len = ber_AlgMd5Len;
420 		hash_len = MD5_DIGEST_LENGTH;
421 	} else {
422 		digest_mech.mechanism	= CKM_SHA_1;
423 		oid = ber_AlgSha1;
424 		oid_len = ber_AlgSha1Len;
425 		hash_len = SHA1_DIGEST_LENGTH;
426 	}
427 
428 	digest_mech.ulParameterLen = 0;
429 	digest_mech.pParameter	= NULL;
430 
431 	rc = digest_mgr_init(sess, &digest_ctx, &digest_mech);
432 	if (rc != CKR_OK) {
433 		goto error;
434 	}
435 	rc = digest_mgr_digest(sess, length_only, &digest_ctx, in_data,
436 	    in_data_len, hash, &hash_len);
437 	if (rc != CKR_OK)
438 		goto error;
439 
440 	rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len,
441 	    hash, hash_len);
442 	if (rc != CKR_OK) {
443 		goto error;
444 	}
445 	tmp = (CK_BYTE *)buf1;
446 	(void) memcpy(tmp,	   oid,	oid_len);
447 	(void) memcpy(tmp + oid_len, octet_str, octet_str_len);
448 
449 	rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len,
450 	    tmp, (oid_len + octet_str_len));
451 	if (rc != CKR_OK)
452 		goto error;
453 
454 	sign_mech.mechanism	= CKM_RSA_PKCS;
455 	sign_mech.ulParameterLen = 0;
456 	sign_mech.pParameter	= NULL;
457 
458 	rc = sign_mgr_init(sess, &sign_ctx, &sign_mech, FALSE, ctx->key);
459 	if (rc != CKR_OK)
460 		goto error;
461 
462 	rc = sign_mgr_sign(sess, length_only, &sign_ctx, ber_data,
463 	    ber_data_len, signature, sig_len);
464 
465 error:
466 	if (octet_str) free(octet_str);
467 	if (ber_data)  free(ber_data);
468 	(void) digest_mgr_cleanup(&digest_ctx);
469 	(void) sign_mgr_cleanup(&sign_ctx);
470 	return (rc);
471 }
472 
473 CK_RV
474 rsa_hash_pkcs_sign_update(
475 	SESSION		* sess,
476 	SIGN_VERIFY_CONTEXT  * ctx,
477 	CK_BYTE		* in_data,
478 	CK_ULONG		in_data_len)
479 {
480 	RSA_DIGEST_CONTEXT  * context = NULL;
481 	CK_MECHANISM	  digest_mech;
482 	CK_RV		 rc;
483 
484 	if (! sess || ! ctx || ! in_data)
485 		return (CKR_FUNCTION_FAILED);
486 
487 	context = (RSA_DIGEST_CONTEXT *)ctx->context;
488 
489 	if (context->flag == FALSE) {
490 		if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS)
491 			digest_mech.mechanism = CKM_MD5;
492 		else
493 			digest_mech.mechanism = CKM_SHA_1;
494 
495 		digest_mech.ulParameterLen = 0;
496 		digest_mech.pParameter	= NULL;
497 
498 		rc = digest_mgr_init(sess, &context->hash_context,
499 		    &digest_mech);
500 		if (rc != CKR_OK) {
501 			goto error;
502 		}
503 		context->flag = TRUE;
504 	}
505 
506 	rc = digest_mgr_digest_update(sess, &context->hash_context,
507 	    in_data, in_data_len);
508 	if (rc != CKR_OK) {
509 		goto error;
510 	}
511 	return (CKR_OK);
512 error:
513 	(void) digest_mgr_cleanup(&context->hash_context);
514 	return (rc);
515 }
516 
517 CK_RV
518 rsa_hash_pkcs_verify(SESSION		* sess,
519 	SIGN_VERIFY_CONTEXT  * ctx,
520 	CK_BYTE		* in_data,
521 	CK_ULONG		in_data_len,
522 	CK_BYTE		* signature,
523 	CK_ULONG		sig_len)
524 {
525 	CK_BYTE	    * ber_data  = NULL;
526 	CK_BYTE	    * octet_str = NULL;
527 	CK_BYTE	    * oid	= NULL;
528 	CK_BYTE	    * tmp	= NULL;
529 
530 	CK_ULONG	buf1[16];
531 	CK_BYTE		hash[SHA1_DIGEST_LENGTH];
532 	DIGEST_CONTEXT	digest_ctx;
533 	SIGN_VERIFY_CONTEXT  verify_ctx;
534 	CK_MECHANISM	 digest_mech;
535 	CK_MECHANISM	 verify_mech;
536 	CK_ULONG	ber_data_len, hash_len, octet_str_len, oid_len;
537 	CK_RV		rc;
538 
539 	if (! sess || ! ctx || ! in_data) {
540 		return (CKR_FUNCTION_FAILED);
541 	}
542 	(void) memset(&digest_ctx, 0x0, sizeof (digest_ctx));
543 	(void) memset(&verify_ctx, 0x0, sizeof (verify_ctx));
544 
545 	if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) {
546 		digest_mech.mechanism	= CKM_MD5;
547 		oid = ber_AlgMd5;
548 		oid_len = ber_AlgMd5Len;
549 		hash_len = MD5_DIGEST_LENGTH;
550 	} else {
551 		digest_mech.mechanism	= CKM_SHA_1;
552 		oid = ber_AlgSha1;
553 		oid_len = ber_AlgSha1Len;
554 		hash_len = SHA1_DIGEST_LENGTH;
555 	}
556 
557 	digest_mech.ulParameterLen = 0;
558 	digest_mech.pParameter	= NULL;
559 
560 	rc = digest_mgr_init(sess, &digest_ctx, &digest_mech);
561 	if (rc != CKR_OK) {
562 		goto done;
563 	}
564 	rc = digest_mgr_digest(sess, FALSE, &digest_ctx, in_data,
565 	    in_data_len, hash, &hash_len);
566 	if (rc != CKR_OK) {
567 		goto done;
568 	}
569 	rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len,
570 	    hash, hash_len);
571 	if (rc != CKR_OK)
572 		goto done;
573 	tmp = (CK_BYTE *)buf1;
574 	(void) memcpy(tmp,   oid, oid_len);
575 	(void) memcpy(tmp + oid_len, octet_str, octet_str_len);
576 
577 	rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len, tmp,
578 	    (oid_len + octet_str_len));
579 	if (rc != CKR_OK) {
580 		goto done;
581 	}
582 
583 	verify_mech.mechanism	= CKM_RSA_PKCS;
584 	verify_mech.ulParameterLen = 0;
585 	verify_mech.pParameter	= NULL;
586 
587 	rc = verify_mgr_init(sess, &verify_ctx, &verify_mech, FALSE, ctx->key);
588 	if (rc != CKR_OK) {
589 		goto done;
590 	}
591 	rc = verify_mgr_verify(sess, &verify_ctx, ber_data,
592 	    ber_data_len, signature, sig_len);
593 done:
594 	if (octet_str) free(octet_str);
595 	if (ber_data)  free(ber_data);
596 
597 	(void) digest_mgr_cleanup(&digest_ctx);
598 	(void) sign_mgr_cleanup(&verify_ctx);
599 	return (rc);
600 }
601 
602 CK_RV
603 rsa_hash_pkcs_verify_update(SESSION		* sess,
604 	SIGN_VERIFY_CONTEXT  * ctx,
605 	CK_BYTE		*in_data,
606 	CK_ULONG	in_data_len)
607 {
608 	RSA_DIGEST_CONTEXT  * context = NULL;
609 	CK_MECHANISM	  digest_mech;
610 	CK_RV		 rc;
611 
612 	if (! sess || ! ctx || ! in_data) {
613 		return (CKR_FUNCTION_FAILED);
614 	}
615 	context = (RSA_DIGEST_CONTEXT *)ctx->context;
616 
617 	if (context->flag == FALSE) {
618 		if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS)
619 			digest_mech.mechanism = CKM_MD5;
620 		else
621 			digest_mech.mechanism = CKM_SHA_1;
622 
623 		digest_mech.ulParameterLen = 0;
624 		digest_mech.pParameter	= NULL;
625 
626 		rc = digest_mgr_init(sess, &context->hash_context,
627 		    &digest_mech);
628 		if (rc != CKR_OK)
629 			goto error;
630 		context->flag = TRUE;
631 	}
632 
633 	rc = digest_mgr_digest_update(sess, &context->hash_context,
634 	    in_data, in_data_len);
635 	if (rc != CKR_OK)
636 		goto error;
637 	return (CKR_OK);
638 error:
639 	(void) digest_mgr_cleanup(&context->hash_context);
640 	return (rc);
641 }
642 
643 CK_RV
644 rsa_hash_pkcs_sign_final(SESSION		* sess,
645 	CK_BBOOL	length_only,
646 	SIGN_VERIFY_CONTEXT  * ctx,
647 	CK_BYTE		* signature,
648 	CK_ULONG	* sig_len)
649 {
650 	CK_BYTE	    * ber_data  = NULL;
651 	CK_BYTE	    * octet_str = NULL;
652 	CK_BYTE	    * oid	= NULL;
653 	CK_BYTE	    * tmp	= NULL;
654 
655 	CK_ULONG buf1[16];
656 	CK_BYTE		hash[SHA1_DIGEST_LENGTH];
657 	RSA_DIGEST_CONTEXT  * context = NULL;
658 	CK_ULONG	ber_data_len, hash_len, octet_str_len, oid_len;
659 	CK_MECHANISM  sign_mech;
660 	SIGN_VERIFY_CONTEXT   sign_ctx;
661 	CK_RV		 rc;
662 
663 	if (! sess || ! ctx || ! sig_len) {
664 		return (CKR_FUNCTION_FAILED);
665 	}
666 
667 	if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) {
668 		oid = ber_AlgMd5;
669 		oid_len = ber_AlgMd5Len;
670 		hash_len = MD5_DIGEST_LENGTH;
671 	} else {
672 		oid = ber_AlgSha1;
673 		oid_len = ber_AlgSha1Len;
674 		hash_len = SHA1_DIGEST_LENGTH;
675 	}
676 
677 	(void) memset(&sign_ctx, 0x0, sizeof (sign_ctx));
678 
679 	context = (RSA_DIGEST_CONTEXT *)ctx->context;
680 
681 	rc = digest_mgr_digest_final(sess,
682 	    &context->hash_context, hash, &hash_len);
683 	if (rc != CKR_OK) {
684 		goto done;
685 	}
686 
687 	rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len,
688 	    hash, hash_len);
689 	if (rc != CKR_OK) {
690 		goto done;
691 	}
692 	tmp = (CK_BYTE *)buf1;
693 	(void) memcpy(tmp,  oid, oid_len);
694 	(void) memcpy(tmp + oid_len, octet_str, octet_str_len);
695 
696 	rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len,
697 	    tmp, (oid_len + octet_str_len));
698 	if (rc != CKR_OK) {
699 		goto done;
700 	}
701 	sign_mech.mechanism	= CKM_RSA_PKCS;
702 	sign_mech.ulParameterLen = 0;
703 	sign_mech.pParameter	= NULL;
704 
705 	rc = sign_mgr_init(sess, &sign_ctx, &sign_mech, FALSE, ctx->key);
706 	if (rc != CKR_OK) {
707 		goto done;
708 	}
709 	rc = sign_mgr_sign(sess, length_only, &sign_ctx, ber_data,
710 	    ber_data_len, signature, sig_len);
711 
712 	if (length_only == TRUE || rc == CKR_BUFFER_TOO_SMALL) {
713 		(void) sign_mgr_cleanup(&sign_ctx);
714 		return (rc);
715 	}
716 
717 done:
718 	if (octet_str) free(octet_str);
719 	if (ber_data)  free(ber_data);
720 
721 	(void) digest_mgr_cleanup(&context->hash_context);
722 	(void) sign_mgr_cleanup(&sign_ctx);
723 	return (rc);
724 }
725 
726 CK_RV
727 rsa_hash_pkcs_verify_final(SESSION		* sess,
728 	SIGN_VERIFY_CONTEXT  * ctx,
729 	CK_BYTE		* signature,
730 	CK_ULONG		sig_len)
731 {
732 	CK_BYTE	    * ber_data  = NULL;
733 	CK_BYTE	    * octet_str = NULL;
734 	CK_BYTE	    * oid	= NULL;
735 	CK_BYTE	    * tmp	= NULL;
736 
737 	CK_ULONG	buf1[16];
738 	CK_BYTE		hash[SHA1_DIGEST_LENGTH];
739 	RSA_DIGEST_CONTEXT  * context = NULL;
740 	CK_ULONG	ber_data_len, hash_len, octet_str_len, oid_len;
741 	CK_MECHANISM	  verify_mech;
742 	SIGN_VERIFY_CONTEXT   verify_ctx;
743 	CK_RV		 rc;
744 
745 	if (! sess || ! ctx || ! signature) {
746 		return (CKR_FUNCTION_FAILED);
747 	}
748 	if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) {
749 		oid = ber_AlgMd5;
750 		oid_len = ber_AlgMd5Len;
751 		hash_len = MD5_DIGEST_LENGTH;
752 	} else {
753 		oid = ber_AlgSha1;
754 		oid_len = ber_AlgSha1Len;
755 		hash_len = SHA1_DIGEST_LENGTH;
756 	}
757 
758 	(void) memset(&verify_ctx, 0x0, sizeof (verify_ctx));
759 
760 	context = (RSA_DIGEST_CONTEXT *)ctx->context;
761 
762 	rc = digest_mgr_digest_final(sess, &context->hash_context,
763 	    hash, &hash_len);
764 	if (rc != CKR_OK) {
765 		goto done;
766 	}
767 	rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len,
768 	    hash, hash_len);
769 	if (rc != CKR_OK) {
770 		goto done;
771 	}
772 	tmp = (CK_BYTE *)buf1;
773 	(void) memcpy(tmp, oid, oid_len);
774 	(void) memcpy(tmp + oid_len, octet_str, octet_str_len);
775 
776 	rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len,
777 	    tmp, (oid_len + octet_str_len));
778 	if (rc != CKR_OK) {
779 		goto done;
780 	}
781 	verify_mech.mechanism	= CKM_RSA_PKCS;
782 	verify_mech.ulParameterLen = 0;
783 	verify_mech.pParameter	= NULL;
784 
785 	rc = verify_mgr_init(sess, &verify_ctx, &verify_mech, FALSE, ctx->key);
786 	if (rc != CKR_OK) {
787 		goto done;
788 	}
789 	rc = verify_mgr_verify(sess, &verify_ctx, ber_data,
790 	    ber_data_len, signature, sig_len);
791 done:
792 	if (octet_str) free(octet_str);
793 	if (ber_data)  free(ber_data);
794 	(void) digest_mgr_cleanup(&context->hash_context);
795 	(void) verify_mgr_cleanup(&verify_ctx);
796 	return (rc);
797 }
798