1 /* 2 * Copyright (c) 2018-2019 iXsystems Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include <sys/cdefs.h> 26 __FBSDID("$FreeBSD$"); 27 28 #include <sys/types.h> 29 #include <sys/systm.h> 30 #include <sys/param.h> 31 #include <sys/endian.h> 32 #include <opencrypto/cbc_mac.h> 33 #include <opencrypto/xform_auth.h> 34 35 /* 36 * Given two CCM_CBC_BLOCK_LEN blocks, xor 37 * them into dst, and then encrypt dst. 38 */ 39 static void 40 xor_and_encrypt(struct aes_cbc_mac_ctx *ctx, 41 const uint8_t *src, uint8_t *dst) 42 { 43 const uint64_t *b1; 44 uint64_t *b2; 45 uint64_t temp_block[CCM_CBC_BLOCK_LEN/sizeof(uint64_t)]; 46 47 b1 = (const uint64_t*)src; 48 b2 = (uint64_t*)dst; 49 50 for (size_t count = 0; 51 count < CCM_CBC_BLOCK_LEN/sizeof(uint64_t); 52 count++) { 53 temp_block[count] = b1[count] ^ b2[count]; 54 } 55 rijndaelEncrypt(ctx->keysched, ctx->rounds, (void*)temp_block, dst); 56 } 57 58 void 59 AES_CBC_MAC_Init(struct aes_cbc_mac_ctx *ctx) 60 { 61 bzero(ctx, sizeof(*ctx)); 62 } 63 64 void 65 AES_CBC_MAC_Setkey(struct aes_cbc_mac_ctx *ctx, const uint8_t *key, uint16_t klen) 66 { 67 ctx->rounds = rijndaelKeySetupEnc(ctx->keysched, key, klen * 8); 68 } 69 70 /* 71 * This is called to set the nonce, aka IV. 72 * Before this call, the authDataLength and cryptDataLength fields 73 * MUST have been set. Sadly, there's no way to return an error. 74 * 75 * The CBC-MAC algorithm requires that the first block contain the 76 * nonce, as well as information about the sizes and lengths involved. 77 */ 78 void 79 AES_CBC_MAC_Reinit(struct aes_cbc_mac_ctx *ctx, const uint8_t *nonce, uint16_t nonceLen) 80 { 81 uint8_t b0[CCM_CBC_BLOCK_LEN]; 82 uint8_t *bp = b0, flags = 0; 83 uint8_t L = 0; 84 uint64_t dataLength = ctx->cryptDataLength; 85 86 KASSERT(ctx->authDataLength != 0 || ctx->cryptDataLength != 0, 87 ("Auth Data and Data lengths cannot both be 0")); 88 89 KASSERT(nonceLen >= 7 && nonceLen <= 13, 90 ("nonceLen must be between 7 and 13 bytes")); 91 92 ctx->nonce = nonce; 93 ctx->nonceLength = nonceLen; 94 95 ctx->authDataCount = 0; 96 ctx->blockIndex = 0; 97 explicit_bzero(ctx->staging_block, sizeof(ctx->staging_block)); 98 99 /* 100 * Need to determine the L field value. This is the number of 101 * bytes needed to specify the length of the message; the length 102 * is whatever is left in the 16 bytes after specifying flags and 103 * the nonce. 104 */ 105 L = 15 - nonceLen; 106 107 flags = ((ctx->authDataLength > 0) << 6) + 108 (((AES_CBC_MAC_HASH_LEN - 2) / 2) << 3) + 109 L - 1; 110 /* 111 * Now we need to set up the first block, which has flags, nonce, 112 * and the message length. 113 */ 114 b0[0] = flags; 115 bcopy(nonce, b0 + 1, nonceLen); 116 bp = b0 + 1 + nonceLen; 117 118 /* Need to copy L' [aka L-1] bytes of cryptDataLength */ 119 for (uint8_t *dst = b0 + sizeof(b0) - 1; dst >= bp; dst--) { 120 *dst = dataLength; 121 dataLength >>= 8; 122 } 123 /* Now need to encrypt b0 */ 124 rijndaelEncrypt(ctx->keysched, ctx->rounds, b0, ctx->block); 125 /* If there is auth data, we need to set up the staging block */ 126 if (ctx->authDataLength) { 127 size_t addLength; 128 if (ctx->authDataLength < ((1<<16) - (1<<8))) { 129 uint16_t sizeVal = htobe16(ctx->authDataLength); 130 bcopy(&sizeVal, ctx->staging_block, sizeof(sizeVal)); 131 addLength = sizeof(sizeVal); 132 } else if (ctx->authDataLength < (1ULL<<32)) { 133 uint32_t sizeVal = htobe32(ctx->authDataLength); 134 ctx->staging_block[0] = 0xff; 135 ctx->staging_block[1] = 0xfe; 136 bcopy(&sizeVal, ctx->staging_block+2, sizeof(sizeVal)); 137 addLength = 2 + sizeof(sizeVal); 138 } else { 139 uint64_t sizeVal = htobe64(ctx->authDataLength); 140 ctx->staging_block[0] = 0xff; 141 ctx->staging_block[1] = 0xff; 142 bcopy(&sizeVal, ctx->staging_block+2, sizeof(sizeVal)); 143 addLength = 2 + sizeof(sizeVal); 144 } 145 ctx->blockIndex = addLength; 146 /* 147 * The length descriptor goes into the AAD buffer, so we 148 * need to account for it. 149 */ 150 ctx->authDataLength += addLength; 151 ctx->authDataCount = addLength; 152 } 153 } 154 155 int 156 AES_CBC_MAC_Update(struct aes_cbc_mac_ctx *ctx, const uint8_t *data, 157 uint16_t length) 158 { 159 size_t copy_amt; 160 161 /* 162 * This will be called in one of two phases: 163 * (1) Applying authentication data, or 164 * (2) Applying the payload data. 165 * 166 * Because CBC-MAC puts the authentication data size before the 167 * data, subsequent calls won't be block-size-aligned. Which 168 * complicates things a fair bit. 169 * 170 * The payload data doesn't have that problem. 171 */ 172 173 if (ctx->authDataCount < ctx->authDataLength) { 174 /* 175 * We need to process data as authentication data. 176 * Since we may be out of sync, we may also need 177 * to pad out the staging block. 178 */ 179 const uint8_t *ptr = data; 180 while (length > 0) { 181 182 copy_amt = MIN(length, 183 sizeof(ctx->staging_block) - ctx->blockIndex); 184 185 bcopy(ptr, ctx->staging_block + ctx->blockIndex, 186 copy_amt); 187 ptr += copy_amt; 188 length -= copy_amt; 189 ctx->authDataCount += copy_amt; 190 ctx->blockIndex += copy_amt; 191 ctx->blockIndex %= sizeof(ctx->staging_block); 192 193 if (ctx->blockIndex == 0 || 194 ctx->authDataCount == ctx->authDataLength) { 195 /* 196 * We're done with this block, so we 197 * xor staging_block with block, and then 198 * encrypt it. 199 */ 200 xor_and_encrypt(ctx, ctx->staging_block, ctx->block); 201 bzero(ctx->staging_block, sizeof(ctx->staging_block)); 202 ctx->blockIndex = 0; 203 if (ctx->authDataCount >= ctx->authDataLength) 204 break; 205 } 206 } 207 /* 208 * We'd like to be able to check length == 0 and return 209 * here, but the way OCF calls us, length is always 210 * blksize (16, in this case). So we have to count on 211 * the fact that OCF calls us separately for the AAD and 212 * for the real data. 213 */ 214 return (0); 215 } 216 /* 217 * If we're here, then we're encoding payload data. 218 * This is marginally easier, except that _Update can 219 * be called with non-aligned update lengths. As a result, 220 * we still need to use the staging block. 221 */ 222 KASSERT((length + ctx->cryptDataCount) <= ctx->cryptDataLength, 223 ("More encryption data than allowed")); 224 225 while (length) { 226 uint8_t *ptr; 227 228 copy_amt = MIN(sizeof(ctx->staging_block) - ctx->blockIndex, 229 length); 230 ptr = ctx->staging_block + ctx->blockIndex; 231 bcopy(data, ptr, copy_amt); 232 data += copy_amt; 233 ctx->blockIndex += copy_amt; 234 ctx->cryptDataCount += copy_amt; 235 length -= copy_amt; 236 if (ctx->blockIndex == sizeof(ctx->staging_block)) { 237 /* We've got a full block */ 238 xor_and_encrypt(ctx, ctx->staging_block, ctx->block); 239 ctx->blockIndex = 0; 240 bzero(ctx->staging_block, sizeof(ctx->staging_block)); 241 } 242 } 243 return (0); 244 } 245 246 void 247 AES_CBC_MAC_Final(uint8_t *buf, struct aes_cbc_mac_ctx *ctx) 248 { 249 uint8_t s0[CCM_CBC_BLOCK_LEN]; 250 251 /* 252 * We first need to check to see if we've got any data 253 * left over to encrypt. 254 */ 255 if (ctx->blockIndex != 0) { 256 xor_and_encrypt(ctx, ctx->staging_block, ctx->block); 257 ctx->cryptDataCount += ctx->blockIndex; 258 ctx->blockIndex = 0; 259 explicit_bzero(ctx->staging_block, sizeof(ctx->staging_block)); 260 } 261 bzero(s0, sizeof(s0)); 262 s0[0] = (15 - ctx->nonceLength) - 1; 263 bcopy(ctx->nonce, s0 + 1, ctx->nonceLength); 264 rijndaelEncrypt(ctx->keysched, ctx->rounds, s0, s0); 265 for (size_t indx = 0; indx < AES_CBC_MAC_HASH_LEN; indx++) 266 buf[indx] = ctx->block[indx] ^ s0[indx]; 267 explicit_bzero(s0, sizeof(s0)); 268 } 269