147e946e7SWyllys Ingersoll /*
247e946e7SWyllys Ingersoll  * The Initial Developer of the Original Code is International
347e946e7SWyllys Ingersoll  * Business Machines Corporation. Portions created by IBM
447e946e7SWyllys Ingersoll  * Corporation are Copyright (C) 2005 International Business
547e946e7SWyllys Ingersoll  * Machines Corporation. All Rights Reserved.
647e946e7SWyllys Ingersoll  *
747e946e7SWyllys Ingersoll  * This program is free software; you can redistribute it and/or modify
847e946e7SWyllys Ingersoll  * it under the terms of the Common Public License as published by
947e946e7SWyllys Ingersoll  * IBM Corporation; either version 1 of the License, or (at your option)
1047e946e7SWyllys Ingersoll  * any later version.
1147e946e7SWyllys Ingersoll  *
1247e946e7SWyllys Ingersoll  * This program is distributed in the hope that it will be useful,
1347e946e7SWyllys Ingersoll  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1447e946e7SWyllys Ingersoll  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1547e946e7SWyllys Ingersoll  * Common Public License for more details.
1647e946e7SWyllys Ingersoll  *
1747e946e7SWyllys Ingersoll  * You should have received a copy of the Common Public License
1847e946e7SWyllys Ingersoll  * along with this program; if not, a copy can be viewed at
1947e946e7SWyllys Ingersoll  * http://www.opensource.org/licenses/cpl1.0.php.
2047e946e7SWyllys Ingersoll  */
2147e946e7SWyllys Ingersoll /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
2247e946e7SWyllys Ingersoll /*
2347e946e7SWyllys Ingersoll  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2447e946e7SWyllys Ingersoll  * Use is subject to license terms.
2547e946e7SWyllys Ingersoll  */
2647e946e7SWyllys Ingersoll 
2747e946e7SWyllys Ingersoll #include "tpmtok_int.h"
2847e946e7SWyllys Ingersoll 
29*ab8176c2SWyllys Ingersoll extern CK_RV
30*ab8176c2SWyllys Ingersoll token_specific_rsa_verify_recover(
31*ab8176c2SWyllys Ingersoll 	TSS_HCONTEXT    hContext,
32*ab8176c2SWyllys Ingersoll 	CK_BYTE		*in_data,
33*ab8176c2SWyllys Ingersoll 	CK_ULONG	in_data_len,
34*ab8176c2SWyllys Ingersoll 	CK_BYTE		*out_data,
35*ab8176c2SWyllys Ingersoll 	CK_ULONG	*out_data_len,
36*ab8176c2SWyllys Ingersoll 	OBJECT		*key_obj);
37*ab8176c2SWyllys Ingersoll 
3847e946e7SWyllys Ingersoll CK_RV
ckm_rsa_key_pair_gen(TSS_HCONTEXT hContext,TEMPLATE * publ_tmpl,TEMPLATE * priv_tmpl)3947e946e7SWyllys Ingersoll ckm_rsa_key_pair_gen(TSS_HCONTEXT hContext,
4047e946e7SWyllys Ingersoll 	TEMPLATE  * publ_tmpl,
4147e946e7SWyllys Ingersoll 	TEMPLATE  * priv_tmpl)
4247e946e7SWyllys Ingersoll {
4347e946e7SWyllys Ingersoll 	CK_RV		rc;
4447e946e7SWyllys Ingersoll 
4547e946e7SWyllys Ingersoll 	rc = token_specific.t_rsa_generate_keypair(
4647e946e7SWyllys Ingersoll 	    hContext, publ_tmpl, priv_tmpl);
4747e946e7SWyllys Ingersoll 
4847e946e7SWyllys Ingersoll 	return (rc);
4947e946e7SWyllys Ingersoll }
5047e946e7SWyllys Ingersoll 
5147e946e7SWyllys Ingersoll static CK_RV
ckm_rsa_encrypt(TSS_HCONTEXT hContext,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,OBJECT * key_obj)5247e946e7SWyllys Ingersoll ckm_rsa_encrypt(
5347e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
5447e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
5547e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
5647e946e7SWyllys Ingersoll 	CK_BYTE   * out_data,
5747e946e7SWyllys Ingersoll 	CK_ULONG  * out_data_len,
5847e946e7SWyllys Ingersoll 	OBJECT    * key_obj)
5947e946e7SWyllys Ingersoll {
6047e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	* attr    = NULL;
6147e946e7SWyllys Ingersoll 	CK_OBJECT_CLASS	keyclass;
6247e946e7SWyllys Ingersoll 	CK_RV		rc;
6347e946e7SWyllys Ingersoll 
6447e946e7SWyllys Ingersoll 	rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
6547e946e7SWyllys Ingersoll 	if (rc == FALSE) {
6647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
6747e946e7SWyllys Ingersoll 	} else
6847e946e7SWyllys Ingersoll 		keyclass = *(CK_OBJECT_CLASS *)attr->pValue;
6947e946e7SWyllys Ingersoll 
7047e946e7SWyllys Ingersoll 	if (keyclass != CKO_PUBLIC_KEY) {
7147e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
7247e946e7SWyllys Ingersoll 	}
7347e946e7SWyllys Ingersoll 
7447e946e7SWyllys Ingersoll 	rc = token_specific.t_rsa_encrypt(hContext,
7547e946e7SWyllys Ingersoll 	    in_data, in_data_len,
7647e946e7SWyllys Ingersoll 	    out_data, out_data_len, key_obj);
7747e946e7SWyllys Ingersoll 
7847e946e7SWyllys Ingersoll 	return (rc);
7947e946e7SWyllys Ingersoll }
8047e946e7SWyllys Ingersoll 
8147e946e7SWyllys Ingersoll static CK_RV
ckm_rsa_decrypt(TSS_HCONTEXT hContext,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,OBJECT * key_obj)8247e946e7SWyllys Ingersoll ckm_rsa_decrypt(
8347e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
8447e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
8547e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
8647e946e7SWyllys Ingersoll 	CK_BYTE   * out_data,
8747e946e7SWyllys Ingersoll 	CK_ULONG  * out_data_len,
8847e946e7SWyllys Ingersoll 	OBJECT    * key_obj) {
8947e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	* attr	= NULL;
9047e946e7SWyllys Ingersoll 	CK_OBJECT_CLASS	keyclass;
9147e946e7SWyllys Ingersoll 	CK_RV		rc;
9247e946e7SWyllys Ingersoll 
9347e946e7SWyllys Ingersoll 
9447e946e7SWyllys Ingersoll 	rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
9547e946e7SWyllys Ingersoll 	if (rc == FALSE) {
9647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
9747e946e7SWyllys Ingersoll 	}
9847e946e7SWyllys Ingersoll 	else
9947e946e7SWyllys Ingersoll 		keyclass = *(CK_OBJECT_CLASS *)attr->pValue;
10047e946e7SWyllys Ingersoll 
10147e946e7SWyllys Ingersoll 	// this had better be a private key
10247e946e7SWyllys Ingersoll 	//
10347e946e7SWyllys Ingersoll 	if (keyclass != CKO_PRIVATE_KEY) {
10447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
10547e946e7SWyllys Ingersoll 	}
10647e946e7SWyllys Ingersoll 	rc = token_specific.t_rsa_decrypt(hContext,
10747e946e7SWyllys Ingersoll 	    in_data, in_data_len,
10847e946e7SWyllys Ingersoll 	    out_data, out_data_len, key_obj);
10947e946e7SWyllys Ingersoll 
11047e946e7SWyllys Ingersoll 	return (rc);
11147e946e7SWyllys Ingersoll }
11247e946e7SWyllys Ingersoll 
11347e946e7SWyllys Ingersoll static CK_RV
ckm_rsa_sign(TSS_HCONTEXT hContext,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,OBJECT * key_obj)11447e946e7SWyllys Ingersoll ckm_rsa_sign(
11547e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
11647e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
11747e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
11847e946e7SWyllys Ingersoll 	CK_BYTE   * out_data,
11947e946e7SWyllys Ingersoll 	CK_ULONG  * out_data_len,
12047e946e7SWyllys Ingersoll 	OBJECT    * key_obj) {
12147e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	* attr	= NULL;
12247e946e7SWyllys Ingersoll 	CK_OBJECT_CLASS	keyclass;
12347e946e7SWyllys Ingersoll 	CK_RV		rc;
12447e946e7SWyllys Ingersoll 
12547e946e7SWyllys Ingersoll 
12647e946e7SWyllys Ingersoll 	rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
12747e946e7SWyllys Ingersoll 	if (rc == FALSE) {
12847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
129*ab8176c2SWyllys Ingersoll 	} else {
13047e946e7SWyllys Ingersoll 		keyclass = *(CK_OBJECT_CLASS *)attr->pValue;
131*ab8176c2SWyllys Ingersoll 	}
13247e946e7SWyllys Ingersoll 
13347e946e7SWyllys Ingersoll 	if (keyclass != CKO_PRIVATE_KEY) {
13447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
13547e946e7SWyllys Ingersoll 	}
13647e946e7SWyllys Ingersoll 	rc = token_specific.t_rsa_sign(
13747e946e7SWyllys Ingersoll 	    hContext, in_data, in_data_len, out_data,
13847e946e7SWyllys Ingersoll 	    out_data_len, key_obj);
13947e946e7SWyllys Ingersoll 
14047e946e7SWyllys Ingersoll 	return (rc);
14147e946e7SWyllys Ingersoll }
14247e946e7SWyllys Ingersoll 
14347e946e7SWyllys Ingersoll static CK_RV
ckm_rsa_verify(TSS_HCONTEXT hContext,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG out_data_len,OBJECT * key_obj)14447e946e7SWyllys Ingersoll ckm_rsa_verify(
14547e946e7SWyllys Ingersoll 	TSS_HCONTEXT hContext,
14647e946e7SWyllys Ingersoll 	CK_BYTE   * in_data,
14747e946e7SWyllys Ingersoll 	CK_ULONG    in_data_len,
14847e946e7SWyllys Ingersoll 	CK_BYTE   * out_data,
14947e946e7SWyllys Ingersoll 	CK_ULONG    out_data_len,
15047e946e7SWyllys Ingersoll 	OBJECT    * key_obj) {
15147e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	* attr	= NULL;
15247e946e7SWyllys Ingersoll 	CK_OBJECT_CLASS	keyclass;
15347e946e7SWyllys Ingersoll 	CK_RV		rc;
15447e946e7SWyllys Ingersoll 
15547e946e7SWyllys Ingersoll 
15647e946e7SWyllys Ingersoll 	rc = template_attribute_find(key_obj->template, CKA_CLASS, &attr);
15747e946e7SWyllys Ingersoll 	if (rc == FALSE) {
15847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
15947e946e7SWyllys Ingersoll 	}
16047e946e7SWyllys Ingersoll 	else
16147e946e7SWyllys Ingersoll 		keyclass = *(CK_OBJECT_CLASS *)attr->pValue;
16247e946e7SWyllys Ingersoll 
16347e946e7SWyllys Ingersoll 	if (keyclass != CKO_PUBLIC_KEY) {
16447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
16547e946e7SWyllys Ingersoll 	}
16647e946e7SWyllys Ingersoll 	rc = token_specific.t_rsa_verify(hContext,
16747e946e7SWyllys Ingersoll 	    in_data, in_data_len, out_data,
16847e946e7SWyllys Ingersoll 	    out_data_len, key_obj);
16947e946e7SWyllys Ingersoll 
17047e946e7SWyllys Ingersoll 	return (rc);
17147e946e7SWyllys Ingersoll }
17247e946e7SWyllys Ingersoll 
17347e946e7SWyllys Ingersoll /*ARGSUSED*/
17447e946e7SWyllys Ingersoll CK_RV
rsa_pkcs_encrypt(SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)17547e946e7SWyllys Ingersoll rsa_pkcs_encrypt(SESSION	   *sess,
17647e946e7SWyllys Ingersoll 	CK_BBOOL	   length_only,
17747e946e7SWyllys Ingersoll 	ENCR_DECR_CONTEXT *ctx,
17847e946e7SWyllys Ingersoll 	CK_BYTE	   *in_data,
17947e946e7SWyllys Ingersoll 	CK_ULONG	   in_data_len,
18047e946e7SWyllys Ingersoll 	CK_BYTE	   *out_data,
181*ab8176c2SWyllys Ingersoll 	CK_ULONG	  *out_data_len)
182*ab8176c2SWyllys Ingersoll {
18347e946e7SWyllys Ingersoll 	OBJECT	  *key_obj  = NULL;
18447e946e7SWyllys Ingersoll 	CK_ATTRIBUTE    *attr	= NULL;
18547e946e7SWyllys Ingersoll 	CK_ULONG	 modulus_bytes;
18647e946e7SWyllys Ingersoll 	CK_BBOOL	 flag;
18747e946e7SWyllys Ingersoll 	CK_RV	    rc;
18847e946e7SWyllys Ingersoll 
18947e946e7SWyllys Ingersoll 
19047e946e7SWyllys Ingersoll 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
19147e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
19247e946e7SWyllys Ingersoll 		return (rc);
19347e946e7SWyllys Ingersoll 	}
19447e946e7SWyllys Ingersoll 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
19547e946e7SWyllys Ingersoll 	if (flag == FALSE) {
19647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
197*ab8176c2SWyllys Ingersoll 	} else {
19847e946e7SWyllys Ingersoll 		modulus_bytes = attr->ulValueLen;
19947e946e7SWyllys Ingersoll 	}
20047e946e7SWyllys Ingersoll 
20147e946e7SWyllys Ingersoll 	if (length_only == TRUE) {
202*ab8176c2SWyllys Ingersoll 		*out_data_len = modulus_bytes;
20347e946e7SWyllys Ingersoll 		return (CKR_OK);
20447e946e7SWyllys Ingersoll 	}
20547e946e7SWyllys Ingersoll 
20647e946e7SWyllys Ingersoll 	if (*out_data_len < modulus_bytes) {
207*ab8176c2SWyllys Ingersoll 		*out_data_len = modulus_bytes;
20847e946e7SWyllys Ingersoll 		return (CKR_BUFFER_TOO_SMALL);
20947e946e7SWyllys Ingersoll 	}
21047e946e7SWyllys Ingersoll 
21147e946e7SWyllys Ingersoll 	rc = ckm_rsa_encrypt(sess->hContext, in_data, in_data_len, out_data,
21247e946e7SWyllys Ingersoll 	    out_data_len, key_obj);
21347e946e7SWyllys Ingersoll 	return (rc);
21447e946e7SWyllys Ingersoll }
21547e946e7SWyllys Ingersoll 
21647e946e7SWyllys Ingersoll /*ARGSUSED*/
21747e946e7SWyllys Ingersoll CK_RV
rsa_pkcs_decrypt(SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)21847e946e7SWyllys Ingersoll rsa_pkcs_decrypt(SESSION	   *sess,
21947e946e7SWyllys Ingersoll 	CK_BBOOL	   length_only,
22047e946e7SWyllys Ingersoll 	ENCR_DECR_CONTEXT *ctx,
22147e946e7SWyllys Ingersoll 	CK_BYTE	   *in_data,
22247e946e7SWyllys Ingersoll 	CK_ULONG	   in_data_len,
22347e946e7SWyllys Ingersoll 	CK_BYTE	   *out_data,
22447e946e7SWyllys Ingersoll 	CK_ULONG	  *out_data_len)
22547e946e7SWyllys Ingersoll {
22647e946e7SWyllys Ingersoll 	OBJECT	  *key_obj  = NULL;
22747e946e7SWyllys Ingersoll 	CK_ATTRIBUTE    *attr	= NULL;
22847e946e7SWyllys Ingersoll 	CK_ULONG	 modulus_bytes;
22947e946e7SWyllys Ingersoll 	CK_BBOOL	 flag;
23047e946e7SWyllys Ingersoll 	CK_RV	    rc;
23147e946e7SWyllys Ingersoll 
23247e946e7SWyllys Ingersoll 
23347e946e7SWyllys Ingersoll 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
23447e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
23547e946e7SWyllys Ingersoll 		return (rc);
23647e946e7SWyllys Ingersoll 	}
23747e946e7SWyllys Ingersoll 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
23847e946e7SWyllys Ingersoll 	if (flag == FALSE)
23947e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
24047e946e7SWyllys Ingersoll 	else
24147e946e7SWyllys Ingersoll 		modulus_bytes = attr->ulValueLen;
24247e946e7SWyllys Ingersoll 
24347e946e7SWyllys Ingersoll 	if (in_data_len != modulus_bytes) {
24447e946e7SWyllys Ingersoll 		return (CKR_ENCRYPTED_DATA_LEN_RANGE);
24547e946e7SWyllys Ingersoll 	}
24647e946e7SWyllys Ingersoll 	if (length_only == TRUE) {
24747e946e7SWyllys Ingersoll 		*out_data_len = modulus_bytes - 11;
24847e946e7SWyllys Ingersoll 		return (CKR_OK);
24947e946e7SWyllys Ingersoll 	}
25047e946e7SWyllys Ingersoll 
25147e946e7SWyllys Ingersoll 	rc = ckm_rsa_decrypt(sess->hContext, in_data,
25247e946e7SWyllys Ingersoll 	    modulus_bytes, out_data,
25347e946e7SWyllys Ingersoll 	    out_data_len, key_obj);
25447e946e7SWyllys Ingersoll 
25547e946e7SWyllys Ingersoll 	if (rc == CKR_DATA_LEN_RANGE) {
25647e946e7SWyllys Ingersoll 		return (CKR_ENCRYPTED_DATA_LEN_RANGE);
25747e946e7SWyllys Ingersoll 	}
25847e946e7SWyllys Ingersoll 	return (rc);
25947e946e7SWyllys Ingersoll }
26047e946e7SWyllys Ingersoll 
26147e946e7SWyllys Ingersoll CK_RV
rsa_pkcs_sign(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)26247e946e7SWyllys Ingersoll rsa_pkcs_sign(SESSION		*sess,
26347e946e7SWyllys Ingersoll 	CK_BBOOL		length_only,
26447e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT *ctx,
26547e946e7SWyllys Ingersoll 	CK_BYTE		*in_data,
26647e946e7SWyllys Ingersoll 	CK_ULONG		in_data_len,
26747e946e7SWyllys Ingersoll 	CK_BYTE		*out_data,
26847e946e7SWyllys Ingersoll 	CK_ULONG	    *out_data_len)
26947e946e7SWyllys Ingersoll {
27047e946e7SWyllys Ingersoll 	OBJECT	  *key_obj   = NULL;
27147e946e7SWyllys Ingersoll 	CK_ATTRIBUTE    *attr	= NULL;
27247e946e7SWyllys Ingersoll 	CK_ULONG	 modulus_bytes;
27347e946e7SWyllys Ingersoll 	CK_BBOOL	 flag;
27447e946e7SWyllys Ingersoll 	CK_RV	    rc;
27547e946e7SWyllys Ingersoll 
27647e946e7SWyllys Ingersoll 
27747e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! out_data_len) {
27847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
27947e946e7SWyllys Ingersoll 	}
28047e946e7SWyllys Ingersoll 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
28147e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
28247e946e7SWyllys Ingersoll 		return (rc);
28347e946e7SWyllys Ingersoll 	}
28447e946e7SWyllys Ingersoll 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
28547e946e7SWyllys Ingersoll 	if (flag == FALSE)
28647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
28747e946e7SWyllys Ingersoll 	else
28847e946e7SWyllys Ingersoll 		modulus_bytes = attr->ulValueLen;
28947e946e7SWyllys Ingersoll 
29047e946e7SWyllys Ingersoll 	if (length_only == TRUE) {
29147e946e7SWyllys Ingersoll 		*out_data_len = modulus_bytes;
29247e946e7SWyllys Ingersoll 		return (CKR_OK);
29347e946e7SWyllys Ingersoll 	}
29447e946e7SWyllys Ingersoll 
29547e946e7SWyllys Ingersoll 	if (*out_data_len < modulus_bytes) {
29647e946e7SWyllys Ingersoll 		*out_data_len = modulus_bytes;
29747e946e7SWyllys Ingersoll 		return (CKR_BUFFER_TOO_SMALL);
29847e946e7SWyllys Ingersoll 	}
29947e946e7SWyllys Ingersoll 
30047e946e7SWyllys Ingersoll 	rc = ckm_rsa_sign(sess->hContext, in_data, in_data_len, out_data,
30147e946e7SWyllys Ingersoll 	    out_data_len, key_obj);
30247e946e7SWyllys Ingersoll 	return (rc);
30347e946e7SWyllys Ingersoll }
30447e946e7SWyllys Ingersoll 
30547e946e7SWyllys Ingersoll /*ARGSUSED*/
30647e946e7SWyllys Ingersoll CK_RV
rsa_pkcs_verify(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * signature,CK_ULONG sig_len)30747e946e7SWyllys Ingersoll rsa_pkcs_verify(SESSION		* sess,
30847e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT * ctx,
30947e946e7SWyllys Ingersoll 	CK_BYTE		* in_data,
31047e946e7SWyllys Ingersoll 	CK_ULONG		in_data_len,
31147e946e7SWyllys Ingersoll 	CK_BYTE		* signature,
31247e946e7SWyllys Ingersoll 	CK_ULONG		sig_len)
31347e946e7SWyllys Ingersoll {
31447e946e7SWyllys Ingersoll 	OBJECT	  *key_obj  = NULL;
31547e946e7SWyllys Ingersoll 	CK_ATTRIBUTE    *attr	= NULL;
31647e946e7SWyllys Ingersoll 	CK_ULONG	 modulus_bytes;
31747e946e7SWyllys Ingersoll 	CK_BBOOL	 flag;
31847e946e7SWyllys Ingersoll 	CK_RV	    rc;
31947e946e7SWyllys Ingersoll 
32047e946e7SWyllys Ingersoll 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
32147e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
32247e946e7SWyllys Ingersoll 		return (rc);
32347e946e7SWyllys Ingersoll 	}
32447e946e7SWyllys Ingersoll 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
32547e946e7SWyllys Ingersoll 	if (flag == FALSE) {
32647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
32747e946e7SWyllys Ingersoll 	}
32847e946e7SWyllys Ingersoll 	else
32947e946e7SWyllys Ingersoll 		modulus_bytes = attr->ulValueLen;
33047e946e7SWyllys Ingersoll 
33147e946e7SWyllys Ingersoll 	// check input data length restrictions
33247e946e7SWyllys Ingersoll 	//
33347e946e7SWyllys Ingersoll 	if (sig_len != modulus_bytes) {
33447e946e7SWyllys Ingersoll 		return (CKR_SIGNATURE_LEN_RANGE);
33547e946e7SWyllys Ingersoll 	}
33647e946e7SWyllys Ingersoll 	// verify is a public key operation --> encrypt
33747e946e7SWyllys Ingersoll 	//
33847e946e7SWyllys Ingersoll 	rc = ckm_rsa_verify(sess->hContext, in_data, in_data_len, signature,
33947e946e7SWyllys Ingersoll 	    sig_len, key_obj);
34047e946e7SWyllys Ingersoll 
34147e946e7SWyllys Ingersoll 	return (rc);
34247e946e7SWyllys Ingersoll }
34347e946e7SWyllys Ingersoll 
34447e946e7SWyllys Ingersoll CK_RV
rsa_pkcs_verify_recover(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * signature,CK_ULONG sig_len,CK_BYTE * out_data,CK_ULONG * out_data_len)345*ab8176c2SWyllys Ingersoll rsa_pkcs_verify_recover(SESSION	*sess,
346*ab8176c2SWyllys Ingersoll 	CK_BBOOL	length_only,
347*ab8176c2SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT	*ctx,
348*ab8176c2SWyllys Ingersoll 	CK_BYTE		*signature,
349*ab8176c2SWyllys Ingersoll 	CK_ULONG	sig_len,
350*ab8176c2SWyllys Ingersoll 	CK_BYTE		*out_data,
351*ab8176c2SWyllys Ingersoll 	CK_ULONG	*out_data_len)
35247e946e7SWyllys Ingersoll {
353*ab8176c2SWyllys Ingersoll 	OBJECT		*key_obj  = NULL;
354*ab8176c2SWyllys Ingersoll 	CK_ATTRIBUTE	*attr	= NULL;
355*ab8176c2SWyllys Ingersoll 	CK_ULONG	modulus_bytes;
356*ab8176c2SWyllys Ingersoll 	CK_BBOOL	flag;
357*ab8176c2SWyllys Ingersoll 	CK_RV		rc;
35847e946e7SWyllys Ingersoll 
35947e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! out_data_len) {
36047e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
36147e946e7SWyllys Ingersoll 	}
36247e946e7SWyllys Ingersoll 	rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj);
36347e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
36447e946e7SWyllys Ingersoll 		return (rc);
36547e946e7SWyllys Ingersoll 	}
36647e946e7SWyllys Ingersoll 	flag = template_attribute_find(key_obj->template, CKA_MODULUS, &attr);
36747e946e7SWyllys Ingersoll 	if (flag == FALSE) {
36847e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
36947e946e7SWyllys Ingersoll 	}
37047e946e7SWyllys Ingersoll 	else
37147e946e7SWyllys Ingersoll 		modulus_bytes = attr->ulValueLen;
37247e946e7SWyllys Ingersoll 
37347e946e7SWyllys Ingersoll 	if (sig_len != modulus_bytes) {
37447e946e7SWyllys Ingersoll 		return (CKR_SIGNATURE_LEN_RANGE);
37547e946e7SWyllys Ingersoll 	}
37647e946e7SWyllys Ingersoll 	if (length_only == TRUE) {
37747e946e7SWyllys Ingersoll 		*out_data_len = modulus_bytes;
37847e946e7SWyllys Ingersoll 		return (CKR_OK);
37947e946e7SWyllys Ingersoll 	}
38047e946e7SWyllys Ingersoll 
381*ab8176c2SWyllys Ingersoll 	rc = token_specific_rsa_verify_recover(sess->hContext,
382*ab8176c2SWyllys Ingersoll 	    signature, modulus_bytes, out_data, out_data_len, key_obj);
38347e946e7SWyllys Ingersoll 
38447e946e7SWyllys Ingersoll 	return (rc);
38547e946e7SWyllys Ingersoll }
38647e946e7SWyllys Ingersoll 
38747e946e7SWyllys Ingersoll CK_RV
rsa_hash_pkcs_sign(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * signature,CK_ULONG * sig_len)38847e946e7SWyllys Ingersoll rsa_hash_pkcs_sign(SESSION		* sess,
38947e946e7SWyllys Ingersoll 	CK_BBOOL		length_only,
39047e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  * ctx,
39147e946e7SWyllys Ingersoll 	CK_BYTE		* in_data,
39247e946e7SWyllys Ingersoll 	CK_ULONG		in_data_len,
39347e946e7SWyllys Ingersoll 	CK_BYTE		* signature,
39447e946e7SWyllys Ingersoll 	CK_ULONG		* sig_len)
39547e946e7SWyllys Ingersoll {
39647e946e7SWyllys Ingersoll 	CK_BYTE	    * ber_data  = NULL;
39747e946e7SWyllys Ingersoll 	CK_BYTE	    * octet_str = NULL;
39847e946e7SWyllys Ingersoll 	CK_BYTE	    * oid	= NULL;
39947e946e7SWyllys Ingersoll 	CK_BYTE	    * tmp	= NULL;
40047e946e7SWyllys Ingersoll 
40147e946e7SWyllys Ingersoll 	CK_ULONG		buf1[16];
40247e946e7SWyllys Ingersoll 
40347e946e7SWyllys Ingersoll 	CK_BYTE		hash[SHA1_DIGEST_LENGTH];
40447e946e7SWyllys Ingersoll 	DIGEST_CONTEXT	digest_ctx;
40547e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  sign_ctx;
40647e946e7SWyllys Ingersoll 	CK_MECHANISM	 digest_mech;
40747e946e7SWyllys Ingersoll 	CK_MECHANISM	 sign_mech;
40847e946e7SWyllys Ingersoll 	CK_ULONG	ber_data_len, hash_len, octet_str_len, oid_len;
40947e946e7SWyllys Ingersoll 	CK_RV		rc;
41047e946e7SWyllys Ingersoll 
41147e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! in_data) {
41247e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
41347e946e7SWyllys Ingersoll 	}
41447e946e7SWyllys Ingersoll 	(void) memset(&digest_ctx, 0x0, sizeof (digest_ctx));
41547e946e7SWyllys Ingersoll 	(void) memset(&sign_ctx,   0x0, sizeof (sign_ctx));
41647e946e7SWyllys Ingersoll 
41747e946e7SWyllys Ingersoll 	if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) {
41847e946e7SWyllys Ingersoll 		digest_mech.mechanism	= CKM_MD5;
41947e946e7SWyllys Ingersoll 		oid = ber_AlgMd5;
42047e946e7SWyllys Ingersoll 		oid_len = ber_AlgMd5Len;
42147e946e7SWyllys Ingersoll 		hash_len = MD5_DIGEST_LENGTH;
42247e946e7SWyllys Ingersoll 	} else {
42347e946e7SWyllys Ingersoll 		digest_mech.mechanism	= CKM_SHA_1;
42447e946e7SWyllys Ingersoll 		oid = ber_AlgSha1;
42547e946e7SWyllys Ingersoll 		oid_len = ber_AlgSha1Len;
42647e946e7SWyllys Ingersoll 		hash_len = SHA1_DIGEST_LENGTH;
42747e946e7SWyllys Ingersoll 	}
42847e946e7SWyllys Ingersoll 
42947e946e7SWyllys Ingersoll 	digest_mech.ulParameterLen = 0;
43047e946e7SWyllys Ingersoll 	digest_mech.pParameter	= NULL;
43147e946e7SWyllys Ingersoll 
43247e946e7SWyllys Ingersoll 	rc = digest_mgr_init(sess, &digest_ctx, &digest_mech);
43347e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
43447e946e7SWyllys Ingersoll 		goto error;
43547e946e7SWyllys Ingersoll 	}
43647e946e7SWyllys Ingersoll 	rc = digest_mgr_digest(sess, length_only, &digest_ctx, in_data,
43747e946e7SWyllys Ingersoll 	    in_data_len, hash, &hash_len);
43847e946e7SWyllys Ingersoll 	if (rc != CKR_OK)
43947e946e7SWyllys Ingersoll 		goto error;
44047e946e7SWyllys Ingersoll 
44147e946e7SWyllys Ingersoll 	rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len,
44247e946e7SWyllys Ingersoll 	    hash, hash_len);
44347e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
44447e946e7SWyllys Ingersoll 		goto error;
44547e946e7SWyllys Ingersoll 	}
44647e946e7SWyllys Ingersoll 	tmp = (CK_BYTE *)buf1;
44747e946e7SWyllys Ingersoll 	(void) memcpy(tmp,	   oid,	oid_len);
44847e946e7SWyllys Ingersoll 	(void) memcpy(tmp + oid_len, octet_str, octet_str_len);
44947e946e7SWyllys Ingersoll 
45047e946e7SWyllys Ingersoll 	rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len,
45147e946e7SWyllys Ingersoll 	    tmp, (oid_len + octet_str_len));
45247e946e7SWyllys Ingersoll 	if (rc != CKR_OK)
45347e946e7SWyllys Ingersoll 		goto error;
45447e946e7SWyllys Ingersoll 
45547e946e7SWyllys Ingersoll 	sign_mech.mechanism	= CKM_RSA_PKCS;
45647e946e7SWyllys Ingersoll 	sign_mech.ulParameterLen = 0;
45747e946e7SWyllys Ingersoll 	sign_mech.pParameter	= NULL;
45847e946e7SWyllys Ingersoll 
45947e946e7SWyllys Ingersoll 	rc = sign_mgr_init(sess, &sign_ctx, &sign_mech, FALSE, ctx->key);
46047e946e7SWyllys Ingersoll 	if (rc != CKR_OK)
46147e946e7SWyllys Ingersoll 		goto error;
46247e946e7SWyllys Ingersoll 
46347e946e7SWyllys Ingersoll 	rc = sign_mgr_sign(sess, length_only, &sign_ctx, ber_data,
46447e946e7SWyllys Ingersoll 	    ber_data_len, signature, sig_len);
46547e946e7SWyllys Ingersoll 
46647e946e7SWyllys Ingersoll error:
46747e946e7SWyllys Ingersoll 	if (octet_str) free(octet_str);
46847e946e7SWyllys Ingersoll 	if (ber_data)  free(ber_data);
46947e946e7SWyllys Ingersoll 	(void) digest_mgr_cleanup(&digest_ctx);
47047e946e7SWyllys Ingersoll 	(void) sign_mgr_cleanup(&sign_ctx);
47147e946e7SWyllys Ingersoll 	return (rc);
47247e946e7SWyllys Ingersoll }
47347e946e7SWyllys Ingersoll 
47447e946e7SWyllys Ingersoll CK_RV
rsa_hash_pkcs_sign_update(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len)47547e946e7SWyllys Ingersoll rsa_hash_pkcs_sign_update(
47647e946e7SWyllys Ingersoll 	SESSION		* sess,
47747e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  * ctx,
47847e946e7SWyllys Ingersoll 	CK_BYTE		* in_data,
47947e946e7SWyllys Ingersoll 	CK_ULONG		in_data_len)
48047e946e7SWyllys Ingersoll {
48147e946e7SWyllys Ingersoll 	RSA_DIGEST_CONTEXT  * context = NULL;
48247e946e7SWyllys Ingersoll 	CK_MECHANISM	  digest_mech;
48347e946e7SWyllys Ingersoll 	CK_RV		 rc;
48447e946e7SWyllys Ingersoll 
48547e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! in_data)
48647e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
48747e946e7SWyllys Ingersoll 
48847e946e7SWyllys Ingersoll 	context = (RSA_DIGEST_CONTEXT *)ctx->context;
48947e946e7SWyllys Ingersoll 
49047e946e7SWyllys Ingersoll 	if (context->flag == FALSE) {
49147e946e7SWyllys Ingersoll 		if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS)
49247e946e7SWyllys Ingersoll 			digest_mech.mechanism = CKM_MD5;
49347e946e7SWyllys Ingersoll 		else
49447e946e7SWyllys Ingersoll 			digest_mech.mechanism = CKM_SHA_1;
49547e946e7SWyllys Ingersoll 
49647e946e7SWyllys Ingersoll 		digest_mech.ulParameterLen = 0;
49747e946e7SWyllys Ingersoll 		digest_mech.pParameter	= NULL;
49847e946e7SWyllys Ingersoll 
49947e946e7SWyllys Ingersoll 		rc = digest_mgr_init(sess, &context->hash_context,
50047e946e7SWyllys Ingersoll 		    &digest_mech);
50147e946e7SWyllys Ingersoll 		if (rc != CKR_OK) {
50247e946e7SWyllys Ingersoll 			goto error;
50347e946e7SWyllys Ingersoll 		}
50447e946e7SWyllys Ingersoll 		context->flag = TRUE;
50547e946e7SWyllys Ingersoll 	}
50647e946e7SWyllys Ingersoll 
50747e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_update(sess, &context->hash_context,
50847e946e7SWyllys Ingersoll 	    in_data, in_data_len);
50947e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
51047e946e7SWyllys Ingersoll 		goto error;
51147e946e7SWyllys Ingersoll 	}
51247e946e7SWyllys Ingersoll 	return (CKR_OK);
51347e946e7SWyllys Ingersoll error:
51447e946e7SWyllys Ingersoll 	(void) digest_mgr_cleanup(&context->hash_context);
51547e946e7SWyllys Ingersoll 	return (rc);
51647e946e7SWyllys Ingersoll }
51747e946e7SWyllys Ingersoll 
51847e946e7SWyllys Ingersoll CK_RV
rsa_hash_pkcs_verify(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * signature,CK_ULONG sig_len)51947e946e7SWyllys Ingersoll rsa_hash_pkcs_verify(SESSION		* sess,
52047e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  * ctx,
52147e946e7SWyllys Ingersoll 	CK_BYTE		* in_data,
52247e946e7SWyllys Ingersoll 	CK_ULONG		in_data_len,
52347e946e7SWyllys Ingersoll 	CK_BYTE		* signature,
52447e946e7SWyllys Ingersoll 	CK_ULONG		sig_len)
52547e946e7SWyllys Ingersoll {
52647e946e7SWyllys Ingersoll 	CK_BYTE	    * ber_data  = NULL;
52747e946e7SWyllys Ingersoll 	CK_BYTE	    * octet_str = NULL;
52847e946e7SWyllys Ingersoll 	CK_BYTE	    * oid	= NULL;
52947e946e7SWyllys Ingersoll 	CK_BYTE	    * tmp	= NULL;
53047e946e7SWyllys Ingersoll 
53147e946e7SWyllys Ingersoll 	CK_ULONG	buf1[16];
53247e946e7SWyllys Ingersoll 	CK_BYTE		hash[SHA1_DIGEST_LENGTH];
53347e946e7SWyllys Ingersoll 	DIGEST_CONTEXT	digest_ctx;
53447e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  verify_ctx;
53547e946e7SWyllys Ingersoll 	CK_MECHANISM	 digest_mech;
53647e946e7SWyllys Ingersoll 	CK_MECHANISM	 verify_mech;
53747e946e7SWyllys Ingersoll 	CK_ULONG	ber_data_len, hash_len, octet_str_len, oid_len;
53847e946e7SWyllys Ingersoll 	CK_RV		rc;
53947e946e7SWyllys Ingersoll 
54047e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! in_data) {
54147e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
54247e946e7SWyllys Ingersoll 	}
54347e946e7SWyllys Ingersoll 	(void) memset(&digest_ctx, 0x0, sizeof (digest_ctx));
54447e946e7SWyllys Ingersoll 	(void) memset(&verify_ctx, 0x0, sizeof (verify_ctx));
54547e946e7SWyllys Ingersoll 
54647e946e7SWyllys Ingersoll 	if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) {
54747e946e7SWyllys Ingersoll 		digest_mech.mechanism	= CKM_MD5;
54847e946e7SWyllys Ingersoll 		oid = ber_AlgMd5;
54947e946e7SWyllys Ingersoll 		oid_len = ber_AlgMd5Len;
55047e946e7SWyllys Ingersoll 		hash_len = MD5_DIGEST_LENGTH;
55147e946e7SWyllys Ingersoll 	} else {
55247e946e7SWyllys Ingersoll 		digest_mech.mechanism	= CKM_SHA_1;
55347e946e7SWyllys Ingersoll 		oid = ber_AlgSha1;
55447e946e7SWyllys Ingersoll 		oid_len = ber_AlgSha1Len;
55547e946e7SWyllys Ingersoll 		hash_len = SHA1_DIGEST_LENGTH;
55647e946e7SWyllys Ingersoll 	}
55747e946e7SWyllys Ingersoll 
55847e946e7SWyllys Ingersoll 	digest_mech.ulParameterLen = 0;
55947e946e7SWyllys Ingersoll 	digest_mech.pParameter	= NULL;
56047e946e7SWyllys Ingersoll 
56147e946e7SWyllys Ingersoll 	rc = digest_mgr_init(sess, &digest_ctx, &digest_mech);
56247e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
56347e946e7SWyllys Ingersoll 		goto done;
56447e946e7SWyllys Ingersoll 	}
56547e946e7SWyllys Ingersoll 	rc = digest_mgr_digest(sess, FALSE, &digest_ctx, in_data,
56647e946e7SWyllys Ingersoll 	    in_data_len, hash, &hash_len);
56747e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
56847e946e7SWyllys Ingersoll 		goto done;
56947e946e7SWyllys Ingersoll 	}
57047e946e7SWyllys Ingersoll 	rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len,
57147e946e7SWyllys Ingersoll 	    hash, hash_len);
57247e946e7SWyllys Ingersoll 	if (rc != CKR_OK)
57347e946e7SWyllys Ingersoll 		goto done;
57447e946e7SWyllys Ingersoll 	tmp = (CK_BYTE *)buf1;
57547e946e7SWyllys Ingersoll 	(void) memcpy(tmp,   oid, oid_len);
57647e946e7SWyllys Ingersoll 	(void) memcpy(tmp + oid_len, octet_str, octet_str_len);
57747e946e7SWyllys Ingersoll 
57847e946e7SWyllys Ingersoll 	rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len, tmp,
57947e946e7SWyllys Ingersoll 	    (oid_len + octet_str_len));
58047e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
58147e946e7SWyllys Ingersoll 		goto done;
58247e946e7SWyllys Ingersoll 	}
58347e946e7SWyllys Ingersoll 
58447e946e7SWyllys Ingersoll 	verify_mech.mechanism	= CKM_RSA_PKCS;
58547e946e7SWyllys Ingersoll 	verify_mech.ulParameterLen = 0;
58647e946e7SWyllys Ingersoll 	verify_mech.pParameter	= NULL;
58747e946e7SWyllys Ingersoll 
58847e946e7SWyllys Ingersoll 	rc = verify_mgr_init(sess, &verify_ctx, &verify_mech, FALSE, ctx->key);
58947e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
59047e946e7SWyllys Ingersoll 		goto done;
59147e946e7SWyllys Ingersoll 	}
59247e946e7SWyllys Ingersoll 	rc = verify_mgr_verify(sess, &verify_ctx, ber_data,
59347e946e7SWyllys Ingersoll 	    ber_data_len, signature, sig_len);
59447e946e7SWyllys Ingersoll done:
59547e946e7SWyllys Ingersoll 	if (octet_str) free(octet_str);
59647e946e7SWyllys Ingersoll 	if (ber_data)  free(ber_data);
59747e946e7SWyllys Ingersoll 
59847e946e7SWyllys Ingersoll 	(void) digest_mgr_cleanup(&digest_ctx);
59947e946e7SWyllys Ingersoll 	(void) sign_mgr_cleanup(&verify_ctx);
60047e946e7SWyllys Ingersoll 	return (rc);
60147e946e7SWyllys Ingersoll }
60247e946e7SWyllys Ingersoll 
60347e946e7SWyllys Ingersoll CK_RV
rsa_hash_pkcs_verify_update(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len)60447e946e7SWyllys Ingersoll rsa_hash_pkcs_verify_update(SESSION		* sess,
60547e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  * ctx,
60647e946e7SWyllys Ingersoll 	CK_BYTE		*in_data,
60747e946e7SWyllys Ingersoll 	CK_ULONG	in_data_len)
60847e946e7SWyllys Ingersoll {
60947e946e7SWyllys Ingersoll 	RSA_DIGEST_CONTEXT  * context = NULL;
61047e946e7SWyllys Ingersoll 	CK_MECHANISM	  digest_mech;
61147e946e7SWyllys Ingersoll 	CK_RV		 rc;
61247e946e7SWyllys Ingersoll 
61347e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! in_data) {
61447e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
61547e946e7SWyllys Ingersoll 	}
61647e946e7SWyllys Ingersoll 	context = (RSA_DIGEST_CONTEXT *)ctx->context;
61747e946e7SWyllys Ingersoll 
61847e946e7SWyllys Ingersoll 	if (context->flag == FALSE) {
61947e946e7SWyllys Ingersoll 		if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS)
62047e946e7SWyllys Ingersoll 			digest_mech.mechanism = CKM_MD5;
62147e946e7SWyllys Ingersoll 		else
62247e946e7SWyllys Ingersoll 			digest_mech.mechanism = CKM_SHA_1;
62347e946e7SWyllys Ingersoll 
62447e946e7SWyllys Ingersoll 		digest_mech.ulParameterLen = 0;
62547e946e7SWyllys Ingersoll 		digest_mech.pParameter	= NULL;
62647e946e7SWyllys Ingersoll 
62747e946e7SWyllys Ingersoll 		rc = digest_mgr_init(sess, &context->hash_context,
62847e946e7SWyllys Ingersoll 		    &digest_mech);
62947e946e7SWyllys Ingersoll 		if (rc != CKR_OK)
63047e946e7SWyllys Ingersoll 			goto error;
63147e946e7SWyllys Ingersoll 		context->flag = TRUE;
63247e946e7SWyllys Ingersoll 	}
63347e946e7SWyllys Ingersoll 
63447e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_update(sess, &context->hash_context,
63547e946e7SWyllys Ingersoll 	    in_data, in_data_len);
63647e946e7SWyllys Ingersoll 	if (rc != CKR_OK)
63747e946e7SWyllys Ingersoll 		goto error;
63847e946e7SWyllys Ingersoll 	return (CKR_OK);
63947e946e7SWyllys Ingersoll error:
64047e946e7SWyllys Ingersoll 	(void) digest_mgr_cleanup(&context->hash_context);
64147e946e7SWyllys Ingersoll 	return (rc);
64247e946e7SWyllys Ingersoll }
64347e946e7SWyllys Ingersoll 
64447e946e7SWyllys Ingersoll CK_RV
rsa_hash_pkcs_sign_final(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * signature,CK_ULONG * sig_len)64547e946e7SWyllys Ingersoll rsa_hash_pkcs_sign_final(SESSION		* sess,
64647e946e7SWyllys Ingersoll 	CK_BBOOL	length_only,
64747e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  * ctx,
64847e946e7SWyllys Ingersoll 	CK_BYTE		* signature,
64947e946e7SWyllys Ingersoll 	CK_ULONG	* sig_len)
65047e946e7SWyllys Ingersoll {
65147e946e7SWyllys Ingersoll 	CK_BYTE	    * ber_data  = NULL;
65247e946e7SWyllys Ingersoll 	CK_BYTE	    * octet_str = NULL;
65347e946e7SWyllys Ingersoll 	CK_BYTE	    * oid	= NULL;
65447e946e7SWyllys Ingersoll 	CK_BYTE	    * tmp	= NULL;
65547e946e7SWyllys Ingersoll 
65647e946e7SWyllys Ingersoll 	CK_ULONG buf1[16];
65747e946e7SWyllys Ingersoll 	CK_BYTE		hash[SHA1_DIGEST_LENGTH];
65847e946e7SWyllys Ingersoll 	RSA_DIGEST_CONTEXT  * context = NULL;
65947e946e7SWyllys Ingersoll 	CK_ULONG	ber_data_len, hash_len, octet_str_len, oid_len;
66047e946e7SWyllys Ingersoll 	CK_MECHANISM  sign_mech;
66147e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT   sign_ctx;
66247e946e7SWyllys Ingersoll 	CK_RV		 rc;
66347e946e7SWyllys Ingersoll 
66447e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! sig_len) {
66547e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
66647e946e7SWyllys Ingersoll 	}
66747e946e7SWyllys Ingersoll 
66847e946e7SWyllys Ingersoll 	if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) {
66947e946e7SWyllys Ingersoll 		oid = ber_AlgMd5;
67047e946e7SWyllys Ingersoll 		oid_len = ber_AlgMd5Len;
67147e946e7SWyllys Ingersoll 		hash_len = MD5_DIGEST_LENGTH;
67247e946e7SWyllys Ingersoll 	} else {
67347e946e7SWyllys Ingersoll 		oid = ber_AlgSha1;
67447e946e7SWyllys Ingersoll 		oid_len = ber_AlgSha1Len;
67547e946e7SWyllys Ingersoll 		hash_len = SHA1_DIGEST_LENGTH;
67647e946e7SWyllys Ingersoll 	}
67747e946e7SWyllys Ingersoll 
67847e946e7SWyllys Ingersoll 	(void) memset(&sign_ctx, 0x0, sizeof (sign_ctx));
67947e946e7SWyllys Ingersoll 
68047e946e7SWyllys Ingersoll 	context = (RSA_DIGEST_CONTEXT *)ctx->context;
68147e946e7SWyllys Ingersoll 
68247e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_final(sess,
68347e946e7SWyllys Ingersoll 	    &context->hash_context, hash, &hash_len);
68447e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
68547e946e7SWyllys Ingersoll 		goto done;
68647e946e7SWyllys Ingersoll 	}
68747e946e7SWyllys Ingersoll 
68847e946e7SWyllys Ingersoll 	rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len,
68947e946e7SWyllys Ingersoll 	    hash, hash_len);
69047e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
69147e946e7SWyllys Ingersoll 		goto done;
69247e946e7SWyllys Ingersoll 	}
69347e946e7SWyllys Ingersoll 	tmp = (CK_BYTE *)buf1;
69447e946e7SWyllys Ingersoll 	(void) memcpy(tmp,  oid, oid_len);
69547e946e7SWyllys Ingersoll 	(void) memcpy(tmp + oid_len, octet_str, octet_str_len);
69647e946e7SWyllys Ingersoll 
69747e946e7SWyllys Ingersoll 	rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len,
69847e946e7SWyllys Ingersoll 	    tmp, (oid_len + octet_str_len));
69947e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
70047e946e7SWyllys Ingersoll 		goto done;
70147e946e7SWyllys Ingersoll 	}
70247e946e7SWyllys Ingersoll 	sign_mech.mechanism	= CKM_RSA_PKCS;
70347e946e7SWyllys Ingersoll 	sign_mech.ulParameterLen = 0;
70447e946e7SWyllys Ingersoll 	sign_mech.pParameter	= NULL;
70547e946e7SWyllys Ingersoll 
70647e946e7SWyllys Ingersoll 	rc = sign_mgr_init(sess, &sign_ctx, &sign_mech, FALSE, ctx->key);
70747e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
70847e946e7SWyllys Ingersoll 		goto done;
70947e946e7SWyllys Ingersoll 	}
71047e946e7SWyllys Ingersoll 	rc = sign_mgr_sign(sess, length_only, &sign_ctx, ber_data,
71147e946e7SWyllys Ingersoll 	    ber_data_len, signature, sig_len);
71247e946e7SWyllys Ingersoll 
71347e946e7SWyllys Ingersoll 	if (length_only == TRUE || rc == CKR_BUFFER_TOO_SMALL) {
71447e946e7SWyllys Ingersoll 		(void) sign_mgr_cleanup(&sign_ctx);
71547e946e7SWyllys Ingersoll 		return (rc);
71647e946e7SWyllys Ingersoll 	}
71747e946e7SWyllys Ingersoll 
71847e946e7SWyllys Ingersoll done:
71947e946e7SWyllys Ingersoll 	if (octet_str) free(octet_str);
72047e946e7SWyllys Ingersoll 	if (ber_data)  free(ber_data);
72147e946e7SWyllys Ingersoll 
72247e946e7SWyllys Ingersoll 	(void) digest_mgr_cleanup(&context->hash_context);
72347e946e7SWyllys Ingersoll 	(void) sign_mgr_cleanup(&sign_ctx);
72447e946e7SWyllys Ingersoll 	return (rc);
72547e946e7SWyllys Ingersoll }
72647e946e7SWyllys Ingersoll 
72747e946e7SWyllys Ingersoll CK_RV
rsa_hash_pkcs_verify_final(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * signature,CK_ULONG sig_len)72847e946e7SWyllys Ingersoll rsa_hash_pkcs_verify_final(SESSION		* sess,
72947e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT  * ctx,
73047e946e7SWyllys Ingersoll 	CK_BYTE		* signature,
73147e946e7SWyllys Ingersoll 	CK_ULONG		sig_len)
73247e946e7SWyllys Ingersoll {
73347e946e7SWyllys Ingersoll 	CK_BYTE	    * ber_data  = NULL;
73447e946e7SWyllys Ingersoll 	CK_BYTE	    * octet_str = NULL;
73547e946e7SWyllys Ingersoll 	CK_BYTE	    * oid	= NULL;
73647e946e7SWyllys Ingersoll 	CK_BYTE	    * tmp	= NULL;
73747e946e7SWyllys Ingersoll 
73847e946e7SWyllys Ingersoll 	CK_ULONG	buf1[16];
73947e946e7SWyllys Ingersoll 	CK_BYTE		hash[SHA1_DIGEST_LENGTH];
74047e946e7SWyllys Ingersoll 	RSA_DIGEST_CONTEXT  * context = NULL;
74147e946e7SWyllys Ingersoll 	CK_ULONG	ber_data_len, hash_len, octet_str_len, oid_len;
74247e946e7SWyllys Ingersoll 	CK_MECHANISM	  verify_mech;
74347e946e7SWyllys Ingersoll 	SIGN_VERIFY_CONTEXT   verify_ctx;
74447e946e7SWyllys Ingersoll 	CK_RV		 rc;
74547e946e7SWyllys Ingersoll 
74647e946e7SWyllys Ingersoll 	if (! sess || ! ctx || ! signature) {
74747e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
74847e946e7SWyllys Ingersoll 	}
74947e946e7SWyllys Ingersoll 	if (ctx->mech.mechanism == CKM_MD5_RSA_PKCS) {
75047e946e7SWyllys Ingersoll 		oid = ber_AlgMd5;
75147e946e7SWyllys Ingersoll 		oid_len = ber_AlgMd5Len;
75247e946e7SWyllys Ingersoll 		hash_len = MD5_DIGEST_LENGTH;
75347e946e7SWyllys Ingersoll 	} else {
75447e946e7SWyllys Ingersoll 		oid = ber_AlgSha1;
75547e946e7SWyllys Ingersoll 		oid_len = ber_AlgSha1Len;
75647e946e7SWyllys Ingersoll 		hash_len = SHA1_DIGEST_LENGTH;
75747e946e7SWyllys Ingersoll 	}
75847e946e7SWyllys Ingersoll 
75947e946e7SWyllys Ingersoll 	(void) memset(&verify_ctx, 0x0, sizeof (verify_ctx));
76047e946e7SWyllys Ingersoll 
76147e946e7SWyllys Ingersoll 	context = (RSA_DIGEST_CONTEXT *)ctx->context;
76247e946e7SWyllys Ingersoll 
76347e946e7SWyllys Ingersoll 	rc = digest_mgr_digest_final(sess, &context->hash_context,
76447e946e7SWyllys Ingersoll 	    hash, &hash_len);
76547e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
76647e946e7SWyllys Ingersoll 		goto done;
76747e946e7SWyllys Ingersoll 	}
76847e946e7SWyllys Ingersoll 	rc = ber_encode_OCTET_STRING(FALSE, &octet_str, &octet_str_len,
76947e946e7SWyllys Ingersoll 	    hash, hash_len);
77047e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
77147e946e7SWyllys Ingersoll 		goto done;
77247e946e7SWyllys Ingersoll 	}
77347e946e7SWyllys Ingersoll 	tmp = (CK_BYTE *)buf1;
77447e946e7SWyllys Ingersoll 	(void) memcpy(tmp, oid, oid_len);
77547e946e7SWyllys Ingersoll 	(void) memcpy(tmp + oid_len, octet_str, octet_str_len);
77647e946e7SWyllys Ingersoll 
77747e946e7SWyllys Ingersoll 	rc = ber_encode_SEQUENCE(FALSE, &ber_data, &ber_data_len,
77847e946e7SWyllys Ingersoll 	    tmp, (oid_len + octet_str_len));
77947e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
78047e946e7SWyllys Ingersoll 		goto done;
78147e946e7SWyllys Ingersoll 	}
78247e946e7SWyllys Ingersoll 	verify_mech.mechanism	= CKM_RSA_PKCS;
78347e946e7SWyllys Ingersoll 	verify_mech.ulParameterLen = 0;
78447e946e7SWyllys Ingersoll 	verify_mech.pParameter	= NULL;
78547e946e7SWyllys Ingersoll 
78647e946e7SWyllys Ingersoll 	rc = verify_mgr_init(sess, &verify_ctx, &verify_mech, FALSE, ctx->key);
78747e946e7SWyllys Ingersoll 	if (rc != CKR_OK) {
78847e946e7SWyllys Ingersoll 		goto done;
78947e946e7SWyllys Ingersoll 	}
79047e946e7SWyllys Ingersoll 	rc = verify_mgr_verify(sess, &verify_ctx, ber_data,
79147e946e7SWyllys Ingersoll 	    ber_data_len, signature, sig_len);
79247e946e7SWyllys Ingersoll done:
79347e946e7SWyllys Ingersoll 	if (octet_str) free(octet_str);
79447e946e7SWyllys Ingersoll 	if (ber_data)  free(ber_data);
79547e946e7SWyllys Ingersoll 	(void) digest_mgr_cleanup(&context->hash_context);
79647e946e7SWyllys Ingersoll 	(void) verify_mgr_cleanup(&verify_ctx);
79747e946e7SWyllys Ingersoll 	return (rc);
79847e946e7SWyllys Ingersoll }
799