aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Stancek <jstancek@redhat.com>2015-08-08 02:47:28 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2015-08-11 10:02:57 -0400
commitd3392f41f6d3cd0a034bd0aca47fabea2b47218e (patch)
treee20ee044fa3c991675968df9e41eca4a07702fb9
parent443c0d7ed9d3815b3425ca12d65337d52b9a0c34 (diff)
crypto: nx - respect sg limit bounds when building sg lists for SHA
Commit 000851119e80 changed sha256/512 update functions to pass more data to nx_build_sg_list(), which ends with sg list overflows and usually with update functions failing for data larger than max_sg_len * NX_PAGE_SIZE. This happens because: - both "total" and "to_process" are updated, which leads to "to_process" getting overflowed for some data lengths For example: In first iteration "total" is 50, and let's assume "to_process" is 30 due to sg limits. At the end of first iteration "total" is set to 20. At start of 2nd iteration "to_process" overflows on: to_process = total - to_process; - "in_sg" is not reset to nx_ctx->in_sg after each iteration - nx_build_sg_list() is hitting overflow because the amount of data passed to it would require more than sgmax elements - as consequence of previous item, data stored in overflowed sg list may no longer be aligned to SHA*_BLOCK_SIZE This patch changes sha256/512 update functions so that "to_process" respects sg limits and never tries to pass more data to nx_build_sg_list() to avoid overflows. "to_process" is calculated as minimum of "total" and sg limits at start of every iteration. Fixes: 000851119e80 ("crypto: nx - Fix SHA concurrence issue and sg limit bounds") Signed-off-by: Jan Stancek <jstancek@redhat.com> Cc: stable@vger.kernel.org Cc: Leonidas Da Silva Barbosa <leosilva@linux.vnet.ibm.com> Cc: Marcelo Henrique Cerri <mhcerri@linux.vnet.ibm.com> Cc: Fionnuala Gunter <fin@linux.vnet.ibm.com> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/crypto/nx/nx-sha256.c27
-rw-r--r--drivers/crypto/nx/nx-sha512.c28
2 files changed, 32 insertions, 23 deletions
diff --git a/drivers/crypto/nx/nx-sha256.c b/drivers/crypto/nx/nx-sha256.c
index 08f8d5cd6334..becb738c897b 100644
--- a/drivers/crypto/nx/nx-sha256.c
+++ b/drivers/crypto/nx/nx-sha256.c
@@ -71,7 +71,6 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
71 struct sha256_state *sctx = shash_desc_ctx(desc); 71 struct sha256_state *sctx = shash_desc_ctx(desc);
72 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); 72 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
73 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb; 73 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
74 struct nx_sg *in_sg;
75 struct nx_sg *out_sg; 74 struct nx_sg *out_sg;
76 u64 to_process = 0, leftover, total; 75 u64 to_process = 0, leftover, total;
77 unsigned long irq_flags; 76 unsigned long irq_flags;
@@ -97,7 +96,6 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
97 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE; 96 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
98 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION; 97 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
99 98
100 in_sg = nx_ctx->in_sg;
101 max_sg_len = min_t(u64, nx_ctx->ap->sglen, 99 max_sg_len = min_t(u64, nx_ctx->ap->sglen,
102 nx_driver.of.max_sg_len/sizeof(struct nx_sg)); 100 nx_driver.of.max_sg_len/sizeof(struct nx_sg));
103 max_sg_len = min_t(u64, max_sg_len, 101 max_sg_len = min_t(u64, max_sg_len,
@@ -114,17 +112,12 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
114 } 112 }
115 113
116 do { 114 do {
117 /* 115 int used_sgs = 0;
118 * to_process: the SHA256_BLOCK_SIZE data chunk to process in 116 struct nx_sg *in_sg = nx_ctx->in_sg;
119 * this update. This value is also restricted by the sg list
120 * limits.
121 */
122 to_process = total - to_process;
123 to_process = to_process & ~(SHA256_BLOCK_SIZE - 1);
124 117
125 if (buf_len) { 118 if (buf_len) {
126 data_len = buf_len; 119 data_len = buf_len;
127 in_sg = nx_build_sg_list(nx_ctx->in_sg, 120 in_sg = nx_build_sg_list(in_sg,
128 (u8 *) sctx->buf, 121 (u8 *) sctx->buf,
129 &data_len, 122 &data_len,
130 max_sg_len); 123 max_sg_len);
@@ -133,15 +126,27 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
133 rc = -EINVAL; 126 rc = -EINVAL;
134 goto out; 127 goto out;
135 } 128 }
129 used_sgs = in_sg - nx_ctx->in_sg;
136 } 130 }
137 131
132 /* to_process: SHA256_BLOCK_SIZE aligned chunk to be
133 * processed in this iteration. This value is restricted
134 * by sg list limits and number of sgs we already used
135 * for leftover data. (see above)
136 * In ideal case, we could allow NX_PAGE_SIZE * max_sg_len,
137 * but because data may not be aligned, we need to account
138 * for that too. */
139 to_process = min_t(u64, total,
140 (max_sg_len - 1 - used_sgs) * NX_PAGE_SIZE);
141 to_process = to_process & ~(SHA256_BLOCK_SIZE - 1);
142
138 data_len = to_process - buf_len; 143 data_len = to_process - buf_len;
139 in_sg = nx_build_sg_list(in_sg, (u8 *) data, 144 in_sg = nx_build_sg_list(in_sg, (u8 *) data,
140 &data_len, max_sg_len); 145 &data_len, max_sg_len);
141 146
142 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg); 147 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
143 148
144 to_process = (data_len + buf_len); 149 to_process = data_len + buf_len;
145 leftover = total - to_process; 150 leftover = total - to_process;
146 151
147 /* 152 /*
diff --git a/drivers/crypto/nx/nx-sha512.c b/drivers/crypto/nx/nx-sha512.c
index aff0fe58eac0..b6e183d58d73 100644
--- a/drivers/crypto/nx/nx-sha512.c
+++ b/drivers/crypto/nx/nx-sha512.c
@@ -71,7 +71,6 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
71 struct sha512_state *sctx = shash_desc_ctx(desc); 71 struct sha512_state *sctx = shash_desc_ctx(desc);
72 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base); 72 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
73 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb; 73 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
74 struct nx_sg *in_sg;
75 struct nx_sg *out_sg; 74 struct nx_sg *out_sg;
76 u64 to_process, leftover = 0, total; 75 u64 to_process, leftover = 0, total;
77 unsigned long irq_flags; 76 unsigned long irq_flags;
@@ -97,7 +96,6 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
97 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE; 96 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
98 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION; 97 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
99 98
100 in_sg = nx_ctx->in_sg;
101 max_sg_len = min_t(u64, nx_ctx->ap->sglen, 99 max_sg_len = min_t(u64, nx_ctx->ap->sglen,
102 nx_driver.of.max_sg_len/sizeof(struct nx_sg)); 100 nx_driver.of.max_sg_len/sizeof(struct nx_sg));
103 max_sg_len = min_t(u64, max_sg_len, 101 max_sg_len = min_t(u64, max_sg_len,
@@ -114,18 +112,12 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
114 } 112 }
115 113
116 do { 114 do {
117 /* 115 int used_sgs = 0;
118 * to_process: the SHA512_BLOCK_SIZE data chunk to process in 116 struct nx_sg *in_sg = nx_ctx->in_sg;
119 * this update. This value is also restricted by the sg list
120 * limits.
121 */
122 to_process = total - leftover;
123 to_process = to_process & ~(SHA512_BLOCK_SIZE - 1);
124 leftover = total - to_process;
125 117
126 if (buf_len) { 118 if (buf_len) {
127 data_len = buf_len; 119 data_len = buf_len;
128 in_sg = nx_build_sg_list(nx_ctx->in_sg, 120 in_sg = nx_build_sg_list(in_sg,
129 (u8 *) sctx->buf, 121 (u8 *) sctx->buf,
130 &data_len, max_sg_len); 122 &data_len, max_sg_len);
131 123
@@ -133,8 +125,20 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
133 rc = -EINVAL; 125 rc = -EINVAL;
134 goto out; 126 goto out;
135 } 127 }
128 used_sgs = in_sg - nx_ctx->in_sg;
136 } 129 }
137 130
131 /* to_process: SHA512_BLOCK_SIZE aligned chunk to be
132 * processed in this iteration. This value is restricted
133 * by sg list limits and number of sgs we already used
134 * for leftover data. (see above)
135 * In ideal case, we could allow NX_PAGE_SIZE * max_sg_len,
136 * but because data may not be aligned, we need to account
137 * for that too. */
138 to_process = min_t(u64, total,
139 (max_sg_len - 1 - used_sgs) * NX_PAGE_SIZE);
140 to_process = to_process & ~(SHA512_BLOCK_SIZE - 1);
141
138 data_len = to_process - buf_len; 142 data_len = to_process - buf_len;
139 in_sg = nx_build_sg_list(in_sg, (u8 *) data, 143 in_sg = nx_build_sg_list(in_sg, (u8 *) data,
140 &data_len, max_sg_len); 144 &data_len, max_sg_len);
@@ -146,7 +150,7 @@ static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
146 goto out; 150 goto out;
147 } 151 }
148 152
149 to_process = (data_len + buf_len); 153 to_process = data_len + buf_len;
150 leftover = total - to_process; 154 leftover = total - to_process;
151 155
152 /* 156 /*