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 /* 227188Smcpowers * Copyright 2008 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> 387188Smcpowers 397421SDaniel.Anderson@Sun.COM #if defined(__i386) || defined(__amd64) 407421SDaniel.Anderson@Sun.COM #include <sys/byteorder.h> 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 #ifdef _LITTLE_ENDIAN 1207421SDaniel.Anderson@Sun.COM counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask); 1217421SDaniel.Anderson@Sun.COM counter = htonll(counter + 1); 1227421SDaniel.Anderson@Sun.COM #else 1237188Smcpowers counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask; 1247188Smcpowers counter++; 1257421SDaniel.Anderson@Sun.COM #endif /* _LITTLE_ENDIAN */ 1267188Smcpowers counter &= ctx->ccm_counter_mask; 1277188Smcpowers ctx->ccm_cb[1] = 1287188Smcpowers (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 1297188Smcpowers 1307188Smcpowers /* 1317329SMark.Powers@Sun.COM * XOR encrypted counter block with the current clear block. 1327188Smcpowers */ 1337329SMark.Powers@Sun.COM xor_block(blockp, lastp); 1347188Smcpowers 1357188Smcpowers ctx->ccm_processed_data_len += block_size; 1367188Smcpowers 1377188Smcpowers if (out == NULL) { 1387188Smcpowers if (ctx->ccm_remainder_len > 0) { 1397188Smcpowers bcopy(blockp, ctx->ccm_copy_to, 1407188Smcpowers ctx->ccm_remainder_len); 1417188Smcpowers bcopy(blockp + ctx->ccm_remainder_len, datap, 1427188Smcpowers need); 1437188Smcpowers } 1447188Smcpowers } else { 1457188Smcpowers crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 1467188Smcpowers &out_data_1_len, &out_data_2, block_size); 1477188Smcpowers 1487188Smcpowers /* copy block to where it belongs */ 1497188Smcpowers if (out_data_1_len == block_size) { 1507188Smcpowers copy_block(lastp, out_data_1); 1517188Smcpowers } else { 1527188Smcpowers bcopy(lastp, out_data_1, out_data_1_len); 1537188Smcpowers if (out_data_2 != NULL) { 1547188Smcpowers bcopy(lastp + out_data_1_len, 1557188Smcpowers out_data_2, 1567188Smcpowers block_size - out_data_1_len); 1577188Smcpowers } 1587188Smcpowers } 1597188Smcpowers /* update offset */ 1607188Smcpowers out->cd_offset += block_size; 1617188Smcpowers } 1627188Smcpowers 1637188Smcpowers /* Update pointer to next block of data to be processed. */ 1647188Smcpowers if (ctx->ccm_remainder_len != 0) { 1657188Smcpowers datap += need; 1667188Smcpowers ctx->ccm_remainder_len = 0; 1677188Smcpowers } else { 1687188Smcpowers datap += block_size; 1697188Smcpowers } 1707188Smcpowers 1717188Smcpowers remainder = (size_t)&data[length] - (size_t)datap; 1727188Smcpowers 1737188Smcpowers /* Incomplete last block. */ 1747188Smcpowers if (remainder > 0 && remainder < block_size) { 1757188Smcpowers bcopy(datap, ctx->ccm_remainder, remainder); 1767188Smcpowers ctx->ccm_remainder_len = remainder; 1777188Smcpowers ctx->ccm_copy_to = datap; 1787188Smcpowers goto out; 1797188Smcpowers } 1807188Smcpowers ctx->ccm_copy_to = NULL; 1817188Smcpowers 1827188Smcpowers } while (remainder > 0); 1837188Smcpowers 1847188Smcpowers out: 1857188Smcpowers return (CRYPTO_SUCCESS); 1867188Smcpowers } 1877188Smcpowers 1887188Smcpowers void 1897188Smcpowers calculate_ccm_mac(ccm_ctx_t *ctx, uint8_t *ccm_mac, 1907188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)) 1917188Smcpowers { 1927188Smcpowers uint64_t counter; 1937188Smcpowers uint8_t *counterp, *mac_buf; 1947188Smcpowers int i; 1957188Smcpowers 1967188Smcpowers mac_buf = (uint8_t *)ctx->ccm_mac_buf; 1977188Smcpowers 1987188Smcpowers /* first counter block start with index 0 */ 1997188Smcpowers counter = 0; 2007188Smcpowers ctx->ccm_cb[1] = (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 2017188Smcpowers 2027188Smcpowers counterp = (uint8_t *)ctx->ccm_tmp; 2037188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp); 2047188Smcpowers 2057188Smcpowers /* calculate XOR of MAC with first counter block */ 2067188Smcpowers for (i = 0; i < ctx->ccm_mac_len; i++) { 2077188Smcpowers ccm_mac[i] = mac_buf[i] ^ counterp[i]; 2087188Smcpowers } 2097188Smcpowers } 2107188Smcpowers 2117188Smcpowers /* ARGSUSED */ 2127188Smcpowers int 2137188Smcpowers ccm_encrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size, 2147188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 2157188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 2167188Smcpowers { 2177188Smcpowers uint8_t *lastp, *mac_buf, *ccm_mac_p, *macp; 2187188Smcpowers void *iov_or_mp; 2197188Smcpowers offset_t offset; 2207188Smcpowers uint8_t *out_data_1; 2217188Smcpowers uint8_t *out_data_2; 2227188Smcpowers size_t out_data_1_len; 2237188Smcpowers int i; 2247188Smcpowers 2257188Smcpowers if (out->cd_length < (ctx->ccm_remainder_len + ctx->ccm_mac_len)) { 2267188Smcpowers return (CRYPTO_DATA_LEN_RANGE); 2277188Smcpowers } 2287188Smcpowers 2297188Smcpowers /* 2307188Smcpowers * When we get here, the number of bytes of payload processed 2317188Smcpowers * plus whatever data remains, if any, 2327188Smcpowers * should be the same as the number of bytes that's being 2337188Smcpowers * passed in the argument during init time. 2347188Smcpowers */ 2357188Smcpowers if ((ctx->ccm_processed_data_len + ctx->ccm_remainder_len) 2367188Smcpowers != (ctx->ccm_data_len)) { 2377188Smcpowers return (CRYPTO_DATA_LEN_RANGE); 2387188Smcpowers } 2397188Smcpowers 2407188Smcpowers mac_buf = (uint8_t *)ctx->ccm_mac_buf; 2417188Smcpowers 2427188Smcpowers if (ctx->ccm_remainder_len > 0) { 2437188Smcpowers 2447188Smcpowers /* ccm_mac_input_buf is not used for encryption */ 2457188Smcpowers macp = (uint8_t *)ctx->ccm_mac_input_buf; 2467188Smcpowers bzero(macp, block_size); 2477188Smcpowers 2487188Smcpowers /* copy remainder to temporary buffer */ 2497188Smcpowers bcopy(ctx->ccm_remainder, macp, ctx->ccm_remainder_len); 2507188Smcpowers 2517188Smcpowers /* calculate the CBC MAC */ 2527188Smcpowers xor_block(macp, mac_buf); 2537188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 2547188Smcpowers 2557188Smcpowers /* calculate the counter mode */ 2567188Smcpowers lastp = (uint8_t *)ctx->ccm_tmp; 2577188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, lastp); 2587188Smcpowers 2597188Smcpowers /* XOR with counter block */ 2607188Smcpowers for (i = 0; i < ctx->ccm_remainder_len; i++) { 2617188Smcpowers macp[i] ^= lastp[i]; 2627188Smcpowers } 2637188Smcpowers ctx->ccm_processed_data_len += ctx->ccm_remainder_len; 2647188Smcpowers } 2657188Smcpowers 2667188Smcpowers /* Calculate the CCM MAC */ 2677188Smcpowers ccm_mac_p = (uint8_t *)ctx->ccm_tmp; 2687188Smcpowers calculate_ccm_mac(ctx, ccm_mac_p, encrypt_block); 2697188Smcpowers 2707188Smcpowers crypto_init_ptrs(out, &iov_or_mp, &offset); 2717188Smcpowers crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 2727188Smcpowers &out_data_1_len, &out_data_2, 2737188Smcpowers ctx->ccm_remainder_len + ctx->ccm_mac_len); 2747188Smcpowers 2757188Smcpowers if (ctx->ccm_remainder_len > 0) { 2767188Smcpowers 2777188Smcpowers /* copy temporary block to where it belongs */ 2787188Smcpowers if (out_data_2 == NULL) { 2797188Smcpowers /* everything will fit in out_data_1 */ 2807188Smcpowers bcopy(macp, out_data_1, ctx->ccm_remainder_len); 2817188Smcpowers bcopy(ccm_mac_p, out_data_1 + ctx->ccm_remainder_len, 2827188Smcpowers ctx->ccm_mac_len); 2837188Smcpowers } else { 2847188Smcpowers 2857188Smcpowers if (out_data_1_len < ctx->ccm_remainder_len) { 2867188Smcpowers 2877188Smcpowers size_t data_2_len_used; 2887188Smcpowers 2897188Smcpowers bcopy(macp, out_data_1, out_data_1_len); 2907188Smcpowers 2917188Smcpowers data_2_len_used = ctx->ccm_remainder_len 2927188Smcpowers - out_data_1_len; 2937188Smcpowers 2947188Smcpowers bcopy((uint8_t *)macp + out_data_1_len, 2957188Smcpowers out_data_2, data_2_len_used); 2967188Smcpowers bcopy(ccm_mac_p, out_data_2 + data_2_len_used, 2977188Smcpowers ctx->ccm_mac_len); 2987188Smcpowers } else { 2997188Smcpowers bcopy(macp, out_data_1, out_data_1_len); 3007188Smcpowers if (out_data_1_len == ctx->ccm_remainder_len) { 3017188Smcpowers /* mac will be in out_data_2 */ 3027188Smcpowers bcopy(ccm_mac_p, out_data_2, 3037188Smcpowers ctx->ccm_mac_len); 3047188Smcpowers } else { 3057421SDaniel.Anderson@Sun.COM size_t len_not_used = out_data_1_len - 3067188Smcpowers ctx->ccm_remainder_len; 3077188Smcpowers /* 3087188Smcpowers * part of mac in will be in 3097188Smcpowers * out_data_1, part of the mac will be 3107188Smcpowers * in out_data_2 3117188Smcpowers */ 3127188Smcpowers bcopy(ccm_mac_p, 3137188Smcpowers out_data_1 + ctx->ccm_remainder_len, 3147188Smcpowers len_not_used); 3157188Smcpowers bcopy(ccm_mac_p + len_not_used, 3167188Smcpowers out_data_2, 3177188Smcpowers ctx->ccm_mac_len - len_not_used); 3187188Smcpowers 3197188Smcpowers } 3207188Smcpowers } 3217188Smcpowers } 3227188Smcpowers } else { 3237188Smcpowers /* copy block to where it belongs */ 3247188Smcpowers bcopy(ccm_mac_p, out_data_1, out_data_1_len); 3257188Smcpowers if (out_data_2 != NULL) { 3267188Smcpowers bcopy(ccm_mac_p + out_data_1_len, out_data_2, 3277188Smcpowers block_size - out_data_1_len); 3287188Smcpowers } 3297188Smcpowers } 3307188Smcpowers out->cd_offset += ctx->ccm_remainder_len + ctx->ccm_mac_len; 3317188Smcpowers ctx->ccm_remainder_len = 0; 3327188Smcpowers return (CRYPTO_SUCCESS); 3337188Smcpowers } 3347188Smcpowers 3357188Smcpowers /* 3367188Smcpowers * This will only deal with decrypting the last block of the input that 3377188Smcpowers * might not be a multiple of block length. 3387188Smcpowers */ 3397188Smcpowers void 3407188Smcpowers ccm_decrypt_incomplete_block(ccm_ctx_t *ctx, 3417188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)) 3427188Smcpowers { 3437188Smcpowers uint8_t *datap, *outp, *counterp; 3447188Smcpowers int i; 3457188Smcpowers 3467188Smcpowers datap = (uint8_t *)ctx->ccm_remainder; 3477188Smcpowers outp = &((ctx->ccm_pt_buf)[ctx->ccm_processed_data_len]); 3487188Smcpowers 3497188Smcpowers counterp = (uint8_t *)ctx->ccm_tmp; 3507188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp); 3517188Smcpowers 3527188Smcpowers /* XOR with counter block */ 3537188Smcpowers for (i = 0; i < ctx->ccm_remainder_len; i++) { 3547188Smcpowers outp[i] = datap[i] ^ counterp[i]; 3557188Smcpowers } 3567188Smcpowers } 3577188Smcpowers 3587188Smcpowers /* 3597188Smcpowers * This will decrypt the cipher text. However, the plaintext won't be 3607188Smcpowers * returned to the caller. It will be returned when decrypt_final() is 3617188Smcpowers * called if the MAC matches 3627188Smcpowers */ 3637188Smcpowers /* ARGSUSED */ 3647188Smcpowers int 3657188Smcpowers ccm_mode_decrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length, 3667188Smcpowers crypto_data_t *out, size_t block_size, 3677188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 3687188Smcpowers void (*copy_block)(uint8_t *, uint8_t *), 3697188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 3707188Smcpowers { 3717188Smcpowers size_t remainder = length; 3727188Smcpowers size_t need; 3737188Smcpowers uint8_t *datap = (uint8_t *)data; 3747188Smcpowers uint8_t *blockp; 3757188Smcpowers uint8_t *cbp; 3767188Smcpowers uint64_t counter; 3777188Smcpowers size_t pt_len, total_decrypted_len, mac_len, pm_len, pd_len; 3787188Smcpowers uint8_t *resultp; 3797188Smcpowers 3807188Smcpowers 3817188Smcpowers pm_len = ctx->ccm_processed_mac_len; 3827188Smcpowers 3837188Smcpowers if (pm_len > 0) { 3847188Smcpowers uint8_t *tmp; 3857188Smcpowers /* 3867188Smcpowers * all ciphertext has been processed, just waiting for 3877188Smcpowers * part of the value of the mac 3887188Smcpowers */ 3897188Smcpowers if ((pm_len + length) > ctx->ccm_mac_len) { 3907188Smcpowers return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 3917188Smcpowers } 3927188Smcpowers tmp = (uint8_t *)ctx->ccm_mac_input_buf; 3937188Smcpowers 3947188Smcpowers bcopy(datap, tmp + pm_len, length); 3957188Smcpowers 3967188Smcpowers ctx->ccm_processed_mac_len += length; 3977188Smcpowers return (CRYPTO_SUCCESS); 3987188Smcpowers } 3997188Smcpowers 4007188Smcpowers /* 4017188Smcpowers * If we decrypt the given data, what total amount of data would 4027188Smcpowers * have been decrypted? 4037188Smcpowers */ 4047188Smcpowers pd_len = ctx->ccm_processed_data_len; 4057188Smcpowers total_decrypted_len = pd_len + length + ctx->ccm_remainder_len; 4067188Smcpowers 4077188Smcpowers if (total_decrypted_len > 4087188Smcpowers (ctx->ccm_data_len + ctx->ccm_mac_len)) { 4097188Smcpowers return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 4107188Smcpowers } 4117188Smcpowers 4127188Smcpowers pt_len = ctx->ccm_data_len; 4137188Smcpowers 4147188Smcpowers if (total_decrypted_len > pt_len) { 4157188Smcpowers /* 4167188Smcpowers * part of the input will be the MAC, need to isolate that 4177188Smcpowers * to be dealt with later. The left-over data in 4187188Smcpowers * ccm_remainder_len from last time will not be part of the 4197188Smcpowers * MAC. Otherwise, it would have already been taken out 4207188Smcpowers * when this call is made last time. 4217188Smcpowers */ 4227188Smcpowers size_t pt_part = pt_len - pd_len - ctx->ccm_remainder_len; 4237188Smcpowers 4247188Smcpowers mac_len = length - pt_part; 4257188Smcpowers 4267188Smcpowers ctx->ccm_processed_mac_len = mac_len; 4277188Smcpowers bcopy(data + pt_part, ctx->ccm_mac_input_buf, mac_len); 4287188Smcpowers 4297188Smcpowers if (pt_part + ctx->ccm_remainder_len < block_size) { 4307188Smcpowers /* 4317188Smcpowers * since this is last of the ciphertext, will 4327188Smcpowers * just decrypt with it here 4337188Smcpowers */ 4347188Smcpowers bcopy(datap, &((uint8_t *)ctx->ccm_remainder) 4357188Smcpowers [ctx->ccm_remainder_len], pt_part); 4367188Smcpowers ctx->ccm_remainder_len += pt_part; 4377188Smcpowers ccm_decrypt_incomplete_block(ctx, encrypt_block); 4387188Smcpowers ctx->ccm_remainder_len = 0; 4397188Smcpowers ctx->ccm_processed_data_len += pt_part; 4407188Smcpowers return (CRYPTO_SUCCESS); 4417188Smcpowers } else { 4427188Smcpowers /* let rest of the code handle this */ 4437188Smcpowers length = pt_part; 4447188Smcpowers } 4457188Smcpowers } else if (length + ctx->ccm_remainder_len < block_size) { 4467188Smcpowers /* accumulate bytes here and return */ 4477188Smcpowers bcopy(datap, 4487188Smcpowers (uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len, 4497188Smcpowers length); 4507188Smcpowers ctx->ccm_remainder_len += length; 4517188Smcpowers ctx->ccm_copy_to = datap; 4527188Smcpowers return (CRYPTO_SUCCESS); 4537188Smcpowers } 4547188Smcpowers 4557188Smcpowers do { 4567188Smcpowers /* Unprocessed data from last call. */ 4577188Smcpowers if (ctx->ccm_remainder_len > 0) { 4587188Smcpowers need = block_size - ctx->ccm_remainder_len; 4597188Smcpowers 4607188Smcpowers if (need > remainder) 4617188Smcpowers return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 4627188Smcpowers 4637188Smcpowers bcopy(datap, &((uint8_t *)ctx->ccm_remainder) 4647188Smcpowers [ctx->ccm_remainder_len], need); 4657188Smcpowers 4667188Smcpowers blockp = (uint8_t *)ctx->ccm_remainder; 4677188Smcpowers } else { 4687188Smcpowers blockp = datap; 4697188Smcpowers } 4707188Smcpowers 4717188Smcpowers /* Calculate the counter mode, ccm_cb is the counter block */ 4727188Smcpowers cbp = (uint8_t *)ctx->ccm_tmp; 4737188Smcpowers encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, cbp); 4747188Smcpowers 4757188Smcpowers /* 4767188Smcpowers * Increment counter. 4777188Smcpowers * Counter bits are confined to the bottom 64 bits 4787188Smcpowers */ 4797421SDaniel.Anderson@Sun.COM #ifdef _LITTLE_ENDIAN 4807421SDaniel.Anderson@Sun.COM counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask); 4817421SDaniel.Anderson@Sun.COM counter = htonll(counter + 1); 4827421SDaniel.Anderson@Sun.COM #else 4837188Smcpowers counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask; 4847188Smcpowers counter++; 4857421SDaniel.Anderson@Sun.COM #endif /* _LITTLE_ENDIAN */ 4867188Smcpowers counter &= ctx->ccm_counter_mask; 4877188Smcpowers ctx->ccm_cb[1] = 4887188Smcpowers (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 4897188Smcpowers 4907188Smcpowers /* XOR with the ciphertext */ 4917188Smcpowers xor_block(blockp, cbp); 4927188Smcpowers 4937188Smcpowers /* Copy the plaintext to the "holding buffer" */ 4947188Smcpowers resultp = (uint8_t *)ctx->ccm_pt_buf + 4957188Smcpowers ctx->ccm_processed_data_len; 4967188Smcpowers copy_block(cbp, resultp); 4977188Smcpowers 4987188Smcpowers ctx->ccm_processed_data_len += block_size; 4997188Smcpowers 5007188Smcpowers ctx->ccm_lastp = blockp; 5017188Smcpowers 5027188Smcpowers /* Update pointer to next block of data to be processed. */ 5037188Smcpowers if (ctx->ccm_remainder_len != 0) { 5047188Smcpowers datap += need; 5057188Smcpowers ctx->ccm_remainder_len = 0; 5067188Smcpowers } else { 5077188Smcpowers datap += block_size; 5087188Smcpowers } 5097188Smcpowers 5107188Smcpowers remainder = (size_t)&data[length] - (size_t)datap; 5117188Smcpowers 5127188Smcpowers /* Incomplete last block */ 5137188Smcpowers if (remainder > 0 && remainder < block_size) { 5147188Smcpowers bcopy(datap, ctx->ccm_remainder, remainder); 5157188Smcpowers ctx->ccm_remainder_len = remainder; 5167188Smcpowers ctx->ccm_copy_to = datap; 5177188Smcpowers if (ctx->ccm_processed_mac_len > 0) { 5187188Smcpowers /* 5197188Smcpowers * not expecting anymore ciphertext, just 5207188Smcpowers * compute plaintext for the remaining input 5217188Smcpowers */ 5227188Smcpowers ccm_decrypt_incomplete_block(ctx, 5237188Smcpowers encrypt_block); 5247188Smcpowers ctx->ccm_processed_data_len += remainder; 5257188Smcpowers ctx->ccm_remainder_len = 0; 5267188Smcpowers } 5277188Smcpowers goto out; 5287188Smcpowers } 5297188Smcpowers ctx->ccm_copy_to = NULL; 5307188Smcpowers 5317188Smcpowers } while (remainder > 0); 5327188Smcpowers 5337188Smcpowers out: 5347188Smcpowers return (CRYPTO_SUCCESS); 5357188Smcpowers } 5367188Smcpowers 5377188Smcpowers int 5387188Smcpowers ccm_decrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size, 5397188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 5407188Smcpowers void (*copy_block)(uint8_t *, uint8_t *), 5417188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 5427188Smcpowers { 5437188Smcpowers size_t mac_remain, pt_len; 5447188Smcpowers uint8_t *pt, *mac_buf, *macp, *ccm_mac_p; 545*7537SMark.Powers@Sun.COM int rv; 5467188Smcpowers 5477188Smcpowers pt_len = ctx->ccm_data_len; 5487188Smcpowers 5497188Smcpowers /* Make sure output buffer can fit all of the plaintext */ 5507188Smcpowers if (out->cd_length < pt_len) { 5517188Smcpowers return (CRYPTO_DATA_LEN_RANGE); 5527188Smcpowers } 5537188Smcpowers 5547188Smcpowers pt = ctx->ccm_pt_buf; 5557188Smcpowers mac_remain = ctx->ccm_processed_data_len; 5567188Smcpowers mac_buf = (uint8_t *)ctx->ccm_mac_buf; 5577188Smcpowers 5587188Smcpowers macp = (uint8_t *)ctx->ccm_tmp; 5597188Smcpowers 5607188Smcpowers while (mac_remain > 0) { 5617188Smcpowers 5627188Smcpowers if (mac_remain < block_size) { 5637188Smcpowers bzero(macp, block_size); 5647188Smcpowers bcopy(pt, macp, mac_remain); 5657188Smcpowers mac_remain = 0; 5667188Smcpowers } else { 5677188Smcpowers copy_block(pt, macp); 5687188Smcpowers mac_remain -= block_size; 5697188Smcpowers pt += block_size; 5707188Smcpowers } 5717188Smcpowers 5727188Smcpowers /* calculate the CBC MAC */ 5737188Smcpowers xor_block(macp, mac_buf); 5747188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 5757188Smcpowers } 5767188Smcpowers 5777188Smcpowers /* Calculate the CCM MAC */ 5787188Smcpowers ccm_mac_p = (uint8_t *)ctx->ccm_tmp; 5797188Smcpowers calculate_ccm_mac((ccm_ctx_t *)ctx, ccm_mac_p, encrypt_block); 5807188Smcpowers 5817188Smcpowers /* compare the input CCM MAC value with what we calculated */ 5827188Smcpowers if (bcmp(ctx->ccm_mac_input_buf, ccm_mac_p, ctx->ccm_mac_len)) { 5837188Smcpowers /* They don't match */ 5847188Smcpowers return (CRYPTO_INVALID_MAC); 5857188Smcpowers } else { 586*7537SMark.Powers@Sun.COM rv = crypto_put_output_data(ctx->ccm_pt_buf, out, pt_len); 587*7537SMark.Powers@Sun.COM if (rv != CRYPTO_SUCCESS) 588*7537SMark.Powers@Sun.COM return (rv); 5897188Smcpowers out->cd_offset += pt_len; 5907188Smcpowers } 5917188Smcpowers return (CRYPTO_SUCCESS); 5927188Smcpowers } 5937188Smcpowers 5947188Smcpowers int 5957188Smcpowers ccm_validate_args(CK_AES_CCM_PARAMS *ccm_param, boolean_t is_encrypt_init) 5967188Smcpowers { 5977188Smcpowers size_t macSize, nonceSize; 5987188Smcpowers uint8_t q; 5997188Smcpowers uint64_t maxValue; 6007188Smcpowers 6017188Smcpowers /* 6027188Smcpowers * Check the length of the MAC. The only valid 6037188Smcpowers * lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16 6047188Smcpowers */ 6057188Smcpowers macSize = ccm_param->ulMACSize; 6067188Smcpowers if ((macSize < 4) || (macSize > 16) || ((macSize % 2) != 0)) { 6077188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 6087188Smcpowers } 6097188Smcpowers 6107188Smcpowers /* Check the nonce length. Valid values are 7, 8, 9, 10, 11, 12, 13 */ 6117188Smcpowers nonceSize = ccm_param->ulNonceSize; 6127188Smcpowers if ((nonceSize < 7) || (nonceSize > 13)) { 6137188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 6147188Smcpowers } 6157188Smcpowers 6167188Smcpowers /* q is the length of the field storing the length, in bytes */ 6177188Smcpowers q = (uint8_t)((15 - nonceSize) & 0xFF); 6187188Smcpowers 6197188Smcpowers 6207188Smcpowers /* 6217188Smcpowers * If it is decrypt, need to make sure size of ciphertext is at least 6227188Smcpowers * bigger than MAC len 6237188Smcpowers */ 6247188Smcpowers if ((!is_encrypt_init) && (ccm_param->ulDataSize < macSize)) { 6257188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 6267188Smcpowers } 6277188Smcpowers 6287188Smcpowers /* 6297188Smcpowers * Check to make sure the length of the payload is within the 6307188Smcpowers * range of values allowed by q 6317188Smcpowers */ 6327188Smcpowers if (q < 8) { 6337188Smcpowers maxValue = (1ULL << (q * 8)) - 1; 6347188Smcpowers } else { 6357188Smcpowers maxValue = ULONG_MAX; 6367188Smcpowers } 6377188Smcpowers 6387188Smcpowers if (ccm_param->ulDataSize > maxValue) { 6397188Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 6407188Smcpowers } 6417188Smcpowers return (CRYPTO_SUCCESS); 6427188Smcpowers } 6437188Smcpowers 6447188Smcpowers /* 6457188Smcpowers * Format the first block used in CBC-MAC (B0) and the initial counter 6467188Smcpowers * block based on formatting functions and counter generation functions 6477188Smcpowers * specified in RFC 3610 and NIST publication 800-38C, appendix A 6487188Smcpowers * 6497188Smcpowers * b0 is the first block used in CBC-MAC 6507188Smcpowers * cb0 is the first counter block 6517188Smcpowers * 6527188Smcpowers * It's assumed that the arguments b0 and cb0 are preallocated AES blocks 6537188Smcpowers * 6547188Smcpowers */ 6557188Smcpowers static void 6567188Smcpowers ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize, 6577188Smcpowers ulong_t authDataSize, uint8_t *b0, ccm_ctx_t *aes_ctx) 6587188Smcpowers { 6597188Smcpowers uint64_t payloadSize; 6607188Smcpowers uint8_t t, q, have_adata = 0; 6617188Smcpowers size_t limit; 6627188Smcpowers int i, j, k; 6637188Smcpowers uint64_t mask = 0; 6647188Smcpowers uint8_t *cb; 6657188Smcpowers 6667188Smcpowers q = (uint8_t)((15 - nonceSize) & 0xFF); 6677188Smcpowers t = (uint8_t)((aes_ctx->ccm_mac_len) & 0xFF); 6687188Smcpowers 6697188Smcpowers /* Construct the first octet of b0 */ 6707188Smcpowers if (authDataSize > 0) { 6717188Smcpowers have_adata = 1; 6727188Smcpowers } 6737188Smcpowers b0[0] = (have_adata << 6) | (((t - 2) / 2) << 3) | (q - 1); 6747188Smcpowers 6757188Smcpowers /* copy the nonce value into b0 */ 6767188Smcpowers bcopy(nonce, &(b0[1]), nonceSize); 6777188Smcpowers 6787188Smcpowers /* store the length of the payload into b0 */ 6797188Smcpowers bzero(&(b0[1+nonceSize]), q); 6807188Smcpowers 6817188Smcpowers payloadSize = aes_ctx->ccm_data_len; 6827188Smcpowers limit = 8 < q ? 8 : q; 6837188Smcpowers 6847188Smcpowers for (i = 0, j = 0, k = 15; i < limit; i++, j += 8, k--) { 6857188Smcpowers b0[k] = (uint8_t)((payloadSize >> j) & 0xFF); 6867188Smcpowers } 6877188Smcpowers 6887188Smcpowers /* format the counter block */ 6897188Smcpowers 6907188Smcpowers cb = (uint8_t *)aes_ctx->ccm_cb; 6917188Smcpowers 6927188Smcpowers cb[0] = 0x07 & (q-1); /* first byte */ 6937188Smcpowers 6947188Smcpowers /* copy the nonce value into the counter block */ 6957188Smcpowers bcopy(nonce, &(cb[1]), nonceSize); 6967188Smcpowers 6977188Smcpowers bzero(&(cb[1+nonceSize]), q); 6987188Smcpowers 6997188Smcpowers /* Create the mask for the counter field based on the size of nonce */ 7007188Smcpowers q <<= 3; 7017188Smcpowers while (q-- > 0) { 7027188Smcpowers mask |= (1ULL << q); 7037188Smcpowers } 7047188Smcpowers 7057188Smcpowers #ifdef _LITTLE_ENDIAN 7067421SDaniel.Anderson@Sun.COM mask = htonll(mask); 7077188Smcpowers #endif 7087188Smcpowers aes_ctx->ccm_counter_mask = mask; 7097188Smcpowers 7107188Smcpowers /* 7117188Smcpowers * During calculation, we start using counter block 1, we will 7127188Smcpowers * set it up right here. 7137188Smcpowers * We can just set the last byte to have the value 1, because 7147188Smcpowers * even with the biggest nonce of 13, the last byte of the 7157188Smcpowers * counter block will be used for the counter value. 7167188Smcpowers */ 7177188Smcpowers cb[15] = 0x01; 7187188Smcpowers } 7197188Smcpowers 7207188Smcpowers /* 7217188Smcpowers * Encode the length of the associated data as 7227188Smcpowers * specified in RFC 3610 and NIST publication 800-38C, appendix A 7237188Smcpowers */ 7247188Smcpowers static void 7257188Smcpowers encode_adata_len(ulong_t auth_data_len, uint8_t *encoded, size_t *encoded_len) 7267188Smcpowers { 7277421SDaniel.Anderson@Sun.COM #ifdef UNALIGNED_POINTERS_PERMITTED 7287421SDaniel.Anderson@Sun.COM uint32_t *lencoded_ptr; 7297421SDaniel.Anderson@Sun.COM #ifdef _LP64 7307421SDaniel.Anderson@Sun.COM uint64_t *llencoded_ptr; 7317421SDaniel.Anderson@Sun.COM #endif 7327421SDaniel.Anderson@Sun.COM #endif /* UNALIGNED_POINTERS_PERMITTED */ 7337421SDaniel.Anderson@Sun.COM 7347188Smcpowers if (auth_data_len < ((1ULL<<16) - (1ULL<<8))) { 7357188Smcpowers /* 0 < a < (2^16-2^8) */ 7367188Smcpowers *encoded_len = 2; 7377188Smcpowers encoded[0] = (auth_data_len & 0xff00) >> 8; 7387188Smcpowers encoded[1] = auth_data_len & 0xff; 7397188Smcpowers 7407188Smcpowers } else if ((auth_data_len >= ((1ULL<<16) - (1ULL<<8))) && 7417188Smcpowers (auth_data_len < (1ULL << 31))) { 7427188Smcpowers /* (2^16-2^8) <= a < 2^32 */ 7437188Smcpowers *encoded_len = 6; 7447188Smcpowers encoded[0] = 0xff; 7457188Smcpowers encoded[1] = 0xfe; 7467421SDaniel.Anderson@Sun.COM #ifdef UNALIGNED_POINTERS_PERMITTED 7477421SDaniel.Anderson@Sun.COM lencoded_ptr = (uint32_t *)&encoded[2]; 7487421SDaniel.Anderson@Sun.COM *lencoded_ptr = htonl(auth_data_len); 7497421SDaniel.Anderson@Sun.COM #else 7507188Smcpowers encoded[2] = (auth_data_len & 0xff000000) >> 24; 7517188Smcpowers encoded[3] = (auth_data_len & 0xff0000) >> 16; 7527188Smcpowers encoded[4] = (auth_data_len & 0xff00) >> 8; 7537188Smcpowers encoded[5] = auth_data_len & 0xff; 7547421SDaniel.Anderson@Sun.COM #endif /* UNALIGNED_POINTERS_PERMITTED */ 7557421SDaniel.Anderson@Sun.COM 7567188Smcpowers #ifdef _LP64 7577188Smcpowers } else { 7587188Smcpowers /* 2^32 <= a < 2^64 */ 7597188Smcpowers *encoded_len = 10; 7607188Smcpowers encoded[0] = 0xff; 7617188Smcpowers encoded[1] = 0xff; 7627421SDaniel.Anderson@Sun.COM #ifdef UNALIGNED_POINTERS_PERMITTED 7637421SDaniel.Anderson@Sun.COM llencoded_ptr = (uint64_t *)&encoded[2]; 7647421SDaniel.Anderson@Sun.COM *llencoded_ptr = htonl(auth_data_len); 7657421SDaniel.Anderson@Sun.COM #else 7667188Smcpowers encoded[2] = (auth_data_len & 0xff00000000000000) >> 56; 7677188Smcpowers encoded[3] = (auth_data_len & 0xff000000000000) >> 48; 7687188Smcpowers encoded[4] = (auth_data_len & 0xff0000000000) >> 40; 7697188Smcpowers encoded[5] = (auth_data_len & 0xff00000000) >> 32; 7707188Smcpowers encoded[6] = (auth_data_len & 0xff000000) >> 24; 7717188Smcpowers encoded[7] = (auth_data_len & 0xff0000) >> 16; 7727188Smcpowers encoded[8] = (auth_data_len & 0xff00) >> 8; 7737188Smcpowers encoded[9] = auth_data_len & 0xff; 7747421SDaniel.Anderson@Sun.COM #endif /* UNALIGNED_POINTERS_PERMITTED */ 7757188Smcpowers #endif /* _LP64 */ 7767188Smcpowers } 7777188Smcpowers } 7787188Smcpowers 7797188Smcpowers /* 7807188Smcpowers * The following function should be call at encrypt or decrypt init time 7817188Smcpowers * for AES CCM mode. 7827188Smcpowers */ 7837188Smcpowers int 7847188Smcpowers ccm_init(ccm_ctx_t *ctx, unsigned char *nonce, size_t nonce_len, 7857188Smcpowers unsigned char *auth_data, size_t auth_data_len, size_t block_size, 7867188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 7877188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 7887188Smcpowers { 7897188Smcpowers uint8_t *mac_buf, *datap, *ivp, *authp; 7907188Smcpowers size_t remainder, processed; 7917188Smcpowers uint8_t encoded_a[10]; /* max encoded auth data length is 10 octets */ 7927188Smcpowers size_t encoded_a_len = 0; 7937188Smcpowers 7947188Smcpowers mac_buf = (uint8_t *)&(ctx->ccm_mac_buf); 7957188Smcpowers 7967188Smcpowers /* 7977188Smcpowers * Format the 1st block for CBC-MAC and construct the 7987188Smcpowers * 1st counter block. 7997188Smcpowers * 8007188Smcpowers * aes_ctx->ccm_iv is used for storing the counter block 8017188Smcpowers * mac_buf will store b0 at this time. 8027188Smcpowers */ 8037188Smcpowers ccm_format_initial_blocks(nonce, nonce_len, 8047188Smcpowers auth_data_len, mac_buf, ctx); 8057188Smcpowers 8067188Smcpowers /* The IV for CBC MAC for AES CCM mode is always zero */ 8077188Smcpowers ivp = (uint8_t *)ctx->ccm_tmp; 8087188Smcpowers bzero(ivp, block_size); 8097188Smcpowers 8107188Smcpowers xor_block(ivp, mac_buf); 8117188Smcpowers 8127188Smcpowers /* encrypt the nonce */ 8137188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 8147188Smcpowers 8157188Smcpowers /* take care of the associated data, if any */ 8167188Smcpowers if (auth_data_len == 0) { 8177188Smcpowers return (CRYPTO_SUCCESS); 8187188Smcpowers } 8197188Smcpowers 8207188Smcpowers encode_adata_len(auth_data_len, encoded_a, &encoded_a_len); 8217188Smcpowers 8227188Smcpowers remainder = auth_data_len; 8237188Smcpowers 8247188Smcpowers /* 1st block: it contains encoded associated data, and some data */ 8257188Smcpowers authp = (uint8_t *)ctx->ccm_tmp; 8267188Smcpowers bzero(authp, block_size); 8277188Smcpowers bcopy(encoded_a, authp, encoded_a_len); 8287188Smcpowers processed = block_size - encoded_a_len; 8297188Smcpowers if (processed > auth_data_len) { 8307188Smcpowers /* in case auth_data is very small */ 8317188Smcpowers processed = auth_data_len; 8327188Smcpowers } 8337188Smcpowers bcopy(auth_data, authp+encoded_a_len, processed); 8347188Smcpowers /* xor with previous buffer */ 8357188Smcpowers xor_block(authp, mac_buf); 8367188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 8377188Smcpowers remainder -= processed; 8387188Smcpowers if (remainder == 0) { 8397188Smcpowers /* a small amount of associated data, it's all done now */ 8407188Smcpowers return (CRYPTO_SUCCESS); 8417188Smcpowers } 8427188Smcpowers 8437188Smcpowers do { 8447188Smcpowers if (remainder < block_size) { 8457188Smcpowers /* 8467188Smcpowers * There's not a block full of data, pad rest of 8477188Smcpowers * buffer with zero 8487188Smcpowers */ 8497188Smcpowers bzero(authp, block_size); 8507188Smcpowers bcopy(&(auth_data[processed]), authp, remainder); 8517188Smcpowers datap = (uint8_t *)authp; 8527188Smcpowers remainder = 0; 8537188Smcpowers } else { 8547188Smcpowers datap = (uint8_t *)(&(auth_data[processed])); 8557188Smcpowers processed += block_size; 8567188Smcpowers remainder -= block_size; 8577188Smcpowers } 8587188Smcpowers 8597188Smcpowers xor_block(datap, mac_buf); 8607188Smcpowers encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 8617188Smcpowers 8627188Smcpowers } while (remainder > 0); 8637188Smcpowers 8647188Smcpowers return (CRYPTO_SUCCESS); 8657188Smcpowers } 8667188Smcpowers 8677188Smcpowers int 8687188Smcpowers ccm_init_ctx(ccm_ctx_t *ccm_ctx, char *param, int kmflag, 8697188Smcpowers boolean_t is_encrypt_init, size_t block_size, 8707188Smcpowers int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 8717188Smcpowers void (*xor_block)(uint8_t *, uint8_t *)) 8727188Smcpowers { 8737188Smcpowers int rv; 8747188Smcpowers CK_AES_CCM_PARAMS *ccm_param; 8757188Smcpowers 8767188Smcpowers if (param != NULL) { 8777188Smcpowers ccm_param = (CK_AES_CCM_PARAMS *)param; 8787188Smcpowers 8797188Smcpowers if ((rv = ccm_validate_args(ccm_param, 8807188Smcpowers is_encrypt_init)) != 0) { 8817188Smcpowers return (rv); 8827188Smcpowers } 8837188Smcpowers 8847188Smcpowers ccm_ctx->ccm_mac_len = ccm_param->ulMACSize; 8857188Smcpowers if (is_encrypt_init) { 8867188Smcpowers ccm_ctx->ccm_data_len = ccm_param->ulDataSize; 8877188Smcpowers } else { 8887188Smcpowers ccm_ctx->ccm_data_len = 8897188Smcpowers ccm_param->ulDataSize - ccm_ctx->ccm_mac_len; 8907188Smcpowers ccm_ctx->ccm_processed_mac_len = 0; 8917188Smcpowers } 8927188Smcpowers ccm_ctx->ccm_processed_data_len = 0; 8937188Smcpowers 8947188Smcpowers ccm_ctx->ccm_flags |= CCM_MODE; 8957188Smcpowers } else { 8967188Smcpowers rv = CRYPTO_MECHANISM_PARAM_INVALID; 8977188Smcpowers goto out; 8987188Smcpowers } 8997188Smcpowers 9007188Smcpowers if (ccm_init(ccm_ctx, ccm_param->nonce, ccm_param->ulNonceSize, 9017188Smcpowers ccm_param->authData, ccm_param->ulAuthDataSize, block_size, 9027188Smcpowers encrypt_block, xor_block) != 0) { 9037188Smcpowers rv = CRYPTO_MECHANISM_PARAM_INVALID; 9047188Smcpowers goto out; 9057188Smcpowers } 9067188Smcpowers if (!is_encrypt_init) { 9077188Smcpowers /* allocate buffer for storing decrypted plaintext */ 9087188Smcpowers #ifdef _KERNEL 9097188Smcpowers ccm_ctx->ccm_pt_buf = kmem_alloc(ccm_ctx->ccm_data_len, 9107188Smcpowers kmflag); 9117188Smcpowers #else 9127188Smcpowers ccm_ctx->ccm_pt_buf = malloc(ccm_ctx->ccm_data_len); 9137188Smcpowers #endif 9147188Smcpowers if (ccm_ctx->ccm_pt_buf == NULL) { 9157188Smcpowers rv = CRYPTO_HOST_MEMORY; 9167188Smcpowers } 9177188Smcpowers } 9187188Smcpowers out: 9197188Smcpowers return (rv); 9207188Smcpowers } 9217188Smcpowers 9227188Smcpowers void * 9237188Smcpowers ccm_alloc_ctx(int kmflag) 9247188Smcpowers { 9257188Smcpowers ccm_ctx_t *ccm_ctx; 9267188Smcpowers 9277188Smcpowers #ifdef _KERNEL 9287188Smcpowers if ((ccm_ctx = kmem_zalloc(sizeof (ccm_ctx_t), kmflag)) == NULL) 9297188Smcpowers #else 9307188Smcpowers if ((ccm_ctx = calloc(1, sizeof (ccm_ctx_t))) == NULL) 9317188Smcpowers #endif 9327188Smcpowers return (NULL); 9337188Smcpowers 9347188Smcpowers ccm_ctx->ccm_flags = CCM_MODE; 9357188Smcpowers return (ccm_ctx); 9367188Smcpowers } 937