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