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
29extern CK_RV
30token_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
38CK_RV
39ckm_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
51static CK_RV
52ckm_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
81static CK_RV
82ckm_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
113static CK_RV
114ckm_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
143static CK_RV
144ckm_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*/
174CK_RV
175rsa_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*/
217CK_RV
218rsa_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
261CK_RV
262rsa_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*/
306CK_RV
307rsa_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
344CK_RV
345rsa_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
387CK_RV
388rsa_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
466error:
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
474CK_RV
475rsa_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);
513error:
514	(void) digest_mgr_cleanup(&context->hash_context);
515	return (rc);
516}
517
518CK_RV
519rsa_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);
594done:
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
603CK_RV
604rsa_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);
639error:
640	(void) digest_mgr_cleanup(&context->hash_context);
641	return (rc);
642}
643
644CK_RV
645rsa_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
718done:
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
727CK_RV
728rsa_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);
792done:
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