• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /**
2   * AES CBC routines supporting the Power 7+ Nest Accelerators driver
3   *
4   * Copyright (C) 2011-2012 International Business Machines Inc.
5   *
6   * This program is free software; you can redistribute it and/or modify
7   * it under the terms of the GNU General Public License as published by
8   * the Free Software Foundation; version 2 only.
9   *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18   *
19   * Author: Kent Yoder <yoder1@us.ibm.com>
20   */
21  
22  #include <crypto/aes.h>
23  #include <crypto/algapi.h>
24  #include <linux/module.h>
25  #include <linux/types.h>
26  #include <linux/crypto.h>
27  #include <asm/vio.h>
28  
29  #include "nx_csbcpb.h"
30  #include "nx.h"
31  
32  
cbc_aes_nx_set_key(struct crypto_tfm * tfm,const u8 * in_key,unsigned int key_len)33  static int cbc_aes_nx_set_key(struct crypto_tfm *tfm,
34  			      const u8          *in_key,
35  			      unsigned int       key_len)
36  {
37  	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
38  	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
39  
40  	nx_ctx_init(nx_ctx, HCOP_FC_AES);
41  
42  	switch (key_len) {
43  	case AES_KEYSIZE_128:
44  		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
45  		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
46  		break;
47  	case AES_KEYSIZE_192:
48  		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
49  		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
50  		break;
51  	case AES_KEYSIZE_256:
52  		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
53  		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
54  		break;
55  	default:
56  		return -EINVAL;
57  	}
58  
59  	csbcpb->cpb.hdr.mode = NX_MODE_AES_CBC;
60  	memcpy(csbcpb->cpb.aes_cbc.key, in_key, key_len);
61  
62  	return 0;
63  }
64  
cbc_aes_nx_crypt(struct blkcipher_desc * desc,struct scatterlist * dst,struct scatterlist * src,unsigned int nbytes,int enc)65  static int cbc_aes_nx_crypt(struct blkcipher_desc *desc,
66  			    struct scatterlist    *dst,
67  			    struct scatterlist    *src,
68  			    unsigned int           nbytes,
69  			    int                    enc)
70  {
71  	struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
72  	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
73  	unsigned long irq_flags;
74  	unsigned int processed = 0, to_process;
75  	int rc;
76  
77  	spin_lock_irqsave(&nx_ctx->lock, irq_flags);
78  
79  	if (enc)
80  		NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
81  	else
82  		NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
83  
84  	do {
85  		to_process = nbytes - processed;
86  
87  		rc = nx_build_sg_lists(nx_ctx, desc, dst, src, &to_process,
88  				       processed, csbcpb->cpb.aes_cbc.iv);
89  		if (rc)
90  			goto out;
91  
92  		if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
93  			rc = -EINVAL;
94  			goto out;
95  		}
96  
97  		rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
98  				   desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
99  		if (rc)
100  			goto out;
101  
102  		memcpy(desc->info, csbcpb->cpb.aes_cbc.cv, AES_BLOCK_SIZE);
103  		atomic_inc(&(nx_ctx->stats->aes_ops));
104  		atomic64_add(csbcpb->csb.processed_byte_count,
105  			     &(nx_ctx->stats->aes_bytes));
106  
107  		processed += to_process;
108  	} while (processed < nbytes);
109  out:
110  	spin_unlock_irqrestore(&nx_ctx->lock, irq_flags);
111  	return rc;
112  }
113  
cbc_aes_nx_encrypt(struct blkcipher_desc * desc,struct scatterlist * dst,struct scatterlist * src,unsigned int nbytes)114  static int cbc_aes_nx_encrypt(struct blkcipher_desc *desc,
115  			      struct scatterlist    *dst,
116  			      struct scatterlist    *src,
117  			      unsigned int           nbytes)
118  {
119  	return cbc_aes_nx_crypt(desc, dst, src, nbytes, 1);
120  }
121  
cbc_aes_nx_decrypt(struct blkcipher_desc * desc,struct scatterlist * dst,struct scatterlist * src,unsigned int nbytes)122  static int cbc_aes_nx_decrypt(struct blkcipher_desc *desc,
123  			      struct scatterlist    *dst,
124  			      struct scatterlist    *src,
125  			      unsigned int           nbytes)
126  {
127  	return cbc_aes_nx_crypt(desc, dst, src, nbytes, 0);
128  }
129  
130  struct crypto_alg nx_cbc_aes_alg = {
131  	.cra_name        = "cbc(aes)",
132  	.cra_driver_name = "cbc-aes-nx",
133  	.cra_priority    = 300,
134  	.cra_flags       = CRYPTO_ALG_TYPE_BLKCIPHER,
135  	.cra_blocksize   = AES_BLOCK_SIZE,
136  	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
137  	.cra_type        = &crypto_blkcipher_type,
138  	.cra_alignmask   = 0xf,
139  	.cra_module      = THIS_MODULE,
140  	.cra_init        = nx_crypto_ctx_aes_cbc_init,
141  	.cra_exit        = nx_crypto_ctx_exit,
142  	.cra_blkcipher = {
143  		.min_keysize = AES_MIN_KEY_SIZE,
144  		.max_keysize = AES_MAX_KEY_SIZE,
145  		.ivsize      = AES_BLOCK_SIZE,
146  		.setkey      = cbc_aes_nx_set_key,
147  		.encrypt     = cbc_aes_nx_encrypt,
148  		.decrypt     = cbc_aes_nx_decrypt,
149  	}
150  };
151