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 * Copyright (c) 2018, Joyent, Inc.
25 */
26
27 #include <pthread.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <sys/types.h>
32 #include <security/cryptoki.h>
33 #include <modes/modes.h>
34 #include <des_impl.h>
35 #include "softSession.h"
36 #include "softObject.h"
37 #include "softCrypt.h"
38 #include "softOps.h"
39
40 /*
41 * Allocate context for the active encryption or decryption operation, and
42 * generate DES or DES3 key schedule to speed up the operation.
43 */
44 CK_RV
soft_des_crypt_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t encrypt)45 soft_des_crypt_init_common(soft_session_t *session_p,
46 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
47 boolean_t encrypt)
48 {
49
50 size_t size;
51 soft_des_ctx_t *soft_des_ctx;
52
53 soft_des_ctx = calloc(1, sizeof (soft_des_ctx_t));
54 if (soft_des_ctx == NULL) {
55 return (CKR_HOST_MEMORY);
56 }
57
58 /* Allocate key schedule for DES or DES3 based on key type. */
59 if (key_p->key_type == CKK_DES)
60 soft_des_ctx->key_sched = des_alloc_keysched(&size, DES, 0);
61 else
62 soft_des_ctx->key_sched = des_alloc_keysched(&size, DES3, 0);
63
64 if (soft_des_ctx->key_sched == NULL) {
65 free(soft_des_ctx);
66 return (CKR_HOST_MEMORY);
67 }
68
69 soft_des_ctx->keysched_len = size;
70 soft_des_ctx->key_type = key_p->key_type;
71
72 (void) pthread_mutex_lock(&session_p->session_mutex);
73 if (encrypt) {
74 /* Called by C_EncryptInit. */
75 session_p->encrypt.context = soft_des_ctx;
76 session_p->encrypt.mech.mechanism = pMechanism->mechanism;
77 } else {
78 /* Called by C_DecryptInit. */
79 session_p->decrypt.context = soft_des_ctx;
80 session_p->decrypt.mech.mechanism = pMechanism->mechanism;
81 }
82 (void) pthread_mutex_unlock(&session_p->session_mutex);
83
84 /*
85 * If this is a non-sensitive key and it does NOT have
86 * a key schedule yet, then allocate one and expand it.
87 * Otherwise, if its a non-sensitive key, and it DOES have
88 * a key schedule already attached to it, just copy the
89 * pre-expanded schedule to the context and avoid the
90 * extra key schedule expansion operation.
91 */
92 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
93 if (OBJ_KEY_SCHED(key_p) == NULL) {
94 void *ks;
95 (void) pthread_mutex_lock(&key_p->object_mutex);
96 if (OBJ_KEY_SCHED(key_p) == NULL) {
97 if (key_p->key_type == CKK_DES)
98 ks = des_alloc_keysched(&size, DES, 0);
99 else
100 ks = des_alloc_keysched(&size, DES3, 0);
101 if (ks == NULL) {
102 (void) pthread_mutex_unlock(
103 &key_p->object_mutex);
104 free(soft_des_ctx);
105 return (CKR_HOST_MEMORY);
106 }
107 /* Initialize key schedule for DES or DES3. */
108 if (key_p->key_type == CKK_DES)
109 des_init_keysched(
110 OBJ_SEC(key_p)->sk_value, DES, ks);
111 else if (key_p->key_type == CKK_DES2)
112 /*
113 * DES3 encryption/decryption needs to
114 * support a DES2 key.
115 */
116 des_init_keysched(
117 OBJ_SEC(key_p)->sk_value, DES2, ks);
118 else
119 des_init_keysched(
120 OBJ_SEC(key_p)->sk_value, DES3, ks);
121
122 OBJ_KEY_SCHED_LEN(key_p) = size;
123 OBJ_KEY_SCHED(key_p) = ks;
124 }
125 (void) pthread_mutex_unlock(&key_p->object_mutex);
126 }
127
128 /* Copy the pre-expanded key schedule from the key object */
129 (void) memcpy(soft_des_ctx->key_sched, OBJ_KEY_SCHED(key_p),
130 OBJ_KEY_SCHED_LEN(key_p));
131 soft_des_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
132 } else {
133 /* for sensitive keys, we cannot cache the key schedule */
134 if (key_p->key_type == CKK_DES)
135 des_init_keysched(OBJ_SEC(key_p)->sk_value,
136 DES, soft_des_ctx->key_sched);
137 else if (key_p->key_type == CKK_DES2)
138 /*
139 * DES3 encryption/decryption needs to
140 * support a DES2 key.
141 */
142 des_init_keysched(OBJ_SEC(key_p)->sk_value,
143 DES2, soft_des_ctx->key_sched);
144 else
145 des_init_keysched(OBJ_SEC(key_p)->sk_value,
146 DES3, soft_des_ctx->key_sched);
147 }
148
149 return (CKR_OK);
150 }
151
152
153 /*
154 * soft_des_encrypt_common()
155 *
156 * Arguments:
157 * session_p: pointer to soft_session_t struct
158 * pData: pointer to the input data to be encrypted
159 * ulDataLen: length of the input data
160 * pEncrypted: pointer to the output data after encryption
161 * pulEncryptedLen: pointer to the length of the output data
162 * update: boolean flag indicates caller is soft_encrypt
163 * or soft_encrypt_update
164 *
165 * Description:
166 * This function calls the corresponding encrypt routine based
167 * on the mechanism.
168 *
169 * Returns:
170 * CKR_OK: success
171 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
172 * is too small
173 * CKR_FUNCTION_FAILED: encrypt function failed
174 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
175 */
176 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)177 soft_des_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
178 CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
179 CK_ULONG_PTR pulEncryptedLen, boolean_t update)
180 {
181 int rc = 0;
182 CK_RV rv = CKR_OK;
183 soft_des_ctx_t *soft_des_ctx =
184 (soft_des_ctx_t *)session_p->encrypt.context;
185 des_ctx_t *des_ctx;
186 CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
187 CK_BYTE *in_buf = NULL;
188 CK_BYTE *out_buf = NULL;
189 CK_ULONG out_len;
190 CK_ULONG total_len;
191 CK_ULONG remain;
192 boolean_t pad_mechanism = B_FALSE;
193
194 pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
195 mechanism == CKM_DES3_CBC_PAD);
196 /*
197 * DES only takes input length that is a multiple of blocksize
198 * for C_Encrypt function with the mechanism CKM_DES<n>_ECB or
199 * CKM_DES<n>_CBC.
200 *
201 * DES allows any input length for C_Encrypt function with the
202 * mechanism CKM_DES<n>_CBC_PAD and for C_EncryptUpdate function.
203 */
204 if (!update && !pad_mechanism) {
205 if ((ulDataLen % DES_BLOCK_LEN) != 0) {
206 rv = CKR_DATA_LEN_RANGE;
207 goto cleanup;
208 }
209 }
210
211 if (!update) {
212 /*
213 * Called by C_Encrypt
214 */
215 if (pad_mechanism) {
216 /*
217 * For CKM_DES<n>_CBC_PAD, compute output length to
218 * count for the padding. If the length of input
219 * data is a multiple of blocksize, then make output
220 * length to be the sum of the input length and
221 * one blocksize. Otherwise, output length will
222 * be rounded up to the next multiple of blocksize.
223 */
224 out_len = DES_BLOCK_LEN *
225 (ulDataLen / DES_BLOCK_LEN + 1);
226 } else {
227 /*
228 * For non-padding mode, the output length will
229 * be same as the input length.
230 */
231 out_len = ulDataLen;
232 }
233
234 /*
235 * If application asks for the length of the output buffer
236 * to hold the ciphertext?
237 */
238 if (pEncrypted == NULL) {
239 *pulEncryptedLen = out_len;
240 return (CKR_OK);
241 }
242
243 /* Is the application-supplied buffer large enough? */
244 if (*pulEncryptedLen < out_len) {
245 *pulEncryptedLen = out_len;
246 return (CKR_BUFFER_TOO_SMALL);
247 }
248
249 /* Encrypt pad bytes in a separate operation */
250 if (pad_mechanism) {
251 out_len -= DES_BLOCK_LEN;
252 }
253
254 in_buf = pData;
255 out_buf = pEncrypted;
256 } else {
257 /*
258 * Called by C_EncryptUpdate
259 *
260 * Add the lengths of last remaining data and current
261 * plaintext together to get the total input length.
262 */
263 total_len = soft_des_ctx->remain_len + ulDataLen;
264
265 /*
266 * If the total input length is less than one blocksize,
267 * or if the total input length is just one blocksize and
268 * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
269 * encryption until when more data comes in next
270 * C_EncryptUpdate or when C_EncryptFinal is called.
271 */
272 if ((total_len < DES_BLOCK_LEN) ||
273 (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
274 if (pData != NULL) {
275 /*
276 * Save input data and its length in
277 * the remaining buffer of DES context.
278 */
279 (void) memcpy(soft_des_ctx->data +
280 soft_des_ctx->remain_len, pData, ulDataLen);
281 soft_des_ctx->remain_len += ulDataLen;
282 }
283
284 /* Set encrypted data length to 0. */
285 *pulEncryptedLen = 0;
286 return (CKR_OK);
287 }
288
289 /* Compute the length of remaing data. */
290 remain = total_len % DES_BLOCK_LEN;
291
292 /*
293 * Make sure that the output length is a multiple of
294 * blocksize.
295 */
296 out_len = total_len - remain;
297
298 /*
299 * If application asks for the length of the output buffer
300 * to hold the ciphertext?
301 */
302 if (pEncrypted == NULL) {
303 *pulEncryptedLen = out_len;
304 return (CKR_OK);
305 }
306
307 /* Is the application-supplied buffer large enough? */
308 if (*pulEncryptedLen < out_len) {
309 *pulEncryptedLen = out_len;
310 return (CKR_BUFFER_TOO_SMALL);
311 }
312
313 if (soft_des_ctx->remain_len != 0) {
314 /*
315 * Copy last remaining data and current input data
316 * to the output buffer.
317 */
318 (void) memmove(pEncrypted + soft_des_ctx->remain_len,
319 pData, out_len - soft_des_ctx->remain_len);
320 (void) memcpy(pEncrypted, soft_des_ctx->data,
321 soft_des_ctx->remain_len);
322 bzero(soft_des_ctx->data, soft_des_ctx->remain_len);
323
324 in_buf = pEncrypted;
325 } else {
326 in_buf = pData;
327 }
328 out_buf = pEncrypted;
329 }
330
331 /*
332 * Begin Encryption now.
333 */
334 switch (mechanism) {
335
336 case CKM_DES_ECB:
337 case CKM_DES3_ECB:
338 {
339
340 ulong_t i;
341 uint8_t *tmp_inbuf;
342 uint8_t *tmp_outbuf;
343
344 for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
345 tmp_inbuf = &in_buf[i];
346 tmp_outbuf = &out_buf[i];
347 /* Crunch one block of data for DES. */
348 if (soft_des_ctx->key_type == CKK_DES)
349 (void) des_crunch_block(
350 soft_des_ctx->key_sched,
351 tmp_inbuf, tmp_outbuf, B_FALSE);
352 else
353 (void) des3_crunch_block(
354 soft_des_ctx->key_sched,
355 tmp_inbuf, tmp_outbuf, B_FALSE);
356 }
357
358 if (update) {
359 /*
360 * For encrypt update, if there is remaining
361 * data, save it and its length in the context.
362 */
363 if (remain != 0)
364 (void) memcpy(soft_des_ctx->data, pData +
365 (ulDataLen - remain), remain);
366 soft_des_ctx->remain_len = remain;
367 }
368
369 *pulEncryptedLen = out_len;
370 break;
371 }
372
373 case CKM_DES_CBC:
374 case CKM_DES_CBC_PAD:
375 case CKM_DES3_CBC:
376 case CKM_DES3_CBC_PAD:
377 {
378 crypto_data_t out;
379
380 out.cd_format = CRYPTO_DATA_RAW;
381 out.cd_offset = 0;
382 out.cd_length = out_len;
383 out.cd_raw.iov_base = (char *)out_buf;
384 out.cd_raw.iov_len = out_len;
385
386 /* Encrypt multiple blocks of data. */
387 rc = des_encrypt_contiguous_blocks(
388 (des_ctx_t *)soft_des_ctx->des_cbc,
389 (char *)in_buf, out_len, &out);
390
391 if (rc != 0)
392 goto encrypt_failed;
393
394 if (update) {
395 /*
396 * For encrypt update, if there is remaining data,
397 * save it and its length in the context.
398 */
399 if (remain != 0)
400 (void) memcpy(soft_des_ctx->data, pData +
401 (ulDataLen - remain), remain);
402 soft_des_ctx->remain_len = remain;
403 } else if (pad_mechanism) {
404 /*
405 * Save the remainder of the input
406 * block in a temporary block because
407 * we don't want to overrun the input buffer
408 * by tacking on pad bytes.
409 */
410 CK_BYTE tmpblock[DES_BLOCK_LEN];
411 (void) memcpy(tmpblock, in_buf + out_len,
412 ulDataLen - out_len);
413 soft_add_pkcs7_padding(tmpblock +
414 (ulDataLen - out_len),
415 DES_BLOCK_LEN, ulDataLen - out_len);
416
417 out.cd_offset = out_len;
418 out.cd_length = DES_BLOCK_LEN;
419 out.cd_raw.iov_base = (char *)out_buf;
420 out.cd_raw.iov_len = out_len + DES_BLOCK_LEN;
421
422 /* Encrypt last block containing pad bytes. */
423 rc = des_encrypt_contiguous_blocks(
424 (des_ctx_t *)soft_des_ctx->des_cbc,
425 (char *)tmpblock, DES_BLOCK_LEN, &out);
426 out_len += DES_BLOCK_LEN;
427 }
428
429 if (rc == 0) {
430 *pulEncryptedLen = out_len;
431 break;
432 }
433 encrypt_failed:
434 *pulEncryptedLen = 0;
435 rv = CKR_FUNCTION_FAILED;
436 goto cleanup;
437
438 }
439 } /* end switch */
440
441 if (update)
442 return (CKR_OK);
443
444 /*
445 * The following code will be executed if the caller is
446 * soft_encrypt() or an error occurred. The encryption
447 * operation will be terminated so we need to do some cleanup.
448 */
449 cleanup:
450 (void) pthread_mutex_lock(&session_p->session_mutex);
451 des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
452 free(des_ctx);
453 freezero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
454 freezero(session_p->encrypt.context, sizeof (soft_des_ctx_t));
455 session_p->encrypt.context = NULL;
456 (void) pthread_mutex_unlock(&session_p->session_mutex);
457
458 return (rv);
459 }
460
461
462 /*
463 * soft_des_decrypt_common()
464 *
465 * Arguments:
466 * session_p: pointer to soft_session_t struct
467 * pEncrypted: pointer to the input data to be decrypted
468 * ulEncryptedLen: length of the input data
469 * pData: pointer to the output data
470 * pulDataLen: pointer to the length of the output data
471 * Update: boolean flag indicates caller is soft_decrypt
472 * or soft_decrypt_update
473 *
474 * Description:
475 * This function calls the corresponding decrypt routine based
476 * on the mechanism.
477 *
478 * Returns:
479 * CKR_OK: success
480 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
481 * is too small
482 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
483 * of blocksize
484 * CKR_FUNCTION_FAILED: decrypt function failed
485 */
486 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)487 soft_des_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
488 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
489 CK_ULONG_PTR pulDataLen, boolean_t update)
490 {
491
492 int rc = 0;
493 CK_RV rv = CKR_OK;
494 soft_des_ctx_t *soft_des_ctx =
495 (soft_des_ctx_t *)session_p->decrypt.context;
496 des_ctx_t *des_ctx;
497 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
498 CK_BYTE *in_buf = NULL;
499 CK_BYTE *out_buf = NULL;
500 CK_ULONG out_len;
501 CK_ULONG total_len;
502 CK_ULONG remain;
503 boolean_t pad_mechanism = B_FALSE;
504
505 pad_mechanism = (mechanism == CKM_DES_CBC_PAD ||
506 mechanism == CKM_DES3_CBC_PAD);
507 /*
508 * DES only takes input length that is a multiple of 8 bytes
509 * for C_Decrypt function with the mechanism CKM_DES<n>_ECB,
510 * CKM_DES<n>_CBC or CKM_DES<n>_CBC_PAD.
511 *
512 * DES allows any input length for C_DecryptUpdate function.
513 */
514 if (!update) {
515 /*
516 * Called by C_Decrypt
517 */
518 if ((ulEncryptedLen % DES_BLOCK_LEN) != 0) {
519 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
520 goto cleanup;
521 }
522
523 /*
524 * If application asks for the length of the output buffer
525 * to hold the plaintext?
526 */
527 if (pData == NULL) {
528 *pulDataLen = ulEncryptedLen;
529 return (CKR_OK);
530 }
531
532 /* Is the application-supplied buffer large enough? */
533 if (!pad_mechanism) {
534 if (*pulDataLen < ulEncryptedLen) {
535 *pulDataLen = ulEncryptedLen;
536 return (CKR_BUFFER_TOO_SMALL);
537 }
538
539 /* Set output length same as input length. */
540 out_len = ulEncryptedLen;
541 } else {
542 /*
543 * For CKM_DES<n>_CBC_PAD, we don't know how
544 * many bytes for padding at this time, so
545 * we'd assume one block was padded.
546 */
547 if (*pulDataLen < (ulEncryptedLen - DES_BLOCK_LEN)) {
548 *pulDataLen = ulEncryptedLen - DES_BLOCK_LEN;
549 return (CKR_BUFFER_TOO_SMALL);
550 }
551 out_len = ulEncryptedLen - DES_BLOCK_LEN;
552 }
553 in_buf = pEncrypted;
554 out_buf = pData;
555 } else {
556 /*
557 * Called by C_DecryptUpdate
558 *
559 * Add the lengths of last remaining data and current
560 * input data together to get the total input length.
561 */
562 total_len = soft_des_ctx->remain_len + ulEncryptedLen;
563
564 /*
565 * If the total input length is less than one blocksize,
566 * or if the total input length is just one blocksize and
567 * the mechanism is CKM_DES<n>_CBC_PAD, we will need to delay
568 * decryption until when more data comes in next
569 * C_DecryptUpdate or when C_DecryptFinal is called.
570 */
571 if ((total_len < DES_BLOCK_LEN) ||
572 (pad_mechanism && (total_len == DES_BLOCK_LEN))) {
573 if (pEncrypted != NULL) {
574 /*
575 * Save input data and its length in
576 * the remaining buffer of DES context.
577 */
578 (void) memcpy(soft_des_ctx->data +
579 soft_des_ctx->remain_len,
580 pEncrypted, ulEncryptedLen);
581 soft_des_ctx->remain_len += ulEncryptedLen;
582 }
583
584 /* Set output data length to 0. */
585 *pulDataLen = 0;
586 return (CKR_OK);
587 }
588
589 /* Compute the length of remaing data. */
590 remain = total_len % DES_BLOCK_LEN;
591
592 /*
593 * Make sure that the output length is a multiple of
594 * blocksize.
595 */
596 out_len = total_len - remain;
597
598 if (pad_mechanism) {
599 /*
600 * If the input data length is a multiple of
601 * blocksize, then save the last block of input
602 * data in the remaining buffer. C_DecryptFinal
603 * will handle this last block of data.
604 */
605 if (remain == 0) {
606 remain = DES_BLOCK_LEN;
607 out_len -= DES_BLOCK_LEN;
608 }
609 }
610
611 /*
612 * If application asks for the length of the output buffer
613 * to hold the plaintext?
614 */
615 if (pData == NULL) {
616 *pulDataLen = out_len;
617 return (CKR_OK);
618 }
619
620 /*
621 * Is the application-supplied buffer large enough?
622 */
623 if (*pulDataLen < out_len) {
624 *pulDataLen = out_len;
625 return (CKR_BUFFER_TOO_SMALL);
626 }
627
628 if (soft_des_ctx->remain_len != 0) {
629 /*
630 * Copy last remaining data and current input data
631 * to the output buffer.
632 */
633 (void) memmove(pData + soft_des_ctx->remain_len,
634 pEncrypted, out_len - soft_des_ctx->remain_len);
635 (void) memcpy(pData, soft_des_ctx->data,
636 soft_des_ctx->remain_len);
637 bzero(soft_des_ctx->data, soft_des_ctx->remain_len);
638
639 in_buf = pData;
640 } else {
641 in_buf = pEncrypted;
642 }
643 out_buf = pData;
644 }
645
646 /*
647 * Begin Decryption.
648 */
649 switch (mechanism) {
650
651 case CKM_DES_ECB:
652 case CKM_DES3_ECB:
653 {
654 uint8_t *tmp_inbuf;
655 uint8_t *tmp_outbuf;
656 ulong_t i;
657
658 for (i = 0; i < out_len; i += DES_BLOCK_LEN) {
659 tmp_inbuf = &in_buf[i];
660 tmp_outbuf = &out_buf[i];
661 /* Crunch one block of data for DES. */
662 if (soft_des_ctx->key_type == CKK_DES)
663 (void) des_crunch_block(
664 soft_des_ctx->key_sched,
665 tmp_inbuf, tmp_outbuf, B_TRUE);
666 else
667 (void) des3_crunch_block(
668 soft_des_ctx->key_sched,
669 tmp_inbuf, tmp_outbuf, B_TRUE);
670 }
671
672 if (update) {
673 /*
674 * For decrypt update, if there is remaining
675 * data, save it and its length in the context.
676 */
677 if (remain != 0)
678 (void) memcpy(soft_des_ctx->data, pEncrypted +
679 (ulEncryptedLen - remain), remain);
680 soft_des_ctx->remain_len = remain;
681 }
682
683 *pulDataLen = out_len;
684 break;
685 }
686
687 case CKM_DES_CBC:
688 case CKM_DES_CBC_PAD:
689 case CKM_DES3_CBC:
690 case CKM_DES3_CBC_PAD:
691 {
692 crypto_data_t out;
693 CK_ULONG rem_len;
694 uint8_t last_block[DES_BLOCK_LEN];
695
696 out.cd_format = CRYPTO_DATA_RAW;
697 out.cd_offset = 0;
698 out.cd_length = out_len;
699 out.cd_raw.iov_base = (char *)out_buf;
700 out.cd_raw.iov_len = out_len;
701
702 /* Decrypt multiple blocks of data. */
703 rc = des_decrypt_contiguous_blocks(
704 (des_ctx_t *)soft_des_ctx->des_cbc,
705 (char *)in_buf, out_len, &out);
706
707 if (rc != 0)
708 goto decrypt_failed;
709
710 if (pad_mechanism && !update) {
711 /* Decrypt last block containing pad bytes. */
712 out.cd_offset = 0;
713 out.cd_length = DES_BLOCK_LEN;
714 out.cd_raw.iov_base = (char *)last_block;
715 out.cd_raw.iov_len = DES_BLOCK_LEN;
716
717 /* Decrypt last block containing pad bytes. */
718 rc = des_decrypt_contiguous_blocks(
719 (des_ctx_t *)soft_des_ctx->des_cbc,
720 (char *)in_buf + out_len, DES_BLOCK_LEN, &out);
721
722 if (rc != 0)
723 goto decrypt_failed;
724
725 /*
726 * Remove padding bytes after decryption of
727 * ciphertext block to produce the original
728 * plaintext.
729 */
730 rv = soft_remove_pkcs7_padding(last_block,
731 DES_BLOCK_LEN, &rem_len);
732 if (rv == CKR_OK) {
733 if (rem_len != 0)
734 (void) memcpy(out_buf + out_len,
735 last_block, rem_len);
736 *pulDataLen = out_len + rem_len;
737 } else {
738 *pulDataLen = 0;
739 goto cleanup;
740 }
741 } else {
742 *pulDataLen = out_len;
743 }
744
745 if (update) {
746 /*
747 * For decrypt update, if there is remaining data,
748 * save it and its length in the context.
749 */
750 if (remain != 0)
751 (void) memcpy(soft_des_ctx->data, pEncrypted +
752 (ulEncryptedLen - remain), remain);
753 soft_des_ctx->remain_len = remain;
754 }
755
756 if (rc == 0)
757 break;
758 decrypt_failed:
759 *pulDataLen = 0;
760 rv = CKR_FUNCTION_FAILED;
761 goto cleanup;
762 }
763 } /* end switch */
764
765 if (update)
766 return (CKR_OK);
767
768 /*
769 * The following code will be executed if the caller is
770 * soft_decrypt() or an error occurred. The decryption
771 * operation will be terminated so we need to do some cleanup.
772 */
773 cleanup:
774 (void) pthread_mutex_lock(&session_p->session_mutex);
775 des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
776 free(des_ctx);
777 freezero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
778 freezero(session_p->decrypt.context, sizeof (soft_des_ctx_t));
779 (void) pthread_mutex_unlock(&session_p->session_mutex);
780
781 return (rv);
782 }
783
784
785 /*
786 * Allocate and initialize a context for DES CBC mode of operation.
787 */
788 void *
des_cbc_ctx_init(void * key_sched,size_t size,uint8_t * ivec,CK_KEY_TYPE type)789 des_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec, CK_KEY_TYPE type)
790 {
791
792 cbc_ctx_t *cbc_ctx;
793
794 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
795 return (NULL);
796
797 cbc_ctx->cbc_keysched = key_sched;
798
799 (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, DES_BLOCK_LEN);
800
801 cbc_ctx->cbc_lastp = (uint8_t *)&cbc_ctx->cbc_iv[0];
802 cbc_ctx->cbc_keysched_len = size;
803 if (type == CKK_DES)
804 cbc_ctx->cbc_flags |= CBC_MODE;
805 else
806 cbc_ctx->cbc_flags |= CBC_MODE | DES3_STRENGTH;
807
808 return (cbc_ctx);
809
810 }
811
812 /*
813 * Allocate and initialize DES contexts for both signing and encrypting,
814 * saving both context pointers in the session struct. For general-length DES
815 * MAC, check the length in the parameter to see if it is in the right range.
816 */
817 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)818 soft_des_sign_verify_init_common(soft_session_t *session_p,
819 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op)
820 {
821 soft_des_ctx_t *soft_des_ctx;
822 CK_MECHANISM encrypt_mech;
823 CK_RV rv;
824
825 if ((key_p->class != CKO_SECRET_KEY) || (key_p->key_type != CKK_DES)) {
826 return (CKR_KEY_TYPE_INCONSISTENT);
827 }
828
829 /* allocate memory for the sign/verify context */
830 soft_des_ctx = malloc(sizeof (soft_des_ctx_t));
831 if (soft_des_ctx == NULL) {
832 return (CKR_HOST_MEMORY);
833 }
834
835 soft_des_ctx->key_type = key_p->key_type;
836
837 /* initialization vector is zero for DES MAC */
838 bzero(soft_des_ctx->ivec, DES_BLOCK_LEN);
839
840 switch (pMechanism->mechanism) {
841
842 case CKM_DES_MAC_GENERAL:
843
844 if (pMechanism->ulParameterLen !=
845 sizeof (CK_MAC_GENERAL_PARAMS)) {
846 free(soft_des_ctx);
847 return (CKR_MECHANISM_PARAM_INVALID);
848 }
849
850 if (*(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter >
851 DES_BLOCK_LEN) {
852 free(soft_des_ctx);
853 return (CKR_MECHANISM_PARAM_INVALID);
854 }
855
856 soft_des_ctx->mac_len = *((CK_MAC_GENERAL_PARAMS_PTR)
857 pMechanism->pParameter);
858
859 /*FALLTHRU*/
860 case CKM_DES_MAC:
861
862 /*
863 * For non-general DES MAC, output is always half as
864 * large as block size
865 */
866 if (pMechanism->mechanism == CKM_DES_MAC) {
867 soft_des_ctx->mac_len = DES_MAC_LEN;
868 }
869
870 /* allocate a context for DES encryption */
871 encrypt_mech.mechanism = CKM_DES_CBC_PAD;
872 encrypt_mech.pParameter = (void *)soft_des_ctx->ivec;
873 encrypt_mech.ulParameterLen = DES_BLOCK_LEN;
874 rv = soft_encrypt_init_internal(session_p, &encrypt_mech,
875 key_p);
876 if (rv != CKR_OK) {
877 free(soft_des_ctx);
878 return (rv);
879 }
880
881 (void) pthread_mutex_lock(&session_p->session_mutex);
882
883 if (sign_op) {
884 session_p->sign.context = soft_des_ctx;
885 session_p->sign.mech.mechanism = pMechanism->mechanism;
886 } else {
887 session_p->verify.context = soft_des_ctx;
888 session_p->verify.mech.mechanism =
889 pMechanism->mechanism;
890 }
891
892 (void) pthread_mutex_unlock(&session_p->session_mutex);
893
894 break;
895 }
896 return (CKR_OK);
897 }
898
899 /*
900 * Called by soft_sign(), soft_sign_final(), soft_verify() or
901 * soft_verify_final().
902 */
903 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)904 soft_des_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
905 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
906 boolean_t sign_op, boolean_t Final)
907 {
908 soft_des_ctx_t *soft_des_ctx_sign_verify;
909 soft_des_ctx_t *soft_des_ctx_encrypt;
910 CK_RV rv;
911 CK_BYTE *pEncrypted = NULL;
912 CK_ULONG ulEncryptedLen = 0;
913 uint8_t remainder;
914 CK_BYTE last_block[DES_BLOCK_LEN];
915 des_ctx_t *des_ctx = NULL;
916
917 if (sign_op) {
918 soft_des_ctx_sign_verify =
919 (soft_des_ctx_t *)session_p->sign.context;
920
921 if (soft_des_ctx_sign_verify->mac_len == 0) {
922 *pulSignedLen = 0;
923 goto clean_exit;
924 }
925
926 /* Application asks for the length of the output buffer. */
927 if (pSigned == NULL) {
928 *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
929 return (CKR_OK);
930 }
931
932 /* Is the application-supplied buffer large enough? */
933 if (*pulSignedLen < soft_des_ctx_sign_verify->mac_len) {
934 *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
935 return (CKR_BUFFER_TOO_SMALL);
936 }
937 } else {
938 soft_des_ctx_sign_verify =
939 (soft_des_ctx_t *)session_p->verify.context;
940 }
941
942 if (Final) {
943 soft_des_ctx_encrypt =
944 (soft_des_ctx_t *)session_p->encrypt.context;
945
946 /*
947 * If there is data left in the buffer from a previous
948 * SignUpdate() call, pass enough zeroed data to a
949 * soft_sign_update call to pad the remainder
950 */
951 if (soft_des_ctx_encrypt->remain_len != 0) {
952 bzero(last_block, DES_BLOCK_LEN);
953 ulEncryptedLen = DES_BLOCK_LEN;
954
955 /*
956 * By passing a buffer to soft_encrypt_final,
957 * we force it to pad the remaining block
958 * and encrypt it.
959 */
960 rv = soft_encrypt_final(session_p, last_block,
961 &ulEncryptedLen);
962 if (rv != CKR_OK) {
963 goto clean_exit;
964 }
965 } else {
966 /*
967 * The last block of enciphered data is stored in:
968 * soft_des_ctx_encrypt->des_cbc->des_ctx->dc_lastp
969 * Copy that data to last_block
970 */
971 soft_des_ctx_encrypt =
972 (soft_des_ctx_t *)session_p->encrypt.context;
973 des_ctx = (des_ctx_t *)soft_des_ctx_encrypt->des_cbc;
974 (void) memcpy(last_block, des_ctx->dc_lastp,
975 DES_BLOCK_LEN);
976
977 /*
978 * Passing a NULL output buffer here
979 * forces the routine to just return.
980 */
981 rv = soft_encrypt_final(session_p, NULL,
982 &ulEncryptedLen);
983 }
984
985 } else {
986 /*
987 * If the input length is not multiple of block size, then
988 * determine the correct encrypted data length by rounding
989 */
990 remainder = ulDataLen % DES_BLOCK_LEN;
991 /*
992 * Because we always use DES_CBC_PAD mechanism
993 * for sign/verify operations, the input will
994 * be padded to the next 8 byte boundary.
995 * Adjust the length fields here accordingly.
996 */
997 ulEncryptedLen = ulDataLen + (DES_BLOCK_LEN - remainder);
998
999 pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
1000 if (pEncrypted == NULL) {
1001 rv = CKR_HOST_MEMORY;
1002 goto clean_exit;
1003 }
1004
1005 /*
1006 * Pad the last block with zeros by copying pData into a zeroed
1007 * pEncrypted. Then pass pEncrypted into soft_encrypt as input
1008 */
1009 bzero(pEncrypted, ulEncryptedLen);
1010 (void) memcpy(pEncrypted, pData, ulDataLen);
1011
1012 rv = soft_encrypt(session_p, pEncrypted, ulDataLen,
1013 pEncrypted, &ulEncryptedLen);
1014 (void) memcpy(last_block,
1015 &pEncrypted[ulEncryptedLen - DES_BLOCK_LEN], DES_BLOCK_LEN);
1016 }
1017
1018 if (rv == CKR_OK) {
1019 *pulSignedLen = soft_des_ctx_sign_verify->mac_len;
1020
1021 /* the leftmost mac_len bytes of last_block is our MAC */
1022 (void) memcpy(pSigned, last_block, *pulSignedLen);
1023 }
1024
1025 clean_exit:
1026
1027 (void) pthread_mutex_lock(&session_p->session_mutex);
1028
1029 /* soft_encrypt_common() has freed the encrypt context */
1030 if (sign_op) {
1031 free(session_p->sign.context);
1032 session_p->sign.context = NULL;
1033 } else {
1034 free(session_p->verify.context);
1035 session_p->verify.context = NULL;
1036 }
1037 session_p->encrypt.flags = 0;
1038
1039 (void) pthread_mutex_unlock(&session_p->session_mutex);
1040
1041 if (pEncrypted) {
1042 free(pEncrypted);
1043 }
1044
1045 return (rv);
1046 }
1047
1048 /*
1049 * Called by soft_sign_update()
1050 */
1051 CK_RV
soft_des_mac_sign_verify_update(soft_session_t * session_p,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)1052 soft_des_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
1053 CK_ULONG ulPartLen)
1054 {
1055 /*
1056 * The DES MAC is calculated by taking the specified number of
1057 * left-most bytes within the last block of
1058 * encrypted data, while the context of the multi-part
1059 * encryption stores the block necessary for XORing with the
1060 * input as per cipher block chaining . Therefore, none of the
1061 * intermediary encrypted blocks of data are necessary for
1062 * the DES MAC, and we can create a placeholder local buffer
1063 * for the encrypted data, which is immediately throw away.
1064 */
1065
1066 soft_des_ctx_t *soft_des_ctx_encrypt;
1067 CK_BYTE *pEncrypted = NULL;
1068 CK_ULONG ulEncryptedLen;
1069 CK_ULONG total_len;
1070 uint8_t remainder;
1071 CK_RV rv;
1072
1073 soft_des_ctx_encrypt = (soft_des_ctx_t *)session_p->encrypt.context;
1074
1075 /* Avoid the malloc if we won't be encrypting any data */
1076 total_len = soft_des_ctx_encrypt->remain_len + ulPartLen;
1077
1078 if (total_len < DES_BLOCK_LEN) {
1079 rv = soft_encrypt_update(session_p, pPart, ulPartLen, NULL,
1080 &ulEncryptedLen);
1081 } else {
1082 remainder = ulPartLen % DES_BLOCK_LEN;
1083
1084 /* round up to the nearest multiple of block size */
1085 ulEncryptedLen = ulPartLen + (DES_BLOCK_LEN - remainder);
1086 pEncrypted = malloc(sizeof (CK_BYTE) * ulEncryptedLen);
1087
1088 if (pEncrypted != NULL) {
1089 rv = soft_encrypt_update(session_p, pPart, ulPartLen,
1090 pEncrypted, &ulEncryptedLen);
1091 free(pEncrypted);
1092 } else {
1093 rv = CKR_HOST_MEMORY;
1094 }
1095 }
1096 return (rv);
1097 }
1098