1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy /* 22eda14cbcSMatt Macy * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23eda14cbcSMatt Macy * Use is subject to license terms. 24eda14cbcSMatt Macy */ 25eda14cbcSMatt Macy 26eda14cbcSMatt Macy #include <sys/zfs_context.h> 27eda14cbcSMatt Macy #include <modes/modes.h> 28eda14cbcSMatt Macy #include <sys/crypto/common.h> 29eda14cbcSMatt Macy #include <sys/crypto/impl.h> 30eda14cbcSMatt Macy 31eda14cbcSMatt Macy #ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS 32eda14cbcSMatt Macy #include <sys/byteorder.h> 33eda14cbcSMatt Macy #define UNALIGNED_POINTERS_PERMITTED 34eda14cbcSMatt Macy #endif 35eda14cbcSMatt Macy 36eda14cbcSMatt Macy /* 37eda14cbcSMatt Macy * Encrypt multiple blocks of data in CCM mode. Decrypt for CCM mode 38eda14cbcSMatt Macy * is done in another function. 39eda14cbcSMatt Macy */ 40eda14cbcSMatt Macy int 41eda14cbcSMatt Macy ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length, 42eda14cbcSMatt Macy crypto_data_t *out, size_t block_size, 43eda14cbcSMatt Macy int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 44eda14cbcSMatt Macy void (*copy_block)(uint8_t *, uint8_t *), 45eda14cbcSMatt Macy void (*xor_block)(uint8_t *, uint8_t *)) 46eda14cbcSMatt Macy { 47eda14cbcSMatt Macy size_t remainder = length; 48eda14cbcSMatt Macy size_t need = 0; 49eda14cbcSMatt Macy uint8_t *datap = (uint8_t *)data; 50eda14cbcSMatt Macy uint8_t *blockp; 51eda14cbcSMatt Macy uint8_t *lastp; 52eda14cbcSMatt Macy void *iov_or_mp; 53eda14cbcSMatt Macy offset_t offset; 54eda14cbcSMatt Macy uint8_t *out_data_1; 55eda14cbcSMatt Macy uint8_t *out_data_2; 56eda14cbcSMatt Macy size_t out_data_1_len; 57eda14cbcSMatt Macy uint64_t counter; 58eda14cbcSMatt Macy uint8_t *mac_buf; 59eda14cbcSMatt Macy 60eda14cbcSMatt Macy if (length + ctx->ccm_remainder_len < block_size) { 61eda14cbcSMatt Macy /* accumulate bytes here and return */ 62da5137abSMartin Matuska memcpy((uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len, 63da5137abSMartin Matuska datap, 64eda14cbcSMatt Macy length); 65eda14cbcSMatt Macy ctx->ccm_remainder_len += length; 66eda14cbcSMatt Macy ctx->ccm_copy_to = datap; 67eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 68eda14cbcSMatt Macy } 69eda14cbcSMatt Macy 70eda14cbcSMatt Macy lastp = (uint8_t *)ctx->ccm_cb; 71eda14cbcSMatt Macy crypto_init_ptrs(out, &iov_or_mp, &offset); 72eda14cbcSMatt Macy 73eda14cbcSMatt Macy mac_buf = (uint8_t *)ctx->ccm_mac_buf; 74eda14cbcSMatt Macy 75eda14cbcSMatt Macy do { 76eda14cbcSMatt Macy /* Unprocessed data from last call. */ 77eda14cbcSMatt Macy if (ctx->ccm_remainder_len > 0) { 78eda14cbcSMatt Macy need = block_size - ctx->ccm_remainder_len; 79eda14cbcSMatt Macy 80eda14cbcSMatt Macy if (need > remainder) 81eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE); 82eda14cbcSMatt Macy 83da5137abSMartin Matuska memcpy(&((uint8_t *)ctx->ccm_remainder) 84da5137abSMartin Matuska [ctx->ccm_remainder_len], datap, need); 85eda14cbcSMatt Macy 86eda14cbcSMatt Macy blockp = (uint8_t *)ctx->ccm_remainder; 87eda14cbcSMatt Macy } else { 88eda14cbcSMatt Macy blockp = datap; 89eda14cbcSMatt Macy } 90eda14cbcSMatt Macy 91eda14cbcSMatt Macy /* 92eda14cbcSMatt Macy * do CBC MAC 93eda14cbcSMatt Macy * 94eda14cbcSMatt Macy * XOR the previous cipher block current clear block. 95eda14cbcSMatt Macy * mac_buf always contain previous cipher block. 96eda14cbcSMatt Macy */ 97eda14cbcSMatt Macy xor_block(blockp, mac_buf); 98eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 99eda14cbcSMatt Macy 100eda14cbcSMatt Macy /* ccm_cb is the counter block */ 101eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, 102eda14cbcSMatt Macy (uint8_t *)ctx->ccm_tmp); 103eda14cbcSMatt Macy 104eda14cbcSMatt Macy lastp = (uint8_t *)ctx->ccm_tmp; 105eda14cbcSMatt Macy 106eda14cbcSMatt Macy /* 107eda14cbcSMatt Macy * Increment counter. Counter bits are confined 108eda14cbcSMatt Macy * to the bottom 64 bits of the counter block. 109eda14cbcSMatt Macy */ 110eda14cbcSMatt Macy #ifdef _ZFS_LITTLE_ENDIAN 111eda14cbcSMatt Macy counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask); 112eda14cbcSMatt Macy counter = htonll(counter + 1); 113eda14cbcSMatt Macy #else 114eda14cbcSMatt Macy counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask; 115eda14cbcSMatt Macy counter++; 116eda14cbcSMatt Macy #endif /* _ZFS_LITTLE_ENDIAN */ 117eda14cbcSMatt Macy counter &= ctx->ccm_counter_mask; 118eda14cbcSMatt Macy ctx->ccm_cb[1] = 119eda14cbcSMatt Macy (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 120eda14cbcSMatt Macy 121eda14cbcSMatt Macy /* 122eda14cbcSMatt Macy * XOR encrypted counter block with the current clear block. 123eda14cbcSMatt Macy */ 124eda14cbcSMatt Macy xor_block(blockp, lastp); 125eda14cbcSMatt Macy 126eda14cbcSMatt Macy ctx->ccm_processed_data_len += block_size; 127eda14cbcSMatt Macy 128eda14cbcSMatt Macy crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 129eda14cbcSMatt Macy &out_data_1_len, &out_data_2, block_size); 130eda14cbcSMatt Macy 131eda14cbcSMatt Macy /* copy block to where it belongs */ 132eda14cbcSMatt Macy if (out_data_1_len == block_size) { 133eda14cbcSMatt Macy copy_block(lastp, out_data_1); 134eda14cbcSMatt Macy } else { 135da5137abSMartin Matuska memcpy(out_data_1, lastp, out_data_1_len); 136eda14cbcSMatt Macy if (out_data_2 != NULL) { 137da5137abSMartin Matuska memcpy(out_data_2, 138da5137abSMartin Matuska lastp + out_data_1_len, 139eda14cbcSMatt Macy block_size - out_data_1_len); 140eda14cbcSMatt Macy } 141eda14cbcSMatt Macy } 142eda14cbcSMatt Macy /* update offset */ 143eda14cbcSMatt Macy out->cd_offset += block_size; 144eda14cbcSMatt Macy 145eda14cbcSMatt Macy /* Update pointer to next block of data to be processed. */ 146eda14cbcSMatt Macy if (ctx->ccm_remainder_len != 0) { 147eda14cbcSMatt Macy datap += need; 148eda14cbcSMatt Macy ctx->ccm_remainder_len = 0; 149eda14cbcSMatt Macy } else { 150eda14cbcSMatt Macy datap += block_size; 151eda14cbcSMatt Macy } 152eda14cbcSMatt Macy 153eda14cbcSMatt Macy remainder = (size_t)&data[length] - (size_t)datap; 154eda14cbcSMatt Macy 155eda14cbcSMatt Macy /* Incomplete last block. */ 156eda14cbcSMatt Macy if (remainder > 0 && remainder < block_size) { 157da5137abSMartin Matuska memcpy(ctx->ccm_remainder, datap, remainder); 158eda14cbcSMatt Macy ctx->ccm_remainder_len = remainder; 159eda14cbcSMatt Macy ctx->ccm_copy_to = datap; 160eda14cbcSMatt Macy goto out; 161eda14cbcSMatt Macy } 162eda14cbcSMatt Macy ctx->ccm_copy_to = NULL; 163eda14cbcSMatt Macy 164eda14cbcSMatt Macy } while (remainder > 0); 165eda14cbcSMatt Macy 166eda14cbcSMatt Macy out: 167eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 168eda14cbcSMatt Macy } 169eda14cbcSMatt Macy 170eda14cbcSMatt Macy void 171eda14cbcSMatt Macy calculate_ccm_mac(ccm_ctx_t *ctx, uint8_t *ccm_mac, 172eda14cbcSMatt Macy int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)) 173eda14cbcSMatt Macy { 174eda14cbcSMatt Macy uint64_t counter; 175eda14cbcSMatt Macy uint8_t *counterp, *mac_buf; 176eda14cbcSMatt Macy int i; 177eda14cbcSMatt Macy 178eda14cbcSMatt Macy mac_buf = (uint8_t *)ctx->ccm_mac_buf; 179eda14cbcSMatt Macy 180eda14cbcSMatt Macy /* first counter block start with index 0 */ 181eda14cbcSMatt Macy counter = 0; 182eda14cbcSMatt Macy ctx->ccm_cb[1] = (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 183eda14cbcSMatt Macy 184eda14cbcSMatt Macy counterp = (uint8_t *)ctx->ccm_tmp; 185eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp); 186eda14cbcSMatt Macy 187eda14cbcSMatt Macy /* calculate XOR of MAC with first counter block */ 188eda14cbcSMatt Macy for (i = 0; i < ctx->ccm_mac_len; i++) { 189eda14cbcSMatt Macy ccm_mac[i] = mac_buf[i] ^ counterp[i]; 190eda14cbcSMatt Macy } 191eda14cbcSMatt Macy } 192eda14cbcSMatt Macy 193eda14cbcSMatt Macy int 194eda14cbcSMatt Macy ccm_encrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size, 195eda14cbcSMatt Macy int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 196eda14cbcSMatt Macy void (*xor_block)(uint8_t *, uint8_t *)) 197eda14cbcSMatt Macy { 198eda14cbcSMatt Macy uint8_t *lastp, *mac_buf, *ccm_mac_p, *macp = NULL; 199eda14cbcSMatt Macy void *iov_or_mp; 200eda14cbcSMatt Macy offset_t offset; 201eda14cbcSMatt Macy uint8_t *out_data_1; 202eda14cbcSMatt Macy uint8_t *out_data_2; 203eda14cbcSMatt Macy size_t out_data_1_len; 204eda14cbcSMatt Macy int i; 205eda14cbcSMatt Macy 206eda14cbcSMatt Macy if (out->cd_length < (ctx->ccm_remainder_len + ctx->ccm_mac_len)) { 207eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE); 208eda14cbcSMatt Macy } 209eda14cbcSMatt Macy 210eda14cbcSMatt Macy /* 211eda14cbcSMatt Macy * When we get here, the number of bytes of payload processed 212eda14cbcSMatt Macy * plus whatever data remains, if any, 213eda14cbcSMatt Macy * should be the same as the number of bytes that's being 214eda14cbcSMatt Macy * passed in the argument during init time. 215eda14cbcSMatt Macy */ 216eda14cbcSMatt Macy if ((ctx->ccm_processed_data_len + ctx->ccm_remainder_len) 217eda14cbcSMatt Macy != (ctx->ccm_data_len)) { 218eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE); 219eda14cbcSMatt Macy } 220eda14cbcSMatt Macy 221eda14cbcSMatt Macy mac_buf = (uint8_t *)ctx->ccm_mac_buf; 222eda14cbcSMatt Macy 223eda14cbcSMatt Macy if (ctx->ccm_remainder_len > 0) { 224eda14cbcSMatt Macy 225eda14cbcSMatt Macy /* ccm_mac_input_buf is not used for encryption */ 226eda14cbcSMatt Macy macp = (uint8_t *)ctx->ccm_mac_input_buf; 227da5137abSMartin Matuska memset(macp, 0, block_size); 228eda14cbcSMatt Macy 229eda14cbcSMatt Macy /* copy remainder to temporary buffer */ 230da5137abSMartin Matuska memcpy(macp, ctx->ccm_remainder, ctx->ccm_remainder_len); 231eda14cbcSMatt Macy 232eda14cbcSMatt Macy /* calculate the CBC MAC */ 233eda14cbcSMatt Macy xor_block(macp, mac_buf); 234eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 235eda14cbcSMatt Macy 236eda14cbcSMatt Macy /* calculate the counter mode */ 237eda14cbcSMatt Macy lastp = (uint8_t *)ctx->ccm_tmp; 238eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, lastp); 239eda14cbcSMatt Macy 240eda14cbcSMatt Macy /* XOR with counter block */ 241eda14cbcSMatt Macy for (i = 0; i < ctx->ccm_remainder_len; i++) { 242eda14cbcSMatt Macy macp[i] ^= lastp[i]; 243eda14cbcSMatt Macy } 244eda14cbcSMatt Macy ctx->ccm_processed_data_len += ctx->ccm_remainder_len; 245eda14cbcSMatt Macy } 246eda14cbcSMatt Macy 247eda14cbcSMatt Macy /* Calculate the CCM MAC */ 248eda14cbcSMatt Macy ccm_mac_p = (uint8_t *)ctx->ccm_tmp; 249eda14cbcSMatt Macy calculate_ccm_mac(ctx, ccm_mac_p, encrypt_block); 250eda14cbcSMatt Macy 251eda14cbcSMatt Macy crypto_init_ptrs(out, &iov_or_mp, &offset); 252eda14cbcSMatt Macy crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1, 253eda14cbcSMatt Macy &out_data_1_len, &out_data_2, 254eda14cbcSMatt Macy ctx->ccm_remainder_len + ctx->ccm_mac_len); 255eda14cbcSMatt Macy 256eda14cbcSMatt Macy if (ctx->ccm_remainder_len > 0) { 257eda14cbcSMatt Macy /* copy temporary block to where it belongs */ 258eda14cbcSMatt Macy if (out_data_2 == NULL) { 259eda14cbcSMatt Macy /* everything will fit in out_data_1 */ 260da5137abSMartin Matuska memcpy(out_data_1, macp, ctx->ccm_remainder_len); 261da5137abSMartin Matuska memcpy(out_data_1 + ctx->ccm_remainder_len, ccm_mac_p, 262eda14cbcSMatt Macy ctx->ccm_mac_len); 263eda14cbcSMatt Macy } else { 264eda14cbcSMatt Macy if (out_data_1_len < ctx->ccm_remainder_len) { 265eda14cbcSMatt Macy size_t data_2_len_used; 266eda14cbcSMatt Macy 267da5137abSMartin Matuska memcpy(out_data_1, macp, out_data_1_len); 268eda14cbcSMatt Macy 269eda14cbcSMatt Macy data_2_len_used = ctx->ccm_remainder_len 270eda14cbcSMatt Macy - out_data_1_len; 271eda14cbcSMatt Macy 272da5137abSMartin Matuska memcpy(out_data_2, 273da5137abSMartin Matuska (uint8_t *)macp + out_data_1_len, 274da5137abSMartin Matuska data_2_len_used); 275da5137abSMartin Matuska memcpy(out_data_2 + data_2_len_used, 276da5137abSMartin Matuska ccm_mac_p, 277eda14cbcSMatt Macy ctx->ccm_mac_len); 278eda14cbcSMatt Macy } else { 279da5137abSMartin Matuska memcpy(out_data_1, macp, out_data_1_len); 280eda14cbcSMatt Macy if (out_data_1_len == ctx->ccm_remainder_len) { 281eda14cbcSMatt Macy /* mac will be in out_data_2 */ 282da5137abSMartin Matuska memcpy(out_data_2, ccm_mac_p, 283eda14cbcSMatt Macy ctx->ccm_mac_len); 284eda14cbcSMatt Macy } else { 285eda14cbcSMatt Macy size_t len_not_used = out_data_1_len - 286eda14cbcSMatt Macy ctx->ccm_remainder_len; 287eda14cbcSMatt Macy /* 288eda14cbcSMatt Macy * part of mac in will be in 289eda14cbcSMatt Macy * out_data_1, part of the mac will be 290eda14cbcSMatt Macy * in out_data_2 291eda14cbcSMatt Macy */ 292da5137abSMartin Matuska memcpy(out_data_1 + 293da5137abSMartin Matuska ctx->ccm_remainder_len, 294da5137abSMartin Matuska ccm_mac_p, len_not_used); 295da5137abSMartin Matuska memcpy(out_data_2, 296da5137abSMartin Matuska ccm_mac_p + len_not_used, 297eda14cbcSMatt Macy ctx->ccm_mac_len - len_not_used); 298eda14cbcSMatt Macy 299eda14cbcSMatt Macy } 300eda14cbcSMatt Macy } 301eda14cbcSMatt Macy } 302eda14cbcSMatt Macy } else { 303eda14cbcSMatt Macy /* copy block to where it belongs */ 304da5137abSMartin Matuska memcpy(out_data_1, ccm_mac_p, out_data_1_len); 305eda14cbcSMatt Macy if (out_data_2 != NULL) { 306da5137abSMartin Matuska memcpy(out_data_2, ccm_mac_p + out_data_1_len, 307eda14cbcSMatt Macy block_size - out_data_1_len); 308eda14cbcSMatt Macy } 309eda14cbcSMatt Macy } 310eda14cbcSMatt Macy out->cd_offset += ctx->ccm_remainder_len + ctx->ccm_mac_len; 311eda14cbcSMatt Macy ctx->ccm_remainder_len = 0; 312eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 313eda14cbcSMatt Macy } 314eda14cbcSMatt Macy 315eda14cbcSMatt Macy /* 316eda14cbcSMatt Macy * This will only deal with decrypting the last block of the input that 317eda14cbcSMatt Macy * might not be a multiple of block length. 318eda14cbcSMatt Macy */ 319eda14cbcSMatt Macy static void 320eda14cbcSMatt Macy ccm_decrypt_incomplete_block(ccm_ctx_t *ctx, 321eda14cbcSMatt Macy int (*encrypt_block)(const void *, const uint8_t *, uint8_t *)) 322eda14cbcSMatt Macy { 323eda14cbcSMatt Macy uint8_t *datap, *outp, *counterp; 324eda14cbcSMatt Macy int i; 325eda14cbcSMatt Macy 326eda14cbcSMatt Macy datap = (uint8_t *)ctx->ccm_remainder; 327eda14cbcSMatt Macy outp = &((ctx->ccm_pt_buf)[ctx->ccm_processed_data_len]); 328eda14cbcSMatt Macy 329eda14cbcSMatt Macy counterp = (uint8_t *)ctx->ccm_tmp; 330eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp); 331eda14cbcSMatt Macy 332eda14cbcSMatt Macy /* XOR with counter block */ 333eda14cbcSMatt Macy for (i = 0; i < ctx->ccm_remainder_len; i++) { 334eda14cbcSMatt Macy outp[i] = datap[i] ^ counterp[i]; 335eda14cbcSMatt Macy } 336eda14cbcSMatt Macy } 337eda14cbcSMatt Macy 338eda14cbcSMatt Macy /* 339eda14cbcSMatt Macy * This will decrypt the cipher text. However, the plaintext won't be 340eda14cbcSMatt Macy * returned to the caller. It will be returned when decrypt_final() is 341eda14cbcSMatt Macy * called if the MAC matches 342eda14cbcSMatt Macy */ 343eda14cbcSMatt Macy int 344eda14cbcSMatt Macy ccm_mode_decrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length, 345eda14cbcSMatt Macy crypto_data_t *out, size_t block_size, 346eda14cbcSMatt Macy int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 347eda14cbcSMatt Macy void (*copy_block)(uint8_t *, uint8_t *), 348eda14cbcSMatt Macy void (*xor_block)(uint8_t *, uint8_t *)) 349eda14cbcSMatt Macy { 350e92ffd9bSMartin Matuska (void) out; 351eda14cbcSMatt Macy size_t remainder = length; 352eda14cbcSMatt Macy size_t need = 0; 353eda14cbcSMatt Macy uint8_t *datap = (uint8_t *)data; 354eda14cbcSMatt Macy uint8_t *blockp; 355eda14cbcSMatt Macy uint8_t *cbp; 356eda14cbcSMatt Macy uint64_t counter; 357eda14cbcSMatt Macy size_t pt_len, total_decrypted_len, mac_len, pm_len, pd_len; 358eda14cbcSMatt Macy uint8_t *resultp; 359eda14cbcSMatt Macy 360eda14cbcSMatt Macy 361eda14cbcSMatt Macy pm_len = ctx->ccm_processed_mac_len; 362eda14cbcSMatt Macy 363eda14cbcSMatt Macy if (pm_len > 0) { 364eda14cbcSMatt Macy uint8_t *tmp; 365eda14cbcSMatt Macy /* 366eda14cbcSMatt Macy * all ciphertext has been processed, just waiting for 367eda14cbcSMatt Macy * part of the value of the mac 368eda14cbcSMatt Macy */ 369eda14cbcSMatt Macy if ((pm_len + length) > ctx->ccm_mac_len) { 370eda14cbcSMatt Macy return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 371eda14cbcSMatt Macy } 372eda14cbcSMatt Macy tmp = (uint8_t *)ctx->ccm_mac_input_buf; 373eda14cbcSMatt Macy 374da5137abSMartin Matuska memcpy(tmp + pm_len, datap, length); 375eda14cbcSMatt Macy 376eda14cbcSMatt Macy ctx->ccm_processed_mac_len += length; 377eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 378eda14cbcSMatt Macy } 379eda14cbcSMatt Macy 380eda14cbcSMatt Macy /* 381eda14cbcSMatt Macy * If we decrypt the given data, what total amount of data would 382eda14cbcSMatt Macy * have been decrypted? 383eda14cbcSMatt Macy */ 384eda14cbcSMatt Macy pd_len = ctx->ccm_processed_data_len; 385eda14cbcSMatt Macy total_decrypted_len = pd_len + length + ctx->ccm_remainder_len; 386eda14cbcSMatt Macy 387eda14cbcSMatt Macy if (total_decrypted_len > 388eda14cbcSMatt Macy (ctx->ccm_data_len + ctx->ccm_mac_len)) { 389eda14cbcSMatt Macy return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 390eda14cbcSMatt Macy } 391eda14cbcSMatt Macy 392eda14cbcSMatt Macy pt_len = ctx->ccm_data_len; 393eda14cbcSMatt Macy 394eda14cbcSMatt Macy if (total_decrypted_len > pt_len) { 395eda14cbcSMatt Macy /* 396eda14cbcSMatt Macy * part of the input will be the MAC, need to isolate that 397eda14cbcSMatt Macy * to be dealt with later. The left-over data in 398eda14cbcSMatt Macy * ccm_remainder_len from last time will not be part of the 399eda14cbcSMatt Macy * MAC. Otherwise, it would have already been taken out 400eda14cbcSMatt Macy * when this call is made last time. 401eda14cbcSMatt Macy */ 402eda14cbcSMatt Macy size_t pt_part = pt_len - pd_len - ctx->ccm_remainder_len; 403eda14cbcSMatt Macy 404eda14cbcSMatt Macy mac_len = length - pt_part; 405eda14cbcSMatt Macy 406eda14cbcSMatt Macy ctx->ccm_processed_mac_len = mac_len; 407da5137abSMartin Matuska memcpy(ctx->ccm_mac_input_buf, data + pt_part, mac_len); 408eda14cbcSMatt Macy 409eda14cbcSMatt Macy if (pt_part + ctx->ccm_remainder_len < block_size) { 410eda14cbcSMatt Macy /* 411eda14cbcSMatt Macy * since this is last of the ciphertext, will 412eda14cbcSMatt Macy * just decrypt with it here 413eda14cbcSMatt Macy */ 414da5137abSMartin Matuska memcpy(&((uint8_t *)ctx->ccm_remainder) 415da5137abSMartin Matuska [ctx->ccm_remainder_len], datap, pt_part); 416eda14cbcSMatt Macy ctx->ccm_remainder_len += pt_part; 417eda14cbcSMatt Macy ccm_decrypt_incomplete_block(ctx, encrypt_block); 418eda14cbcSMatt Macy ctx->ccm_processed_data_len += ctx->ccm_remainder_len; 419eda14cbcSMatt Macy ctx->ccm_remainder_len = 0; 420eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 421eda14cbcSMatt Macy } else { 422eda14cbcSMatt Macy /* let rest of the code handle this */ 423eda14cbcSMatt Macy length = pt_part; 424eda14cbcSMatt Macy } 425eda14cbcSMatt Macy } else if (length + ctx->ccm_remainder_len < block_size) { 426eda14cbcSMatt Macy /* accumulate bytes here and return */ 427da5137abSMartin Matuska memcpy((uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len, 428da5137abSMartin Matuska datap, 429eda14cbcSMatt Macy length); 430eda14cbcSMatt Macy ctx->ccm_remainder_len += length; 431eda14cbcSMatt Macy ctx->ccm_copy_to = datap; 432eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 433eda14cbcSMatt Macy } 434eda14cbcSMatt Macy 435eda14cbcSMatt Macy do { 436eda14cbcSMatt Macy /* Unprocessed data from last call. */ 437eda14cbcSMatt Macy if (ctx->ccm_remainder_len > 0) { 438eda14cbcSMatt Macy need = block_size - ctx->ccm_remainder_len; 439eda14cbcSMatt Macy 440eda14cbcSMatt Macy if (need > remainder) 441eda14cbcSMatt Macy return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE); 442eda14cbcSMatt Macy 443da5137abSMartin Matuska memcpy(&((uint8_t *)ctx->ccm_remainder) 444da5137abSMartin Matuska [ctx->ccm_remainder_len], datap, need); 445eda14cbcSMatt Macy 446eda14cbcSMatt Macy blockp = (uint8_t *)ctx->ccm_remainder; 447eda14cbcSMatt Macy } else { 448eda14cbcSMatt Macy blockp = datap; 449eda14cbcSMatt Macy } 450eda14cbcSMatt Macy 451eda14cbcSMatt Macy /* Calculate the counter mode, ccm_cb is the counter block */ 452eda14cbcSMatt Macy cbp = (uint8_t *)ctx->ccm_tmp; 453eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, cbp); 454eda14cbcSMatt Macy 455eda14cbcSMatt Macy /* 456eda14cbcSMatt Macy * Increment counter. 457eda14cbcSMatt Macy * Counter bits are confined to the bottom 64 bits 458eda14cbcSMatt Macy */ 459eda14cbcSMatt Macy #ifdef _ZFS_LITTLE_ENDIAN 460eda14cbcSMatt Macy counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask); 461eda14cbcSMatt Macy counter = htonll(counter + 1); 462eda14cbcSMatt Macy #else 463eda14cbcSMatt Macy counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask; 464eda14cbcSMatt Macy counter++; 465eda14cbcSMatt Macy #endif /* _ZFS_LITTLE_ENDIAN */ 466eda14cbcSMatt Macy counter &= ctx->ccm_counter_mask; 467eda14cbcSMatt Macy ctx->ccm_cb[1] = 468eda14cbcSMatt Macy (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter; 469eda14cbcSMatt Macy 470eda14cbcSMatt Macy /* XOR with the ciphertext */ 471eda14cbcSMatt Macy xor_block(blockp, cbp); 472eda14cbcSMatt Macy 473eda14cbcSMatt Macy /* Copy the plaintext to the "holding buffer" */ 474eda14cbcSMatt Macy resultp = (uint8_t *)ctx->ccm_pt_buf + 475eda14cbcSMatt Macy ctx->ccm_processed_data_len; 476eda14cbcSMatt Macy copy_block(cbp, resultp); 477eda14cbcSMatt Macy 478eda14cbcSMatt Macy ctx->ccm_processed_data_len += block_size; 479eda14cbcSMatt Macy 480eda14cbcSMatt Macy ctx->ccm_lastp = blockp; 481eda14cbcSMatt Macy 482eda14cbcSMatt Macy /* Update pointer to next block of data to be processed. */ 483eda14cbcSMatt Macy if (ctx->ccm_remainder_len != 0) { 484eda14cbcSMatt Macy datap += need; 485eda14cbcSMatt Macy ctx->ccm_remainder_len = 0; 486eda14cbcSMatt Macy } else { 487eda14cbcSMatt Macy datap += block_size; 488eda14cbcSMatt Macy } 489eda14cbcSMatt Macy 490eda14cbcSMatt Macy remainder = (size_t)&data[length] - (size_t)datap; 491eda14cbcSMatt Macy 492eda14cbcSMatt Macy /* Incomplete last block */ 493eda14cbcSMatt Macy if (remainder > 0 && remainder < block_size) { 494da5137abSMartin Matuska memcpy(ctx->ccm_remainder, datap, remainder); 495eda14cbcSMatt Macy ctx->ccm_remainder_len = remainder; 496eda14cbcSMatt Macy ctx->ccm_copy_to = datap; 497eda14cbcSMatt Macy if (ctx->ccm_processed_mac_len > 0) { 498eda14cbcSMatt Macy /* 499eda14cbcSMatt Macy * not expecting anymore ciphertext, just 500eda14cbcSMatt Macy * compute plaintext for the remaining input 501eda14cbcSMatt Macy */ 502eda14cbcSMatt Macy ccm_decrypt_incomplete_block(ctx, 503eda14cbcSMatt Macy encrypt_block); 504eda14cbcSMatt Macy ctx->ccm_processed_data_len += remainder; 505eda14cbcSMatt Macy ctx->ccm_remainder_len = 0; 506eda14cbcSMatt Macy } 507eda14cbcSMatt Macy goto out; 508eda14cbcSMatt Macy } 509eda14cbcSMatt Macy ctx->ccm_copy_to = NULL; 510eda14cbcSMatt Macy 511eda14cbcSMatt Macy } while (remainder > 0); 512eda14cbcSMatt Macy 513eda14cbcSMatt Macy out: 514eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 515eda14cbcSMatt Macy } 516eda14cbcSMatt Macy 517eda14cbcSMatt Macy int 518eda14cbcSMatt Macy ccm_decrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size, 519eda14cbcSMatt Macy int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 520eda14cbcSMatt Macy void (*copy_block)(uint8_t *, uint8_t *), 521eda14cbcSMatt Macy void (*xor_block)(uint8_t *, uint8_t *)) 522eda14cbcSMatt Macy { 523eda14cbcSMatt Macy size_t mac_remain, pt_len; 524eda14cbcSMatt Macy uint8_t *pt, *mac_buf, *macp, *ccm_mac_p; 525eda14cbcSMatt Macy int rv; 526eda14cbcSMatt Macy 527eda14cbcSMatt Macy pt_len = ctx->ccm_data_len; 528eda14cbcSMatt Macy 529eda14cbcSMatt Macy /* Make sure output buffer can fit all of the plaintext */ 530eda14cbcSMatt Macy if (out->cd_length < pt_len) { 531eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE); 532eda14cbcSMatt Macy } 533eda14cbcSMatt Macy 534eda14cbcSMatt Macy pt = ctx->ccm_pt_buf; 535eda14cbcSMatt Macy mac_remain = ctx->ccm_processed_data_len; 536eda14cbcSMatt Macy mac_buf = (uint8_t *)ctx->ccm_mac_buf; 537eda14cbcSMatt Macy 538eda14cbcSMatt Macy macp = (uint8_t *)ctx->ccm_tmp; 539eda14cbcSMatt Macy 540eda14cbcSMatt Macy while (mac_remain > 0) { 541eda14cbcSMatt Macy if (mac_remain < block_size) { 542da5137abSMartin Matuska memset(macp, 0, block_size); 543da5137abSMartin Matuska memcpy(macp, pt, mac_remain); 544eda14cbcSMatt Macy mac_remain = 0; 545eda14cbcSMatt Macy } else { 546eda14cbcSMatt Macy copy_block(pt, macp); 547eda14cbcSMatt Macy mac_remain -= block_size; 548eda14cbcSMatt Macy pt += block_size; 549eda14cbcSMatt Macy } 550eda14cbcSMatt Macy 551eda14cbcSMatt Macy /* calculate the CBC MAC */ 552eda14cbcSMatt Macy xor_block(macp, mac_buf); 553eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 554eda14cbcSMatt Macy } 555eda14cbcSMatt Macy 556eda14cbcSMatt Macy /* Calculate the CCM MAC */ 557eda14cbcSMatt Macy ccm_mac_p = (uint8_t *)ctx->ccm_tmp; 558eda14cbcSMatt Macy calculate_ccm_mac((ccm_ctx_t *)ctx, ccm_mac_p, encrypt_block); 559eda14cbcSMatt Macy 560eda14cbcSMatt Macy /* compare the input CCM MAC value with what we calculated */ 561da5137abSMartin Matuska if (memcmp(ctx->ccm_mac_input_buf, ccm_mac_p, ctx->ccm_mac_len)) { 562eda14cbcSMatt Macy /* They don't match */ 563eda14cbcSMatt Macy return (CRYPTO_INVALID_MAC); 564eda14cbcSMatt Macy } else { 565eda14cbcSMatt Macy rv = crypto_put_output_data(ctx->ccm_pt_buf, out, pt_len); 566eda14cbcSMatt Macy if (rv != CRYPTO_SUCCESS) 567eda14cbcSMatt Macy return (rv); 568eda14cbcSMatt Macy out->cd_offset += pt_len; 569eda14cbcSMatt Macy } 570eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 571eda14cbcSMatt Macy } 572eda14cbcSMatt Macy 573eda14cbcSMatt Macy static int 574eda14cbcSMatt Macy ccm_validate_args(CK_AES_CCM_PARAMS *ccm_param, boolean_t is_encrypt_init) 575eda14cbcSMatt Macy { 576eda14cbcSMatt Macy size_t macSize, nonceSize; 577eda14cbcSMatt Macy uint8_t q; 578eda14cbcSMatt Macy uint64_t maxValue; 579eda14cbcSMatt Macy 580eda14cbcSMatt Macy /* 581eda14cbcSMatt Macy * Check the length of the MAC. The only valid 582eda14cbcSMatt Macy * lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16 583eda14cbcSMatt Macy */ 584eda14cbcSMatt Macy macSize = ccm_param->ulMACSize; 585eda14cbcSMatt Macy if ((macSize < 4) || (macSize > 16) || ((macSize % 2) != 0)) { 586eda14cbcSMatt Macy return (CRYPTO_MECHANISM_PARAM_INVALID); 587eda14cbcSMatt Macy } 588eda14cbcSMatt Macy 589eda14cbcSMatt Macy /* Check the nonce length. Valid values are 7, 8, 9, 10, 11, 12, 13 */ 590eda14cbcSMatt Macy nonceSize = ccm_param->ulNonceSize; 591eda14cbcSMatt Macy if ((nonceSize < 7) || (nonceSize > 13)) { 592eda14cbcSMatt Macy return (CRYPTO_MECHANISM_PARAM_INVALID); 593eda14cbcSMatt Macy } 594eda14cbcSMatt Macy 595eda14cbcSMatt Macy /* q is the length of the field storing the length, in bytes */ 596eda14cbcSMatt Macy q = (uint8_t)((15 - nonceSize) & 0xFF); 597eda14cbcSMatt Macy 598eda14cbcSMatt Macy 599eda14cbcSMatt Macy /* 600eda14cbcSMatt Macy * If it is decrypt, need to make sure size of ciphertext is at least 601eda14cbcSMatt Macy * bigger than MAC len 602eda14cbcSMatt Macy */ 603eda14cbcSMatt Macy if ((!is_encrypt_init) && (ccm_param->ulDataSize < macSize)) { 604eda14cbcSMatt Macy return (CRYPTO_MECHANISM_PARAM_INVALID); 605eda14cbcSMatt Macy } 606eda14cbcSMatt Macy 607eda14cbcSMatt Macy /* 608eda14cbcSMatt Macy * Check to make sure the length of the payload is within the 609eda14cbcSMatt Macy * range of values allowed by q 610eda14cbcSMatt Macy */ 611eda14cbcSMatt Macy if (q < 8) { 612eda14cbcSMatt Macy maxValue = (1ULL << (q * 8)) - 1; 613eda14cbcSMatt Macy } else { 614eda14cbcSMatt Macy maxValue = ULONG_MAX; 615eda14cbcSMatt Macy } 616eda14cbcSMatt Macy 617eda14cbcSMatt Macy if (ccm_param->ulDataSize > maxValue) { 618eda14cbcSMatt Macy return (CRYPTO_MECHANISM_PARAM_INVALID); 619eda14cbcSMatt Macy } 620eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 621eda14cbcSMatt Macy } 622eda14cbcSMatt Macy 623eda14cbcSMatt Macy /* 624eda14cbcSMatt Macy * Format the first block used in CBC-MAC (B0) and the initial counter 625eda14cbcSMatt Macy * block based on formatting functions and counter generation functions 626eda14cbcSMatt Macy * specified in RFC 3610 and NIST publication 800-38C, appendix A 627eda14cbcSMatt Macy * 628eda14cbcSMatt Macy * b0 is the first block used in CBC-MAC 629eda14cbcSMatt Macy * cb0 is the first counter block 630eda14cbcSMatt Macy * 631eda14cbcSMatt Macy * It's assumed that the arguments b0 and cb0 are preallocated AES blocks 632eda14cbcSMatt Macy * 633eda14cbcSMatt Macy */ 634eda14cbcSMatt Macy static void 635eda14cbcSMatt Macy ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize, 636eda14cbcSMatt Macy ulong_t authDataSize, uint8_t *b0, ccm_ctx_t *aes_ctx) 637eda14cbcSMatt Macy { 638eda14cbcSMatt Macy uint64_t payloadSize; 639eda14cbcSMatt Macy uint8_t t, q, have_adata = 0; 640eda14cbcSMatt Macy size_t limit; 641eda14cbcSMatt Macy int i, j, k; 642eda14cbcSMatt Macy uint64_t mask = 0; 643eda14cbcSMatt Macy uint8_t *cb; 644eda14cbcSMatt Macy 645eda14cbcSMatt Macy q = (uint8_t)((15 - nonceSize) & 0xFF); 646eda14cbcSMatt Macy t = (uint8_t)((aes_ctx->ccm_mac_len) & 0xFF); 647eda14cbcSMatt Macy 648eda14cbcSMatt Macy /* Construct the first octet of b0 */ 649eda14cbcSMatt Macy if (authDataSize > 0) { 650eda14cbcSMatt Macy have_adata = 1; 651eda14cbcSMatt Macy } 652eda14cbcSMatt Macy b0[0] = (have_adata << 6) | (((t - 2) / 2) << 3) | (q - 1); 653eda14cbcSMatt Macy 654eda14cbcSMatt Macy /* copy the nonce value into b0 */ 655da5137abSMartin Matuska memcpy(&(b0[1]), nonce, nonceSize); 656eda14cbcSMatt Macy 657eda14cbcSMatt Macy /* store the length of the payload into b0 */ 658da5137abSMartin Matuska memset(&(b0[1+nonceSize]), 0, q); 659eda14cbcSMatt Macy 660eda14cbcSMatt Macy payloadSize = aes_ctx->ccm_data_len; 661eda14cbcSMatt Macy limit = 8 < q ? 8 : q; 662eda14cbcSMatt Macy 663eda14cbcSMatt Macy for (i = 0, j = 0, k = 15; i < limit; i++, j += 8, k--) { 664eda14cbcSMatt Macy b0[k] = (uint8_t)((payloadSize >> j) & 0xFF); 665eda14cbcSMatt Macy } 666eda14cbcSMatt Macy 667eda14cbcSMatt Macy /* format the counter block */ 668eda14cbcSMatt Macy 669eda14cbcSMatt Macy cb = (uint8_t *)aes_ctx->ccm_cb; 670eda14cbcSMatt Macy 671eda14cbcSMatt Macy cb[0] = 0x07 & (q-1); /* first byte */ 672eda14cbcSMatt Macy 673eda14cbcSMatt Macy /* copy the nonce value into the counter block */ 674da5137abSMartin Matuska memcpy(&(cb[1]), nonce, nonceSize); 675eda14cbcSMatt Macy 676da5137abSMartin Matuska memset(&(cb[1+nonceSize]), 0, q); 677eda14cbcSMatt Macy 678eda14cbcSMatt Macy /* Create the mask for the counter field based on the size of nonce */ 679eda14cbcSMatt Macy q <<= 3; 680eda14cbcSMatt Macy while (q-- > 0) { 681eda14cbcSMatt Macy mask |= (1ULL << q); 682eda14cbcSMatt Macy } 683eda14cbcSMatt Macy 684eda14cbcSMatt Macy #ifdef _ZFS_LITTLE_ENDIAN 685eda14cbcSMatt Macy mask = htonll(mask); 686eda14cbcSMatt Macy #endif 687eda14cbcSMatt Macy aes_ctx->ccm_counter_mask = mask; 688eda14cbcSMatt Macy 689eda14cbcSMatt Macy /* 690eda14cbcSMatt Macy * During calculation, we start using counter block 1, we will 691eda14cbcSMatt Macy * set it up right here. 692eda14cbcSMatt Macy * We can just set the last byte to have the value 1, because 693eda14cbcSMatt Macy * even with the biggest nonce of 13, the last byte of the 694eda14cbcSMatt Macy * counter block will be used for the counter value. 695eda14cbcSMatt Macy */ 696eda14cbcSMatt Macy cb[15] = 0x01; 697eda14cbcSMatt Macy } 698eda14cbcSMatt Macy 699eda14cbcSMatt Macy /* 700eda14cbcSMatt Macy * Encode the length of the associated data as 701eda14cbcSMatt Macy * specified in RFC 3610 and NIST publication 800-38C, appendix A 702eda14cbcSMatt Macy */ 703eda14cbcSMatt Macy static void 704eda14cbcSMatt Macy encode_adata_len(ulong_t auth_data_len, uint8_t *encoded, size_t *encoded_len) 705eda14cbcSMatt Macy { 706eda14cbcSMatt Macy #ifdef UNALIGNED_POINTERS_PERMITTED 707eda14cbcSMatt Macy uint32_t *lencoded_ptr; 708eda14cbcSMatt Macy #ifdef _LP64 709eda14cbcSMatt Macy uint64_t *llencoded_ptr; 710eda14cbcSMatt Macy #endif 711eda14cbcSMatt Macy #endif /* UNALIGNED_POINTERS_PERMITTED */ 712eda14cbcSMatt Macy 713eda14cbcSMatt Macy if (auth_data_len < ((1ULL<<16) - (1ULL<<8))) { 714eda14cbcSMatt Macy /* 0 < a < (2^16-2^8) */ 715eda14cbcSMatt Macy *encoded_len = 2; 716eda14cbcSMatt Macy encoded[0] = (auth_data_len & 0xff00) >> 8; 717eda14cbcSMatt Macy encoded[1] = auth_data_len & 0xff; 718eda14cbcSMatt Macy 719eda14cbcSMatt Macy } else if ((auth_data_len >= ((1ULL<<16) - (1ULL<<8))) && 720eda14cbcSMatt Macy (auth_data_len < (1ULL << 31))) { 721eda14cbcSMatt Macy /* (2^16-2^8) <= a < 2^32 */ 722eda14cbcSMatt Macy *encoded_len = 6; 723eda14cbcSMatt Macy encoded[0] = 0xff; 724eda14cbcSMatt Macy encoded[1] = 0xfe; 725eda14cbcSMatt Macy #ifdef UNALIGNED_POINTERS_PERMITTED 726eda14cbcSMatt Macy lencoded_ptr = (uint32_t *)&encoded[2]; 727eda14cbcSMatt Macy *lencoded_ptr = htonl(auth_data_len); 728eda14cbcSMatt Macy #else 729eda14cbcSMatt Macy encoded[2] = (auth_data_len & 0xff000000) >> 24; 730eda14cbcSMatt Macy encoded[3] = (auth_data_len & 0xff0000) >> 16; 731eda14cbcSMatt Macy encoded[4] = (auth_data_len & 0xff00) >> 8; 732eda14cbcSMatt Macy encoded[5] = auth_data_len & 0xff; 733eda14cbcSMatt Macy #endif /* UNALIGNED_POINTERS_PERMITTED */ 734eda14cbcSMatt Macy 735eda14cbcSMatt Macy #ifdef _LP64 736eda14cbcSMatt Macy } else { 737eda14cbcSMatt Macy /* 2^32 <= a < 2^64 */ 738eda14cbcSMatt Macy *encoded_len = 10; 739eda14cbcSMatt Macy encoded[0] = 0xff; 740eda14cbcSMatt Macy encoded[1] = 0xff; 741eda14cbcSMatt Macy #ifdef UNALIGNED_POINTERS_PERMITTED 742eda14cbcSMatt Macy llencoded_ptr = (uint64_t *)&encoded[2]; 743eda14cbcSMatt Macy *llencoded_ptr = htonl(auth_data_len); 744eda14cbcSMatt Macy #else 745eda14cbcSMatt Macy encoded[2] = (auth_data_len & 0xff00000000000000) >> 56; 746eda14cbcSMatt Macy encoded[3] = (auth_data_len & 0xff000000000000) >> 48; 747eda14cbcSMatt Macy encoded[4] = (auth_data_len & 0xff0000000000) >> 40; 748eda14cbcSMatt Macy encoded[5] = (auth_data_len & 0xff00000000) >> 32; 749eda14cbcSMatt Macy encoded[6] = (auth_data_len & 0xff000000) >> 24; 750eda14cbcSMatt Macy encoded[7] = (auth_data_len & 0xff0000) >> 16; 751eda14cbcSMatt Macy encoded[8] = (auth_data_len & 0xff00) >> 8; 752eda14cbcSMatt Macy encoded[9] = auth_data_len & 0xff; 753eda14cbcSMatt Macy #endif /* UNALIGNED_POINTERS_PERMITTED */ 754eda14cbcSMatt Macy #endif /* _LP64 */ 755eda14cbcSMatt Macy } 756eda14cbcSMatt Macy } 757eda14cbcSMatt Macy 758eda14cbcSMatt Macy static int 759eda14cbcSMatt Macy ccm_init(ccm_ctx_t *ctx, unsigned char *nonce, size_t nonce_len, 760eda14cbcSMatt Macy unsigned char *auth_data, size_t auth_data_len, size_t block_size, 761eda14cbcSMatt Macy int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 762eda14cbcSMatt Macy void (*xor_block)(uint8_t *, uint8_t *)) 763eda14cbcSMatt Macy { 764eda14cbcSMatt Macy uint8_t *mac_buf, *datap, *ivp, *authp; 765eda14cbcSMatt Macy size_t remainder, processed; 766eda14cbcSMatt Macy uint8_t encoded_a[10]; /* max encoded auth data length is 10 octets */ 767eda14cbcSMatt Macy size_t encoded_a_len = 0; 768eda14cbcSMatt Macy 769eda14cbcSMatt Macy mac_buf = (uint8_t *)&(ctx->ccm_mac_buf); 770eda14cbcSMatt Macy 771eda14cbcSMatt Macy /* 772eda14cbcSMatt Macy * Format the 1st block for CBC-MAC and construct the 773eda14cbcSMatt Macy * 1st counter block. 774eda14cbcSMatt Macy * 775eda14cbcSMatt Macy * aes_ctx->ccm_iv is used for storing the counter block 776eda14cbcSMatt Macy * mac_buf will store b0 at this time. 777eda14cbcSMatt Macy */ 778eda14cbcSMatt Macy ccm_format_initial_blocks(nonce, nonce_len, 779eda14cbcSMatt Macy auth_data_len, mac_buf, ctx); 780eda14cbcSMatt Macy 781eda14cbcSMatt Macy /* The IV for CBC MAC for AES CCM mode is always zero */ 782eda14cbcSMatt Macy ivp = (uint8_t *)ctx->ccm_tmp; 783da5137abSMartin Matuska memset(ivp, 0, block_size); 784eda14cbcSMatt Macy 785eda14cbcSMatt Macy xor_block(ivp, mac_buf); 786eda14cbcSMatt Macy 787eda14cbcSMatt Macy /* encrypt the nonce */ 788eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 789eda14cbcSMatt Macy 790eda14cbcSMatt Macy /* take care of the associated data, if any */ 791eda14cbcSMatt Macy if (auth_data_len == 0) { 792eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 793eda14cbcSMatt Macy } 794eda14cbcSMatt Macy 795eda14cbcSMatt Macy encode_adata_len(auth_data_len, encoded_a, &encoded_a_len); 796eda14cbcSMatt Macy 797eda14cbcSMatt Macy remainder = auth_data_len; 798eda14cbcSMatt Macy 799eda14cbcSMatt Macy /* 1st block: it contains encoded associated data, and some data */ 800eda14cbcSMatt Macy authp = (uint8_t *)ctx->ccm_tmp; 801da5137abSMartin Matuska memset(authp, 0, block_size); 802da5137abSMartin Matuska memcpy(authp, encoded_a, encoded_a_len); 803eda14cbcSMatt Macy processed = block_size - encoded_a_len; 804eda14cbcSMatt Macy if (processed > auth_data_len) { 805eda14cbcSMatt Macy /* in case auth_data is very small */ 806eda14cbcSMatt Macy processed = auth_data_len; 807eda14cbcSMatt Macy } 808da5137abSMartin Matuska memcpy(authp+encoded_a_len, auth_data, processed); 809eda14cbcSMatt Macy /* xor with previous buffer */ 810eda14cbcSMatt Macy xor_block(authp, mac_buf); 811eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 812eda14cbcSMatt Macy remainder -= processed; 813eda14cbcSMatt Macy if (remainder == 0) { 814eda14cbcSMatt Macy /* a small amount of associated data, it's all done now */ 815eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 816eda14cbcSMatt Macy } 817eda14cbcSMatt Macy 818eda14cbcSMatt Macy do { 819eda14cbcSMatt Macy if (remainder < block_size) { 820eda14cbcSMatt Macy /* 821eda14cbcSMatt Macy * There's not a block full of data, pad rest of 822eda14cbcSMatt Macy * buffer with zero 823eda14cbcSMatt Macy */ 824da5137abSMartin Matuska memset(authp, 0, block_size); 825da5137abSMartin Matuska memcpy(authp, &(auth_data[processed]), remainder); 826eda14cbcSMatt Macy datap = (uint8_t *)authp; 827eda14cbcSMatt Macy remainder = 0; 828eda14cbcSMatt Macy } else { 829eda14cbcSMatt Macy datap = (uint8_t *)(&(auth_data[processed])); 830eda14cbcSMatt Macy processed += block_size; 831eda14cbcSMatt Macy remainder -= block_size; 832eda14cbcSMatt Macy } 833eda14cbcSMatt Macy 834eda14cbcSMatt Macy xor_block(datap, mac_buf); 835eda14cbcSMatt Macy encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf); 836eda14cbcSMatt Macy 837eda14cbcSMatt Macy } while (remainder > 0); 838eda14cbcSMatt Macy 839eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 840eda14cbcSMatt Macy } 841eda14cbcSMatt Macy 842eda14cbcSMatt Macy /* 843eda14cbcSMatt Macy * The following function should be call at encrypt or decrypt init time 844eda14cbcSMatt Macy * for AES CCM mode. 845eda14cbcSMatt Macy */ 846eda14cbcSMatt Macy int 847eda14cbcSMatt Macy ccm_init_ctx(ccm_ctx_t *ccm_ctx, char *param, int kmflag, 848eda14cbcSMatt Macy boolean_t is_encrypt_init, size_t block_size, 849eda14cbcSMatt Macy int (*encrypt_block)(const void *, const uint8_t *, uint8_t *), 850eda14cbcSMatt Macy void (*xor_block)(uint8_t *, uint8_t *)) 851eda14cbcSMatt Macy { 852eda14cbcSMatt Macy int rv; 853eda14cbcSMatt Macy CK_AES_CCM_PARAMS *ccm_param; 854eda14cbcSMatt Macy 855eda14cbcSMatt Macy if (param != NULL) { 856eda14cbcSMatt Macy ccm_param = (CK_AES_CCM_PARAMS *)param; 857eda14cbcSMatt Macy 858eda14cbcSMatt Macy if ((rv = ccm_validate_args(ccm_param, 859eda14cbcSMatt Macy is_encrypt_init)) != 0) { 860eda14cbcSMatt Macy return (rv); 861eda14cbcSMatt Macy } 862eda14cbcSMatt Macy 863eda14cbcSMatt Macy ccm_ctx->ccm_mac_len = ccm_param->ulMACSize; 864eda14cbcSMatt Macy if (is_encrypt_init) { 865eda14cbcSMatt Macy ccm_ctx->ccm_data_len = ccm_param->ulDataSize; 866eda14cbcSMatt Macy } else { 867eda14cbcSMatt Macy ccm_ctx->ccm_data_len = 868eda14cbcSMatt Macy ccm_param->ulDataSize - ccm_ctx->ccm_mac_len; 869eda14cbcSMatt Macy ccm_ctx->ccm_processed_mac_len = 0; 870eda14cbcSMatt Macy } 871eda14cbcSMatt Macy ccm_ctx->ccm_processed_data_len = 0; 872eda14cbcSMatt Macy 873eda14cbcSMatt Macy ccm_ctx->ccm_flags |= CCM_MODE; 874eda14cbcSMatt Macy } else { 875eda14cbcSMatt Macy return (CRYPTO_MECHANISM_PARAM_INVALID); 876eda14cbcSMatt Macy } 877eda14cbcSMatt Macy 878eda14cbcSMatt Macy if (ccm_init(ccm_ctx, ccm_param->nonce, ccm_param->ulNonceSize, 879eda14cbcSMatt Macy ccm_param->authData, ccm_param->ulAuthDataSize, block_size, 880eda14cbcSMatt Macy encrypt_block, xor_block) != 0) { 881eda14cbcSMatt Macy return (CRYPTO_MECHANISM_PARAM_INVALID); 882eda14cbcSMatt Macy } 883eda14cbcSMatt Macy if (!is_encrypt_init) { 884eda14cbcSMatt Macy /* allocate buffer for storing decrypted plaintext */ 885eda14cbcSMatt Macy ccm_ctx->ccm_pt_buf = vmem_alloc(ccm_ctx->ccm_data_len, 886eda14cbcSMatt Macy kmflag); 887eda14cbcSMatt Macy if (ccm_ctx->ccm_pt_buf == NULL) { 888eda14cbcSMatt Macy rv = CRYPTO_HOST_MEMORY; 889eda14cbcSMatt Macy } 890eda14cbcSMatt Macy } 891eda14cbcSMatt Macy return (rv); 892eda14cbcSMatt Macy } 893eda14cbcSMatt Macy 894eda14cbcSMatt Macy void * 895eda14cbcSMatt Macy ccm_alloc_ctx(int kmflag) 896eda14cbcSMatt Macy { 897eda14cbcSMatt Macy ccm_ctx_t *ccm_ctx; 898eda14cbcSMatt Macy 899eda14cbcSMatt Macy if ((ccm_ctx = kmem_zalloc(sizeof (ccm_ctx_t), kmflag)) == NULL) 900eda14cbcSMatt Macy return (NULL); 901eda14cbcSMatt Macy 902eda14cbcSMatt Macy ccm_ctx->ccm_flags = CCM_MODE; 903eda14cbcSMatt Macy return (ccm_ctx); 904eda14cbcSMatt Macy } 905