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_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
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)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
soft_decrypt(soft_session_t * session_p,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)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
soft_decrypt_update(soft_session_t * session_p,CK_BYTE_PTR pEncryptedPart,CK_ULONG ulEncryptedPartLen,CK_BYTE_PTR pPart,CK_ULONG_PTR pulPartLen)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
soft_decrypt_final(soft_session_t * session_p,CK_BYTE_PTR pLastPart,CK_ULONG_PTR pulLastPartLen)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