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