From 772beacfb0c07b06c2517df75c394eabdfba484e Mon Sep 17 00:00:00 2001 From: Emman Date: Tue, 19 Apr 2022 17:42:21 +0800 Subject: [PATCH] support zuc256 for eea --- zuc/core.go | 82 ++++++++++++++++++++++++++++++++++++++++++------ zuc/core_test.go | 60 +++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 10 deletions(-) diff --git a/zuc/core.go b/zuc/core.go index 5e5fa38..68f810c 100644 --- a/zuc/core.go +++ b/zuc/core.go @@ -50,6 +50,12 @@ var sbox1 = [256]byte{ 0x64, 0xbe, 0x85, 0x9b, 0x2f, 0x59, 0x8a, 0xd7, 0xb0, 0x25, 0xac, 0xaf, 0x12, 0x03, 0xe2, 0xf2, } +// constant D-0 for ZUC-256 +var zuc256_d0 = [16]byte{ + 0x22, 0x2F, 0x24, 0x2A, 0x6D, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x52, 0x10, 0x30, +} + type zucState32 struct { lfsr [16]uint32 // linear feedback shift register r1 uint32 @@ -114,17 +120,64 @@ func (s *zucState32) enterWorkMode() { s.enterInitMode(0) } -func newZUCState(key, iv []byte) (*zucState32, error) { - if len(key) != 16 { - return nil, fmt.Errorf("zuc: invalid key size %d, expect 16 in bytes", len(key)) - } - if len(iv) != 16 { - return nil, fmt.Errorf("zuc: invalid iv size %d, expect 16 in bytes", len(iv)) - } - state := &zucState32{} - // loading key and iv +func makeFieldValue3(a, b, c uint32) uint32 { + return (a << 23) | (b << 8) | c +} + +func makeFieldValue4(a, b, c, d uint32) uint32 { + return (a << 23) | (b << 16) | (c << 8) | d +} + +func (s *zucState32) loadKeyIV16(key, iv []byte) { for i := 0; i < 16; i++ { - state.lfsr[i] = (uint32(key[i]) << 23) | (kd[i] << 8) | uint32(iv[i]) + s.lfsr[i] = makeFieldValue3(uint32(key[i]), kd[i], uint32(iv[i])) + } +} + +func (s *zucState32) loadKeyIV32(key, iv, d []byte) { + iv17 := iv[17] >> 2 + iv18 := ((iv[17] & 0x3) << 4) | (iv[18] >> 4) + iv19 := ((iv[18] & 0xf) << 2) | (iv[19] >> 6) + iv20 := iv[19] & 0x3f + iv21 := iv[20] >> 2 + iv22 := ((iv[20] & 0x3) << 4) | (iv[21] >> 4) + iv23 := ((iv[21] & 0xf) << 2) | (iv[22] >> 6) + iv24 := iv[22] & 0x3f + 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])) + s.lfsr[3] = makeFieldValue4(uint32(key[3]), uint32(d[3]), uint32(key[24]), uint32(key[19])) + s.lfsr[4] = makeFieldValue4(uint32(key[4]), uint32(d[4]), uint32(key[25]), uint32(key[20])) + s.lfsr[5] = makeFieldValue4(uint32(iv[0]), uint32(d[5]|iv17), uint32(key[5]), uint32(key[26])) + s.lfsr[6] = makeFieldValue4(uint32(iv[1]), uint32(d[6]|iv18), uint32(key[6]), uint32(key[27])) + s.lfsr[7] = makeFieldValue4(uint32(iv[10]), uint32(d[7]|iv19), uint32(key[7]), uint32(iv[2])) + s.lfsr[8] = makeFieldValue4(uint32(key[8]), uint32(d[8]|iv20), uint32(iv[3]), uint32(iv[11])) + s.lfsr[9] = makeFieldValue4(uint32(key[9]), uint32(d[9]|iv21), uint32(iv[12]), uint32(iv[4])) + s.lfsr[10] = makeFieldValue4(uint32(iv[5]), uint32(d[10]|iv22), uint32(key[10]), uint32(key[28])) + s.lfsr[11] = makeFieldValue4(uint32(key[11]), uint32(d[11]|iv23), uint32(iv[6]), uint32(iv[13])) + 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) { + k := len(key) + ivLen := len(iv) + state := &zucState32{} + switch k { + default: + return nil, fmt.Errorf("zuc: invalid key size %d, we support 16/32 now", k) + case 16: // ZUC-128 + if ivLen != 16 { + return nil, fmt.Errorf("zuc: invalid iv size %d, expect 16 in bytes", ivLen) + } + state.loadKeyIV16(key, iv) + case 32: // ZUC-256 + if ivLen != 23 { + return nil, fmt.Errorf("zuc: invalid iv size %d, expect 23 in bytes", ivLen) + } + state.loadKeyIV32(key, iv, zuc256_d0[:]) } // initialization @@ -148,3 +201,12 @@ func (s *zucState32) genKeyword() uint32 { s.enterWorkMode() return z } + +func (s *zucState32) genKeywords(words []uint32) { + if len(words) == 0 { + return + } + for i := 0; i < len(words); i++ { + words[i] = s.genKeyword() + } +} diff --git a/zuc/core_test.go b/zuc/core_test.go index cf312bf..df7b83b 100644 --- a/zuc/core_test.go +++ b/zuc/core_test.go @@ -1,6 +1,7 @@ package zuc import ( + "reflect" "testing" ) @@ -39,3 +40,62 @@ func Test_genKeyword_case3(t *testing.T) { t.Errorf("expected=%x, result=%x\n", 0x3279c419, z2) } } + +var zuc256Tests = []struct { + key []byte + iv []byte + expectedKeys []uint32 +}{ + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + []uint32{ + 0x58d03ad6, 0x2e032ce2, 0xdafc683a, 0x39bdcb03, 0x52a2bc67, + 0xf1b7de74, 0x163ce3a1, 0x01ef5558, 0x9639d75b, 0x95fa681b, + 0x7f090df7, 0x56391ccc, 0x903b7612, 0x744d544c, 0x17bc3fad, + 0x8b163b08, 0x21787c0b, 0x97775bb8, 0x4943c6bb, 0xe8ad8afd, + }, + }, + { + []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + []uint32{ + 0x3356cbae, 0xd1a1c18b, 0x6baa4ffe, 0x343f777c, 0x9e15128f, + 0x251ab65b, 0x949f7b26, 0xef7157f2, 0x96dd2fa9, 0xdf95e3ee, + 0x7a5be02e, 0xc32ba585, 0x505af316, 0xc2f9ded2, 0x7cdbd935, + 0xe441ce11, 0x15fd0a80, 0xbb7aef67, 0x68989416, 0xb8fac8c2, + }, + }, +} + +func Test_ZUC256(t *testing.T) { + for i, test := range zuc256Tests { + c, err := newZUCState(test.key, test.iv) + if err != nil { + t.Error(err) + } + words := make([]uint32, 20) + c.genKeywords(words) + if !reflect.DeepEqual(words, test.expectedKeys) { + t.Errorf("#%d: wrong output: got %x, expected %x", i, words, test.expectedKeys) + } + } +}