xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDecryptUtil.c (revision 5c277ab3267e7c6f448aefd8628b381dfc90b565)
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
soft_remove_pkcs7_padding(CK_BYTE * pData,CK_ULONG padded_len,CK_ULONG * pulDataLen)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
soft_decrypt_init(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p)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_CCM:
174 	case CKM_AES_GCM:
175 	case CKM_AES_GMAC:
176 		return (soft_aes_crypt_init_common(session_p, pMechanism,
177 		    key_p, B_FALSE));
178 
179 	case CKM_BLOWFISH_CBC:
180 	{
181 		soft_blowfish_ctx_t *soft_blowfish_ctx;
182 
183 		if (key_p->key_type != CKK_BLOWFISH)
184 			return (CKR_KEY_TYPE_INCONSISTENT);
185 
186 		if ((pMechanism->pParameter == NULL) ||
187 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
188 			return (CKR_MECHANISM_PARAM_INVALID);
189 
190 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
191 		    key_p, B_FALSE);
192 
193 		if (rv != CKR_OK)
194 			return (rv);
195 
196 		(void) pthread_mutex_lock(&session_p->session_mutex);
197 
198 		soft_blowfish_ctx =
199 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
200 
201 		/* Save Initialization Vector in the context. */
202 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
203 		    BLOWFISH_BLOCK_LEN);
204 
205 		/* Allocate a context for CBC */
206 		soft_blowfish_ctx->blowfish_cbc =
207 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
208 		    soft_blowfish_ctx->keysched_len,
209 		    soft_blowfish_ctx->ivec);
210 
211 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
212 			freezero(soft_blowfish_ctx->key_sched,
213 			    soft_blowfish_ctx->keysched_len);
214 			freezero(session_p->decrypt.context,
215 			    sizeof (soft_blowfish_ctx_t));
216 			session_p->decrypt.context = NULL;
217 			(void) pthread_mutex_unlock(&session_p->session_mutex);
218 			return (CKR_HOST_MEMORY);
219 		}
220 
221 		(void) pthread_mutex_unlock(&session_p->session_mutex);
222 		return (rv);
223 	}
224 
225 	case CKM_RC4:
226 
227 		if (key_p->key_type != CKK_RC4) {
228 			return (CKR_KEY_TYPE_INCONSISTENT);
229 		}
230 
231 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
232 		    B_FALSE));
233 
234 	case CKM_RSA_X_509:
235 	case CKM_RSA_PKCS:
236 
237 		if (key_p->key_type != CKK_RSA) {
238 			return (CKR_KEY_TYPE_INCONSISTENT);
239 		}
240 
241 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
242 		    key_p, B_FALSE));
243 
244 	default:
245 		return (CKR_MECHANISM_INVALID);
246 	}
247 }
248 
249 
250 /*
251  * soft_decrypt_common()
252  *
253  * Arguments:
254  *      session_p:	pointer to soft_session_t struct
255  *	pEncrypted:	pointer to the encrypted data as input
256  *	ulEncryptedLen:	length of the input data
257  *	pData:		pointer to the output data contains plaintext
258  *	pulDataLen:	pointer to the length of the output data
259  *	Update:		boolean flag indicates caller is soft_decrypt
260  *			or soft_decrypt_update
261  *
262  * Description:
263  *      This function calls the corresponding decrypt routine based
264  *	on the mechanism.
265  *
266  * Returns:
267  *	see soft_decrypt_common().
268  */
269 CK_RV
soft_decrypt_common(soft_session_t * session_p,CK_BYTE_PTR pEncrypted,CK_ULONG ulEncryptedLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen,boolean_t Update)270 soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
271     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
272     CK_ULONG_PTR pulDataLen, boolean_t Update)
273 {
274 
275 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
276 
277 	switch (mechanism) {
278 
279 	case CKM_DES_ECB:
280 	case CKM_DES_CBC:
281 	case CKM_DES3_ECB:
282 	case CKM_DES3_CBC:
283 
284 		if (ulEncryptedLen == 0) {
285 			*pulDataLen = 0;
286 			return (CKR_OK);
287 		}
288 		/* FALLTHROUGH */
289 
290 	case CKM_DES_CBC_PAD:
291 	case CKM_DES3_CBC_PAD:
292 
293 		return (soft_des_decrypt_common(session_p, pEncrypted,
294 		    ulEncryptedLen, pData, pulDataLen, Update));
295 
296 	case CKM_AES_ECB:
297 	case CKM_AES_CBC:
298 	case CKM_AES_CBC_PAD:
299 	case CKM_AES_CTR:
300 	case CKM_AES_CCM:
301 	case CKM_AES_GCM:
302 	case CKM_AES_GMAC:
303 		if (Update) {
304 			return (soft_aes_decrypt_update(session_p, pEncrypted,
305 			    ulEncryptedLen, pData, pulDataLen));
306 		} else {
307 			return (soft_aes_decrypt(session_p, pEncrypted,
308 			    ulEncryptedLen, pData, pulDataLen));
309 		}
310 
311 	case CKM_BLOWFISH_CBC:
312 
313 		if (ulEncryptedLen == 0) {
314 			*pulDataLen = 0;
315 			return (CKR_OK);
316 		}
317 
318 		return (soft_blowfish_decrypt_common(session_p, pEncrypted,
319 		    ulEncryptedLen, pData, pulDataLen, Update));
320 
321 	case CKM_RC4:
322 
323 		if (ulEncryptedLen == 0) {
324 			*pulDataLen = 0;
325 			return (CKR_OK);
326 		}
327 
328 
329 		return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
330 		    ulEncryptedLen, pData, pulDataLen));
331 
332 	case CKM_RSA_X_509:
333 	case CKM_RSA_PKCS:
334 
335 		return (soft_rsa_decrypt_common(session_p, pEncrypted,
336 		    ulEncryptedLen, pData, pulDataLen, mechanism));
337 
338 	default:
339 		return (CKR_MECHANISM_INVALID);
340 
341 	}
342 }
343 
344 
345 /*
346  * soft_decrypt()
347  *
348  * Arguments:
349  *      session_p:	pointer to soft_session_t struct
350  *	pEncryptedData: pointer to the encrypted data as input
351  *	ulEncryptedDataLen: length of the input data
352  *	pData:		pointer to the output data contains plaintext
353  *	pulDataLen:	pointer to the length of the output data
354  *
355  * Description:
356  *      called by C_Decrypt(). This function calls the soft_decrypt_common
357  *	routine.
358  *
359  * Returns:
360  *	see soft_decrypt_common().
361  */
362 CK_RV
soft_decrypt(soft_session_t * session_p,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)363 soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
364     CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
365     CK_ULONG_PTR pulDataLen)
366 {
367 
368 	return (soft_decrypt_common(session_p, pEncryptedData,
369 	    ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
370 }
371 
372 
373 /*
374  * soft_decrypt_update()
375  *
376  * Arguments:
377  *      session_p:	pointer to soft_session_t struct
378  *	pEncryptedPart: pointer to the encrypted data as input
379  *	ulEncryptedPartLen: length of the input data
380  *	pPart:          pointer to the output data contains plaintext
381  *	pulPartLen:     pointer to the length of the output data
382  *
383  * Description:
384  *      called by C_DecryptUpdate(). This function calls the
385  *	soft_decrypt_common routine (with update flag on).
386  *
387  * Returns:
388  *	see soft_decrypt_common().
389  */
390 CK_RV
soft_decrypt_update(soft_session_t * session_p,CK_BYTE_PTR pEncryptedPart,CK_ULONG ulEncryptedPartLen,CK_BYTE_PTR pPart,CK_ULONG_PTR pulPartLen)391 soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
392     CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
393 {
394 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
395 
396 	switch (mechanism) {
397 
398 	case CKM_DES_ECB:
399 	case CKM_DES_CBC:
400 	case CKM_DES_CBC_PAD:
401 	case CKM_DES3_ECB:
402 	case CKM_DES3_CBC:
403 	case CKM_DES3_CBC_PAD:
404 	case CKM_AES_ECB:
405 	case CKM_AES_CBC:
406 	case CKM_AES_CBC_PAD:
407 	case CKM_AES_CTR:
408 	case CKM_AES_CCM:
409 	case CKM_AES_GCM:
410 	case CKM_AES_GMAC:
411 	case CKM_BLOWFISH_CBC:
412 	case CKM_RC4:
413 
414 		return (soft_decrypt_common(session_p, pEncryptedPart,
415 		    ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
416 
417 	default:
418 		/* PKCS11: The mechanism only supports single-part operation. */
419 		return (CKR_MECHANISM_INVALID);
420 	}
421 
422 }
423 
424 
425 /*
426  * soft_decrypt_final()
427  *
428  * Arguments:
429  *      session_p:	pointer to soft_session_t struct
430  *      pLastPart:	pointer to the last recovered data part
431  *      pulLastPartLen:	pointer to the length of the last recovered data part
432  *
433  * Description:
434  *      called by C_DecryptFinal().
435  *
436  * Returns:
437  *	CKR_OK: success
438  *	CKR_FUNCTION_FAILED: decrypt final function failed
439  *	CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
440  */
441 CK_RV
soft_decrypt_final(soft_session_t * session_p,CK_BYTE_PTR pLastPart,CK_ULONG_PTR pulLastPartLen)442 soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
443     CK_ULONG_PTR pulLastPartLen)
444 {
445 
446 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
447 	CK_ULONG out_len;
448 	CK_RV rv = CKR_OK;
449 	int rc;
450 
451 	(void) pthread_mutex_lock(&session_p->session_mutex);
452 
453 	if (session_p->decrypt.context == NULL) {
454 		rv = CKR_OPERATION_NOT_INITIALIZED;
455 		*pulLastPartLen = 0;
456 		goto clean2;
457 	}
458 	switch (mechanism) {
459 
460 	case CKM_DES_CBC_PAD:
461 	case CKM_DES3_CBC_PAD:
462 	{
463 
464 		soft_des_ctx_t *soft_des_ctx;
465 
466 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
467 
468 		/*
469 		 * We should have only one block of data left in the
470 		 * remaining buffer.
471 		 */
472 		if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
473 			*pulLastPartLen = 0;
474 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
475 			/* Cleanup memory space. */
476 			free(soft_des_ctx->des_cbc);
477 			freezero(soft_des_ctx->key_sched,
478 			    soft_des_ctx->keysched_len);
479 
480 			goto clean1;
481 		}
482 
483 		out_len = DES_BLOCK_LEN;
484 
485 		/*
486 		 * If application asks for the length of the output buffer
487 		 * to hold the plaintext?
488 		 */
489 		if (pLastPart == NULL) {
490 			*pulLastPartLen = out_len;
491 			rv = CKR_OK;
492 			goto clean2;
493 		} else {
494 			crypto_data_t out;
495 
496 			/* Copy remaining data to the output buffer. */
497 			(void) memcpy(pLastPart, soft_des_ctx->data,
498 			    DES_BLOCK_LEN);
499 
500 			out.cd_format = CRYPTO_DATA_RAW;
501 			out.cd_offset = 0;
502 			out.cd_length = DES_BLOCK_LEN;
503 			out.cd_raw.iov_base = (char *)pLastPart;
504 			out.cd_raw.iov_len = DES_BLOCK_LEN;
505 
506 			/* Decrypt final block of data. */
507 			rc = des_decrypt_contiguous_blocks(
508 			    (des_ctx_t *)soft_des_ctx->des_cbc,
509 			    (char *)pLastPart, DES_BLOCK_LEN, &out);
510 
511 			if (rc == 0) {
512 				/*
513 				 * Remove padding bytes after decryption of
514 				 * ciphertext block to produce the original
515 				 * plaintext.
516 				 */
517 				rv = soft_remove_pkcs7_padding(pLastPart,
518 				    DES_BLOCK_LEN, &out_len);
519 				if (rv != CKR_OK)
520 					*pulLastPartLen = 0;
521 				else
522 					*pulLastPartLen = out_len;
523 			} else {
524 				*pulLastPartLen = 0;
525 				rv = CKR_FUNCTION_FAILED;
526 			}
527 
528 			/* Cleanup memory space. */
529 			free(soft_des_ctx->des_cbc);
530 			freezero(soft_des_ctx->key_sched,
531 			    soft_des_ctx->keysched_len);
532 
533 		}
534 
535 		break;
536 	}
537 
538 	case CKM_DES_CBC:
539 	case CKM_DES_ECB:
540 	case CKM_DES3_CBC:
541 	case CKM_DES3_ECB:
542 	{
543 
544 		soft_des_ctx_t *soft_des_ctx;
545 
546 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
547 		/*
548 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
549 		 * so when the final is called, the remaining buffer
550 		 * should not contain any more data.
551 		 */
552 		*pulLastPartLen = 0;
553 		if (soft_des_ctx->remain_len != 0) {
554 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
555 		} else {
556 			if (pLastPart == NULL)
557 				goto clean2;
558 		}
559 
560 		/* Cleanup memory space. */
561 		free(soft_des_ctx->des_cbc);
562 		freezero(soft_des_ctx->key_sched,
563 		    soft_des_ctx->keysched_len);
564 
565 		break;
566 	}
567 
568 	case CKM_AES_CBC_PAD:
569 	case CKM_AES_CBC:
570 	case CKM_AES_ECB:
571 	case CKM_AES_CTR:
572 	case CKM_AES_CCM:
573 	case CKM_AES_GCM:
574 	case CKM_AES_GMAC:
575 		rv = soft_aes_decrypt_final(session_p, pLastPart,
576 		    pulLastPartLen);
577 		break;
578 
579 	case CKM_BLOWFISH_CBC:
580 	{
581 		soft_blowfish_ctx_t *soft_blowfish_ctx;
582 
583 		soft_blowfish_ctx =
584 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
585 
586 		*pulLastPartLen = 0;
587 		if (soft_blowfish_ctx->remain_len != 0)
588 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
589 		else {
590 			if (pLastPart == NULL)
591 				goto clean2;
592 		}
593 
594 		free(soft_blowfish_ctx->blowfish_cbc);
595 		freezero(soft_blowfish_ctx->key_sched,
596 		    soft_blowfish_ctx->keysched_len);
597 
598 		break;
599 	}
600 
601 	case CKM_RC4:
602 	{
603 		ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
604 		explicit_bzero(key, sizeof (*key));
605 		*pulLastPartLen = 0;
606 		break;
607 	}
608 
609 	default:
610 		/* PKCS11: The mechanism only supports single-part operation. */
611 		rv = CKR_MECHANISM_INVALID;
612 		break;
613 	}
614 
615 clean1:
616 	free(session_p->decrypt.context);
617 	session_p->decrypt.context = NULL;
618 
619 clean2:
620 	(void) pthread_mutex_unlock(&session_p->session_mutex);
621 
622 	return (rv);
623 
624 }
625