Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: powerpc/ghash - Use API partial block handling

Use the Crypto API partial block handling.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Herbert Xu f5bd7e84 ef11957b

+28 -53
+28 -53
arch/powerpc/crypto/ghash.c
··· 12 12 */ 13 13 14 14 #include "aesp8-ppc.h" 15 - #include <asm/simd.h> 16 15 #include <asm/switch_to.h> 17 16 #include <crypto/aes.h> 18 - #include <crypto/b128ops.h> 17 + #include <crypto/gf128mul.h> 19 18 #include <crypto/ghash.h> 20 19 #include <crypto/internal/hash.h> 21 20 #include <crypto/internal/simd.h> 22 - #include <crypto/scatterwalk.h> 23 21 #include <linux/err.h> 24 22 #include <linux/kernel.h> 25 23 #include <linux/module.h> 24 + #include <linux/string.h> 26 25 #include <linux/uaccess.h> 27 26 28 27 void gcm_init_p8(u128 htable[16], const u64 Xi[2]); ··· 38 39 39 40 struct p8_ghash_desc_ctx { 40 41 u64 shash[2]; 41 - u8 buffer[GHASH_DIGEST_SIZE]; 42 - int bytes; 43 42 }; 44 43 45 44 static int p8_ghash_init(struct shash_desc *desc) 46 45 { 47 46 struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc); 48 47 49 - dctx->bytes = 0; 50 48 memset(dctx->shash, 0, GHASH_DIGEST_SIZE); 51 49 return 0; 52 50 } ··· 70 74 } 71 75 72 76 static inline void __ghash_block(struct p8_ghash_ctx *ctx, 73 - struct p8_ghash_desc_ctx *dctx) 77 + struct p8_ghash_desc_ctx *dctx, 78 + const u8 *src) 74 79 { 75 80 if (crypto_simd_usable()) { 76 81 preempt_disable(); 77 82 pagefault_disable(); 78 83 enable_kernel_vsx(); 79 - gcm_ghash_p8(dctx->shash, ctx->htable, 80 - dctx->buffer, GHASH_DIGEST_SIZE); 84 + gcm_ghash_p8(dctx->shash, ctx->htable, src, GHASH_BLOCK_SIZE); 81 85 disable_kernel_vsx(); 82 86 pagefault_enable(); 83 87 preempt_enable(); 84 88 } else { 85 - crypto_xor((u8 *)dctx->shash, dctx->buffer, GHASH_BLOCK_SIZE); 89 + crypto_xor((u8 *)dctx->shash, src, GHASH_BLOCK_SIZE); 86 90 gf128mul_lle((be128 *)dctx->shash, &ctx->key); 87 91 } 88 92 } 89 93 90 - static inline void __ghash_blocks(struct p8_ghash_ctx *ctx, 91 - struct p8_ghash_desc_ctx *dctx, 92 - const u8 *src, unsigned int srclen) 94 + static inline int __ghash_blocks(struct p8_ghash_ctx *ctx, 95 + struct p8_ghash_desc_ctx *dctx, 96 + const u8 *src, unsigned int srclen) 93 97 { 98 + int remain = srclen - round_down(srclen, GHASH_BLOCK_SIZE); 99 + 100 + srclen -= remain; 94 101 if (crypto_simd_usable()) { 95 102 preempt_disable(); 96 103 pagefault_disable(); ··· 104 105 pagefault_enable(); 105 106 preempt_enable(); 106 107 } else { 107 - while (srclen >= GHASH_BLOCK_SIZE) { 108 + do { 108 109 crypto_xor((u8 *)dctx->shash, src, GHASH_BLOCK_SIZE); 109 110 gf128mul_lle((be128 *)dctx->shash, &ctx->key); 110 111 srclen -= GHASH_BLOCK_SIZE; 111 112 src += GHASH_BLOCK_SIZE; 112 - } 113 + } while (srclen); 113 114 } 115 + 116 + return remain; 114 117 } 115 118 116 119 static int p8_ghash_update(struct shash_desc *desc, 117 120 const u8 *src, unsigned int srclen) 118 121 { 119 - unsigned int len; 120 122 struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm)); 121 123 struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc); 122 124 123 - if (dctx->bytes) { 124 - if (dctx->bytes + srclen < GHASH_DIGEST_SIZE) { 125 - memcpy(dctx->buffer + dctx->bytes, src, 126 - srclen); 127 - dctx->bytes += srclen; 128 - return 0; 129 - } 130 - memcpy(dctx->buffer + dctx->bytes, src, 131 - GHASH_DIGEST_SIZE - dctx->bytes); 132 - 133 - __ghash_block(ctx, dctx); 134 - 135 - src += GHASH_DIGEST_SIZE - dctx->bytes; 136 - srclen -= GHASH_DIGEST_SIZE - dctx->bytes; 137 - dctx->bytes = 0; 138 - } 139 - len = srclen & ~(GHASH_DIGEST_SIZE - 1); 140 - if (len) { 141 - __ghash_blocks(ctx, dctx, src, len); 142 - src += len; 143 - srclen -= len; 144 - } 145 - if (srclen) { 146 - memcpy(dctx->buffer, src, srclen); 147 - dctx->bytes = srclen; 148 - } 149 - return 0; 125 + return __ghash_blocks(ctx, dctx, src, srclen); 150 126 } 151 127 152 - static int p8_ghash_final(struct shash_desc *desc, u8 *out) 128 + static int p8_ghash_finup(struct shash_desc *desc, const u8 *src, 129 + unsigned int len, u8 *out) 153 130 { 154 - int i; 155 131 struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm)); 156 132 struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc); 157 133 158 - if (dctx->bytes) { 159 - for (i = dctx->bytes; i < GHASH_DIGEST_SIZE; i++) 160 - dctx->buffer[i] = 0; 161 - __ghash_block(ctx, dctx); 162 - dctx->bytes = 0; 134 + if (len) { 135 + u8 buf[GHASH_BLOCK_SIZE] = {}; 136 + 137 + memcpy(buf, src, len); 138 + __ghash_block(ctx, dctx, buf); 139 + memzero_explicit(buf, sizeof(buf)); 163 140 } 164 141 memcpy(out, dctx->shash, GHASH_DIGEST_SIZE); 165 142 return 0; ··· 145 170 .digestsize = GHASH_DIGEST_SIZE, 146 171 .init = p8_ghash_init, 147 172 .update = p8_ghash_update, 148 - .final = p8_ghash_final, 173 + .finup = p8_ghash_finup, 149 174 .setkey = p8_ghash_setkey, 150 - .descsize = sizeof(struct p8_ghash_desc_ctx) 151 - + sizeof(struct ghash_desc_ctx), 175 + .descsize = sizeof(struct p8_ghash_desc_ctx), 152 176 .base = { 153 177 .cra_name = "ghash", 154 178 .cra_driver_name = "p8_ghash", 155 179 .cra_priority = 1000, 180 + .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, 156 181 .cra_blocksize = GHASH_BLOCK_SIZE, 157 182 .cra_ctxsize = sizeof(struct p8_ghash_ctx), 158 183 .cra_module = THIS_MODULE,