1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * AES ECB 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/aes.h> |
11 | #include <crypto/algapi.h> |
12 | #include <linux/module.h> |
13 | #include <linux/types.h> |
14 | #include <linux/crypto.h> |
15 | #include <asm/vio.h> |
16 | |
17 | #include "nx_csbcpb.h" |
18 | #include "nx.h" |
19 | |
20 | |
21 | static int ecb_aes_nx_set_key(struct crypto_skcipher *tfm, |
22 | const u8 *in_key, |
23 | unsigned int key_len) |
24 | { |
25 | struct nx_crypto_ctx *nx_ctx = crypto_skcipher_ctx(tfm); |
26 | struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb; |
27 | |
28 | nx_ctx_init(nx_ctx, HCOP_FC_AES); |
29 | |
30 | switch (key_len) { |
31 | case AES_KEYSIZE_128: |
32 | NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128); |
33 | nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128]; |
34 | break; |
35 | case AES_KEYSIZE_192: |
36 | NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192); |
37 | nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192]; |
38 | break; |
39 | case AES_KEYSIZE_256: |
40 | NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256); |
41 | nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256]; |
42 | break; |
43 | default: |
44 | return -EINVAL; |
45 | } |
46 | |
47 | csbcpb->cpb.hdr.mode = NX_MODE_AES_ECB; |
48 | memcpy(csbcpb->cpb.aes_ecb.key, in_key, key_len); |
49 | |
50 | return 0; |
51 | } |
52 | |
53 | static int ecb_aes_nx_crypt(struct skcipher_request *req, |
54 | int enc) |
55 | { |
56 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); |
57 | struct nx_crypto_ctx *nx_ctx = crypto_skcipher_ctx(tfm); |
58 | struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; |
59 | unsigned long irq_flags; |
60 | unsigned int processed = 0, to_process; |
61 | int rc; |
62 | |
63 | spin_lock_irqsave(&nx_ctx->lock, irq_flags); |
64 | |
65 | if (enc) |
66 | NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT; |
67 | else |
68 | NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT; |
69 | |
70 | do { |
71 | to_process = req->cryptlen - processed; |
72 | |
73 | rc = nx_build_sg_lists(nx_ctx, NULL, dst: req->dst, src: req->src, |
74 | nbytes: &to_process, offset: processed, NULL); |
75 | if (rc) |
76 | goto out; |
77 | |
78 | if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) { |
79 | rc = -EINVAL; |
80 | goto out; |
81 | } |
82 | |
83 | rc = nx_hcall_sync(ctx: nx_ctx, op: &nx_ctx->op, |
84 | may_sleep: req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP); |
85 | if (rc) |
86 | goto out; |
87 | |
88 | atomic_inc(v: &(nx_ctx->stats->aes_ops)); |
89 | atomic64_add(be32_to_cpu(csbcpb->csb.processed_byte_count), |
90 | v: &(nx_ctx->stats->aes_bytes)); |
91 | |
92 | processed += to_process; |
93 | } while (processed < req->cryptlen); |
94 | |
95 | out: |
96 | spin_unlock_irqrestore(lock: &nx_ctx->lock, flags: irq_flags); |
97 | return rc; |
98 | } |
99 | |
100 | static int ecb_aes_nx_encrypt(struct skcipher_request *req) |
101 | { |
102 | return ecb_aes_nx_crypt(req, enc: 1); |
103 | } |
104 | |
105 | static int ecb_aes_nx_decrypt(struct skcipher_request *req) |
106 | { |
107 | return ecb_aes_nx_crypt(req, enc: 0); |
108 | } |
109 | |
110 | struct skcipher_alg nx_ecb_aes_alg = { |
111 | .base.cra_name = "ecb(aes)" , |
112 | .base.cra_driver_name = "ecb-aes-nx" , |
113 | .base.cra_priority = 300, |
114 | .base.cra_blocksize = AES_BLOCK_SIZE, |
115 | .base.cra_alignmask = 0xf, |
116 | .base.cra_ctxsize = sizeof(struct nx_crypto_ctx), |
117 | .base.cra_module = THIS_MODULE, |
118 | .init = nx_crypto_ctx_aes_ecb_init, |
119 | .exit = nx_crypto_ctx_skcipher_exit, |
120 | .min_keysize = AES_MIN_KEY_SIZE, |
121 | .max_keysize = AES_MAX_KEY_SIZE, |
122 | .setkey = ecb_aes_nx_set_key, |
123 | .encrypt = ecb_aes_nx_encrypt, |
124 | .decrypt = ecb_aes_nx_decrypt, |
125 | }; |
126 | |