mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 12:16:20 +08:00
refactoring, rename internal packages
This commit is contained in:
parent
b96e51e3ff
commit
1710bdff4a
@ -8,8 +8,8 @@ import (
|
|||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -112,14 +112,14 @@ func (c *ccm) deriveCounter(counter *[ccmBlockSize]byte, nonce []byte) {
|
|||||||
|
|
||||||
func (c *ccm) cmac(out, data []byte) {
|
func (c *ccm) cmac(out, data []byte) {
|
||||||
for len(data) >= ccmBlockSize {
|
for len(data) >= ccmBlockSize {
|
||||||
xor.XorBytes(out, out, data)
|
subtle.XORBytes(out, out, data)
|
||||||
c.cipher.Encrypt(out, out)
|
c.cipher.Encrypt(out, out)
|
||||||
data = data[ccmBlockSize:]
|
data = data[ccmBlockSize:]
|
||||||
}
|
}
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
var block [ccmBlockSize]byte
|
var block [ccmBlockSize]byte
|
||||||
copy(block[:], data)
|
copy(block[:], data)
|
||||||
xor.XorBytes(out, out, data)
|
subtle.XORBytes(out, out, data)
|
||||||
c.cipher.Encrypt(out, out)
|
c.cipher.Encrypt(out, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +168,7 @@ func (c *ccm) auth(nonce, plaintext, additionalData []byte, tagMask *[ccmBlockSi
|
|||||||
if len(plaintext) > 0 {
|
if len(plaintext) > 0 {
|
||||||
c.cmac(out[:], plaintext)
|
c.cmac(out[:], plaintext)
|
||||||
}
|
}
|
||||||
xor.XorWords(out[:], out[:], tagMask[:])
|
subtle.XORBytes(out[:], out[:], tagMask[:])
|
||||||
return out[:c.tagSize]
|
return out[:c.tagSize]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,8 +179,8 @@ func (c *ccm) Seal(dst, nonce, plaintext, data []byte) []byte {
|
|||||||
if uint64(len(plaintext)) > uint64(c.MaxLength()) {
|
if uint64(len(plaintext)) > uint64(c.MaxLength()) {
|
||||||
panic("cipher: message too large for CCM")
|
panic("cipher: message too large for CCM")
|
||||||
}
|
}
|
||||||
ret, out := subtle.SliceForAppend(dst, len(plaintext)+c.tagSize)
|
ret, out := alias.SliceForAppend(dst, len(plaintext)+c.tagSize)
|
||||||
if subtle.InexactOverlap(out, plaintext) {
|
if alias.InexactOverlap(out, plaintext) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,8 +225,8 @@ func (c *ccm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
|||||||
c.deriveCounter(&counter, nonce)
|
c.deriveCounter(&counter, nonce)
|
||||||
c.cipher.Encrypt(tagMask[:], counter[:])
|
c.cipher.Encrypt(tagMask[:], counter[:])
|
||||||
|
|
||||||
ret, out := subtle.SliceForAppend(dst, len(ciphertext))
|
ret, out := alias.SliceForAppend(dst, len(ciphertext))
|
||||||
if subtle.InexactOverlap(out, ciphertext) {
|
if alias.InexactOverlap(out, ciphertext) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const GF128_FDBK byte = 0x87
|
const GF128_FDBK byte = 0x87
|
||||||
@ -89,7 +89,7 @@ func (c *xts) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
|
|||||||
if len(plaintext) < blockSize {
|
if len(plaintext) < blockSize {
|
||||||
panic("xts: plaintext length is smaller than the block size")
|
panic("xts: plaintext length is smaller than the block size")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(ciphertext[:len(plaintext)], plaintext) {
|
if alias.InexactOverlap(ciphertext[:len(plaintext)], plaintext) {
|
||||||
panic("xts: invalid buffer overlap")
|
panic("xts: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,18 +112,18 @@ func (c *xts) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
|
|||||||
copy(tweaks[blockSize*i:], tweak[:])
|
copy(tweaks[blockSize*i:], tweak[:])
|
||||||
mul2(tweak)
|
mul2(tweak)
|
||||||
}
|
}
|
||||||
xor.XorBytes(ciphertext, plaintext, tweaks)
|
subtle.XORBytes(ciphertext, plaintext, tweaks)
|
||||||
concCipher.EncryptBlocks(ciphertext, ciphertext)
|
concCipher.EncryptBlocks(ciphertext, ciphertext)
|
||||||
xor.XorBytes(ciphertext, ciphertext, tweaks)
|
subtle.XORBytes(ciphertext, ciphertext, tweaks)
|
||||||
plaintext = plaintext[batchSize:]
|
plaintext = plaintext[batchSize:]
|
||||||
lastCiphertext = ciphertext[batchSize-blockSize:]
|
lastCiphertext = ciphertext[batchSize-blockSize:]
|
||||||
ciphertext = ciphertext[batchSize:]
|
ciphertext = ciphertext[batchSize:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for len(plaintext) >= blockSize {
|
for len(plaintext) >= blockSize {
|
||||||
xor.XorBytes(ciphertext, plaintext, tweak[:])
|
subtle.XORBytes(ciphertext, plaintext, tweak[:])
|
||||||
c.k1.Encrypt(ciphertext, ciphertext)
|
c.k1.Encrypt(ciphertext, ciphertext)
|
||||||
xor.XorBytes(ciphertext, ciphertext, tweak[:])
|
subtle.XORBytes(ciphertext, ciphertext, tweak[:])
|
||||||
plaintext = plaintext[blockSize:]
|
plaintext = plaintext[blockSize:]
|
||||||
lastCiphertext = ciphertext
|
lastCiphertext = ciphertext
|
||||||
ciphertext = ciphertext[blockSize:]
|
ciphertext = ciphertext[blockSize:]
|
||||||
@ -139,11 +139,11 @@ func (c *xts) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) {
|
|||||||
//Steal ciphertext to complete the block
|
//Steal ciphertext to complete the block
|
||||||
copy(x[remain:], lastCiphertext[remain:blockSize])
|
copy(x[remain:], lastCiphertext[remain:blockSize])
|
||||||
//Merge the tweak into the input block
|
//Merge the tweak into the input block
|
||||||
xor.XorBytes(x[:], x[:], tweak[:])
|
subtle.XORBytes(x[:], x[:], tweak[:])
|
||||||
//Encrypt the final block using K1
|
//Encrypt the final block using K1
|
||||||
c.k1.Encrypt(x[:], x[:])
|
c.k1.Encrypt(x[:], x[:])
|
||||||
//Merge the tweak into the output block
|
//Merge the tweak into the output block
|
||||||
xor.XorBytes(lastCiphertext, x[:], tweak[:])
|
subtle.XORBytes(lastCiphertext, x[:], tweak[:])
|
||||||
}
|
}
|
||||||
tweakPool.Put(tweak)
|
tweakPool.Put(tweak)
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ func (c *xts) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
|
|||||||
if len(ciphertext) < blockSize {
|
if len(ciphertext) < blockSize {
|
||||||
panic("xts: ciphertext length is smaller than the block size")
|
panic("xts: ciphertext length is smaller than the block size")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) {
|
if alias.InexactOverlap(plaintext[:len(ciphertext)], ciphertext) {
|
||||||
panic("xts: invalid buffer overlap")
|
panic("xts: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,18 +179,18 @@ func (c *xts) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
|
|||||||
copy(tweaks[blockSize*i:], tweak[:])
|
copy(tweaks[blockSize*i:], tweak[:])
|
||||||
mul2(tweak)
|
mul2(tweak)
|
||||||
}
|
}
|
||||||
xor.XorBytes(plaintext, ciphertext, tweaks)
|
subtle.XORBytes(plaintext, ciphertext, tweaks)
|
||||||
concCipher.DecryptBlocks(plaintext, plaintext)
|
concCipher.DecryptBlocks(plaintext, plaintext)
|
||||||
xor.XorBytes(plaintext, plaintext, tweaks)
|
subtle.XORBytes(plaintext, plaintext, tweaks)
|
||||||
plaintext = plaintext[batchSize:]
|
plaintext = plaintext[batchSize:]
|
||||||
ciphertext = ciphertext[batchSize:]
|
ciphertext = ciphertext[batchSize:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for len(ciphertext) >= 2*blockSize {
|
for len(ciphertext) >= 2*blockSize {
|
||||||
xor.XorBytes(plaintext, ciphertext, tweak[:])
|
subtle.XORBytes(plaintext, ciphertext, tweak[:])
|
||||||
c.k1.Decrypt(plaintext, plaintext)
|
c.k1.Decrypt(plaintext, plaintext)
|
||||||
xor.XorBytes(plaintext, plaintext, tweak[:])
|
subtle.XORBytes(plaintext, plaintext, tweak[:])
|
||||||
plaintext = plaintext[blockSize:]
|
plaintext = plaintext[blockSize:]
|
||||||
ciphertext = ciphertext[blockSize:]
|
ciphertext = ciphertext[blockSize:]
|
||||||
|
|
||||||
@ -203,9 +203,9 @@ func (c *xts) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
|
|||||||
var tt [blockSize]byte
|
var tt [blockSize]byte
|
||||||
copy(tt[:], tweak[:])
|
copy(tt[:], tweak[:])
|
||||||
mul2(&tt)
|
mul2(&tt)
|
||||||
xor.XorBytes(x[:], ciphertext, tt[:])
|
subtle.XORBytes(x[:], ciphertext, tt[:])
|
||||||
c.k1.Decrypt(x[:], x[:])
|
c.k1.Decrypt(x[:], x[:])
|
||||||
xor.XorBytes(plaintext, x[:], tt[:])
|
subtle.XORBytes(plaintext, x[:], tt[:])
|
||||||
|
|
||||||
//Retrieve the length of the final block
|
//Retrieve the length of the final block
|
||||||
remain -= blockSize
|
remain -= blockSize
|
||||||
@ -220,9 +220,9 @@ func (c *xts) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) {
|
|||||||
//The last block contains exactly 128 bits
|
//The last block contains exactly 128 bits
|
||||||
copy(x[:], ciphertext)
|
copy(x[:], ciphertext)
|
||||||
}
|
}
|
||||||
xor.XorBytes(x[:], x[:], tweak[:])
|
subtle.XORBytes(x[:], x[:], tweak[:])
|
||||||
c.k1.Decrypt(x[:], x[:])
|
c.k1.Decrypt(x[:], x[:])
|
||||||
xor.XorBytes(plaintext, x[:], tweak[:])
|
subtle.XORBytes(plaintext, x[:], tweak[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
tweakPool.Put(tweak)
|
tweakPool.Put(tweak)
|
||||||
|
42
internal/alias/alias_test.go
Normal file
42
internal/alias/alias_test.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package alias
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
var a, b [100]byte
|
||||||
|
|
||||||
|
var aliasingTests = []struct {
|
||||||
|
x, y []byte
|
||||||
|
anyOverlap, inexactOverlap bool
|
||||||
|
}{
|
||||||
|
{a[:], b[:], false, false},
|
||||||
|
{a[:], b[:0], false, false},
|
||||||
|
{a[:], b[:50], false, false},
|
||||||
|
{a[40:50], a[50:60], false, false},
|
||||||
|
{a[40:50], a[60:70], false, false},
|
||||||
|
{a[:51], a[50:], true, true},
|
||||||
|
{a[:], a[:], true, false},
|
||||||
|
{a[:50], a[:60], true, false},
|
||||||
|
{a[:], nil, false, false},
|
||||||
|
{nil, nil, false, false},
|
||||||
|
{a[:], a[:0], false, false},
|
||||||
|
{a[:10], a[:10:20], true, false},
|
||||||
|
{a[:10], a[5:10:20], true, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) {
|
||||||
|
any := AnyOverlap(x, y)
|
||||||
|
if any != anyOverlap {
|
||||||
|
t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any)
|
||||||
|
}
|
||||||
|
inexact := InexactOverlap(x, y)
|
||||||
|
if inexact != inexactOverlap {
|
||||||
|
t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAliasing(t *testing.T) {
|
||||||
|
for i, tt := range aliasingTests {
|
||||||
|
testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap)
|
||||||
|
testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap)
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package subtle
|
package alias
|
||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
20
internal/subtle/xor.go
Normal file
20
internal/subtle/xor.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package subtle
|
||||||
|
|
||||||
|
// XORBytes sets dst[i] = x[i] ^ y[i] for all i < n = min(len(x), len(y)),
|
||||||
|
// returning n, the number of bytes written to dst.
|
||||||
|
// If dst does not have length at least n,
|
||||||
|
// XORBytes panics without writing anything to dst.
|
||||||
|
func XORBytes(dst, x, y []byte) int {
|
||||||
|
n := len(x)
|
||||||
|
if len(y) < n {
|
||||||
|
n = len(y)
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if n > len(dst) {
|
||||||
|
panic("subtle.XORBytes: dst too short")
|
||||||
|
}
|
||||||
|
xorBytes(&dst[0], &x[0], &y[0], n) // arch-specific
|
||||||
|
return n
|
||||||
|
}
|
11
internal/subtle/xor_amd64.go
Normal file
11
internal/subtle/xor_amd64.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
|
//go:build amd64 && !generic
|
||||||
|
// +build amd64,!generic
|
||||||
|
|
||||||
|
package subtle
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func xorBytes(dst, a, b *byte, n int)
|
@ -1,13 +1,14 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
//go:build amd64 && !generic
|
//go:build amd64 && !generic
|
||||||
// +build amd64,!generic
|
// +build amd64,!generic
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
// func xorBytesSSE2(dst, a, b *byte, n int)
|
// func xorBytes(dst, a, b *byte, n int)
|
||||||
TEXT ·xorBytesSSE2(SB), NOSPLIT, $0
|
TEXT ·xorBytes(SB), NOSPLIT, $0
|
||||||
MOVQ dst+0(FP), BX
|
MOVQ dst+0(FP), BX
|
||||||
MOVQ a+8(FP), SI
|
MOVQ a+8(FP), SI
|
||||||
MOVQ b+16(FP), CX
|
MOVQ b+16(FP), CX
|
11
internal/subtle/xor_arm64.go
Normal file
11
internal/subtle/xor_arm64.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
|
//go:build arm64 && !generic
|
||||||
|
// +build arm64,!generic
|
||||||
|
|
||||||
|
package subtle
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func xorBytes(dst, a, b *byte, n int)
|
@ -1,13 +1,14 @@
|
|||||||
// Copyright 2020 The Go Authors. All rights reserved.
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
//go:build arm64 && !generic
|
//go:build arm64 && !generic
|
||||||
// +build arm64,!generic
|
// +build arm64,!generic
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
// func xorBytesARM64(dst, a, b *byte, n int)
|
// func xorBytes(dst, a, b *byte, n int)
|
||||||
TEXT ·xorBytesARM64(SB), NOSPLIT|NOFRAME, $0
|
TEXT ·xorBytes(SB), NOSPLIT|NOFRAME, $0
|
||||||
MOVD dst+0(FP), R0
|
MOVD dst+0(FP), R0
|
||||||
MOVD a+8(FP), R1
|
MOVD a+8(FP), R1
|
||||||
MOVD b+16(FP), R2
|
MOVD b+16(FP), R2
|
@ -1,27 +1,25 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
// Copyright 2013 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
//go:build !amd64 && !arm64 || generic
|
//go:build !amd64 && !arm64 || generic
|
||||||
// +build !amd64,!arm64 generic
|
// +build !amd64,!arm64 generic
|
||||||
|
|
||||||
package xor
|
package subtle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// xorBytes xors the bytes in a and b. The destination should have enough
|
const wordSize = int(unsafe.Sizeof(uintptr(0)))
|
||||||
// space, otherwise xorBytes will panic. Returns the number of bytes xor'd.
|
|
||||||
func XorBytes(dst, a, b []byte) int {
|
|
||||||
n := len(a)
|
|
||||||
if len(b) < n {
|
|
||||||
n = len(b)
|
|
||||||
}
|
|
||||||
if n == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const supportsUnaligned = runtime.GOARCH == "386" ||
|
||||||
|
runtime.GOARCH == "ppc64" ||
|
||||||
|
runtime.GOARCH == "ppc64le" ||
|
||||||
|
runtime.GOARCH == "s390x"
|
||||||
|
|
||||||
|
func xorBytes(dst, a, b []byte, n int) int {
|
||||||
switch {
|
switch {
|
||||||
case supportsUnaligned:
|
case supportsUnaligned:
|
||||||
fastXORBytes(dst, a, b, n)
|
fastXORBytes(dst, a, b, n)
|
||||||
@ -36,16 +34,10 @@ func XorBytes(dst, a, b []byte) int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
const wordSize = int(unsafe.Sizeof(uintptr(0)))
|
|
||||||
const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"
|
|
||||||
|
|
||||||
// fastXORBytes xors in bulk. It only works on architectures that
|
// fastXORBytes xors in bulk. It only works on architectures that
|
||||||
// support unaligned read/writes.
|
// support unaligned read/writes.
|
||||||
// n needs to be smaller or equal than the length of a and b.
|
// n needs to be smaller or equal than the length of a and b.
|
||||||
func fastXORBytes(dst, a, b []byte, n int) {
|
func fastXORBytes(dst, a, b []byte, n int) {
|
||||||
// Assert dst has enough space
|
|
||||||
_ = dst[n-1]
|
|
||||||
|
|
||||||
w := n / wordSize
|
w := n / wordSize
|
||||||
if w > 0 {
|
if w > 0 {
|
||||||
dw := *(*[]uintptr)(unsafe.Pointer(&dst))
|
dw := *(*[]uintptr)(unsafe.Pointer(&dst))
|
||||||
@ -67,25 +59,3 @@ func safeXORBytes(dst, a, b []byte, n int) {
|
|||||||
dst[i] = a[i] ^ b[i]
|
dst[i] = a[i] ^ b[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.)
|
|
||||||
// The arguments are assumed to be of equal length.
|
|
||||||
func fastXORWords(dst, a, b []byte) {
|
|
||||||
dw := *(*[]uintptr)(unsafe.Pointer(&dst))
|
|
||||||
aw := *(*[]uintptr)(unsafe.Pointer(&a))
|
|
||||||
bw := *(*[]uintptr)(unsafe.Pointer(&b))
|
|
||||||
n := len(b) / wordSize
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
dw[i] = aw[i] ^ bw[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.)
|
|
||||||
// The slice arguments a and b are assumed to be of equal length.
|
|
||||||
func XorWords(dst, a, b []byte) {
|
|
||||||
if supportsUnaligned {
|
|
||||||
fastXORWords(dst, a, b)
|
|
||||||
} else {
|
|
||||||
safeXORBytes(dst, a, b, len(b))
|
|
||||||
}
|
|
||||||
}
|
|
95
internal/subtle/xor_test.go
Normal file
95
internal/subtle/xor_test.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package subtle_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestXORBytes(t *testing.T) {
|
||||||
|
for n := 1; n <= 1024; n++ {
|
||||||
|
if n > 16 && testing.Short() {
|
||||||
|
n += n >> 3
|
||||||
|
}
|
||||||
|
for alignP := 0; alignP < 8; alignP++ {
|
||||||
|
for alignQ := 0; alignQ < 8; alignQ++ {
|
||||||
|
for alignD := 0; alignD < 8; alignD++ {
|
||||||
|
p := make([]byte, alignP+n, alignP+n+10)[alignP:]
|
||||||
|
q := make([]byte, alignQ+n, alignQ+n+10)[alignQ:]
|
||||||
|
if n&1 != 0 {
|
||||||
|
p = p[:n]
|
||||||
|
} else {
|
||||||
|
q = q[:n]
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(rand.Reader, p); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(rand.Reader, q); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d := make([]byte, alignD+n, alignD+n+10)
|
||||||
|
for i := range d {
|
||||||
|
d[i] = 0xdd
|
||||||
|
}
|
||||||
|
want := make([]byte, len(d), cap(d))
|
||||||
|
copy(want[:cap(want)], d[:cap(d)])
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
want[alignD+i] = p[i] ^ q[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
if subtle.XORBytes(d[alignD:], p, q); !bytes.Equal(d, want) {
|
||||||
|
t.Fatalf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXorBytesPanic(t *testing.T) {
|
||||||
|
mustPanic(t, "subtle.XORBytes: dst too short", func() {
|
||||||
|
subtle.XORBytes(nil, make([]byte, 1), make([]byte, 1))
|
||||||
|
})
|
||||||
|
mustPanic(t, "subtle.XORBytes: dst too short", func() {
|
||||||
|
subtle.XORBytes(make([]byte, 1), make([]byte, 2), make([]byte, 3))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkXORBytes(b *testing.B) {
|
||||||
|
dst := make([]byte, 1<<15)
|
||||||
|
data0 := make([]byte, 1<<15)
|
||||||
|
data1 := make([]byte, 1<<15)
|
||||||
|
sizes := []int64{1 << 3, 1 << 7, 1 << 11, 1 << 15}
|
||||||
|
for _, size := range sizes {
|
||||||
|
b.Run(fmt.Sprintf("%dBytes", size), func(b *testing.B) {
|
||||||
|
s0 := data0[:size]
|
||||||
|
s1 := data1[:size]
|
||||||
|
b.SetBytes(int64(size))
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
subtle.XORBytes(dst, s0, s1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustPanic(t *testing.T, expected string, f func()) {
|
||||||
|
t.Helper()
|
||||||
|
defer func() {
|
||||||
|
switch msg := recover().(type) {
|
||||||
|
case nil:
|
||||||
|
t.Errorf("expected panic(%q), but did not panic", expected)
|
||||||
|
case string:
|
||||||
|
if msg != expected {
|
||||||
|
t.Errorf("expected panic(%q), but got panic(%q)", expected, msg)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("expected panic(%q), but got panic(%T%v)", expected, msg, msg)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
f()
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
//go:build amd64 && !generic
|
|
||||||
// +build amd64,!generic
|
|
||||||
|
|
||||||
package xor
|
|
||||||
|
|
||||||
// XorBytes xors the bytes in a and b. The destination should have enough
|
|
||||||
// space, otherwise xorBytes will panic. Returns the number of bytes xor'd.
|
|
||||||
func XorBytes(dst, a, b []byte) int {
|
|
||||||
n := len(a)
|
|
||||||
if len(b) < n {
|
|
||||||
n = len(b)
|
|
||||||
}
|
|
||||||
if n == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
_ = dst[n-1]
|
|
||||||
xorBytesSSE2(&dst[0], &a[0], &b[0], n) // amd64 must have SSE2
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func XorWords(dst, a, b []byte) {
|
|
||||||
XorBytes(dst, a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func xorBytesSSE2(dst, a, b *byte, n int)
|
|
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
//go:build arm64 && !generic
|
|
||||||
// +build arm64,!generic
|
|
||||||
|
|
||||||
package xor
|
|
||||||
|
|
||||||
// xorBytes xors the bytes in a and b. The destination should have enough
|
|
||||||
// space, otherwise xorBytes will panic. Returns the number of bytes xor'd.
|
|
||||||
func XorBytes(dst, a, b []byte) int {
|
|
||||||
n := len(a)
|
|
||||||
if len(b) < n {
|
|
||||||
n = len(b)
|
|
||||||
}
|
|
||||||
if n == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
// make sure dst has enough space
|
|
||||||
_ = dst[n-1]
|
|
||||||
|
|
||||||
xorBytesARM64(&dst[0], &a[0], &b[0], n)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func XorWords(dst, a, b []byte) {
|
|
||||||
XorBytes(dst, a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func xorBytesARM64(dst, a, b *byte, n int)
|
|
@ -3,7 +3,7 @@ package padding
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://www.ibm.com/docs/en/linux-on-systems?topic=processes-ansi-x923-cipher-block-chaining
|
// https://www.ibm.com/docs/en/linux-on-systems?topic=processes-ansi-x923-cipher-block-chaining
|
||||||
@ -15,7 +15,7 @@ func (pad ansiX923Padding) BlockSize() int {
|
|||||||
|
|
||||||
func (pad ansiX923Padding) Pad(src []byte) []byte {
|
func (pad ansiX923Padding) Pad(src []byte) []byte {
|
||||||
overhead := pad.BlockSize() - len(src)%pad.BlockSize()
|
overhead := pad.BlockSize() - len(src)%pad.BlockSize()
|
||||||
ret, out := subtle.SliceForAppend(src, overhead)
|
ret, out := alias.SliceForAppend(src, overhead)
|
||||||
out[overhead-1] = byte(overhead)
|
out[overhead-1] = byte(overhead)
|
||||||
for i := 0; i < overhead-1; i++ {
|
for i := 0; i < overhead-1; i++ {
|
||||||
out[i] = 0
|
out[i] = 0
|
||||||
|
@ -4,7 +4,7 @@ package padding
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc5652#section-6.3
|
// https://datatracker.ietf.org/doc/html/rfc5652#section-6.3
|
||||||
@ -16,7 +16,7 @@ func (pad pkcs7Padding) BlockSize() int {
|
|||||||
|
|
||||||
func (pad pkcs7Padding) Pad(src []byte) []byte {
|
func (pad pkcs7Padding) Pad(src []byte) []byte {
|
||||||
overhead := pad.BlockSize() - len(src)%pad.BlockSize()
|
overhead := pad.BlockSize() - len(src)%pad.BlockSize()
|
||||||
ret, out := subtle.SliceForAppend(src, overhead)
|
ret, out := alias.SliceForAppend(src, overhead)
|
||||||
for i := 0; i < overhead; i++ {
|
for i := 0; i < overhead; i++ {
|
||||||
out[i] = byte(overhead)
|
out[i] = byte(overhead)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/randutil"
|
"github.com/emmansun/gmsm/internal/randutil"
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/sm2/sm2ec"
|
"github.com/emmansun/gmsm/sm2/sm2ec"
|
||||||
"github.com/emmansun/gmsm/sm3"
|
"github.com/emmansun/gmsm/sm3"
|
||||||
"golang.org/x/crypto/cryptobyte"
|
"golang.org/x/crypto/cryptobyte"
|
||||||
@ -345,7 +345,7 @@ func Encrypt(random io.Reader, pub *ecdsa.PublicKey, msg []byte, opts *Encrypter
|
|||||||
}
|
}
|
||||||
|
|
||||||
//A6, C2 = M + t;
|
//A6, C2 = M + t;
|
||||||
xor.XorBytes(c2, msg, c2)
|
subtle.XORBytes(c2, msg, c2)
|
||||||
|
|
||||||
//A7, C3 = hash(x2||M||y2)
|
//A7, C3 = hash(x2||M||y2)
|
||||||
c3 := calculateC3(curve, x2, y2, msg)
|
c3 := calculateC3(curve, x2, y2, msg)
|
||||||
@ -402,7 +402,7 @@ func rawDecrypt(priv *PrivateKey, x1, y1 *big.Int, c2, c3 []byte) ([]byte, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
//B5, calculate msg = c2 ^ t
|
//B5, calculate msg = c2 ^ t
|
||||||
xor.XorBytes(msg, c2, msg)
|
subtle.XORBytes(msg, c2, msg)
|
||||||
|
|
||||||
u := calculateC3(curve, x2, y2, msg)
|
u := calculateC3(curve, x2, y2, msg)
|
||||||
for i := 0; i < sm3.Size; i++ {
|
for i := 0; i < sm3.Size; i++ {
|
||||||
|
@ -93,6 +93,10 @@ func (ke *KeyExchange) SetPeerParameters(peerPub *ecdsa.PublicKey, peerUID []byt
|
|||||||
return errors.New("sm2: 'peerPub' already exists, please do not set it")
|
return errors.New("sm2: 'peerPub' already exists, please do not set it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !IsSM2PublicKey(peerPub) {
|
||||||
|
return errors.New("sm2: peer public key is not expected/supported")
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
ke.peerPub = peerPub
|
ke.peerPub = peerPub
|
||||||
ke.peerZ, err = calculateZA(ke.peerPub, peerUID)
|
ke.peerZ, err = calculateZA(ke.peerPub, peerUID)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package sm2
|
package sm2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
@ -83,6 +85,7 @@ func TestKeyExchangeSimplest(t *testing.T) {
|
|||||||
func TestSetPeerParameters(t *testing.T) {
|
func TestSetPeerParameters(t *testing.T) {
|
||||||
priv1, _ := GenerateKey(rand.Reader)
|
priv1, _ := GenerateKey(rand.Reader)
|
||||||
priv2, _ := GenerateKey(rand.Reader)
|
priv2, _ := GenerateKey(rand.Reader)
|
||||||
|
priv3, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
uidA := []byte("Alice")
|
uidA := []byte("Alice")
|
||||||
uidB := []byte("Bob")
|
uidB := []byte("Bob")
|
||||||
|
|
||||||
@ -101,6 +104,11 @@ func TestSetPeerParameters(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置对端参数
|
// 设置对端参数
|
||||||
|
err = initiator.SetPeerParameters(&priv3.PublicKey, uidB)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("should be failed")
|
||||||
|
}
|
||||||
|
|
||||||
err = initiator.SetPeerParameters(&priv2.PublicKey, uidB)
|
err = initiator.SetPeerParameters(&priv2.PublicKey, uidB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -6,8 +6,8 @@ package sm4
|
|||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Assert that sm4CipherAsm implements the cbcEncAble and cbcDecAble interfaces.
|
// Assert that sm4CipherAsm implements the cbcEncAble and cbcDecAble interfaces.
|
||||||
@ -56,7 +56,7 @@ func (x *cbc) CryptBlocks(dst, src []byte) {
|
|||||||
if len(dst) < len(src) {
|
if len(dst) < len(src) {
|
||||||
panic("cipher: output smaller than input")
|
panic("cipher: output smaller than input")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:len(src)], src) {
|
if alias.InexactOverlap(dst[:len(src)], src) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
if len(src) == 0 {
|
if len(src) == 0 {
|
||||||
@ -79,7 +79,7 @@ func (x *cbc) CryptBlocks(dst, src []byte) {
|
|||||||
for start > 0 {
|
for start > 0 {
|
||||||
x.b.DecryptBlocks(temp, src[start:end])
|
x.b.DecryptBlocks(temp, src[start:end])
|
||||||
copy(batchSrc, src[start-BlockSize:])
|
copy(batchSrc, src[start-BlockSize:])
|
||||||
xor.XorBytes(dst[start:], temp, batchSrc)
|
subtle.XORBytes(dst[start:], temp, batchSrc)
|
||||||
end = start
|
end = start
|
||||||
start -= x.b.blocksSize
|
start -= x.b.blocksSize
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ func (x *cbc) CryptBlocks(dst, src []byte) {
|
|||||||
copy(batchSrc[BlockSize:], src[:end])
|
copy(batchSrc[BlockSize:], src[:end])
|
||||||
x.b.DecryptBlocks(temp, batchSrc[BlockSize:])
|
x.b.DecryptBlocks(temp, batchSrc[BlockSize:])
|
||||||
copy(batchSrc, x.iv)
|
copy(batchSrc, x.iv)
|
||||||
xor.XorBytes(dst, temp[:end], batchSrc)
|
subtle.XORBytes(dst, temp[:end], batchSrc)
|
||||||
|
|
||||||
// Set the new iv to the first block we copied earlier.
|
// Set the new iv to the first block we copied earlier.
|
||||||
x.iv, x.tmp = x.tmp, x.iv
|
x.iv, x.tmp = x.tmp, x.iv
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BlockSize the sm4 block size in bytes.
|
// BlockSize the sm4 block size in bytes.
|
||||||
@ -49,7 +49,7 @@ func (c *sm4Cipher) Encrypt(dst, src []byte) {
|
|||||||
if len(dst) < BlockSize {
|
if len(dst) < BlockSize {
|
||||||
panic("sm4: output not full block")
|
panic("sm4: output not full block")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
||||||
panic("sm4: invalid buffer overlap")
|
panic("sm4: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
encryptBlockGo(c.enc, dst, src)
|
encryptBlockGo(c.enc, dst, src)
|
||||||
@ -62,7 +62,7 @@ func (c *sm4Cipher) Decrypt(dst, src []byte) {
|
|||||||
if len(dst) < BlockSize {
|
if len(dst) < BlockSize {
|
||||||
panic("sm4: output not full block")
|
panic("sm4: output not full block")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
||||||
panic("sm4: invalid buffer overlap")
|
panic("sm4: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
decryptBlockGo(c.dec, dst, src)
|
decryptBlockGo(c.dec, dst, src)
|
||||||
|
@ -6,7 +6,7 @@ package sm4
|
|||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
"golang.org/x/sys/cpu"
|
"golang.org/x/sys/cpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ func (c *sm4CipherAsm) Encrypt(dst, src []byte) {
|
|||||||
if len(dst) < BlockSize {
|
if len(dst) < BlockSize {
|
||||||
panic("sm4: output not full block")
|
panic("sm4: output not full block")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
||||||
panic("sm4: invalid buffer overlap")
|
panic("sm4: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
encryptBlockAsm(&c.enc[0], &dst[0], &src[0], INST_AES)
|
encryptBlockAsm(&c.enc[0], &dst[0], &src[0], INST_AES)
|
||||||
@ -78,7 +78,7 @@ func (c *sm4CipherAsm) EncryptBlocks(dst, src []byte) {
|
|||||||
if len(dst) < c.blocksSize {
|
if len(dst) < c.blocksSize {
|
||||||
panic("sm4: output not full blocks")
|
panic("sm4: output not full blocks")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:c.blocksSize], src[:c.blocksSize]) {
|
if alias.InexactOverlap(dst[:c.blocksSize], src[:c.blocksSize]) {
|
||||||
panic("sm4: invalid buffer overlap")
|
panic("sm4: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
encryptBlocksAsm(&c.enc[0], dst, src, INST_AES)
|
encryptBlocksAsm(&c.enc[0], dst, src, INST_AES)
|
||||||
@ -91,7 +91,7 @@ func (c *sm4CipherAsm) Decrypt(dst, src []byte) {
|
|||||||
if len(dst) < BlockSize {
|
if len(dst) < BlockSize {
|
||||||
panic("sm4: output not full block")
|
panic("sm4: output not full block")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
||||||
panic("sm4: invalid buffer overlap")
|
panic("sm4: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
encryptBlockAsm(&c.dec[0], &dst[0], &src[0], INST_AES)
|
encryptBlockAsm(&c.dec[0], &dst[0], &src[0], INST_AES)
|
||||||
@ -104,7 +104,7 @@ func (c *sm4CipherAsm) DecryptBlocks(dst, src []byte) {
|
|||||||
if len(dst) < c.blocksSize {
|
if len(dst) < c.blocksSize {
|
||||||
panic("sm4: output not full blocks")
|
panic("sm4: output not full blocks")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:c.blocksSize], src[:c.blocksSize]) {
|
if alias.InexactOverlap(dst[:c.blocksSize], src[:c.blocksSize]) {
|
||||||
panic("sm4: invalid buffer overlap")
|
panic("sm4: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
encryptBlocksAsm(&c.dec[0], dst, src, INST_AES)
|
encryptBlocksAsm(&c.dec[0], dst, src, INST_AES)
|
||||||
|
@ -6,7 +6,7 @@ package sm4
|
|||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sm4CipherNI struct {
|
type sm4CipherNI struct {
|
||||||
@ -29,7 +29,7 @@ func (c *sm4CipherNI) Encrypt(dst, src []byte) {
|
|||||||
if len(dst) < BlockSize {
|
if len(dst) < BlockSize {
|
||||||
panic("sm4: output not full block")
|
panic("sm4: output not full block")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
||||||
panic("sm4: invalid buffer overlap")
|
panic("sm4: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
encryptBlockAsm(&c.enc[0], &dst[0], &src[0], INST_SM4)
|
encryptBlockAsm(&c.enc[0], &dst[0], &src[0], INST_SM4)
|
||||||
@ -42,7 +42,7 @@ func (c *sm4CipherNI) Decrypt(dst, src []byte) {
|
|||||||
if len(dst) < BlockSize {
|
if len(dst) < BlockSize {
|
||||||
panic("sm4: output not full block")
|
panic("sm4: output not full block")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
||||||
panic("sm4: invalid buffer overlap")
|
panic("sm4: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
encryptBlockAsm(&c.dec[0], &dst[0], &src[0], INST_SM4)
|
encryptBlockAsm(&c.dec[0], &dst[0], &src[0], INST_SM4)
|
||||||
|
@ -6,8 +6,8 @@ package sm4
|
|||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Assert that sm4CipherAsm implements the ctrAble interface.
|
// Assert that sm4CipherAsm implements the ctrAble interface.
|
||||||
@ -83,14 +83,14 @@ func (x *ctr) XORKeyStream(dst, src []byte) {
|
|||||||
if len(dst) < len(src) {
|
if len(dst) < len(src) {
|
||||||
panic("cipher: output smaller than input")
|
panic("cipher: output smaller than input")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:len(src)], src) {
|
if alias.InexactOverlap(dst[:len(src)], src) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
for len(src) > 0 {
|
for len(src) > 0 {
|
||||||
if x.outUsed >= len(x.out)-BlockSize {
|
if x.outUsed >= len(x.out)-BlockSize {
|
||||||
x.refill()
|
x.refill()
|
||||||
}
|
}
|
||||||
n := xor.XorBytes(dst, src, x.out[x.outUsed:])
|
n := subtle.XORBytes(dst, src, x.out[x.outUsed:])
|
||||||
dst = dst[n:]
|
dst = dst[n:]
|
||||||
src = src[n:]
|
src = src[n:]
|
||||||
x.outUsed += n
|
x.outUsed += n
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Assert that sm4CipherAsm implements the gcmAble interface.
|
// Assert that sm4CipherAsm implements the gcmAble interface.
|
||||||
@ -86,8 +86,8 @@ func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
|
|||||||
panic("cipher: message too large for GCM")
|
panic("cipher: message too large for GCM")
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, out := subtle.SliceForAppend(dst, len(plaintext)+g.tagSize)
|
ret, out := alias.SliceForAppend(dst, len(plaintext)+g.tagSize)
|
||||||
if subtle.InexactOverlap(out, plaintext) {
|
if alias.InexactOverlap(out, plaintext) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +137,8 @@ func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
|||||||
var expectedTag [gcmTagSize]byte
|
var expectedTag [gcmTagSize]byte
|
||||||
g.auth(expectedTag[:], ciphertext, data, &tagMask)
|
g.auth(expectedTag[:], ciphertext, data, &tagMask)
|
||||||
|
|
||||||
ret, out := subtle.SliceForAppend(dst, len(ciphertext))
|
ret, out := alias.SliceForAppend(dst, len(ciphertext))
|
||||||
if subtle.InexactOverlap(out, ciphertext) {
|
if alias.InexactOverlap(out, ciphertext) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +274,7 @@ func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
|
|||||||
gcmInc32(counter)
|
gcmInc32(counter)
|
||||||
}
|
}
|
||||||
g.cipher.EncryptBlocks(mask, counters)
|
g.cipher.EncryptBlocks(mask, counters)
|
||||||
xor.XorWords(out, in, mask[:])
|
subtle.XORBytes(out, in, mask[:])
|
||||||
out = out[g.cipher.blocksSize:]
|
out = out[g.cipher.blocksSize:]
|
||||||
in = in[g.cipher.blocksSize:]
|
in = in[g.cipher.blocksSize:]
|
||||||
}
|
}
|
||||||
@ -286,7 +286,7 @@ func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
|
|||||||
gcmInc32(counter)
|
gcmInc32(counter)
|
||||||
}
|
}
|
||||||
g.cipher.EncryptBlocks(mask, counters)
|
g.cipher.EncryptBlocks(mask, counters)
|
||||||
xor.XorBytes(out, in, mask[:blocks*gcmBlockSize])
|
subtle.XORBytes(out, in, mask[:blocks*gcmBlockSize])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,5 +328,5 @@ func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]
|
|||||||
binary.BigEndian.PutUint64(out, y.low)
|
binary.BigEndian.PutUint64(out, y.low)
|
||||||
binary.BigEndian.PutUint64(out[8:], y.high)
|
binary.BigEndian.PutUint64(out[8:], y.high)
|
||||||
|
|
||||||
xor.XorWords(out, out, tagMask[:])
|
subtle.XORBytes(out, out, tagMask[:])
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ package sm4
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
goSubtle "crypto/subtle"
|
"crypto/subtle"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sm4CipherGCM implements crypto/cipher.gcmAble so that crypto/cipher.NewGCM
|
// sm4CipherGCM implements crypto/cipher.gcmAble so that crypto/cipher.NewGCM
|
||||||
@ -86,8 +86,8 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
|
|||||||
var tagOut [gcmTagSize]byte
|
var tagOut [gcmTagSize]byte
|
||||||
gcmSm4Data(&g.bytesProductTable, data, &tagOut)
|
gcmSm4Data(&g.bytesProductTable, data, &tagOut)
|
||||||
|
|
||||||
ret, out := subtle.SliceForAppend(dst, len(plaintext)+g.tagSize)
|
ret, out := alias.SliceForAppend(dst, len(plaintext)+g.tagSize)
|
||||||
if subtle.InexactOverlap(out[:len(plaintext)], plaintext) {
|
if alias.InexactOverlap(out[:len(plaintext)], plaintext) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,8 +140,8 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
|||||||
var expectedTag [gcmTagSize]byte
|
var expectedTag [gcmTagSize]byte
|
||||||
gcmSm4Data(&g.bytesProductTable, data, &expectedTag)
|
gcmSm4Data(&g.bytesProductTable, data, &expectedTag)
|
||||||
|
|
||||||
ret, out := subtle.SliceForAppend(dst, len(ciphertext))
|
ret, out := alias.SliceForAppend(dst, len(ciphertext))
|
||||||
if subtle.InexactOverlap(out, ciphertext) {
|
if alias.InexactOverlap(out, ciphertext) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
if len(ciphertext) > 0 {
|
if len(ciphertext) > 0 {
|
||||||
@ -149,7 +149,7 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
gcmSm4Finish(&g.bytesProductTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data)))
|
gcmSm4Finish(&g.bytesProductTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data)))
|
||||||
|
|
||||||
if goSubtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
|
if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
|
||||||
for i := range out {
|
for i := range out {
|
||||||
out[i] = 0
|
out[i] = 0
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ package sm4
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
goSubtle "crypto/subtle"
|
"crypto/subtle"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
@ -79,8 +79,8 @@ func (g *gcmNI) Seal(dst, nonce, plaintext, data []byte) []byte {
|
|||||||
var tagOut [gcmTagSize]byte
|
var tagOut [gcmTagSize]byte
|
||||||
gcmSm4Data(&g.bytesProductTable, data, &tagOut)
|
gcmSm4Data(&g.bytesProductTable, data, &tagOut)
|
||||||
|
|
||||||
ret, out := subtle.SliceForAppend(dst, len(plaintext)+g.tagSize)
|
ret, out := alias.SliceForAppend(dst, len(plaintext)+g.tagSize)
|
||||||
if subtle.InexactOverlap(out[:len(plaintext)], plaintext) {
|
if alias.InexactOverlap(out[:len(plaintext)], plaintext) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,8 +133,8 @@ func (g *gcmNI) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
|||||||
var expectedTag [gcmTagSize]byte
|
var expectedTag [gcmTagSize]byte
|
||||||
gcmSm4Data(&g.bytesProductTable, data, &expectedTag)
|
gcmSm4Data(&g.bytesProductTable, data, &expectedTag)
|
||||||
|
|
||||||
ret, out := subtle.SliceForAppend(dst, len(ciphertext))
|
ret, out := alias.SliceForAppend(dst, len(ciphertext))
|
||||||
if subtle.InexactOverlap(out, ciphertext) {
|
if alias.InexactOverlap(out, ciphertext) {
|
||||||
panic("cipher: invalid buffer overlap")
|
panic("cipher: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
if len(ciphertext) > 0 {
|
if len(ciphertext) > 0 {
|
||||||
@ -142,7 +142,7 @@ func (g *gcmNI) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
gcmSm4Finish(&g.bytesProductTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data)))
|
gcmSm4Finish(&g.bytesProductTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data)))
|
||||||
|
|
||||||
if goSubtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
|
if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
|
||||||
for i := range out {
|
for i := range out {
|
||||||
out[i] = 0
|
out[i] = 0
|
||||||
}
|
}
|
||||||
|
20
sm9/sm9.go
20
sm9/sm9.go
@ -3,14 +3,14 @@ package sm9
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/subtle"
|
goSubtle "crypto/subtle"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/sm3"
|
"github.com/emmansun/gmsm/sm3"
|
||||||
"github.com/emmansun/gmsm/sm9/bn256"
|
"github.com/emmansun/gmsm/sm9/bn256"
|
||||||
"golang.org/x/crypto/cryptobyte"
|
"golang.org/x/crypto/cryptobyte"
|
||||||
@ -325,7 +325,7 @@ func Encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
xor.XorBytes(key, key[:len(plaintext)], plaintext)
|
subtle.XORBytes(key, key[:len(plaintext)], plaintext)
|
||||||
|
|
||||||
hash := sm3.New()
|
hash := sm3.New()
|
||||||
hash.Write(key)
|
hash.Write(key)
|
||||||
@ -349,7 +349,7 @@ func (pub *EncryptMasterPublicKey) Encrypt(rand io.Reader, uid []byte, hid byte,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
xor.XorBytes(key, key[:len(plaintext)], plaintext)
|
subtle.XORBytes(key, key[:len(plaintext)], plaintext)
|
||||||
|
|
||||||
hash := sm3.New()
|
hash := sm3.New()
|
||||||
hash.Write(key)
|
hash.Write(key)
|
||||||
@ -385,11 +385,11 @@ func Decrypt(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error) {
|
|||||||
hash.Write(key[len(c2):])
|
hash.Write(key[len(c2):])
|
||||||
c32 := hash.Sum(nil)
|
c32 := hash.Sum(nil)
|
||||||
|
|
||||||
if subtle.ConstantTimeCompare(c3[:sm3.Size], c32) != 1 {
|
if goSubtle.ConstantTimeCompare(c3[:sm3.Size], c32) != 1 {
|
||||||
return nil, errors.New("sm9: invalid mac value")
|
return nil, errors.New("sm9: invalid mac value")
|
||||||
}
|
}
|
||||||
|
|
||||||
xor.XorBytes(key, c2, key[:len(c2)])
|
subtle.XORBytes(key, c2, key[:len(c2)])
|
||||||
return key[:len(c2)], nil
|
return key[:len(c2)], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,10 +437,10 @@ func DecryptASN1(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error
|
|||||||
hash.Write(key[len(c2Bytes):])
|
hash.Write(key[len(c2Bytes):])
|
||||||
c32 := hash.Sum(nil)
|
c32 := hash.Sum(nil)
|
||||||
|
|
||||||
if subtle.ConstantTimeCompare(c3Bytes, c32) != 1 {
|
if goSubtle.ConstantTimeCompare(c3Bytes, c32) != 1 {
|
||||||
return nil, errors.New("sm9: invalid mac value")
|
return nil, errors.New("sm9: invalid mac value")
|
||||||
}
|
}
|
||||||
xor.XorBytes(key, c2Bytes, key[:len(c2Bytes)])
|
subtle.XORBytes(key, c2Bytes, key[:len(c2Bytes)])
|
||||||
return key[:len(c2Bytes)], nil
|
return key[:len(c2Bytes)], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,7 +597,7 @@ func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error)
|
|||||||
// step 6, verify signature
|
// step 6, verify signature
|
||||||
if len(sB) > 0 {
|
if len(sB) > 0 {
|
||||||
signature := ke.sign(false, 0x82)
|
signature := ke.sign(false, 0x82)
|
||||||
if subtle.ConstantTimeCompare(signature, sB) != 1 {
|
if goSubtle.ConstantTimeCompare(signature, sB) != 1 {
|
||||||
return nil, errors.New("sm9: invalid responder's signature")
|
return nil, errors.New("sm9: invalid responder's signature")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -611,7 +611,7 @@ func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error)
|
|||||||
// ConfirmInitiator for responder's step B8
|
// ConfirmInitiator for responder's step B8
|
||||||
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) error {
|
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) error {
|
||||||
buffer := ke.sign(true, 0x83)
|
buffer := ke.sign(true, 0x83)
|
||||||
if subtle.ConstantTimeCompare(buffer, s1) != 1 {
|
if goSubtle.ConstantTimeCompare(buffer, s1) != 1 {
|
||||||
return errors.New("sm9: invalid initiator's signature")
|
return errors.New("sm9: invalid initiator's signature")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/sm3"
|
"github.com/emmansun/gmsm/sm3"
|
||||||
"github.com/emmansun/gmsm/sm9/bn256"
|
"github.com/emmansun/gmsm/sm9/bn256"
|
||||||
)
|
)
|
||||||
@ -493,7 +493,7 @@ func TestEncryptSM9Sample(t *testing.T) {
|
|||||||
if hex.EncodeToString(key) != expectedKey {
|
if hex.EncodeToString(key) != expectedKey {
|
||||||
t.Errorf("not expected key")
|
t.Errorf("not expected key")
|
||||||
}
|
}
|
||||||
xor.XorBytes(key, key[:len(plaintext)], plaintext)
|
subtle.XORBytes(key, key[:len(plaintext)], plaintext)
|
||||||
|
|
||||||
hash := sm3.New()
|
hash := sm3.New()
|
||||||
hash.Write(key)
|
hash.Write(key)
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
"github.com/emmansun/gmsm/internal/subtle"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const RoundWords = 32
|
const RoundWords = 32
|
||||||
@ -35,7 +35,7 @@ func xorKeyStreamGeneric(c *zucState32, dst, src []byte) {
|
|||||||
for j := 0; j < RoundWords; j++ {
|
for j := 0; j < RoundWords; j++ {
|
||||||
binary.BigEndian.PutUint32(keyBytes[j*4:], keyWords[j])
|
binary.BigEndian.PutUint32(keyBytes[j*4:], keyWords[j])
|
||||||
}
|
}
|
||||||
xor.XorBytes(dst, src, keyBytes[:])
|
subtle.XORBytes(dst, src, keyBytes[:])
|
||||||
dst = dst[RoundWords*4:]
|
dst = dst[RoundWords*4:]
|
||||||
src = src[RoundWords*4:]
|
src = src[RoundWords*4:]
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ func xorKeyStreamGeneric(c *zucState32, dst, src []byte) {
|
|||||||
for j := 0; j < words-rounds*RoundWords; j++ {
|
for j := 0; j < words-rounds*RoundWords; j++ {
|
||||||
binary.BigEndian.PutUint32(keyBytes[j*4:], keyWords[j])
|
binary.BigEndian.PutUint32(keyBytes[j*4:], keyWords[j])
|
||||||
}
|
}
|
||||||
xor.XorBytes(dst, src, keyBytes[:])
|
subtle.XORBytes(dst, src, keyBytes[:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ func (c *zucState32) XORKeyStream(dst, src []byte) {
|
|||||||
if len(dst) < len(src) {
|
if len(dst) < len(src) {
|
||||||
panic("zuc: output smaller than input")
|
panic("zuc: output smaller than input")
|
||||||
}
|
}
|
||||||
if subtle.InexactOverlap(dst[:len(src)], src) {
|
if alias.InexactOverlap(dst[:len(src)], src) {
|
||||||
panic("zuc: invalid buffer overlap")
|
panic("zuc: invalid buffer overlap")
|
||||||
}
|
}
|
||||||
xorKeyStream(c, dst, src)
|
xorKeyStream(c, dst, src)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
package zuc
|
package zuc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/emmansun/gmsm/internal/xor"
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
@ -17,13 +17,13 @@ func xorKeyStream(c *zucState32, dst, src []byte) {
|
|||||||
if words > 0 {
|
if words > 0 {
|
||||||
dstWords := dst[:words*4]
|
dstWords := dst[:words*4]
|
||||||
genKeyStreamRev32Asm(dstWords, c)
|
genKeyStreamRev32Asm(dstWords, c)
|
||||||
xor.XorBytes(dst, src, dstWords)
|
subtle.XORBytes(dst, src, dstWords)
|
||||||
}
|
}
|
||||||
// handle remain bytes
|
// handle remain bytes
|
||||||
if words*4 < len(src) {
|
if words*4 < len(src) {
|
||||||
var singleWord [4]byte
|
var singleWord [4]byte
|
||||||
genKeyStreamRev32Asm(singleWord[:], c)
|
genKeyStreamRev32Asm(singleWord[:], c)
|
||||||
xor.XorBytes(dst[words*4:], src[words*4:], singleWord[:])
|
subtle.XORBytes(dst[words*4:], src[words*4:], singleWord[:])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
xorKeyStreamGeneric(c, dst, src)
|
xorKeyStreamGeneric(c, dst, src)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user