zuc: eia refactoring

This commit is contained in:
Sun Yimin 2022-07-08 16:08:43 +08:00 committed by GitHub
parent 38db8cebd3
commit f51e5cca1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 140 additions and 67 deletions

View File

@ -8,18 +8,18 @@ import (
) )
const ( const (
chunk = 4 chunk = 16
) )
type ZUC128Mac struct { type ZUC128Mac struct {
zucState32 zucState32
initState zucState32 k0 [8]uint32
tagSize int
k0 uint32
t uint32 t uint32
x [chunk]byte x [chunk]byte
nx int nx int
len uint64 len uint64
tagSize int
initState zucState32
} }
// NewHash create hash for zuc-128 eia, with arguments key and iv. // NewHash create hash for zuc-128 eia, with arguments key and iv.
@ -79,36 +79,39 @@ func (m *ZUC128Mac) Size() int {
} }
func (m *ZUC128Mac) BlockSize() int { func (m *ZUC128Mac) BlockSize() int {
return 4 return chunk
} }
func (m *ZUC128Mac) Reset() { func (m *ZUC128Mac) Reset() {
m.k0 = 0
m.t = 0 m.t = 0
m.nx = 0 m.nx = 0
m.len = 0 m.len = 0
m.r1 = m.initState.r1 m.r1 = m.initState.r1
m.r2 = m.initState.r2 m.r2 = m.initState.r2
copy(m.lfsr[:], m.initState.lfsr[:]) copy(m.lfsr[:], m.initState.lfsr[:])
m.k0 = m.genKeyword() m.genKeywords(m.k0[:4])
} }
func (m *ZUC128Mac) block(p []byte) { func (m *ZUC128Mac) block(p []byte) {
var k64, t64 uint64
t64 = uint64(m.t) << 32
for len(p) >= chunk { for len(p) >= chunk {
w := binary.BigEndian.Uint32(p) m.genKeywords(m.k0[4:])
k1 := m.genKeyword() for i := 0; i < 4; i++ {
k64 = uint64(m.k0[i])<<32 | uint64(m.k0[i+1])
for i := 0; i < 32; i++ { w := binary.BigEndian.Uint32(p[i*4:])
for j := 0; j < 32; j++ {
if w&0x80000000 == 0x80000000 { if w&0x80000000 == 0x80000000 {
m.t ^= m.k0 t64 ^= k64
} }
w <<= 1 w <<= 1
m.k0 = (m.k0 << 1) | (k1 >> 31) k64 <<= 1
k1 <<= 1
} }
}
copy(m.k0[:4], m.k0[4:])
p = p[chunk:] p = p[chunk:]
} }
m.t = uint32(t64 >> 32)
} }
func (m *ZUC128Mac) Write(p []byte) (nn int, err error) { func (m *ZUC128Mac) Write(p []byte) (nn int, err error) {
@ -135,26 +138,49 @@ func (m *ZUC128Mac) Write(p []byte) (nn int, err error) {
} }
func (m *ZUC128Mac) checkSum(additionalBits int, b byte) [4]byte { func (m *ZUC128Mac) checkSum(additionalBits int, b byte) [4]byte {
if m.nx >= 4 { if m.nx >= chunk {
panic("m.nx >= 4") panic("m.nx >= 16")
} }
kIdx := 0
if m.nx > 0 || additionalBits > 0 { if m.nx > 0 || additionalBits > 0 {
var k64, t64 uint64
t64 = uint64(m.t) << 32
m.x[m.nx] = b m.x[m.nx] = b
w := binary.BigEndian.Uint32(m.x[:]) nRemainBits := 8*m.nx + additionalBits
k1 := m.genKeyword() if nRemainBits > 64 {
m.genKeywords(m.k0[4:6])
for i := 0; i < 8*m.nx+additionalBits; i++ { }
words := (nRemainBits + 31) / 32
for i := 0; i < words-1; i++ {
k64 = uint64(m.k0[i])<<32 | uint64(m.k0[i+1])
w := binary.BigEndian.Uint32(m.x[i*4:])
for j := 0; j < 32; j++ {
if w&0x80000000 == 0x80000000 { if w&0x80000000 == 0x80000000 {
m.t ^= m.k0 t64 ^= k64
} }
w <<= 1 w <<= 1
m.k0 = (m.k0 << 1) | (k1 >> 31) k64 <<= 1
k1 <<= 1
} }
} }
m.t ^= m.k0 nRemainBits -= (words - 1) * 32
k1 := m.genKeyword() kIdx = words - 1
m.t ^= k1 if nRemainBits > 0 {
k64 = uint64(m.k0[kIdx])<<32 | uint64(m.k0[kIdx+1])
w := binary.BigEndian.Uint32(m.x[(words-1)*4:])
for j := 0; j < nRemainBits; j++ {
if w&0x80000000 == 0x80000000 {
t64 ^= k64
}
w <<= 1
k64 <<= 1
}
m.k0[kIdx] = uint32(k64 >> 32)
m.k0[kIdx+1] = m.k0[kIdx+2]
}
m.t = uint32(t64 >> 32)
}
m.t ^= m.k0[kIdx]
m.t ^= m.k0[kIdx+1]
var digest [4]byte var digest [4]byte
binary.BigEndian.PutUint32(digest[:], m.t) binary.BigEndian.PutUint32(digest[:], m.t)

View File

@ -7,13 +7,13 @@ import (
type ZUC256Mac struct { type ZUC256Mac struct {
zucState32 zucState32
initState zucState32 k0 [8]uint32
tagSize int
k0 []uint32
t []uint32 t []uint32
x [chunk]byte x [chunk]byte
nx int nx int
len uint64 len uint64
tagSize int
initState zucState32
} }
// NewHash256 create hash for zuc-256 eia, with arguments key, iv and tagSize. // NewHash256 create hash for zuc-256 eia, with arguments key, iv and tagSize.
@ -36,7 +36,6 @@ func NewHash256(key, iv []byte, tagSize int) (*ZUC256Mac, error) {
} }
mac.tagSize = tagSize mac.tagSize = tagSize
mac.t = make([]uint32, mac.tagSize/4) mac.t = make([]uint32, mac.tagSize/4)
mac.k0 = make([]uint32, mac.tagSize/4)
switch k { switch k {
default: default:
return nil, fmt.Errorf("zuc/eia: invalid key size %d, expect 32 in bytes", k) return nil, fmt.Errorf("zuc/eia: invalid key size %d, expect 32 in bytes", k)
@ -81,31 +80,55 @@ func (m *ZUC256Mac) Reset() {
m.r2 = m.initState.r2 m.r2 = m.initState.r2
copy(m.lfsr[:], m.initState.lfsr[:]) copy(m.lfsr[:], m.initState.lfsr[:])
m.genKeywords(m.t) m.genKeywords(m.t)
m.genKeywords(m.k0) m.genKeywords(m.k0[:4])
} }
func (m *ZUC256Mac) block(p []byte) { func (m *ZUC256Mac) block(p []byte) {
var k64, t64 uint64
if m.tagSize == 4 {
t64 = uint64(m.t[0]) << 32
}
tagWords := m.tagSize / 4
for len(p) >= chunk { for len(p) >= chunk {
w := binary.BigEndian.Uint32(p) m.genKeywords(m.k0[4:])
k1 := m.genKeyword() for l := 0; l < 4; l++ {
w := binary.BigEndian.Uint32(p[l*4:])
switch m.tagSize {
case 4:
k64 = uint64(m.k0[l])<<32 | uint64(m.k0[l+1])
for j := 0; j < 32; j++ {
if w&0x80000000 == 0x80000000 {
t64 ^= k64
}
w <<= 1
k64 <<= 1
}
default:
k1 := m.k0[tagWords+l]
for i := 0; i < 32; i++ { for i := 0; i < 32; i++ {
if w&0x80000000 == 0x80000000 { if w&0x80000000 == 0x80000000 {
for j := 0; j < m.tagSize/4; j++ { for j := 0; j < tagWords; j++ {
m.t[j] ^= m.k0[j] m.t[j] ^= m.k0[j]
} }
} }
w <<= 1 w <<= 1
var j int var j int
for j = 0; j < m.tagSize/4-1; j++ { for j = 0; j < tagWords-1; j++ {
m.k0[j] = (m.k0[j] << 1) | (m.k0[j+1] >> 31) m.k0[j] = (m.k0[j] << 1) | (m.k0[j+1] >> 31)
} }
m.k0[j] = (m.k0[j] << 1) | (k1 >> 31) m.k0[j] = (m.k0[j] << 1) | (k1 >> 31)
k1 <<= 1 k1 <<= 1
} }
}
}
if tagWords != 4 {
copy(m.k0[:4], m.k0[4:])
}
p = p[chunk:] p = p[chunk:]
} }
if m.tagSize == 4 {
m.t[0] = uint32(t64 >> 32)
}
} }
func (m *ZUC256Mac) Write(p []byte) (nn int, err error) { func (m *ZUC256Mac) Write(p []byte) (nn int, err error) {
@ -132,15 +155,20 @@ func (m *ZUC256Mac) Write(p []byte) (nn int, err error) {
} }
func (m *ZUC256Mac) checkSum(additionalBits int, b byte) []byte { func (m *ZUC256Mac) checkSum(additionalBits int, b byte) []byte {
if m.nx >= 4 { if m.nx >= chunk {
panic("m.nx >= 4") panic("m.nx >= 16")
} }
kIdx := 0
if m.nx > 0 || additionalBits > 0 { if m.nx > 0 || additionalBits > 0 {
m.x[m.nx] = b m.x[m.nx] = b
w := binary.BigEndian.Uint32(m.x[:]) m.genKeywords(m.k0[4:])
k1 := m.genKeyword() nRemainBits := 8*m.nx + additionalBits
words := (nRemainBits + 31) / 32
for i := 0; i < 8*m.nx+additionalBits; i++ { for l := 0; l < words-1; l++ {
w := binary.BigEndian.Uint32(m.x[l*4:])
k1 := m.k0[m.tagSize/4+l]
for i := 0; i < 32; i++ {
if w&0x80000000 == 0x80000000 { if w&0x80000000 == 0x80000000 {
for j := 0; j < m.tagSize/4; j++ { for j := 0; j < m.tagSize/4; j++ {
m.t[j] ^= m.k0[j] m.t[j] ^= m.k0[j]
@ -155,10 +183,29 @@ func (m *ZUC256Mac) checkSum(additionalBits int, b byte) []byte {
k1 <<= 1 k1 <<= 1
} }
} }
nRemainBits -= (words - 1) * 32
kIdx = words - 1
if nRemainBits > 0 {
w := binary.BigEndian.Uint32(m.x[(words-1)*4:])
for i := 0; i < nRemainBits; i++ {
if w&0x80000000 == 0x80000000 {
for j := 0; j < m.tagSize/4; j++ {
m.t[j] ^= m.k0[j+kIdx]
}
}
w <<= 1
var j int
for j = 0; j < m.tagSize/4; j++ {
m.k0[j+kIdx] = (m.k0[j+kIdx] << 1) | (m.k0[kIdx+j+1] >> 31)
}
m.k0[j+kIdx] <<= 1
}
}
}
digest := make([]byte, m.tagSize) digest := make([]byte, m.tagSize)
for j := 0; j < m.tagSize/4; j++ { for j := 0; j < m.tagSize/4; j++ {
m.t[j] ^= m.k0[j] m.t[j] ^= m.k0[j+kIdx]
binary.BigEndian.PutUint32(digest[j*4:], m.t[j]) binary.BigEndian.PutUint32(digest[j*4:], m.t[j])
} }