package aes
import (
"crypto/internal/fips140/alias"
"crypto/internal/fips140/subtle"
"crypto/internal/fips140deps/byteorder"
"math/bits"
)
type CTR struct {
b Block
ivlo, ivhi uint64
offset uint64
}
func NewCTR (b *Block , iv []byte ) *CTR {
c := newCTR (b , iv )
return &c
}
func newCTR(b *Block , iv []byte ) CTR {
if len (iv ) != BlockSize {
panic ("bad IV length" )
}
return CTR {
b : *b ,
ivlo : byteorder .BEUint64 (iv [8 :16 ]),
ivhi : byteorder .BEUint64 (iv [0 :8 ]),
offset : 0 ,
}
}
func (c *CTR ) XORKeyStream (dst , src []byte ) {
c .XORKeyStreamAt (dst , src , c .offset )
var carry uint64
c .offset , carry = bits .Add64 (c .offset , uint64 (len (src )), 0 )
if carry != 0 {
panic ("crypto/aes: counter overflow" )
}
}
func RoundToBlock (c *CTR ) {
if remainder := c .offset % BlockSize ; remainder != 0 {
var carry uint64
c .offset , carry = bits .Add64 (c .offset , BlockSize -remainder , 0 )
if carry != 0 {
panic ("crypto/aes: counter overflow" )
}
}
}
func (c *CTR ) XORKeyStreamAt (dst , src []byte , offset uint64 ) {
if len (dst ) < len (src ) {
panic ("crypto/aes: len(dst) < len(src)" )
}
dst = dst [:len (src )]
if alias .InexactOverlap (dst , src ) {
panic ("crypto/aes: invalid buffer overlap" )
}
ivlo , ivhi := add128 (c .ivlo , c .ivhi , offset /BlockSize )
if blockOffset := offset % BlockSize ; blockOffset != 0 {
var in , out [BlockSize ]byte
copy (in [blockOffset :], src )
ctrBlocks1 (&c .b , &out , &in , ivlo , ivhi )
n := copy (dst , out [blockOffset :])
src = src [n :]
dst = dst [n :]
ivlo , ivhi = add128 (ivlo , ivhi , 1 )
}
for len (src ) >= 8 *BlockSize {
ctrBlocks8 (&c .b , (*[8 * BlockSize ]byte )(dst ), (*[8 * BlockSize ]byte )(src ), ivlo , ivhi )
src = src [8 *BlockSize :]
dst = dst [8 *BlockSize :]
ivlo , ivhi = add128 (ivlo , ivhi , 8 )
}
if len (src ) >= 4 *BlockSize {
ctrBlocks4 (&c .b , (*[4 * BlockSize ]byte )(dst ), (*[4 * BlockSize ]byte )(src ), ivlo , ivhi )
src = src [4 *BlockSize :]
dst = dst [4 *BlockSize :]
ivlo , ivhi = add128 (ivlo , ivhi , 4 )
}
if len (src ) >= 2 *BlockSize {
ctrBlocks2 (&c .b , (*[2 * BlockSize ]byte )(dst ), (*[2 * BlockSize ]byte )(src ), ivlo , ivhi )
src = src [2 *BlockSize :]
dst = dst [2 *BlockSize :]
ivlo , ivhi = add128 (ivlo , ivhi , 2 )
}
if len (src ) >= 1 *BlockSize {
ctrBlocks1 (&c .b , (*[1 * BlockSize ]byte )(dst ), (*[1 * BlockSize ]byte )(src ), ivlo , ivhi )
src = src [1 *BlockSize :]
dst = dst [1 *BlockSize :]
ivlo , ivhi = add128 (ivlo , ivhi , 1 )
}
if len (src ) != 0 {
var in , out [BlockSize ]byte
copy (in [:], src )
ctrBlocks1 (&c .b , &out , &in , ivlo , ivhi )
copy (dst , out [:])
}
}
func ctrBlocks(b *Block , dst , src []byte , ivlo , ivhi uint64 ) {
buf := make ([]byte , len (src ), 8 *BlockSize )
for i := 0 ; i < len (buf ); i += BlockSize {
byteorder .BEPutUint64 (buf [i :], ivhi )
byteorder .BEPutUint64 (buf [i +8 :], ivlo )
ivlo , ivhi = add128 (ivlo , ivhi , 1 )
b .Encrypt (buf [i :], buf [i :])
}
subtle .XORBytes (buf , src , buf )
copy (dst , buf )
}
func add128(lo , hi uint64 , x uint64 ) (uint64 , uint64 ) {
lo , c := bits .Add64 (lo , x , 0 )
hi , _ = bits .Add64 (hi , 0 , c )
return lo , hi
}
The pages are generated with Golds v0.7.3-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .