package aes
+import (
+ "encoding/binary"
+)
+
// Encrypt one block from src into dst, using the expanded key xk.
func encryptBlockGo(xk []uint32, dst, src []byte) {
- var s0, s1, s2, s3, t0, t1, t2, t3 uint32
-
- s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
- s1 = uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
- s2 = uint32(src[8])<<24 | uint32(src[9])<<16 | uint32(src[10])<<8 | uint32(src[11])
- s3 = uint32(src[12])<<24 | uint32(src[13])<<16 | uint32(src[14])<<8 | uint32(src[15])
+ _ = src[15] // early bounds check
+ s0 := binary.BigEndian.Uint32(src[0:4])
+ s1 := binary.BigEndian.Uint32(src[4:8])
+ s2 := binary.BigEndian.Uint32(src[8:12])
+ s3 := binary.BigEndian.Uint32(src[12:16])
// First round just XORs input with key.
s0 ^= xk[0]
// Number of rounds is set by length of expanded key.
nr := len(xk)/4 - 2 // - 2: one above, one more below
k := 4
+ var t0, t1, t2, t3 uint32
for r := 0; r < nr; r++ {
t0 = xk[k+0] ^ te0[uint8(s0>>24)] ^ te1[uint8(s1>>16)] ^ te2[uint8(s2>>8)] ^ te3[uint8(s3)]
t1 = xk[k+1] ^ te0[uint8(s1>>24)] ^ te1[uint8(s2>>16)] ^ te2[uint8(s3>>8)] ^ te3[uint8(s0)]
s2 ^= xk[k+2]
s3 ^= xk[k+3]
- dst[0], dst[1], dst[2], dst[3] = byte(s0>>24), byte(s0>>16), byte(s0>>8), byte(s0)
- dst[4], dst[5], dst[6], dst[7] = byte(s1>>24), byte(s1>>16), byte(s1>>8), byte(s1)
- dst[8], dst[9], dst[10], dst[11] = byte(s2>>24), byte(s2>>16), byte(s2>>8), byte(s2)
- dst[12], dst[13], dst[14], dst[15] = byte(s3>>24), byte(s3>>16), byte(s3>>8), byte(s3)
+ _ = dst[15] // early bounds check
+ binary.BigEndian.PutUint32(dst[0:4], s0)
+ binary.BigEndian.PutUint32(dst[4:8], s1)
+ binary.BigEndian.PutUint32(dst[8:12], s2)
+ binary.BigEndian.PutUint32(dst[12:16], s3)
}
// Decrypt one block from src into dst, using the expanded key xk.
func decryptBlockGo(xk []uint32, dst, src []byte) {
- var s0, s1, s2, s3, t0, t1, t2, t3 uint32
-
- s0 = uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
- s1 = uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
- s2 = uint32(src[8])<<24 | uint32(src[9])<<16 | uint32(src[10])<<8 | uint32(src[11])
- s3 = uint32(src[12])<<24 | uint32(src[13])<<16 | uint32(src[14])<<8 | uint32(src[15])
+ _ = src[15] // early bounds check
+ s0 := binary.BigEndian.Uint32(src[0:4])
+ s1 := binary.BigEndian.Uint32(src[4:8])
+ s2 := binary.BigEndian.Uint32(src[8:12])
+ s3 := binary.BigEndian.Uint32(src[12:16])
// First round just XORs input with key.
s0 ^= xk[0]
// Number of rounds is set by length of expanded key.
nr := len(xk)/4 - 2 // - 2: one above, one more below
k := 4
+ var t0, t1, t2, t3 uint32
for r := 0; r < nr; r++ {
t0 = xk[k+0] ^ td0[uint8(s0>>24)] ^ td1[uint8(s3>>16)] ^ td2[uint8(s2>>8)] ^ td3[uint8(s1)]
t1 = xk[k+1] ^ td0[uint8(s1>>24)] ^ td1[uint8(s0>>16)] ^ td2[uint8(s3>>8)] ^ td3[uint8(s2)]
s2 ^= xk[k+2]
s3 ^= xk[k+3]
- dst[0], dst[1], dst[2], dst[3] = byte(s0>>24), byte(s0>>16), byte(s0>>8), byte(s0)
- dst[4], dst[5], dst[6], dst[7] = byte(s1>>24), byte(s1>>16), byte(s1>>8), byte(s1)
- dst[8], dst[9], dst[10], dst[11] = byte(s2>>24), byte(s2>>16), byte(s2>>8), byte(s2)
- dst[12], dst[13], dst[14], dst[15] = byte(s3>>24), byte(s3>>16), byte(s3>>8), byte(s3)
+ _ = dst[15] // early bounds check
+ binary.BigEndian.PutUint32(dst[0:4], s0)
+ binary.BigEndian.PutUint32(dst[4:8], s1)
+ binary.BigEndian.PutUint32(dst[8:12], s2)
+ binary.BigEndian.PutUint32(dst[12:16], s3)
}
// Apply sbox0 to each byte in w.
var i int
nk := len(key) / 4
for i = 0; i < nk; i++ {
- enc[i] = uint32(key[4*i])<<24 | uint32(key[4*i+1])<<16 | uint32(key[4*i+2])<<8 | uint32(key[4*i+3])
+ enc[i] = binary.BigEndian.Uint32(key[4*i:])
}
for ; i < len(enc); i++ {
t := enc[i-1]
import (
"crypto/cipher"
"crypto/internal/subtle"
- "unsafe"
+ "encoding/binary"
)
// Assert that aesCipherAsm implements the ctrAble interface.
}
var ac aesctr
ac.block = c
- ac.ctr[0] = *(*uint64)(unsafe.Pointer((&iv[0]))) // high bits
- ac.ctr[1] = *(*uint64)(unsafe.Pointer((&iv[8]))) // low bits
+ ac.ctr[0] = binary.BigEndian.Uint64(iv[0:]) // high bits
+ ac.ctr[1] = binary.BigEndian.Uint64(iv[8:]) // low bits
ac.buffer = ac.storage[:0]
return &ac
}
// Fill up the buffer with an incrementing count.
c.buffer = c.storage[:streamBufferSize]
c0, c1 := c.ctr[0], c.ctr[1]
- for i := 0; i < streamBufferSize; i += BlockSize {
- b0 := (*uint64)(unsafe.Pointer(&c.buffer[i]))
- b1 := (*uint64)(unsafe.Pointer(&c.buffer[i+BlockSize/2]))
- *b0, *b1 = c0, c1
+ for i := 0; i < streamBufferSize; i += 16 {
+ binary.BigEndian.PutUint64(c.buffer[i+0:], c0)
+ binary.BigEndian.PutUint64(c.buffer[i+8:], c1)
+
// Increment in big endian: c0 is high, c1 is low.
c1++
if c1 == 0 {
"crypto/cipher"
subtleoverlap "crypto/internal/subtle"
"crypto/subtle"
+ "encoding/binary"
"errors"
"internal/cpu"
)
// inc increments the rightmost 32-bits of the count value by 1.
func (x *gcmCount) inc() {
- // The compiler should optimize this to a 32-bit addition.
- n := uint32(x[15]) | uint32(x[14])<<8 | uint32(x[13])<<16 | uint32(x[12])<<24
- n += 1
- x[12] = byte(n >> 24)
- x[13] = byte(n >> 16)
- x[14] = byte(n >> 8)
- x[15] = byte(n)
+ binary.BigEndian.PutUint32(x[len(x)-4:], binary.BigEndian.Uint32(x[len(x)-4:])+1)
}
// gcmLengths writes len0 || len1 as big-endian values to a 16-byte array.
func gcmLengths(len0, len1 uint64) [16]byte {
- return [16]byte{
- byte(len0 >> 56),
- byte(len0 >> 48),
- byte(len0 >> 40),
- byte(len0 >> 32),
- byte(len0 >> 24),
- byte(len0 >> 16),
- byte(len0 >> 8),
- byte(len0),
- byte(len1 >> 56),
- byte(len1 >> 48),
- byte(len1 >> 40),
- byte(len1 >> 32),
- byte(len1 >> 24),
- byte(len1 >> 16),
- byte(len1 >> 8),
- byte(len1),
- }
+ v := [16]byte{}
+ binary.BigEndian.PutUint64(v[0:], len0)
+ binary.BigEndian.PutUint64(v[8:], len1)
+ return v
}
// gcmHashKey represents the 16-byte hash key required by the GHASH algorithm.
import (
subtleoverlap "crypto/internal/subtle"
"crypto/subtle"
+ "encoding/binary"
"errors"
)
}
// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM
-// standard and make getUint64 suitable for marshaling these values, the bits
-// are stored backwards. For example:
+// standard and make binary.BigEndian suitable for marshaling these values, the
+// bits are stored in big endian order. For example:
// the coefficient of x⁰ can be obtained by v.low >> 63.
// the coefficient of x⁶³ can be obtained by v.low & 1.
// the coefficient of x⁶⁴ can be obtained by v.high >> 63.
// would expect, say, 4*key to be in index 4 of the table but due to
// this bit ordering it will actually be in index 0010 (base 2) = 2.
x := gcmFieldElement{
- getUint64(key[:8]),
- getUint64(key[8:]),
+ binary.BigEndian.Uint64(key[:8]),
+ binary.BigEndian.Uint64(key[8:]),
}
g.productTable[reverseBits(1)] = x
// Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks.
func (g *gcm) updateBlocks(y *gcmFieldElement, blocks []byte) {
for len(blocks) > 0 {
- y.low ^= getUint64(blocks)
- y.high ^= getUint64(blocks[8:])
+ y.low ^= binary.BigEndian.Uint64(blocks)
+ y.high ^= binary.BigEndian.Uint64(blocks[8:])
g.mul(y)
blocks = blocks[gcmBlockSize:]
}
// gcmInc32 treats the final four bytes of counterBlock as a big-endian value
// and increments it.
func gcmInc32(counterBlock *[16]byte) {
- for i := gcmBlockSize - 1; i >= gcmBlockSize-4; i-- {
- counterBlock[i]++
- if counterBlock[i] != 0 {
- break
- }
- }
+ ctr := counterBlock[len(counterBlock)-4:]
+ binary.BigEndian.PutUint32(ctr, binary.BigEndian.Uint32(ctr)+1)
}
// sliceForAppend takes a slice and a requested number of bytes. It returns a
g.update(&y, nonce)
y.high ^= uint64(len(nonce)) * 8
g.mul(&y)
- putUint64(counter[:8], y.low)
- putUint64(counter[8:], y.high)
+ binary.BigEndian.PutUint64(counter[:8], y.low)
+ binary.BigEndian.PutUint64(counter[8:], y.high)
}
}
g.mul(&y)
- putUint64(out, y.low)
- putUint64(out[8:], y.high)
+ binary.BigEndian.PutUint64(out, y.low)
+ binary.BigEndian.PutUint64(out[8:], y.high)
xorWords(out, out, tagMask[:])
}
-
-func getUint64(data []byte) uint64 {
- _ = data[7] // bounds check hint to compiler; see golang.org/issue/14808
- r := uint64(data[0])<<56 |
- uint64(data[1])<<48 |
- uint64(data[2])<<40 |
- uint64(data[3])<<32 |
- uint64(data[4])<<24 |
- uint64(data[5])<<16 |
- uint64(data[6])<<8 |
- uint64(data[7])
- return r
-}
-
-func putUint64(out []byte, v uint64) {
- _ = out[7] // bounds check hint to compiler; see golang.org/issue/14808
- out[0] = byte(v >> 56)
- out[1] = byte(v >> 48)
- out[2] = byte(v >> 40)
- out[3] = byte(v >> 32)
- out[4] = byte(v >> 24)
- out[5] = byte(v >> 16)
- out[6] = byte(v >> 8)
- out[7] = byte(v)
-}
"bufio"
"crypto/aes"
"crypto/cipher"
+ "encoding/binary"
"io"
"os"
"runtime"
// dst = encrypt(t^seed)
// seed = encrypt(t^dst)
ns := time.Now().UnixNano()
- r.time[0] = byte(ns >> 56)
- r.time[1] = byte(ns >> 48)
- r.time[2] = byte(ns >> 40)
- r.time[3] = byte(ns >> 32)
- r.time[4] = byte(ns >> 24)
- r.time[5] = byte(ns >> 16)
- r.time[6] = byte(ns >> 8)
- r.time[7] = byte(ns)
+ binary.BigEndian.PutUint64(r.time[:], uint64(ns))
r.cipher.Encrypt(r.time[0:], r.time[0:])
for i := 0; i < aes.BlockSize; i++ {
r.dst[i] = r.time[i] ^ r.seed[i]
// and interface definitions, but nothing that makes
// system calls.
"crypto": {"L2", "hash"}, // interfaces
- "crypto/cipher": {"L2", "crypto/subtle", "crypto/internal/subtle"},
+ "crypto/cipher": {"L2", "crypto/subtle", "crypto/internal/subtle", "encoding/binary"},
"crypto/internal/subtle": {"unsafe", "reflect"}, // reflect behind a appengine tag
"crypto/subtle": {},
"encoding/base32": {"L2"},