17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
59627968bSmcpowers * Common Development and Distribution License (the "License").
69627968bSmcpowers * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21726fad2aSDina K Nimeh
227c478bd9Sstevel@tonic-gate /*
23726fad2aSDina K Nimeh * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*a8793c76SJason King * Copyright (c) 2018, Joyent, Inc.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include <pthread.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <strings.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
3323c57df7Smcpowers #include <modes/modes.h>
347c478bd9Sstevel@tonic-gate #include <des_impl.h>
357c478bd9Sstevel@tonic-gate #include "softSession.h"
367c478bd9Sstevel@tonic-gate #include "softObject.h"
377c478bd9Sstevel@tonic-gate #include "softCrypt.h"
387c478bd9Sstevel@tonic-gate #include "softOps.h"
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate * Allocate context for the active encryption or decryption operation, and
427c478bd9Sstevel@tonic-gate * generate DES or DES3 key schedule to speed up the operation.
437c478bd9Sstevel@tonic-gate */
447c478bd9Sstevel@tonic-gate CK_RV
soft_des_crypt_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t encrypt)457c478bd9Sstevel@tonic-gate soft_des_crypt_init_common(soft_session_t *session_p,
467c478bd9Sstevel@tonic-gate CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
477c478bd9Sstevel@tonic-gate boolean_t encrypt)
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate size_t size;
517c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx;
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t));
547c478bd9Sstevel@tonic-gate if (soft_des_ctx == NULL) {
557c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
567c478bd9Sstevel@tonic-gate }
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate /* Allocate key schedule for DES or DES3 based on key type. */
597c478bd9Sstevel@tonic-gate if (key_p->key_type == CKK_DES)
607c478bd9Sstevel@tonic-gate soft_des_ctx->key_sched = des_alloc_keysched(&size, DES, 0);
617c478bd9Sstevel@tonic-gate else
627c478bd9Sstevel@tonic-gate soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0);
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate if (soft_des_ctx->key_sched == NULL) {
657c478bd9Sstevel@tonic-gate free(soft_des_ctx);
667c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate soft_des_ctx->keysched_len = size;
707c478bd9Sstevel@tonic-gate soft_des_ctx->key_type = key_p->key_type;
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
737c478bd9Sstevel@tonic-gate if (encrypt) {
747c478bd9Sstevel@tonic-gate /* Called by C_EncryptInit. */
757c478bd9Sstevel@tonic-gate session_p->encrypt.context = soft_des_ctx;
767c478bd9Sstevel@tonic-gate session_p->encrypt.mech.mechanism = pMechanism->mechanism;
777c478bd9Sstevel@tonic-gate } else {
787c478bd9Sstevel@tonic-gate /* Called by C_DecryptInit. */
797c478bd9Sstevel@tonic-gate session_p->decrypt.context = soft_des_ctx;
807c478bd9Sstevel@tonic-gate session_p->decrypt.mech.mechanism = pMechanism->mechanism;
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate * If this is a non-sensitive key and it does NOT have
867c478bd9Sstevel@tonic-gate * a key schedule yet, then allocate one and expand it.
877c478bd9Sstevel@tonic-gate * Otherwise, if its a non-sensitive key, and it DOES have
887c478bd9Sstevel@tonic-gate * a key schedule already attached to it, just copy the
897c478bd9Sstevel@tonic-gate * pre-expanded schedule to the context and avoid the
907c478bd9Sstevel@tonic-gate * extra key schedule expansion operation.
917c478bd9Sstevel@tonic-gate */
927c478bd9Sstevel@tonic-gate if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
939627968bSmcpowers if (OBJ_KEY_SCHED(key_p) == NULL) {
947c478bd9Sstevel@tonic-gate void *ks;
959627968bSmcpowers (void) pthread_mutex_lock(&key_p->object_mutex);
969627968bSmcpowers if (OBJ_KEY_SCHED(key_p) == NULL) {
979627968bSmcpowers if (key_p->key_type == CKK_DES)
989627968bSmcpowers ks = des_alloc_keysched(&size, DES, 0);
999627968bSmcpowers else
1009627968bSmcpowers ks = des_alloc_keysched(&size, DES3, 0);
1019627968bSmcpowers if (ks == NULL) {
1029627968bSmcpowers (void) pthread_mutex_unlock(
1039627968bSmcpowers &key_p->object_mutex);
1049627968bSmcpowers free(soft_des_ctx);
1059627968bSmcpowers return (CKR_HOST_MEMORY);
1069627968bSmcpowers }
1079627968bSmcpowers /* Initialize key schedule for DES or DES3. */
1089627968bSmcpowers if (key_p->key_type == CKK_DES)
1099627968bSmcpowers des_init_keysched(
1109627968bSmcpowers OBJ_SEC(key_p)->sk_value, DES, ks);
1119627968bSmcpowers else if (key_p->key_type == CKK_DES2)
1129627968bSmcpowers /*
1139627968bSmcpowers * DES3 encryption/decryption needs to
1149627968bSmcpowers * support a DES2 key.
1159627968bSmcpowers */
1169627968bSmcpowers des_init_keysched(
1179627968bSmcpowers OBJ_SEC(key_p)->sk_value, DES2, ks);
1189627968bSmcpowers else
1199627968bSmcpowers des_init_keysched(
1209627968bSmcpowers OBJ_SEC(key_p)->sk_value, DES3, ks);
1219627968bSmcpowers
1229627968bSmcpowers OBJ_KEY_SCHED_LEN(key_p) = size;
1239627968bSmcpowers OBJ_KEY_SCHED(key_p) = ks;
1247c478bd9Sstevel@tonic-gate }
1259627968bSmcpowers (void) pthread_mutex_unlock(&key_p->object_mutex);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate /* Copy the pre-expanded key schedule from the key object */
1297c478bd9Sstevel@tonic-gate (void) memcpy(soft_des_ctx->key_sched, OBJ_KEY_SCHED(key_p),
1309627968bSmcpowers OBJ_KEY_SCHED_LEN(key_p));
1317c478bd9Sstevel@tonic-gate soft_des_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
1327c478bd9Sstevel@tonic-gate } else {
1337c478bd9Sstevel@tonic-gate /* for sensitive keys, we cannot cache the key schedule */
1347c478bd9Sstevel@tonic-gate if (key_p->key_type == CKK_DES)
1357c478bd9Sstevel@tonic-gate des_init_keysched(OBJ_SEC(key_p)->sk_value,
1369627968bSmcpowers DES, soft_des_ctx->key_sched);
1377c478bd9Sstevel@tonic-gate else if (key_p->key_type == CKK_DES2)
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate * DES3 encryption/decryption needs to
1407c478bd9Sstevel@tonic-gate * support a DES2 key.
1417c478bd9Sstevel@tonic-gate */
1427c478bd9Sstevel@tonic-gate des_init_keysched(OBJ_SEC(key_p)->sk_value,
1439627968bSmcpowers DES2, soft_des_ctx->key_sched);
1447c478bd9Sstevel@tonic-gate else
1457c478bd9Sstevel@tonic-gate des_init_keysched(OBJ_SEC(key_p)->sk_value,
1469627968bSmcpowers DES3, soft_des_ctx->key_sched);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate return (CKR_OK);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate * soft_des_encrypt_common()
1557c478bd9Sstevel@tonic-gate *
1567c478bd9Sstevel@tonic-gate * Arguments:
1577c478bd9Sstevel@tonic-gate * session_p: pointer to soft_session_t struct
1587c478bd9Sstevel@tonic-gate * pData: pointer to the input data to be encrypted
1597c478bd9Sstevel@tonic-gate * ulDataLen: length of the input data
1607c478bd9Sstevel@tonic-gate * pEncrypted: pointer to the output data after encryption
1617c478bd9Sstevel@tonic-gate * pulEncryptedLen: pointer to the length of the output data
1627c478bd9Sstevel@tonic-gate * update: boolean flag indicates caller is soft_encrypt
1637c478bd9Sstevel@tonic-gate * or soft_encrypt_update
1647c478bd9Sstevel@tonic-gate *
1657c478bd9Sstevel@tonic-gate * Description:
1667c478bd9Sstevel@tonic-gate * This function calls the corresponding encrypt routine based
1677c478bd9Sstevel@tonic-gate * on the mechanism.
1687c478bd9Sstevel@tonic-gate *
1697c478bd9Sstevel@tonic-gate * Returns:
1707c478bd9Sstevel@tonic-gate * CKR_OK: success
1717c478bd9Sstevel@tonic-gate * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
1727c478bd9Sstevel@tonic-gate * is too small
1737c478bd9Sstevel@tonic-gate * CKR_FUNCTION_FAILED: encrypt function failed
1747c478bd9Sstevel@tonic-gate * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
1757c478bd9Sstevel@tonic-gate */
1767c478bd9Sstevel@tonic-gate CK_RV
soft_des_encrypt_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncrypted,CK_ULONG_PTR pulEncryptedLen,boolean_t update)1777c478bd9Sstevel@tonic-gate soft_des_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
1787c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
1797c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulEncryptedLen, boolean_t update)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate int rc = 0;
1827c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
1837c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx =
1847c478bd9Sstevel@tonic-gate (soft_des_ctx_t *)session_p->encrypt.context;
1857c478bd9Sstevel@tonic-gate des_ctx_t *des_ctx;
1867c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
1877c478bd9Sstevel@tonic-gate CK_BYTE *in_buf = NULL;
1887c478bd9Sstevel@tonic-gate CK_BYTE *out_buf = NULL;
1897c478bd9Sstevel@tonic-gate CK_ULONG out_len;
1907c478bd9Sstevel@tonic-gate CK_ULONG total_len;
1917c478bd9Sstevel@tonic-gate CK_ULONG remain;
1927c478bd9Sstevel@tonic-gate boolean_t pad_mechanism = B_FALSE;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
1957c478bd9Sstevel@tonic-gate mechanism == CKM_DES3_CBC_PAD);
1967c478bd9Sstevel@tonic-gate /*
1977c478bd9Sstevel@tonic-gate * DES only takes input length that is a multiple of blocksize
1987c478bd9Sstevel@tonic-gate * for C_Encrypt function with the mechanism CKM_DES<n>_ECB or
1997c478bd9Sstevel@tonic-gate * CKM_DES<n>_CBC.
2007c478bd9Sstevel@tonic-gate *
2017c478bd9Sstevel@tonic-gate * DES allows any input length for C_Encrypt function with the
2027c478bd9Sstevel@tonic-gate * mechanism CKM_DES<n>_CBC_PAD and for C_EncryptUpdate function.
2037c478bd9Sstevel@tonic-gate */
2047c478bd9Sstevel@tonic-gate if (!update && !pad_mechanism) {
2057c478bd9Sstevel@tonic-gate if ((ulDataLen % DES_BLOCK_LEN) != 0) {
2067c478bd9Sstevel@tonic-gate rv = CKR_DATA_LEN_RANGE;
2077c478bd9Sstevel@tonic-gate goto cleanup;
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate if (!update) {
2127c478bd9Sstevel@tonic-gate /*
2137c478bd9Sstevel@tonic-gate * Called by C_Encrypt
2147c478bd9Sstevel@tonic-gate */
2157c478bd9Sstevel@tonic-gate if (pad_mechanism) {
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate * For CKM_DES<n>_CBC_PAD, compute output length to
2187c478bd9Sstevel@tonic-gate * count for the padding. If the length of input
2197c478bd9Sstevel@tonic-gate * data is a multiple of blocksize, then make output
2207c478bd9Sstevel@tonic-gate * length to be the sum of the input length and
2217c478bd9Sstevel@tonic-gate * one blocksize. Otherwise, output length will
2227c478bd9Sstevel@tonic-gate * be rounded up to the next multiple of blocksize.
2237c478bd9Sstevel@tonic-gate */
2247c478bd9Sstevel@tonic-gate out_len = DES_BLOCK_LEN *
2259627968bSmcpowers (ulDataLen / DES_BLOCK_LEN + 1);
2267c478bd9Sstevel@tonic-gate } else {
2277c478bd9Sstevel@tonic-gate /*
2287c478bd9Sstevel@tonic-gate * For non-padding mode, the output length will
2297c478bd9Sstevel@tonic-gate * be same as the input length.
2307c478bd9Sstevel@tonic-gate */
2317c478bd9Sstevel@tonic-gate out_len = ulDataLen;
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate * If application asks for the length of the output buffer
2367c478bd9Sstevel@tonic-gate * to hold the ciphertext?
2377c478bd9Sstevel@tonic-gate */
2387c478bd9Sstevel@tonic-gate if (pEncrypted == NULL) {
2397c478bd9Sstevel@tonic-gate *pulEncryptedLen = out_len;
2407c478bd9Sstevel@tonic-gate return (CKR_OK);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */
2447c478bd9Sstevel@tonic-gate if (*pulEncryptedLen < out_len) {
2457c478bd9Sstevel@tonic-gate *pulEncryptedLen = out_len;
2467c478bd9Sstevel@tonic-gate return (CKR_BUFFER_TOO_SMALL);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /* Encrypt pad bytes in a separate operation */
2507c478bd9Sstevel@tonic-gate if (pad_mechanism) {
2517c478bd9Sstevel@tonic-gate out_len -= DES_BLOCK_LEN;
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate in_buf = pData;
2557c478bd9Sstevel@tonic-gate out_buf = pEncrypted;
2567c478bd9Sstevel@tonic-gate } else {
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate * Called by C_EncryptUpdate
2597c478bd9Sstevel@tonic-gate *
2607c478bd9Sstevel@tonic-gate * Add the lengths of last remaining data and current
2617c478bd9Sstevel@tonic-gate * plaintext together to get the total input length.
2627c478bd9Sstevel@tonic-gate */
2637c478bd9Sstevel@tonic-gate total_len = soft_des_ctx->remain_len + ulDataLen;
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate /*
2667c478bd9Sstevel@tonic-gate * If the total input length is less than one blocksize,
2677c478bd9Sstevel@tonic-gate * or if the total input length is just one blocksize and
2687c478bd9Sstevel@tonic-gate * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
2697c478bd9Sstevel@tonic-gate * encryption until when more data comes in next
2707c478bd9Sstevel@tonic-gate * C_EncryptUpdate or when C_EncryptFinal is called.
2717c478bd9Sstevel@tonic-gate */
2727c478bd9Sstevel@tonic-gate if ((total_len < DES_BLOCK_LEN) ||
2737c478bd9Sstevel@tonic-gate (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
2747c478bd9Sstevel@tonic-gate if (pData != NULL) {
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate * Save input data and its length in
2777c478bd9Sstevel@tonic-gate * the remaining buffer of DES context.
2787c478bd9Sstevel@tonic-gate */
2797c478bd9Sstevel@tonic-gate (void) memcpy(soft_des_ctx->data +
2807c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len, pData, ulDataLen);
2817c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len += ulDataLen;
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate /* Set encrypted data length to 0. */
2857c478bd9Sstevel@tonic-gate *pulEncryptedLen = 0;
2867c478bd9Sstevel@tonic-gate return (CKR_OK);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate /* Compute the length of remaing data. */
2907c478bd9Sstevel@tonic-gate remain = total_len % DES_BLOCK_LEN;
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate * Make sure that the output length is a multiple of
2947c478bd9Sstevel@tonic-gate * blocksize.
2957c478bd9Sstevel@tonic-gate */
2967c478bd9Sstevel@tonic-gate out_len = total_len - remain;
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate * If application asks for the length of the output buffer
3007c478bd9Sstevel@tonic-gate * to hold the ciphertext?
3017c478bd9Sstevel@tonic-gate */
3027c478bd9Sstevel@tonic-gate if (pEncrypted == NULL) {
3037c478bd9Sstevel@tonic-gate *pulEncryptedLen = out_len;
3047c478bd9Sstevel@tonic-gate return (CKR_OK);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */
3087c478bd9Sstevel@tonic-gate if (*pulEncryptedLen < out_len) {
3097c478bd9Sstevel@tonic-gate *pulEncryptedLen = out_len;
3107c478bd9Sstevel@tonic-gate return (CKR_BUFFER_TOO_SMALL);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate if (soft_des_ctx->remain_len != 0) {
3147c478bd9Sstevel@tonic-gate /*
3157c478bd9Sstevel@tonic-gate * Copy last remaining data and current input data
3167c478bd9Sstevel@tonic-gate * to the output buffer.
3177c478bd9Sstevel@tonic-gate */
3187c478bd9Sstevel@tonic-gate (void) memmove(pEncrypted + soft_des_ctx->remain_len,
3197c478bd9Sstevel@tonic-gate pData, out_len - soft_des_ctx->remain_len);
3207c478bd9Sstevel@tonic-gate (void) memcpy(pEncrypted, soft_des_ctx->data,
3217c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len);
3227c478bd9Sstevel@tonic-gate bzero(soft_des_ctx->data, soft_des_ctx->remain_len);
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate in_buf = pEncrypted;
3257c478bd9Sstevel@tonic-gate } else {
3267c478bd9Sstevel@tonic-gate in_buf = pData;
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate out_buf = pEncrypted;
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate * Begin Encryption now.
3337c478bd9Sstevel@tonic-gate */
3347c478bd9Sstevel@tonic-gate switch (mechanism) {
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate case CKM_DES_ECB:
3377c478bd9Sstevel@tonic-gate case CKM_DES3_ECB:
3387c478bd9Sstevel@tonic-gate {
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate ulong_t i;
3417c478bd9Sstevel@tonic-gate uint8_t *tmp_inbuf;
3427c478bd9Sstevel@tonic-gate uint8_t *tmp_outbuf;
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
3457c478bd9Sstevel@tonic-gate tmp_inbuf = &in_buf[i];
3467c478bd9Sstevel@tonic-gate tmp_outbuf = &out_buf[i];
3477c478bd9Sstevel@tonic-gate /* Crunch one block of data for DES. */
3487c478bd9Sstevel@tonic-gate if (soft_des_ctx->key_type == CKK_DES)
34923c57df7Smcpowers (void) des_crunch_block(
35023c57df7Smcpowers soft_des_ctx->key_sched,
3517c478bd9Sstevel@tonic-gate tmp_inbuf, tmp_outbuf, B_FALSE);
3527c478bd9Sstevel@tonic-gate else
35323c57df7Smcpowers (void) des3_crunch_block(
35423c57df7Smcpowers soft_des_ctx->key_sched,
3557c478bd9Sstevel@tonic-gate tmp_inbuf, tmp_outbuf, B_FALSE);
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate if (update) {
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate * For encrypt update, if there is remaining
3617c478bd9Sstevel@tonic-gate * data, save it and its length in the context.
3627c478bd9Sstevel@tonic-gate */
3637c478bd9Sstevel@tonic-gate if (remain != 0)
3647c478bd9Sstevel@tonic-gate (void) memcpy(soft_des_ctx->data, pData +
3657c478bd9Sstevel@tonic-gate (ulDataLen - remain), remain);
3667c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len = remain;
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate *pulEncryptedLen = out_len;
3707c478bd9Sstevel@tonic-gate break;
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate case CKM_DES_CBC:
3747c478bd9Sstevel@tonic-gate case CKM_DES_CBC_PAD:
3757c478bd9Sstevel@tonic-gate case CKM_DES3_CBC:
3767c478bd9Sstevel@tonic-gate case CKM_DES3_CBC_PAD:
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate crypto_data_t out;
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate out.cd_format = CRYPTO_DATA_RAW;
3817c478bd9Sstevel@tonic-gate out.cd_offset = 0;
3827c478bd9Sstevel@tonic-gate out.cd_length = out_len;
3837c478bd9Sstevel@tonic-gate out.cd_raw.iov_base = (char *)out_buf;
3847c478bd9Sstevel@tonic-gate out.cd_raw.iov_len = out_len;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate /* Encrypt multiple blocks of data. */
3877c478bd9Sstevel@tonic-gate rc = des_encrypt_contiguous_blocks(
3887c478bd9Sstevel@tonic-gate (des_ctx_t *)soft_des_ctx->des_cbc,
3897c478bd9Sstevel@tonic-gate (char *)in_buf, out_len, &out);
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate if (rc != 0)
3927c478bd9Sstevel@tonic-gate goto encrypt_failed;
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate if (update) {
3957c478bd9Sstevel@tonic-gate /*
3967c478bd9Sstevel@tonic-gate * For encrypt update, if there is remaining data,
3977c478bd9Sstevel@tonic-gate * save it and its length in the context.
3987c478bd9Sstevel@tonic-gate */
3997c478bd9Sstevel@tonic-gate if (remain != 0)
4007c478bd9Sstevel@tonic-gate (void) memcpy(soft_des_ctx->data, pData +
4017c478bd9Sstevel@tonic-gate (ulDataLen - remain), remain);
4027c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len = remain;
4037c478bd9Sstevel@tonic-gate } else if (pad_mechanism) {
4047c478bd9Sstevel@tonic-gate /*
4057c478bd9Sstevel@tonic-gate * Save the remainder of the input
4067c478bd9Sstevel@tonic-gate * block in a temporary block because
4077c478bd9Sstevel@tonic-gate * we don't want to overrun the input buffer
4087c478bd9Sstevel@tonic-gate * by tacking on pad bytes.
4097c478bd9Sstevel@tonic-gate */
4107c478bd9Sstevel@tonic-gate CK_BYTE tmpblock[DES_BLOCK_LEN];
4117c478bd9Sstevel@tonic-gate (void) memcpy(tmpblock, in_buf + out_len,
4129627968bSmcpowers ulDataLen - out_len);
4137c478bd9Sstevel@tonic-gate soft_add_pkcs7_padding(tmpblock +
4149627968bSmcpowers (ulDataLen - out_len),
4159627968bSmcpowers DES_BLOCK_LEN, ulDataLen - out_len);
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate out.cd_offset = out_len;
4187c478bd9Sstevel@tonic-gate out.cd_length = DES_BLOCK_LEN;
4197c478bd9Sstevel@tonic-gate out.cd_raw.iov_base = (char *)out_buf;
4207c478bd9Sstevel@tonic-gate out.cd_raw.iov_len = out_len + DES_BLOCK_LEN;
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /* Encrypt last block containing pad bytes. */
4237c478bd9Sstevel@tonic-gate rc = des_encrypt_contiguous_blocks(
4247c478bd9Sstevel@tonic-gate (des_ctx_t *)soft_des_ctx->des_cbc,
4257c478bd9Sstevel@tonic-gate (char *)tmpblock, DES_BLOCK_LEN, &out);
4267c478bd9Sstevel@tonic-gate out_len += DES_BLOCK_LEN;
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate if (rc == 0) {
4307c478bd9Sstevel@tonic-gate *pulEncryptedLen = out_len;
4317c478bd9Sstevel@tonic-gate break;
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate encrypt_failed:
4347c478bd9Sstevel@tonic-gate *pulEncryptedLen = 0;
4357c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
4367c478bd9Sstevel@tonic-gate goto cleanup;
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate } /* end switch */
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate if (update)
4427c478bd9Sstevel@tonic-gate return (CKR_OK);
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate /*
4457c478bd9Sstevel@tonic-gate * The following code will be executed if the caller is
4467c478bd9Sstevel@tonic-gate * soft_encrypt() or an error occurred. The encryption
4477c478bd9Sstevel@tonic-gate * operation will be terminated so we need to do some cleanup.
4487c478bd9Sstevel@tonic-gate */
4497c478bd9Sstevel@tonic-gate cleanup:
4507c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
4517c478bd9Sstevel@tonic-gate des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
452*a8793c76SJason King free(des_ctx);
453*a8793c76SJason King freezero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
454*a8793c76SJason King freezero(session_p->encrypt.context, sizeof (soft_des_ctx_t));
4557c478bd9Sstevel@tonic-gate session_p->encrypt.context = NULL;
4567c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate return (rv);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate /*
4637c478bd9Sstevel@tonic-gate * soft_des_decrypt_common()
4647c478bd9Sstevel@tonic-gate *
4657c478bd9Sstevel@tonic-gate * Arguments:
4667c478bd9Sstevel@tonic-gate * session_p: pointer to soft_session_t struct
4677c478bd9Sstevel@tonic-gate * pEncrypted: pointer to the input data to be decrypted
4687c478bd9Sstevel@tonic-gate * ulEncryptedLen: length of the input data
4697c478bd9Sstevel@tonic-gate * pData: pointer to the output data
4707c478bd9Sstevel@tonic-gate * pulDataLen: pointer to the length of the output data
4717c478bd9Sstevel@tonic-gate * Update: boolean flag indicates caller is soft_decrypt
4727c478bd9Sstevel@tonic-gate * or soft_decrypt_update
4737c478bd9Sstevel@tonic-gate *
4747c478bd9Sstevel@tonic-gate * Description:
4757c478bd9Sstevel@tonic-gate * This function calls the corresponding decrypt routine based
4767c478bd9Sstevel@tonic-gate * on the mechanism.
4777c478bd9Sstevel@tonic-gate *
4787c478bd9Sstevel@tonic-gate * Returns:
4797c478bd9Sstevel@tonic-gate * CKR_OK: success
4807c478bd9Sstevel@tonic-gate * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
4817c478bd9Sstevel@tonic-gate * is too small
4827c478bd9Sstevel@tonic-gate * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
4837c478bd9Sstevel@tonic-gate * of blocksize
4847c478bd9Sstevel@tonic-gate * CKR_FUNCTION_FAILED: decrypt function failed
4857c478bd9Sstevel@tonic-gate */
4867c478bd9Sstevel@tonic-gate CK_RV
soft_des_decrypt_common(soft_session_t * session_p,CK_BYTE_PTR pEncrypted,CK_ULONG ulEncryptedLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen,boolean_t update)4877c478bd9Sstevel@tonic-gate soft_des_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
4887c478bd9Sstevel@tonic-gate CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
4897c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulDataLen, boolean_t update)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate int rc = 0;
4937c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
4947c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx =
4957c478bd9Sstevel@tonic-gate (soft_des_ctx_t *)session_p->decrypt.context;
4967c478bd9Sstevel@tonic-gate des_ctx_t *des_ctx;
4977c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
4987c478bd9Sstevel@tonic-gate CK_BYTE *in_buf = NULL;
4997c478bd9Sstevel@tonic-gate CK_BYTE *out_buf = NULL;
5007c478bd9Sstevel@tonic-gate CK_ULONG out_len;
5017c478bd9Sstevel@tonic-gate CK_ULONG total_len;
5027c478bd9Sstevel@tonic-gate CK_ULONG remain;
5037c478bd9Sstevel@tonic-gate boolean_t pad_mechanism = B_FALSE;
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
5067c478bd9Sstevel@tonic-gate mechanism == CKM_DES3_CBC_PAD);
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate * DES only takes input length that is a multiple of 8 bytes
5097c478bd9Sstevel@tonic-gate * for C_Decrypt function with the mechanism CKM_DES<n>_ECB,
5107c478bd9Sstevel@tonic-gate * CKM_DES<n>_CBC or CKM_DES<n>_CBC_PAD.
5117c478bd9Sstevel@tonic-gate *
5127c478bd9Sstevel@tonic-gate * DES allows any input length for C_DecryptUpdate function.
5137c478bd9Sstevel@tonic-gate */
5147c478bd9Sstevel@tonic-gate if (!update) {
5157c478bd9Sstevel@tonic-gate /*
5167c478bd9Sstevel@tonic-gate * Called by C_Decrypt
5177c478bd9Sstevel@tonic-gate */
5187c478bd9Sstevel@tonic-gate if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
5197c478bd9Sstevel@tonic-gate rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
5207c478bd9Sstevel@tonic-gate goto cleanup;
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate /*
5247c478bd9Sstevel@tonic-gate * If application asks for the length of the output buffer
5257c478bd9Sstevel@tonic-gate * to hold the plaintext?
5267c478bd9Sstevel@tonic-gate */
5277c478bd9Sstevel@tonic-gate if (pData == NULL) {
5287c478bd9Sstevel@tonic-gate *pulDataLen = ulEncryptedLen;
5297c478bd9Sstevel@tonic-gate return (CKR_OK);
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */
5337c478bd9Sstevel@tonic-gate if (!pad_mechanism) {
5347c478bd9Sstevel@tonic-gate if (*pulDataLen < ulEncryptedLen) {
5357c478bd9Sstevel@tonic-gate *pulDataLen = ulEncryptedLen;
5367c478bd9Sstevel@tonic-gate return (CKR_BUFFER_TOO_SMALL);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate /* Set output length same as input length. */
5407c478bd9Sstevel@tonic-gate out_len = ulEncryptedLen;
5417c478bd9Sstevel@tonic-gate } else {
5427c478bd9Sstevel@tonic-gate /*
5437c478bd9Sstevel@tonic-gate * For CKM_DES<n>_CBC_PAD, we don't know how
5447c478bd9Sstevel@tonic-gate * many bytes for padding at this time, so
5457c478bd9Sstevel@tonic-gate * we'd assume one block was padded.
5467c478bd9Sstevel@tonic-gate */
5477c478bd9Sstevel@tonic-gate if (*pulDataLen < (ulEncryptedLen - DES_BLOCK_LEN)) {
5487c478bd9Sstevel@tonic-gate *pulDataLen = ulEncryptedLen - DES_BLOCK_LEN;
5497c478bd9Sstevel@tonic-gate return (CKR_BUFFER_TOO_SMALL);
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate out_len = ulEncryptedLen - DES_BLOCK_LEN;
5527c478bd9Sstevel@tonic-gate }
5537c478bd9Sstevel@tonic-gate in_buf = pEncrypted;
5547c478bd9Sstevel@tonic-gate out_buf = pData;
5557c478bd9Sstevel@tonic-gate } else {
5567c478bd9Sstevel@tonic-gate /*
5577c478bd9Sstevel@tonic-gate * Called by C_DecryptUpdate
5587c478bd9Sstevel@tonic-gate *
5597c478bd9Sstevel@tonic-gate * Add the lengths of last remaining data and current
5607c478bd9Sstevel@tonic-gate * input data together to get the total input length.
5617c478bd9Sstevel@tonic-gate */
5627c478bd9Sstevel@tonic-gate total_len = soft_des_ctx->remain_len + ulEncryptedLen;
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate /*
5657c478bd9Sstevel@tonic-gate * If the total input length is less than one blocksize,
5667c478bd9Sstevel@tonic-gate * or if the total input length is just one blocksize and
5677c478bd9Sstevel@tonic-gate * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
5687c478bd9Sstevel@tonic-gate * decryption until when more data comes in next
5697c478bd9Sstevel@tonic-gate * C_DecryptUpdate or when C_DecryptFinal is called.
5707c478bd9Sstevel@tonic-gate */
5717c478bd9Sstevel@tonic-gate if ((total_len < DES_BLOCK_LEN) ||
5727c478bd9Sstevel@tonic-gate (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
5737c478bd9Sstevel@tonic-gate if (pEncrypted != NULL) {
5747c478bd9Sstevel@tonic-gate /*
5757c478bd9Sstevel@tonic-gate * Save input data and its length in
5767c478bd9Sstevel@tonic-gate * the remaining buffer of DES context.
5777c478bd9Sstevel@tonic-gate */
5787c478bd9Sstevel@tonic-gate (void) memcpy(soft_des_ctx->data +
5797c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len,
5807c478bd9Sstevel@tonic-gate pEncrypted, ulEncryptedLen);
5817c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len += ulEncryptedLen;
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate /* Set output data length to 0. */
5857c478bd9Sstevel@tonic-gate *pulDataLen = 0;
5867c478bd9Sstevel@tonic-gate return (CKR_OK);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate /* Compute the length of remaing data. */
5907c478bd9Sstevel@tonic-gate remain = total_len % DES_BLOCK_LEN;
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate /*
5937c478bd9Sstevel@tonic-gate * Make sure that the output length is a multiple of
5947c478bd9Sstevel@tonic-gate * blocksize.
5957c478bd9Sstevel@tonic-gate */
5967c478bd9Sstevel@tonic-gate out_len = total_len - remain;
5977c478bd9Sstevel@tonic-gate
5987c478bd9Sstevel@tonic-gate if (pad_mechanism) {
5997c478bd9Sstevel@tonic-gate /*
6007c478bd9Sstevel@tonic-gate * If the input data length is a multiple of
6017c478bd9Sstevel@tonic-gate * blocksize, then save the last block of input
6027c478bd9Sstevel@tonic-gate * data in the remaining buffer. C_DecryptFinal
6037c478bd9Sstevel@tonic-gate * will handle this last block of data.
6047c478bd9Sstevel@tonic-gate */
6057c478bd9Sstevel@tonic-gate if (remain == 0) {
6067c478bd9Sstevel@tonic-gate remain = DES_BLOCK_LEN;
6077c478bd9Sstevel@tonic-gate out_len -= DES_BLOCK_LEN;
6087c478bd9Sstevel@tonic-gate }
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate /*
6127c478bd9Sstevel@tonic-gate * If application asks for the length of the output buffer
6137c478bd9Sstevel@tonic-gate * to hold the plaintext?
6147c478bd9Sstevel@tonic-gate */
6157c478bd9Sstevel@tonic-gate if (pData == NULL) {
6167c478bd9Sstevel@tonic-gate *pulDataLen = out_len;
6177c478bd9Sstevel@tonic-gate return (CKR_OK);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate /*
6217c478bd9Sstevel@tonic-gate * Is the application-supplied buffer large enough?
6227c478bd9Sstevel@tonic-gate */
6237c478bd9Sstevel@tonic-gate if (*pulDataLen < out_len) {
6247c478bd9Sstevel@tonic-gate *pulDataLen = out_len;
6257c478bd9Sstevel@tonic-gate return (CKR_BUFFER_TOO_SMALL);
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate if (soft_des_ctx->remain_len != 0) {
6297c478bd9Sstevel@tonic-gate /*
6307c478bd9Sstevel@tonic-gate * Copy last remaining data and current input data
6317c478bd9Sstevel@tonic-gate * to the output buffer.
6327c478bd9Sstevel@tonic-gate */
6337c478bd9Sstevel@tonic-gate (void) memmove(pData + soft_des_ctx->remain_len,
6347c478bd9Sstevel@tonic-gate pEncrypted, out_len - soft_des_ctx->remain_len);
6357c478bd9Sstevel@tonic-gate (void) memcpy(pData, soft_des_ctx->data,
6367c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len);
6377c478bd9Sstevel@tonic-gate bzero(soft_des_ctx->data, soft_des_ctx->remain_len);
6387c478bd9Sstevel@tonic-gate
6397c478bd9Sstevel@tonic-gate in_buf = pData;
6407c478bd9Sstevel@tonic-gate } else {
6417c478bd9Sstevel@tonic-gate in_buf = pEncrypted;
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate out_buf = pData;
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate /*
6477c478bd9Sstevel@tonic-gate * Begin Decryption.
6487c478bd9Sstevel@tonic-gate */
6497c478bd9Sstevel@tonic-gate switch (mechanism) {
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate case CKM_DES_ECB:
6527c478bd9Sstevel@tonic-gate case CKM_DES3_ECB:
6537c478bd9Sstevel@tonic-gate {
6547c478bd9Sstevel@tonic-gate uint8_t *tmp_inbuf;
6557c478bd9Sstevel@tonic-gate uint8_t *tmp_outbuf;
6567c478bd9Sstevel@tonic-gate ulong_t i;
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
6597c478bd9Sstevel@tonic-gate tmp_inbuf = &in_buf[i];
6607c478bd9Sstevel@tonic-gate tmp_outbuf = &out_buf[i];
6617c478bd9Sstevel@tonic-gate /* Crunch one block of data for DES. */
6627c478bd9Sstevel@tonic-gate if (soft_des_ctx->key_type == CKK_DES)
66323c57df7Smcpowers (void) des_crunch_block(
66423c57df7Smcpowers soft_des_ctx->key_sched,
6657c478bd9Sstevel@tonic-gate tmp_inbuf, tmp_outbuf, B_TRUE);
6667c478bd9Sstevel@tonic-gate else
66723c57df7Smcpowers (void) des3_crunch_block(
66823c57df7Smcpowers soft_des_ctx->key_sched,
6697c478bd9Sstevel@tonic-gate tmp_inbuf, tmp_outbuf, B_TRUE);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate if (update) {
6737c478bd9Sstevel@tonic-gate /*
6747c478bd9Sstevel@tonic-gate * For decrypt update, if there is remaining
6757c478bd9Sstevel@tonic-gate * data, save it and its length in the context.
6767c478bd9Sstevel@tonic-gate */
6777c478bd9Sstevel@tonic-gate if (remain != 0)
6787c478bd9Sstevel@tonic-gate (void) memcpy(soft_des_ctx->data, pEncrypted +
6797c478bd9Sstevel@tonic-gate (ulEncryptedLen - remain), remain);
6807c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len = remain;
6817c478bd9Sstevel@tonic-gate }
6827c478bd9Sstevel@tonic-gate
6837c478bd9Sstevel@tonic-gate *pulDataLen = out_len;
6847c478bd9Sstevel@tonic-gate break;
6857c478bd9Sstevel@tonic-gate }
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate case CKM_DES_CBC:
6887c478bd9Sstevel@tonic-gate case CKM_DES_CBC_PAD:
6897c478bd9Sstevel@tonic-gate case CKM_DES3_CBC:
6907c478bd9Sstevel@tonic-gate case CKM_DES3_CBC_PAD:
6917c478bd9Sstevel@tonic-gate {
6927c478bd9Sstevel@tonic-gate crypto_data_t out;
6937c478bd9Sstevel@tonic-gate CK_ULONG rem_len;
6947c478bd9Sstevel@tonic-gate uint8_t last_block[DES_BLOCK_LEN];
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate out.cd_format = CRYPTO_DATA_RAW;
6977c478bd9Sstevel@tonic-gate out.cd_offset = 0;
6987c478bd9Sstevel@tonic-gate out.cd_length = out_len;
6997c478bd9Sstevel@tonic-gate out.cd_raw.iov_base = (char *)out_buf;
7007c478bd9Sstevel@tonic-gate out.cd_raw.iov_len = out_len;
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate /* Decrypt multiple blocks of data. */
7037c478bd9Sstevel@tonic-gate rc = des_decrypt_contiguous_blocks(
7047c478bd9Sstevel@tonic-gate (des_ctx_t *)soft_des_ctx->des_cbc,
7057c478bd9Sstevel@tonic-gate (char *)in_buf, out_len, &out);
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate if (rc != 0)
7087c478bd9Sstevel@tonic-gate goto decrypt_failed;
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate if (pad_mechanism && !update) {
7117c478bd9Sstevel@tonic-gate /* Decrypt last block containing pad bytes. */
7127c478bd9Sstevel@tonic-gate out.cd_offset = 0;
7137c478bd9Sstevel@tonic-gate out.cd_length = DES_BLOCK_LEN;
7147c478bd9Sstevel@tonic-gate out.cd_raw.iov_base = (char *)last_block;
7157c478bd9Sstevel@tonic-gate out.cd_raw.iov_len = DES_BLOCK_LEN;
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate /* Decrypt last block containing pad bytes. */
7187c478bd9Sstevel@tonic-gate rc = des_decrypt_contiguous_blocks(
7197c478bd9Sstevel@tonic-gate (des_ctx_t *)soft_des_ctx->des_cbc,
7207c478bd9Sstevel@tonic-gate (char *)in_buf + out_len, DES_BLOCK_LEN, &out);
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate if (rc != 0)
7237c478bd9Sstevel@tonic-gate goto decrypt_failed;
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate /*
7267c478bd9Sstevel@tonic-gate * Remove padding bytes after decryption of
7277c478bd9Sstevel@tonic-gate * ciphertext block to produce the original
7287c478bd9Sstevel@tonic-gate * plaintext.
7297c478bd9Sstevel@tonic-gate */
7307c478bd9Sstevel@tonic-gate rv = soft_remove_pkcs7_padding(last_block,
731726fad2aSDina K Nimeh DES_BLOCK_LEN, &rem_len);
7327c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
7337c478bd9Sstevel@tonic-gate if (rem_len != 0)
7347c478bd9Sstevel@tonic-gate (void) memcpy(out_buf + out_len,
7359627968bSmcpowers last_block, rem_len);
7367c478bd9Sstevel@tonic-gate *pulDataLen = out_len + rem_len;
7377c478bd9Sstevel@tonic-gate } else {
7387c478bd9Sstevel@tonic-gate *pulDataLen = 0;
7397c478bd9Sstevel@tonic-gate goto cleanup;
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate } else {
7427c478bd9Sstevel@tonic-gate *pulDataLen = out_len;
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate if (update) {
7467c478bd9Sstevel@tonic-gate /*
7477c478bd9Sstevel@tonic-gate * For decrypt update, if there is remaining data,
7487c478bd9Sstevel@tonic-gate * save it and its length in the context.
7497c478bd9Sstevel@tonic-gate */
7507c478bd9Sstevel@tonic-gate if (remain != 0)
7517c478bd9Sstevel@tonic-gate (void) memcpy(soft_des_ctx->data, pEncrypted +
7527c478bd9Sstevel@tonic-gate (ulEncryptedLen - remain), remain);
7537c478bd9Sstevel@tonic-gate soft_des_ctx->remain_len = remain;
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate if (rc == 0)
7577c478bd9Sstevel@tonic-gate break;
7587c478bd9Sstevel@tonic-gate decrypt_failed:
7597c478bd9Sstevel@tonic-gate *pulDataLen = 0;
7607c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
7617c478bd9Sstevel@tonic-gate goto cleanup;
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate } /* end switch */
7647c478bd9Sstevel@tonic-gate
7657c478bd9Sstevel@tonic-gate if (update)
7667c478bd9Sstevel@tonic-gate return (CKR_OK);
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate /*
7697c478bd9Sstevel@tonic-gate * The following code will be executed if the caller is
7707c478bd9Sstevel@tonic-gate * soft_decrypt() or an error occurred. The decryption
7717c478bd9Sstevel@tonic-gate * operation will be terminated so we need to do some cleanup.
7727c478bd9Sstevel@tonic-gate */
7737c478bd9Sstevel@tonic-gate cleanup:
7747c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
7757c478bd9Sstevel@tonic-gate des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
776*a8793c76SJason King free(des_ctx);
777*a8793c76SJason King freezero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
778*a8793c76SJason King freezero(session_p->decrypt.context, sizeof (soft_des_ctx_t));
7797c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate return (rv);
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate * Allocate and initialize a context for DES CBC mode of operation.
7877c478bd9Sstevel@tonic-gate */
7887c478bd9Sstevel@tonic-gate void *
des_cbc_ctx_init(void * key_sched,size_t size,uint8_t * ivec,CK_KEY_TYPE type)7897c478bd9Sstevel@tonic-gate des_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec, CK_KEY_TYPE type)
7907c478bd9Sstevel@tonic-gate {
7917c478bd9Sstevel@tonic-gate
79223c57df7Smcpowers cbc_ctx_t *cbc_ctx;
7937c478bd9Sstevel@tonic-gate
79423c57df7Smcpowers if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
7957c478bd9Sstevel@tonic-gate return (NULL);
7967c478bd9Sstevel@tonic-gate
79716239bc8SMark Powers cbc_ctx->cbc_keysched = key_sched;
7987c478bd9Sstevel@tonic-gate
79916239bc8SMark Powers (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, DES_BLOCK_LEN);
8007c478bd9Sstevel@tonic-gate
80116239bc8SMark Powers cbc_ctx->cbc_lastp = (uint8_t *)&cbc_ctx->cbc_iv[0];
80216239bc8SMark Powers cbc_ctx->cbc_keysched_len = size;
8037c478bd9Sstevel@tonic-gate if (type == CKK_DES)
80416239bc8SMark Powers cbc_ctx->cbc_flags |= CBC_MODE;
8057c478bd9Sstevel@tonic-gate else
80616239bc8SMark Powers cbc_ctx->cbc_flags |= CBC_MODE | DES3_STRENGTH;
8077c478bd9Sstevel@tonic-gate
80823c57df7Smcpowers return (cbc_ctx);
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate /*
8137c478bd9Sstevel@tonic-gate * Allocate and initialize DES contexts for both signing and encrypting,
8147c478bd9Sstevel@tonic-gate * saving both context pointers in the session struct. For general-length DES
8157c478bd9Sstevel@tonic-gate * MAC, check the length in the parameter to see if it is in the right range.
8167c478bd9Sstevel@tonic-gate */
8177c478bd9Sstevel@tonic-gate CK_RV
soft_des_sign_verify_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t sign_op)8187c478bd9Sstevel@tonic-gate soft_des_sign_verify_init_common(soft_session_t *session_p,
819*a8793c76SJason King CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op)
8207c478bd9Sstevel@tonic-gate {
8217c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx;
8227c478bd9Sstevel@tonic-gate CK_MECHANISM encrypt_mech;
8237c478bd9Sstevel@tonic-gate CK_RV rv;
8247c478bd9Sstevel@tonic-gate
8259627968bSmcpowers if ((key_p->class != CKO_SECRET_KEY) || (key_p->key_type != CKK_DES)) {
8267c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
8277c478bd9Sstevel@tonic-gate }
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate /* allocate memory for the sign/verify context */
8307c478bd9Sstevel@tonic-gate soft_des_ctx = malloc(sizeof (soft_des_ctx_t));
8317c478bd9Sstevel@tonic-gate if (soft_des_ctx == NULL) {
8327c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
8337c478bd9Sstevel@tonic-gate }
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate soft_des_ctx->key_type = key_p->key_type;
8367c478bd9Sstevel@tonic-gate
8377c478bd9Sstevel@tonic-gate /* initialization vector is zero for DES MAC */
8387c478bd9Sstevel@tonic-gate bzero(soft_des_ctx->ivec, DES_BLOCK_LEN);
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate switch (pMechanism->mechanism) {
8417c478bd9Sstevel@tonic-gate
8427c478bd9Sstevel@tonic-gate case CKM_DES_MAC_GENERAL:
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate if (pMechanism->ulParameterLen !=
8459627968bSmcpowers sizeof (CK_MAC_GENERAL_PARAMS)) {
8467c478bd9Sstevel@tonic-gate free(soft_des_ctx);
8477c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID);
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
8519627968bSmcpowers DES_BLOCK_LEN) {
8527c478bd9Sstevel@tonic-gate free(soft_des_ctx);
8537c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID);
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate soft_des_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
8579627968bSmcpowers pMechanism->pParameter);
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate /*FALLTHRU*/
8607c478bd9Sstevel@tonic-gate case CKM_DES_MAC:
8617c478bd9Sstevel@tonic-gate
8627c478bd9Sstevel@tonic-gate /*
8637c478bd9Sstevel@tonic-gate * For non-general DES MAC, output is always half as
8647c478bd9Sstevel@tonic-gate * large as block size
8657c478bd9Sstevel@tonic-gate */
8667c478bd9Sstevel@tonic-gate if (pMechanism->mechanism == CKM_DES_MAC) {
8677c478bd9Sstevel@tonic-gate soft_des_ctx->mac_len = DES_MAC_LEN;
8687c478bd9Sstevel@tonic-gate }
8697c478bd9Sstevel@tonic-gate
8707c478bd9Sstevel@tonic-gate /* allocate a context for DES encryption */
8717c478bd9Sstevel@tonic-gate encrypt_mech.mechanism = CKM_DES_CBC_PAD;
8727c478bd9Sstevel@tonic-gate encrypt_mech.pParameter = (void *)soft_des_ctx->ivec;
8737c478bd9Sstevel@tonic-gate encrypt_mech.ulParameterLen = DES_BLOCK_LEN;
8747c478bd9Sstevel@tonic-gate rv = soft_encrypt_init_internal(session_p, &encrypt_mech,
8759627968bSmcpowers key_p);
8767c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
8777c478bd9Sstevel@tonic-gate free(soft_des_ctx);
8787c478bd9Sstevel@tonic-gate return (rv);
8797c478bd9Sstevel@tonic-gate }
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate if (sign_op) {
8847c478bd9Sstevel@tonic-gate session_p->sign.context = soft_des_ctx;
8857c478bd9Sstevel@tonic-gate session_p->sign.mech.mechanism = pMechanism->mechanism;
8867c478bd9Sstevel@tonic-gate } else {
8877c478bd9Sstevel@tonic-gate session_p->verify.context = soft_des_ctx;
8887c478bd9Sstevel@tonic-gate session_p->verify.mech.mechanism =
8899627968bSmcpowers pMechanism->mechanism;
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate
8927c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate break;
8957c478bd9Sstevel@tonic-gate }
8967c478bd9Sstevel@tonic-gate return (CKR_OK);
8977c478bd9Sstevel@tonic-gate }
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate /*
9007c478bd9Sstevel@tonic-gate * Called by soft_sign(), soft_sign_final(), soft_verify() or
9017c478bd9Sstevel@tonic-gate * soft_verify_final().
9027c478bd9Sstevel@tonic-gate */
9037c478bd9Sstevel@tonic-gate CK_RV
soft_des_sign_verify_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSigned,CK_ULONG_PTR pulSignedLen,boolean_t sign_op,boolean_t Final)9047c478bd9Sstevel@tonic-gate soft_des_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
905*a8793c76SJason King CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
906*a8793c76SJason King boolean_t sign_op, boolean_t Final)
9077c478bd9Sstevel@tonic-gate {
9087c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx_sign_verify;
9097c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx_encrypt;
9107c478bd9Sstevel@tonic-gate CK_RV rv;
9117c478bd9Sstevel@tonic-gate CK_BYTE *pEncrypted = NULL;
9127c478bd9Sstevel@tonic-gate CK_ULONG ulEncryptedLen = 0;
9137c478bd9Sstevel@tonic-gate uint8_t remainder;
9147c478bd9Sstevel@tonic-gate CK_BYTE last_block[DES_BLOCK_LEN];
9157c478bd9Sstevel@tonic-gate des_ctx_t *des_ctx = NULL;
9167c478bd9Sstevel@tonic-gate
9177c478bd9Sstevel@tonic-gate if (sign_op) {
9187c478bd9Sstevel@tonic-gate soft_des_ctx_sign_verify =
9199627968bSmcpowers (soft_des_ctx_t *)session_p->sign.context;
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate if (soft_des_ctx_sign_verify->mac_len == 0) {
9227c478bd9Sstevel@tonic-gate *pulSignedLen = 0;
9237c478bd9Sstevel@tonic-gate goto clean_exit;
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate /* Application asks for the length of the output buffer. */
9277c478bd9Sstevel@tonic-gate if (pSigned == NULL) {
9287c478bd9Sstevel@tonic-gate *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
9297c478bd9Sstevel@tonic-gate return (CKR_OK);
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate /* Is the application-supplied buffer large enough? */
9337c478bd9Sstevel@tonic-gate if (*pulSignedLen < soft_des_ctx_sign_verify->mac_len) {
9347c478bd9Sstevel@tonic-gate *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
9357c478bd9Sstevel@tonic-gate return (CKR_BUFFER_TOO_SMALL);
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate } else {
9387c478bd9Sstevel@tonic-gate soft_des_ctx_sign_verify =
9399627968bSmcpowers (soft_des_ctx_t *)session_p->verify.context;
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate if (Final) {
9437c478bd9Sstevel@tonic-gate soft_des_ctx_encrypt =
9449627968bSmcpowers (soft_des_ctx_t *)session_p->encrypt.context;
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gate /*
9477c478bd9Sstevel@tonic-gate * If there is data left in the buffer from a previous
9487c478bd9Sstevel@tonic-gate * SignUpdate() call, pass enough zeroed data to a
9497c478bd9Sstevel@tonic-gate * soft_sign_update call to pad the remainder
9507c478bd9Sstevel@tonic-gate */
9517c478bd9Sstevel@tonic-gate if (soft_des_ctx_encrypt->remain_len != 0) {
9527c478bd9Sstevel@tonic-gate bzero(last_block, DES_BLOCK_LEN);
9537c478bd9Sstevel@tonic-gate ulEncryptedLen = DES_BLOCK_LEN;
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate /*
9567c478bd9Sstevel@tonic-gate * By passing a buffer to soft_encrypt_final,
9577c478bd9Sstevel@tonic-gate * we force it to pad the remaining block
9587c478bd9Sstevel@tonic-gate * and encrypt it.
9597c478bd9Sstevel@tonic-gate */
9607c478bd9Sstevel@tonic-gate rv = soft_encrypt_final(session_p, last_block,
9619627968bSmcpowers &ulEncryptedLen);
9627c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
9637c478bd9Sstevel@tonic-gate goto clean_exit;
9647c478bd9Sstevel@tonic-gate }
9657c478bd9Sstevel@tonic-gate } else {
9667c478bd9Sstevel@tonic-gate /*
9677c478bd9Sstevel@tonic-gate * The last block of enciphered data is stored in:
9687c478bd9Sstevel@tonic-gate * soft_des_ctx_encrypt->des_cbc->des_ctx->dc_lastp
9697c478bd9Sstevel@tonic-gate * Copy that data to last_block
9707c478bd9Sstevel@tonic-gate */
9717c478bd9Sstevel@tonic-gate soft_des_ctx_encrypt =
9729627968bSmcpowers (soft_des_ctx_t *)session_p->encrypt.context;
9737c478bd9Sstevel@tonic-gate des_ctx = (des_ctx_t *)soft_des_ctx_encrypt->des_cbc;
9747c478bd9Sstevel@tonic-gate (void) memcpy(last_block, des_ctx->dc_lastp,
9759627968bSmcpowers DES_BLOCK_LEN);
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate /*
9787c478bd9Sstevel@tonic-gate * Passing a NULL output buffer here
9797c478bd9Sstevel@tonic-gate * forces the routine to just return.
9807c478bd9Sstevel@tonic-gate */
9817c478bd9Sstevel@tonic-gate rv = soft_encrypt_final(session_p, NULL,
9829627968bSmcpowers &ulEncryptedLen);
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate } else {
9867c478bd9Sstevel@tonic-gate /*
9877c478bd9Sstevel@tonic-gate * If the input length is not multiple of block size, then
9887c478bd9Sstevel@tonic-gate * determine the correct encrypted data length by rounding
9897c478bd9Sstevel@tonic-gate */
9907c478bd9Sstevel@tonic-gate remainder = ulDataLen % DES_BLOCK_LEN;
9917c478bd9Sstevel@tonic-gate /*
9927c478bd9Sstevel@tonic-gate * Because we always use DES_CBC_PAD mechanism
9937c478bd9Sstevel@tonic-gate * for sign/verify operations, the input will
9947c478bd9Sstevel@tonic-gate * be padded to the next 8 byte boundary.
9957c478bd9Sstevel@tonic-gate * Adjust the length fields here accordingly.
9967c478bd9Sstevel@tonic-gate */
9979627968bSmcpowers ulEncryptedLen = ulDataLen + (DES_BLOCK_LEN - remainder);
9987c478bd9Sstevel@tonic-gate
9997c478bd9Sstevel@tonic-gate pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
10007c478bd9Sstevel@tonic-gate if (pEncrypted == NULL) {
10017c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
10027c478bd9Sstevel@tonic-gate goto clean_exit;
10037c478bd9Sstevel@tonic-gate }
10047c478bd9Sstevel@tonic-gate
10057c478bd9Sstevel@tonic-gate /*
10067c478bd9Sstevel@tonic-gate * Pad the last block with zeros by copying pData into a zeroed
10077c478bd9Sstevel@tonic-gate * pEncrypted. Then pass pEncrypted into soft_encrypt as input
10087c478bd9Sstevel@tonic-gate */
10097c478bd9Sstevel@tonic-gate bzero(pEncrypted, ulEncryptedLen);
10107c478bd9Sstevel@tonic-gate (void) memcpy(pEncrypted, pData, ulDataLen);
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gate rv = soft_encrypt(session_p, pEncrypted, ulDataLen,
10139627968bSmcpowers pEncrypted, &ulEncryptedLen);
10147c478bd9Sstevel@tonic-gate (void) memcpy(last_block,
10159627968bSmcpowers &pEncrypted[ulEncryptedLen - DES_BLOCK_LEN], DES_BLOCK_LEN);
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate
10187c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
10197c478bd9Sstevel@tonic-gate *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate /* the leftmost mac_len bytes of last_block is our MAC */
10227c478bd9Sstevel@tonic-gate (void) memcpy(pSigned, last_block, *pulSignedLen);
10237c478bd9Sstevel@tonic-gate }
10247c478bd9Sstevel@tonic-gate
10257c478bd9Sstevel@tonic-gate clean_exit:
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate /* soft_encrypt_common() has freed the encrypt context */
10307c478bd9Sstevel@tonic-gate if (sign_op) {
10317c478bd9Sstevel@tonic-gate free(session_p->sign.context);
10327c478bd9Sstevel@tonic-gate session_p->sign.context = NULL;
10337c478bd9Sstevel@tonic-gate } else {
10347c478bd9Sstevel@tonic-gate free(session_p->verify.context);
10357c478bd9Sstevel@tonic-gate session_p->verify.context = NULL;
10367c478bd9Sstevel@tonic-gate }
10377c478bd9Sstevel@tonic-gate session_p->encrypt.flags = 0;
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate if (pEncrypted) {
10427c478bd9Sstevel@tonic-gate free(pEncrypted);
10437c478bd9Sstevel@tonic-gate }
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate return (rv);
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate
10487c478bd9Sstevel@tonic-gate /*
10497c478bd9Sstevel@tonic-gate * Called by soft_sign_update()
10507c478bd9Sstevel@tonic-gate */
10517c478bd9Sstevel@tonic-gate CK_RV
soft_des_mac_sign_verify_update(soft_session_t * session_p,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)10527c478bd9Sstevel@tonic-gate soft_des_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
1053*a8793c76SJason King CK_ULONG ulPartLen)
10547c478bd9Sstevel@tonic-gate {
10557c478bd9Sstevel@tonic-gate /*
10567c478bd9Sstevel@tonic-gate * The DES MAC is calculated by taking the specified number of
10577c478bd9Sstevel@tonic-gate * left-most bytes within the last block of
10587c478bd9Sstevel@tonic-gate * encrypted data, while the context of the multi-part
10597c478bd9Sstevel@tonic-gate * encryption stores the block necessary for XORing with the
10607c478bd9Sstevel@tonic-gate * input as per cipher block chaining . Therefore, none of the
10617c478bd9Sstevel@tonic-gate * intermediary encrypted blocks of data are necessary for
10627c478bd9Sstevel@tonic-gate * the DES MAC, and we can create a placeholder local buffer
10637c478bd9Sstevel@tonic-gate * for the encrypted data, which is immediately throw away.
10647c478bd9Sstevel@tonic-gate */
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx_encrypt;
10677c478bd9Sstevel@tonic-gate CK_BYTE *pEncrypted = NULL;
10687c478bd9Sstevel@tonic-gate CK_ULONG ulEncryptedLen;
10697c478bd9Sstevel@tonic-gate CK_ULONG total_len;
10707c478bd9Sstevel@tonic-gate uint8_t remainder;
10717c478bd9Sstevel@tonic-gate CK_RV rv;
10727c478bd9Sstevel@tonic-gate
10737c478bd9Sstevel@tonic-gate soft_des_ctx_encrypt = (soft_des_ctx_t *)session_p->encrypt.context;
10747c478bd9Sstevel@tonic-gate
10757c478bd9Sstevel@tonic-gate /* Avoid the malloc if we won't be encrypting any data */
10767c478bd9Sstevel@tonic-gate total_len = soft_des_ctx_encrypt->remain_len + ulPartLen;
10777c478bd9Sstevel@tonic-gate
10787c478bd9Sstevel@tonic-gate if (total_len < DES_BLOCK_LEN) {
10797c478bd9Sstevel@tonic-gate rv = soft_encrypt_update(session_p, pPart, ulPartLen, NULL,
10809627968bSmcpowers &ulEncryptedLen);
10817c478bd9Sstevel@tonic-gate } else {
10827c478bd9Sstevel@tonic-gate remainder = ulPartLen % DES_BLOCK_LEN;
10837c478bd9Sstevel@tonic-gate
10847c478bd9Sstevel@tonic-gate /* round up to the nearest multiple of block size */
10857c478bd9Sstevel@tonic-gate ulEncryptedLen = ulPartLen + (DES_BLOCK_LEN - remainder);
10867c478bd9Sstevel@tonic-gate pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate if (pEncrypted != NULL) {
10897c478bd9Sstevel@tonic-gate rv = soft_encrypt_update(session_p, pPart, ulPartLen,
10909627968bSmcpowers pEncrypted, &ulEncryptedLen);
10917c478bd9Sstevel@tonic-gate free(pEncrypted);
10927c478bd9Sstevel@tonic-gate } else {
10937c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
10947c478bd9Sstevel@tonic-gate }
10957c478bd9Sstevel@tonic-gate }
10967c478bd9Sstevel@tonic-gate return (rv);
10977c478bd9Sstevel@tonic-gate }
1098