xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_tpm/common/verify_mgr.c (revision 46b592853d0f4f11781b6b0a7533f267c6aee132)
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_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 
207 CK_RV
208 verify_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 
230 CK_RV
231 verify_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 
281 CK_RV
282 verify_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 
309 CK_RV
310 verify_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 
334 CK_RV
335 verify_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