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.
30 #include <sys/types.h>
31 #include <security/cryptoki.h>
32 #include <modes/modes.h>
34 #include "softSession.h"
35 #include "softObject.h"
36 #include "softCrypt.h"
40 * Allocate context for the active encryption or decryption operation, and
41 * generate DES or DES3 key schedule to speed up the operation.
44 soft_des_crypt_init_common(soft_session_t
*session_p
,
45 CK_MECHANISM_PTR pMechanism
, soft_object_t
*key_p
,
50 soft_des_ctx_t
*soft_des_ctx
;
52 soft_des_ctx
= calloc(1, sizeof (soft_des_ctx_t
));
53 if (soft_des_ctx
== NULL
) {
54 return (CKR_HOST_MEMORY
);
57 /* Allocate key schedule for DES or DES3 based on key type. */
58 if (key_p
->key_type
== CKK_DES
)
59 soft_des_ctx
->key_sched
= des_alloc_keysched(&size
, DES
, 0);
61 soft_des_ctx
->key_sched
= des_alloc_keysched(&size
, DES3
, 0);
63 if (soft_des_ctx
->key_sched
== NULL
) {
65 return (CKR_HOST_MEMORY
);
68 soft_des_ctx
->keysched_len
= size
;
69 soft_des_ctx
->key_type
= key_p
->key_type
;
71 (void) pthread_mutex_lock(&session_p
->session_mutex
);
73 /* Called by C_EncryptInit. */
74 session_p
->encrypt
.context
= soft_des_ctx
;
75 session_p
->encrypt
.mech
.mechanism
= pMechanism
->mechanism
;
77 /* Called by C_DecryptInit. */
78 session_p
->decrypt
.context
= soft_des_ctx
;
79 session_p
->decrypt
.mech
.mechanism
= pMechanism
->mechanism
;
81 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
84 * If this is a non-sensitive key and it does NOT have
85 * a key schedule yet, then allocate one and expand it.
86 * Otherwise, if its a non-sensitive key, and it DOES have
87 * a key schedule already attached to it, just copy the
88 * pre-expanded schedule to the context and avoid the
89 * extra key schedule expansion operation.
91 if (!(key_p
->bool_attr_mask
& SENSITIVE_BOOL_ON
)) {
92 if (OBJ_KEY_SCHED(key_p
) == NULL
) {
94 (void) pthread_mutex_lock(&key_p
->object_mutex
);
95 if (OBJ_KEY_SCHED(key_p
) == NULL
) {
96 if (key_p
->key_type
== CKK_DES
)
97 ks
= des_alloc_keysched(&size
, DES
, 0);
99 ks
= des_alloc_keysched(&size
, DES3
, 0);
101 (void) pthread_mutex_unlock(
102 &key_p
->object_mutex
);
104 return (CKR_HOST_MEMORY
);
106 /* Initialize key schedule for DES or DES3. */
107 if (key_p
->key_type
== CKK_DES
)
109 OBJ_SEC(key_p
)->sk_value
, DES
, ks
);
110 else if (key_p
->key_type
== CKK_DES2
)
112 * DES3 encryption/decryption needs to
113 * support a DES2 key.
116 OBJ_SEC(key_p
)->sk_value
, DES2
, ks
);
119 OBJ_SEC(key_p
)->sk_value
, DES3
, ks
);
121 OBJ_KEY_SCHED_LEN(key_p
) = size
;
122 OBJ_KEY_SCHED(key_p
) = ks
;
124 (void) pthread_mutex_unlock(&key_p
->object_mutex
);
127 /* Copy the pre-expanded key schedule from the key object */
128 (void) memcpy(soft_des_ctx
->key_sched
, OBJ_KEY_SCHED(key_p
),
129 OBJ_KEY_SCHED_LEN(key_p
));
130 soft_des_ctx
->keysched_len
= OBJ_KEY_SCHED_LEN(key_p
);
132 /* for sensitive keys, we cannot cache the key schedule */
133 if (key_p
->key_type
== CKK_DES
)
134 des_init_keysched(OBJ_SEC(key_p
)->sk_value
,
135 DES
, soft_des_ctx
->key_sched
);
136 else if (key_p
->key_type
== CKK_DES2
)
138 * DES3 encryption/decryption needs to
139 * support a DES2 key.
141 des_init_keysched(OBJ_SEC(key_p
)->sk_value
,
142 DES2
, soft_des_ctx
->key_sched
);
144 des_init_keysched(OBJ_SEC(key_p
)->sk_value
,
145 DES3
, soft_des_ctx
->key_sched
);
153 * soft_des_encrypt_common()
156 * session_p: pointer to soft_session_t struct
157 * pData: pointer to the input data to be encrypted
158 * ulDataLen: length of the input data
159 * pEncrypted: pointer to the output data after encryption
160 * pulEncryptedLen: pointer to the length of the output data
161 * update: boolean flag indicates caller is soft_encrypt
162 * or soft_encrypt_update
165 * This function calls the corresponding encrypt routine based
170 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
172 * CKR_FUNCTION_FAILED: encrypt function failed
173 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
176 soft_des_encrypt_common(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
177 CK_ULONG ulDataLen
, CK_BYTE_PTR pEncrypted
,
178 CK_ULONG_PTR pulEncryptedLen
, boolean_t update
)
182 soft_des_ctx_t
*soft_des_ctx
=
183 (soft_des_ctx_t
*)session_p
->encrypt
.context
;
185 CK_MECHANISM_TYPE mechanism
= session_p
->encrypt
.mech
.mechanism
;
186 CK_BYTE
*in_buf
= NULL
;
187 CK_BYTE
*out_buf
= NULL
;
191 boolean_t pad_mechanism
= B_FALSE
;
193 pad_mechanism
= (mechanism
== CKM_DES_CBC_PAD
||
194 mechanism
== CKM_DES3_CBC_PAD
);
196 * DES only takes input length that is a multiple of blocksize
197 * for C_Encrypt function with the mechanism CKM_DES<n>_ECB or
200 * DES allows any input length for C_Encrypt function with the
201 * mechanism CKM_DES<n>_CBC_PAD and for C_EncryptUpdate function.
203 if (!update
&& !pad_mechanism
) {
204 if ((ulDataLen
% DES_BLOCK_LEN
) != 0) {
205 rv
= CKR_DATA_LEN_RANGE
;
212 * Called by C_Encrypt
216 * For CKM_DES<n>_CBC_PAD, compute output length to
217 * count for the padding. If the length of input
218 * data is a multiple of blocksize, then make output
219 * length to be the sum of the input length and
220 * one blocksize. Otherwise, output length will
221 * be rounded up to the next multiple of blocksize.
223 out_len
= DES_BLOCK_LEN
*
224 (ulDataLen
/ DES_BLOCK_LEN
+ 1);
227 * For non-padding mode, the output length will
228 * be same as the input length.
234 * If application asks for the length of the output buffer
235 * to hold the ciphertext?
237 if (pEncrypted
== NULL
) {
238 *pulEncryptedLen
= out_len
;
242 /* Is the application-supplied buffer large enough? */
243 if (*pulEncryptedLen
< out_len
) {
244 *pulEncryptedLen
= out_len
;
245 return (CKR_BUFFER_TOO_SMALL
);
248 /* Encrypt pad bytes in a separate operation */
250 out_len
-= DES_BLOCK_LEN
;
254 out_buf
= pEncrypted
;
257 * Called by C_EncryptUpdate
259 * Add the lengths of last remaining data and current
260 * plaintext together to get the total input length.
262 total_len
= soft_des_ctx
->remain_len
+ ulDataLen
;
265 * If the total input length is less than one blocksize,
266 * or if the total input length is just one blocksize and
267 * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
268 * encryption until when more data comes in next
269 * C_EncryptUpdate or when C_EncryptFinal is called.
271 if ((total_len
< DES_BLOCK_LEN
) ||
272 (pad_mechanism
&& (total_len
== DES_BLOCK_LEN
))) {
275 * Save input data and its length in
276 * the remaining buffer of DES context.
278 (void) memcpy(soft_des_ctx
->data
+
279 soft_des_ctx
->remain_len
, pData
, ulDataLen
);
280 soft_des_ctx
->remain_len
+= ulDataLen
;
283 /* Set encrypted data length to 0. */
284 *pulEncryptedLen
= 0;
288 /* Compute the length of remaing data. */
289 remain
= total_len
% DES_BLOCK_LEN
;
292 * Make sure that the output length is a multiple of
295 out_len
= total_len
- remain
;
298 * If application asks for the length of the output buffer
299 * to hold the ciphertext?
301 if (pEncrypted
== NULL
) {
302 *pulEncryptedLen
= out_len
;
306 /* Is the application-supplied buffer large enough? */
307 if (*pulEncryptedLen
< out_len
) {
308 *pulEncryptedLen
= out_len
;
309 return (CKR_BUFFER_TOO_SMALL
);
312 if (soft_des_ctx
->remain_len
!= 0) {
314 * Copy last remaining data and current input data
315 * to the output buffer.
317 (void) memmove(pEncrypted
+ soft_des_ctx
->remain_len
,
318 pData
, out_len
- soft_des_ctx
->remain_len
);
319 (void) memcpy(pEncrypted
, soft_des_ctx
->data
,
320 soft_des_ctx
->remain_len
);
321 bzero(soft_des_ctx
->data
, soft_des_ctx
->remain_len
);
327 out_buf
= pEncrypted
;
331 * Begin Encryption now.
343 for (i
= 0; i
< out_len
; i
+= DES_BLOCK_LEN
) {
344 tmp_inbuf
= &in_buf
[i
];
345 tmp_outbuf
= &out_buf
[i
];
346 /* Crunch one block of data for DES. */
347 if (soft_des_ctx
->key_type
== CKK_DES
)
348 (void) des_crunch_block(
349 soft_des_ctx
->key_sched
,
350 tmp_inbuf
, tmp_outbuf
, B_FALSE
);
352 (void) des3_crunch_block(
353 soft_des_ctx
->key_sched
,
354 tmp_inbuf
, tmp_outbuf
, B_FALSE
);
359 * For encrypt update, if there is remaining
360 * data, save it and its length in the context.
363 (void) memcpy(soft_des_ctx
->data
, pData
+
364 (ulDataLen
- remain
), remain
);
365 soft_des_ctx
->remain_len
= remain
;
368 *pulEncryptedLen
= out_len
;
373 case CKM_DES_CBC_PAD
:
375 case CKM_DES3_CBC_PAD
:
379 out
.cd_format
= CRYPTO_DATA_RAW
;
381 out
.cd_length
= out_len
;
382 out
.cd_raw
.iov_base
= (char *)out_buf
;
383 out
.cd_raw
.iov_len
= out_len
;
385 /* Encrypt multiple blocks of data. */
386 rc
= des_encrypt_contiguous_blocks(
387 (des_ctx_t
*)soft_des_ctx
->des_cbc
,
388 (char *)in_buf
, out_len
, &out
);
395 * For encrypt update, if there is remaining data,
396 * save it and its length in the context.
399 (void) memcpy(soft_des_ctx
->data
, pData
+
400 (ulDataLen
- remain
), remain
);
401 soft_des_ctx
->remain_len
= remain
;
402 } else if (pad_mechanism
) {
404 * Save the remainder of the input
405 * block in a temporary block because
406 * we don't want to overrun the input buffer
407 * by tacking on pad bytes.
409 CK_BYTE tmpblock
[DES_BLOCK_LEN
];
410 (void) memcpy(tmpblock
, in_buf
+ out_len
,
411 ulDataLen
- out_len
);
412 soft_add_pkcs7_padding(tmpblock
+
413 (ulDataLen
- out_len
),
414 DES_BLOCK_LEN
, ulDataLen
- out_len
);
416 out
.cd_offset
= out_len
;
417 out
.cd_length
= DES_BLOCK_LEN
;
418 out
.cd_raw
.iov_base
= (char *)out_buf
;
419 out
.cd_raw
.iov_len
= out_len
+ DES_BLOCK_LEN
;
421 /* Encrypt last block containing pad bytes. */
422 rc
= des_encrypt_contiguous_blocks(
423 (des_ctx_t
*)soft_des_ctx
->des_cbc
,
424 (char *)tmpblock
, DES_BLOCK_LEN
, &out
);
425 out_len
+= DES_BLOCK_LEN
;
429 *pulEncryptedLen
= out_len
;
433 *pulEncryptedLen
= 0;
434 rv
= CKR_FUNCTION_FAILED
;
444 * The following code will be executed if the caller is
445 * soft_encrypt() or an error occurred. The encryption
446 * operation will be terminated so we need to do some cleanup.
449 (void) pthread_mutex_lock(&session_p
->session_mutex
);
450 des_ctx
= (des_ctx_t
*)soft_des_ctx
->des_cbc
;
451 if (des_ctx
!= NULL
) {
452 bzero(des_ctx
->dc_keysched
, des_ctx
->dc_keysched_len
);
453 free(soft_des_ctx
->des_cbc
);
456 bzero(soft_des_ctx
->key_sched
, soft_des_ctx
->keysched_len
);
457 free(soft_des_ctx
->key_sched
);
458 free(session_p
->encrypt
.context
);
459 session_p
->encrypt
.context
= NULL
;
460 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
467 * soft_des_decrypt_common()
470 * session_p: pointer to soft_session_t struct
471 * pEncrypted: pointer to the input data to be decrypted
472 * ulEncryptedLen: length of the input data
473 * pData: pointer to the output data
474 * pulDataLen: pointer to the length of the output data
475 * Update: boolean flag indicates caller is soft_decrypt
476 * or soft_decrypt_update
479 * This function calls the corresponding decrypt routine based
484 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
486 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
488 * CKR_FUNCTION_FAILED: decrypt function failed
491 soft_des_decrypt_common(soft_session_t
*session_p
, CK_BYTE_PTR pEncrypted
,
492 CK_ULONG ulEncryptedLen
, CK_BYTE_PTR pData
,
493 CK_ULONG_PTR pulDataLen
, boolean_t update
)
498 soft_des_ctx_t
*soft_des_ctx
=
499 (soft_des_ctx_t
*)session_p
->decrypt
.context
;
501 CK_MECHANISM_TYPE mechanism
= session_p
->decrypt
.mech
.mechanism
;
502 CK_BYTE
*in_buf
= NULL
;
503 CK_BYTE
*out_buf
= NULL
;
507 boolean_t pad_mechanism
= B_FALSE
;
509 pad_mechanism
= (mechanism
== CKM_DES_CBC_PAD
||
510 mechanism
== CKM_DES3_CBC_PAD
);
512 * DES only takes input length that is a multiple of 8 bytes
513 * for C_Decrypt function with the mechanism CKM_DES<n>_ECB,
514 * CKM_DES<n>_CBC or CKM_DES<n>_CBC_PAD.
516 * DES allows any input length for C_DecryptUpdate function.
520 * Called by C_Decrypt
522 if ((ulEncryptedLen
% DES_BLOCK_LEN
) != 0) {
523 rv
= CKR_ENCRYPTED_DATA_LEN_RANGE
;
528 * If application asks for the length of the output buffer
529 * to hold the plaintext?
532 *pulDataLen
= ulEncryptedLen
;
536 /* Is the application-supplied buffer large enough? */
537 if (!pad_mechanism
) {
538 if (*pulDataLen
< ulEncryptedLen
) {
539 *pulDataLen
= ulEncryptedLen
;
540 return (CKR_BUFFER_TOO_SMALL
);
543 /* Set output length same as input length. */
544 out_len
= ulEncryptedLen
;
547 * For CKM_DES<n>_CBC_PAD, we don't know how
548 * many bytes for padding at this time, so
549 * we'd assume one block was padded.
551 if (*pulDataLen
< (ulEncryptedLen
- DES_BLOCK_LEN
)) {
552 *pulDataLen
= ulEncryptedLen
- DES_BLOCK_LEN
;
553 return (CKR_BUFFER_TOO_SMALL
);
555 out_len
= ulEncryptedLen
- DES_BLOCK_LEN
;
561 * Called by C_DecryptUpdate
563 * Add the lengths of last remaining data and current
564 * input data together to get the total input length.
566 total_len
= soft_des_ctx
->remain_len
+ ulEncryptedLen
;
569 * If the total input length is less than one blocksize,
570 * or if the total input length is just one blocksize and
571 * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
572 * decryption until when more data comes in next
573 * C_DecryptUpdate or when C_DecryptFinal is called.
575 if ((total_len
< DES_BLOCK_LEN
) ||
576 (pad_mechanism
&& (total_len
== DES_BLOCK_LEN
))) {
577 if (pEncrypted
!= NULL
) {
579 * Save input data and its length in
580 * the remaining buffer of DES context.
582 (void) memcpy(soft_des_ctx
->data
+
583 soft_des_ctx
->remain_len
,
584 pEncrypted
, ulEncryptedLen
);
585 soft_des_ctx
->remain_len
+= ulEncryptedLen
;
588 /* Set output data length to 0. */
593 /* Compute the length of remaing data. */
594 remain
= total_len
% DES_BLOCK_LEN
;
597 * Make sure that the output length is a multiple of
600 out_len
= total_len
- remain
;
604 * If the input data length is a multiple of
605 * blocksize, then save the last block of input
606 * data in the remaining buffer. C_DecryptFinal
607 * will handle this last block of data.
610 remain
= DES_BLOCK_LEN
;
611 out_len
-= DES_BLOCK_LEN
;
616 * If application asks for the length of the output buffer
617 * to hold the plaintext?
620 *pulDataLen
= out_len
;
625 * Is the application-supplied buffer large enough?
627 if (*pulDataLen
< out_len
) {
628 *pulDataLen
= out_len
;
629 return (CKR_BUFFER_TOO_SMALL
);
632 if (soft_des_ctx
->remain_len
!= 0) {
634 * Copy last remaining data and current input data
635 * to the output buffer.
637 (void) memmove(pData
+ soft_des_ctx
->remain_len
,
638 pEncrypted
, out_len
- soft_des_ctx
->remain_len
);
639 (void) memcpy(pData
, soft_des_ctx
->data
,
640 soft_des_ctx
->remain_len
);
641 bzero(soft_des_ctx
->data
, soft_des_ctx
->remain_len
);
662 for (i
= 0; i
< out_len
; i
+= DES_BLOCK_LEN
) {
663 tmp_inbuf
= &in_buf
[i
];
664 tmp_outbuf
= &out_buf
[i
];
665 /* Crunch one block of data for DES. */
666 if (soft_des_ctx
->key_type
== CKK_DES
)
667 (void) des_crunch_block(
668 soft_des_ctx
->key_sched
,
669 tmp_inbuf
, tmp_outbuf
, B_TRUE
);
671 (void) des3_crunch_block(
672 soft_des_ctx
->key_sched
,
673 tmp_inbuf
, tmp_outbuf
, B_TRUE
);
678 * For decrypt update, if there is remaining
679 * data, save it and its length in the context.
682 (void) memcpy(soft_des_ctx
->data
, pEncrypted
+
683 (ulEncryptedLen
- remain
), remain
);
684 soft_des_ctx
->remain_len
= remain
;
687 *pulDataLen
= out_len
;
692 case CKM_DES_CBC_PAD
:
694 case CKM_DES3_CBC_PAD
:
698 uint8_t last_block
[DES_BLOCK_LEN
];
700 out
.cd_format
= CRYPTO_DATA_RAW
;
702 out
.cd_length
= out_len
;
703 out
.cd_raw
.iov_base
= (char *)out_buf
;
704 out
.cd_raw
.iov_len
= out_len
;
706 /* Decrypt multiple blocks of data. */
707 rc
= des_decrypt_contiguous_blocks(
708 (des_ctx_t
*)soft_des_ctx
->des_cbc
,
709 (char *)in_buf
, out_len
, &out
);
714 if (pad_mechanism
&& !update
) {
715 /* Decrypt last block containing pad bytes. */
717 out
.cd_length
= DES_BLOCK_LEN
;
718 out
.cd_raw
.iov_base
= (char *)last_block
;
719 out
.cd_raw
.iov_len
= DES_BLOCK_LEN
;
721 /* Decrypt last block containing pad bytes. */
722 rc
= des_decrypt_contiguous_blocks(
723 (des_ctx_t
*)soft_des_ctx
->des_cbc
,
724 (char *)in_buf
+ out_len
, DES_BLOCK_LEN
, &out
);
730 * Remove padding bytes after decryption of
731 * ciphertext block to produce the original
734 rv
= soft_remove_pkcs7_padding(last_block
,
735 DES_BLOCK_LEN
, &rem_len
);
738 (void) memcpy(out_buf
+ out_len
,
739 last_block
, rem_len
);
740 *pulDataLen
= out_len
+ rem_len
;
746 *pulDataLen
= out_len
;
751 * For decrypt update, if there is remaining data,
752 * save it and its length in the context.
755 (void) memcpy(soft_des_ctx
->data
, pEncrypted
+
756 (ulEncryptedLen
- remain
), remain
);
757 soft_des_ctx
->remain_len
= remain
;
764 rv
= CKR_FUNCTION_FAILED
;
773 * The following code will be executed if the caller is
774 * soft_decrypt() or an error occurred. The decryption
775 * operation will be terminated so we need to do some cleanup.
778 (void) pthread_mutex_lock(&session_p
->session_mutex
);
779 des_ctx
= (des_ctx_t
*)soft_des_ctx
->des_cbc
;
780 if (des_ctx
!= NULL
) {
781 bzero(des_ctx
->dc_keysched
, des_ctx
->dc_keysched_len
);
782 free(soft_des_ctx
->des_cbc
);
785 bzero(soft_des_ctx
->key_sched
, soft_des_ctx
->keysched_len
);
786 free(soft_des_ctx
->key_sched
);
787 free(session_p
->decrypt
.context
);
788 session_p
->decrypt
.context
= NULL
;
789 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
796 * Allocate and initialize a context for DES CBC mode of operation.
799 des_cbc_ctx_init(void *key_sched
, size_t size
, uint8_t *ivec
, CK_KEY_TYPE type
)
804 if ((cbc_ctx
= calloc(1, sizeof (cbc_ctx_t
))) == NULL
)
807 cbc_ctx
->cbc_keysched
= key_sched
;
809 (void) memcpy(&cbc_ctx
->cbc_iv
[0], ivec
, DES_BLOCK_LEN
);
811 cbc_ctx
->cbc_lastp
= (uint8_t *)&cbc_ctx
->cbc_iv
[0];
812 cbc_ctx
->cbc_keysched_len
= size
;
814 cbc_ctx
->cbc_flags
|= CBC_MODE
;
816 cbc_ctx
->cbc_flags
|= CBC_MODE
| DES3_STRENGTH
;
823 * Allocate and initialize DES contexts for both signing and encrypting,
824 * saving both context pointers in the session struct. For general-length DES
825 * MAC, check the length in the parameter to see if it is in the right range.
828 soft_des_sign_verify_init_common(soft_session_t
*session_p
,
829 CK_MECHANISM_PTR pMechanism
, soft_object_t
*key_p
, boolean_t sign_op
)
831 soft_des_ctx_t
*soft_des_ctx
;
832 CK_MECHANISM encrypt_mech
;
835 if ((key_p
->class != CKO_SECRET_KEY
) || (key_p
->key_type
!= CKK_DES
)) {
836 return (CKR_KEY_TYPE_INCONSISTENT
);
839 /* allocate memory for the sign/verify context */
840 soft_des_ctx
= malloc(sizeof (soft_des_ctx_t
));
841 if (soft_des_ctx
== NULL
) {
842 return (CKR_HOST_MEMORY
);
845 soft_des_ctx
->key_type
= key_p
->key_type
;
847 /* initialization vector is zero for DES MAC */
848 bzero(soft_des_ctx
->ivec
, DES_BLOCK_LEN
);
850 switch (pMechanism
->mechanism
) {
852 case CKM_DES_MAC_GENERAL
:
854 if (pMechanism
->ulParameterLen
!=
855 sizeof (CK_MAC_GENERAL_PARAMS
)) {
857 return (CKR_MECHANISM_PARAM_INVALID
);
860 if (*(CK_MAC_GENERAL_PARAMS
*)pMechanism
->pParameter
>
863 return (CKR_MECHANISM_PARAM_INVALID
);
866 soft_des_ctx
->mac_len
= *((CK_MAC_GENERAL_PARAMS_PTR
)
867 pMechanism
->pParameter
);
873 * For non-general DES MAC, output is always half as
874 * large as block size
876 if (pMechanism
->mechanism
== CKM_DES_MAC
) {
877 soft_des_ctx
->mac_len
= DES_MAC_LEN
;
880 /* allocate a context for DES encryption */
881 encrypt_mech
.mechanism
= CKM_DES_CBC_PAD
;
882 encrypt_mech
.pParameter
= (void *)soft_des_ctx
->ivec
;
883 encrypt_mech
.ulParameterLen
= DES_BLOCK_LEN
;
884 rv
= soft_encrypt_init_internal(session_p
, &encrypt_mech
,
891 (void) pthread_mutex_lock(&session_p
->session_mutex
);
894 session_p
->sign
.context
= soft_des_ctx
;
895 session_p
->sign
.mech
.mechanism
= pMechanism
->mechanism
;
897 session_p
->verify
.context
= soft_des_ctx
;
898 session_p
->verify
.mech
.mechanism
=
899 pMechanism
->mechanism
;
902 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
910 * Called by soft_sign(), soft_sign_final(), soft_verify() or
911 * soft_verify_final().
914 soft_des_sign_verify_common(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
915 CK_ULONG ulDataLen
, CK_BYTE_PTR pSigned
, CK_ULONG_PTR pulSignedLen
,
916 boolean_t sign_op
, boolean_t Final
)
918 soft_des_ctx_t
*soft_des_ctx_sign_verify
;
919 soft_des_ctx_t
*soft_des_ctx_encrypt
;
921 CK_BYTE
*pEncrypted
= NULL
;
922 CK_ULONG ulEncryptedLen
= 0;
924 CK_BYTE last_block
[DES_BLOCK_LEN
];
925 des_ctx_t
*des_ctx
= NULL
;
928 soft_des_ctx_sign_verify
=
929 (soft_des_ctx_t
*)session_p
->sign
.context
;
931 if (soft_des_ctx_sign_verify
->mac_len
== 0) {
936 /* Application asks for the length of the output buffer. */
937 if (pSigned
== NULL
) {
938 *pulSignedLen
= soft_des_ctx_sign_verify
->mac_len
;
942 /* Is the application-supplied buffer large enough? */
943 if (*pulSignedLen
< soft_des_ctx_sign_verify
->mac_len
) {
944 *pulSignedLen
= soft_des_ctx_sign_verify
->mac_len
;
945 return (CKR_BUFFER_TOO_SMALL
);
948 soft_des_ctx_sign_verify
=
949 (soft_des_ctx_t
*)session_p
->verify
.context
;
953 soft_des_ctx_encrypt
=
954 (soft_des_ctx_t
*)session_p
->encrypt
.context
;
957 * If there is data left in the buffer from a previous
958 * SignUpdate() call, pass enough zeroed data to a
959 * soft_sign_update call to pad the remainder
961 if (soft_des_ctx_encrypt
->remain_len
!= 0) {
962 bzero(last_block
, DES_BLOCK_LEN
);
963 ulEncryptedLen
= DES_BLOCK_LEN
;
966 * By passing a buffer to soft_encrypt_final,
967 * we force it to pad the remaining block
970 rv
= soft_encrypt_final(session_p
, last_block
,
977 * The last block of enciphered data is stored in:
978 * soft_des_ctx_encrypt->des_cbc->des_ctx->dc_lastp
979 * Copy that data to last_block
981 soft_des_ctx_encrypt
=
982 (soft_des_ctx_t
*)session_p
->encrypt
.context
;
983 des_ctx
= (des_ctx_t
*)soft_des_ctx_encrypt
->des_cbc
;
984 (void) memcpy(last_block
, des_ctx
->dc_lastp
,
988 * Passing a NULL output buffer here
989 * forces the routine to just return.
991 rv
= soft_encrypt_final(session_p
, NULL
,
997 * If the input length is not multiple of block size, then
998 * determine the correct encrypted data length by rounding
1000 remainder
= ulDataLen
% DES_BLOCK_LEN
;
1002 * Because we always use DES_CBC_PAD mechanism
1003 * for sign/verify operations, the input will
1004 * be padded to the next 8 byte boundary.
1005 * Adjust the length fields here accordingly.
1007 ulEncryptedLen
= ulDataLen
+ (DES_BLOCK_LEN
- remainder
);
1009 pEncrypted
= malloc(sizeof (CK_BYTE
) * ulEncryptedLen
);
1010 if (pEncrypted
== NULL
) {
1011 rv
= CKR_HOST_MEMORY
;
1016 * Pad the last block with zeros by copying pData into a zeroed
1017 * pEncrypted. Then pass pEncrypted into soft_encrypt as input
1019 bzero(pEncrypted
, ulEncryptedLen
);
1020 (void) memcpy(pEncrypted
, pData
, ulDataLen
);
1022 rv
= soft_encrypt(session_p
, pEncrypted
, ulDataLen
,
1023 pEncrypted
, &ulEncryptedLen
);
1024 (void) memcpy(last_block
,
1025 &pEncrypted
[ulEncryptedLen
- DES_BLOCK_LEN
], DES_BLOCK_LEN
);
1029 *pulSignedLen
= soft_des_ctx_sign_verify
->mac_len
;
1031 /* the leftmost mac_len bytes of last_block is our MAC */
1032 (void) memcpy(pSigned
, last_block
, *pulSignedLen
);
1037 (void) pthread_mutex_lock(&session_p
->session_mutex
);
1039 /* soft_encrypt_common() has freed the encrypt context */
1041 free(session_p
->sign
.context
);
1042 session_p
->sign
.context
= NULL
;
1044 free(session_p
->verify
.context
);
1045 session_p
->verify
.context
= NULL
;
1047 session_p
->encrypt
.flags
= 0;
1049 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
1059 * Called by soft_sign_update()
1062 soft_des_mac_sign_verify_update(soft_session_t
*session_p
, CK_BYTE_PTR pPart
,
1066 * The DES MAC is calculated by taking the specified number of
1067 * left-most bytes within the last block of
1068 * encrypted data, while the context of the multi-part
1069 * encryption stores the block necessary for XORing with the
1070 * input as per cipher block chaining . Therefore, none of the
1071 * intermediary encrypted blocks of data are necessary for
1072 * the DES MAC, and we can create a placeholder local buffer
1073 * for the encrypted data, which is immediately throw away.
1076 soft_des_ctx_t
*soft_des_ctx_encrypt
;
1077 CK_BYTE
*pEncrypted
= NULL
;
1078 CK_ULONG ulEncryptedLen
;
1083 soft_des_ctx_encrypt
= (soft_des_ctx_t
*)session_p
->encrypt
.context
;
1085 /* Avoid the malloc if we won't be encrypting any data */
1086 total_len
= soft_des_ctx_encrypt
->remain_len
+ ulPartLen
;
1088 if (total_len
< DES_BLOCK_LEN
) {
1089 rv
= soft_encrypt_update(session_p
, pPart
, ulPartLen
, NULL
,
1092 remainder
= ulPartLen
% DES_BLOCK_LEN
;
1094 /* round up to the nearest multiple of block size */
1095 ulEncryptedLen
= ulPartLen
+ (DES_BLOCK_LEN
- remainder
);
1096 pEncrypted
= malloc(sizeof (CK_BYTE
) * ulEncryptedLen
);
1098 if (pEncrypted
!= NULL
) {
1099 rv
= soft_encrypt_update(session_p
, pPart
, ulPartLen
,
1100 pEncrypted
, &ulEncryptedLen
);
1103 rv
= CKR_HOST_MEMORY
;