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