aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/crypto/nx/nx-aes-gcm.c132
1 files changed, 112 insertions, 20 deletions
diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c
index 9e89bdf34487..025d9a8d5b19 100644
--- a/drivers/crypto/nx/nx-aes-gcm.c
+++ b/drivers/crypto/nx/nx-aes-gcm.c
@@ -187,40 +187,125 @@ static int nx_gca(struct nx_crypto_ctx *nx_ctx,
187 return rc; 187 return rc;
188} 188}
189 189
190static int gmac(struct aead_request *req, struct blkcipher_desc *desc)
191{
192 int rc;
193 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
194 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
195 struct nx_sg *nx_sg;
196 unsigned int nbytes = req->assoclen;
197 unsigned int processed = 0, to_process;
198 u32 max_sg_len;
199
200 /* Set GMAC mode */
201 csbcpb->cpb.hdr.mode = NX_MODE_AES_GMAC;
202
203 NX_CPB_FDM(csbcpb) &= ~NX_FDM_CONTINUATION;
204
205 /* page_limit: number of sg entries that fit on one page */
206 max_sg_len = min_t(u32, nx_driver.of.max_sg_len/sizeof(struct nx_sg),
207 nx_ctx->ap->sglen);
208
209 /* Copy IV */
210 memcpy(csbcpb->cpb.aes_gcm.iv_or_cnt, desc->info, AES_BLOCK_SIZE);
211
212 do {
213 /*
214 * to_process: the data chunk to process in this update.
215 * This value is bound by sg list limits.
216 */
217 to_process = min_t(u64, nbytes - processed,
218 nx_ctx->ap->databytelen);
219 to_process = min_t(u64, to_process,
220 NX_PAGE_SIZE * (max_sg_len - 1));
221
222 if ((to_process + processed) < nbytes)
223 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
224 else
225 NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
226
227 nx_sg = nx_walk_and_build(nx_ctx->in_sg, nx_ctx->ap->sglen,
228 req->assoc, processed, to_process);
229 nx_ctx->op.inlen = (nx_ctx->in_sg - nx_sg)
230 * sizeof(struct nx_sg);
231
232 csbcpb->cpb.aes_gcm.bit_length_data = 0;
233 csbcpb->cpb.aes_gcm.bit_length_aad = 8 * nbytes;
234
235 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
236 req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
237 if (rc)
238 goto out;
239
240 memcpy(csbcpb->cpb.aes_gcm.in_pat_or_aad,
241 csbcpb->cpb.aes_gcm.out_pat_or_mac, AES_BLOCK_SIZE);
242 memcpy(csbcpb->cpb.aes_gcm.in_s0,
243 csbcpb->cpb.aes_gcm.out_s0, AES_BLOCK_SIZE);
244
245 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
246
247 atomic_inc(&(nx_ctx->stats->aes_ops));
248 atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
249
250 processed += to_process;
251 } while (processed < nbytes);
252
253out:
254 /* Restore GCM mode */
255 csbcpb->cpb.hdr.mode = NX_MODE_AES_GCM;
256 return rc;
257}
258
190static int gcm_empty(struct aead_request *req, struct blkcipher_desc *desc, 259static int gcm_empty(struct aead_request *req, struct blkcipher_desc *desc,
191 int enc) 260 int enc)
192{ 261{
193 int rc; 262 int rc;
194 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm); 263 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
195 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb; 264 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
265 char out[AES_BLOCK_SIZE];
266 struct nx_sg *in_sg, *out_sg;
196 267
197 /* For scenarios where the input message is zero length, AES CTR mode 268 /* For scenarios where the input message is zero length, AES CTR mode
198 * may be used. Set the source data to be a single block (16B) of all 269 * may be used. Set the source data to be a single block (16B) of all
199 * zeros, and set the input IV value to be the same as the GMAC IV 270 * zeros, and set the input IV value to be the same as the GMAC IV
200 * value. - nx_wb 4.8.1.3 */ 271 * value. - nx_wb 4.8.1.3 */
201 char src[AES_BLOCK_SIZE] = {};
202 struct scatterlist sg;
203
204 desc->tfm = crypto_alloc_blkcipher("ctr(aes)", 0, 0);
205 if (IS_ERR(desc->tfm)) {
206 rc = -ENOMEM;
207 goto out;
208 }
209
210 crypto_blkcipher_setkey(desc->tfm, csbcpb->cpb.aes_gcm.key,
211 NX_CPB_KEY_SIZE(csbcpb) == NX_KS_AES_128 ? 16 :
212 NX_CPB_KEY_SIZE(csbcpb) == NX_KS_AES_192 ? 24 : 32);
213 272
214 sg_init_one(&sg, src, AES_BLOCK_SIZE); 273 /* Change to ECB mode */
274 csbcpb->cpb.hdr.mode = NX_MODE_AES_ECB;
275 memcpy(csbcpb->cpb.aes_ecb.key, csbcpb->cpb.aes_gcm.key,
276 sizeof(csbcpb->cpb.aes_ecb.key));
215 if (enc) 277 if (enc)
216 rc = crypto_blkcipher_encrypt_iv(desc, req->dst, &sg, 278 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
217 AES_BLOCK_SIZE);
218 else 279 else
219 rc = crypto_blkcipher_decrypt_iv(desc, req->dst, &sg, 280 NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
220 AES_BLOCK_SIZE); 281
221 crypto_free_blkcipher(desc->tfm); 282 /* Encrypt the counter/IV */
283 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *) desc->info,
284 AES_BLOCK_SIZE, nx_ctx->ap->sglen);
285 out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *) out, sizeof(out),
286 nx_ctx->ap->sglen);
287 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
288 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
222 289
290 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
291 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
292 if (rc)
293 goto out;
294 atomic_inc(&(nx_ctx->stats->aes_ops));
295
296 /* Copy out the auth tag */
297 memcpy(csbcpb->cpb.aes_gcm.out_pat_or_mac, out,
298 crypto_aead_authsize(crypto_aead_reqtfm(req)));
223out: 299out:
300 /* Restore XCBC mode */
301 csbcpb->cpb.hdr.mode = NX_MODE_AES_GCM;
302
303 /*
304 * ECB key uses the same region that GCM AAD and counter, so it's safe
305 * to just fill it with zeroes.
306 */
307 memset(csbcpb->cpb.aes_ecb.key, 0, sizeof(csbcpb->cpb.aes_ecb.key));
308
224 return rc; 309 return rc;
225} 310}
226 311
@@ -242,8 +327,14 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
242 *(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1; 327 *(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1;
243 328
244 if (nbytes == 0) { 329 if (nbytes == 0) {
245 rc = gcm_empty(req, &desc, enc); 330 if (req->assoclen == 0)
246 goto out; 331 rc = gcm_empty(req, &desc, enc);
332 else
333 rc = gmac(req, &desc);
334 if (rc)
335 goto out;
336 else
337 goto mac;
247 } 338 }
248 339
249 /* Process associated data */ 340 /* Process associated data */
@@ -310,6 +401,7 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
310 processed += to_process; 401 processed += to_process;
311 } while (processed < nbytes); 402 } while (processed < nbytes);
312 403
404mac:
313 if (enc) { 405 if (enc) {
314 /* copy out the auth tag */ 406 /* copy out the auth tag */
315 scatterwalk_map_and_copy(csbcpb->cpb.aes_gcm.out_pat_or_mac, 407 scatterwalk_map_and_copy(csbcpb->cpb.aes_gcm.out_pat_or_mac,