17188Smcpowers /* 27188Smcpowers * CDDL HEADER START 37188Smcpowers * 47188Smcpowers * The contents of this file are subject to the terms of the 57188Smcpowers * Common Development and Distribution License (the "License"). 67188Smcpowers * You may not use this file except in compliance with the License. 77188Smcpowers * 87188Smcpowers * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97188Smcpowers * or http://www.opensolaris.org/os/licensing. 107188Smcpowers * See the License for the specific language governing permissions 117188Smcpowers * and limitations under the License. 127188Smcpowers * 137188Smcpowers * When distributing Covered Code, include this CDDL HEADER in each 147188Smcpowers * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157188Smcpowers * If applicable, add the following below this CDDL HEADER, with the 167188Smcpowers * fields enclosed by brackets "[]" replaced with your own identifying 177188Smcpowers * information: Portions Copyright [yyyy] [name of copyright owner] 187188Smcpowers * 197188Smcpowers * CDDL HEADER END 207188Smcpowers */ 217188Smcpowers /* 22*11413Sopensolaris@drydog.com * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 237188Smcpowers * Use is subject to license terms. 247188Smcpowers */ 257188Smcpowers 267188Smcpowers #ifndef _KERNEL 277188Smcpowers #include <strings.h> 287188Smcpowers #include <limits.h> 297188Smcpowers #include <assert.h> 307188Smcpowers #include <security/cryptoki.h> 317188Smcpowers #endif 327188Smcpowers 337188Smcpowers #include <sys/types.h> 347188Smcpowers #include <sys/kmem.h> 357188Smcpowers #include <modes/modes.h> 367188Smcpowers #include <sys/crypto/common.h> 377188Smcpowers #include <sys/crypto/impl.h> 389392Sopensolaris@drydog.com #include <sys/byteorder.h> 397188Smcpowers 407421SDaniel.Anderson@Sun.COM #if defined(__i386) || defined(__amd64) 417421SDaniel.Anderson@Sun.COM #define UNALIGNED_POINTERS_PERMITTED 427421SDaniel.Anderson@Sun.COM #endif 437421SDaniel.Anderson@Sun.COM 447188Smcpowers /* 457188Smcpowers * Encrypt multiple blocks of data in CCM mode. Decrypt for CCM mode 467188Smcpowers * is done in another function. 477188Smcpowers */ 487188Smcpowers int 497188Smcpowers ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length, 507188Smcpowers crypto_data_t *out, size_t block_size, 517188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 527188Smcpowers void (*copy_block)(uint8_t *, uint8_t *), 537188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 547188Smcpowers { 557188Smcpowers size_t remainder = length; 567188Smcpowers size_t need; 577188Smcpowers uint8_t *datap = (uint8_t *)data; 587188Smcpowers uint8_t *blockp; 597188Smcpowers uint8_t *lastp; 607188Smcpowers void *iov_or_mp; 617188Smcpowers offset_t offset; 627188Smcpowers uint8_t *out_data_1; 637188Smcpowers uint8_t *out_data_2; 647188Smcpowers size_t out_data_1_len; 657188Smcpowers uint64_t counter; 667188Smcpowers uint8_t *mac_buf; 677188Smcpowers 687188Smcpowers if (length + ctx->ccm_remainder_len < block_size) { 697188Smcpowers /* accumulate bytes here and return */ 707188Smcpowers bcopy(datap, 717188Smcpowers (uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len, 727188Smcpowers length); 737188Smcpowers ctx->ccm_remainder_len += length; 747188Smcpowers ctx->ccm_copy_to = datap; 757188Smcpowers return (CRYPTO_SUCCESS); 767188Smcpowers } 777188Smcpowers 787188Smcpowers lastp = (uint8_t *)ctx->ccm_cb; 797188Smcpowers if (out != NULL) 807188Smcpowers crypto_init_ptrs(out, &iov_or_mp, &offset); 817188Smcpowers 827188Smcpowers mac_buf = (uint8_t *)ctx->ccm_mac_buf; 837188Smcpowers 847188Smcpowers do { 857188Smcpowers /* Unprocessed data from last call. */ 867188Smcpowers if (ctx->ccm_remainder_len > 0) { 877188Smcpowers need = block_size - ctx->ccm_remainder_len; 887188Smcpowers 897188Smcpowers if (need > remainder) 907188Smcpowers return (CRYPTO_DATA_LEN_RANGE); 917188Smcpowers 927188Smcpowers bcopy(datap, &((uint8_t *)ctx->ccm_remainder) 937188Smcpowers [ctx->ccm_remainder_len], need); 947188Smcpowers 957188Smcpowers blockp = (uint8_t *)ctx->ccm_remainder; 967188Smcpowers } else { 977188Smcpowers blockp = datap; 987188Smcpowers } 997188Smcpowers 1007188Smcpowers /* 1017188Smcpowers * do CBC MAC 1027188Smcpowers * 1037188Smcpowers * XOR the previous cipher block current clear block. 1047188Smcpowers * mac_buf always contain previous cipher block. 1057188Smcpowers */ 1067188Smcpowers xor_block(blockp, mac_buf); 1077188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 1087188Smcpowers 1097188Smcpowers /* ccm_cb is the counter block */ 1107188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, 1117188Smcpowers (uint8_t *)ctx->ccm_tmp); 1127188Smcpowers 1137188Smcpowers lastp = (uint8_t *)ctx->ccm_tmp; 1147188Smcpowers 1157188Smcpowers /* 1167188Smcpowers * Increment counter. Counter bits are confined 1177188Smcpowers * to the bottom 64 bits of the counter block. 1187188Smcpowers */ 1197421SDaniel.Anderson@Sun.COM counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask); 1207421SDaniel.Anderson@Sun.COM counter = htonll(counter + 1); 1217188Smcpowers counter &= ctx->ccm_counter_mask; 1227188Smcpowers ctx->ccm_cb[1] = 1237188Smcpowers (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 1247188Smcpowers 1257188Smcpowers /* 1267329SMark.Powers@Sun.COM * XOR encrypted counter block with the current clear block. 1277188Smcpowers */ 1287329SMark.Powers@Sun.COM xor_block(blockp, lastp); 1297188Smcpowers 1307188Smcpowers ctx->ccm_processed_data_len += block_size; 1317188Smcpowers 1327188Smcpowers if (out == NULL) { 1337188Smcpowers if (ctx->ccm_remainder_len > 0) { 1347188Smcpowers bcopy(blockp, ctx->ccm_copy_to, 1357188Smcpowers ctx->ccm_remainder_len); 1367188Smcpowers bcopy(blockp + ctx->ccm_remainder_len, datap, 1377188Smcpowers need); 1387188Smcpowers } 1397188Smcpowers } else { 1407188Smcpowers crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 1417188Smcpowers &out_data_1_len, &out_data_2, block_size); 1427188Smcpowers 1437188Smcpowers /* copy block to where it belongs */ 1447188Smcpowers if (out_data_1_len == block_size) { 1457188Smcpowers copy_block(lastp, out_data_1); 1467188Smcpowers } else { 1477188Smcpowers bcopy(lastp, out_data_1, out_data_1_len); 1487188Smcpowers if (out_data_2 != NULL) { 1497188Smcpowers bcopy(lastp + out_data_1_len, 1507188Smcpowers out_data_2, 1517188Smcpowers block_size - out_data_1_len); 1527188Smcpowers } 1537188Smcpowers } 1547188Smcpowers /* update offset */ 1557188Smcpowers out->cd_offset += block_size; 1567188Smcpowers } 1577188Smcpowers 1587188Smcpowers /* Update pointer to next block of data to be processed. */ 1597188Smcpowers if (ctx->ccm_remainder_len != 0) { 1607188Smcpowers datap += need; 1617188Smcpowers ctx->ccm_remainder_len = 0; 1627188Smcpowers } else { 1637188Smcpowers datap += block_size; 1647188Smcpowers } 1657188Smcpowers 1667188Smcpowers remainder = (size_t)&data[length] - (size_t)datap; 1677188Smcpowers 1687188Smcpowers /* Incomplete last block. */ 1697188Smcpowers if (remainder > 0 && remainder < block_size) { 1707188Smcpowers bcopy(datap, ctx->ccm_remainder, remainder); 1717188Smcpowers ctx->ccm_remainder_len = remainder; 1727188Smcpowers ctx->ccm_copy_to = datap; 1737188Smcpowers goto out; 1747188Smcpowers } 1757188Smcpowers ctx->ccm_copy_to = NULL; 1767188Smcpowers 1777188Smcpowers } while (remainder > 0); 1787188Smcpowers 1797188Smcpowers out: 1807188Smcpowers return (CRYPTO_SUCCESS); 1817188Smcpowers } 1827188Smcpowers 1837188Smcpowers void 1847188Smcpowers calculate_ccm_mac(ccm_ctx_t *ctx, uint8_t *ccm_mac, 1857188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)) 1867188Smcpowers { 1877188Smcpowers uint64_t counter; 1887188Smcpowers uint8_t *counterp, *mac_buf; 1897188Smcpowers int i; 1907188Smcpowers 1917188Smcpowers mac_buf = (uint8_t *)ctx->ccm_mac_buf; 1927188Smcpowers 1937188Smcpowers /* first counter block start with index 0 */ 1947188Smcpowers counter = 0; 1957188Smcpowers ctx->ccm_cb[1] = (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 1967188Smcpowers 1977188Smcpowers counterp = (uint8_t *)ctx->ccm_tmp; 1987188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp); 1997188Smcpowers 2007188Smcpowers /* calculate XOR of MAC with first counter block */ 2017188Smcpowers for (i = 0; i < ctx->ccm_mac_len; i++) { 2027188Smcpowers ccm_mac[i] = mac_buf[i] ^ counterp[i]; 2037188Smcpowers } 2047188Smcpowers } 2057188Smcpowers 2067188Smcpowers /* ARGSUSED */ 2077188Smcpowers int 2087188Smcpowers ccm_encrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size, 2097188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 2107188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 2117188Smcpowers { 2127188Smcpowers uint8_t *lastp, *mac_buf, *ccm_mac_p, *macp; 2137188Smcpowers void *iov_or_mp; 2147188Smcpowers offset_t offset; 2157188Smcpowers uint8_t *out_data_1; 2167188Smcpowers uint8_t *out_data_2; 2177188Smcpowers size_t out_data_1_len; 2187188Smcpowers int i; 2197188Smcpowers 2207188Smcpowers if (out->cd_length < (ctx->ccm_remainder_len + ctx->ccm_mac_len)) { 2217188Smcpowers return (CRYPTO_DATA_LEN_RANGE); 2227188Smcpowers } 2237188Smcpowers 2247188Smcpowers /* 2257188Smcpowers * When we get here, the number of bytes of payload processed 2267188Smcpowers * plus whatever data remains, if any, 2277188Smcpowers * should be the same as the number of bytes that's being 2287188Smcpowers * passed in the argument during init time. 2297188Smcpowers */ 2307188Smcpowers if ((ctx->ccm_processed_data_len + ctx->ccm_remainder_len) 2317188Smcpowers != (ctx->ccm_data_len)) { 2327188Smcpowers return (CRYPTO_DATA_LEN_RANGE); 2337188Smcpowers } 2347188Smcpowers 2357188Smcpowers mac_buf = (uint8_t *)ctx->ccm_mac_buf; 2367188Smcpowers 2377188Smcpowers if (ctx->ccm_remainder_len > 0) { 2387188Smcpowers 2397188Smcpowers /* ccm_mac_input_buf is not used for encryption */ 2407188Smcpowers macp = (uint8_t *)ctx->ccm_mac_input_buf; 2417188Smcpowers bzero(macp, block_size); 2427188Smcpowers 2437188Smcpowers /* copy remainder to temporary buffer */ 2447188Smcpowers bcopy(ctx->ccm_remainder, macp, ctx->ccm_remainder_len); 2457188Smcpowers 2467188Smcpowers /* calculate the CBC MAC */ 2477188Smcpowers xor_block(macp, mac_buf); 2487188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 2497188Smcpowers 2507188Smcpowers /* calculate the counter mode */ 2517188Smcpowers lastp = (uint8_t *)ctx->ccm_tmp; 2527188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, lastp); 2537188Smcpowers 2547188Smcpowers /* XOR with counter block */ 2557188Smcpowers for (i = 0; i < ctx->ccm_remainder_len; i++) { 2567188Smcpowers macp[i] ^= lastp[i]; 2577188Smcpowers } 2587188Smcpowers ctx->ccm_processed_data_len += ctx->ccm_remainder_len; 2597188Smcpowers } 2607188Smcpowers 2617188Smcpowers /* Calculate the CCM MAC */ 2627188Smcpowers ccm_mac_p = (uint8_t *)ctx->ccm_tmp; 2637188Smcpowers calculate_ccm_mac(ctx, ccm_mac_p, encrypt_block); 2647188Smcpowers 2657188Smcpowers crypto_init_ptrs(out, &iov_or_mp, &offset); 2667188Smcpowers crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 2677188Smcpowers &out_data_1_len, &out_data_2, 2687188Smcpowers ctx->ccm_remainder_len + ctx->ccm_mac_len); 2697188Smcpowers 2707188Smcpowers if (ctx->ccm_remainder_len > 0) { 2717188Smcpowers 2727188Smcpowers /* copy temporary block to where it belongs */ 2737188Smcpowers if (out_data_2 == NULL) { 2747188Smcpowers /* everything will fit in out_data_1 */ 2757188Smcpowers bcopy(macp, out_data_1, ctx->ccm_remainder_len); 2767188Smcpowers bcopy(ccm_mac_p, out_data_1 + ctx->ccm_remainder_len, 2777188Smcpowers ctx->ccm_mac_len); 2787188Smcpowers } else { 2797188Smcpowers 2807188Smcpowers if (out_data_1_len < ctx->ccm_remainder_len) { 2817188Smcpowers 2827188Smcpowers size_t data_2_len_used; 2837188Smcpowers 2847188Smcpowers bcopy(macp, out_data_1, out_data_1_len); 2857188Smcpowers 2867188Smcpowers data_2_len_used = ctx->ccm_remainder_len 2877188Smcpowers - out_data_1_len; 2887188Smcpowers 2897188Smcpowers bcopy((uint8_t *)macp + out_data_1_len, 2907188Smcpowers out_data_2, data_2_len_used); 2917188Smcpowers bcopy(ccm_mac_p, out_data_2 + data_2_len_used, 2927188Smcpowers ctx->ccm_mac_len); 2937188Smcpowers } else { 2947188Smcpowers bcopy(macp, out_data_1, out_data_1_len); 2957188Smcpowers if (out_data_1_len == ctx->ccm_remainder_len) { 2967188Smcpowers /* mac will be in out_data_2 */ 2977188Smcpowers bcopy(ccm_mac_p, out_data_2, 2987188Smcpowers ctx->ccm_mac_len); 2997188Smcpowers } else { 3007421SDaniel.Anderson@Sun.COM size_t len_not_used = out_data_1_len - 3017188Smcpowers ctx->ccm_remainder_len; 3027188Smcpowers /* 3037188Smcpowers * part of mac in will be in 3047188Smcpowers * out_data_1, part of the mac will be 3057188Smcpowers * in out_data_2 3067188Smcpowers */ 3077188Smcpowers bcopy(ccm_mac_p, 3087188Smcpowers out_data_1 + ctx->ccm_remainder_len, 3097188Smcpowers len_not_used); 3107188Smcpowers bcopy(ccm_mac_p + len_not_used, 3117188Smcpowers out_data_2, 3127188Smcpowers ctx->ccm_mac_len - len_not_used); 3137188Smcpowers 3147188Smcpowers } 3157188Smcpowers } 3167188Smcpowers } 3177188Smcpowers } else { 3187188Smcpowers /* copy block to where it belongs */ 3197188Smcpowers bcopy(ccm_mac_p, out_data_1, out_data_1_len); 3207188Smcpowers if (out_data_2 != NULL) { 3217188Smcpowers bcopy(ccm_mac_p + out_data_1_len, out_data_2, 3227188Smcpowers block_size - out_data_1_len); 3237188Smcpowers } 3247188Smcpowers } 3257188Smcpowers out->cd_offset += ctx->ccm_remainder_len + ctx->ccm_mac_len; 3267188Smcpowers ctx->ccm_remainder_len = 0; 3277188Smcpowers return (CRYPTO_SUCCESS); 3287188Smcpowers } 3297188Smcpowers 3307188Smcpowers /* 3317188Smcpowers * This will only deal with decrypting the last block of the input that 3327188Smcpowers * might not be a multiple of block length. 3337188Smcpowers */ 3347188Smcpowers void 3357188Smcpowers ccm_decrypt_incomplete_block(ccm_ctx_t *ctx, 3367188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)) 3377188Smcpowers { 3387188Smcpowers uint8_t *datap, *outp, *counterp; 3397188Smcpowers int i; 3407188Smcpowers 3417188Smcpowers datap = (uint8_t *)ctx->ccm_remainder; 3427188Smcpowers outp = &((ctx->ccm_pt_buf)[ctx->ccm_processed_data_len]); 3437188Smcpowers 3447188Smcpowers counterp = (uint8_t *)ctx->ccm_tmp; 3457188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp); 3467188Smcpowers 3477188Smcpowers /* XOR with counter block */ 3487188Smcpowers for (i = 0; i < ctx->ccm_remainder_len; i++) { 3497188Smcpowers outp[i] = datap[i] ^ counterp[i]; 3507188Smcpowers } 3517188Smcpowers } 3527188Smcpowers 3537188Smcpowers /* 3547188Smcpowers * This will decrypt the cipher text. However, the plaintext won't be 3557188Smcpowers * returned to the caller. It will be returned when decrypt_final() is 3567188Smcpowers * called if the MAC matches 3577188Smcpowers */ 3587188Smcpowers /* ARGSUSED */ 3597188Smcpowers int 3607188Smcpowers ccm_mode_decrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length, 3617188Smcpowers crypto_data_t *out, size_t block_size, 3627188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 3637188Smcpowers void (*copy_block)(uint8_t *, uint8_t *), 3647188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 3657188Smcpowers { 3667188Smcpowers size_t remainder = length; 3677188Smcpowers size_t need; 3687188Smcpowers uint8_t *datap = (uint8_t *)data; 3697188Smcpowers uint8_t *blockp; 3707188Smcpowers uint8_t *cbp; 3717188Smcpowers uint64_t counter; 3727188Smcpowers size_t pt_len, total_decrypted_len, mac_len, pm_len, pd_len; 3737188Smcpowers uint8_t *resultp; 3747188Smcpowers 3757188Smcpowers 3767188Smcpowers pm_len = ctx->ccm_processed_mac_len; 3777188Smcpowers 3787188Smcpowers if (pm_len > 0) { 3797188Smcpowers uint8_t *tmp; 3807188Smcpowers /* 3817188Smcpowers * all ciphertext has been processed, just waiting for 3827188Smcpowers * part of the value of the mac 3837188Smcpowers */ 3847188Smcpowers if ((pm_len + length) > ctx->ccm_mac_len) { 3857188Smcpowers return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 3867188Smcpowers } 3877188Smcpowers tmp = (uint8_t *)ctx->ccm_mac_input_buf; 3887188Smcpowers 3897188Smcpowers bcopy(datap, tmp + pm_len, length); 3907188Smcpowers 3917188Smcpowers ctx->ccm_processed_mac_len += length; 3927188Smcpowers return (CRYPTO_SUCCESS); 3937188Smcpowers } 3947188Smcpowers 3957188Smcpowers /* 3967188Smcpowers * If we decrypt the given data, what total amount of data would 3977188Smcpowers * have been decrypted? 3987188Smcpowers */ 3997188Smcpowers pd_len = ctx->ccm_processed_data_len; 4007188Smcpowers total_decrypted_len = pd_len + length + ctx->ccm_remainder_len; 4017188Smcpowers 4027188Smcpowers if (total_decrypted_len > 4037188Smcpowers (ctx->ccm_data_len + ctx->ccm_mac_len)) { 4047188Smcpowers return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 4057188Smcpowers } 4067188Smcpowers 4077188Smcpowers pt_len = ctx->ccm_data_len; 4087188Smcpowers 4097188Smcpowers if (total_decrypted_len > pt_len) { 4107188Smcpowers /* 4117188Smcpowers * part of the input will be the MAC, need to isolate that 4127188Smcpowers * to be dealt with later. The left-over data in 4137188Smcpowers * ccm_remainder_len from last time will not be part of the 4147188Smcpowers * MAC. Otherwise, it would have already been taken out 4157188Smcpowers * when this call is made last time. 4167188Smcpowers */ 4177188Smcpowers size_t pt_part = pt_len - pd_len - ctx->ccm_remainder_len; 4187188Smcpowers 4197188Smcpowers mac_len = length - pt_part; 4207188Smcpowers 4217188Smcpowers ctx->ccm_processed_mac_len = mac_len; 4227188Smcpowers bcopy(data + pt_part, ctx->ccm_mac_input_buf, mac_len); 4237188Smcpowers 4247188Smcpowers if (pt_part + ctx->ccm_remainder_len < block_size) { 4257188Smcpowers /* 4267188Smcpowers * since this is last of the ciphertext, will 4277188Smcpowers * just decrypt with it here 4287188Smcpowers */ 4297188Smcpowers bcopy(datap, &((uint8_t *)ctx->ccm_remainder) 4307188Smcpowers [ctx->ccm_remainder_len], pt_part); 4317188Smcpowers ctx->ccm_remainder_len += pt_part; 4327188Smcpowers ccm_decrypt_incomplete_block(ctx, encrypt_block); 4337188Smcpowers ctx->ccm_remainder_len = 0; 4347188Smcpowers ctx->ccm_processed_data_len += pt_part; 4357188Smcpowers return (CRYPTO_SUCCESS); 4367188Smcpowers } else { 4377188Smcpowers /* let rest of the code handle this */ 4387188Smcpowers length = pt_part; 4397188Smcpowers } 4407188Smcpowers } else if (length + ctx->ccm_remainder_len < block_size) { 4417188Smcpowers /* accumulate bytes here and return */ 4427188Smcpowers bcopy(datap, 4437188Smcpowers (uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len, 4447188Smcpowers length); 4457188Smcpowers ctx->ccm_remainder_len += length; 4467188Smcpowers ctx->ccm_copy_to = datap; 4477188Smcpowers return (CRYPTO_SUCCESS); 4487188Smcpowers } 4497188Smcpowers 4507188Smcpowers do { 4517188Smcpowers /* Unprocessed data from last call. */ 4527188Smcpowers if (ctx->ccm_remainder_len > 0) { 4537188Smcpowers need = block_size - ctx->ccm_remainder_len; 4547188Smcpowers 4557188Smcpowers if (need > remainder) 4567188Smcpowers return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 4577188Smcpowers 4587188Smcpowers bcopy(datap, &((uint8_t *)ctx->ccm_remainder) 4597188Smcpowers [ctx->ccm_remainder_len], need); 4607188Smcpowers 4617188Smcpowers blockp = (uint8_t *)ctx->ccm_remainder; 4627188Smcpowers } else { 4637188Smcpowers blockp = datap; 4647188Smcpowers } 4657188Smcpowers 4667188Smcpowers /* Calculate the counter mode, ccm_cb is the counter block */ 4677188Smcpowers cbp = (uint8_t *)ctx->ccm_tmp; 4687188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, cbp); 4697188Smcpowers 4707188Smcpowers /* 4717188Smcpowers * Increment counter. 4727188Smcpowers * Counter bits are confined to the bottom 64 bits 4737188Smcpowers */ 4747421SDaniel.Anderson@Sun.COM counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask); 4757421SDaniel.Anderson@Sun.COM counter = htonll(counter + 1); 4767188Smcpowers counter &= ctx->ccm_counter_mask; 4777188Smcpowers ctx->ccm_cb[1] = 4787188Smcpowers (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 4797188Smcpowers 4807188Smcpowers /* XOR with the ciphertext */ 4817188Smcpowers xor_block(blockp, cbp); 4827188Smcpowers 4837188Smcpowers /* Copy the plaintext to the "holding buffer" */ 4847188Smcpowers resultp = (uint8_t *)ctx->ccm_pt_buf + 4857188Smcpowers ctx->ccm_processed_data_len; 4867188Smcpowers copy_block(cbp, resultp); 4877188Smcpowers 4887188Smcpowers ctx->ccm_processed_data_len += block_size; 4897188Smcpowers 4907188Smcpowers ctx->ccm_lastp = blockp; 4917188Smcpowers 4927188Smcpowers /* Update pointer to next block of data to be processed. */ 4937188Smcpowers if (ctx->ccm_remainder_len != 0) { 4947188Smcpowers datap += need; 4957188Smcpowers ctx->ccm_remainder_len = 0; 4967188Smcpowers } else { 4977188Smcpowers datap += block_size; 4987188Smcpowers } 4997188Smcpowers 5007188Smcpowers remainder = (size_t)&data[length] - (size_t)datap; 5017188Smcpowers 5027188Smcpowers /* Incomplete last block */ 5037188Smcpowers if (remainder > 0 && remainder < block_size) { 5047188Smcpowers bcopy(datap, ctx->ccm_remainder, remainder); 5057188Smcpowers ctx->ccm_remainder_len = remainder; 5067188Smcpowers ctx->ccm_copy_to = datap; 5077188Smcpowers if (ctx->ccm_processed_mac_len > 0) { 5087188Smcpowers /* 5097188Smcpowers * not expecting anymore ciphertext, just 5107188Smcpowers * compute plaintext for the remaining input 5117188Smcpowers */ 5127188Smcpowers ccm_decrypt_incomplete_block(ctx, 5137188Smcpowers encrypt_block); 5147188Smcpowers ctx->ccm_processed_data_len += remainder; 5157188Smcpowers ctx->ccm_remainder_len = 0; 5167188Smcpowers } 5177188Smcpowers goto out; 5187188Smcpowers } 5197188Smcpowers ctx->ccm_copy_to = NULL; 5207188Smcpowers 5217188Smcpowers } while (remainder > 0); 5227188Smcpowers 5237188Smcpowers out: 5247188Smcpowers return (CRYPTO_SUCCESS); 5257188Smcpowers } 5267188Smcpowers 5277188Smcpowers int 5287188Smcpowers ccm_decrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size, 5297188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 5307188Smcpowers void (*copy_block)(uint8_t *, uint8_t *), 5317188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 5327188Smcpowers { 5337188Smcpowers size_t mac_remain, pt_len; 5347188Smcpowers uint8_t *pt, *mac_buf, *macp, *ccm_mac_p; 5357537SMark.Powers@Sun.COM int rv; 5367188Smcpowers 5377188Smcpowers pt_len = ctx->ccm_data_len; 5387188Smcpowers 5397188Smcpowers /* Make sure output buffer can fit all of the plaintext */ 5407188Smcpowers if (out->cd_length < pt_len) { 5417188Smcpowers return (CRYPTO_DATA_LEN_RANGE); 5427188Smcpowers } 5437188Smcpowers 5447188Smcpowers pt = ctx->ccm_pt_buf; 5457188Smcpowers mac_remain = ctx->ccm_processed_data_len; 5467188Smcpowers mac_buf = (uint8_t *)ctx->ccm_mac_buf; 5477188Smcpowers 5487188Smcpowers macp = (uint8_t *)ctx->ccm_tmp; 5497188Smcpowers 5507188Smcpowers while (mac_remain > 0) { 5517188Smcpowers 5527188Smcpowers if (mac_remain < block_size) { 5537188Smcpowers bzero(macp, block_size); 5547188Smcpowers bcopy(pt, macp, mac_remain); 5557188Smcpowers mac_remain = 0; 5567188Smcpowers } else { 5577188Smcpowers copy_block(pt, macp); 5587188Smcpowers mac_remain -= block_size; 5597188Smcpowers pt += block_size; 5607188Smcpowers } 5617188Smcpowers 5627188Smcpowers /* calculate the CBC MAC */ 5637188Smcpowers xor_block(macp, mac_buf); 5647188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 5657188Smcpowers } 5667188Smcpowers 5677188Smcpowers /* Calculate the CCM MAC */ 5687188Smcpowers ccm_mac_p = (uint8_t *)ctx->ccm_tmp; 5697188Smcpowers calculate_ccm_mac((ccm_ctx_t *)ctx, ccm_mac_p, encrypt_block); 5707188Smcpowers 5717188Smcpowers /* compare the input CCM MAC value with what we calculated */ 5727188Smcpowers if (bcmp(ctx->ccm_mac_input_buf, ccm_mac_p, ctx->ccm_mac_len)) { 5737188Smcpowers /* They don't match */ 5747188Smcpowers return (CRYPTO_INVALID_MAC); 5757188Smcpowers } else { 5767537SMark.Powers@Sun.COM rv = crypto_put_output_data(ctx->ccm_pt_buf, out, pt_len); 5777537SMark.Powers@Sun.COM if (rv != CRYPTO_SUCCESS) 5787537SMark.Powers@Sun.COM return (rv); 5797188Smcpowers out->cd_offset += pt_len; 5807188Smcpowers } 5817188Smcpowers return (CRYPTO_SUCCESS); 5827188Smcpowers } 5837188Smcpowers 5847188Smcpowers int 5857188Smcpowers ccm_validate_args(CK_AES_CCM_PARAMS *ccm_param, boolean_t is_encrypt_init) 5867188Smcpowers { 5877188Smcpowers size_t macSize, nonceSize; 5887188Smcpowers uint8_t q; 5897188Smcpowers uint64_t maxValue; 5907188Smcpowers 5917188Smcpowers /* 5927188Smcpowers * Check the length of the MAC. The only valid 5937188Smcpowers * lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16 5947188Smcpowers */ 5957188Smcpowers macSize = ccm_param->ulMACSize; 5967188Smcpowers if ((macSize < 4) || (macSize > 16) || ((macSize % 2) != 0)) { 5977188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 5987188Smcpowers } 5997188Smcpowers 6007188Smcpowers /* Check the nonce length. Valid values are 7, 8, 9, 10, 11, 12, 13 */ 6017188Smcpowers nonceSize = ccm_param->ulNonceSize; 6027188Smcpowers if ((nonceSize < 7) || (nonceSize > 13)) { 6037188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 6047188Smcpowers } 6057188Smcpowers 6067188Smcpowers /* q is the length of the field storing the length, in bytes */ 6077188Smcpowers q = (uint8_t)((15 - nonceSize) & 0xFF); 6087188Smcpowers 6097188Smcpowers 6107188Smcpowers /* 6117188Smcpowers * If it is decrypt, need to make sure size of ciphertext is at least 6127188Smcpowers * bigger than MAC len 6137188Smcpowers */ 6147188Smcpowers if ((!is_encrypt_init) && (ccm_param->ulDataSize < macSize)) { 6157188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 6167188Smcpowers } 6177188Smcpowers 6187188Smcpowers /* 6197188Smcpowers * Check to make sure the length of the payload is within the 6207188Smcpowers * range of values allowed by q 6217188Smcpowers */ 6227188Smcpowers if (q < 8) { 6237188Smcpowers maxValue = (1ULL << (q * 8)) - 1; 6247188Smcpowers } else { 6257188Smcpowers maxValue = ULONG_MAX; 6267188Smcpowers } 6277188Smcpowers 6287188Smcpowers if (ccm_param->ulDataSize > maxValue) { 6297188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 6307188Smcpowers } 6317188Smcpowers return (CRYPTO_SUCCESS); 6327188Smcpowers } 6337188Smcpowers 6347188Smcpowers /* 6357188Smcpowers * Format the first block used in CBC-MAC (B0) and the initial counter 6367188Smcpowers * block based on formatting functions and counter generation functions 6377188Smcpowers * specified in RFC 3610 and NIST publication 800-38C, appendix A 6387188Smcpowers * 6397188Smcpowers * b0 is the first block used in CBC-MAC 6407188Smcpowers * cb0 is the first counter block 6417188Smcpowers * 6427188Smcpowers * It's assumed that the arguments b0 and cb0 are preallocated AES blocks 6437188Smcpowers * 6447188Smcpowers */ 6457188Smcpowers static void 6467188Smcpowers ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize, 6477188Smcpowers ulong_t authDataSize, uint8_t *b0, ccm_ctx_t *aes_ctx) 6487188Smcpowers { 6497188Smcpowers uint64_t payloadSize; 6507188Smcpowers uint8_t t, q, have_adata = 0; 6517188Smcpowers size_t limit; 6527188Smcpowers int i, j, k; 6537188Smcpowers uint64_t mask = 0; 6547188Smcpowers uint8_t *cb; 6557188Smcpowers 6567188Smcpowers q = (uint8_t)((15 - nonceSize) & 0xFF); 6577188Smcpowers t = (uint8_t)((aes_ctx->ccm_mac_len) & 0xFF); 6587188Smcpowers 6597188Smcpowers /* Construct the first octet of b0 */ 6607188Smcpowers if (authDataSize > 0) { 6617188Smcpowers have_adata = 1; 6627188Smcpowers } 6637188Smcpowers b0[0] = (have_adata << 6) | (((t - 2) / 2) << 3) | (q - 1); 6647188Smcpowers 6657188Smcpowers /* copy the nonce value into b0 */ 6667188Smcpowers bcopy(nonce, &(b0[1]), nonceSize); 6677188Smcpowers 6687188Smcpowers /* store the length of the payload into b0 */ 6697188Smcpowers bzero(&(b0[1+nonceSize]), q); 6707188Smcpowers 6717188Smcpowers payloadSize = aes_ctx->ccm_data_len; 6727188Smcpowers limit = 8 < q ? 8 : q; 6737188Smcpowers 6747188Smcpowers for (i = 0, j = 0, k = 15; i < limit; i++, j += 8, k--) { 6757188Smcpowers b0[k] = (uint8_t)((payloadSize >> j) & 0xFF); 6767188Smcpowers } 6777188Smcpowers 6787188Smcpowers /* format the counter block */ 6797188Smcpowers 6807188Smcpowers cb = (uint8_t *)aes_ctx->ccm_cb; 6817188Smcpowers 6827188Smcpowers cb[0] = 0x07 & (q-1); /* first byte */ 6837188Smcpowers 6847188Smcpowers /* copy the nonce value into the counter block */ 6857188Smcpowers bcopy(nonce, &(cb[1]), nonceSize); 6867188Smcpowers 6877188Smcpowers bzero(&(cb[1+nonceSize]), q); 6887188Smcpowers 6897188Smcpowers /* Create the mask for the counter field based on the size of nonce */ 6907188Smcpowers q <<= 3; 6917188Smcpowers while (q-- > 0) { 6927188Smcpowers mask |= (1ULL << q); 6937188Smcpowers } 6947188Smcpowers 6959392Sopensolaris@drydog.com aes_ctx->ccm_counter_mask = htonll(mask); 6967188Smcpowers 6977188Smcpowers /* 6987188Smcpowers * During calculation, we start using counter block 1, we will 6997188Smcpowers * set it up right here. 7007188Smcpowers * We can just set the last byte to have the value 1, because 7017188Smcpowers * even with the biggest nonce of 13, the last byte of the 7027188Smcpowers * counter block will be used for the counter value. 7037188Smcpowers */ 7047188Smcpowers cb[15] = 0x01; 7057188Smcpowers } 7067188Smcpowers 7077188Smcpowers /* 7087188Smcpowers * Encode the length of the associated data as 7097188Smcpowers * specified in RFC 3610 and NIST publication 800-38C, appendix A 7107188Smcpowers */ 7117188Smcpowers static void 7127188Smcpowers encode_adata_len(ulong_t auth_data_len, uint8_t *encoded, size_t *encoded_len) 7137188Smcpowers { 7147421SDaniel.Anderson@Sun.COM #ifdef UNALIGNED_POINTERS_PERMITTED 7157421SDaniel.Anderson@Sun.COM uint32_t *lencoded_ptr; 7167421SDaniel.Anderson@Sun.COM #ifdef _LP64 7177421SDaniel.Anderson@Sun.COM uint64_t *llencoded_ptr; 7187421SDaniel.Anderson@Sun.COM #endif 7197421SDaniel.Anderson@Sun.COM #endif /* UNALIGNED_POINTERS_PERMITTED */ 7207421SDaniel.Anderson@Sun.COM 7217188Smcpowers if (auth_data_len < ((1ULL<<16) - (1ULL<<8))) { 7227188Smcpowers /* 0 < a < (2^16-2^8) */ 7237188Smcpowers *encoded_len = 2; 7247188Smcpowers encoded[0] = (auth_data_len & 0xff00) >> 8; 7257188Smcpowers encoded[1] = auth_data_len & 0xff; 7267188Smcpowers 7277188Smcpowers } else if ((auth_data_len >= ((1ULL<<16) - (1ULL<<8))) && 7287188Smcpowers (auth_data_len < (1ULL << 31))) { 7297188Smcpowers /* (2^16-2^8) <= a < 2^32 */ 7307188Smcpowers *encoded_len = 6; 7317188Smcpowers encoded[0] = 0xff; 7327188Smcpowers encoded[1] = 0xfe; 7337421SDaniel.Anderson@Sun.COM #ifdef UNALIGNED_POINTERS_PERMITTED 734*11413Sopensolaris@drydog.com lencoded_ptr = (uint32_t *)(void *)&encoded[2]; 7357421SDaniel.Anderson@Sun.COM *lencoded_ptr = htonl(auth_data_len); 7367421SDaniel.Anderson@Sun.COM #else 7377188Smcpowers encoded[2] = (auth_data_len & 0xff000000) >> 24; 7387188Smcpowers encoded[3] = (auth_data_len & 0xff0000) >> 16; 7397188Smcpowers encoded[4] = (auth_data_len & 0xff00) >> 8; 7407188Smcpowers encoded[5] = auth_data_len & 0xff; 7417421SDaniel.Anderson@Sun.COM #endif /* UNALIGNED_POINTERS_PERMITTED */ 7427421SDaniel.Anderson@Sun.COM 7437188Smcpowers #ifdef _LP64 7447188Smcpowers } else { 7457188Smcpowers /* 2^32 <= a < 2^64 */ 7467188Smcpowers *encoded_len = 10; 7477188Smcpowers encoded[0] = 0xff; 7487188Smcpowers encoded[1] = 0xff; 7497421SDaniel.Anderson@Sun.COM #ifdef UNALIGNED_POINTERS_PERMITTED 750*11413Sopensolaris@drydog.com llencoded_ptr = (uint64_t *)(void *)&encoded[2]; 7517421SDaniel.Anderson@Sun.COM *llencoded_ptr = htonl(auth_data_len); 7527421SDaniel.Anderson@Sun.COM #else 7537188Smcpowers encoded[2] = (auth_data_len & 0xff00000000000000) >> 56; 7547188Smcpowers encoded[3] = (auth_data_len & 0xff000000000000) >> 48; 7557188Smcpowers encoded[4] = (auth_data_len & 0xff0000000000) >> 40; 7567188Smcpowers encoded[5] = (auth_data_len & 0xff00000000) >> 32; 7577188Smcpowers encoded[6] = (auth_data_len & 0xff000000) >> 24; 7587188Smcpowers encoded[7] = (auth_data_len & 0xff0000) >> 16; 7597188Smcpowers encoded[8] = (auth_data_len & 0xff00) >> 8; 7607188Smcpowers encoded[9] = auth_data_len & 0xff; 7617421SDaniel.Anderson@Sun.COM #endif /* UNALIGNED_POINTERS_PERMITTED */ 7627188Smcpowers #endif /* _LP64 */ 7637188Smcpowers } 7647188Smcpowers } 7657188Smcpowers 7667188Smcpowers /* 7677188Smcpowers * The following function should be call at encrypt or decrypt init time 7687188Smcpowers * for AES CCM mode. 7697188Smcpowers */ 7707188Smcpowers int 7717188Smcpowers ccm_init(ccm_ctx_t *ctx, unsigned char *nonce, size_t nonce_len, 7727188Smcpowers unsigned char *auth_data, size_t auth_data_len, size_t block_size, 7737188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 7747188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 7757188Smcpowers { 7767188Smcpowers uint8_t *mac_buf, *datap, *ivp, *authp; 7777188Smcpowers size_t remainder, processed; 7787188Smcpowers uint8_t encoded_a[10]; /* max encoded auth data length is 10 octets */ 7797188Smcpowers size_t encoded_a_len = 0; 7807188Smcpowers 7817188Smcpowers mac_buf = (uint8_t *)&(ctx->ccm_mac_buf); 7827188Smcpowers 7837188Smcpowers /* 7847188Smcpowers * Format the 1st block for CBC-MAC and construct the 7857188Smcpowers * 1st counter block. 7867188Smcpowers * 7877188Smcpowers * aes_ctx->ccm_iv is used for storing the counter block 7887188Smcpowers * mac_buf will store b0 at this time. 7897188Smcpowers */ 7907188Smcpowers ccm_format_initial_blocks(nonce, nonce_len, 7917188Smcpowers auth_data_len, mac_buf, ctx); 7927188Smcpowers 7937188Smcpowers /* The IV for CBC MAC for AES CCM mode is always zero */ 7947188Smcpowers ivp = (uint8_t *)ctx->ccm_tmp; 7957188Smcpowers bzero(ivp, block_size); 7967188Smcpowers 7977188Smcpowers xor_block(ivp, mac_buf); 7987188Smcpowers 7997188Smcpowers /* encrypt the nonce */ 8007188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 8017188Smcpowers 8027188Smcpowers /* take care of the associated data, if any */ 8037188Smcpowers if (auth_data_len == 0) { 8047188Smcpowers return (CRYPTO_SUCCESS); 8057188Smcpowers } 8067188Smcpowers 8077188Smcpowers encode_adata_len(auth_data_len, encoded_a, &encoded_a_len); 8087188Smcpowers 8097188Smcpowers remainder = auth_data_len; 8107188Smcpowers 8117188Smcpowers /* 1st block: it contains encoded associated data, and some data */ 8127188Smcpowers authp = (uint8_t *)ctx->ccm_tmp; 8137188Smcpowers bzero(authp, block_size); 8147188Smcpowers bcopy(encoded_a, authp, encoded_a_len); 8157188Smcpowers processed = block_size - encoded_a_len; 8167188Smcpowers if (processed > auth_data_len) { 8177188Smcpowers /* in case auth_data is very small */ 8187188Smcpowers processed = auth_data_len; 8197188Smcpowers } 8207188Smcpowers bcopy(auth_data, authp+encoded_a_len, processed); 8217188Smcpowers /* xor with previous buffer */ 8227188Smcpowers xor_block(authp, mac_buf); 8237188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 8247188Smcpowers remainder -= processed; 8257188Smcpowers if (remainder == 0) { 8267188Smcpowers /* a small amount of associated data, it's all done now */ 8277188Smcpowers return (CRYPTO_SUCCESS); 8287188Smcpowers } 8297188Smcpowers 8307188Smcpowers do { 8317188Smcpowers if (remainder < block_size) { 8327188Smcpowers /* 8337188Smcpowers * There's not a block full of data, pad rest of 8347188Smcpowers * buffer with zero 8357188Smcpowers */ 8367188Smcpowers bzero(authp, block_size); 8377188Smcpowers bcopy(&(auth_data[processed]), authp, remainder); 8387188Smcpowers datap = (uint8_t *)authp; 8397188Smcpowers remainder = 0; 8407188Smcpowers } else { 8417188Smcpowers datap = (uint8_t *)(&(auth_data[processed])); 8427188Smcpowers processed += block_size; 8437188Smcpowers remainder -= block_size; 8447188Smcpowers } 8457188Smcpowers 8467188Smcpowers xor_block(datap, mac_buf); 8477188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 8487188Smcpowers 8497188Smcpowers } while (remainder > 0); 8507188Smcpowers 8517188Smcpowers return (CRYPTO_SUCCESS); 8527188Smcpowers } 8537188Smcpowers 8547188Smcpowers int 8557188Smcpowers ccm_init_ctx(ccm_ctx_t *ccm_ctx, char *param, int kmflag, 8567188Smcpowers boolean_t is_encrypt_init, size_t block_size, 8577188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 8587188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 8597188Smcpowers { 8607188Smcpowers int rv; 8617188Smcpowers CK_AES_CCM_PARAMS *ccm_param; 8627188Smcpowers 8637188Smcpowers if (param != NULL) { 864*11413Sopensolaris@drydog.com ccm_param = (CK_AES_CCM_PARAMS *)(void *)param; 8657188Smcpowers 8667188Smcpowers if ((rv = ccm_validate_args(ccm_param, 8677188Smcpowers is_encrypt_init)) != 0) { 8687188Smcpowers return (rv); 8697188Smcpowers } 8707188Smcpowers 8717188Smcpowers ccm_ctx->ccm_mac_len = ccm_param->ulMACSize; 8727188Smcpowers if (is_encrypt_init) { 8737188Smcpowers ccm_ctx->ccm_data_len = ccm_param->ulDataSize; 8747188Smcpowers } else { 8757188Smcpowers ccm_ctx->ccm_data_len = 8767188Smcpowers ccm_param->ulDataSize - ccm_ctx->ccm_mac_len; 8777188Smcpowers ccm_ctx->ccm_processed_mac_len = 0; 8787188Smcpowers } 8797188Smcpowers ccm_ctx->ccm_processed_data_len = 0; 8807188Smcpowers 8817188Smcpowers ccm_ctx->ccm_flags |= CCM_MODE; 8827188Smcpowers } else { 8837188Smcpowers rv = CRYPTO_MECHANISM_PARAM_INVALID; 8847188Smcpowers goto out; 8857188Smcpowers } 8867188Smcpowers 8877188Smcpowers if (ccm_init(ccm_ctx, ccm_param->nonce, ccm_param->ulNonceSize, 8887188Smcpowers ccm_param->authData, ccm_param->ulAuthDataSize, block_size, 8897188Smcpowers encrypt_block, xor_block) != 0) { 8907188Smcpowers rv = CRYPTO_MECHANISM_PARAM_INVALID; 8917188Smcpowers goto out; 8927188Smcpowers } 8937188Smcpowers if (!is_encrypt_init) { 8947188Smcpowers /* allocate buffer for storing decrypted plaintext */ 8957188Smcpowers #ifdef _KERNEL 8967188Smcpowers ccm_ctx->ccm_pt_buf = kmem_alloc(ccm_ctx->ccm_data_len, 8977188Smcpowers kmflag); 8987188Smcpowers #else 8997188Smcpowers ccm_ctx->ccm_pt_buf = malloc(ccm_ctx->ccm_data_len); 9007188Smcpowers #endif 9017188Smcpowers if (ccm_ctx->ccm_pt_buf == NULL) { 9027188Smcpowers rv = CRYPTO_HOST_MEMORY; 9037188Smcpowers } 9047188Smcpowers } 9057188Smcpowers out: 9067188Smcpowers return (rv); 9077188Smcpowers } 9087188Smcpowers 9097188Smcpowers void * 9107188Smcpowers ccm_alloc_ctx(int kmflag) 9117188Smcpowers { 9127188Smcpowers ccm_ctx_t *ccm_ctx; 9137188Smcpowers 9147188Smcpowers #ifdef _KERNEL 9157188Smcpowers if ((ccm_ctx = kmem_zalloc(sizeof (ccm_ctx_t), kmflag)) == NULL) 9167188Smcpowers #else 9177188Smcpowers if ((ccm_ctx = calloc(1, sizeof (ccm_ctx_t))) == NULL) 9187188Smcpowers #endif 9197188Smcpowers return (NULL); 9207188Smcpowers 9217188Smcpowers ccm_ctx->ccm_flags = CCM_MODE; 9227188Smcpowers return (ccm_ctx); 9237188Smcpowers } 924