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