zuc: reduce bounds checking

This commit is contained in:
Sun Yimin 2023-06-15 16:47:50 +08:00 committed by GitHub
parent 79f0fb6b0d
commit 008e826fdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 31 deletions

View File

@ -62,7 +62,7 @@ var zuc256_d0 = [16]byte{
0x40, 0x40, 0x40, 0x40, 0x40, 0x52, 0x10, 0x30,
}
var zuc256_d = [][16]byte{
var zuc256_d = [3][16]byte{
{
0x22, 0x2F, 0x25, 0x2A, 0x6D, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x52, 0x10, 0x30,
@ -113,15 +113,16 @@ func (s *zucState32) f32() uint32 {
return w
}
func rotateLeft31(x uint32, k int) uint32 {
return (x<<k | x>>(31-k)) & 0x7FFFFFFF
}
func add31(x, y uint32) uint32 {
resut := x + y
return (resut & 0x7FFFFFFF) + (resut >> 31)
}
/*
func rotateLeft31(x uint32, k int) uint32 {
return (x<<k | x>>(31-k)) & 0x7FFFFFFF
}
func add31(x, y uint32) uint32 {
resut := x + y
return (resut & 0x7FFFFFFF) + (resut >> 31)
}
*/
func (s *zucState32) enterInitMode(w uint32) {
v := uint64(s.lfsr[15])<<15 + uint64(s.lfsr[13])<<17 + uint64(s.lfsr[10])<<21 + uint64(s.lfsr[4])<<20 + uint64(s.lfsr[0])<<8 + uint64(s.lfsr[0]) + uint64(w)
v = (v & 0x7FFFFFFF) + (v >> 31)
@ -146,12 +147,27 @@ func makeFieldValue4(a, b, c, d uint32) uint32 {
}
func (s *zucState32) loadKeyIV16(key, iv []byte) {
for i := 0; i < 16; i++ {
s.lfsr[i] = makeFieldValue3(uint32(key[i]), kd[i], uint32(iv[i]))
}
s.lfsr[15] = makeFieldValue3(uint32(key[15]), kd[15], uint32(iv[15]))
s.lfsr[0] = makeFieldValue3(uint32(key[0]), kd[0], uint32(iv[0]))
s.lfsr[1] = makeFieldValue3(uint32(key[1]), kd[1], uint32(iv[1]))
s.lfsr[2] = makeFieldValue3(uint32(key[2]), kd[2], uint32(iv[2]))
s.lfsr[3] = makeFieldValue3(uint32(key[3]), kd[3], uint32(iv[3]))
s.lfsr[4] = makeFieldValue3(uint32(key[4]), kd[4], uint32(iv[4]))
s.lfsr[5] = makeFieldValue3(uint32(key[5]), kd[5], uint32(iv[5]))
s.lfsr[6] = makeFieldValue3(uint32(key[6]), kd[6], uint32(iv[6]))
s.lfsr[7] = makeFieldValue3(uint32(key[7]), kd[7], uint32(iv[7]))
s.lfsr[8] = makeFieldValue3(uint32(key[8]), kd[8], uint32(iv[8]))
s.lfsr[9] = makeFieldValue3(uint32(key[9]), kd[9], uint32(iv[9]))
s.lfsr[10] = makeFieldValue3(uint32(key[10]), kd[10], uint32(iv[10]))
s.lfsr[11] = makeFieldValue3(uint32(key[11]), kd[11], uint32(iv[11]))
s.lfsr[12] = makeFieldValue3(uint32(key[12]), kd[12], uint32(iv[12]))
s.lfsr[13] = makeFieldValue3(uint32(key[13]), kd[13], uint32(iv[13]))
s.lfsr[14] = makeFieldValue3(uint32(key[14]), kd[14], uint32(iv[14]))
}
func (s *zucState32) loadKeyIV32(key, iv, d []byte) {
_ = iv[22]
_ = key[31]
iv17 := iv[17] >> 2
iv18 := ((iv[17] & 0x3) << 4) | (iv[18] >> 4)
iv19 := ((iv[18] & 0xf) << 2) | (iv[19] >> 6)
@ -160,6 +176,7 @@ func (s *zucState32) loadKeyIV32(key, iv, d []byte) {
iv22 := ((iv[20] & 0x3) << 4) | (iv[21] >> 4)
iv23 := ((iv[21] & 0xf) << 2) | (iv[22] >> 6)
iv24 := iv[22] & 0x3f
s.lfsr[15] = makeFieldValue4(uint32(key[15]), uint32(d[15]|(key[31]&0x0f)), uint32(key[30]), uint32(key[29]))
s.lfsr[0] = makeFieldValue4(uint32(key[0]), uint32(d[0]), uint32(key[21]), uint32(key[16]))
s.lfsr[1] = makeFieldValue4(uint32(key[1]), uint32(d[1]), uint32(key[22]), uint32(key[17]))
s.lfsr[2] = makeFieldValue4(uint32(key[2]), uint32(d[2]), uint32(key[23]), uint32(key[18]))
@ -175,7 +192,6 @@ func (s *zucState32) loadKeyIV32(key, iv, d []byte) {
s.lfsr[12] = makeFieldValue4(uint32(key[12]), uint32(d[12]|iv24), uint32(iv[7]), uint32(iv[14]))
s.lfsr[13] = makeFieldValue4(uint32(key[13]), uint32(d[13]), uint32(iv[15]), uint32(iv[8]))
s.lfsr[14] = makeFieldValue4(uint32(key[14]), uint32(d[14]|(key[31]>>4)), uint32(iv[16]), uint32(iv[9]))
s.lfsr[15] = makeFieldValue4(uint32(key[15]), uint32(d[15]|(key[31]&0x0f)), uint32(key[30]), uint32(key[29]))
}
func newZUCState(key, iv []byte) (*zucState32, error) {
@ -221,3 +237,11 @@ func (s *zucState32) genKeywords(words []uint32) {
}
genKeyStream(words, s)
}
func genKeyStreamRev32(keyStream []byte, pState *zucState32) {
for len(keyStream) >= 4 {
z := genKeyword(pState)
binary.BigEndian.PutUint32(keyStream, z)
keyStream = keyStream[4:]
}
}

View File

@ -1,4 +1,4 @@
//go:build !amd64 && !arm64 || purego
//go:build (!amd64 && !arm64) || purego
// +build !amd64,!arm64 purego
package zuc

View File

@ -28,22 +28,15 @@ func NewEEACipher(key []byte, count, bearer, direction uint32) (cipher.Stream, e
func xorKeyStreamGeneric(c *zucState32, dst, src []byte) {
words := (len(src) + 3) / 4
rounds := words / RoundWords
var keyWords [RoundWords]uint32
var keyBytes [RoundWords * 4]byte
for i := 0; i < rounds; i++ {
c.genKeywords(keyWords[:])
for j := 0; j < RoundWords; j++ {
binary.BigEndian.PutUint32(keyBytes[j*4:], keyWords[j])
}
genKeyStreamRev32(keyBytes[:], c)
subtle.XORBytes(dst, src, keyBytes[:])
dst = dst[RoundWords*4:]
src = src[RoundWords*4:]
}
if rounds*RoundWords < words {
c.genKeywords(keyWords[:words-rounds*RoundWords])
for j := 0; j < words-rounds*RoundWords; j++ {
binary.BigEndian.PutUint32(keyBytes[j*4:], keyWords[j])
}
genKeyStreamRev32(keyBytes[:4*(words-rounds*RoundWords)], c)
subtle.XORBytes(dst, src, keyBytes[:])
}
}

View File

@ -98,14 +98,33 @@ func blockGeneric(m *ZUC128Mac, p []byte) {
t64 = uint64(m.t) << 32
for len(p) >= chunk {
m.genKeywords(m.k0[4:])
for i := 0; i < 4; i++ {
k64 = uint64(m.k0[i])<<32 | uint64(m.k0[i+1])
w := binary.BigEndian.Uint32(p[i*4:])
for j := 0; j < 32; j++ {
t64 ^= ^(uint64(w>>31) - 1) & k64
w <<= 1
k64 <<= 1
}
k64 = uint64(m.k0[0])<<32 | uint64(m.k0[1])
w := binary.BigEndian.Uint32(p[0:4])
for j := 0; j < 32; j++ {
t64 ^= ^(uint64(w>>31) - 1) & k64
w <<= 1
k64 <<= 1
}
k64 = uint64(m.k0[1])<<32 | uint64(m.k0[2])
w = binary.BigEndian.Uint32(p[4:8])
for j := 0; j < 32; j++ {
t64 ^= ^(uint64(w>>31) - 1) & k64
w <<= 1
k64 <<= 1
}
k64 = uint64(m.k0[2])<<32 | uint64(m.k0[3])
w = binary.BigEndian.Uint32(p[8:12])
for j := 0; j < 32; j++ {
t64 ^= ^(uint64(w>>31) - 1) & k64
w <<= 1
k64 <<= 1
}
k64 = uint64(m.k0[3])<<32 | uint64(m.k0[4])
w = binary.BigEndian.Uint32(p[12:16])
for j := 0; j < 32; j++ {
t64 ^= ^(uint64(w>>31) - 1) & k64
w <<= 1
k64 <<= 1
}
copy(m.k0[:4], m.k0[4:])
p = p[chunk:]