diff options
| author | Jan Stancek <jstancek@redhat.com> | 2015-08-08 02:47:28 -0400 |
|---|---|---|
| committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-08-11 10:02:57 -0400 |
| commit | d3392f41f6d3cd0a034bd0aca47fabea2b47218e (patch) | |
| tree | e20ee044fa3c991675968df9e41eca4a07702fb9 | |
| parent | 443c0d7ed9d3815b3425ca12d65337d52b9a0c34 (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.c | 27 | ||||
| -rw-r--r-- | drivers/crypto/nx/nx-sha512.c | 28 |
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 | /* |
