nx-aes-xcbc.c (9507B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * AES XCBC routines supporting the Power 7+ Nest Accelerators driver 4 * 5 * Copyright (C) 2011-2012 International Business Machines Inc. 6 * 7 * Author: Kent Yoder <yoder1@us.ibm.com> 8 */ 9 10#include <crypto/internal/hash.h> 11#include <crypto/aes.h> 12#include <crypto/algapi.h> 13#include <linux/module.h> 14#include <linux/types.h> 15#include <linux/crypto.h> 16#include <asm/vio.h> 17 18#include "nx_csbcpb.h" 19#include "nx.h" 20 21 22struct xcbc_state { 23 u8 state[AES_BLOCK_SIZE]; 24 unsigned int count; 25 u8 buffer[AES_BLOCK_SIZE]; 26}; 27 28static int nx_xcbc_set_key(struct crypto_shash *desc, 29 const u8 *in_key, 30 unsigned int key_len) 31{ 32 struct nx_crypto_ctx *nx_ctx = crypto_shash_ctx(desc); 33 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; 34 35 switch (key_len) { 36 case AES_KEYSIZE_128: 37 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128]; 38 break; 39 default: 40 return -EINVAL; 41 } 42 43 memcpy(csbcpb->cpb.aes_xcbc.key, in_key, key_len); 44 45 return 0; 46} 47 48/* 49 * Based on RFC 3566, for a zero-length message: 50 * 51 * n = 1 52 * K1 = E(K, 0x01010101010101010101010101010101) 53 * K3 = E(K, 0x03030303030303030303030303030303) 54 * E[0] = 0x00000000000000000000000000000000 55 * M[1] = 0x80000000000000000000000000000000 (0 length message with padding) 56 * E[1] = (K1, M[1] ^ E[0] ^ K3) 57 * Tag = M[1] 58 */ 59static int nx_xcbc_empty(struct shash_desc *desc, u8 *out) 60{ 61 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); 62 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; 63 struct nx_sg *in_sg, *out_sg; 64 u8 keys[2][AES_BLOCK_SIZE]; 65 u8 key[32]; 66 int rc = 0; 67 int len; 68 69 /* Change to ECB mode */ 70 csbcpb->cpb.hdr.mode = NX_MODE_AES_ECB; 71 memcpy(key, csbcpb->cpb.aes_xcbc.key, AES_BLOCK_SIZE); 72 memcpy(csbcpb->cpb.aes_ecb.key, key, AES_BLOCK_SIZE); 73 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT; 74 75 /* K1 and K3 base patterns */ 76 memset(keys[0], 0x01, sizeof(keys[0])); 77 memset(keys[1], 0x03, sizeof(keys[1])); 78 79 len = sizeof(keys); 80 /* Generate K1 and K3 encrypting the patterns */ 81 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *) keys, &len, 82 nx_ctx->ap->sglen); 83 84 if (len != sizeof(keys)) 85 return -EINVAL; 86 87 out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *) keys, &len, 88 nx_ctx->ap->sglen); 89 90 if (len != sizeof(keys)) 91 return -EINVAL; 92 93 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg); 94 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); 95 96 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 0); 97 if (rc) 98 goto out; 99 atomic_inc(&(nx_ctx->stats->aes_ops)); 100 101 /* XOr K3 with the padding for a 0 length message */ 102 keys[1][0] ^= 0x80; 103 104 len = sizeof(keys[1]); 105 106 /* Encrypt the final result */ 107 memcpy(csbcpb->cpb.aes_ecb.key, keys[0], AES_BLOCK_SIZE); 108 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *) keys[1], &len, 109 nx_ctx->ap->sglen); 110 111 if (len != sizeof(keys[1])) 112 return -EINVAL; 113 114 len = AES_BLOCK_SIZE; 115 out_sg = nx_build_sg_list(nx_ctx->out_sg, out, &len, 116 nx_ctx->ap->sglen); 117 118 if (len != AES_BLOCK_SIZE) 119 return -EINVAL; 120 121 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg); 122 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); 123 124 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 0); 125 if (rc) 126 goto out; 127 atomic_inc(&(nx_ctx->stats->aes_ops)); 128 129out: 130 /* Restore XCBC mode */ 131 csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC; 132 memcpy(csbcpb->cpb.aes_xcbc.key, key, AES_BLOCK_SIZE); 133 NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT; 134 135 return rc; 136} 137 138static int nx_crypto_ctx_aes_xcbc_init2(struct crypto_tfm *tfm) 139{ 140 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm); 141 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; 142 int err; 143 144 err = nx_crypto_ctx_aes_xcbc_init(tfm); 145 if (err) 146 return err; 147 148 nx_ctx_init(nx_ctx, HCOP_FC_AES); 149 150 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128); 151 csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC; 152 153 return 0; 154} 155 156static int nx_xcbc_init(struct shash_desc *desc) 157{ 158 struct xcbc_state *sctx = shash_desc_ctx(desc); 159 160 memset(sctx, 0, sizeof *sctx); 161 162 return 0; 163} 164 165static int nx_xcbc_update(struct shash_desc *desc, 166 const u8 *data, 167 unsigned int len) 168{ 169 struct xcbc_state *sctx = shash_desc_ctx(desc); 170 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); 171 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; 172 struct nx_sg *in_sg; 173 struct nx_sg *out_sg; 174 u32 to_process = 0, leftover, total; 175 unsigned int max_sg_len; 176 unsigned long irq_flags; 177 int rc = 0; 178 int data_len; 179 180 spin_lock_irqsave(&nx_ctx->lock, irq_flags); 181 182 183 total = sctx->count + len; 184 185 /* 2 cases for total data len: 186 * 1: <= AES_BLOCK_SIZE: copy into state, return 0 187 * 2: > AES_BLOCK_SIZE: process X blocks, copy in leftover 188 */ 189 if (total <= AES_BLOCK_SIZE) { 190 memcpy(sctx->buffer + sctx->count, data, len); 191 sctx->count += len; 192 goto out; 193 } 194 195 in_sg = nx_ctx->in_sg; 196 max_sg_len = min_t(u64, nx_driver.of.max_sg_len/sizeof(struct nx_sg), 197 nx_ctx->ap->sglen); 198 max_sg_len = min_t(u64, max_sg_len, 199 nx_ctx->ap->databytelen/NX_PAGE_SIZE); 200 201 data_len = AES_BLOCK_SIZE; 202 out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state, 203 &len, nx_ctx->ap->sglen); 204 205 if (data_len != AES_BLOCK_SIZE) { 206 rc = -EINVAL; 207 goto out; 208 } 209 210 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); 211 212 do { 213 to_process = total - to_process; 214 to_process = to_process & ~(AES_BLOCK_SIZE - 1); 215 216 leftover = total - to_process; 217 218 /* the hardware will not accept a 0 byte operation for this 219 * algorithm and the operation MUST be finalized to be correct. 220 * So if we happen to get an update that falls on a block sized 221 * boundary, we must save off the last block to finalize with 222 * later. */ 223 if (!leftover) { 224 to_process -= AES_BLOCK_SIZE; 225 leftover = AES_BLOCK_SIZE; 226 } 227 228 if (sctx->count) { 229 data_len = sctx->count; 230 in_sg = nx_build_sg_list(nx_ctx->in_sg, 231 (u8 *) sctx->buffer, 232 &data_len, 233 max_sg_len); 234 if (data_len != sctx->count) { 235 rc = -EINVAL; 236 goto out; 237 } 238 } 239 240 data_len = to_process - sctx->count; 241 in_sg = nx_build_sg_list(in_sg, 242 (u8 *) data, 243 &data_len, 244 max_sg_len); 245 246 if (data_len != to_process - sctx->count) { 247 rc = -EINVAL; 248 goto out; 249 } 250 251 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * 252 sizeof(struct nx_sg); 253 254 /* we've hit the nx chip previously and we're updating again, 255 * so copy over the partial digest */ 256 if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) { 257 memcpy(csbcpb->cpb.aes_xcbc.cv, 258 csbcpb->cpb.aes_xcbc.out_cv_mac, 259 AES_BLOCK_SIZE); 260 } 261 262 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE; 263 if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) { 264 rc = -EINVAL; 265 goto out; 266 } 267 268 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 0); 269 if (rc) 270 goto out; 271 272 atomic_inc(&(nx_ctx->stats->aes_ops)); 273 274 /* everything after the first update is continuation */ 275 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION; 276 277 total -= to_process; 278 data += to_process - sctx->count; 279 sctx->count = 0; 280 in_sg = nx_ctx->in_sg; 281 } while (leftover > AES_BLOCK_SIZE); 282 283 /* copy the leftover back into the state struct */ 284 memcpy(sctx->buffer, data, leftover); 285 sctx->count = leftover; 286 287out: 288 spin_unlock_irqrestore(&nx_ctx->lock, irq_flags); 289 return rc; 290} 291 292static int nx_xcbc_final(struct shash_desc *desc, u8 *out) 293{ 294 struct xcbc_state *sctx = shash_desc_ctx(desc); 295 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); 296 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; 297 struct nx_sg *in_sg, *out_sg; 298 unsigned long irq_flags; 299 int rc = 0; 300 int len; 301 302 spin_lock_irqsave(&nx_ctx->lock, irq_flags); 303 304 if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) { 305 /* we've hit the nx chip previously, now we're finalizing, 306 * so copy over the partial digest */ 307 memcpy(csbcpb->cpb.aes_xcbc.cv, 308 csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE); 309 } else if (sctx->count == 0) { 310 /* 311 * we've never seen an update, so this is a 0 byte op. The 312 * hardware cannot handle a 0 byte op, so just ECB to 313 * generate the hash. 314 */ 315 rc = nx_xcbc_empty(desc, out); 316 goto out; 317 } 318 319 /* final is represented by continuing the operation and indicating that 320 * this is not an intermediate operation */ 321 NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE; 322 323 len = sctx->count; 324 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buffer, 325 &len, nx_ctx->ap->sglen); 326 327 if (len != sctx->count) { 328 rc = -EINVAL; 329 goto out; 330 } 331 332 len = AES_BLOCK_SIZE; 333 out_sg = nx_build_sg_list(nx_ctx->out_sg, out, &len, 334 nx_ctx->ap->sglen); 335 336 if (len != AES_BLOCK_SIZE) { 337 rc = -EINVAL; 338 goto out; 339 } 340 341 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg); 342 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg); 343 344 if (!nx_ctx->op.outlen) { 345 rc = -EINVAL; 346 goto out; 347 } 348 349 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 0); 350 if (rc) 351 goto out; 352 353 atomic_inc(&(nx_ctx->stats->aes_ops)); 354 355 memcpy(out, csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE); 356out: 357 spin_unlock_irqrestore(&nx_ctx->lock, irq_flags); 358 return rc; 359} 360 361struct shash_alg nx_shash_aes_xcbc_alg = { 362 .digestsize = AES_BLOCK_SIZE, 363 .init = nx_xcbc_init, 364 .update = nx_xcbc_update, 365 .final = nx_xcbc_final, 366 .setkey = nx_xcbc_set_key, 367 .descsize = sizeof(struct xcbc_state), 368 .statesize = sizeof(struct xcbc_state), 369 .base = { 370 .cra_name = "xcbc(aes)", 371 .cra_driver_name = "xcbc-aes-nx", 372 .cra_priority = 300, 373 .cra_blocksize = AES_BLOCK_SIZE, 374 .cra_module = THIS_MODULE, 375 .cra_ctxsize = sizeof(struct nx_crypto_ctx), 376 .cra_init = nx_crypto_ctx_aes_xcbc_init2, 377 .cra_exit = nx_crypto_ctx_exit, 378 } 379};