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