Home | History | Annotate | Download | only in common
      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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <pthread.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <strings.h>
     30 #include <sys/types.h>
     31 #include <security/cryptoki.h>
     32 #include <modes/modes.h>
     33 #include <des_impl.h>
     34 #include "softSession.h"
     35 #include "softObject.h"
     36 #include "softCrypt.h"
     37 #include "softOps.h"
     38 
     39 /*
     40  * Allocate context for the active encryption or decryption operation, and
     41  * generate DES or DES3 key schedule to speed up the operation.
     42  */
     43 CK_RV
     44 soft_des_crypt_init_common(soft_session_t *session_p,
     45     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
     46     boolean_t encrypt)
     47 {
     48 
     49 	size_t size;
     50 	soft_des_ctx_t *soft_des_ctx;
     51 
     52 	soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t));
     53 	if (soft_des_ctx == NULL) {
     54 		return (CKR_HOST_MEMORY);
     55 	}
     56 
     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);
     60 	else
     61 		soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0);
     62 
     63 	if (soft_des_ctx->key_sched == NULL) {
     64 		free(soft_des_ctx);
     65 		return (CKR_HOST_MEMORY);
     66 	}
     67 
     68 	soft_des_ctx->keysched_len = size;
     69 	soft_des_ctx->key_type = key_p->key_type;
     70 
     71 	(void) pthread_mutex_lock(&session_p->session_mutex);
     72 	if (encrypt) {
     73 		/* Called by C_EncryptInit. */
     74 		session_p->encrypt.context = soft_des_ctx;
     75 		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
     76 	} else {
     77 		/* Called by C_DecryptInit. */
     78 		session_p->decrypt.context = soft_des_ctx;
     79 		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
     80 	}
     81 	(void) pthread_mutex_unlock(&session_p->session_mutex);
     82 
     83 	/*
     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.
     90 	 */
     91 	if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
     92 		if (OBJ_KEY_SCHED(key_p) == NULL) {
     93 			void *ks;
     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);
     98 				else
     99 					ks = des_alloc_keysched(&size, DES3, 0);
    100 				if (ks == NULL) {
    101 					(void) pthread_mutex_unlock(
    102 					    &key_p->object_mutex);
    103 					free(soft_des_ctx);
    104 					return (CKR_HOST_MEMORY);
    105 				}
    106 				/* Initialize key schedule for DES or DES3. */
    107 				if (key_p->key_type == CKK_DES)
    108 					des_init_keysched(
    109 					    OBJ_SEC(key_p)->sk_value, DES, ks);
    110 				else if (key_p->key_type == CKK_DES2)
    111 					/*
    112 					 * DES3 encryption/decryption needs to
    113 					 * support a DES2 key.
    114 					 */
    115 					des_init_keysched(
    116 					    OBJ_SEC(key_p)->sk_value, DES2, ks);
    117 				else
    118 					des_init_keysched(
    119 					    OBJ_SEC(key_p)->sk_value, DES3, ks);
    120 
    121 				OBJ_KEY_SCHED_LEN(key_p) = size;
    122 				OBJ_KEY_SCHED(key_p) = ks;
    123 			}
    124 			(void) pthread_mutex_unlock(&key_p->object_mutex);
    125 		}
    126 
    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);
    131 	} else {
    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)
    137 			/*
    138 			 * DES3 encryption/decryption needs to
    139 			 * support a DES2 key.
    140 			 */
    141 			des_init_keysched(OBJ_SEC(key_p)->sk_value,
    142 			    DES2, soft_des_ctx->key_sched);
    143 		else
    144 			des_init_keysched(OBJ_SEC(key_p)->sk_value,
    145 			    DES3, soft_des_ctx->key_sched);
    146 	}
    147 
    148 	return (CKR_OK);
    149 }
    150 
    151 
    152 /*
    153  * soft_des_encrypt_common()
    154  *
    155  * Arguments:
    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
    163  *
    164  * Description:
    165  *      This function calls the corresponding encrypt routine based
    166  *	on the mechanism.
    167  *
    168  * Returns:
    169  *      CKR_OK: success
    170  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
    171  *			      is too small
    172  *	CKR_FUNCTION_FAILED: encrypt function failed
    173  *	CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
    174  */
    175 CK_RV
    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)
    179 {
    180 	int rc = 0;
    181 	CK_RV rv = CKR_OK;
    182 	soft_des_ctx_t *soft_des_ctx =
    183 	    (soft_des_ctx_t *)session_p->encrypt.context;
    184 	des_ctx_t *des_ctx;
    185 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
    186 	CK_BYTE *in_buf = NULL;
    187 	CK_BYTE *out_buf = NULL;
    188 	CK_ULONG out_len;
    189 	CK_ULONG total_len;
    190 	CK_ULONG remain;
    191 	boolean_t pad_mechanism = B_FALSE;
    192 
    193 	pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
    194 	    mechanism == CKM_DES3_CBC_PAD);
    195 	/*
    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
    198 	 * CKM_DES<n>_CBC.
    199 	 *
    200 	 * DES allows any input length for C_Encrypt function with the
    201 	 * mechanism CKM_DES<n>_CBC_PAD and for C_EncryptUpdate function.
    202 	 */
    203 	if (!update && !pad_mechanism) {
    204 		if ((ulDataLen % DES_BLOCK_LEN) != 0) {
    205 			rv = CKR_DATA_LEN_RANGE;
    206 			goto cleanup;
    207 		}
    208 	}
    209 
    210 	if (!update) {
    211 		/*
    212 		 * Called by C_Encrypt
    213 		 */
    214 		if (pad_mechanism) {
    215 			/*
    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.
    222 			 */
    223 			out_len = DES_BLOCK_LEN *
    224 			    (ulDataLen / DES_BLOCK_LEN + 1);
    225 		} else {
    226 			/*
    227 			 * For non-padding mode, the output length will
    228 			 * be same as the input length.
    229 			 */
    230 			out_len = ulDataLen;
    231 		}
    232 
    233 		/*
    234 		 * If application asks for the length of the output buffer
    235 		 * to hold the ciphertext?
    236 		 */
    237 		if (pEncrypted == NULL) {
    238 			*pulEncryptedLen = out_len;
    239 			return (CKR_OK);
    240 		}
    241 
    242 		/* Is the application-supplied buffer large enough? */
    243 		if (*pulEncryptedLen < out_len) {
    244 			*pulEncryptedLen = out_len;
    245 			return (CKR_BUFFER_TOO_SMALL);
    246 		}
    247 
    248 		/* Encrypt pad bytes in a separate operation */
    249 		if (pad_mechanism) {
    250 			out_len -= DES_BLOCK_LEN;
    251 		}
    252 
    253 		in_buf = pData;
    254 		out_buf = pEncrypted;
    255 	} else {
    256 		/*
    257 		 * Called by C_EncryptUpdate
    258 		 *
    259 		 * Add the lengths of last remaining data and current
    260 		 * plaintext together to get the total input length.
    261 		 */
    262 		total_len = soft_des_ctx->remain_len + ulDataLen;
    263 
    264 		/*
    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.
    270 		 */
    271 		if ((total_len < DES_BLOCK_LEN) ||
    272 		    (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
    273 			if (pData != NULL) {
    274 				/*
    275 				 * Save input data and its length in
    276 				 * the remaining buffer of DES context.
    277 				 */
    278 				(void) memcpy(soft_des_ctx->data +
    279 				    soft_des_ctx->remain_len, pData, ulDataLen);
    280 				soft_des_ctx->remain_len += ulDataLen;
    281 			}
    282 
    283 			/* Set encrypted data length to 0. */
    284 			*pulEncryptedLen = 0;
    285 			return (CKR_OK);
    286 		}
    287 
    288 		/* Compute the length of remaing data. */
    289 		remain = total_len % DES_BLOCK_LEN;
    290 
    291 		/*
    292 		 * Make sure that the output length is a multiple of
    293 		 * blocksize.
    294 		 */
    295 		out_len = total_len - remain;
    296 
    297 		/*
    298 		 * If application asks for the length of the output buffer
    299 		 * to hold the ciphertext?
    300 		 */
    301 		if (pEncrypted == NULL) {
    302 			*pulEncryptedLen = out_len;
    303 			return (CKR_OK);
    304 		}
    305 
    306 		/* Is the application-supplied buffer large enough? */
    307 		if (*pulEncryptedLen < out_len) {
    308 			*pulEncryptedLen = out_len;
    309 			return (CKR_BUFFER_TOO_SMALL);
    310 		}
    311 
    312 		if (soft_des_ctx->remain_len != 0) {
    313 			/*
    314 			 * Copy last remaining data and current input data
    315 			 * to the output buffer.
    316 			 */
    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);
    322 
    323 			in_buf = pEncrypted;
    324 		} else {
    325 			in_buf = pData;
    326 		}
    327 		out_buf = pEncrypted;
    328 	}
    329 
    330 	/*
    331 	 * Begin Encryption now.
    332 	 */
    333 	switch (mechanism) {
    334 
    335 	case CKM_DES_ECB:
    336 	case CKM_DES3_ECB:
    337 	{
    338 
    339 		ulong_t i;
    340 		uint8_t *tmp_inbuf;
    341 		uint8_t *tmp_outbuf;
    342 
    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);
    351 			else
    352 				(void) des3_crunch_block(
    353 				    soft_des_ctx->key_sched,
    354 				    tmp_inbuf, tmp_outbuf, B_FALSE);
    355 		}
    356 
    357 		if (update) {
    358 			/*
    359 			 * For encrypt update, if there is remaining
    360 			 * data, save it and its length in the context.
    361 			 */
    362 			if (remain != 0)
    363 				(void) memcpy(soft_des_ctx->data, pData +
    364 				    (ulDataLen - remain), remain);
    365 			soft_des_ctx->remain_len = remain;
    366 		}
    367 
    368 		*pulEncryptedLen = out_len;
    369 		break;
    370 	}
    371 
    372 	case CKM_DES_CBC:
    373 	case CKM_DES_CBC_PAD:
    374 	case CKM_DES3_CBC:
    375 	case CKM_DES3_CBC_PAD:
    376 	{
    377 		crypto_data_t out;
    378 
    379 		out.cd_format =  CRYPTO_DATA_RAW;
    380 		out.cd_offset = 0;
    381 		out.cd_length = out_len;
    382 		out.cd_raw.iov_base = (char *)out_buf;
    383 		out.cd_raw.iov_len = out_len;
    384 
    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);
    389 
    390 		if (rc != 0)
    391 			goto encrypt_failed;
    392 
    393 		if (update) {
    394 			/*
    395 			 * For encrypt update, if there is remaining data,
    396 			 * save it and its length in the context.
    397 			 */
    398 			if (remain != 0)
    399 				(void) memcpy(soft_des_ctx->data, pData +
    400 				    (ulDataLen - remain), remain);
    401 			soft_des_ctx->remain_len = remain;
    402 		} else if (pad_mechanism) {
    403 			/*
    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.
    408 			 */
    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);
    415 
    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;
    420 
    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;
    426 		}
    427 
    428 		if (rc == 0) {
    429 			*pulEncryptedLen = out_len;
    430 			break;
    431 		}
    432 encrypt_failed:
    433 		*pulEncryptedLen = 0;
    434 		rv = CKR_FUNCTION_FAILED;
    435 		goto cleanup;
    436 
    437 	}
    438 	} /* end switch */
    439 
    440 	if (update)
    441 		return (CKR_OK);
    442 
    443 	/*
    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.
    447 	 */
    448 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);
    454 	}
    455 
    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);
    461 
    462 	return (rv);
    463 }
    464 
    465 
    466 /*
    467  * soft_des_decrypt_common()
    468  *
    469  * Arguments:
    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
    477  *
    478  * Description:
    479  *      This function calls the corresponding decrypt routine based
    480  *	on the mechanism.
    481  *
    482  * Returns:
    483  *      CKR_OK: success
    484  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
    485  *			      is too small
    486  *	CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
    487  *				      of blocksize
    488  *	CKR_FUNCTION_FAILED: decrypt function failed
    489  */
    490 CK_RV
    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)
    494 {
    495 
    496 	int rc = 0;
    497 	CK_RV rv = CKR_OK;
    498 	soft_des_ctx_t *soft_des_ctx =
    499 	    (soft_des_ctx_t *)session_p->decrypt.context;
    500 	des_ctx_t *des_ctx;
    501 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
    502 	CK_BYTE *in_buf = NULL;
    503 	CK_BYTE *out_buf = NULL;
    504 	CK_ULONG out_len;
    505 	CK_ULONG total_len;
    506 	CK_ULONG remain;
    507 	boolean_t pad_mechanism = B_FALSE;
    508 
    509 	pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
    510 	    mechanism == CKM_DES3_CBC_PAD);
    511 	/*
    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.
    515 	 *
    516 	 * DES allows any input length for C_DecryptUpdate function.
    517 	 */
    518 	if (!update) {
    519 		/*
    520 		 * Called by C_Decrypt
    521 		 */
    522 		if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
    523 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
    524 			goto cleanup;
    525 		}
    526 
    527 		/*
    528 		 * If application asks for the length of the output buffer
    529 		 * to hold the plaintext?
    530 		 */
    531 		if (pData == NULL) {
    532 			*pulDataLen = ulEncryptedLen;
    533 			return (CKR_OK);
    534 		}
    535 
    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);
    541 			}
    542 
    543 			/* Set output length same as input length. */
    544 			out_len = ulEncryptedLen;
    545 		} else {
    546 			/*
    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.
    550 			 */
    551 			if (*pulDataLen < (ulEncryptedLen - DES_BLOCK_LEN)) {
    552 				*pulDataLen = ulEncryptedLen - DES_BLOCK_LEN;
    553 				return (CKR_BUFFER_TOO_SMALL);
    554 			}
    555 			out_len = ulEncryptedLen - DES_BLOCK_LEN;
    556 		}
    557 		in_buf = pEncrypted;
    558 		out_buf = pData;
    559 	} else {
    560 		/*
    561 		 *  Called by C_DecryptUpdate
    562 		 *
    563 		 * Add the lengths of last remaining data and current
    564 		 * input data together to get the total input length.
    565 		 */
    566 		total_len = soft_des_ctx->remain_len + ulEncryptedLen;
    567 
    568 		/*
    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.
    574 		 */
    575 		if ((total_len < DES_BLOCK_LEN) ||
    576 		    (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
    577 			if (pEncrypted != NULL) {
    578 				/*
    579 				 * Save input data and its length in
    580 				 * the remaining buffer of DES context.
    581 				 */
    582 				(void) memcpy(soft_des_ctx->data +
    583 				    soft_des_ctx->remain_len,
    584 				    pEncrypted, ulEncryptedLen);
    585 				soft_des_ctx->remain_len += ulEncryptedLen;
    586 			}
    587 
    588 			/* Set output data length to 0. */
    589 			*pulDataLen = 0;
    590 			return (CKR_OK);
    591 		}
    592 
    593 		/* Compute the length of remaing data. */
    594 		remain = total_len % DES_BLOCK_LEN;
    595 
    596 		/*
    597 		 * Make sure that the output length is a multiple of
    598 		 * blocksize.
    599 		 */
    600 		out_len = total_len - remain;
    601 
    602 		if (pad_mechanism) {
    603 			/*
    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.
    608 			 */
    609 			if (remain == 0) {
    610 				remain = DES_BLOCK_LEN;
    611 				out_len -= DES_BLOCK_LEN;
    612 			}
    613 		}
    614 
    615 		/*
    616 		 * If application asks for the length of the output buffer
    617 		 * to hold the plaintext?
    618 		 */
    619 		if (pData == NULL) {
    620 			*pulDataLen = out_len;
    621 			return (CKR_OK);
    622 		}
    623 
    624 		/*
    625 		 * Is the application-supplied buffer large enough?
    626 		 */
    627 		if (*pulDataLen < out_len) {
    628 			*pulDataLen = out_len;
    629 			return (CKR_BUFFER_TOO_SMALL);
    630 		}
    631 
    632 		if (soft_des_ctx->remain_len != 0) {
    633 			/*
    634 			 * Copy last remaining data and current input data
    635 			 * to the output buffer.
    636 			 */
    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);
    642 
    643 			in_buf = pData;
    644 		} else {
    645 			in_buf = pEncrypted;
    646 		}
    647 		out_buf = pData;
    648 	}
    649 
    650 	/*
    651 	 * Begin Decryption.
    652 	 */
    653 	switch (mechanism) {
    654 
    655 	case CKM_DES_ECB:
    656 	case CKM_DES3_ECB:
    657 	{
    658 		uint8_t *tmp_inbuf;
    659 		uint8_t *tmp_outbuf;
    660 		ulong_t i;
    661 
    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);
    670 			else
    671 				(void) des3_crunch_block(
    672 				    soft_des_ctx->key_sched,
    673 				    tmp_inbuf, tmp_outbuf, B_TRUE);
    674 		}
    675 
    676 		if (update) {
    677 			/*
    678 			 * For decrypt update, if there is remaining
    679 			 * data, save it and its length in the context.
    680 			 */
    681 			if (remain != 0)
    682 				(void) memcpy(soft_des_ctx->data, pEncrypted +
    683 				    (ulEncryptedLen - remain), remain);
    684 			soft_des_ctx->remain_len = remain;
    685 		}
    686 
    687 		*pulDataLen = out_len;
    688 		break;
    689 	}
    690 
    691 	case CKM_DES_CBC:
    692 	case CKM_DES_CBC_PAD:
    693 	case CKM_DES3_CBC:
    694 	case CKM_DES3_CBC_PAD:
    695 	{
    696 		crypto_data_t out;
    697 		CK_ULONG rem_len;
    698 		uint8_t last_block[DES_BLOCK_LEN];
    699 
    700 		out.cd_format =  CRYPTO_DATA_RAW;
    701 		out.cd_offset = 0;
    702 		out.cd_length = out_len;
    703 		out.cd_raw.iov_base = (char *)out_buf;
    704 		out.cd_raw.iov_len = out_len;
    705 
    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);
    710 
    711 		if (rc != 0)
    712 			goto decrypt_failed;
    713 
    714 		if (pad_mechanism && !update) {
    715 			/* Decrypt last block containing pad bytes. */
    716 			out.cd_offset = 0;
    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;
    720 
    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);
    725 
    726 			if (rc != 0)
    727 				goto decrypt_failed;
    728 
    729 			/*
    730 			 * Remove padding bytes after decryption of
    731 			 * ciphertext block to produce the original
    732 			 * plaintext.
    733 			 */
    734 			rv = soft_remove_pkcs7_padding(last_block,
    735 			    DES_BLOCK_LEN, &rem_len, DES_BLOCK_LEN);
    736 			if (rv == CKR_OK) {
    737 				if (rem_len != 0)
    738 					(void) memcpy(out_buf + out_len,
    739 					    last_block, rem_len);
    740 				*pulDataLen = out_len + rem_len;
    741 			} else {
    742 				*pulDataLen = 0;
    743 				goto cleanup;
    744 			}
    745 		} else {
    746 			*pulDataLen = out_len;
    747 		}
    748 
    749 		if (update) {
    750 			/*
    751 			 * For decrypt update, if there is remaining data,
    752 			 * save it and its length in the context.
    753 			 */
    754 			if (remain != 0)
    755 				(void) memcpy(soft_des_ctx->data, pEncrypted +
    756 				    (ulEncryptedLen - remain), remain);
    757 			soft_des_ctx->remain_len = remain;
    758 		}
    759 
    760 		if (rc == 0)
    761 			break;
    762 decrypt_failed:
    763 		*pulDataLen = 0;
    764 		rv = CKR_FUNCTION_FAILED;
    765 		goto cleanup;
    766 	}
    767 	} /* end switch */
    768 
    769 	if (update)
    770 		return (CKR_OK);
    771 
    772 	/*
    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.
    776 	 */
    777 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);
    783 	}
    784 
    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);
    790 
    791 	return (rv);
    792 }
    793 
    794 
    795 /*
    796  * Allocate and initialize a context for DES CBC mode of operation.
    797  */
    798 void *
    799 des_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec, CK_KEY_TYPE type)
    800 {
    801 
    802 	cbc_ctx_t *cbc_ctx;
    803 
    804 	if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
    805 		return (NULL);
    806 
    807 	cbc_ctx->cbc_keysched = key_sched;
    808 
    809 	(void) memcpy(&cbc_ctx->cbc_iv[0], ivec, DES_BLOCK_LEN);
    810 
    811 	cbc_ctx->cbc_lastp = (uint8_t *)&cbc_ctx->cbc_iv[0];
    812 	cbc_ctx->cbc_keysched_len = size;
    813 	if (type == CKK_DES)
    814 		cbc_ctx->cbc_flags |= CBC_MODE;
    815 	else
    816 		cbc_ctx->cbc_flags |= CBC_MODE | DES3_STRENGTH;
    817 
    818 	return (cbc_ctx);
    819 
    820 }
    821 
    822 /*
    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.
    826  */
    827 CK_RV
    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)
    830 {
    831 	soft_des_ctx_t	*soft_des_ctx;
    832 	CK_MECHANISM	encrypt_mech;
    833 	CK_RV rv;
    834 
    835 	if ((key_p->class != CKO_SECRET_KEY) || (key_p->key_type != CKK_DES)) {
    836 		return (CKR_KEY_TYPE_INCONSISTENT);
    837 	}
    838 
    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);
    843 	}
    844 
    845 	soft_des_ctx->key_type = key_p->key_type;
    846 
    847 	/* initialization vector is zero for DES MAC */
    848 	bzero(soft_des_ctx->ivec, DES_BLOCK_LEN);
    849 
    850 	switch (pMechanism->mechanism) {
    851 
    852 	case CKM_DES_MAC_GENERAL:
    853 
    854 		if (pMechanism->ulParameterLen !=
    855 		    sizeof (CK_MAC_GENERAL_PARAMS)) {
    856 			free(soft_des_ctx);
    857 			return (CKR_MECHANISM_PARAM_INVALID);
    858 		}
    859 
    860 		if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
    861 		    DES_BLOCK_LEN) {
    862 			free(soft_des_ctx);
    863 			return (CKR_MECHANISM_PARAM_INVALID);
    864 		}
    865 
    866 		soft_des_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
    867 		    pMechanism->pParameter);
    868 
    869 		/*FALLTHRU*/
    870 	case CKM_DES_MAC:
    871 
    872 		/*
    873 		 * For non-general DES MAC, output is always half as
    874 		 * large as block size
    875 		 */
    876 		if (pMechanism->mechanism == CKM_DES_MAC) {
    877 			soft_des_ctx->mac_len = DES_MAC_LEN;
    878 		}
    879 
    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,
    885 		    key_p);
    886 		if (rv != CKR_OK) {
    887 			free(soft_des_ctx);
    888 			return (rv);
    889 		}
    890 
    891 		(void) pthread_mutex_lock(&session_p->session_mutex);
    892 
    893 		if (sign_op) {
    894 			session_p->sign.context = soft_des_ctx;
    895 			session_p->sign.mech.mechanism = pMechanism->mechanism;
    896 		} else {
    897 			session_p->verify.context = soft_des_ctx;
    898 			session_p->verify.mech.mechanism =
    899 			    pMechanism->mechanism;
    900 		}
    901 
    902 		(void) pthread_mutex_unlock(&session_p->session_mutex);
    903 
    904 		break;
    905 	}
    906 	return (CKR_OK);
    907 }
    908 
    909 /*
    910  * Called by soft_sign(), soft_sign_final(), soft_verify() or
    911  * soft_verify_final().
    912  */
    913 CK_RV
    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)
    917 {
    918 	soft_des_ctx_t		*soft_des_ctx_sign_verify;
    919 	soft_des_ctx_t		*soft_des_ctx_encrypt;
    920 	CK_RV			rv;
    921 	CK_BYTE			*pEncrypted = NULL;
    922 	CK_ULONG		ulEncryptedLen = 0;
    923 	uint8_t			remainder;
    924 	CK_BYTE			last_block[DES_BLOCK_LEN];
    925 	des_ctx_t		*des_ctx = NULL;
    926 
    927 	if (sign_op) {
    928 		soft_des_ctx_sign_verify =
    929 		    (soft_des_ctx_t *)session_p->sign.context;
    930 
    931 		if (soft_des_ctx_sign_verify->mac_len == 0) {
    932 			*pulSignedLen = 0;
    933 			goto clean_exit;
    934 		}
    935 
    936 		/* Application asks for the length of the output buffer. */
    937 		if (pSigned == NULL) {
    938 			*pulSignedLen = soft_des_ctx_sign_verify->mac_len;
    939 			return (CKR_OK);
    940 		}
    941 
    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);
    946 		}
    947 	} else {
    948 		soft_des_ctx_sign_verify =
    949 		    (soft_des_ctx_t *)session_p->verify.context;
    950 	}
    951 
    952 	if (Final) {
    953 		soft_des_ctx_encrypt =
    954 		    (soft_des_ctx_t *)session_p->encrypt.context;
    955 
    956 		/*
    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
    960 		 */
    961 		if (soft_des_ctx_encrypt->remain_len != 0) {
    962 			bzero(last_block, DES_BLOCK_LEN);
    963 			ulEncryptedLen = DES_BLOCK_LEN;
    964 
    965 			/*
    966 			 * By passing a buffer to soft_encrypt_final,
    967 			 * we force it to pad the remaining block
    968 			 * and encrypt it.
    969 			 */
    970 			rv = soft_encrypt_final(session_p, last_block,
    971 			    &ulEncryptedLen);
    972 			if (rv != CKR_OK) {
    973 				goto clean_exit;
    974 			}
    975 		} else {
    976 			/*
    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
    980 			 */
    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,
    985 			    DES_BLOCK_LEN);
    986 
    987 			/*
    988 			 * Passing a NULL output buffer here
    989 			 * forces the routine to just return.
    990 			 */
    991 			rv = soft_encrypt_final(session_p, NULL,
    992 			    &ulEncryptedLen);
    993 		}
    994 
    995 	} else {
    996 		/*
    997 		 * If the input length is not multiple of block size, then
    998 		 * determine the correct encrypted data length by rounding
    999 		 */
   1000 		remainder = ulDataLen % DES_BLOCK_LEN;
   1001 		/*
   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.
   1006 		 */
   1007 		ulEncryptedLen = ulDataLen + (DES_BLOCK_LEN - remainder);
   1008 
   1009 		pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
   1010 		if (pEncrypted == NULL) {
   1011 			rv = CKR_HOST_MEMORY;
   1012 			goto clean_exit;
   1013 		}
   1014 
   1015 		/*
   1016 		 * Pad the last block with zeros by copying pData into a zeroed
   1017 		 * pEncrypted. Then pass pEncrypted into soft_encrypt as input
   1018 		 */
   1019 		bzero(pEncrypted, ulEncryptedLen);
   1020 		(void) memcpy(pEncrypted, pData, ulDataLen);
   1021 
   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);
   1026 	}
   1027 
   1028 	if (rv == CKR_OK) {
   1029 		*pulSignedLen = soft_des_ctx_sign_verify->mac_len;
   1030 
   1031 		/* the leftmost mac_len bytes of last_block is our MAC */
   1032 		(void) memcpy(pSigned, last_block, *pulSignedLen);
   1033 	}
   1034 
   1035 clean_exit:
   1036 
   1037 	(void) pthread_mutex_lock(&session_p->session_mutex);
   1038 
   1039 	/* soft_encrypt_common() has freed the encrypt context */
   1040 	if (sign_op) {
   1041 		free(session_p->sign.context);
   1042 		session_p->sign.context = NULL;
   1043 	} else {
   1044 		free(session_p->verify.context);
   1045 		session_p->verify.context = NULL;
   1046 	}
   1047 	session_p->encrypt.flags = 0;
   1048 
   1049 	(void) pthread_mutex_unlock(&session_p->session_mutex);
   1050 
   1051 	if (pEncrypted) {
   1052 		free(pEncrypted);
   1053 	}
   1054 
   1055 	return (rv);
   1056 }
   1057 
   1058 /*
   1059  * Called by soft_sign_update()
   1060  */
   1061 CK_RV
   1062 soft_des_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
   1063 	CK_ULONG ulPartLen)
   1064 {
   1065 	/*
   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.
   1074 	 */
   1075 
   1076 	soft_des_ctx_t	*soft_des_ctx_encrypt;
   1077 	CK_BYTE		*pEncrypted = NULL;
   1078 	CK_ULONG	ulEncryptedLen;
   1079 	CK_ULONG	total_len;
   1080 	uint8_t		remainder;
   1081 	CK_RV		rv;
   1082 
   1083 	soft_des_ctx_encrypt = (soft_des_ctx_t *)session_p->encrypt.context;
   1084 
   1085 	/* Avoid the malloc if we won't be encrypting any data */
   1086 	total_len = soft_des_ctx_encrypt->remain_len + ulPartLen;
   1087 
   1088 	if (total_len < DES_BLOCK_LEN) {
   1089 		rv = soft_encrypt_update(session_p, pPart, ulPartLen, NULL,
   1090 		    &ulEncryptedLen);
   1091 	} else {
   1092 		remainder = ulPartLen % DES_BLOCK_LEN;
   1093 
   1094 		/* round up to the nearest multiple of block size */
   1095 		ulEncryptedLen = ulPartLen + (DES_BLOCK_LEN - remainder);
   1096 		pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
   1097 
   1098 		if (pEncrypted != NULL) {
   1099 			rv = soft_encrypt_update(session_p, pPart, ulPartLen,
   1100 			    pEncrypted, &ulEncryptedLen);
   1101 			free(pEncrypted);
   1102 		} else {
   1103 			rv = CKR_HOST_MEMORY;
   1104 		}
   1105 	}
   1106 	return (rv);
   1107 }
   1108