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