xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDecryptUtil.c (revision 142d813a06c6f9a6142e2c276b62129a17a31a65)
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 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2018, Joyent, Inc.
25  * Copyright 2017 Jason King.
26  */
27 
28 #include <pthread.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <sys/types.h>
33 #include <security/cryptoki.h>
34 #include <modes/modes.h>
35 #include <arcfour.h>
36 #include "softSession.h"
37 #include "softObject.h"
38 #include "softOps.h"
39 #include "softCrypt.h"
40 #include "softRSA.h"
41 
42 /*
43  * Remove padding bytes.
44  */
45 CK_RV
46 soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
47     CK_ULONG *pulDataLen)
48 {
49 	CK_RV	rv;
50 
51 #ifdef	__sparcv9
52 	if ((rv = pkcs7_decode(pData, (&padded_len))) != CKR_OK)
53 #else	/* !__sparcv9 */
54 	if ((rv = pkcs7_decode(pData, (size_t *)(&padded_len))) != CKR_OK)
55 #endif	/* __sparcv9 */
56 		return (rv);
57 
58 	*pulDataLen = padded_len;
59 	return (CKR_OK);
60 }
61 
62 
63 /*
64  * soft_decrypt_init()
65  *
66  * Arguments:
67  *	session_p:	pointer to soft_session_t struct
68  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
69  *	key_p:		pointer to key soft_object_t struct
70  *
71  * Description:
72  *	called by C_DecryptInit(). This function calls the corresponding
73  *	decrypt init routine based on the mechanism.
74  *
75  * Returns:
76  *	CKR_OK: success
77  *	CKR_HOST_MEMORY: run out of system memory
78  *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
79  *	CKR_MECHANISM_INVALID: invalid mechanism type
80  *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
81  *				   with the specified mechanism
82  */
83 CK_RV
84 soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
85     soft_object_t *key_p)
86 {
87 
88 	CK_RV rv;
89 
90 	switch (pMechanism->mechanism) {
91 
92 	case CKM_DES_ECB:
93 
94 		if (key_p->key_type != CKK_DES) {
95 			return (CKR_KEY_TYPE_INCONSISTENT);
96 		}
97 
98 		goto ecb_common;
99 
100 	case CKM_DES3_ECB:
101 
102 		if ((key_p->key_type != CKK_DES2) &&
103 		    (key_p->key_type != CKK_DES3)) {
104 			return (CKR_KEY_TYPE_INCONSISTENT);
105 		}
106 
107 ecb_common:
108 
109 		return (soft_des_crypt_init_common(session_p, pMechanism,
110 		    key_p, B_FALSE));
111 
112 	case CKM_DES_CBC:
113 	case CKM_DES_CBC_PAD:
114 
115 		if (key_p->key_type != CKK_DES) {
116 			return (CKR_KEY_TYPE_INCONSISTENT);
117 		}
118 
119 		goto cbc_common;
120 
121 	case CKM_DES3_CBC:
122 	case CKM_DES3_CBC_PAD:
123 	{
124 		soft_des_ctx_t *soft_des_ctx;
125 
126 		if ((key_p->key_type != CKK_DES2) &&
127 		    (key_p->key_type != CKK_DES3)) {
128 			return (CKR_KEY_TYPE_INCONSISTENT);
129 		}
130 
131 cbc_common:
132 		if ((pMechanism->pParameter == NULL) ||
133 		    (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
134 			return (CKR_MECHANISM_PARAM_INVALID);
135 		}
136 
137 		rv = soft_des_crypt_init_common(session_p, pMechanism,
138 		    key_p, B_FALSE);
139 
140 		if (rv != CKR_OK)
141 			return (rv);
142 
143 		(void) pthread_mutex_lock(&session_p->session_mutex);
144 
145 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
146 		/* Save Initialization Vector (IV) in the context. */
147 		(void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
148 		    DES_BLOCK_LEN);
149 
150 		/* Allocate a context for DES cipher-block chaining. */
151 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
152 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
153 		    soft_des_ctx->ivec, key_p->key_type);
154 
155 		if (soft_des_ctx->des_cbc == NULL) {
156 			freezero(soft_des_ctx->key_sched,
157 			    soft_des_ctx->keysched_len);
158 			freezero(session_p->decrypt.context,
159 			    sizeof (soft_des_ctx_t));
160 			session_p->decrypt.context = NULL;
161 			(void) pthread_mutex_unlock(&session_p->session_mutex);
162 			return (CKR_HOST_MEMORY);
163 		}
164 
165 		(void) pthread_mutex_unlock(&session_p->session_mutex);
166 
167 		return (rv);
168 	}
169 	case CKM_AES_ECB:
170 	case CKM_AES_CBC:
171 	case CKM_AES_CBC_PAD:
172 	case CKM_AES_CTR:
173 	case CKM_AES_GCM:
174 	case CKM_AES_CCM:
175 		return (soft_aes_crypt_init_common(session_p, pMechanism,
176 		    key_p, B_FALSE));
177 
178 	case CKM_BLOWFISH_CBC:
179 	{
180 		soft_blowfish_ctx_t *soft_blowfish_ctx;
181 
182 		if (key_p->key_type != CKK_BLOWFISH)
183 			return (CKR_KEY_TYPE_INCONSISTENT);
184 
185 		if ((pMechanism->pParameter == NULL) ||
186 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
187 			return (CKR_MECHANISM_PARAM_INVALID);
188 
189 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
190 		    key_p, B_FALSE);
191 
192 		if (rv != CKR_OK)
193 			return (rv);
194 
195 		(void) pthread_mutex_lock(&session_p->session_mutex);
196 
197 		soft_blowfish_ctx =
198 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
199 
200 		/* Save Initialization Vector in the context. */
201 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
202 		    BLOWFISH_BLOCK_LEN);
203 
204 		/* Allocate a context for CBC */
205 		soft_blowfish_ctx->blowfish_cbc =
206 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
207 		    soft_blowfish_ctx->keysched_len,
208 		    soft_blowfish_ctx->ivec);
209 
210 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
211 			freezero(soft_blowfish_ctx->key_sched,
212 			    soft_blowfish_ctx->keysched_len);
213 			freezero(session_p->decrypt.context,
214 			    sizeof (soft_blowfish_ctx_t));
215 			session_p->decrypt.context = NULL;
216 			(void) pthread_mutex_unlock(&session_p->session_mutex);
217 			return (CKR_HOST_MEMORY);
218 		}
219 
220 		(void) pthread_mutex_unlock(&session_p->session_mutex);
221 		return (rv);
222 	}
223 
224 	case CKM_RC4:
225 
226 		if (key_p->key_type != CKK_RC4) {
227 			return (CKR_KEY_TYPE_INCONSISTENT);
228 		}
229 
230 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
231 		    B_FALSE));
232 
233 	case CKM_RSA_X_509:
234 	case CKM_RSA_PKCS:
235 
236 		if (key_p->key_type != CKK_RSA) {
237 			return (CKR_KEY_TYPE_INCONSISTENT);
238 		}
239 
240 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
241 		    key_p, B_FALSE));
242 
243 	default:
244 		return (CKR_MECHANISM_INVALID);
245 	}
246 }
247 
248 
249 /*
250  * soft_decrypt_common()
251  *
252  * Arguments:
253  *      session_p:	pointer to soft_session_t struct
254  *	pEncrypted:	pointer to the encrypted data as input
255  *	ulEncryptedLen:	length of the input data
256  *	pData:		pointer to the output data contains plaintext
257  *	pulDataLen:	pointer to the length of the output data
258  *	Update:		boolean flag indicates caller is soft_decrypt
259  *			or soft_decrypt_update
260  *
261  * Description:
262  *      This function calls the corresponding decrypt routine based
263  *	on the mechanism.
264  *
265  * Returns:
266  *	see soft_decrypt_common().
267  */
268 CK_RV
269 soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
270     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
271     CK_ULONG_PTR pulDataLen, boolean_t Update)
272 {
273 
274 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
275 
276 	switch (mechanism) {
277 
278 	case CKM_DES_ECB:
279 	case CKM_DES_CBC:
280 	case CKM_DES3_ECB:
281 	case CKM_DES3_CBC:
282 
283 		if (ulEncryptedLen == 0) {
284 			*pulDataLen = 0;
285 			return (CKR_OK);
286 		}
287 		/* FALLTHROUGH */
288 
289 	case CKM_DES_CBC_PAD:
290 	case CKM_DES3_CBC_PAD:
291 
292 		return (soft_des_decrypt_common(session_p, pEncrypted,
293 		    ulEncryptedLen, pData, pulDataLen, Update));
294 
295 	case CKM_AES_ECB:
296 	case CKM_AES_CBC:
297 	case CKM_AES_CTR:
298 	case CKM_AES_CCM:
299 	case CKM_AES_GCM:
300 	case CKM_AES_CBC_PAD:
301 		if (Update) {
302 			return (soft_aes_decrypt_update(session_p, pEncrypted,
303 			    ulEncryptedLen, pData, pulDataLen));
304 		} else {
305 			return (soft_aes_decrypt(session_p, pEncrypted,
306 			    ulEncryptedLen, pData, pulDataLen));
307 		}
308 
309 	case CKM_BLOWFISH_CBC:
310 
311 		if (ulEncryptedLen == 0) {
312 			*pulDataLen = 0;
313 			return (CKR_OK);
314 		}
315 
316 		return (soft_blowfish_decrypt_common(session_p, pEncrypted,
317 		    ulEncryptedLen, pData, pulDataLen, Update));
318 
319 	case CKM_RC4:
320 
321 		if (ulEncryptedLen == 0) {
322 			*pulDataLen = 0;
323 			return (CKR_OK);
324 		}
325 
326 
327 		return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
328 		    ulEncryptedLen, pData, pulDataLen));
329 
330 	case CKM_RSA_X_509:
331 	case CKM_RSA_PKCS:
332 
333 		return (soft_rsa_decrypt_common(session_p, pEncrypted,
334 		    ulEncryptedLen, pData, pulDataLen, mechanism));
335 
336 	default:
337 		return (CKR_MECHANISM_INVALID);
338 
339 	}
340 }
341 
342 
343 /*
344  * soft_decrypt()
345  *
346  * Arguments:
347  *      session_p:	pointer to soft_session_t struct
348  *	pEncryptedData: pointer to the encrypted data as input
349  *	ulEncryptedDataLen: length of the input data
350  *	pData:		pointer to the output data contains plaintext
351  *	pulDataLen:	pointer to the length of the output data
352  *
353  * Description:
354  *      called by C_Decrypt(). This function calls the soft_decrypt_common
355  *	routine.
356  *
357  * Returns:
358  *	see soft_decrypt_common().
359  */
360 CK_RV
361 soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
362     CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
363     CK_ULONG_PTR pulDataLen)
364 {
365 
366 	return (soft_decrypt_common(session_p, pEncryptedData,
367 	    ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
368 }
369 
370 
371 /*
372  * soft_decrypt_update()
373  *
374  * Arguments:
375  *      session_p:	pointer to soft_session_t struct
376  *	pEncryptedPart: pointer to the encrypted data as input
377  *	ulEncryptedPartLen: length of the input data
378  *	pPart:          pointer to the output data contains plaintext
379  *	pulPartLen:     pointer to the length of the output data
380  *
381  * Description:
382  *      called by C_DecryptUpdate(). This function calls the
383  *	soft_decrypt_common routine (with update flag on).
384  *
385  * Returns:
386  *	see soft_decrypt_common().
387  */
388 CK_RV
389 soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
390     CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
391 {
392 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
393 
394 	switch (mechanism) {
395 
396 	case CKM_DES_ECB:
397 	case CKM_DES_CBC:
398 	case CKM_DES_CBC_PAD:
399 	case CKM_DES3_ECB:
400 	case CKM_DES3_CBC:
401 	case CKM_DES3_CBC_PAD:
402 	case CKM_AES_ECB:
403 	case CKM_AES_CBC:
404 	case CKM_AES_CBC_PAD:
405 	case CKM_AES_CTR:
406 	case CKM_AES_GCM:
407 	case CKM_AES_CCM:
408 	case CKM_BLOWFISH_CBC:
409 	case CKM_RC4:
410 
411 		return (soft_decrypt_common(session_p, pEncryptedPart,
412 		    ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
413 
414 	default:
415 		/* PKCS11: The mechanism only supports single-part operation. */
416 		return (CKR_MECHANISM_INVALID);
417 	}
418 
419 }
420 
421 
422 /*
423  * soft_decrypt_final()
424  *
425  * Arguments:
426  *      session_p:	pointer to soft_session_t struct
427  *      pLastPart:	pointer to the last recovered data part
428  *      pulLastPartLen:	pointer to the length of the last recovered data part
429  *
430  * Description:
431  *      called by C_DecryptFinal().
432  *
433  * Returns:
434  *	CKR_OK: success
435  *	CKR_FUNCTION_FAILED: decrypt final function failed
436  *	CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
437  */
438 CK_RV
439 soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
440     CK_ULONG_PTR pulLastPartLen)
441 {
442 
443 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
444 	CK_ULONG out_len;
445 	CK_RV rv = CKR_OK;
446 	int rc;
447 
448 	(void) pthread_mutex_lock(&session_p->session_mutex);
449 
450 	if (session_p->decrypt.context == NULL) {
451 		rv = CKR_OPERATION_NOT_INITIALIZED;
452 		*pulLastPartLen = 0;
453 		goto clean2;
454 	}
455 	switch (mechanism) {
456 
457 	case CKM_DES_CBC_PAD:
458 	case CKM_DES3_CBC_PAD:
459 	{
460 
461 		soft_des_ctx_t *soft_des_ctx;
462 
463 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
464 
465 		/*
466 		 * We should have only one block of data left in the
467 		 * remaining buffer.
468 		 */
469 		if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
470 			*pulLastPartLen = 0;
471 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
472 			/* Cleanup memory space. */
473 			free(soft_des_ctx->des_cbc);
474 			freezero(soft_des_ctx->key_sched,
475 			    soft_des_ctx->keysched_len);
476 
477 			goto clean1;
478 		}
479 
480 		out_len = DES_BLOCK_LEN;
481 
482 		/*
483 		 * If application asks for the length of the output buffer
484 		 * to hold the plaintext?
485 		 */
486 		if (pLastPart == NULL) {
487 			*pulLastPartLen = out_len;
488 			rv = CKR_OK;
489 			goto clean2;
490 		} else {
491 			crypto_data_t out;
492 
493 			/* Copy remaining data to the output buffer. */
494 			(void) memcpy(pLastPart, soft_des_ctx->data,
495 			    DES_BLOCK_LEN);
496 
497 			out.cd_format = CRYPTO_DATA_RAW;
498 			out.cd_offset = 0;
499 			out.cd_length = DES_BLOCK_LEN;
500 			out.cd_raw.iov_base = (char *)pLastPart;
501 			out.cd_raw.iov_len = DES_BLOCK_LEN;
502 
503 			/* Decrypt final block of data. */
504 			rc = des_decrypt_contiguous_blocks(
505 			    (des_ctx_t *)soft_des_ctx->des_cbc,
506 			    (char *)pLastPart, DES_BLOCK_LEN, &out);
507 
508 			if (rc == 0) {
509 				/*
510 				 * Remove padding bytes after decryption of
511 				 * ciphertext block to produce the original
512 				 * plaintext.
513 				 */
514 				rv = soft_remove_pkcs7_padding(pLastPart,
515 				    DES_BLOCK_LEN, &out_len);
516 				if (rv != CKR_OK)
517 					*pulLastPartLen = 0;
518 				else
519 					*pulLastPartLen = out_len;
520 			} else {
521 				*pulLastPartLen = 0;
522 				rv = CKR_FUNCTION_FAILED;
523 			}
524 
525 			/* Cleanup memory space. */
526 			free(soft_des_ctx->des_cbc);
527 			freezero(soft_des_ctx->key_sched,
528 			    soft_des_ctx->keysched_len);
529 
530 		}
531 
532 		break;
533 	}
534 
535 	case CKM_DES_CBC:
536 	case CKM_DES_ECB:
537 	case CKM_DES3_CBC:
538 	case CKM_DES3_ECB:
539 	{
540 
541 		soft_des_ctx_t *soft_des_ctx;
542 
543 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
544 		/*
545 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
546 		 * so when the final is called, the remaining buffer
547 		 * should not contain any more data.
548 		 */
549 		*pulLastPartLen = 0;
550 		if (soft_des_ctx->remain_len != 0) {
551 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
552 		} else {
553 			if (pLastPart == NULL)
554 				goto clean2;
555 		}
556 
557 		/* Cleanup memory space. */
558 		free(soft_des_ctx->des_cbc);
559 		freezero(soft_des_ctx->key_sched,
560 		    soft_des_ctx->keysched_len);
561 
562 		break;
563 	}
564 
565 	case CKM_AES_CBC_PAD:
566 	case CKM_AES_CBC:
567 	case CKM_AES_ECB:
568 	case CKM_AES_CTR:
569 	case CKM_AES_CCM:
570 	case CKM_AES_GCM:
571 		rv = soft_aes_decrypt_final(session_p, pLastPart,
572 		    pulLastPartLen);
573 		break;
574 
575 	case CKM_BLOWFISH_CBC:
576 	{
577 		soft_blowfish_ctx_t *soft_blowfish_ctx;
578 
579 		soft_blowfish_ctx =
580 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
581 
582 		*pulLastPartLen = 0;
583 		if (soft_blowfish_ctx->remain_len != 0)
584 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
585 		else {
586 			if (pLastPart == NULL)
587 				goto clean2;
588 		}
589 
590 		free(soft_blowfish_ctx->blowfish_cbc);
591 		freezero(soft_blowfish_ctx->key_sched,
592 		    soft_blowfish_ctx->keysched_len);
593 
594 		break;
595 	}
596 
597 	case CKM_RC4:
598 	{
599 		ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
600 		explicit_bzero(key, sizeof (*key));
601 		*pulLastPartLen = 0;
602 		break;
603 	}
604 
605 	default:
606 		/* PKCS11: The mechanism only supports single-part operation. */
607 		rv = CKR_MECHANISM_INVALID;
608 		break;
609 	}
610 
611 clean1:
612 	free(session_p->decrypt.context);
613 	session_p->decrypt.context = NULL;
614 
615 clean2:
616 	(void) pthread_mutex_unlock(&session_p->session_mutex);
617 
618 	return (rv);
619 
620 }
621