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