Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

Pull crypto fixes from Herbert Xu:
 "This fixes a bug in CBC/CTR on ARM64 that breaks chaining as well as a
  bug in the core API that causes registration failures when a driver
  unloads and then reloads an algorithm"

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: arm64/aes-blk - honour iv_out requirement in CBC and CTR modes
  crypto: api - Clear CRYPTO_ALG_DEAD bit before registering an alg
This commit is contained in:
Linus Torvalds 2017-02-01 09:24:00 -08:00
commit e387dc122f
2 changed files with 44 additions and 47 deletions

View File

@ -193,15 +193,16 @@ AES_ENTRY(aes_cbc_encrypt)
cbz w6, .Lcbcencloop cbz w6, .Lcbcencloop
ld1 {v0.16b}, [x5] /* get iv */ ld1 {v0.16b}, [x5] /* get iv */
enc_prepare w3, x2, x5 enc_prepare w3, x2, x6
.Lcbcencloop: .Lcbcencloop:
ld1 {v1.16b}, [x1], #16 /* get next pt block */ ld1 {v1.16b}, [x1], #16 /* get next pt block */
eor v0.16b, v0.16b, v1.16b /* ..and xor with iv */ eor v0.16b, v0.16b, v1.16b /* ..and xor with iv */
encrypt_block v0, w3, x2, x5, w6 encrypt_block v0, w3, x2, x6, w7
st1 {v0.16b}, [x0], #16 st1 {v0.16b}, [x0], #16
subs w4, w4, #1 subs w4, w4, #1
bne .Lcbcencloop bne .Lcbcencloop
st1 {v0.16b}, [x5] /* return iv */
ret ret
AES_ENDPROC(aes_cbc_encrypt) AES_ENDPROC(aes_cbc_encrypt)
@ -211,7 +212,7 @@ AES_ENTRY(aes_cbc_decrypt)
cbz w6, .LcbcdecloopNx cbz w6, .LcbcdecloopNx
ld1 {v7.16b}, [x5] /* get iv */ ld1 {v7.16b}, [x5] /* get iv */
dec_prepare w3, x2, x5 dec_prepare w3, x2, x6
.LcbcdecloopNx: .LcbcdecloopNx:
#if INTERLEAVE >= 2 #if INTERLEAVE >= 2
@ -248,7 +249,7 @@ AES_ENTRY(aes_cbc_decrypt)
.Lcbcdecloop: .Lcbcdecloop:
ld1 {v1.16b}, [x1], #16 /* get next ct block */ ld1 {v1.16b}, [x1], #16 /* get next ct block */
mov v0.16b, v1.16b /* ...and copy to v0 */ mov v0.16b, v1.16b /* ...and copy to v0 */
decrypt_block v0, w3, x2, x5, w6 decrypt_block v0, w3, x2, x6, w7
eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */ eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */
mov v7.16b, v1.16b /* ct is next iv */ mov v7.16b, v1.16b /* ct is next iv */
st1 {v0.16b}, [x0], #16 st1 {v0.16b}, [x0], #16
@ -256,6 +257,7 @@ AES_ENTRY(aes_cbc_decrypt)
bne .Lcbcdecloop bne .Lcbcdecloop
.Lcbcdecout: .Lcbcdecout:
FRAME_POP FRAME_POP
st1 {v7.16b}, [x5] /* return iv */
ret ret
AES_ENDPROC(aes_cbc_decrypt) AES_ENDPROC(aes_cbc_decrypt)
@ -267,24 +269,15 @@ AES_ENDPROC(aes_cbc_decrypt)
AES_ENTRY(aes_ctr_encrypt) AES_ENTRY(aes_ctr_encrypt)
FRAME_PUSH FRAME_PUSH
cbnz w6, .Lctrfirst /* 1st time around? */ cbz w6, .Lctrnotfirst /* 1st time around? */
umov x5, v4.d[1] /* keep swabbed ctr in reg */
rev x5, x5
#if INTERLEAVE >= 2
cmn w5, w4 /* 32 bit overflow? */
bcs .Lctrinc
add x5, x5, #1 /* increment BE ctr */
b .LctrincNx
#else
b .Lctrinc
#endif
.Lctrfirst:
enc_prepare w3, x2, x6 enc_prepare w3, x2, x6
ld1 {v4.16b}, [x5] ld1 {v4.16b}, [x5]
umov x5, v4.d[1] /* keep swabbed ctr in reg */
rev x5, x5 .Lctrnotfirst:
umov x8, v4.d[1] /* keep swabbed ctr in reg */
rev x8, x8
#if INTERLEAVE >= 2 #if INTERLEAVE >= 2
cmn w5, w4 /* 32 bit overflow? */ cmn w8, w4 /* 32 bit overflow? */
bcs .Lctrloop bcs .Lctrloop
.LctrloopNx: .LctrloopNx:
subs w4, w4, #INTERLEAVE subs w4, w4, #INTERLEAVE
@ -292,11 +285,11 @@ AES_ENTRY(aes_ctr_encrypt)
#if INTERLEAVE == 2 #if INTERLEAVE == 2
mov v0.8b, v4.8b mov v0.8b, v4.8b
mov v1.8b, v4.8b mov v1.8b, v4.8b
rev x7, x5 rev x7, x8
add x5, x5, #1 add x8, x8, #1
ins v0.d[1], x7 ins v0.d[1], x7
rev x7, x5 rev x7, x8
add x5, x5, #1 add x8, x8, #1
ins v1.d[1], x7 ins v1.d[1], x7
ld1 {v2.16b-v3.16b}, [x1], #32 /* get 2 input blocks */ ld1 {v2.16b-v3.16b}, [x1], #32 /* get 2 input blocks */
do_encrypt_block2x do_encrypt_block2x
@ -305,7 +298,7 @@ AES_ENTRY(aes_ctr_encrypt)
st1 {v0.16b-v1.16b}, [x0], #32 st1 {v0.16b-v1.16b}, [x0], #32
#else #else
ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */ ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */
dup v7.4s, w5 dup v7.4s, w8
mov v0.16b, v4.16b mov v0.16b, v4.16b
add v7.4s, v7.4s, v8.4s add v7.4s, v7.4s, v8.4s
mov v1.16b, v4.16b mov v1.16b, v4.16b
@ -323,18 +316,12 @@ AES_ENTRY(aes_ctr_encrypt)
eor v2.16b, v7.16b, v2.16b eor v2.16b, v7.16b, v2.16b
eor v3.16b, v5.16b, v3.16b eor v3.16b, v5.16b, v3.16b
st1 {v0.16b-v3.16b}, [x0], #64 st1 {v0.16b-v3.16b}, [x0], #64
add x5, x5, #INTERLEAVE add x8, x8, #INTERLEAVE
#endif #endif
cbz w4, .LctroutNx rev x7, x8
.LctrincNx:
rev x7, x5
ins v4.d[1], x7 ins v4.d[1], x7
cbz w4, .Lctrout
b .LctrloopNx b .LctrloopNx
.LctroutNx:
sub x5, x5, #1
rev x7, x5
ins v4.d[1], x7
b .Lctrout
.Lctr1x: .Lctr1x:
adds w4, w4, #INTERLEAVE adds w4, w4, #INTERLEAVE
beq .Lctrout beq .Lctrout
@ -342,30 +329,39 @@ AES_ENTRY(aes_ctr_encrypt)
.Lctrloop: .Lctrloop:
mov v0.16b, v4.16b mov v0.16b, v4.16b
encrypt_block v0, w3, x2, x6, w7 encrypt_block v0, w3, x2, x6, w7
adds x8, x8, #1 /* increment BE ctr */
rev x7, x8
ins v4.d[1], x7
bcs .Lctrcarry /* overflow? */
.Lctrcarrydone:
subs w4, w4, #1 subs w4, w4, #1
bmi .Lctrhalfblock /* blocks < 0 means 1/2 block */ bmi .Lctrhalfblock /* blocks < 0 means 1/2 block */
ld1 {v3.16b}, [x1], #16 ld1 {v3.16b}, [x1], #16
eor v3.16b, v0.16b, v3.16b eor v3.16b, v0.16b, v3.16b
st1 {v3.16b}, [x0], #16 st1 {v3.16b}, [x0], #16
beq .Lctrout bne .Lctrloop
.Lctrinc:
adds x5, x5, #1 /* increment BE ctr */ .Lctrout:
rev x7, x5 st1 {v4.16b}, [x5] /* return next CTR value */
ins v4.d[1], x7 FRAME_POP
bcc .Lctrloop /* no overflow? */ ret
.Lctrhalfblock:
ld1 {v3.8b}, [x1]
eor v3.8b, v0.8b, v3.8b
st1 {v3.8b}, [x0]
FRAME_POP
ret
.Lctrcarry:
umov x7, v4.d[0] /* load upper word of ctr */ umov x7, v4.d[0] /* load upper word of ctr */
rev x7, x7 /* ... to handle the carry */ rev x7, x7 /* ... to handle the carry */
add x7, x7, #1 add x7, x7, #1
rev x7, x7 rev x7, x7
ins v4.d[0], x7 ins v4.d[0], x7
b .Lctrloop b .Lctrcarrydone
.Lctrhalfblock:
ld1 {v3.8b}, [x1]
eor v3.8b, v0.8b, v3.8b
st1 {v3.8b}, [x0]
.Lctrout:
FRAME_POP
ret
AES_ENDPROC(aes_ctr_encrypt) AES_ENDPROC(aes_ctr_encrypt)
.ltorg .ltorg

View File

@ -356,6 +356,7 @@ int crypto_register_alg(struct crypto_alg *alg)
struct crypto_larval *larval; struct crypto_larval *larval;
int err; int err;
alg->cra_flags &= ~CRYPTO_ALG_DEAD;
err = crypto_check_alg(alg); err = crypto_check_alg(alg);
if (err) if (err)
return err; return err;