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]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2018, Joyent, Inc.
31 #include <sys/types.h>
32 #include <security/cryptoki.h>
33 #include <modes/modes.h>
35 #include "softSession.h"
36 #include "softObject.h"
37 #include "softCrypt.h"
41 * Allocate context for the active encryption or decryption operation, and
42 * generate DES or DES3 key schedule to speed up the operation.
45 soft_des_crypt_init_common(soft_session_t
*session_p
,
46 CK_MECHANISM_PTR pMechanism
, soft_object_t
*key_p
,
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);
62 soft_des_ctx
->key_sched
= des_alloc_keysched(&size
, DES3
, 0);
64 if (soft_des_ctx
->key_sched
== NULL
) {
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
);
74 /* Called by C_EncryptInit. */
75 session_p
->encrypt
.context
= soft_des_ctx
;
76 session_p
->encrypt
.mech
.mechanism
= pMechanism
->mechanism
;
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
) {
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);
100 ks
= des_alloc_keysched(&size
, DES3
, 0);
102 (void) pthread_mutex_unlock(
103 &key_p
->object_mutex
);
105 return (CKR_HOST_MEMORY
);
107 /* Initialize key schedule for DES or DES3. */
108 if (key_p
->key_type
== CKK_DES
)
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.
117 OBJ_SEC(key_p
)->sk_value
, DES2
, ks
);
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
);
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
);
145 des_init_keysched(OBJ_SEC(key_p
)->sk_value
,
146 DES3
, soft_des_ctx
->key_sched
);
154 * soft_des_encrypt_common()
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
166 * This function calls the corresponding encrypt routine based
171 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
173 * CKR_FUNCTION_FAILED: encrypt function failed
174 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
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
)
183 soft_des_ctx_t
*soft_des_ctx
=
184 (soft_des_ctx_t
*)session_p
->encrypt
.context
;
186 CK_MECHANISM_TYPE mechanism
= session_p
->encrypt
.mech
.mechanism
;
187 CK_BYTE
*in_buf
= NULL
;
188 CK_BYTE
*out_buf
= NULL
;
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
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
;
213 * Called by C_Encrypt
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);
228 * For non-padding mode, the output length will
229 * be same as the input length.
235 * If application asks for the length of the output buffer
236 * to hold the ciphertext?
238 if (pEncrypted
== NULL
) {
239 *pulEncryptedLen
= out_len
;
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 */
251 out_len
-= DES_BLOCK_LEN
;
255 out_buf
= pEncrypted
;
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
))) {
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;
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
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
;
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
);
328 out_buf
= pEncrypted
;
332 * Begin Encryption now.
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
);
353 (void) des3_crunch_block(
354 soft_des_ctx
->key_sched
,
355 tmp_inbuf
, tmp_outbuf
, B_FALSE
);
360 * For encrypt update, if there is remaining
361 * data, save it and its length in the context.
364 (void) memcpy(soft_des_ctx
->data
, pData
+
365 (ulDataLen
- remain
), remain
);
366 soft_des_ctx
->remain_len
= remain
;
369 *pulEncryptedLen
= out_len
;
374 case CKM_DES_CBC_PAD
:
376 case CKM_DES3_CBC_PAD
:
380 out
.cd_format
= CRYPTO_DATA_RAW
;
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
);
396 * For encrypt update, if there is remaining data,
397 * save it and its length in the context.
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
;
430 *pulEncryptedLen
= out_len
;
434 *pulEncryptedLen
= 0;
435 rv
= CKR_FUNCTION_FAILED
;
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.
450 (void) pthread_mutex_lock(&session_p
->session_mutex
);
451 des_ctx
= (des_ctx_t
*)soft_des_ctx
->des_cbc
;
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
);
463 * soft_des_decrypt_common()
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
475 * This function calls the corresponding decrypt routine based
480 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
482 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
484 * CKR_FUNCTION_FAILED: decrypt function failed
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
)
494 soft_des_ctx_t
*soft_des_ctx
=
495 (soft_des_ctx_t
*)session_p
->decrypt
.context
;
497 CK_MECHANISM_TYPE mechanism
= session_p
->decrypt
.mech
.mechanism
;
498 CK_BYTE
*in_buf
= NULL
;
499 CK_BYTE
*out_buf
= NULL
;
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.
516 * Called by C_Decrypt
518 if ((ulEncryptedLen
% DES_BLOCK_LEN
) != 0) {
519 rv
= CKR_ENCRYPTED_DATA_LEN_RANGE
;
524 * If application asks for the length of the output buffer
525 * to hold the plaintext?
528 *pulDataLen
= ulEncryptedLen
;
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
;
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
;
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. */
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
596 out_len
= total_len
- remain
;
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.
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?
616 *pulDataLen
= out_len
;
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
);
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
);
667 (void) des3_crunch_block(
668 soft_des_ctx
->key_sched
,
669 tmp_inbuf
, tmp_outbuf
, B_TRUE
);
674 * For decrypt update, if there is remaining
675 * data, save it and its length in the context.
678 (void) memcpy(soft_des_ctx
->data
, pEncrypted
+
679 (ulEncryptedLen
- remain
), remain
);
680 soft_des_ctx
->remain_len
= remain
;
683 *pulDataLen
= out_len
;
688 case CKM_DES_CBC_PAD
:
690 case CKM_DES3_CBC_PAD
:
694 uint8_t last_block
[DES_BLOCK_LEN
];
696 out
.cd_format
= CRYPTO_DATA_RAW
;
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
);
710 if (pad_mechanism
&& !update
) {
711 /* Decrypt last block containing pad bytes. */
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
);
726 * Remove padding bytes after decryption of
727 * ciphertext block to produce the original
730 rv
= soft_remove_pkcs7_padding(last_block
,
731 DES_BLOCK_LEN
, &rem_len
);
734 (void) memcpy(out_buf
+ out_len
,
735 last_block
, rem_len
);
736 *pulDataLen
= out_len
+ rem_len
;
742 *pulDataLen
= out_len
;
747 * For decrypt update, if there is remaining data,
748 * save it and its length in the context.
751 (void) memcpy(soft_des_ctx
->data
, pEncrypted
+
752 (ulEncryptedLen
- remain
), remain
);
753 soft_des_ctx
->remain_len
= remain
;
760 rv
= CKR_FUNCTION_FAILED
;
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.
774 (void) pthread_mutex_lock(&session_p
->session_mutex
);
775 des_ctx
= (des_ctx_t
*)soft_des_ctx
->des_cbc
;
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
);
786 * Allocate and initialize a context for DES CBC mode of operation.
789 des_cbc_ctx_init(void *key_sched
, size_t size
, uint8_t *ivec
, CK_KEY_TYPE type
)
794 if ((cbc_ctx
= calloc(1, sizeof (cbc_ctx_t
))) == 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
;
804 cbc_ctx
->cbc_flags
|= CBC_MODE
;
806 cbc_ctx
->cbc_flags
|= CBC_MODE
| DES3_STRENGTH
;
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.
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
;
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
)) {
847 return (CKR_MECHANISM_PARAM_INVALID
);
850 if (*(CK_MAC_GENERAL_PARAMS
*)pMechanism
->pParameter
>
853 return (CKR_MECHANISM_PARAM_INVALID
);
856 soft_des_ctx
->mac_len
= *((CK_MAC_GENERAL_PARAMS_PTR
)
857 pMechanism
->pParameter
);
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
,
881 (void) pthread_mutex_lock(&session_p
->session_mutex
);
884 session_p
->sign
.context
= soft_des_ctx
;
885 session_p
->sign
.mech
.mechanism
= pMechanism
->mechanism
;
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
);
900 * Called by soft_sign(), soft_sign_final(), soft_verify() or
901 * soft_verify_final().
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
;
911 CK_BYTE
*pEncrypted
= NULL
;
912 CK_ULONG ulEncryptedLen
= 0;
914 CK_BYTE last_block
[DES_BLOCK_LEN
];
915 des_ctx_t
*des_ctx
= NULL
;
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) {
926 /* Application asks for the length of the output buffer. */
927 if (pSigned
== NULL
) {
928 *pulSignedLen
= soft_des_ctx_sign_verify
->mac_len
;
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
);
938 soft_des_ctx_sign_verify
=
939 (soft_des_ctx_t
*)session_p
->verify
.context
;
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
960 rv
= soft_encrypt_final(session_p
, last_block
,
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
,
978 * Passing a NULL output buffer here
979 * forces the routine to just return.
981 rv
= soft_encrypt_final(session_p
, NULL
,
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
;
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
);
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
);
1027 (void) pthread_mutex_lock(&session_p
->session_mutex
);
1029 /* soft_encrypt_common() has freed the encrypt context */
1031 free(session_p
->sign
.context
);
1032 session_p
->sign
.context
= NULL
;
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
);
1049 * Called by soft_sign_update()
1052 soft_des_mac_sign_verify_update(soft_session_t
*session_p
, CK_BYTE_PTR pPart
,
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
;
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
,
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
);
1093 rv
= CKR_HOST_MEMORY
;