Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softDESCrypt.c
blobc6c8472f61007dc2d33735cbaeea9928973682d3
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2018, Joyent, Inc.
27 #include <pthread.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <sys/types.h>
32 #include <security/cryptoki.h>
33 #include <modes/modes.h>
34 #include <des_impl.h>
35 #include "softSession.h"
36 #include "softObject.h"
37 #include "softCrypt.h"
38 #include "softOps.h"
41 * Allocate context for the active encryption or decryption operation, and
42 * generate DES or DES3 key schedule to speed up the operation.
44 CK_RV
45 soft_des_crypt_init_common(soft_session_t *session_p,
46 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
47 boolean_t encrypt)
50 size_t size;
51 soft_des_ctx_t *soft_des_ctx;
53 soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t));
54 if (soft_des_ctx == NULL) {
55 return (CKR_HOST_MEMORY);
58 /* Allocate key schedule for DES or DES3 based on key type. */
59 if (key_p->key_type == CKK_DES)
60 soft_des_ctx->key_sched = des_alloc_keysched(&size, DES, 0);
61 else
62 soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0);
64 if (soft_des_ctx->key_sched == NULL) {
65 free(soft_des_ctx);
66 return (CKR_HOST_MEMORY);
69 soft_des_ctx->keysched_len = size;
70 soft_des_ctx->key_type = key_p->key_type;
72 (void) pthread_mutex_lock(&session_p->session_mutex);
73 if (encrypt) {
74 /* Called by C_EncryptInit. */
75 session_p->encrypt.context = soft_des_ctx;
76 session_p->encrypt.mech.mechanism = pMechanism->mechanism;
77 } else {
78 /* Called by C_DecryptInit. */
79 session_p->decrypt.context = soft_des_ctx;
80 session_p->decrypt.mech.mechanism = pMechanism->mechanism;
82 (void) pthread_mutex_unlock(&session_p->session_mutex);
85 * If this is a non-sensitive key and it does NOT have
86 * a key schedule yet, then allocate one and expand it.
87 * Otherwise, if its a non-sensitive key, and it DOES have
88 * a key schedule already attached to it, just copy the
89 * pre-expanded schedule to the context and avoid the
90 * extra key schedule expansion operation.
92 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
93 if (OBJ_KEY_SCHED(key_p) == NULL) {
94 void *ks;
95 (void) pthread_mutex_lock(&key_p->object_mutex);
96 if (OBJ_KEY_SCHED(key_p) == NULL) {
97 if (key_p->key_type == CKK_DES)
98 ks = des_alloc_keysched(&size, DES, 0);
99 else
100 ks = des_alloc_keysched(&size, DES3, 0);
101 if (ks == NULL) {
102 (void) pthread_mutex_unlock(
103 &key_p->object_mutex);
104 free(soft_des_ctx);
105 return (CKR_HOST_MEMORY);
107 /* Initialize key schedule for DES or DES3. */
108 if (key_p->key_type == CKK_DES)
109 des_init_keysched(
110 OBJ_SEC(key_p)->sk_value, DES, ks);
111 else if (key_p->key_type == CKK_DES2)
113 * DES3 encryption/decryption needs to
114 * support a DES2 key.
116 des_init_keysched(
117 OBJ_SEC(key_p)->sk_value, DES2, ks);
118 else
119 des_init_keysched(
120 OBJ_SEC(key_p)->sk_value, DES3, ks);
122 OBJ_KEY_SCHED_LEN(key_p) = size;
123 OBJ_KEY_SCHED(key_p) = ks;
125 (void) pthread_mutex_unlock(&key_p->object_mutex);
128 /* Copy the pre-expanded key schedule from the key object */
129 (void) memcpy(soft_des_ctx->key_sched, OBJ_KEY_SCHED(key_p),
130 OBJ_KEY_SCHED_LEN(key_p));
131 soft_des_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
132 } else {
133 /* for sensitive keys, we cannot cache the key schedule */
134 if (key_p->key_type == CKK_DES)
135 des_init_keysched(OBJ_SEC(key_p)->sk_value,
136 DES, soft_des_ctx->key_sched);
137 else if (key_p->key_type == CKK_DES2)
139 * DES3 encryption/decryption needs to
140 * support a DES2 key.
142 des_init_keysched(OBJ_SEC(key_p)->sk_value,
143 DES2, soft_des_ctx->key_sched);
144 else
145 des_init_keysched(OBJ_SEC(key_p)->sk_value,
146 DES3, soft_des_ctx->key_sched);
149 return (CKR_OK);
154 * soft_des_encrypt_common()
156 * Arguments:
157 * session_p: pointer to soft_session_t struct
158 * pData: pointer to the input data to be encrypted
159 * ulDataLen: length of the input data
160 * pEncrypted: pointer to the output data after encryption
161 * pulEncryptedLen: pointer to the length of the output data
162 * update: boolean flag indicates caller is soft_encrypt
163 * or soft_encrypt_update
165 * Description:
166 * This function calls the corresponding encrypt routine based
167 * on the mechanism.
169 * Returns:
170 * CKR_OK: success
171 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
172 * is too small
173 * CKR_FUNCTION_FAILED: encrypt function failed
174 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
176 CK_RV
177 soft_des_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
178 CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
179 CK_ULONG_PTR pulEncryptedLen, boolean_t update)
181 int rc = 0;
182 CK_RV rv = CKR_OK;
183 soft_des_ctx_t *soft_des_ctx =
184 (soft_des_ctx_t *)session_p->encrypt.context;
185 des_ctx_t *des_ctx;
186 CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
187 CK_BYTE *in_buf = NULL;
188 CK_BYTE *out_buf = NULL;
189 CK_ULONG out_len;
190 CK_ULONG total_len;
191 CK_ULONG remain;
192 boolean_t pad_mechanism = B_FALSE;
194 pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
195 mechanism == CKM_DES3_CBC_PAD);
197 * DES only takes input length that is a multiple of blocksize
198 * for C_Encrypt function with the mechanism CKM_DES<n>_ECB or
199 * CKM_DES<n>_CBC.
201 * DES allows any input length for C_Encrypt function with the
202 * mechanism CKM_DES<n>_CBC_PAD and for C_EncryptUpdate function.
204 if (!update && !pad_mechanism) {
205 if ((ulDataLen % DES_BLOCK_LEN) != 0) {
206 rv = CKR_DATA_LEN_RANGE;
207 goto cleanup;
211 if (!update) {
213 * Called by C_Encrypt
215 if (pad_mechanism) {
217 * For CKM_DES<n>_CBC_PAD, compute output length to
218 * count for the padding. If the length of input
219 * data is a multiple of blocksize, then make output
220 * length to be the sum of the input length and
221 * one blocksize. Otherwise, output length will
222 * be rounded up to the next multiple of blocksize.
224 out_len = DES_BLOCK_LEN *
225 (ulDataLen / DES_BLOCK_LEN + 1);
226 } else {
228 * For non-padding mode, the output length will
229 * be same as the input length.
231 out_len = ulDataLen;
235 * If application asks for the length of the output buffer
236 * to hold the ciphertext?
238 if (pEncrypted == NULL) {
239 *pulEncryptedLen = out_len;
240 return (CKR_OK);
243 /* Is the application-supplied buffer large enough? */
244 if (*pulEncryptedLen < out_len) {
245 *pulEncryptedLen = out_len;
246 return (CKR_BUFFER_TOO_SMALL);
249 /* Encrypt pad bytes in a separate operation */
250 if (pad_mechanism) {
251 out_len -= DES_BLOCK_LEN;
254 in_buf = pData;
255 out_buf = pEncrypted;
256 } else {
258 * Called by C_EncryptUpdate
260 * Add the lengths of last remaining data and current
261 * plaintext together to get the total input length.
263 total_len = soft_des_ctx->remain_len + ulDataLen;
266 * If the total input length is less than one blocksize,
267 * or if the total input length is just one blocksize and
268 * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
269 * encryption until when more data comes in next
270 * C_EncryptUpdate or when C_EncryptFinal is called.
272 if ((total_len < DES_BLOCK_LEN) ||
273 (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
274 if (pData != NULL) {
276 * Save input data and its length in
277 * the remaining buffer of DES context.
279 (void) memcpy(soft_des_ctx->data +
280 soft_des_ctx->remain_len, pData, ulDataLen);
281 soft_des_ctx->remain_len += ulDataLen;
284 /* Set encrypted data length to 0. */
285 *pulEncryptedLen = 0;
286 return (CKR_OK);
289 /* Compute the length of remaing data. */
290 remain = total_len % DES_BLOCK_LEN;
293 * Make sure that the output length is a multiple of
294 * blocksize.
296 out_len = total_len - remain;
299 * If application asks for the length of the output buffer
300 * to hold the ciphertext?
302 if (pEncrypted == NULL) {
303 *pulEncryptedLen = out_len;
304 return (CKR_OK);
307 /* Is the application-supplied buffer large enough? */
308 if (*pulEncryptedLen < out_len) {
309 *pulEncryptedLen = out_len;
310 return (CKR_BUFFER_TOO_SMALL);
313 if (soft_des_ctx->remain_len != 0) {
315 * Copy last remaining data and current input data
316 * to the output buffer.
318 (void) memmove(pEncrypted + soft_des_ctx->remain_len,
319 pData, out_len - soft_des_ctx->remain_len);
320 (void) memcpy(pEncrypted, soft_des_ctx->data,
321 soft_des_ctx->remain_len);
322 bzero(soft_des_ctx->data, soft_des_ctx->remain_len);
324 in_buf = pEncrypted;
325 } else {
326 in_buf = pData;
328 out_buf = pEncrypted;
332 * Begin Encryption now.
334 switch (mechanism) {
336 case CKM_DES_ECB:
337 case CKM_DES3_ECB:
340 ulong_t i;
341 uint8_t *tmp_inbuf;
342 uint8_t *tmp_outbuf;
344 for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
345 tmp_inbuf = &in_buf[i];
346 tmp_outbuf = &out_buf[i];
347 /* Crunch one block of data for DES. */
348 if (soft_des_ctx->key_type == CKK_DES)
349 (void) des_crunch_block(
350 soft_des_ctx->key_sched,
351 tmp_inbuf, tmp_outbuf, B_FALSE);
352 else
353 (void) des3_crunch_block(
354 soft_des_ctx->key_sched,
355 tmp_inbuf, tmp_outbuf, B_FALSE);
358 if (update) {
360 * For encrypt update, if there is remaining
361 * data, save it and its length in the context.
363 if (remain != 0)
364 (void) memcpy(soft_des_ctx->data, pData +
365 (ulDataLen - remain), remain);
366 soft_des_ctx->remain_len = remain;
369 *pulEncryptedLen = out_len;
370 break;
373 case CKM_DES_CBC:
374 case CKM_DES_CBC_PAD:
375 case CKM_DES3_CBC:
376 case CKM_DES3_CBC_PAD:
378 crypto_data_t out;
380 out.cd_format = CRYPTO_DATA_RAW;
381 out.cd_offset = 0;
382 out.cd_length = out_len;
383 out.cd_raw.iov_base = (char *)out_buf;
384 out.cd_raw.iov_len = out_len;
386 /* Encrypt multiple blocks of data. */
387 rc = des_encrypt_contiguous_blocks(
388 (des_ctx_t *)soft_des_ctx->des_cbc,
389 (char *)in_buf, out_len, &out);
391 if (rc != 0)
392 goto encrypt_failed;
394 if (update) {
396 * For encrypt update, if there is remaining data,
397 * save it and its length in the context.
399 if (remain != 0)
400 (void) memcpy(soft_des_ctx->data, pData +
401 (ulDataLen - remain), remain);
402 soft_des_ctx->remain_len = remain;
403 } else if (pad_mechanism) {
405 * Save the remainder of the input
406 * block in a temporary block because
407 * we don't want to overrun the input buffer
408 * by tacking on pad bytes.
410 CK_BYTE tmpblock[DES_BLOCK_LEN];
411 (void) memcpy(tmpblock, in_buf + out_len,
412 ulDataLen - out_len);
413 soft_add_pkcs7_padding(tmpblock +
414 (ulDataLen - out_len),
415 DES_BLOCK_LEN, ulDataLen - out_len);
417 out.cd_offset = out_len;
418 out.cd_length = DES_BLOCK_LEN;
419 out.cd_raw.iov_base = (char *)out_buf;
420 out.cd_raw.iov_len = out_len + DES_BLOCK_LEN;
422 /* Encrypt last block containing pad bytes. */
423 rc = des_encrypt_contiguous_blocks(
424 (des_ctx_t *)soft_des_ctx->des_cbc,
425 (char *)tmpblock, DES_BLOCK_LEN, &out);
426 out_len += DES_BLOCK_LEN;
429 if (rc == 0) {
430 *pulEncryptedLen = out_len;
431 break;
433 encrypt_failed:
434 *pulEncryptedLen = 0;
435 rv = CKR_FUNCTION_FAILED;
436 goto cleanup;
439 } /* end switch */
441 if (update)
442 return (CKR_OK);
445 * The following code will be executed if the caller is
446 * soft_encrypt() or an error occurred. The encryption
447 * operation will be terminated so we need to do some cleanup.
449 cleanup:
450 (void) pthread_mutex_lock(&session_p->session_mutex);
451 des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
452 free(des_ctx);
453 freezero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
454 freezero(session_p->encrypt.context, sizeof (soft_des_ctx_t));
455 session_p->encrypt.context = NULL;
456 (void) pthread_mutex_unlock(&session_p->session_mutex);
458 return (rv);
463 * soft_des_decrypt_common()
465 * Arguments:
466 * session_p: pointer to soft_session_t struct
467 * pEncrypted: pointer to the input data to be decrypted
468 * ulEncryptedLen: length of the input data
469 * pData: pointer to the output data
470 * pulDataLen: pointer to the length of the output data
471 * Update: boolean flag indicates caller is soft_decrypt
472 * or soft_decrypt_update
474 * Description:
475 * This function calls the corresponding decrypt routine based
476 * on the mechanism.
478 * Returns:
479 * CKR_OK: success
480 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
481 * is too small
482 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
483 * of blocksize
484 * CKR_FUNCTION_FAILED: decrypt function failed
486 CK_RV
487 soft_des_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
488 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
489 CK_ULONG_PTR pulDataLen, boolean_t update)
492 int rc = 0;
493 CK_RV rv = CKR_OK;
494 soft_des_ctx_t *soft_des_ctx =
495 (soft_des_ctx_t *)session_p->decrypt.context;
496 des_ctx_t *des_ctx;
497 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
498 CK_BYTE *in_buf = NULL;
499 CK_BYTE *out_buf = NULL;
500 CK_ULONG out_len;
501 CK_ULONG total_len;
502 CK_ULONG remain;
503 boolean_t pad_mechanism = B_FALSE;
505 pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
506 mechanism == CKM_DES3_CBC_PAD);
508 * DES only takes input length that is a multiple of 8 bytes
509 * for C_Decrypt function with the mechanism CKM_DES<n>_ECB,
510 * CKM_DES<n>_CBC or CKM_DES<n>_CBC_PAD.
512 * DES allows any input length for C_DecryptUpdate function.
514 if (!update) {
516 * Called by C_Decrypt
518 if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
519 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
520 goto cleanup;
524 * If application asks for the length of the output buffer
525 * to hold the plaintext?
527 if (pData == NULL) {
528 *pulDataLen = ulEncryptedLen;
529 return (CKR_OK);
532 /* Is the application-supplied buffer large enough? */
533 if (!pad_mechanism) {
534 if (*pulDataLen < ulEncryptedLen) {
535 *pulDataLen = ulEncryptedLen;
536 return (CKR_BUFFER_TOO_SMALL);
539 /* Set output length same as input length. */
540 out_len = ulEncryptedLen;
541 } else {
543 * For CKM_DES<n>_CBC_PAD, we don't know how
544 * many bytes for padding at this time, so
545 * we'd assume one block was padded.
547 if (*pulDataLen < (ulEncryptedLen - DES_BLOCK_LEN)) {
548 *pulDataLen = ulEncryptedLen - DES_BLOCK_LEN;
549 return (CKR_BUFFER_TOO_SMALL);
551 out_len = ulEncryptedLen - DES_BLOCK_LEN;
553 in_buf = pEncrypted;
554 out_buf = pData;
555 } else {
557 * Called by C_DecryptUpdate
559 * Add the lengths of last remaining data and current
560 * input data together to get the total input length.
562 total_len = soft_des_ctx->remain_len + ulEncryptedLen;
565 * If the total input length is less than one blocksize,
566 * or if the total input length is just one blocksize and
567 * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
568 * decryption until when more data comes in next
569 * C_DecryptUpdate or when C_DecryptFinal is called.
571 if ((total_len < DES_BLOCK_LEN) ||
572 (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
573 if (pEncrypted != NULL) {
575 * Save input data and its length in
576 * the remaining buffer of DES context.
578 (void) memcpy(soft_des_ctx->data +
579 soft_des_ctx->remain_len,
580 pEncrypted, ulEncryptedLen);
581 soft_des_ctx->remain_len += ulEncryptedLen;
584 /* Set output data length to 0. */
585 *pulDataLen = 0;
586 return (CKR_OK);
589 /* Compute the length of remaing data. */
590 remain = total_len % DES_BLOCK_LEN;
593 * Make sure that the output length is a multiple of
594 * blocksize.
596 out_len = total_len - remain;
598 if (pad_mechanism) {
600 * If the input data length is a multiple of
601 * blocksize, then save the last block of input
602 * data in the remaining buffer. C_DecryptFinal
603 * will handle this last block of data.
605 if (remain == 0) {
606 remain = DES_BLOCK_LEN;
607 out_len -= DES_BLOCK_LEN;
612 * If application asks for the length of the output buffer
613 * to hold the plaintext?
615 if (pData == NULL) {
616 *pulDataLen = out_len;
617 return (CKR_OK);
621 * Is the application-supplied buffer large enough?
623 if (*pulDataLen < out_len) {
624 *pulDataLen = out_len;
625 return (CKR_BUFFER_TOO_SMALL);
628 if (soft_des_ctx->remain_len != 0) {
630 * Copy last remaining data and current input data
631 * to the output buffer.
633 (void) memmove(pData + soft_des_ctx->remain_len,
634 pEncrypted, out_len - soft_des_ctx->remain_len);
635 (void) memcpy(pData, soft_des_ctx->data,
636 soft_des_ctx->remain_len);
637 bzero(soft_des_ctx->data, soft_des_ctx->remain_len);
639 in_buf = pData;
640 } else {
641 in_buf = pEncrypted;
643 out_buf = pData;
647 * Begin Decryption.
649 switch (mechanism) {
651 case CKM_DES_ECB:
652 case CKM_DES3_ECB:
654 uint8_t *tmp_inbuf;
655 uint8_t *tmp_outbuf;
656 ulong_t i;
658 for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
659 tmp_inbuf = &in_buf[i];
660 tmp_outbuf = &out_buf[i];
661 /* Crunch one block of data for DES. */
662 if (soft_des_ctx->key_type == CKK_DES)
663 (void) des_crunch_block(
664 soft_des_ctx->key_sched,
665 tmp_inbuf, tmp_outbuf, B_TRUE);
666 else
667 (void) des3_crunch_block(
668 soft_des_ctx->key_sched,
669 tmp_inbuf, tmp_outbuf, B_TRUE);
672 if (update) {
674 * For decrypt update, if there is remaining
675 * data, save it and its length in the context.
677 if (remain != 0)
678 (void) memcpy(soft_des_ctx->data, pEncrypted +
679 (ulEncryptedLen - remain), remain);
680 soft_des_ctx->remain_len = remain;
683 *pulDataLen = out_len;
684 break;
687 case CKM_DES_CBC:
688 case CKM_DES_CBC_PAD:
689 case CKM_DES3_CBC:
690 case CKM_DES3_CBC_PAD:
692 crypto_data_t out;
693 CK_ULONG rem_len;
694 uint8_t last_block[DES_BLOCK_LEN];
696 out.cd_format = CRYPTO_DATA_RAW;
697 out.cd_offset = 0;
698 out.cd_length = out_len;
699 out.cd_raw.iov_base = (char *)out_buf;
700 out.cd_raw.iov_len = out_len;
702 /* Decrypt multiple blocks of data. */
703 rc = des_decrypt_contiguous_blocks(
704 (des_ctx_t *)soft_des_ctx->des_cbc,
705 (char *)in_buf, out_len, &out);
707 if (rc != 0)
708 goto decrypt_failed;
710 if (pad_mechanism && !update) {
711 /* Decrypt last block containing pad bytes. */
712 out.cd_offset = 0;
713 out.cd_length = DES_BLOCK_LEN;
714 out.cd_raw.iov_base = (char *)last_block;
715 out.cd_raw.iov_len = DES_BLOCK_LEN;
717 /* Decrypt last block containing pad bytes. */
718 rc = des_decrypt_contiguous_blocks(
719 (des_ctx_t *)soft_des_ctx->des_cbc,
720 (char *)in_buf + out_len, DES_BLOCK_LEN, &out);
722 if (rc != 0)
723 goto decrypt_failed;
726 * Remove padding bytes after decryption of
727 * ciphertext block to produce the original
728 * plaintext.
730 rv = soft_remove_pkcs7_padding(last_block,
731 DES_BLOCK_LEN, &rem_len);
732 if (rv == CKR_OK) {
733 if (rem_len != 0)
734 (void) memcpy(out_buf + out_len,
735 last_block, rem_len);
736 *pulDataLen = out_len + rem_len;
737 } else {
738 *pulDataLen = 0;
739 goto cleanup;
741 } else {
742 *pulDataLen = out_len;
745 if (update) {
747 * For decrypt update, if there is remaining data,
748 * save it and its length in the context.
750 if (remain != 0)
751 (void) memcpy(soft_des_ctx->data, pEncrypted +
752 (ulEncryptedLen - remain), remain);
753 soft_des_ctx->remain_len = remain;
756 if (rc == 0)
757 break;
758 decrypt_failed:
759 *pulDataLen = 0;
760 rv = CKR_FUNCTION_FAILED;
761 goto cleanup;
763 } /* end switch */
765 if (update)
766 return (CKR_OK);
769 * The following code will be executed if the caller is
770 * soft_decrypt() or an error occurred. The decryption
771 * operation will be terminated so we need to do some cleanup.
773 cleanup:
774 (void) pthread_mutex_lock(&session_p->session_mutex);
775 des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
776 free(des_ctx);
777 freezero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
778 freezero(session_p->decrypt.context, sizeof (soft_des_ctx_t));
779 (void) pthread_mutex_unlock(&session_p->session_mutex);
781 return (rv);
786 * Allocate and initialize a context for DES CBC mode of operation.
788 void *
789 des_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec, CK_KEY_TYPE type)
792 cbc_ctx_t *cbc_ctx;
794 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
795 return (NULL);
797 cbc_ctx->cbc_keysched = key_sched;
799 (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, DES_BLOCK_LEN);
801 cbc_ctx->cbc_lastp = (uint8_t *)&cbc_ctx->cbc_iv[0];
802 cbc_ctx->cbc_keysched_len = size;
803 if (type == CKK_DES)
804 cbc_ctx->cbc_flags |= CBC_MODE;
805 else
806 cbc_ctx->cbc_flags |= CBC_MODE | DES3_STRENGTH;
808 return (cbc_ctx);
813 * Allocate and initialize DES contexts for both signing and encrypting,
814 * saving both context pointers in the session struct. For general-length DES
815 * MAC, check the length in the parameter to see if it is in the right range.
817 CK_RV
818 soft_des_sign_verify_init_common(soft_session_t *session_p,
819 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op)
821 soft_des_ctx_t *soft_des_ctx;
822 CK_MECHANISM encrypt_mech;
823 CK_RV rv;
825 if ((key_p->class != CKO_SECRET_KEY) || (key_p->key_type != CKK_DES)) {
826 return (CKR_KEY_TYPE_INCONSISTENT);
829 /* allocate memory for the sign/verify context */
830 soft_des_ctx = malloc(sizeof (soft_des_ctx_t));
831 if (soft_des_ctx == NULL) {
832 return (CKR_HOST_MEMORY);
835 soft_des_ctx->key_type = key_p->key_type;
837 /* initialization vector is zero for DES MAC */
838 bzero(soft_des_ctx->ivec, DES_BLOCK_LEN);
840 switch (pMechanism->mechanism) {
842 case CKM_DES_MAC_GENERAL:
844 if (pMechanism->ulParameterLen !=
845 sizeof (CK_MAC_GENERAL_PARAMS)) {
846 free(soft_des_ctx);
847 return (CKR_MECHANISM_PARAM_INVALID);
850 if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
851 DES_BLOCK_LEN) {
852 free(soft_des_ctx);
853 return (CKR_MECHANISM_PARAM_INVALID);
856 soft_des_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
857 pMechanism->pParameter);
859 /*FALLTHRU*/
860 case CKM_DES_MAC:
863 * For non-general DES MAC, output is always half as
864 * large as block size
866 if (pMechanism->mechanism == CKM_DES_MAC) {
867 soft_des_ctx->mac_len = DES_MAC_LEN;
870 /* allocate a context for DES encryption */
871 encrypt_mech.mechanism = CKM_DES_CBC_PAD;
872 encrypt_mech.pParameter = (void *)soft_des_ctx->ivec;
873 encrypt_mech.ulParameterLen = DES_BLOCK_LEN;
874 rv = soft_encrypt_init_internal(session_p, &encrypt_mech,
875 key_p);
876 if (rv != CKR_OK) {
877 free(soft_des_ctx);
878 return (rv);
881 (void) pthread_mutex_lock(&session_p->session_mutex);
883 if (sign_op) {
884 session_p->sign.context = soft_des_ctx;
885 session_p->sign.mech.mechanism = pMechanism->mechanism;
886 } else {
887 session_p->verify.context = soft_des_ctx;
888 session_p->verify.mech.mechanism =
889 pMechanism->mechanism;
892 (void) pthread_mutex_unlock(&session_p->session_mutex);
894 break;
896 return (CKR_OK);
900 * Called by soft_sign(), soft_sign_final(), soft_verify() or
901 * soft_verify_final().
903 CK_RV
904 soft_des_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
905 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
906 boolean_t sign_op, boolean_t Final)
908 soft_des_ctx_t *soft_des_ctx_sign_verify;
909 soft_des_ctx_t *soft_des_ctx_encrypt;
910 CK_RV rv;
911 CK_BYTE *pEncrypted = NULL;
912 CK_ULONG ulEncryptedLen = 0;
913 uint8_t remainder;
914 CK_BYTE last_block[DES_BLOCK_LEN];
915 des_ctx_t *des_ctx = NULL;
917 if (sign_op) {
918 soft_des_ctx_sign_verify =
919 (soft_des_ctx_t *)session_p->sign.context;
921 if (soft_des_ctx_sign_verify->mac_len == 0) {
922 *pulSignedLen = 0;
923 goto clean_exit;
926 /* Application asks for the length of the output buffer. */
927 if (pSigned == NULL) {
928 *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
929 return (CKR_OK);
932 /* Is the application-supplied buffer large enough? */
933 if (*pulSignedLen < soft_des_ctx_sign_verify->mac_len) {
934 *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
935 return (CKR_BUFFER_TOO_SMALL);
937 } else {
938 soft_des_ctx_sign_verify =
939 (soft_des_ctx_t *)session_p->verify.context;
942 if (Final) {
943 soft_des_ctx_encrypt =
944 (soft_des_ctx_t *)session_p->encrypt.context;
947 * If there is data left in the buffer from a previous
948 * SignUpdate() call, pass enough zeroed data to a
949 * soft_sign_update call to pad the remainder
951 if (soft_des_ctx_encrypt->remain_len != 0) {
952 bzero(last_block, DES_BLOCK_LEN);
953 ulEncryptedLen = DES_BLOCK_LEN;
956 * By passing a buffer to soft_encrypt_final,
957 * we force it to pad the remaining block
958 * and encrypt it.
960 rv = soft_encrypt_final(session_p, last_block,
961 &ulEncryptedLen);
962 if (rv != CKR_OK) {
963 goto clean_exit;
965 } else {
967 * The last block of enciphered data is stored in:
968 * soft_des_ctx_encrypt->des_cbc->des_ctx->dc_lastp
969 * Copy that data to last_block
971 soft_des_ctx_encrypt =
972 (soft_des_ctx_t *)session_p->encrypt.context;
973 des_ctx = (des_ctx_t *)soft_des_ctx_encrypt->des_cbc;
974 (void) memcpy(last_block, des_ctx->dc_lastp,
975 DES_BLOCK_LEN);
978 * Passing a NULL output buffer here
979 * forces the routine to just return.
981 rv = soft_encrypt_final(session_p, NULL,
982 &ulEncryptedLen);
985 } else {
987 * If the input length is not multiple of block size, then
988 * determine the correct encrypted data length by rounding
990 remainder = ulDataLen % DES_BLOCK_LEN;
992 * Because we always use DES_CBC_PAD mechanism
993 * for sign/verify operations, the input will
994 * be padded to the next 8 byte boundary.
995 * Adjust the length fields here accordingly.
997 ulEncryptedLen = ulDataLen + (DES_BLOCK_LEN - remainder);
999 pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
1000 if (pEncrypted == NULL) {
1001 rv = CKR_HOST_MEMORY;
1002 goto clean_exit;
1006 * Pad the last block with zeros by copying pData into a zeroed
1007 * pEncrypted. Then pass pEncrypted into soft_encrypt as input
1009 bzero(pEncrypted, ulEncryptedLen);
1010 (void) memcpy(pEncrypted, pData, ulDataLen);
1012 rv = soft_encrypt(session_p, pEncrypted, ulDataLen,
1013 pEncrypted, &ulEncryptedLen);
1014 (void) memcpy(last_block,
1015 &pEncrypted[ulEncryptedLen - DES_BLOCK_LEN], DES_BLOCK_LEN);
1018 if (rv == CKR_OK) {
1019 *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
1021 /* the leftmost mac_len bytes of last_block is our MAC */
1022 (void) memcpy(pSigned, last_block, *pulSignedLen);
1025 clean_exit:
1027 (void) pthread_mutex_lock(&session_p->session_mutex);
1029 /* soft_encrypt_common() has freed the encrypt context */
1030 if (sign_op) {
1031 free(session_p->sign.context);
1032 session_p->sign.context = NULL;
1033 } else {
1034 free(session_p->verify.context);
1035 session_p->verify.context = NULL;
1037 session_p->encrypt.flags = 0;
1039 (void) pthread_mutex_unlock(&session_p->session_mutex);
1041 if (pEncrypted) {
1042 free(pEncrypted);
1045 return (rv);
1049 * Called by soft_sign_update()
1051 CK_RV
1052 soft_des_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
1053 CK_ULONG ulPartLen)
1056 * The DES MAC is calculated by taking the specified number of
1057 * left-most bytes within the last block of
1058 * encrypted data, while the context of the multi-part
1059 * encryption stores the block necessary for XORing with the
1060 * input as per cipher block chaining . Therefore, none of the
1061 * intermediary encrypted blocks of data are necessary for
1062 * the DES MAC, and we can create a placeholder local buffer
1063 * for the encrypted data, which is immediately throw away.
1066 soft_des_ctx_t *soft_des_ctx_encrypt;
1067 CK_BYTE *pEncrypted = NULL;
1068 CK_ULONG ulEncryptedLen;
1069 CK_ULONG total_len;
1070 uint8_t remainder;
1071 CK_RV rv;
1073 soft_des_ctx_encrypt = (soft_des_ctx_t *)session_p->encrypt.context;
1075 /* Avoid the malloc if we won't be encrypting any data */
1076 total_len = soft_des_ctx_encrypt->remain_len + ulPartLen;
1078 if (total_len < DES_BLOCK_LEN) {
1079 rv = soft_encrypt_update(session_p, pPart, ulPartLen, NULL,
1080 &ulEncryptedLen);
1081 } else {
1082 remainder = ulPartLen % DES_BLOCK_LEN;
1084 /* round up to the nearest multiple of block size */
1085 ulEncryptedLen = ulPartLen + (DES_BLOCK_LEN - remainder);
1086 pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
1088 if (pEncrypted != NULL) {
1089 rv = soft_encrypt_update(session_p, pPart, ulPartLen,
1090 pEncrypted, &ulEncryptedLen);
1091 free(pEncrypted);
1092 } else {
1093 rv = CKR_HOST_MEMORY;
1096 return (rv);