162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * AES ECB routines supporting the Power 7+ Nest Accelerators driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2011-2012 International Business Machines Inc.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Kent Yoder <yoder1@us.ibm.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <crypto/aes.h>
1162306a36Sopenharmony_ci#include <crypto/algapi.h>
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci#include <linux/crypto.h>
1562306a36Sopenharmony_ci#include <asm/vio.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "nx_csbcpb.h"
1862306a36Sopenharmony_ci#include "nx.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic int ecb_aes_nx_set_key(struct crypto_skcipher *tfm,
2262306a36Sopenharmony_ci			      const u8               *in_key,
2362306a36Sopenharmony_ci			      unsigned int            key_len)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	struct nx_crypto_ctx *nx_ctx = crypto_skcipher_ctx(tfm);
2662306a36Sopenharmony_ci	struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	nx_ctx_init(nx_ctx, HCOP_FC_AES);
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	switch (key_len) {
3162306a36Sopenharmony_ci	case AES_KEYSIZE_128:
3262306a36Sopenharmony_ci		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
3362306a36Sopenharmony_ci		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
3462306a36Sopenharmony_ci		break;
3562306a36Sopenharmony_ci	case AES_KEYSIZE_192:
3662306a36Sopenharmony_ci		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
3762306a36Sopenharmony_ci		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
3862306a36Sopenharmony_ci		break;
3962306a36Sopenharmony_ci	case AES_KEYSIZE_256:
4062306a36Sopenharmony_ci		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
4162306a36Sopenharmony_ci		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
4262306a36Sopenharmony_ci		break;
4362306a36Sopenharmony_ci	default:
4462306a36Sopenharmony_ci		return -EINVAL;
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	csbcpb->cpb.hdr.mode = NX_MODE_AES_ECB;
4862306a36Sopenharmony_ci	memcpy(csbcpb->cpb.aes_ecb.key, in_key, key_len);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	return 0;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic int ecb_aes_nx_crypt(struct skcipher_request *req,
5462306a36Sopenharmony_ci			    int                      enc)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
5762306a36Sopenharmony_ci	struct nx_crypto_ctx *nx_ctx = crypto_skcipher_ctx(tfm);
5862306a36Sopenharmony_ci	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
5962306a36Sopenharmony_ci	unsigned long irq_flags;
6062306a36Sopenharmony_ci	unsigned int processed = 0, to_process;
6162306a36Sopenharmony_ci	int rc;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	spin_lock_irqsave(&nx_ctx->lock, irq_flags);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (enc)
6662306a36Sopenharmony_ci		NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
6762306a36Sopenharmony_ci	else
6862306a36Sopenharmony_ci		NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	do {
7162306a36Sopenharmony_ci		to_process = req->cryptlen - processed;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci		rc = nx_build_sg_lists(nx_ctx, NULL, req->dst, req->src,
7462306a36Sopenharmony_ci				       &to_process, processed, NULL);
7562306a36Sopenharmony_ci		if (rc)
7662306a36Sopenharmony_ci			goto out;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci		if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
7962306a36Sopenharmony_ci			rc = -EINVAL;
8062306a36Sopenharmony_ci			goto out;
8162306a36Sopenharmony_ci		}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci		rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
8462306a36Sopenharmony_ci				   req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
8562306a36Sopenharmony_ci		if (rc)
8662306a36Sopenharmony_ci			goto out;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci		atomic_inc(&(nx_ctx->stats->aes_ops));
8962306a36Sopenharmony_ci		atomic64_add(be32_to_cpu(csbcpb->csb.processed_byte_count),
9062306a36Sopenharmony_ci			     &(nx_ctx->stats->aes_bytes));
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci		processed += to_process;
9362306a36Sopenharmony_ci	} while (processed < req->cryptlen);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ciout:
9662306a36Sopenharmony_ci	spin_unlock_irqrestore(&nx_ctx->lock, irq_flags);
9762306a36Sopenharmony_ci	return rc;
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic int ecb_aes_nx_encrypt(struct skcipher_request *req)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	return ecb_aes_nx_crypt(req, 1);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic int ecb_aes_nx_decrypt(struct skcipher_request *req)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	return ecb_aes_nx_crypt(req, 0);
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistruct skcipher_alg nx_ecb_aes_alg = {
11162306a36Sopenharmony_ci	.base.cra_name		= "ecb(aes)",
11262306a36Sopenharmony_ci	.base.cra_driver_name	= "ecb-aes-nx",
11362306a36Sopenharmony_ci	.base.cra_priority	= 300,
11462306a36Sopenharmony_ci	.base.cra_blocksize	= AES_BLOCK_SIZE,
11562306a36Sopenharmony_ci	.base.cra_alignmask	= 0xf,
11662306a36Sopenharmony_ci	.base.cra_ctxsize	= sizeof(struct nx_crypto_ctx),
11762306a36Sopenharmony_ci	.base.cra_module	= THIS_MODULE,
11862306a36Sopenharmony_ci	.init			= nx_crypto_ctx_aes_ecb_init,
11962306a36Sopenharmony_ci	.exit			= nx_crypto_ctx_skcipher_exit,
12062306a36Sopenharmony_ci	.min_keysize		= AES_MIN_KEY_SIZE,
12162306a36Sopenharmony_ci	.max_keysize		= AES_MAX_KEY_SIZE,
12262306a36Sopenharmony_ci	.setkey			= ecb_aes_nx_set_key,
12362306a36Sopenharmony_ci	.encrypt		= ecb_aes_nx_encrypt,
12462306a36Sopenharmony_ci	.decrypt		= ecb_aes_nx_decrypt,
12562306a36Sopenharmony_ci};
126