mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 04:06:18 +08:00
sm4: ppc64x, gcm with EncryptBlocks
This commit is contained in:
parent
78d55a69bc
commit
e8d1100481
@ -94,40 +94,53 @@ func (g *gcmAsm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// counterCrypt encrypts in using AES in counter mode and places the result
|
const fourBlocksSize = 64
|
||||||
|
const eightBlocksSize = fourBlocksSize * 2
|
||||||
|
|
||||||
|
// counterCrypt encrypts in using SM4 in counter mode and places the result
|
||||||
// into out. counter is the initial count value and will be updated with the next
|
// into out. counter is the initial count value and will be updated with the next
|
||||||
// count value. The length of out must be greater than or equal to the length
|
// count value. The length of out must be greater than or equal to the length
|
||||||
// of in.
|
// of in.
|
||||||
// counterCryptASM implements counterCrypt which then allows the loop to
|
|
||||||
// be unrolled and optimized.
|
|
||||||
func (g *gcmAsm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
|
func (g *gcmAsm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
|
||||||
var mask [gcmBlockSize]byte
|
var mask [eightBlocksSize]byte
|
||||||
|
var counters [eightBlocksSize]byte
|
||||||
|
|
||||||
for len(in) >= gcmBlockSize {
|
for len(in) >= eightBlocksSize {
|
||||||
// Hint to avoid bounds check
|
for i := 0; i < 8; i++ {
|
||||||
_, _ = in[15], out[15]
|
copy(counters[i*gcmBlockSize:(i+1)*gcmBlockSize], counter[:])
|
||||||
g.cipher.Encrypt(mask[:], counter[:])
|
gcmInc32(counter)
|
||||||
gcmInc32(counter)
|
}
|
||||||
|
g.cipher.EncryptBlocks(mask[:], counters[:])
|
||||||
|
subtle.XORBytes(out, in, mask[:])
|
||||||
|
out = out[eightBlocksSize:]
|
||||||
|
in = in[eightBlocksSize:]
|
||||||
|
}
|
||||||
|
|
||||||
// XOR 16 bytes each loop iteration in 8 byte chunks
|
if len(in) >= fourBlocksSize {
|
||||||
in0 := binary.LittleEndian.Uint64(in[0:])
|
for i := 0; i < 4; i++ {
|
||||||
in1 := binary.LittleEndian.Uint64(in[8:])
|
copy(counters[i*gcmBlockSize:(i+1)*gcmBlockSize], counter[:])
|
||||||
m0 := binary.LittleEndian.Uint64(mask[:8])
|
gcmInc32(counter)
|
||||||
m1 := binary.LittleEndian.Uint64(mask[8:])
|
}
|
||||||
binary.LittleEndian.PutUint64(out[:8], in0^m0)
|
g.cipher.EncryptBlocks(mask[:], counters[:])
|
||||||
binary.LittleEndian.PutUint64(out[8:], in1^m1)
|
subtle.XORBytes(out, in, mask[:fourBlocksSize])
|
||||||
out = out[16:]
|
out = out[fourBlocksSize:]
|
||||||
in = in[16:]
|
in = in[fourBlocksSize:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(in) > 0 {
|
if len(in) > 0 {
|
||||||
g.cipher.Encrypt(mask[:], counter[:])
|
blocks := (len(in) + gcmBlockSize - 1) / gcmBlockSize
|
||||||
gcmInc32(counter)
|
if blocks > 1 {
|
||||||
// XOR leftover bytes
|
for i := 0; i < blocks; i++ {
|
||||||
for i, inb := range in {
|
copy(counters[i*gcmBlockSize:], counter[:])
|
||||||
out[i] = inb ^ mask[i]
|
gcmInc32(counter)
|
||||||
|
}
|
||||||
|
g.cipher.EncryptBlocks(mask[:], counters[:])
|
||||||
|
} else {
|
||||||
|
g.cipher.Encrypt(mask[:], counter[:])
|
||||||
|
gcmInc32(counter)
|
||||||
}
|
}
|
||||||
}
|
subtle.XORBytes(out, in, mask[:blocks*gcmBlockSize])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// increments the rightmost 32-bits of the count value by 1.
|
// increments the rightmost 32-bits of the count value by 1.
|
||||||
@ -160,11 +173,7 @@ func (g *gcmAsm) auth(out, ciphertext, aad []byte, tagMask *[gcmTagSize]byte) {
|
|||||||
g.paddedGHASH(&hash, ciphertext)
|
g.paddedGHASH(&hash, ciphertext)
|
||||||
lens := gcmLengths(uint64(len(aad))*8, uint64(len(ciphertext))*8)
|
lens := gcmLengths(uint64(len(aad))*8, uint64(len(ciphertext))*8)
|
||||||
g.paddedGHASH(&hash, lens[:])
|
g.paddedGHASH(&hash, lens[:])
|
||||||
|
subtle.XORBytes(out, hash[:], tagMask[:])
|
||||||
copy(out, hash[:])
|
|
||||||
for i := range out {
|
|
||||||
out[i] ^= tagMask[i]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seal encrypts and authenticates plaintext. See the [cipher.AEAD] interface for
|
// Seal encrypts and authenticates plaintext. See the [cipher.AEAD] interface for
|
||||||
@ -228,7 +237,7 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
|||||||
// clear(out)
|
// clear(out)
|
||||||
for i := range out {
|
for i := range out {
|
||||||
out[i] = 0
|
out[i] = 0
|
||||||
}
|
}
|
||||||
return nil, errOpen
|
return nil, errOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user