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