xref: /titanic_53/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelVerify.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <sys/crypto/ioctl.h>
32 #include <security/cryptoki.h>
33 #include "kernelGlobal.h"
34 #include "kernelObject.h"
35 #include "kernelSession.h"
36 
37 CK_RV
38 C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
39     CK_OBJECT_HANDLE hKey)
40 {
41 
42 	CK_RV rv;
43 	kernel_session_t *session_p;
44 	kernel_object_t	*key_p;
45 	boolean_t ses_lock_held = B_FALSE;
46 	crypto_verify_init_t verify_init;
47 	crypto_mech_type_t k_mech_type;
48 	int r;
49 
50 	if (!kernel_initialized)
51 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
52 
53 	if (pMechanism == NULL) {
54 		return (CKR_ARGUMENTS_BAD);
55 	}
56 
57 	/* Get the kernel's internal mechanism number. */
58 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
59 	if (rv != CKR_OK)
60 		return (rv);
61 
62 	/* Obtain the session pointer. */
63 	rv = handle2session(hSession, &session_p);
64 	if (rv != CKR_OK)
65 		return (rv);
66 
67 	/* Obtain the object pointer. */
68 	HANDLE2OBJECT(hKey, key_p, rv);
69 	if (rv != CKR_OK) {
70 		goto clean_exit;
71 	}
72 
73 	/* Check to see if key object supports verification. */
74 	if (key_p->is_lib_obj && !(key_p->bool_attr_mask & VERIFY_BOOL_ON)) {
75 		rv = CKR_KEY_TYPE_INCONSISTENT;
76 		goto clean_exit;
77 	}
78 
79 	(void) pthread_mutex_lock(&session_p->session_mutex);
80 	ses_lock_held = B_TRUE;
81 
82 	/*
83 	 * This active flag will remain ON until application calls either
84 	 * C_Verify or C_VerifyFinal to verify a signature on data.
85 	 */
86 	session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
87 
88 	if (!key_p->is_lib_obj) {
89 		verify_init.vi_key.ck_format = CRYPTO_KEY_REFERENCE;
90 		verify_init.vi_key.ck_obj_id = key_p->k_handle;
91 	} else {
92 		if (key_p->class == CKO_SECRET_KEY) {
93 			verify_init.vi_key.ck_format = CRYPTO_KEY_RAW;
94 			verify_init.vi_key.ck_data =
95 			    get_symmetric_key_value(key_p);
96 			if (verify_init.vi_key.ck_data == NULL) {
97 				rv = CKR_HOST_MEMORY;
98 				goto clean_exit;
99 			}
100 			verify_init.vi_key.ck_length =
101 			    OBJ_SEC(key_p)->sk_value_len << 3;
102 
103 		} else if (key_p->key_type == CKK_RSA) {
104 			if (get_rsa_public_key(key_p, &verify_init.vi_key) !=
105 			    CKR_OK) {
106 				rv = CKR_HOST_MEMORY;
107 				goto clean_exit;
108 			}
109 		} else if (key_p->key_type == CKK_DSA) {
110 			if (get_dsa_public_key(key_p, &verify_init.vi_key) !=
111 			    CKR_OK) {
112 				rv = CKR_HOST_MEMORY;
113 				goto clean_exit;
114 			}
115 		} else {
116 			rv = CKR_KEY_TYPE_INCONSISTENT;
117 			goto clean_exit;
118 		}
119 	}
120 
121 	verify_init.vi_session = session_p->k_session;
122 	(void) pthread_mutex_unlock(&session_p->session_mutex);
123 	ses_lock_held = B_FALSE;
124 	verify_init.vi_mech.cm_type = k_mech_type;
125 	verify_init.vi_mech.cm_param = pMechanism->pParameter;
126 	verify_init.vi_mech.cm_param_len = pMechanism->ulParameterLen;
127 
128 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_INIT, &verify_init)) < 0) {
129 		if (errno != EINTR)
130 			break;
131 	}
132 	if (r < 0) {
133 		rv = CKR_FUNCTION_FAILED;
134 	} else {
135 		rv = crypto2pkcs11_error_number(verify_init.vi_return_value);
136 	}
137 
138 	/* free the memory allocated for sign_init.si_key */
139 	if (key_p->is_lib_obj) {
140 		if (key_p->class == CKO_SECRET_KEY) {
141 			free(verify_init.vi_key.ck_data);
142 		} else if (key_p->key_type == CKK_RSA) {
143 			free_key_attributes(&verify_init.vi_key);
144 		}
145 	}
146 
147 	if (rv != CKR_OK) {
148 		(void) pthread_mutex_lock(&session_p->session_mutex);
149 		session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
150 		ses_lock_held = B_TRUE;
151 	}
152 
153 clean_exit:
154 	REFRELE(session_p, ses_lock_held);
155 	return (rv);
156 }
157 
158 
159 CK_RV
160 C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
161     CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
162 {
163 
164 	CK_RV rv;
165 	kernel_session_t *session_p;
166 	boolean_t ses_lock_held = B_FALSE;
167 	crypto_verify_t verify;
168 	int r;
169 
170 	if (!kernel_initialized)
171 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
172 
173 	/* Obatin the session pointer */
174 	rv = handle2session(hSession, &session_p);
175 	if (rv != CKR_OK)
176 		return (rv);
177 
178 	(void) pthread_mutex_lock(&session_p->session_mutex);
179 	ses_lock_held = B_TRUE;
180 
181 	/* Application must call C_VerifyInit before calling C_Verify. */
182 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
183 		REFRELE(session_p, ses_lock_held);
184 		return (CKR_OPERATION_NOT_INITIALIZED);
185 	}
186 
187 	/*
188 	 * C_Verify must be called without intervening C_VerifyUpdate
189 	 * calls.
190 	 */
191 	if (session_p->verify.flags & CRYPTO_OPERATION_UPDATE) {
192 		/*
193 		 * C_Verify can not be used to terminate a multi-part
194 		 * operation, so we'll leave the active verify operation
195 		 * flag on and let the application continue with the
196 		 * verify update operation.
197 		 */
198 		REFRELE(session_p, ses_lock_held);
199 		return (CKR_FUNCTION_FAILED);
200 	}
201 
202 	verify.cv_session = session_p->k_session;
203 	(void) pthread_mutex_unlock(&session_p->session_mutex);
204 	ses_lock_held = B_FALSE;
205 	verify.cv_datalen = ulDataLen;
206 	verify.cv_databuf = (char *)pData;
207 	verify.cv_signlen = ulSignatureLen;
208 	verify.cv_signbuf = (char *)pSignature;
209 
210 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY, &verify)) < 0) {
211 		if (errno != EINTR)
212 			break;
213 	}
214 	if (r < 0) {
215 		rv = CKR_FUNCTION_FAILED;
216 	} else {
217 		rv = crypto2pkcs11_error_number(verify.cv_return_value);
218 	}
219 
220 clean_exit:
221 	/*
222 	 * Always terminate the active verify operation.
223 	 * Application needs to call C_VerifyInit again for next
224 	 * verify operation.
225 	 */
226 	(void) pthread_mutex_lock(&session_p->session_mutex);
227 	session_p->verify.flags = 0;
228 	ses_lock_held = B_TRUE;
229 	REFRELE(session_p, ses_lock_held);
230 
231 	return (rv);
232 }
233 
234 
235 CK_RV
236 C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
237     CK_ULONG ulPartLen)
238 {
239 
240 	CK_RV rv;
241 	kernel_session_t *session_p;
242 	boolean_t ses_lock_held = B_FALSE;
243 	crypto_verify_update_t verify_update;
244 	int r;
245 
246 	if (!kernel_initialized)
247 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
248 
249 	/* Obtain the session pointer */
250 	rv = handle2session(hSession, &session_p);
251 	if (rv != CKR_OK)
252 		return (rv);
253 
254 	if (pPart == NULL) {
255 		rv = CKR_ARGUMENTS_BAD;
256 		goto clean_exit;
257 	}
258 
259 	(void) pthread_mutex_lock(&session_p->session_mutex);
260 	ses_lock_held = B_TRUE;
261 
262 	/*
263 	 * Application must call C_VerifyInit before calling
264 	 * C_VerifyUpdate.
265 	 */
266 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
267 		REFRELE(session_p, ses_lock_held);
268 		return (CKR_OPERATION_NOT_INITIALIZED);
269 	}
270 
271 	session_p->verify.flags |= CRYPTO_OPERATION_UPDATE;
272 
273 	verify_update.vu_session = session_p->k_session;
274 	(void) pthread_mutex_unlock(&session_p->session_mutex);
275 	ses_lock_held = B_FALSE;
276 
277 	verify_update.vu_datalen = ulPartLen;
278 	verify_update.vu_databuf = (char *)pPart;
279 
280 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_UPDATE,
281 	    &verify_update)) < 0) {
282 		if (errno != EINTR)
283 			break;
284 	}
285 	if (r < 0) {
286 		rv = CKR_FUNCTION_FAILED;
287 	} else {
288 		rv = crypto2pkcs11_error_number(verify_update.vu_return_value);
289 	}
290 
291 	if (rv == CKR_OK) {
292 		REFRELE(session_p, ses_lock_held);
293 		return (rv);
294 	}
295 
296 clean_exit:
297 	/*
298 	 * After an error occurred, terminate the current verify
299 	 * operation by resetting the active and update flags.
300 	 */
301 	(void) pthread_mutex_lock(&session_p->session_mutex);
302 	session_p->verify.flags = 0;
303 	ses_lock_held = B_TRUE;
304 	REFRELE(session_p, ses_lock_held);
305 
306 	return (rv);
307 }
308 
309 
310 CK_RV
311 C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
312     CK_ULONG ulSignatureLen)
313 {
314 
315 	CK_RV rv;
316 	kernel_session_t *session_p;
317 	boolean_t ses_lock_held = B_FALSE;
318 	crypto_verify_final_t verify_final;
319 	int r;
320 
321 	if (!kernel_initialized)
322 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
323 
324 	/* Obtain the session pointer */
325 	rv = handle2session(hSession, &session_p);
326 	if (rv != CKR_OK)
327 		return (rv);
328 
329 	(void) pthread_mutex_lock(&session_p->session_mutex);
330 	ses_lock_held = B_TRUE;
331 
332 	/*
333 	 * Application must call C_VerifyInit before calling
334 	 * C_VerifyFinal.
335 	 */
336 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
337 		REFRELE(session_p, ses_lock_held);
338 		return (CKR_OPERATION_NOT_INITIALIZED);
339 	}
340 
341 	verify_final.vf_session = session_p->k_session;
342 	(void) pthread_mutex_unlock(&session_p->session_mutex);
343 	ses_lock_held = B_FALSE;
344 
345 	verify_final.vf_signlen = ulSignatureLen;
346 	verify_final.vf_signbuf = (char *)pSignature;
347 
348 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_FINAL, &verify_final)) < 0) {
349 		if (errno != EINTR)
350 			break;
351 	}
352 	if (r < 0) {
353 		rv = CKR_FUNCTION_FAILED;
354 	} else {
355 		rv = crypto2pkcs11_error_number(verify_final.vf_return_value);
356 	}
357 
358 clean_exit:
359 	/* Always terminate the active verify operation */
360 	(void) pthread_mutex_lock(&session_p->session_mutex);
361 	session_p->verify.flags = 0;
362 	ses_lock_held = B_TRUE;
363 	REFRELE(session_p, ses_lock_held);
364 
365 	return (rv);
366 }
367 
368 
369 CK_RV
370 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
371     CK_OBJECT_HANDLE hKey)
372 {
373 
374 	CK_RV rv;
375 	kernel_session_t *session_p;
376 	kernel_object_t	*key_p;
377 	boolean_t ses_lock_held = B_FALSE;
378 	crypto_verify_recover_init_t vr_init;
379 	crypto_mech_type_t k_mech_type;
380 	int r;
381 
382 	if (!kernel_initialized)
383 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
384 
385 	if (pMechanism == NULL) {
386 		return (CKR_ARGUMENTS_BAD);
387 	}
388 
389 	/* Get the kernel's internal mechanism number. */
390 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
391 	if (rv != CKR_OK)
392 		return (rv);
393 
394 	/* Obtain the session pointer. */
395 	rv = handle2session(hSession, &session_p);
396 	if (rv != CKR_OK)
397 		return (rv);
398 
399 	/* Obtain the object pointer. */
400 	HANDLE2OBJECT(hKey, key_p, rv);
401 	if (rv != CKR_OK) {
402 		goto clean_exit;
403 	}
404 
405 	/*
406 	 * Check to see if key object is a RSA key and if it supports
407 	 * verify_recover.
408 	 */
409 	if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) &&
410 	    (key_p->bool_attr_mask & VERIFY_RECOVER_BOOL_ON))) {
411 		rv = CKR_KEY_TYPE_INCONSISTENT;
412 		goto clean_exit;
413 	}
414 
415 	(void) pthread_mutex_lock(&session_p->session_mutex);
416 	ses_lock_held = B_TRUE;
417 
418 	/*
419 	 * This active flag will remain ON until application calls
420 	 * C_VerifyRecover to verify a signature on data.
421 	 */
422 	session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
423 
424 	/* Set up the key data */
425 	if (!key_p->is_lib_obj) {
426 		vr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE;
427 		vr_init.ri_key.ck_obj_id = key_p->k_handle;
428 	} else {
429 		if (key_p->key_type == CKK_RSA) {
430 			if (get_rsa_public_key(key_p, &vr_init.ri_key) !=
431 			    CKR_OK) {
432 				rv = CKR_HOST_MEMORY;
433 				goto clean_exit;
434 			}
435 		} else {
436 			rv = CKR_KEY_TYPE_INCONSISTENT;
437 			goto clean_exit;
438 		}
439 	}
440 
441 	vr_init.ri_session = session_p->k_session;
442 	(void) pthread_mutex_unlock(&session_p->session_mutex);
443 	ses_lock_held = B_FALSE;
444 	vr_init.ri_mech.cm_type = k_mech_type;
445 	vr_init.ri_mech.cm_param = pMechanism->pParameter;
446 	vr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen;
447 
448 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER_INIT,
449 	    &vr_init)) < 0) {
450 		if (errno != EINTR)
451 			break;
452 	}
453 	if (r < 0) {
454 		rv = CKR_FUNCTION_FAILED;
455 	} else {
456 		rv = crypto2pkcs11_error_number(vr_init.ri_return_value);
457 	}
458 
459 	/* free the memory allocated for vr_init.ri_key */
460 	if (key_p->is_lib_obj) {
461 		free_key_attributes(&vr_init.ri_key);
462 	}
463 
464 	if (rv != CKR_OK) {
465 		(void) pthread_mutex_lock(&session_p->session_mutex);
466 		session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
467 		ses_lock_held = B_TRUE;
468 	}
469 
470 clean_exit:
471 	REFRELE(session_p, ses_lock_held);
472 	return (rv);
473 }
474 
475 
476 CK_RV
477 C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
478     CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
479 {
480 
481 	CK_RV rv;
482 	kernel_session_t *session_p;
483 	boolean_t ses_lock_held = B_FALSE;
484 	crypto_verify_recover_t verify_recover;
485 	int r;
486 
487 	if (!kernel_initialized)
488 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
489 
490 	/* Obtain the session pointer */
491 	rv = handle2session(hSession, &session_p);
492 	if (rv != CKR_OK)
493 		return (rv);
494 
495 	if (pSignature == NULL || pulDataLen == NULL) {
496 		rv = CKR_ARGUMENTS_BAD;
497 		goto clean_exit;
498 	}
499 
500 	(void) pthread_mutex_lock(&session_p->session_mutex);
501 	ses_lock_held = B_TRUE;
502 
503 	/*
504 	 * Application must call C_VerifyRecoverInit before calling
505 	 * C_Verify.
506 	 */
507 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
508 		REFRELE(session_p, ses_lock_held);
509 		return (CKR_OPERATION_NOT_INITIALIZED);
510 	}
511 
512 	verify_recover.vr_session = session_p->k_session;
513 	(void) pthread_mutex_unlock(&session_p->session_mutex);
514 	ses_lock_held = B_FALSE;
515 	verify_recover.vr_signlen = ulSignatureLen;
516 	verify_recover.vr_signbuf = (char *)pSignature;
517 	verify_recover.vr_datalen = *pulDataLen;
518 	verify_recover.vr_databuf = (char *)pData;
519 
520 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER,
521 	    &verify_recover)) < 0) {
522 		if (errno != EINTR)
523 			break;
524 	}
525 	if (r < 0) {
526 		rv = CKR_FUNCTION_FAILED;
527 	} else {
528 		rv = crypto2pkcs11_error_number(
529 		    verify_recover.vr_return_value);
530 	}
531 
532 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
533 		*pulDataLen = verify_recover.vr_datalen;
534 
535 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
536 	    (rv == CKR_OK && pData == NULL)) {
537 		/*
538 		 * We will not terminate the active verify operation flag,
539 		 * when the application-supplied buffer is too small, or
540 		 * the application asks for the length of buffer to hold
541 		 * the recovered data.
542 		 */
543 		REFRELE(session_p, ses_lock_held);
544 		return (rv);
545 	}
546 
547 clean_exit:
548 	/*
549 	 * Always terminate the active verify operation.
550 	 * Application needs to call C_VerifyInit again for next
551 	 * verify operation.
552 	 */
553 	(void) pthread_mutex_lock(&session_p->session_mutex);
554 	session_p->verify.flags = 0;
555 	ses_lock_held = B_TRUE;
556 	REFRELE(session_p, ses_lock_held);
557 
558 	return (rv);
559 }
560