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