zuc: eea XORKeyStreamAt fix issue

This commit is contained in:
Sun Yimin 2024-12-05 17:32:24 +08:00 committed by GitHub
parent fcd1aa22d2
commit 379396b688
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 17 deletions

View File

@ -10,6 +10,7 @@ import (
const ( const (
RoundWords = 32 RoundWords = 32
WordSize = 4 WordSize = 4
WordMask = WordSize - 1
RoundBytes = RoundWords * WordSize RoundBytes = RoundWords * WordSize
) )
@ -86,8 +87,7 @@ func (c *eea) XORKeyStream(dst, src []byte) {
src = src[RoundBytes:] src = src[RoundBytes:]
} }
if len(src) > 0 { if len(src) > 0 {
words := (len(src) + WordSize - 1) / WordSize byteLen := (len(src) + WordMask) &^ WordMask
byteLen := WordSize * words
genKeyStreamRev32(keyBytes[:byteLen], &c.zucState32) genKeyStreamRev32(keyBytes[:byteLen], &c.zucState32)
n := subtle.XORBytes(dst, src, keyBytes[:]) n := subtle.XORBytes(dst, src, keyBytes[:])
// save remaining key bytes // save remaining key bytes
@ -115,38 +115,44 @@ func (c *eea) XORKeyStreamAt(dst, src []byte, offset uint64) {
if offset < c.used { if offset < c.used {
// reset the state to the initial state // reset the state to the initial state
c.reset() c.reset()
} else if offset == c.used { }
if offset == c.used {
c.XORKeyStream(dst, src) c.XORKeyStream(dst, src)
return return
} }
diff := offset - c.used offsetDiff := offset - c.used
if diff <= uint64(c.xLen) { if offsetDiff <= uint64(c.xLen) {
c.xLen -= int(diff) c.xLen -= int(offsetDiff)
c.used += diff c.used += offsetDiff
c.XORKeyStream(dst, src) c.XORKeyStream(dst, src)
return return
} }
// consumed all remaining key bytes first
c.used += uint64(c.xLen)
offsetDiff -= uint64(c.xLen)
c.xLen = 0
// forward the state to the offset // forward the state to the offset
// this part can be optimized by a little bit
stepLen := uint64(RoundBytes) stepLen := uint64(RoundBytes)
var keys [RoundWords]uint32 var keyStream [RoundWords]uint32
for ; diff >= uint64(stepLen); diff -= stepLen { for ; offsetDiff >= uint64(stepLen); offsetDiff -= stepLen {
genKeyStream(keys[:], &c.zucState32) genKeyStream(keyStream[:], &c.zucState32)
c.used += stepLen c.used += stepLen
} }
if diff > 0 { if offsetDiff > 0 {
words := (diff + WordSize - 1) / WordSize numWords := (offsetDiff + WordMask) / WordSize
genKeyStream(keys[:words], &c.zucState32) genKeyStream(keyStream[:numWords], &c.zucState32)
partiallyUsed := int(diff % WordSize) partiallyUsed := int(offsetDiff & WordMask)
c.used += words * WordSize c.used += numWords * WordSize
if partiallyUsed > 0 { if partiallyUsed > 0 {
// save remaining key bytes (less than 4 bytes) // save remaining key bytes (less than 4 bytes)
c.xLen = WordSize - partiallyUsed c.xLen = WordSize - partiallyUsed
c.used -= uint64(c.xLen) c.used -= uint64(c.xLen)
byteorder.BEPutUint32(c.x[:], keys[words-1]) byteorder.BEPutUint32(c.x[:], keyStream[numWords-1])
copy(c.x[:], c.x[partiallyUsed:]) copy(c.x[:], c.x[partiallyUsed:])
} }
} }

View File

@ -113,6 +113,13 @@ func TestXORStreamAt(t *testing.T) {
t.Errorf("expected=%x, result=%x\n", expected[32:64], dst[32:64]) t.Errorf("expected=%x, result=%x\n", expected[32:64], dst[32:64])
} }
} }
for i := 1; i < 4; i++ {
c.XORKeyStreamAt(dst[:i], src[:i], 0)
c.XORKeyStreamAt(dst[32:64], src[32:64], 32)
if !bytes.Equal(dst[32:64], expected[32:64]) {
t.Errorf("expected=%x, result=%x\n", expected[32:64], dst[32:64])
}
}
}) })
t.Run("Jump and forward (skipped keys more than 128)", func(t *testing.T) { t.Run("Jump and forward (skipped keys more than 128)", func(t *testing.T) {