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 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 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 u32 max_sg_len; 76 int rc; 77 78 spin_lock_irqsave(&nx_ctx->lock, irq_flags); 79 80 max_sg_len = min_t(u32, nx_driver.of.max_sg_len/sizeof(struct nx_sg), 81 nx_ctx->ap->sglen); 82 83 if (enc) 84 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT; 85 else 86 NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT; 87 88 do { 89 to_process = min_t(u64, nbytes - processed, 90 nx_ctx->ap->databytelen); 91 to_process = min_t(u64, to_process, 92 NX_PAGE_SIZE * (max_sg_len - 1)); 93 to_process = to_process & ~(AES_BLOCK_SIZE - 1); 94 95 rc = nx_build_sg_lists(nx_ctx, desc, dst, src, to_process, 96 processed, csbcpb->cpb.aes_cbc.iv); 97 if (rc) 98 goto out; 99 100 if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) { 101 rc = -EINVAL; 102 goto out; 103 } 104 105 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op, 106 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP); 107 if (rc) 108 goto out; 109 110 memcpy(desc->info, csbcpb->cpb.aes_cbc.cv, AES_BLOCK_SIZE); 111 atomic_inc(&(nx_ctx->stats->aes_ops)); 112 atomic64_add(csbcpb->csb.processed_byte_count, 113 &(nx_ctx->stats->aes_bytes)); 114 115 processed += to_process; 116 } while (processed < nbytes); 117 out: 118 spin_unlock_irqrestore(&nx_ctx->lock, irq_flags); 119 return rc; 120 } 121 122 static int cbc_aes_nx_encrypt(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, 1); 128 } 129 130 static int cbc_aes_nx_decrypt(struct blkcipher_desc *desc, 131 struct scatterlist *dst, 132 struct scatterlist *src, 133 unsigned int nbytes) 134 { 135 return cbc_aes_nx_crypt(desc, dst, src, nbytes, 0); 136 } 137 138 struct crypto_alg nx_cbc_aes_alg = { 139 .cra_name = "cbc(aes)", 140 .cra_driver_name = "cbc-aes-nx", 141 .cra_priority = 300, 142 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 143 .cra_blocksize = AES_BLOCK_SIZE, 144 .cra_ctxsize = sizeof(struct nx_crypto_ctx), 145 .cra_type = &crypto_blkcipher_type, 146 .cra_alignmask = 0xf, 147 .cra_module = THIS_MODULE, 148 .cra_init = nx_crypto_ctx_aes_cbc_init, 149 .cra_exit = nx_crypto_ctx_exit, 150 .cra_blkcipher = { 151 .min_keysize = AES_MIN_KEY_SIZE, 152 .max_keysize = AES_MAX_KEY_SIZE, 153 .ivsize = AES_BLOCK_SIZE, 154 .setkey = cbc_aes_nx_set_key, 155 .encrypt = cbc_aes_nx_encrypt, 156 .decrypt = cbc_aes_nx_decrypt, 157 } 158 }; 159