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