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
22/* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
23/*
24 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#include "tpmtok_int.h"
29
30CK_RV
31verify_mgr_init(SESSION		* sess,
32	SIGN_VERIFY_CONTEXT * ctx,
33	CK_MECHANISM	* mech,
34	CK_BBOOL		recover_mode,
35	CK_OBJECT_HANDLE	key)
36{
37	OBJECT	  * key_obj = NULL;
38	CK_ATTRIBUTE    * attr    = NULL;
39	CK_KEY_TYPE	keytype;
40	CK_OBJECT_CLASS   class;
41	CK_BBOOL	  flag;
42	CK_RV		rc;
43
44
45	if (! sess || ! ctx) {
46		return (CKR_FUNCTION_FAILED);
47	}
48	if (ctx->active != FALSE) {
49		return (CKR_OPERATION_ACTIVE);
50	}
51
52	// key usage restrictions
53	//
54	rc = object_mgr_find_in_map1(sess->hContext, key, &key_obj);
55	if (rc != CKR_OK) {
56		return (CKR_KEY_HANDLE_INVALID);
57	}
58	// is key allowed to verify signatures?
59	//
60	rc = template_attribute_find(key_obj->template, CKA_VERIFY, &attr);
61	if (rc == FALSE) {
62		return (CKR_KEY_TYPE_INCONSISTENT);
63	} else {
64		flag = *(CK_BBOOL *)attr->pValue;
65		if (flag != TRUE) {
66			return (CKR_KEY_FUNCTION_NOT_PERMITTED);
67		}
68	}
69
70	switch (mech->mechanism) {
71		case CKM_RSA_PKCS:
72		{
73			rc = template_attribute_find(key_obj->template,
74			    CKA_KEY_TYPE, &attr);
75			if (rc == FALSE) {
76				return (CKR_KEY_TYPE_INCONSISTENT);
77			} else {
78				keytype = *(CK_KEY_TYPE *)attr->pValue;
79				if (keytype != CKK_RSA) {
80					return (CKR_KEY_TYPE_INCONSISTENT);
81				}
82			}
83
84			flag = template_attribute_find(key_obj->template,
85			    CKA_CLASS, &attr);
86			if (flag == FALSE) {
87				return (CKR_FUNCTION_FAILED);
88			}
89			else
90				class = *(CK_OBJECT_CLASS *)attr->pValue;
91
92			if (class != CKO_PUBLIC_KEY) {
93				return (CKR_FUNCTION_FAILED);
94			}
95			// PKCS #11 doesn't allow multi - part RSA operations
96			ctx->context_len = 0;
97			ctx->context	= NULL;
98		}
99		break;
100
101		case CKM_MD5_RSA_PKCS:
102		case CKM_SHA1_RSA_PKCS:
103		{
104			rc = template_attribute_find(key_obj->template,
105			    CKA_KEY_TYPE, &attr);
106			if (rc == FALSE) {
107				return (CKR_KEY_TYPE_INCONSISTENT);
108			} else {
109				keytype = *(CK_KEY_TYPE *)attr->pValue;
110				if (keytype != CKK_RSA) {
111					return (CKR_KEY_TYPE_INCONSISTENT);
112				}
113			}
114
115			flag = template_attribute_find(key_obj->template,
116			    CKA_CLASS, &attr);
117			if (flag == FALSE) {
118				return (CKR_FUNCTION_FAILED);
119			}
120			else
121				class = *(CK_OBJECT_CLASS *)attr->pValue;
122
123			if (class != CKO_PUBLIC_KEY) {
124				return (CKR_FUNCTION_FAILED);
125			}
126			ctx->context_len = sizeof (RSA_DIGEST_CONTEXT);
127			ctx->context = (CK_BYTE *)malloc(
128			    sizeof (RSA_DIGEST_CONTEXT));
129			if (! ctx->context) {
130				return (CKR_HOST_MEMORY);
131			}
132			(void) memset(ctx->context, 0x0,
133			    sizeof (RSA_DIGEST_CONTEXT));
134		}
135		break;
136
137		case CKM_MD5_HMAC:
138		case CKM_SHA_1_HMAC:
139		{
140			rc = template_attribute_find(key_obj->template,
141			    CKA_KEY_TYPE, &attr);
142			if (rc == FALSE) {
143				return (CKR_KEY_TYPE_INCONSISTENT);
144			} else {
145				keytype = *(CK_KEY_TYPE *)attr->pValue;
146				if (keytype != CKK_GENERIC_SECRET) {
147					return (CKR_KEY_TYPE_INCONSISTENT);
148				}
149			}
150
151			// PKCS #11 doesn't allow multi - part HMAC operations
152			ctx->context_len = 0;
153			ctx->context	= NULL;
154		}
155		break;
156
157		case CKM_MD5_HMAC_GENERAL:
158		case CKM_SHA_1_HMAC_GENERAL:
159		{
160			CK_MAC_GENERAL_PARAMS *param =
161			    (CK_MAC_GENERAL_PARAMS *)mech->pParameter;
162
163			if (mech->ulParameterLen !=
164			    sizeof (CK_MAC_GENERAL_PARAMS)) {
165				return (CKR_MECHANISM_PARAM_INVALID);
166			}
167			if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) &&
168			    (*param > 16)) {
169				return (CKR_MECHANISM_PARAM_INVALID);
170			}
171			if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) &&
172			    (*param > 20)) {
173				return (CKR_MECHANISM_PARAM_INVALID);
174			}
175			rc = template_attribute_find(key_obj->template,
176			    CKA_KEY_TYPE, &attr);
177			if (rc == FALSE) {
178				return (CKR_KEY_TYPE_INCONSISTENT);
179			} else {
180				keytype = *(CK_KEY_TYPE *)attr->pValue;
181				if (keytype != CKK_GENERIC_SECRET) {
182					return (CKR_KEY_TYPE_INCONSISTENT);
183				}
184			}
185
186			ctx->context_len = 0;
187			ctx->context	= NULL;
188		}
189		break;
190
191		default:
192		return (CKR_MECHANISM_INVALID);
193	}
194
195
196	ctx->key		 = key;
197	ctx->mech.ulParameterLen = mech->ulParameterLen;
198	ctx->mech.mechanism	= mech->mechanism;
199	ctx->mech.pParameter	= mech->pParameter;
200	ctx->multi		= FALSE;
201	ctx->active		= TRUE;
202	ctx->recover		= recover_mode;
203
204	return (CKR_OK);
205}
206
207CK_RV
208verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
209{
210	if (! ctx) {
211		return (CKR_FUNCTION_FAILED);
212	}
213	ctx->key		 = 0;
214	ctx->mech.ulParameterLen = 0;
215	ctx->mech.mechanism	= 0;
216	ctx->multi		= FALSE;
217	ctx->active		= FALSE;
218	ctx->recover		= FALSE;
219	ctx->context_len	 = 0;
220	ctx->mech.pParameter = NULL;
221
222	if (ctx->context) {
223		free(ctx->context);
224		ctx->context = NULL;
225	}
226
227	return (CKR_OK);
228}
229
230CK_RV
231verify_mgr_verify(SESSION		* sess,
232	SIGN_VERIFY_CONTEXT * ctx,
233	CK_BYTE		* in_data,
234	CK_ULONG		in_data_len,
235	CK_BYTE		* signature,
236	CK_ULONG		sig_len)
237{
238	if (! sess || ! ctx) {
239		return (CKR_FUNCTION_FAILED);
240	}
241	if (ctx->active == FALSE) {
242		return (CKR_OPERATION_NOT_INITIALIZED);
243	}
244	if (ctx->recover == TRUE) {
245		return (CKR_OPERATION_NOT_INITIALIZED);
246	}
247
248	if (! in_data || ! signature) {
249		return (CKR_FUNCTION_FAILED);
250	}
251	if (ctx->multi == TRUE) {
252		return (CKR_OPERATION_ACTIVE);
253	}
254
255	switch (ctx->mech.mechanism) {
256		case CKM_RSA_PKCS:
257		return (rsa_pkcs_verify(sess,	ctx,
258		    in_data,   in_data_len,
259		    signature, sig_len));
260		case CKM_MD5_RSA_PKCS:
261		case CKM_SHA1_RSA_PKCS:
262			return (rsa_hash_pkcs_verify(sess,	ctx,
263			    in_data,   in_data_len,
264			    signature, sig_len));
265
266		case CKM_MD5_HMAC:
267		case CKM_MD5_HMAC_GENERAL:
268			return (md5_hmac_verify(sess,	ctx,
269			    in_data,   in_data_len,
270			    signature, sig_len));
271		case CKM_SHA_1_HMAC:
272		case CKM_SHA_1_HMAC_GENERAL:
273			return (sha1_hmac_verify(sess,	ctx,
274			    in_data,   in_data_len,
275			    signature, sig_len));
276		default:
277		return (CKR_MECHANISM_INVALID);
278	}
279}
280
281CK_RV
282verify_mgr_verify_update(SESSION * sess,
283	SIGN_VERIFY_CONTEXT * ctx,
284	CK_BYTE		* in_data,
285	CK_ULONG		in_data_len)
286{
287	if (! sess || ! ctx || ! in_data) {
288		return (CKR_FUNCTION_FAILED);
289	}
290	if (ctx->active == FALSE) {
291		return (CKR_OPERATION_NOT_INITIALIZED);
292	}
293	if (ctx->recover == TRUE) {
294		return (CKR_OPERATION_NOT_INITIALIZED);
295	}
296	ctx->multi = TRUE;
297
298
299	switch (ctx->mech.mechanism) {
300		case CKM_MD5_RSA_PKCS:
301		case CKM_SHA1_RSA_PKCS:
302			return (rsa_hash_pkcs_verify_update(sess, ctx,
303			    in_data, in_data_len));
304		default:
305			return (CKR_MECHANISM_INVALID);
306	}
307}
308
309CK_RV
310verify_mgr_verify_final(SESSION		* sess,
311	SIGN_VERIFY_CONTEXT * ctx,
312	CK_BYTE		* signature,
313	CK_ULONG		sig_len)
314{
315	if (! sess || ! ctx) {
316		return (CKR_FUNCTION_FAILED);
317	}
318	if (ctx->active == FALSE) {
319		return (CKR_OPERATION_NOT_INITIALIZED);
320	}
321	if (ctx->recover == TRUE) {
322		return (CKR_OPERATION_NOT_INITIALIZED);
323	}
324	switch (ctx->mech.mechanism) {
325		case CKM_MD5_RSA_PKCS:
326		case CKM_SHA1_RSA_PKCS:
327			return (rsa_hash_pkcs_verify_final(sess, ctx,
328			    signature, sig_len));
329		default:
330			return (CKR_MECHANISM_INVALID);
331	}
332}
333
334CK_RV
335verify_mgr_verify_recover(SESSION		* sess,
336	CK_BBOOL		length_only,
337	SIGN_VERIFY_CONTEXT * ctx,
338	CK_BYTE		* signature,
339	CK_ULONG		sig_len,
340	CK_BYTE		* out_data,
341	CK_ULONG	    * out_len)
342{
343	if (! sess || ! ctx) {
344		return (CKR_FUNCTION_FAILED);
345	}
346	if (ctx->active == FALSE) {
347		return (CKR_OPERATION_NOT_INITIALIZED);
348	}
349	if (ctx->recover == FALSE) {
350		return (CKR_OPERATION_NOT_INITIALIZED);
351	}
352
353	if (! signature || ! out_len) {
354		return (CKR_FUNCTION_FAILED);
355	}
356	if (ctx->multi == TRUE) {
357		return (CKR_OPERATION_ACTIVE);
358	}
359
360	switch (ctx->mech.mechanism) {
361		case CKM_RSA_PKCS:
362		return (rsa_pkcs_verify_recover(sess,	length_only,
363		    ctx, signature, sig_len, out_data,  out_len));
364		default:
365			return (CKR_MECHANISM_INVALID);
366	}
367}
368