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 "softSession.h"
33 #include "softObject.h"
34 #include "softCrypt.h"
35 #include <aes_impl.h>
36
37 /*
38 * Allocate context for the active encryption or decryption operation, and
39 * generate AES key schedule to speed up the operation.
40 */
41 CK_RV
soft_aes_crypt_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t encrypt)42 soft_aes_crypt_init_common(soft_session_t *session_p,
43 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
44 boolean_t encrypt)
45 {
46 size_t size;
47 soft_aes_ctx_t *soft_aes_ctx;
48
49 soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t));
50 if (soft_aes_ctx == NULL) {
51 return (CKR_HOST_MEMORY);
52 }
53
54 soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
55
56 if (soft_aes_ctx->key_sched == NULL) {
57 free(soft_aes_ctx);
58 return (CKR_HOST_MEMORY);
59 }
60
61 soft_aes_ctx->keysched_len = size;
62
63 (void) pthread_mutex_lock(&session_p->session_mutex);
64 if (encrypt) {
65 /* Called by C_EncryptInit. */
66 session_p->encrypt.context = soft_aes_ctx;
67 session_p->encrypt.mech.mechanism = pMechanism->mechanism;
68 } else {
69 /* Called by C_DecryptInit. */
70 session_p->decrypt.context = soft_aes_ctx;
71 session_p->decrypt.mech.mechanism = pMechanism->mechanism;
72 }
73 (void) pthread_mutex_unlock(&session_p->session_mutex);
74
75 /*
76 * If this is a non-sensitive key and it does NOT have
77 * a key schedule yet, then allocate one and expand it.
78 * Otherwise, if it's a non-sensitive key, and it DOES have
79 * a key schedule already attached to it, just copy the
80 * pre-expanded schedule to the context and avoid the
81 * extra key schedule expansion operation.
82 */
83 if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
84 if (OBJ_KEY_SCHED(key_p) == NULL) {
85 void *ks;
86
87 (void) pthread_mutex_lock(&key_p->object_mutex);
88 if (OBJ_KEY_SCHED(key_p) == NULL) {
89 ks = aes_alloc_keysched(&size, 0);
90 if (ks == NULL) {
91 (void) pthread_mutex_unlock(
92 &key_p->object_mutex);
93 free(soft_aes_ctx);
94 return (CKR_HOST_MEMORY);
95 }
96 #ifdef __sparcv9
97 /* LINTED */
98 aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
99 (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
100 #else /* !__sparcv9 */
101 aes_init_keysched(OBJ_SEC_VALUE(key_p),
102 (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
103 #endif /* __sparcv9 */
104 OBJ_KEY_SCHED_LEN(key_p) = size;
105 OBJ_KEY_SCHED(key_p) = ks;
106 }
107 (void) pthread_mutex_unlock(&key_p->object_mutex);
108 }
109 (void) memcpy(soft_aes_ctx->key_sched, OBJ_KEY_SCHED(key_p),
110 OBJ_KEY_SCHED_LEN(key_p));
111 soft_aes_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
112 } else {
113 /*
114 * Initialize key schedule for AES. aes_init_keysched()
115 * requires key length in bits.
116 */
117 #ifdef __sparcv9
118 /* LINTED */
119 aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
120 (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
121 #else /* !__sparcv9 */
122 aes_init_keysched(OBJ_SEC_VALUE(key_p),
123 (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
124 #endif /* __sparcv9 */
125 }
126 return (CKR_OK);
127 }
128
129
130 /*
131 * soft_aes_encrypt_common()
132 *
133 * Arguments:
134 * session_p: pointer to soft_session_t struct
135 * pData: pointer to the input data to be encrypted
136 * ulDataLen: length of the input data
137 * pEncrypted: pointer to the output data after encryption
138 * pulEncryptedLen: pointer to the length of the output data
139 * update: boolean flag indicates caller is soft_encrypt
140 * or soft_encrypt_update
141 *
142 * Description:
143 * This function calls the corresponding encrypt routine based
144 * on the mechanism.
145 *
146 * Returns:
147 * CKR_OK: success
148 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
149 * is too small
150 * CKR_FUNCTION_FAILED: encrypt function failed
151 * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
152 */
153 CK_RV
soft_aes_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)154 soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
155 CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
156 CK_ULONG_PTR pulEncryptedLen, boolean_t update)
157 {
158
159 int rc = 0;
160 CK_RV rv = CKR_OK;
161 soft_aes_ctx_t *soft_aes_ctx =
162 (soft_aes_ctx_t *)session_p->encrypt.context;
163 aes_ctx_t *aes_ctx;
164 CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
165 CK_BYTE *in_buf = NULL;
166 CK_BYTE *out_buf = NULL;
167 CK_ULONG out_len;
168 CK_ULONG total_len;
169 CK_ULONG remain;
170
171 if (mechanism == CKM_AES_CTR)
172 goto do_encryption;
173
174 /*
175 * AES only takes input length that is a multiple of blocksize
176 * for C_Encrypt function with the mechanism CKM_AES_ECB or
177 * CKM_AES_CBC.
178 *
179 * AES allows any input length for C_Encrypt function with the
180 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function.
181 */
182 if ((!update) && (mechanism != CKM_AES_CBC_PAD)) {
183 if ((ulDataLen % AES_BLOCK_LEN) != 0) {
184 rv = CKR_DATA_LEN_RANGE;
185 goto cleanup;
186 }
187 }
188
189 if (!update) {
190 /*
191 * Called by C_Encrypt
192 */
193 if (mechanism == CKM_AES_CBC_PAD) {
194 /*
195 * For CKM_AES_CBC_PAD, compute output length to
196 * count for the padding. If the length of input
197 * data is a multiple of blocksize, then make output
198 * length to be the sum of the input length and
199 * one blocksize. Otherwise, output length will
200 * be rounded up to the next multiple of blocksize.
201 */
202 out_len = AES_BLOCK_LEN *
203 (ulDataLen / AES_BLOCK_LEN + 1);
204 } else {
205 /*
206 * For non-padding mode, the output length will
207 * be same as the input length.
208 */
209 out_len = ulDataLen;
210 }
211
212 /*
213 * If application asks for the length of the output buffer
214 * to hold the ciphertext?
215 */
216 if (pEncrypted == NULL) {
217 *pulEncryptedLen = out_len;
218 return (CKR_OK);
219 }
220
221 /* Is the application-supplied buffer large enough? */
222 if (*pulEncryptedLen < out_len) {
223 *pulEncryptedLen = out_len;
224 return (CKR_BUFFER_TOO_SMALL);
225 }
226
227 /* Encrypt pad bytes in a separate operation */
228 if (mechanism == CKM_AES_CBC_PAD) {
229 out_len -= AES_BLOCK_LEN;
230 }
231
232 in_buf = pData;
233 out_buf = pEncrypted;
234 } else {
235 /*
236 * Called by C_EncryptUpdate
237 *
238 * Add the lengths of last remaining data and current
239 * plaintext together to get the total input length.
240 */
241 total_len = soft_aes_ctx->remain_len + ulDataLen;
242
243 /*
244 * If the total input length is less than one blocksize,
245 * or if the total input length is just one blocksize and
246 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
247 * encryption until when more data comes in next
248 * C_EncryptUpdate or when C_EncryptFinal is called.
249 */
250 if ((total_len < AES_BLOCK_LEN) ||
251 ((mechanism == CKM_AES_CBC_PAD) &&
252 (total_len == AES_BLOCK_LEN))) {
253 if (pEncrypted != NULL) {
254 /*
255 * Save input data and its length in
256 * the remaining buffer of AES context.
257 */
258 (void) memcpy(soft_aes_ctx->data +
259 soft_aes_ctx->remain_len, pData, ulDataLen);
260 soft_aes_ctx->remain_len += ulDataLen;
261 }
262
263 /* Set encrypted data length to 0. */
264 *pulEncryptedLen = 0;
265 return (CKR_OK);
266 }
267
268 /* Compute the length of remaing data. */
269 remain = total_len % AES_BLOCK_LEN;
270
271 /*
272 * Make sure that the output length is a multiple of
273 * blocksize.
274 */
275 out_len = total_len - remain;
276
277 /*
278 * If application asks for the length of the output buffer
279 * to hold the ciphertext?
280 */
281 if (pEncrypted == NULL) {
282 *pulEncryptedLen = out_len;
283 return (CKR_OK);
284 }
285
286 /* Is the application-supplied buffer large enough? */
287 if (*pulEncryptedLen < out_len) {
288 *pulEncryptedLen = out_len;
289 return (CKR_BUFFER_TOO_SMALL);
290 }
291
292 if (soft_aes_ctx->remain_len != 0) {
293 /*
294 * Copy last remaining data and current input data
295 * to the output buffer.
296 */
297 (void) memmove(pEncrypted + soft_aes_ctx->remain_len,
298 pData, out_len - soft_aes_ctx->remain_len);
299 (void) memcpy(pEncrypted, soft_aes_ctx->data,
300 soft_aes_ctx->remain_len);
301 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
302
303 in_buf = pEncrypted;
304 } else {
305 in_buf = pData;
306 }
307 out_buf = pEncrypted;
308 }
309
310 do_encryption:
311 /*
312 * Begin Encryption now.
313 */
314 switch (mechanism) {
315
316 case CKM_AES_ECB:
317 {
318
319 ulong_t i;
320 uint8_t *tmp_inbuf;
321 uint8_t *tmp_outbuf;
322
323 for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
324 tmp_inbuf = &in_buf[i];
325 tmp_outbuf = &out_buf[i];
326 /* Crunch one block of data for AES. */
327 (void) aes_encrypt_block(soft_aes_ctx->key_sched,
328 tmp_inbuf, tmp_outbuf);
329 }
330
331 if (update) {
332 /*
333 * For encrypt update, if there is a remaining
334 * data, save it and its length in the context.
335 */
336 if (remain != 0)
337 (void) memcpy(soft_aes_ctx->data, pData +
338 (ulDataLen - remain), remain);
339 soft_aes_ctx->remain_len = remain;
340 }
341
342 *pulEncryptedLen = out_len;
343
344 break;
345 }
346
347 case CKM_AES_CBC:
348 case CKM_AES_CBC_PAD:
349 {
350 crypto_data_t out;
351
352 out.cd_format = CRYPTO_DATA_RAW;
353 out.cd_offset = 0;
354 out.cd_length = out_len;
355 out.cd_raw.iov_base = (char *)out_buf;
356 out.cd_raw.iov_len = out_len;
357
358 /* Encrypt multiple blocks of data. */
359 rc = aes_encrypt_contiguous_blocks(
360 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
361 (char *)in_buf, out_len, &out);
362
363 if (rc != 0)
364 goto encrypt_failed;
365
366 if (update) {
367 /*
368 * For encrypt update, if there is remaining data,
369 * save it and its length in the context.
370 */
371 if (remain != 0)
372 (void) memcpy(soft_aes_ctx->data, pData +
373 (ulDataLen - remain), remain);
374 soft_aes_ctx->remain_len = remain;
375 } else if (mechanism == CKM_AES_CBC_PAD) {
376 /*
377 * Save the remainder of the input
378 * block in a temporary block because
379 * we dont want to overrun the buffer
380 * by tacking on pad bytes.
381 */
382 CK_BYTE tmpblock[AES_BLOCK_LEN];
383 (void) memcpy(tmpblock, in_buf + out_len,
384 ulDataLen - out_len);
385 soft_add_pkcs7_padding(tmpblock +
386 (ulDataLen - out_len),
387 AES_BLOCK_LEN, ulDataLen - out_len);
388
389 out.cd_offset = out_len;
390 out.cd_length = AES_BLOCK_LEN;
391 out.cd_raw.iov_base = (char *)out_buf;
392 out.cd_raw.iov_len = out_len + AES_BLOCK_LEN;
393
394 /* Encrypt last block containing pad bytes. */
395 rc = aes_encrypt_contiguous_blocks(
396 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
397 (char *)tmpblock, AES_BLOCK_LEN, &out);
398
399 out_len += AES_BLOCK_LEN;
400 }
401
402 if (rc == 0) {
403 *pulEncryptedLen = out_len;
404 break;
405 }
406 encrypt_failed:
407 *pulEncryptedLen = 0;
408 rv = CKR_FUNCTION_FAILED;
409 goto cleanup;
410 }
411 case CKM_AES_CTR:
412 {
413 crypto_data_t out;
414
415 out.cd_format = CRYPTO_DATA_RAW;
416 out.cd_offset = 0;
417 out.cd_length = *pulEncryptedLen;
418 out.cd_raw.iov_base = (char *)pEncrypted;
419 out.cd_raw.iov_len = *pulEncryptedLen;
420
421 rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
422 (char *)pData, ulDataLen, &out);
423
424 if (rc != 0) {
425 *pulEncryptedLen = 0;
426 rv = CKR_FUNCTION_FAILED;
427 goto cleanup;
428 }
429 /*
430 * Since AES counter mode is a stream cipher, we call
431 * aes_counter_final() to pick up any remaining bytes.
432 * It is an internal function that does not destroy
433 * the context like *normal* final routines.
434 */
435 if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0)
436 rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
437 aes_encrypt_block);
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 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
452 if (aes_ctx != NULL) {
453 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
454 free(soft_aes_ctx->aes_cbc);
455 }
456
457 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
458 free(soft_aes_ctx->key_sched);
459 free(session_p->encrypt.context);
460 session_p->encrypt.context = NULL;
461 (void) pthread_mutex_unlock(&session_p->session_mutex);
462
463 return (rv);
464 }
465
466
467 /*
468 * soft_aes_decrypt_common()
469 *
470 * Arguments:
471 * session_p: pointer to soft_session_t struct
472 * pEncrypted: pointer to the input data to be decrypted
473 * ulEncryptedLen: length of the input data
474 * pData: pointer to the output data
475 * pulDataLen: pointer to the length of the output data
476 * Update: boolean flag indicates caller is soft_decrypt
477 * or soft_decrypt_update
478 *
479 * Description:
480 * This function calls the corresponding decrypt routine based
481 * on the mechanism.
482 *
483 * Returns:
484 * CKR_OK: success
485 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
486 * is too small
487 * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
488 * of blocksize
489 * CKR_FUNCTION_FAILED: decrypt function failed
490 */
491 CK_RV
soft_aes_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)492 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
493 CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
494 CK_ULONG_PTR pulDataLen, boolean_t update)
495 {
496
497 int rc = 0;
498 CK_RV rv = CKR_OK;
499 soft_aes_ctx_t *soft_aes_ctx =
500 (soft_aes_ctx_t *)session_p->decrypt.context;
501 aes_ctx_t *aes_ctx;
502 CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
503 CK_BYTE *in_buf = NULL;
504 CK_BYTE *out_buf = NULL;
505 CK_ULONG out_len;
506 CK_ULONG total_len;
507 CK_ULONG remain;
508
509 if (mechanism == CKM_AES_CTR)
510 goto do_decryption;
511
512 /*
513 * AES only takes input length that is a multiple of 16 bytes
514 * for C_Decrypt function with the mechanism CKM_AES_ECB,
515 * CKM_AES_CBC or CKM_AES_CBC_PAD.
516 *
517 * AES allows any input length for C_DecryptUpdate function.
518 */
519 if (!update) {
520 /*
521 * Called by C_Decrypt
522 */
523 if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
524 rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
525 goto cleanup;
526 }
527
528 /*
529 * If application asks for the length of the output buffer
530 * to hold the plaintext?
531 */
532 if (pData == NULL) {
533 *pulDataLen = ulEncryptedLen;
534 return (CKR_OK);
535 }
536
537 /* Is the application-supplied buffer large enough? */
538 if (mechanism != CKM_AES_CBC_PAD) {
539 if (*pulDataLen < ulEncryptedLen) {
540 *pulDataLen = ulEncryptedLen;
541 return (CKR_BUFFER_TOO_SMALL);
542 }
543 out_len = ulEncryptedLen;
544 } else {
545 /*
546 * For CKM_AES_CBC_PAD, we don't know how
547 * many bytes for padding at this time, so
548 * we'd assume one block was padded.
549 */
550 if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
551 *pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
552 return (CKR_BUFFER_TOO_SMALL);
553 }
554 out_len = ulEncryptedLen - AES_BLOCK_LEN;
555 }
556 in_buf = pEncrypted;
557 out_buf = pData;
558 } else {
559 /*
560 * Called by C_DecryptUpdate
561 *
562 * Add the lengths of last remaining data and current
563 * input data together to get the total input length.
564 */
565 total_len = soft_aes_ctx->remain_len + ulEncryptedLen;
566
567 /*
568 * If the total input length is less than one blocksize,
569 * or if the total input length is just one blocksize and
570 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
571 * decryption until when more data comes in next
572 * C_DecryptUpdate or when C_DecryptFinal is called.
573 */
574 if ((total_len < AES_BLOCK_LEN) ||
575 ((mechanism == CKM_AES_CBC_PAD) &&
576 (total_len == AES_BLOCK_LEN))) {
577 if (pData != NULL) {
578 /*
579 * Save input data and its length in
580 * the remaining buffer of AES context.
581 */
582 (void) memcpy(soft_aes_ctx->data +
583 soft_aes_ctx->remain_len,
584 pEncrypted, ulEncryptedLen);
585 soft_aes_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 % AES_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 (mechanism == CKM_AES_CBC_PAD) {
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 = AES_BLOCK_LEN;
611 out_len -= AES_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_aes_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_aes_ctx->remain_len,
638 pEncrypted, out_len - soft_aes_ctx->remain_len);
639 (void) memcpy(pData, soft_aes_ctx->data,
640 soft_aes_ctx->remain_len);
641 bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
642
643 in_buf = pData;
644 } else {
645 in_buf = pEncrypted;
646 }
647 out_buf = pData;
648 }
649
650 do_decryption:
651 /*
652 * Begin Decryption.
653 */
654 switch (mechanism) {
655
656 case CKM_AES_ECB:
657 {
658
659 ulong_t i;
660 uint8_t *tmp_inbuf;
661 uint8_t *tmp_outbuf;
662
663 for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
664 tmp_inbuf = &in_buf[i];
665 tmp_outbuf = &out_buf[i];
666 /* Crunch one block of data for AES. */
667 (void) aes_decrypt_block(soft_aes_ctx->key_sched,
668 tmp_inbuf, tmp_outbuf);
669 }
670
671 if (update) {
672 /*
673 * For decrypt update, if there is a remaining
674 * data, save it and its length in the context.
675 */
676 if (remain != 0)
677 (void) memcpy(soft_aes_ctx->data, pEncrypted +
678 (ulEncryptedLen - remain), remain);
679 soft_aes_ctx->remain_len = remain;
680 }
681
682 *pulDataLen = out_len;
683
684 break;
685 }
686
687 case CKM_AES_CBC:
688 case CKM_AES_CBC_PAD:
689 {
690 crypto_data_t out;
691 CK_ULONG rem_len;
692 uint8_t last_block[AES_BLOCK_LEN];
693
694 out.cd_format = CRYPTO_DATA_RAW;
695 out.cd_offset = 0;
696 out.cd_length = out_len;
697 out.cd_raw.iov_base = (char *)out_buf;
698 out.cd_raw.iov_len = out_len;
699
700 /* Decrypt multiple blocks of data. */
701 rc = aes_decrypt_contiguous_blocks(
702 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
703 (char *)in_buf, out_len, &out);
704
705 if (rc != 0)
706 goto decrypt_failed;
707
708 if ((mechanism == CKM_AES_CBC_PAD) && (!update)) {
709 /* Decrypt last block containing pad bytes. */
710 out.cd_offset = 0;
711 out.cd_length = AES_BLOCK_LEN;
712 out.cd_raw.iov_base = (char *)last_block;
713 out.cd_raw.iov_len = AES_BLOCK_LEN;
714
715 /* Decrypt last block containing pad bytes. */
716 rc = aes_decrypt_contiguous_blocks(
717 (aes_ctx_t *)soft_aes_ctx->aes_cbc,
718 (char *)in_buf + out_len, AES_BLOCK_LEN, &out);
719
720 if (rc != 0)
721 goto decrypt_failed;
722
723 /*
724 * Remove padding bytes after decryption of
725 * ciphertext block to produce the original
726 * plaintext.
727 */
728 rv = soft_remove_pkcs7_padding(last_block,
729 AES_BLOCK_LEN, &rem_len);
730 if (rv == CKR_OK) {
731 if (rem_len != 0)
732 (void) memcpy(out_buf + out_len,
733 last_block, rem_len);
734 *pulDataLen = out_len + rem_len;
735 } else {
736 *pulDataLen = 0;
737 goto cleanup;
738 }
739 } else {
740 *pulDataLen = out_len;
741 }
742
743 if (update) {
744 /*
745 * For decrypt update, if there is remaining data,
746 * save it and its length in the context.
747 */
748 if (remain != 0)
749 (void) memcpy(soft_aes_ctx->data, pEncrypted +
750 (ulEncryptedLen - remain), remain);
751 soft_aes_ctx->remain_len = remain;
752 }
753
754 if (rc == 0)
755 break;
756 decrypt_failed:
757 *pulDataLen = 0;
758 rv = CKR_FUNCTION_FAILED;
759 goto cleanup;
760 }
761 case CKM_AES_CTR:
762 {
763 crypto_data_t out;
764
765 out.cd_format = CRYPTO_DATA_RAW;
766 out.cd_offset = 0;
767 out.cd_length = *pulDataLen;
768 out.cd_raw.iov_base = (char *)pData;
769 out.cd_raw.iov_len = *pulDataLen;
770
771 rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
772 (char *)pEncrypted, ulEncryptedLen, &out);
773
774 if (rc != 0) {
775 *pulDataLen = 0;
776 rv = CKR_FUNCTION_FAILED;
777 goto cleanup;
778 }
779
780 /*
781 * Since AES counter mode is a stream cipher, we call
782 * aes_counter_final() to pick up any remaining bytes.
783 * It is an internal function that does not destroy
784 * the context like *normal* final routines.
785 */
786 if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
787 > 0) {
788 rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
789 aes_encrypt_block);
790 if (rc == CRYPTO_DATA_LEN_RANGE)
791 rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
792 }
793 }
794 } /* end switch */
795
796 if (update)
797 return (CKR_OK);
798
799 /*
800 * The following code will be executed if the caller is
801 * soft_decrypt() or an error occurred. The decryption
802 * operation will be terminated so we need to do some cleanup.
803 */
804 cleanup:
805 (void) pthread_mutex_lock(&session_p->session_mutex);
806 aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
807 if (aes_ctx != NULL) {
808 bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
809 free(soft_aes_ctx->aes_cbc);
810 }
811
812 bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
813 free(soft_aes_ctx->key_sched);
814 free(session_p->decrypt.context);
815 session_p->decrypt.context = NULL;
816 (void) pthread_mutex_unlock(&session_p->session_mutex);
817
818 return (rv);
819 }
820
821
822 /*
823 * Allocate and initialize a context for AES CBC mode of operation.
824 */
825 void *
aes_cbc_ctx_init(void * key_sched,size_t size,uint8_t * ivec)826 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
827 {
828
829 cbc_ctx_t *cbc_ctx;
830
831 if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
832 return (NULL);
833
834 cbc_ctx->cbc_keysched = key_sched;
835 cbc_ctx->cbc_keysched_len = size;
836
837 (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
838
839 cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
840 cbc_ctx->cbc_flags |= CBC_MODE;
841
842 return (cbc_ctx);
843 }
844
845 /*
846 * Allocate and initialize a context for AES CTR mode of operation.
847 */
848 void *
aes_ctr_ctx_init(void * key_sched,size_t size,uint8_t * param)849 aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
850 {
851
852 ctr_ctx_t *ctr_ctx;
853 CK_AES_CTR_PARAMS *pp;
854
855 /* LINTED: pointer alignment */
856 pp = (CK_AES_CTR_PARAMS *)param;
857
858 if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
859 return (NULL);
860
861 ctr_ctx->ctr_keysched = key_sched;
862 ctr_ctx->ctr_keysched_len = size;
863
864 if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block)
865 != CRYPTO_SUCCESS) {
866 free(ctr_ctx);
867 return (NULL);
868 }
869
870 return (ctr_ctx);
871 }
872