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 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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
soft_des_crypt_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t encrypt)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
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)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
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)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);
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 *
des_cbc_ctx_init(void * key_sched,size_t size,uint8_t * ivec,CK_KEY_TYPE type)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
soft_des_sign_verify_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t sign_op)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
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)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
soft_des_mac_sign_verify_update(soft_session_t * session_p,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)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