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

crypto: arm64/sm4-ccm - Rewrite skcipher walker loop

The fact that an error in the skcipher walker API are indicated
not only by a non-zero return value, but also by the fact that
walk->nbytes is zero, causes the layout of the skcipher walker
loop to be sufficiently different from the usual layout, which
is not a problem in itself, but it is likely to cause reading
confusion and difficulty in code maintenance.

This patch rewrites skcipher walker loop, and separates the
last chunk cryption from the loop to avoid wrong calls to the
skcipher walker API. In addition to following the usual convention
of checking walk->nbytes, it also makes the loop execute logic
clearer and easier to understand.

Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Tianjia Zhang and committed by
Herbert Xu
3b9d9021 d58fa987

+26 -22
+26 -22
arch/arm64/crypto/sm4-ce-ccm-glue.c
··· 166 166 unsigned int nbytes, u8 *mac)) 167 167 { 168 168 u8 __aligned(8) ctr0[SM4_BLOCK_SIZE]; 169 - int err; 169 + int err = 0; 170 170 171 171 /* preserve the initial ctr0 for the TAG */ 172 172 memcpy(ctr0, walk->iv, SM4_BLOCK_SIZE); ··· 177 177 if (req->assoclen) 178 178 ccm_calculate_auth_mac(req, mac); 179 179 180 - do { 180 + while (walk->nbytes && walk->nbytes != walk->total) { 181 181 unsigned int tail = walk->nbytes % SM4_BLOCK_SIZE; 182 - const u8 *src = walk->src.virt.addr; 183 - u8 *dst = walk->dst.virt.addr; 184 182 185 - if (walk->nbytes == walk->total) 186 - tail = 0; 187 - 188 - if (walk->nbytes - tail) 189 - sm4_ce_ccm_crypt(rkey_enc, dst, src, walk->iv, 190 - walk->nbytes - tail, mac); 191 - 192 - if (walk->nbytes == walk->total) 193 - sm4_ce_ccm_final(rkey_enc, ctr0, mac); 183 + sm4_ce_ccm_crypt(rkey_enc, walk->dst.virt.addr, 184 + walk->src.virt.addr, walk->iv, 185 + walk->nbytes - tail, mac); 194 186 195 187 kernel_neon_end(); 196 188 197 - if (walk->nbytes) { 198 - err = skcipher_walk_done(walk, tail); 199 - if (err) 200 - return err; 201 - if (walk->nbytes) 202 - kernel_neon_begin(); 203 - } 204 - } while (walk->nbytes > 0); 189 + err = skcipher_walk_done(walk, tail); 205 190 206 - return 0; 191 + kernel_neon_begin(); 192 + } 193 + 194 + if (walk->nbytes) { 195 + sm4_ce_ccm_crypt(rkey_enc, walk->dst.virt.addr, 196 + walk->src.virt.addr, walk->iv, 197 + walk->nbytes, mac); 198 + 199 + sm4_ce_ccm_final(rkey_enc, ctr0, mac); 200 + 201 + kernel_neon_end(); 202 + 203 + err = skcipher_walk_done(walk, 0); 204 + } else { 205 + sm4_ce_ccm_final(rkey_enc, ctr0, mac); 206 + 207 + kernel_neon_end(); 208 + } 209 + 210 + return err; 207 211 } 208 212 209 213 static int ccm_encrypt(struct aead_request *req)