Lines Matching +full:op +full:- +full:mode
2 * sun4i-ss-hash.c - hardware cryptographic accelerator for Allwinner A20 SoC
4 * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
15 #include "sun4i-ss.h"
23 struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm); in sun4i_hash_crainit() local
24 struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg); in sun4i_hash_crainit()
27 memset(op, 0, sizeof(struct sun4i_tfm_ctx)); in sun4i_hash_crainit()
30 op->ss = algt->ss; in sun4i_hash_crainit()
40 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_init() local
42 struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); in sun4i_hash_init()
45 memset(op, 0, sizeof(struct sun4i_req_ctx)); in sun4i_hash_init()
48 op->mode = algt->mode; in sun4i_hash_init()
55 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_export_md5() local
59 octx->byte_count = op->byte_count + op->len; in sun4i_hash_export_md5()
61 memcpy(octx->block, op->buf, op->len); in sun4i_hash_export_md5()
63 if (op->byte_count) { in sun4i_hash_export_md5()
65 octx->hash[i] = op->hash[i]; in sun4i_hash_export_md5()
67 octx->hash[0] = SHA1_H0; in sun4i_hash_export_md5()
68 octx->hash[1] = SHA1_H1; in sun4i_hash_export_md5()
69 octx->hash[2] = SHA1_H2; in sun4i_hash_export_md5()
70 octx->hash[3] = SHA1_H3; in sun4i_hash_export_md5()
78 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_import_md5() local
84 op->byte_count = ictx->byte_count & ~0x3F; in sun4i_hash_import_md5()
85 op->len = ictx->byte_count & 0x3F; in sun4i_hash_import_md5()
87 memcpy(op->buf, ictx->block, op->len); in sun4i_hash_import_md5()
90 op->hash[i] = ictx->hash[i]; in sun4i_hash_import_md5()
97 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_export_sha1() local
101 octx->count = op->byte_count + op->len; in sun4i_hash_export_sha1()
103 memcpy(octx->buffer, op->buf, op->len); in sun4i_hash_export_sha1()
105 if (op->byte_count) { in sun4i_hash_export_sha1()
107 octx->state[i] = op->hash[i]; in sun4i_hash_export_sha1()
109 octx->state[0] = SHA1_H0; in sun4i_hash_export_sha1()
110 octx->state[1] = SHA1_H1; in sun4i_hash_export_sha1()
111 octx->state[2] = SHA1_H2; in sun4i_hash_export_sha1()
112 octx->state[3] = SHA1_H3; in sun4i_hash_export_sha1()
113 octx->state[4] = SHA1_H4; in sun4i_hash_export_sha1()
121 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_import_sha1() local
127 op->byte_count = ictx->count & ~0x3F; in sun4i_hash_import_sha1()
128 op->len = ictx->count & 0x3F; in sun4i_hash_import_sha1()
130 memcpy(op->buf, ictx->buffer, op->len); in sun4i_hash_import_sha1()
133 op->hash[i] = ictx->state[i]; in sun4i_hash_import_sha1()
152 * The extra bytes will go to a temporary buffer op->buf storing op->len bytes
155 * if op->len + areq->nbytes < 64
156 * => all data will be written to wait buffer (op->buf) and end=0
157 * if not, write all data from op->buf to the device and position end to
161 * update1 60o => op->len=60
164 * so write all data from op->buf and one word of SGs
165 * write remaining data in op->buf
166 * final state op->len=56
171 * i is the total bytes read from SGs, to be compared to areq->nbytes in sun4i_hash()
173 * SG->length could be greater than areq->nbytes in sun4i_hash()
183 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash() local
186 struct sun4i_ss_ctx *ss = tfmctx->ss; in sun4i_hash()
187 struct scatterlist *in_sg = areq->src; in sun4i_hash()
193 dev_dbg(ss->dev, "%s %s bc=%llu len=%u mode=%x wl=%u h0=%0x", in sun4i_hash()
194 __func__, crypto_tfm_alg_name(areq->base.tfm), in sun4i_hash()
195 op->byte_count, areq->nbytes, op->mode, in sun4i_hash()
196 op->len, op->hash[0]); in sun4i_hash()
198 if (unlikely(!areq->nbytes) && !(op->flags & SS_HASH_FINAL)) in sun4i_hash()
202 if (unlikely(areq->nbytes > UINT_MAX - op->len)) { in sun4i_hash()
203 dev_err(ss->dev, "Cannot process too large request\n"); in sun4i_hash()
204 return -EINVAL; in sun4i_hash()
207 if (op->len + areq->nbytes < 64 && !(op->flags & SS_HASH_FINAL)) { in sun4i_hash()
208 /* linearize data to op->buf */ in sun4i_hash()
209 copied = sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), in sun4i_hash()
210 op->buf + op->len, areq->nbytes, 0); in sun4i_hash()
211 op->len += copied; in sun4i_hash()
215 spin_lock_bh(&ss->slock); in sun4i_hash()
221 if (op->byte_count) { in sun4i_hash()
224 writel(op->hash[i], ss->base + SS_IV0 + i * 4); in sun4i_hash()
227 writel(op->mode | SS_ENABLED | ivmode, ss->base + SS_CTL); in sun4i_hash()
229 if (!(op->flags & SS_HASH_UPDATE)) in sun4i_hash()
233 if (!(op->flags & SS_HASH_FINAL)) { in sun4i_hash()
234 end = ((areq->nbytes + op->len) / 64) * 64 - op->len; in sun4i_hash()
236 if (end > areq->nbytes || areq->nbytes - end > 63) { in sun4i_hash()
237 dev_err(ss->dev, "ERROR: Bound error %u %u\n", in sun4i_hash()
238 end, areq->nbytes); in sun4i_hash()
239 err = -EINVAL; in sun4i_hash()
244 if (areq->nbytes < 4) in sun4i_hash()
247 end = ((areq->nbytes + op->len) / 4) * 4 - op->len; in sun4i_hash()
250 /* TODO if SGlen % 4 and !op->len then DMA */ in sun4i_hash()
253 if (in_sg->length % 4) in sun4i_hash()
257 if (i == 1 && !op->len && areq->nbytes) in sun4i_hash()
258 dev_dbg(ss->dev, "We can DMA\n"); in sun4i_hash()
261 sg_miter_start(&mi, areq->src, sg_nents(areq->src), in sun4i_hash()
269 * - the buffer is already used in sun4i_hash()
270 * - the SG does not have enough byte remaining ( < 4) in sun4i_hash()
272 if (op->len || (mi.length - in_i) < 4) { in sun4i_hash()
275 * - the buffer is full in sun4i_hash()
276 * - reach the end in sun4i_hash()
278 while (op->len < 64 && i < end) { in sun4i_hash()
280 in_r = min(end - i, 64 - op->len); in sun4i_hash()
281 in_r = min_t(size_t, mi.length - in_i, in_r); in sun4i_hash()
282 memcpy(op->buf + op->len, mi.addr + in_i, in_r); in sun4i_hash()
283 op->len += in_r; in sun4i_hash()
291 if (op->len > 3 && !(op->len % 4)) { in sun4i_hash()
293 writesl(ss->base + SS_RXFIFO, op->buf, in sun4i_hash()
294 op->len / 4); in sun4i_hash()
295 op->byte_count += op->len; in sun4i_hash()
296 op->len = 0; in sun4i_hash()
299 if (mi.length - in_i > 3 && i < end) { in sun4i_hash()
301 in_r = min_t(size_t, mi.length - in_i, areq->nbytes - i); in sun4i_hash()
302 in_r = min_t(size_t, ((mi.length - in_i) / 4) * 4, in_r); in sun4i_hash()
304 todo = min3((u32)(end - i) / 4, rx_cnt, (u32)in_r / 4); in sun4i_hash()
305 writesl(ss->base + SS_RXFIFO, mi.addr + in_i, todo); in sun4i_hash()
306 op->byte_count += todo * 4; in sun4i_hash()
309 rx_cnt -= todo; in sun4i_hash()
311 spaces = readl(ss->base + SS_FCSR); in sun4i_hash()
323 * store the remaining bytes in op->buf in sun4i_hash()
325 if ((areq->nbytes - i) < 64) { in sun4i_hash()
326 while (i < areq->nbytes && in_i < mi.length && op->len < 64) { in sun4i_hash()
328 in_r = min(areq->nbytes - i, 64 - op->len); in sun4i_hash()
329 in_r = min_t(size_t, mi.length - in_i, in_r); in sun4i_hash()
330 memcpy(op->buf + op->len, mi.addr + in_i, in_r); in sun4i_hash()
331 op->len += in_r; in sun4i_hash()
348 if (op->flags & SS_HASH_FINAL) in sun4i_hash()
351 writel(op->mode | SS_ENABLED | SS_DATA_END, ss->base + SS_CTL); in sun4i_hash()
354 v = readl(ss->base + SS_CTL); in sun4i_hash()
358 dev_err_ratelimited(ss->dev, in sun4i_hash()
360 i, SS_TIMEOUT, v, areq->nbytes); in sun4i_hash()
361 err = -EIO; in sun4i_hash()
375 op->hash[i] = readl(ss->base + SS_MD0 + i * 4); in sun4i_hash()
394 if (op->len) { in sun4i_hash()
395 nwait = op->len / 4; in sun4i_hash()
397 writesl(ss->base + SS_RXFIFO, op->buf, nwait); in sun4i_hash()
398 op->byte_count += 4 * nwait; in sun4i_hash()
401 nbw = op->len - 4 * nwait; in sun4i_hash()
403 wb = cpu_to_le32(*(u32 *)(op->buf + nwait * 4)); in sun4i_hash()
404 wb &= GENMASK((nbw * 8) - 1, 0); in sun4i_hash()
406 op->byte_count += nbw; in sun4i_hash()
420 fill = 64 - (op->byte_count % 64); in sun4i_hash()
427 j += (fill - min_fill) / sizeof(u32); in sun4i_hash()
430 if (op->mode == SS_OP_SHA1) { in sun4i_hash()
432 *bits = cpu_to_be64(op->byte_count << 3); in sun4i_hash()
436 *bits = cpu_to_le64(op->byte_count << 3); in sun4i_hash()
439 writesl(ss->base + SS_RXFIFO, bf, j); in sun4i_hash()
442 writel(op->mode | SS_ENABLED | SS_DATA_END, ss->base + SS_CTL); in sun4i_hash()
451 v = readl(ss->base + SS_CTL); in sun4i_hash()
455 dev_err_ratelimited(ss->dev, in sun4i_hash()
457 i, SS_TIMEOUT, v, areq->nbytes); in sun4i_hash()
458 err = -EIO; in sun4i_hash()
472 if (op->mode == SS_OP_SHA1) { in sun4i_hash()
474 v = cpu_to_be32(readl(ss->base + SS_MD0 + i * 4)); in sun4i_hash()
475 memcpy(areq->result + i * 4, &v, 4); in sun4i_hash()
479 v = cpu_to_le32(readl(ss->base + SS_MD0 + i * 4)); in sun4i_hash()
480 memcpy(areq->result + i * 4, &v, 4); in sun4i_hash()
485 writel(0, ss->base + SS_CTL); in sun4i_hash()
486 spin_unlock_bh(&ss->slock); in sun4i_hash()
492 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_final() local
494 op->flags = SS_HASH_FINAL; in sun4i_hash_final()
500 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_update() local
502 op->flags = SS_HASH_UPDATE; in sun4i_hash_update()
509 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_finup() local
511 op->flags = SS_HASH_UPDATE | SS_HASH_FINAL; in sun4i_hash_finup()
519 struct sun4i_req_ctx *op = ahash_request_ctx(areq); in sun4i_hash_digest() local
525 op->flags = SS_HASH_UPDATE | SS_HASH_FINAL; in sun4i_hash_digest()