summaryrefslogtreecommitdiffstats
path: root/src/crypto/cipher
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/cipher')
-rw-r--r--src/crypto/cipher/benchmark_test.go153
-rw-r--r--src/crypto/cipher/cbc.go163
-rw-r--r--src/crypto/cipher/cbc_aes_test.go104
-rw-r--r--src/crypto/cipher/cfb.go80
-rw-r--r--src/crypto/cipher/cfb_test.go113
-rw-r--r--src/crypto/cipher/cipher.go69
-rw-r--r--src/crypto/cipher/cipher_test.go90
-rw-r--r--src/crypto/cipher/common_test.go28
-rw-r--r--src/crypto/cipher/ctr.go91
-rw-r--r--src/crypto/cipher/ctr_aes_test.go102
-rw-r--r--src/crypto/cipher/ctr_test.go55
-rw-r--r--src/crypto/cipher/example_test.go363
-rw-r--r--src/crypto/cipher/export_test.go8
-rw-r--r--src/crypto/cipher/gcm.go426
-rw-r--r--src/crypto/cipher/gcm_test.go511
-rw-r--r--src/crypto/cipher/io.go53
-rw-r--r--src/crypto/cipher/ofb.go74
-rw-r--r--src/crypto/cipher/ofb_test.go102
-rw-r--r--src/crypto/cipher/xor_amd64.go27
-rw-r--r--src/crypto/cipher/xor_amd64.s54
-rw-r--r--src/crypto/cipher/xor_arm64.go29
-rw-r--r--src/crypto/cipher/xor_arm64.s67
-rw-r--r--src/crypto/cipher/xor_generic.go91
-rw-r--r--src/crypto/cipher/xor_ppc64x.go29
-rw-r--r--src/crypto/cipher/xor_ppc64x.s87
-rw-r--r--src/crypto/cipher/xor_test.go75
26 files changed, 3044 insertions, 0 deletions
diff --git a/src/crypto/cipher/benchmark_test.go b/src/crypto/cipher/benchmark_test.go
new file mode 100644
index 0000000..90d0cd7
--- /dev/null
+++ b/src/crypto/cipher/benchmark_test.go
@@ -0,0 +1,153 @@
+// Copyright 2013 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.
+
+package cipher_test
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "testing"
+)
+
+func benchmarkAESGCMSign(b *testing.B, buf []byte) {
+ b.SetBytes(int64(len(buf)))
+
+ var key [16]byte
+ var nonce [12]byte
+ aes, _ := aes.NewCipher(key[:])
+ aesgcm, _ := cipher.NewGCM(aes)
+ var out []byte
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ out = aesgcm.Seal(out[:0], nonce[:], nil, buf)
+ }
+}
+
+func benchmarkAESGCMSeal(b *testing.B, buf []byte) {
+ b.SetBytes(int64(len(buf)))
+
+ var key [16]byte
+ var nonce [12]byte
+ var ad [13]byte
+ aes, _ := aes.NewCipher(key[:])
+ aesgcm, _ := cipher.NewGCM(aes)
+ var out []byte
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ out = aesgcm.Seal(out[:0], nonce[:], buf, ad[:])
+ }
+}
+
+func benchmarkAESGCMOpen(b *testing.B, buf []byte) {
+ b.SetBytes(int64(len(buf)))
+
+ var key [16]byte
+ var nonce [12]byte
+ var ad [13]byte
+ aes, _ := aes.NewCipher(key[:])
+ aesgcm, _ := cipher.NewGCM(aes)
+ var out []byte
+ out = aesgcm.Seal(out[:0], nonce[:], buf, ad[:])
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := aesgcm.Open(buf[:0], nonce[:], out, ad[:])
+ if err != nil {
+ b.Errorf("Open: %v", err)
+ }
+ }
+}
+
+func BenchmarkAESGCMSeal1K(b *testing.B) {
+ benchmarkAESGCMSeal(b, make([]byte, 1024))
+}
+
+func BenchmarkAESGCMOpen1K(b *testing.B) {
+ benchmarkAESGCMOpen(b, make([]byte, 1024))
+}
+
+func BenchmarkAESGCMSign8K(b *testing.B) {
+ benchmarkAESGCMSign(b, make([]byte, 8*1024))
+}
+
+func BenchmarkAESGCMSeal8K(b *testing.B) {
+ benchmarkAESGCMSeal(b, make([]byte, 8*1024))
+}
+
+func BenchmarkAESGCMOpen8K(b *testing.B) {
+ benchmarkAESGCMOpen(b, make([]byte, 8*1024))
+}
+
+func benchmarkAESStream(b *testing.B, mode func(cipher.Block, []byte) cipher.Stream, buf []byte) {
+ b.SetBytes(int64(len(buf)))
+
+ var key [16]byte
+ var iv [16]byte
+ aes, _ := aes.NewCipher(key[:])
+ stream := mode(aes, iv[:])
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ stream.XORKeyStream(buf, buf)
+ }
+}
+
+// If we test exactly 1K blocks, we would generate exact multiples of
+// the cipher's block size, and the cipher stream fragments would
+// always be wordsize aligned, whereas non-aligned is a more typical
+// use-case.
+const almost1K = 1024 - 5
+const almost8K = 8*1024 - 5
+
+func BenchmarkAESCFBEncrypt1K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCFBEncrypter, make([]byte, almost1K))
+}
+
+func BenchmarkAESCFBDecrypt1K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost1K))
+}
+
+func BenchmarkAESCFBDecrypt8K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCFBDecrypter, make([]byte, almost8K))
+}
+
+func BenchmarkAESOFB1K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewOFB, make([]byte, almost1K))
+}
+
+func BenchmarkAESCTR1K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost1K))
+}
+
+func BenchmarkAESCTR8K(b *testing.B) {
+ benchmarkAESStream(b, cipher.NewCTR, make([]byte, almost8K))
+}
+
+func BenchmarkAESCBCEncrypt1K(b *testing.B) {
+ buf := make([]byte, 1024)
+ b.SetBytes(int64(len(buf)))
+
+ var key [16]byte
+ var iv [16]byte
+ aes, _ := aes.NewCipher(key[:])
+ cbc := cipher.NewCBCEncrypter(aes, iv[:])
+ for i := 0; i < b.N; i++ {
+ cbc.CryptBlocks(buf, buf)
+ }
+}
+
+func BenchmarkAESCBCDecrypt1K(b *testing.B) {
+ buf := make([]byte, 1024)
+ b.SetBytes(int64(len(buf)))
+
+ var key [16]byte
+ var iv [16]byte
+ aes, _ := aes.NewCipher(key[:])
+ cbc := cipher.NewCBCDecrypter(aes, iv[:])
+ for i := 0; i < b.N; i++ {
+ cbc.CryptBlocks(buf, buf)
+ }
+}
diff --git a/src/crypto/cipher/cbc.go b/src/crypto/cipher/cbc.go
new file mode 100644
index 0000000..0d07192
--- /dev/null
+++ b/src/crypto/cipher/cbc.go
@@ -0,0 +1,163 @@
+// Copyright 2009 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.
+
+// Cipher block chaining (CBC) mode.
+
+// CBC provides confidentiality by xoring (chaining) each plaintext block
+// with the previous ciphertext block before applying the block cipher.
+
+// See NIST SP 800-38A, pp 10-11
+
+package cipher
+
+import "crypto/internal/subtle"
+
+type cbc struct {
+ b Block
+ blockSize int
+ iv []byte
+ tmp []byte
+}
+
+func newCBC(b Block, iv []byte) *cbc {
+ return &cbc{
+ b: b,
+ blockSize: b.BlockSize(),
+ iv: dup(iv),
+ tmp: make([]byte, b.BlockSize()),
+ }
+}
+
+type cbcEncrypter cbc
+
+// cbcEncAble is an interface implemented by ciphers that have a specific
+// optimized implementation of CBC encryption, like crypto/aes.
+// NewCBCEncrypter will check for this interface and return the specific
+// BlockMode if found.
+type cbcEncAble interface {
+ NewCBCEncrypter(iv []byte) BlockMode
+}
+
+// NewCBCEncrypter returns a BlockMode which encrypts in cipher block chaining
+// mode, using the given Block. The length of iv must be the same as the
+// Block's block size.
+func NewCBCEncrypter(b Block, iv []byte) BlockMode {
+ if len(iv) != b.BlockSize() {
+ panic("cipher.NewCBCEncrypter: IV length must equal block size")
+ }
+ if cbc, ok := b.(cbcEncAble); ok {
+ return cbc.NewCBCEncrypter(iv)
+ }
+ return (*cbcEncrypter)(newCBC(b, iv))
+}
+
+func (x *cbcEncrypter) BlockSize() int { return x.blockSize }
+
+func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
+ if len(src)%x.blockSize != 0 {
+ panic("crypto/cipher: input not full blocks")
+ }
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
+
+ iv := x.iv
+
+ for len(src) > 0 {
+ // Write the xor to dst, then encrypt in place.
+ xorBytes(dst[:x.blockSize], src[:x.blockSize], iv)
+ x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize])
+
+ // Move to the next block with this block as the next iv.
+ iv = dst[:x.blockSize]
+ src = src[x.blockSize:]
+ dst = dst[x.blockSize:]
+ }
+
+ // Save the iv for the next CryptBlocks call.
+ copy(x.iv, iv)
+}
+
+func (x *cbcEncrypter) SetIV(iv []byte) {
+ if len(iv) != len(x.iv) {
+ panic("cipher: incorrect length IV")
+ }
+ copy(x.iv, iv)
+}
+
+type cbcDecrypter cbc
+
+// cbcDecAble is an interface implemented by ciphers that have a specific
+// optimized implementation of CBC decryption, like crypto/aes.
+// NewCBCDecrypter will check for this interface and return the specific
+// BlockMode if found.
+type cbcDecAble interface {
+ NewCBCDecrypter(iv []byte) BlockMode
+}
+
+// NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
+// mode, using the given Block. The length of iv must be the same as the
+// Block's block size and must match the iv used to encrypt the data.
+func NewCBCDecrypter(b Block, iv []byte) BlockMode {
+ if len(iv) != b.BlockSize() {
+ panic("cipher.NewCBCDecrypter: IV length must equal block size")
+ }
+ if cbc, ok := b.(cbcDecAble); ok {
+ return cbc.NewCBCDecrypter(iv)
+ }
+ return (*cbcDecrypter)(newCBC(b, iv))
+}
+
+func (x *cbcDecrypter) BlockSize() int { return x.blockSize }
+
+func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
+ if len(src)%x.blockSize != 0 {
+ panic("crypto/cipher: input not full blocks")
+ }
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
+ if len(src) == 0 {
+ return
+ }
+
+ // For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv).
+ // To avoid making a copy each time, we loop over the blocks BACKWARDS.
+ end := len(src)
+ start := end - x.blockSize
+ prev := start - x.blockSize
+
+ // Copy the last block of ciphertext in preparation as the new iv.
+ copy(x.tmp, src[start:end])
+
+ // Loop over all but the first block.
+ for start > 0 {
+ x.b.Decrypt(dst[start:end], src[start:end])
+ xorBytes(dst[start:end], dst[start:end], src[prev:start])
+
+ end = start
+ start = prev
+ prev -= x.blockSize
+ }
+
+ // The first block is special because it uses the saved iv.
+ x.b.Decrypt(dst[start:end], src[start:end])
+ xorBytes(dst[start:end], dst[start:end], x.iv)
+
+ // Set the new iv to the first block we copied earlier.
+ x.iv, x.tmp = x.tmp, x.iv
+}
+
+func (x *cbcDecrypter) SetIV(iv []byte) {
+ if len(iv) != len(x.iv) {
+ panic("cipher: incorrect length IV")
+ }
+ copy(x.iv, iv)
+}
diff --git a/src/crypto/cipher/cbc_aes_test.go b/src/crypto/cipher/cbc_aes_test.go
new file mode 100644
index 0000000..bf9e7ad
--- /dev/null
+++ b/src/crypto/cipher/cbc_aes_test.go
@@ -0,0 +1,104 @@
+// Copyright 2009 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.
+
+// CBC AES test vectors.
+
+// See U.S. National Institute of Standards and Technology (NIST)
+// Special Publication 800-38A, ``Recommendation for Block Cipher
+// Modes of Operation,'' 2001 Edition, pp. 24-29.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "testing"
+)
+
+var cbcAESTests = []struct {
+ name string
+ key []byte
+ iv []byte
+ in []byte
+ out []byte
+}{
+ // NIST SP 800-38A pp 27-29
+ {
+ "CBC-AES128",
+ commonKey128,
+ commonIV,
+ commonInput,
+ []byte{
+ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
+ 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
+ 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
+ 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7,
+ },
+ },
+ {
+ "CBC-AES192",
+ commonKey192,
+ commonIV,
+ commonInput,
+ []byte{
+ 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
+ 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
+ 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
+ 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81, 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd,
+ },
+ },
+ {
+ "CBC-AES256",
+ commonKey256,
+ commonIV,
+ commonInput,
+ []byte{
+ 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+ 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+ 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+ 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b,
+ },
+ },
+}
+
+func TestCBCEncrypterAES(t *testing.T) {
+ for _, test := range cbcAESTests {
+ c, err := aes.NewCipher(test.key)
+ if err != nil {
+ t.Errorf("%s: NewCipher(%d bytes) = %s", test.name, len(test.key), err)
+ continue
+ }
+
+ encrypter := cipher.NewCBCEncrypter(c, test.iv)
+
+ data := make([]byte, len(test.in))
+ copy(data, test.in)
+
+ encrypter.CryptBlocks(data, data)
+ if !bytes.Equal(test.out, data) {
+ t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test.name, data, test.out)
+ }
+ }
+}
+
+func TestCBCDecrypterAES(t *testing.T) {
+ for _, test := range cbcAESTests {
+ c, err := aes.NewCipher(test.key)
+ if err != nil {
+ t.Errorf("%s: NewCipher(%d bytes) = %s", test.name, len(test.key), err)
+ continue
+ }
+
+ decrypter := cipher.NewCBCDecrypter(c, test.iv)
+
+ data := make([]byte, len(test.out))
+ copy(data, test.out)
+
+ decrypter.CryptBlocks(data, data)
+ if !bytes.Equal(test.in, data) {
+ t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test.name, data, test.in)
+ }
+ }
+}
diff --git a/src/crypto/cipher/cfb.go b/src/crypto/cipher/cfb.go
new file mode 100644
index 0000000..80c9bc2
--- /dev/null
+++ b/src/crypto/cipher/cfb.go
@@ -0,0 +1,80 @@
+// Copyright 2010 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.
+
+// CFB (Cipher Feedback) Mode.
+
+package cipher
+
+import "crypto/internal/subtle"
+
+type cfb struct {
+ b Block
+ next []byte
+ out []byte
+ outUsed int
+
+ decrypt bool
+}
+
+func (x *cfb) XORKeyStream(dst, src []byte) {
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
+ for len(src) > 0 {
+ if x.outUsed == len(x.out) {
+ x.b.Encrypt(x.out, x.next)
+ x.outUsed = 0
+ }
+
+ if x.decrypt {
+ // We can precompute a larger segment of the
+ // keystream on decryption. This will allow
+ // larger batches for xor, and we should be
+ // able to match CTR/OFB performance.
+ copy(x.next[x.outUsed:], src)
+ }
+ n := xorBytes(dst, src, x.out[x.outUsed:])
+ if !x.decrypt {
+ copy(x.next[x.outUsed:], dst)
+ }
+ dst = dst[n:]
+ src = src[n:]
+ x.outUsed += n
+ }
+}
+
+// NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode,
+// using the given Block. The iv must be the same length as the Block's block
+// size.
+func NewCFBEncrypter(block Block, iv []byte) Stream {
+ return newCFB(block, iv, false)
+}
+
+// NewCFBDecrypter returns a Stream which decrypts with cipher feedback mode,
+// using the given Block. The iv must be the same length as the Block's block
+// size.
+func NewCFBDecrypter(block Block, iv []byte) Stream {
+ return newCFB(block, iv, true)
+}
+
+func newCFB(block Block, iv []byte, decrypt bool) Stream {
+ blockSize := block.BlockSize()
+ if len(iv) != blockSize {
+ // stack trace will indicate whether it was de or encryption
+ panic("cipher.newCFB: IV length must equal block size")
+ }
+ x := &cfb{
+ b: block,
+ out: make([]byte, blockSize),
+ next: make([]byte, blockSize),
+ outUsed: blockSize,
+ decrypt: decrypt,
+ }
+ copy(x.next, iv)
+
+ return x
+}
diff --git a/src/crypto/cipher/cfb_test.go b/src/crypto/cipher/cfb_test.go
new file mode 100644
index 0000000..72f62e6
--- /dev/null
+++ b/src/crypto/cipher/cfb_test.go
@@ -0,0 +1,113 @@
+// Copyright 2010 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.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/hex"
+ "testing"
+)
+
+// cfbTests contains the test vectors from
+// https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section
+// F.3.13.
+var cfbTests = []struct {
+ key, iv, plaintext, ciphertext string
+}{
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "000102030405060708090a0b0c0d0e0f",
+ "6bc1bee22e409f96e93d7e117393172a",
+ "3b3fd92eb72dad20333449f8e83cfb4a",
+ },
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "3B3FD92EB72DAD20333449F8E83CFB4A",
+ "ae2d8a571e03ac9c9eb76fac45af8e51",
+ "c8a64537a0b3a93fcde3cdad9f1ce58b",
+ },
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "C8A64537A0B3A93FCDE3CDAD9F1CE58B",
+ "30c81c46a35ce411e5fbc1191a0a52ef",
+ "26751f67a3cbb140b1808cf187a4f4df",
+ },
+ {
+ "2b7e151628aed2a6abf7158809cf4f3c",
+ "26751F67A3CBB140B1808CF187A4F4DF",
+ "f69f2445df4f9b17ad2b417be66c3710",
+ "c04b05357c5d1c0eeac4c66f9ff7f2e6",
+ },
+}
+
+func TestCFBVectors(t *testing.T) {
+ for i, test := range cfbTests {
+ key, err := hex.DecodeString(test.key)
+ if err != nil {
+ t.Fatal(err)
+ }
+ iv, err := hex.DecodeString(test.iv)
+ if err != nil {
+ t.Fatal(err)
+ }
+ plaintext, err := hex.DecodeString(test.plaintext)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expected, err := hex.DecodeString(test.ciphertext)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ciphertext := make([]byte, len(plaintext))
+ cfb := cipher.NewCFBEncrypter(block, iv)
+ cfb.XORKeyStream(ciphertext, plaintext)
+
+ if !bytes.Equal(ciphertext, expected) {
+ t.Errorf("#%d: wrong output: got %x, expected %x", i, ciphertext, expected)
+ }
+
+ cfbdec := cipher.NewCFBDecrypter(block, iv)
+ plaintextCopy := make([]byte, len(ciphertext))
+ cfbdec.XORKeyStream(plaintextCopy, ciphertext)
+
+ if !bytes.Equal(plaintextCopy, plaintext) {
+ t.Errorf("#%d: wrong plaintext: got %x, expected %x", i, plaintextCopy, plaintext)
+ }
+ }
+}
+
+func TestCFBInverse(t *testing.T) {
+ block, err := aes.NewCipher(commonKey128)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ plaintext := []byte("this is the plaintext. this is the plaintext.")
+ iv := make([]byte, block.BlockSize())
+ rand.Reader.Read(iv)
+ cfb := cipher.NewCFBEncrypter(block, iv)
+ ciphertext := make([]byte, len(plaintext))
+ copy(ciphertext, plaintext)
+ cfb.XORKeyStream(ciphertext, ciphertext)
+
+ cfbdec := cipher.NewCFBDecrypter(block, iv)
+ plaintextCopy := make([]byte, len(plaintext))
+ copy(plaintextCopy, ciphertext)
+ cfbdec.XORKeyStream(plaintextCopy, plaintextCopy)
+
+ if !bytes.Equal(plaintextCopy, plaintext) {
+ t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
+ }
+}
diff --git a/src/crypto/cipher/cipher.go b/src/crypto/cipher/cipher.go
new file mode 100644
index 0000000..7e1a4de
--- /dev/null
+++ b/src/crypto/cipher/cipher.go
@@ -0,0 +1,69 @@
+// Copyright 2010 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.
+
+// Package cipher implements standard block cipher modes that can be wrapped
+// around low-level block cipher implementations.
+// See https://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
+// and NIST Special Publication 800-38A.
+package cipher
+
+// A Block represents an implementation of block cipher
+// using a given key. It provides the capability to encrypt
+// or decrypt individual blocks. The mode implementations
+// extend that capability to streams of blocks.
+type Block interface {
+ // BlockSize returns the cipher's block size.
+ BlockSize() int
+
+ // Encrypt encrypts the first block in src into dst.
+ // Dst and src must overlap entirely or not at all.
+ Encrypt(dst, src []byte)
+
+ // Decrypt decrypts the first block in src into dst.
+ // Dst and src must overlap entirely or not at all.
+ Decrypt(dst, src []byte)
+}
+
+// A Stream represents a stream cipher.
+type Stream interface {
+ // XORKeyStream XORs each byte in the given slice with a byte from the
+ // cipher's key stream. Dst and src must overlap entirely or not at all.
+ //
+ // If len(dst) < len(src), XORKeyStream should panic. It is acceptable
+ // to pass a dst bigger than src, and in that case, XORKeyStream will
+ // only update dst[:len(src)] and will not touch the rest of dst.
+ //
+ // Multiple calls to XORKeyStream behave as if the concatenation of
+ // the src buffers was passed in a single run. That is, Stream
+ // maintains state and does not reset at each XORKeyStream call.
+ XORKeyStream(dst, src []byte)
+}
+
+// A BlockMode represents a block cipher running in a block-based mode (CBC,
+// ECB etc).
+type BlockMode interface {
+ // BlockSize returns the mode's block size.
+ BlockSize() int
+
+ // CryptBlocks encrypts or decrypts a number of blocks. The length of
+ // src must be a multiple of the block size. Dst and src must overlap
+ // entirely or not at all.
+ //
+ // If len(dst) < len(src), CryptBlocks should panic. It is acceptable
+ // to pass a dst bigger than src, and in that case, CryptBlocks will
+ // only update dst[:len(src)] and will not touch the rest of dst.
+ //
+ // Multiple calls to CryptBlocks behave as if the concatenation of
+ // the src buffers was passed in a single run. That is, BlockMode
+ // maintains state and does not reset at each CryptBlocks call.
+ CryptBlocks(dst, src []byte)
+}
+
+// Utility routines
+
+func dup(p []byte) []byte {
+ q := make([]byte, len(p))
+ copy(q, p)
+ return q
+}
diff --git a/src/crypto/cipher/cipher_test.go b/src/crypto/cipher/cipher_test.go
new file mode 100644
index 0000000..4d7cd6b
--- /dev/null
+++ b/src/crypto/cipher/cipher_test.go
@@ -0,0 +1,90 @@
+// Copyright 2013 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.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "testing"
+)
+
+func TestCryptBlocks(t *testing.T) {
+ buf := make([]byte, 16)
+ block, _ := aes.NewCipher(buf)
+
+ mode := cipher.NewCBCDecrypter(block, buf)
+ mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+ mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+
+ mode = cipher.NewCBCEncrypter(block, buf)
+ mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) })
+ mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) })
+}
+
+func mustPanic(t *testing.T, msg string, f func()) {
+ defer func() {
+ err := recover()
+ if err == nil {
+ t.Errorf("function did not panic, wanted %q", msg)
+ } else if err != msg {
+ t.Errorf("got panic %v, wanted %q", err, msg)
+ }
+ }()
+ f()
+}
+
+func TestEmptyPlaintext(t *testing.T) {
+ var key [16]byte
+ a, err := aes.NewCipher(key[:16])
+ if err != nil {
+ t.Fatal(err)
+ }
+ d, err := des.NewCipher(key[:8])
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ s := 16
+ pt := make([]byte, s)
+ ct := make([]byte, s)
+ for i := 0; i < 16; i++ {
+ pt[i], ct[i] = byte(i), byte(i)
+ }
+
+ assertEqual := func(name string, got, want []byte) {
+ if !bytes.Equal(got, want) {
+ t.Fatalf("%s: got %v, want %v", name, got, want)
+ }
+ }
+
+ for _, b := range []cipher.Block{a, d} {
+ iv := make([]byte, b.BlockSize())
+ cbce := cipher.NewCBCEncrypter(b, iv)
+ cbce.CryptBlocks(ct, pt[:0])
+ assertEqual("CBC encrypt", ct, pt)
+
+ cbcd := cipher.NewCBCDecrypter(b, iv)
+ cbcd.CryptBlocks(ct, pt[:0])
+ assertEqual("CBC decrypt", ct, pt)
+
+ cfbe := cipher.NewCFBEncrypter(b, iv)
+ cfbe.XORKeyStream(ct, pt[:0])
+ assertEqual("CFB encrypt", ct, pt)
+
+ cfbd := cipher.NewCFBDecrypter(b, iv)
+ cfbd.XORKeyStream(ct, pt[:0])
+ assertEqual("CFB decrypt", ct, pt)
+
+ ctr := cipher.NewCTR(b, iv)
+ ctr.XORKeyStream(ct, pt[:0])
+ assertEqual("CTR", ct, pt)
+
+ ofb := cipher.NewOFB(b, iv)
+ ofb.XORKeyStream(ct, pt[:0])
+ assertEqual("OFB", ct, pt)
+ }
+}
diff --git a/src/crypto/cipher/common_test.go b/src/crypto/cipher/common_test.go
new file mode 100644
index 0000000..c75c919
--- /dev/null
+++ b/src/crypto/cipher/common_test.go
@@ -0,0 +1,28 @@
+// Copyright 2009 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.
+
+package cipher_test
+
+// Common values for tests.
+
+var commonInput = []byte{
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
+}
+
+var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
+
+var commonKey192 = []byte{
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
+ 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
+}
+
+var commonKey256 = []byte{
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
+}
+
+var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
diff --git a/src/crypto/cipher/ctr.go b/src/crypto/cipher/ctr.go
new file mode 100644
index 0000000..cba028d
--- /dev/null
+++ b/src/crypto/cipher/ctr.go
@@ -0,0 +1,91 @@
+// Copyright 2009 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.
+
+// Counter (CTR) mode.
+
+// CTR converts a block cipher into a stream cipher by
+// repeatedly encrypting an incrementing counter and
+// xoring the resulting stream of data with the input.
+
+// See NIST SP 800-38A, pp 13-15
+
+package cipher
+
+import "crypto/internal/subtle"
+
+type ctr struct {
+ b Block
+ ctr []byte
+ out []byte
+ outUsed int
+}
+
+const streamBufferSize = 512
+
+// ctrAble is an interface implemented by ciphers that have a specific optimized
+// implementation of CTR, like crypto/aes. NewCTR will check for this interface
+// and return the specific Stream if found.
+type ctrAble interface {
+ NewCTR(iv []byte) Stream
+}
+
+// NewCTR returns a Stream which encrypts/decrypts using the given Block in
+// counter mode. The length of iv must be the same as the Block's block size.
+func NewCTR(block Block, iv []byte) Stream {
+ if ctr, ok := block.(ctrAble); ok {
+ return ctr.NewCTR(iv)
+ }
+ if len(iv) != block.BlockSize() {
+ panic("cipher.NewCTR: IV length must equal block size")
+ }
+ bufSize := streamBufferSize
+ if bufSize < block.BlockSize() {
+ bufSize = block.BlockSize()
+ }
+ return &ctr{
+ b: block,
+ ctr: dup(iv),
+ out: make([]byte, 0, bufSize),
+ outUsed: 0,
+ }
+}
+
+func (x *ctr) refill() {
+ remain := len(x.out) - x.outUsed
+ copy(x.out, x.out[x.outUsed:])
+ x.out = x.out[:cap(x.out)]
+ bs := x.b.BlockSize()
+ for remain <= len(x.out)-bs {
+ x.b.Encrypt(x.out[remain:], x.ctr)
+ remain += bs
+
+ // Increment counter
+ for i := len(x.ctr) - 1; i >= 0; i-- {
+ x.ctr[i]++
+ if x.ctr[i] != 0 {
+ break
+ }
+ }
+ }
+ x.out = x.out[:remain]
+ x.outUsed = 0
+}
+
+func (x *ctr) XORKeyStream(dst, src []byte) {
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
+ for len(src) > 0 {
+ if x.outUsed >= len(x.out)-x.b.BlockSize() {
+ x.refill()
+ }
+ n := xorBytes(dst, src, x.out[x.outUsed:])
+ dst = dst[n:]
+ src = src[n:]
+ x.outUsed += n
+ }
+}
diff --git a/src/crypto/cipher/ctr_aes_test.go b/src/crypto/cipher/ctr_aes_test.go
new file mode 100644
index 0000000..d019ae0
--- /dev/null
+++ b/src/crypto/cipher/ctr_aes_test.go
@@ -0,0 +1,102 @@
+// Copyright 2009 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.
+
+// CTR AES test vectors.
+
+// See U.S. National Institute of Standards and Technology (NIST)
+// Special Publication 800-38A, ``Recommendation for Block Cipher
+// Modes of Operation,'' 2001 Edition, pp. 55-58.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "testing"
+)
+
+var commonCounter = []byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}
+
+var ctrAESTests = []struct {
+ name string
+ key []byte
+ iv []byte
+ in []byte
+ out []byte
+}{
+ // NIST SP 800-38A pp 55-58
+ {
+ "CTR-AES128",
+ commonKey128,
+ commonCounter,
+ commonInput,
+ []byte{
+ 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce,
+ 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
+ 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab,
+ 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee,
+ },
+ },
+ {
+ "CTR-AES192",
+ commonKey192,
+ commonCounter,
+ commonInput,
+ []byte{
+ 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b,
+ 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94,
+ 0x1e, 0x36, 0xb2, 0x6b, 0xd1, 0xeb, 0xc6, 0x70, 0xd1, 0xbd, 0x1d, 0x66, 0x56, 0x20, 0xab, 0xf7,
+ 0x4f, 0x78, 0xa7, 0xf6, 0xd2, 0x98, 0x09, 0x58, 0x5a, 0x97, 0xda, 0xec, 0x58, 0xc6, 0xb0, 0x50,
+ },
+ },
+ {
+ "CTR-AES256",
+ commonKey256,
+ commonCounter,
+ commonInput,
+ []byte{
+ 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28,
+ 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5,
+ 0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d,
+ 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6,
+ },
+ },
+}
+
+func TestCTR_AES(t *testing.T) {
+ for _, tt := range ctrAESTests {
+ test := tt.name
+
+ c, err := aes.NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
+ continue
+ }
+
+ for j := 0; j <= 5; j += 5 {
+ in := tt.in[0 : len(tt.in)-j]
+ ctr := cipher.NewCTR(c, tt.iv)
+ encrypted := make([]byte, len(in))
+ ctr.XORKeyStream(encrypted, in)
+ if out := tt.out[0:len(in)]; !bytes.Equal(out, encrypted) {
+ t.Errorf("%s/%d: CTR\ninpt %x\nhave %x\nwant %x", test, len(in), in, encrypted, out)
+ }
+ }
+
+ for j := 0; j <= 7; j += 7 {
+ in := tt.out[0 : len(tt.out)-j]
+ ctr := cipher.NewCTR(c, tt.iv)
+ plain := make([]byte, len(in))
+ ctr.XORKeyStream(plain, in)
+ if out := tt.in[0:len(in)]; !bytes.Equal(out, plain) {
+ t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), plain, out)
+ }
+ }
+
+ if t.Failed() {
+ break
+ }
+ }
+}
diff --git a/src/crypto/cipher/ctr_test.go b/src/crypto/cipher/ctr_test.go
new file mode 100644
index 0000000..e5cce57
--- /dev/null
+++ b/src/crypto/cipher/ctr_test.go
@@ -0,0 +1,55 @@
+// Copyright 2015 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.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "testing"
+)
+
+type noopBlock int
+
+func (b noopBlock) BlockSize() int { return int(b) }
+func (noopBlock) Encrypt(dst, src []byte) { copy(dst, src) }
+func (noopBlock) Decrypt(dst, src []byte) { copy(dst, src) }
+
+func inc(b []byte) {
+ for i := len(b) - 1; i >= 0; i++ {
+ b[i]++
+ if b[i] != 0 {
+ break
+ }
+ }
+}
+
+func xor(a, b []byte) {
+ for i := range a {
+ a[i] ^= b[i]
+ }
+}
+
+func TestCTR(t *testing.T) {
+ for size := 64; size <= 1024; size *= 2 {
+ iv := make([]byte, size)
+ ctr := cipher.NewCTR(noopBlock(size), iv)
+ src := make([]byte, 1024)
+ for i := range src {
+ src[i] = 0xff
+ }
+ want := make([]byte, 1024)
+ copy(want, src)
+ counter := make([]byte, size)
+ for i := 1; i < len(want)/size; i++ {
+ inc(counter)
+ xor(want[i*size:(i+1)*size], counter)
+ }
+ dst := make([]byte, 1024)
+ ctr.XORKeyStream(dst, src)
+ if !bytes.Equal(dst, want) {
+ t.Errorf("for size %d\nhave %x\nwant %x", size, dst, want)
+ }
+ }
+}
diff --git a/src/crypto/cipher/example_test.go b/src/crypto/cipher/example_test.go
new file mode 100644
index 0000000..9c32d6a
--- /dev/null
+++ b/src/crypto/cipher/example_test.go
@@ -0,0 +1,363 @@
+// Copyright 2012 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.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "os"
+)
+
+func ExampleNewGCM_encrypt() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // Seal/Open calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ // When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
+ key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
+ plaintext := []byte("exampleplaintext")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ // Never use more than 2^32 random nonces with a given key because of the risk of a repeat.
+ nonce := make([]byte, 12)
+ if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+ panic(err.Error())
+ }
+
+ aesgcm, err := cipher.NewGCM(block)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
+ fmt.Printf("%x\n", ciphertext)
+}
+
+func ExampleNewGCM_decrypt() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // Seal/Open calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ // When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
+ key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
+ ciphertext, _ := hex.DecodeString("c3aaa29f002ca75870806e44086700f62ce4d43e902b3888e23ceff797a7a471")
+ nonce, _ := hex.DecodeString("64a9433eae7ccceee2fc0eda")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ aesgcm, err := cipher.NewGCM(block)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ fmt.Printf("%s\n", plaintext)
+ // Output: exampleplaintext
+}
+
+func ExampleNewCBCDecrypter() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // NewCipher calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ key, _ := hex.DecodeString("6368616e676520746869732070617373")
+ ciphertext, _ := hex.DecodeString("73c86d43a9d700a253a96c85b0f6b03ac9792e0e757f869cca306bd3cba1c62b")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ if len(ciphertext) < aes.BlockSize {
+ panic("ciphertext too short")
+ }
+ iv := ciphertext[:aes.BlockSize]
+ ciphertext = ciphertext[aes.BlockSize:]
+
+ // CBC mode always works in whole blocks.
+ if len(ciphertext)%aes.BlockSize != 0 {
+ panic("ciphertext is not a multiple of the block size")
+ }
+
+ mode := cipher.NewCBCDecrypter(block, iv)
+
+ // CryptBlocks can work in-place if the two arguments are the same.
+ mode.CryptBlocks(ciphertext, ciphertext)
+
+ // If the original plaintext lengths are not a multiple of the block
+ // size, padding would have to be added when encrypting, which would be
+ // removed at this point. For an example, see
+ // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's
+ // critical to note that ciphertexts must be authenticated (i.e. by
+ // using crypto/hmac) before being decrypted in order to avoid creating
+ // a padding oracle.
+
+ fmt.Printf("%s\n", ciphertext)
+ // Output: exampleplaintext
+}
+
+func ExampleNewCBCEncrypter() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // NewCipher calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ key, _ := hex.DecodeString("6368616e676520746869732070617373")
+ plaintext := []byte("exampleplaintext")
+
+ // CBC mode works on blocks so plaintexts may need to be padded to the
+ // next whole block. For an example of such padding, see
+ // https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
+ // assume that the plaintext is already of the correct length.
+ if len(plaintext)%aes.BlockSize != 0 {
+ panic("plaintext is not a multiple of the block size")
+ }
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ panic(err)
+ }
+
+ mode := cipher.NewCBCEncrypter(block, iv)
+ mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
+
+ // It's important to remember that ciphertexts must be authenticated
+ // (i.e. by using crypto/hmac) as well as being encrypted in order to
+ // be secure.
+
+ fmt.Printf("%x\n", ciphertext)
+}
+
+func ExampleNewCFBDecrypter() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // NewCipher calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ key, _ := hex.DecodeString("6368616e676520746869732070617373")
+ ciphertext, _ := hex.DecodeString("7dd015f06bec7f1b8f6559dad89f4131da62261786845100056b353194ad")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ if len(ciphertext) < aes.BlockSize {
+ panic("ciphertext too short")
+ }
+ iv := ciphertext[:aes.BlockSize]
+ ciphertext = ciphertext[aes.BlockSize:]
+
+ stream := cipher.NewCFBDecrypter(block, iv)
+
+ // XORKeyStream can work in-place if the two arguments are the same.
+ stream.XORKeyStream(ciphertext, ciphertext)
+ fmt.Printf("%s", ciphertext)
+ // Output: some plaintext
+}
+
+func ExampleNewCFBEncrypter() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // NewCipher calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ key, _ := hex.DecodeString("6368616e676520746869732070617373")
+ plaintext := []byte("some plaintext")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ panic(err)
+ }
+
+ stream := cipher.NewCFBEncrypter(block, iv)
+ stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+ // It's important to remember that ciphertexts must be authenticated
+ // (i.e. by using crypto/hmac) as well as being encrypted in order to
+ // be secure.
+ fmt.Printf("%x\n", ciphertext)
+}
+
+func ExampleNewCTR() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // NewCipher calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ key, _ := hex.DecodeString("6368616e676520746869732070617373")
+ plaintext := []byte("some plaintext")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ panic(err)
+ }
+
+ stream := cipher.NewCTR(block, iv)
+ stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+ // It's important to remember that ciphertexts must be authenticated
+ // (i.e. by using crypto/hmac) as well as being encrypted in order to
+ // be secure.
+
+ // CTR mode is the same for both encryption and decryption, so we can
+ // also decrypt that ciphertext with NewCTR.
+
+ plaintext2 := make([]byte, len(plaintext))
+ stream = cipher.NewCTR(block, iv)
+ stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
+
+ fmt.Printf("%s\n", plaintext2)
+ // Output: some plaintext
+}
+
+func ExampleNewOFB() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // NewCipher calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ key, _ := hex.DecodeString("6368616e676520746869732070617373")
+ plaintext := []byte("some plaintext")
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // The IV needs to be unique, but not secure. Therefore it's common to
+ // include it at the beginning of the ciphertext.
+ ciphertext := make([]byte, aes.BlockSize+len(plaintext))
+ iv := ciphertext[:aes.BlockSize]
+ if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+ panic(err)
+ }
+
+ stream := cipher.NewOFB(block, iv)
+ stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
+
+ // It's important to remember that ciphertexts must be authenticated
+ // (i.e. by using crypto/hmac) as well as being encrypted in order to
+ // be secure.
+
+ // OFB mode is the same for both encryption and decryption, so we can
+ // also decrypt that ciphertext with NewOFB.
+
+ plaintext2 := make([]byte, len(plaintext))
+ stream = cipher.NewOFB(block, iv)
+ stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
+
+ fmt.Printf("%s\n", plaintext2)
+ // Output: some plaintext
+}
+
+func ExampleStreamReader() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // NewCipher calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ key, _ := hex.DecodeString("6368616e676520746869732070617373")
+
+ encrypted, _ := hex.DecodeString("cf0495cc6f75dafc23948538e79904a9")
+ bReader := bytes.NewReader(encrypted)
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // If the key is unique for each ciphertext, then it's ok to use a zero
+ // IV.
+ var iv [aes.BlockSize]byte
+ stream := cipher.NewOFB(block, iv[:])
+
+ reader := &cipher.StreamReader{S: stream, R: bReader}
+ // Copy the input to the output stream, decrypting as we go.
+ if _, err := io.Copy(os.Stdout, reader); err != nil {
+ panic(err)
+ }
+
+ // Note that this example is simplistic in that it omits any
+ // authentication of the encrypted data. If you were actually to use
+ // StreamReader in this manner, an attacker could flip arbitrary bits in
+ // the output.
+
+ // Output: some secret text
+}
+
+func ExampleStreamWriter() {
+ // Load your secret key from a safe place and reuse it across multiple
+ // NewCipher calls. (Obviously don't use this example key for anything
+ // real.) If you want to convert a passphrase to a key, use a suitable
+ // package like bcrypt or scrypt.
+ key, _ := hex.DecodeString("6368616e676520746869732070617373")
+
+ bReader := bytes.NewReader([]byte("some secret text"))
+
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+
+ // If the key is unique for each ciphertext, then it's ok to use a zero
+ // IV.
+ var iv [aes.BlockSize]byte
+ stream := cipher.NewOFB(block, iv[:])
+
+ var out bytes.Buffer
+
+ writer := &cipher.StreamWriter{S: stream, W: &out}
+ // Copy the input to the output buffer, encrypting as we go.
+ if _, err := io.Copy(writer, bReader); err != nil {
+ panic(err)
+ }
+
+ // Note that this example is simplistic in that it omits any
+ // authentication of the encrypted data. If you were actually to use
+ // StreamReader in this manner, an attacker could flip arbitrary bits in
+ // the decrypted result.
+
+ fmt.Printf("%x\n", out.Bytes())
+ // Output: cf0495cc6f75dafc23948538e79904a9
+}
diff --git a/src/crypto/cipher/export_test.go b/src/crypto/cipher/export_test.go
new file mode 100644
index 0000000..cf8007a
--- /dev/null
+++ b/src/crypto/cipher/export_test.go
@@ -0,0 +1,8 @@
+// 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.
+
+package cipher
+
+// Export internal functions for testing.
+var XorBytes = xorBytes
diff --git a/src/crypto/cipher/gcm.go b/src/crypto/cipher/gcm.go
new file mode 100644
index 0000000..ba0af84
--- /dev/null
+++ b/src/crypto/cipher/gcm.go
@@ -0,0 +1,426 @@
+// Copyright 2013 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.
+
+package cipher
+
+import (
+ subtleoverlap "crypto/internal/subtle"
+ "crypto/subtle"
+ "encoding/binary"
+ "errors"
+)
+
+// AEAD is a cipher mode providing authenticated encryption with associated
+// data. For a description of the methodology, see
+// https://en.wikipedia.org/wiki/Authenticated_encryption
+type AEAD interface {
+ // NonceSize returns the size of the nonce that must be passed to Seal
+ // and Open.
+ NonceSize() int
+
+ // Overhead returns the maximum difference between the lengths of a
+ // plaintext and its ciphertext.
+ Overhead() int
+
+ // Seal encrypts and authenticates plaintext, authenticates the
+ // additional data and appends the result to dst, returning the updated
+ // slice. The nonce must be NonceSize() bytes long and unique for all
+ // time, for a given key.
+ //
+ // To reuse plaintext's storage for the encrypted output, use plaintext[:0]
+ // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
+ Seal(dst, nonce, plaintext, additionalData []byte) []byte
+
+ // Open decrypts and authenticates ciphertext, authenticates the
+ // additional data and, if successful, appends the resulting plaintext
+ // to dst, returning the updated slice. The nonce must be NonceSize()
+ // bytes long and both it and the additional data must match the
+ // value passed to Seal.
+ //
+ // To reuse ciphertext's storage for the decrypted output, use ciphertext[:0]
+ // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
+ //
+ // Even if the function fails, the contents of dst, up to its capacity,
+ // may be overwritten.
+ Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error)
+}
+
+// gcmAble is an interface implemented by ciphers that have a specific optimized
+// implementation of GCM, like crypto/aes. NewGCM will check for this interface
+// and return the specific AEAD if found.
+type gcmAble interface {
+ NewGCM(nonceSize, tagSize int) (AEAD, error)
+}
+
+// gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM
+// 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.
+// the coefficient of x¹²⁷ can be obtained by v.high & 1.
+type gcmFieldElement struct {
+ low, high uint64
+}
+
+// gcm represents a Galois Counter Mode with a specific key. See
+// https://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+type gcm struct {
+ cipher Block
+ nonceSize int
+ tagSize int
+ // productTable contains the first sixteen powers of the key, H.
+ // However, they are in bit reversed order. See NewGCMWithNonceSize.
+ productTable [16]gcmFieldElement
+}
+
+// NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode
+// with the standard nonce length.
+//
+// In general, the GHASH operation performed by this implementation of GCM is not constant-time.
+// An exception is when the underlying Block was created by aes.NewCipher
+// on systems with hardware support for AES. See the crypto/aes package documentation for details.
+func NewGCM(cipher Block) (AEAD, error) {
+ return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, gcmTagSize)
+}
+
+// NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois
+// Counter Mode, which accepts nonces of the given length. The length must not
+// be zero.
+//
+// Only use this function if you require compatibility with an existing
+// cryptosystem that uses non-standard nonce lengths. All other users should use
+// NewGCM, which is faster and more resistant to misuse.
+func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) {
+ return newGCMWithNonceAndTagSize(cipher, size, gcmTagSize)
+}
+
+// NewGCMWithTagSize returns the given 128-bit, block cipher wrapped in Galois
+// Counter Mode, which generates tags with the given length.
+//
+// Tag sizes between 12 and 16 bytes are allowed.
+//
+// Only use this function if you require compatibility with an existing
+// cryptosystem that uses non-standard tag lengths. All other users should use
+// NewGCM, which is more resistant to misuse.
+func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error) {
+ return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, tagSize)
+}
+
+func newGCMWithNonceAndTagSize(cipher Block, nonceSize, tagSize int) (AEAD, error) {
+ if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize {
+ return nil, errors.New("cipher: incorrect tag size given to GCM")
+ }
+
+ if nonceSize <= 0 {
+ return nil, errors.New("cipher: the nonce can't have zero length, or the security of the key will be immediately compromised")
+ }
+
+ if cipher, ok := cipher.(gcmAble); ok {
+ return cipher.NewGCM(nonceSize, tagSize)
+ }
+
+ if cipher.BlockSize() != gcmBlockSize {
+ return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
+ }
+
+ var key [gcmBlockSize]byte
+ cipher.Encrypt(key[:], key[:])
+
+ g := &gcm{cipher: cipher, nonceSize: nonceSize, tagSize: tagSize}
+
+ // We precompute 16 multiples of |key|. However, when we do lookups
+ // into this table we'll be using bits from a field element and
+ // therefore the bits will be in the reverse order. So normally one
+ // 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{
+ binary.BigEndian.Uint64(key[:8]),
+ binary.BigEndian.Uint64(key[8:]),
+ }
+ g.productTable[reverseBits(1)] = x
+
+ for i := 2; i < 16; i += 2 {
+ g.productTable[reverseBits(i)] = gcmDouble(&g.productTable[reverseBits(i/2)])
+ g.productTable[reverseBits(i+1)] = gcmAdd(&g.productTable[reverseBits(i)], &x)
+ }
+
+ return g, nil
+}
+
+const (
+ gcmBlockSize = 16
+ gcmTagSize = 16
+ gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes.
+ gcmStandardNonceSize = 12
+)
+
+func (g *gcm) NonceSize() int {
+ return g.nonceSize
+}
+
+func (g *gcm) Overhead() int {
+ return g.tagSize
+}
+
+func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
+ if len(nonce) != g.nonceSize {
+ panic("crypto/cipher: incorrect nonce length given to GCM")
+ }
+ if uint64(len(plaintext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize()) {
+ panic("crypto/cipher: message too large for GCM")
+ }
+
+ ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+ if subtleoverlap.InexactOverlap(out, plaintext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
+
+ var counter, tagMask [gcmBlockSize]byte
+ g.deriveCounter(&counter, nonce)
+
+ g.cipher.Encrypt(tagMask[:], counter[:])
+ gcmInc32(&counter)
+
+ g.counterCrypt(out, plaintext, &counter)
+
+ var tag [gcmTagSize]byte
+ g.auth(tag[:], out[:len(plaintext)], data, &tagMask)
+ copy(out[len(plaintext):], tag[:])
+
+ return ret
+}
+
+var errOpen = errors.New("cipher: message authentication failed")
+
+func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
+ if len(nonce) != g.nonceSize {
+ panic("crypto/cipher: incorrect nonce length given to GCM")
+ }
+ // Sanity check to prevent the authentication from always succeeding if an implementation
+ // leaves tagSize uninitialized, for example.
+ if g.tagSize < gcmMinimumTagSize {
+ panic("crypto/cipher: incorrect GCM tag size")
+ }
+
+ if len(ciphertext) < g.tagSize {
+ return nil, errOpen
+ }
+ if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize())+uint64(g.tagSize) {
+ return nil, errOpen
+ }
+
+ tag := ciphertext[len(ciphertext)-g.tagSize:]
+ ciphertext = ciphertext[:len(ciphertext)-g.tagSize]
+
+ var counter, tagMask [gcmBlockSize]byte
+ g.deriveCounter(&counter, nonce)
+
+ g.cipher.Encrypt(tagMask[:], counter[:])
+ gcmInc32(&counter)
+
+ var expectedTag [gcmTagSize]byte
+ g.auth(expectedTag[:], ciphertext, data, &tagMask)
+
+ ret, out := sliceForAppend(dst, len(ciphertext))
+ if subtleoverlap.InexactOverlap(out, ciphertext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
+
+ if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
+ // The AESNI code decrypts and authenticates concurrently, and
+ // so overwrites dst in the event of a tag mismatch. That
+ // behavior is mimicked here in order to be consistent across
+ // platforms.
+ for i := range out {
+ out[i] = 0
+ }
+ return nil, errOpen
+ }
+
+ g.counterCrypt(out, ciphertext, &counter)
+
+ return ret, nil
+}
+
+// reverseBits reverses the order of the bits of 4-bit number in i.
+func reverseBits(i int) int {
+ i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
+ i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
+ return i
+}
+
+// gcmAdd adds two elements of GF(2¹²⁸) and returns the sum.
+func gcmAdd(x, y *gcmFieldElement) gcmFieldElement {
+ // Addition in a characteristic 2 field is just XOR.
+ return gcmFieldElement{x.low ^ y.low, x.high ^ y.high}
+}
+
+// gcmDouble returns the result of doubling an element of GF(2¹²⁸).
+func gcmDouble(x *gcmFieldElement) (double gcmFieldElement) {
+ msbSet := x.high&1 == 1
+
+ // Because of the bit-ordering, doubling is actually a right shift.
+ double.high = x.high >> 1
+ double.high |= x.low << 63
+ double.low = x.low >> 1
+
+ // If the most-significant bit was set before shifting then it,
+ // conceptually, becomes a term of x^128. This is greater than the
+ // irreducible polynomial so the result has to be reduced. The
+ // irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to
+ // eliminate the term at x^128 which also means subtracting the other
+ // four terms. In characteristic 2 fields, subtraction == addition ==
+ // XOR.
+ if msbSet {
+ double.low ^= 0xe100000000000000
+ }
+
+ return
+}
+
+var gcmReductionTable = []uint16{
+ 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
+ 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
+}
+
+// mul sets y to y*H, where H is the GCM key, fixed during NewGCMWithNonceSize.
+func (g *gcm) mul(y *gcmFieldElement) {
+ var z gcmFieldElement
+
+ for i := 0; i < 2; i++ {
+ word := y.high
+ if i == 1 {
+ word = y.low
+ }
+
+ // Multiplication works by multiplying z by 16 and adding in
+ // one of the precomputed multiples of H.
+ for j := 0; j < 64; j += 4 {
+ msw := z.high & 0xf
+ z.high >>= 4
+ z.high |= z.low << 60
+ z.low >>= 4
+ z.low ^= uint64(gcmReductionTable[msw]) << 48
+
+ // the values in |table| are ordered for
+ // little-endian bit positions. See the comment
+ // in NewGCMWithNonceSize.
+ t := &g.productTable[word&0xf]
+
+ z.low ^= t.low
+ z.high ^= t.high
+ word >>= 4
+ }
+ }
+
+ *y = z
+}
+
+// updateBlocks extends y with more polynomial terms from blocks, based on
+// 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 ^= binary.BigEndian.Uint64(blocks)
+ y.high ^= binary.BigEndian.Uint64(blocks[8:])
+ g.mul(y)
+ blocks = blocks[gcmBlockSize:]
+ }
+}
+
+// update extends y with more polynomial terms from data. If data is not a
+// multiple of gcmBlockSize bytes long then the remainder is zero padded.
+func (g *gcm) update(y *gcmFieldElement, data []byte) {
+ fullBlocks := (len(data) >> 4) << 4
+ g.updateBlocks(y, data[:fullBlocks])
+
+ if len(data) != fullBlocks {
+ var partialBlock [gcmBlockSize]byte
+ copy(partialBlock[:], data[fullBlocks:])
+ g.updateBlocks(y, partialBlock[:])
+ }
+}
+
+// gcmInc32 treats the final four bytes of counterBlock as a big-endian value
+// and increments it.
+func gcmInc32(counterBlock *[16]byte) {
+ 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
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+ if total := len(in) + n; cap(in) >= total {
+ head = in[:total]
+ } else {
+ head = make([]byte, total)
+ copy(head, in)
+ }
+ tail = head[len(in):]
+ return
+}
+
+// counterCrypt crypts in to out using g.cipher in counter mode.
+func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
+ var mask [gcmBlockSize]byte
+
+ for len(in) >= gcmBlockSize {
+ g.cipher.Encrypt(mask[:], counter[:])
+ gcmInc32(counter)
+
+ xorWords(out, in, mask[:])
+ out = out[gcmBlockSize:]
+ in = in[gcmBlockSize:]
+ }
+
+ if len(in) > 0 {
+ g.cipher.Encrypt(mask[:], counter[:])
+ gcmInc32(counter)
+ xorBytes(out, in, mask[:])
+ }
+}
+
+// deriveCounter computes the initial GCM counter state from the given nonce.
+// See NIST SP 800-38D, section 7.1. This assumes that counter is filled with
+// zeros on entry.
+func (g *gcm) deriveCounter(counter *[gcmBlockSize]byte, nonce []byte) {
+ // GCM has two modes of operation with respect to the initial counter
+ // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path"
+ // for nonces of other lengths. For a 96-bit nonce, the nonce, along
+ // with a four-byte big-endian counter starting at one, is used
+ // directly as the starting counter. For other nonce sizes, the counter
+ // is computed by passing it through the GHASH function.
+ if len(nonce) == gcmStandardNonceSize {
+ copy(counter[:], nonce)
+ counter[gcmBlockSize-1] = 1
+ } else {
+ var y gcmFieldElement
+ g.update(&y, nonce)
+ y.high ^= uint64(len(nonce)) * 8
+ g.mul(&y)
+ binary.BigEndian.PutUint64(counter[:8], y.low)
+ binary.BigEndian.PutUint64(counter[8:], y.high)
+ }
+}
+
+// auth calculates GHASH(ciphertext, additionalData), masks the result with
+// tagMask and writes the result to out.
+func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) {
+ var y gcmFieldElement
+ g.update(&y, additionalData)
+ g.update(&y, ciphertext)
+
+ y.low ^= uint64(len(additionalData)) * 8
+ y.high ^= uint64(len(ciphertext)) * 8
+
+ g.mul(&y)
+
+ binary.BigEndian.PutUint64(out, y.low)
+ binary.BigEndian.PutUint64(out[8:], y.high)
+
+ xorWords(out, out, tagMask[:])
+}
diff --git a/src/crypto/cipher/gcm_test.go b/src/crypto/cipher/gcm_test.go
new file mode 100644
index 0000000..0d53e47
--- /dev/null
+++ b/src/crypto/cipher/gcm_test.go
@@ -0,0 +1,511 @@
+// Copyright 2013 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.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/hex"
+ "errors"
+ "io"
+ "reflect"
+ "testing"
+)
+
+var aesGCMTests = []struct {
+ key, nonce, plaintext, ad, result string
+}{
+ {
+ "11754cd72aec309bf52f7687212e8957",
+ "3c819d9a9bed087615030b65",
+ "",
+ "",
+ "250327c674aaf477aef2675748cf6971",
+ },
+ {
+ "ca47248ac0b6f8372a97ac43508308ed",
+ "ffd2b598feabc9019262d2be",
+ "",
+ "",
+ "60d20404af527d248d893ae495707d1a",
+ },
+ {
+ "fbe3467cc254f81be8e78d765a2e6333",
+ "c6697351ff4aec29cdbaabf2",
+ "",
+ "67",
+ "3659cdc25288bf499ac736c03bfc1159",
+ },
+ {
+ "8a7f9d80d08ad0bd5a20fb689c88f9fc",
+ "88b7b27d800937fda4f47301",
+ "",
+ "50edd0503e0d7b8c91608eb5a1",
+ "ed6f65322a4740011f91d2aae22dd44e",
+ },
+ {
+ "051758e95ed4abb2cdc69bb454110e82",
+ "c99a66320db73158a35a255d",
+ "",
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339f",
+ "6ce77f1a5616c505b6aec09420234036",
+ },
+ {
+ "77be63708971c4e240d1cb79e8d77feb",
+ "e0e00f19fed7ba0136a797f3",
+ "",
+ "7a43ec1d9c0a5a78a0b16533a6213cab",
+ "209fcc8d3675ed938e9c7166709dd946",
+ },
+ {
+ "7680c5d3ca6154758e510f4d25b98820",
+ "f8f105f9c3df4965780321f8",
+ "",
+ "c94c410194c765e3dcc7964379758ed3",
+ "94dca8edfcf90bb74b153c8d48a17930",
+ },
+ {
+ "7fddb57453c241d03efbed3ac44e371c",
+ "ee283a3fc75575e33efd4887",
+ "d5de42b461646c255c87bd2962d3b9a2",
+ "",
+ "2ccda4a5415cb91e135c2a0f78c9b2fdb36d1df9b9d5e596f83e8b7f52971cb3",
+ },
+ {
+ "ab72c77b97cb5fe9a382d9fe81ffdbed",
+ "54cc7dc2c37ec006bcc6d1da",
+ "007c5e5b3e59df24a7c355584fc1518d",
+ "",
+ "0e1bde206a07a9c2c1b65300f8c649972b4401346697138c7a4891ee59867d0c",
+ },
+ {
+ "fe47fcce5fc32665d2ae399e4eec72ba",
+ "5adb9609dbaeb58cbd6e7275",
+ "7c0e88c88899a779228465074797cd4c2e1498d259b54390b85e3eef1c02df60e743f1b840382c4bccaf3bafb4ca8429bea063",
+ "88319d6e1d3ffa5f987199166c8a9b56c2aeba5a",
+ "98f4826f05a265e6dd2be82db241c0fbbbf9ffb1c173aa83964b7cf5393043736365253ddbc5db8778371495da76d269e5db3e291ef1982e4defedaa2249f898556b47",
+ },
+ {
+ "ec0c2ba17aa95cd6afffe949da9cc3a8",
+ "296bce5b50b7d66096d627ef",
+ "b85b3753535b825cbe5f632c0b843c741351f18aa484281aebec2f45bb9eea2d79d987b764b9611f6c0f8641843d5d58f3a242",
+ "f8d00f05d22bf68599bcdeb131292ad6e2df5d14",
+ "a7443d31c26bdf2a1c945e29ee4bd344a99cfaf3aa71f8b3f191f83c2adfc7a07162995506fde6309ffc19e716eddf1a828c5a890147971946b627c40016da1ecf3e77",
+ },
+ {
+ "2c1f21cf0f6fb3661943155c3e3d8492",
+ "23cb5ff362e22426984d1907",
+ "42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d68b5615ba7c1220ff6510e259f06655d8",
+ "5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f4488f33cfb5e979e42b6e1cfc0a60238982a7aec",
+ "81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222b6ad57af43e1895df9dca2a5344a62cc57a3ee28136e94c74838997ae9823f3a",
+ },
+ {
+ "d9f7d2411091f947b4d6f1e2d1f0fb2e",
+ "e1934f5db57cc983e6b180e7",
+ "73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490c2c6f6166f4a59431e182663fcaea05a",
+ "0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a20115d2e51398344b16bee1ed7c499b353d6c597af8",
+ "aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d573c7891c2a91fbc48db29967ec9542b2321b51ca862cb637cdd03b99a0f93b134",
+ },
+ {
+ "fe9bb47deb3a61e423c2231841cfd1fb",
+ "4d328eb776f500a2f7fb47aa",
+ "f1cc3818e421876bb6b8bbd6c9",
+ "",
+ "b88c5c1977b35b517b0aeae96743fd4727fe5cdb4b5b42818dea7ef8c9",
+ },
+ {
+ "6703df3701a7f54911ca72e24dca046a",
+ "12823ab601c350ea4bc2488c",
+ "793cd125b0b84a043e3ac67717",
+ "",
+ "b2051c80014f42f08735a7b0cd38e6bcd29962e5f2c13626b85a877101",
+ },
+ // These cases test non-standard nonce sizes.
+ {
+ "1672c3537afa82004c6b8a46f6f0d026",
+ "05",
+ "",
+ "",
+ "8e2ad721f9455f74d8b53d3141f27e8e",
+ },
+ {
+ "9a4fea86a621a91ab371e492457796c0",
+ "75",
+ "ca6131faf0ff210e4e693d6c31c109fc5b6f54224eb120f37de31dc59ec669b6",
+ "4f6e2585c161f05a9ae1f2f894e9f0ab52b45d0f",
+ "5698c0a384241d30004290aac56bb3ece6fe8eacc5c4be98954deb9c3ff6aebf5d50e1af100509e1fba2a5e8a0af9670",
+ },
+ {
+ "d0f1f4defa1e8c08b4b26d576392027c",
+ "42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac",
+ "",
+ "",
+ "7ab49b57ddf5f62c427950111c5c4f0d",
+ },
+ {
+ "4a0c00a3d284dea9d4bf8b8dde86685e",
+ "f8cbe82588e784bcacbe092cd9089b51e01527297f635bf294b3aa787d91057ef23869789698ac960707857f163ecb242135a228ad93964f5dc4a4d7f88fd7b3b07dd0a5b37f9768fb05a523639f108c34c661498a56879e501a2321c8a4a94d7e1b89db255ac1f685e185263368e99735ebe62a7f2931b47282be8eb165e4d7",
+ "6d4bf87640a6a48a50d28797b7",
+ "8d8c7ffc55086d539b5a8f0d1232654c",
+ "0d803ec309482f35b8e6226f2b56303239298e06b281c2d51aaba3c125",
+ },
+ {
+ "0e18a844ac5bf38e4cd72d9b0942e506",
+ "0870d4b28a2954489a0abcd5",
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b3",
+ "05eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea9",
+ "cace28f4976afd72e3c5128167eb788fbf6634dda0a2f53148d00f6fa557f5e9e8f736c12e450894af56cb67f7d99e1027258c8571bd91ee3b7360e0d508aa1f382411a16115f9c05251cc326d4016f62e0eb8151c048465b0c6c8ff12558d43310e18b2cb1889eec91557ce21ba05955cf4c1d4847aadfb1b0a83f3a3b82b7efa62a5f03c5d6eda381a85dd78dbc55c",
+ },
+ {
+ "1f6c3a3bc0542aabba4ef8f6c7169e73",
+ "f3584606472b260e0dd2ebb2",
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d8def4f89d4b66335c1c7e4248367d8ed9612ec453902d8e50af89d7709d1a596c1f41f",
+ "95aa82ca6c49ae90cd1668baac7aa6f2b4a8ca99b2c2372acb08cf61c9c3805e6e0328da4cd76a19edd2d3994c798b0022569ad418d1fee4d9cd45a391c601ffc92ad91501432fee150287617c13629e69fc7281cd7165a63eab49cf714bce3a75a74f76ea7e64ff81eb61fdfec39b67bf0de98c7e4e32bdf97c8c6ac75ba43c02f4b2ed7216ecf3014df000108b67cf99505b179f8ed4980a6103d1bca70dbe9bbfab0ed59801d6e5f2d6f67d3ec5168e212e2daf02c6b963c98a1f7097de0c56891a2b211b01070dd8fd8b16c2a1a4e3cfd292d2984b3561d555d16c33ddc2bcf7edde13efe520c7e2abdda44d81881c531aeeeb66244c3b791ea8acfb6a68",
+ "55864065117e07650ca650a0f0d9ef4b02aee7c58928462fddb49045bf85355b4653fa26158210a7f3ef5b3ca48612e8b7adf5c025c1b821960af770d935df1c9a1dd25077d6b1c7f937b2e20ce981b07980880214698f3fad72fa370b3b7da257ce1d0cf352bc5304fada3e0f8927bd4e5c1abbffa563bdedcb567daa64faaed748cb361732200ba3506836a3c1c82aafa14c76dc07f6c4277ff2c61325f91fdbd6c1883e745fcaadd5a6d692eeaa5ad56eead6a9d74a595d22757ed89532a4b8831e2b9e2315baea70a9b95d228f09d491a5ed5ab7076766703457e3159bbb9b17b329525669863153079448c68cd2f200c0be9d43061a60639cb59d50993d276c05caaa565db8ce633b2673e4012bebbca02b1a64d779d04066f3e949ece173825885ec816468c819a8129007cc05d8785c48077d09eb1abcba14508dde85a6f16a744bc95faef24888d53a8020515ab20307efaecbdf143a26563c67989bceedc2d6d2bb9699bb6c615d93767e4158c1124e3b6c723aaa47796e59a60d3696cd85adfae9a62f2c02c22009f80ed494bdc587f31dd892c253b5c6d6b7db078fa72d23474ee54f8144d6561182d71c862941dbc0b2cb37a4d4b23cbad5637e6be901cc73f16d5aec39c60dddee631511e57b47520b61ae1892d2d1bd2b486e30faec892f171b6de98d96108016fac805604761f8e74742b3bb7dc8a290a46bf697c3e4446e6e65832cbae7cf1aaad1",
+ },
+ {
+ "0795d80bc7f40f4d41c280271a2e4f7f",
+ "ff824c906594aff365d3cb1f",
+ "1ad4e74d127f935beee57cff920665babe7ce56227377afe570ba786193ded3412d4812453157f42fafc418c02a746c1232c234a639d49baa8f041c12e2ef540027764568ce49886e0d913e28059a3a485c6eee96337a30b28e4cd5612c2961539fa6bc5de034cbedc5fa15db844013e0bef276e27ca7a4faf47a5c1093bd643354108144454d221b3737e6cb87faac36ed131959babe44af2890cfcc4e23ffa24470e689ce0894f5407bb0c8665cff536008ad2ac6f1c9ef8289abd0bd9b72f21c597bda5210cf928c805af2dd4a464d52e36819d521f967bba5386930ab5b4cf4c71746d7e6e964673457348e9d71d170d9eb560bd4bdb779e610ba816bf776231ebd0af5966f5cdab6815944032ab4dd060ad8dab880549e910f1ffcf6862005432afad",
+ "98a47a430d8fd74dc1829a91e3481f8ed024d8ba34c9b903321b04864db333e558ae28653dffb2",
+ "3b8f91443480e647473a0a0b03d571c622b7e70e4309a02c9bb7980053010d865e6aec161354dc9f481b2cd5213e09432b57ec4e58fbd0a8549dd15c8c4e74a6529f75fad0ce5a9e20e2beeb2f91eb638bf88999968de438d2f1cedbfb0a1c81f9e8e7362c738e0fddd963692a4f4df9276b7f040979ce874cf6fa3de26da0713784bdb25e4efcb840554ef5b38b5fe8380549a496bd8e423a7456df6f4ae78a07ebe2276a8e22fc2243ec4f78abe0c99c733fd67c8c492699fa5ee2289cdd0a8d469bf883520ee74efb854bfadc7366a49ee65ca4e894e3335e2b672618d362eee12a577dd8dc2ba55c49c1fc3ad68180e9b112d0234d4aa28f5661f1e036450ca6f18be0166676bd80f8a4890c6ddea306fabb7ff3cb2860aa32a827e3a312912a2dfa70f6bc1c07de238448f2d751bd0cf15bf7",
+ },
+ {
+ "e2e001a36c60d2bf40d69ff5b2b1161ea218db263be16a4e",
+ "84230643130d05425826641e",
+ "adb034f3f4a7ca45e2993812d113a9821d50df151af978bccc6d3bc113e15bc0918fb385377dca1916022ce816d56a332649484043c0fc0f2d37d040182b00a9bbb42ef231f80b48fb3730110d9a4433e38c73264c703579a705b9c031b969ec6d98de9f90e9e78b21179c2eb1e061946cd4bbb844f031ecf6eaac27a4151311adf1b03eda97c9fbae66295f468af4b35faf6ba39f9d8f95873bbc2b51cf3dfec0ed3c9b850696336cc093b24a8765a936d14dd56edc6bf518272169f75e67b74ba452d0aae90416a997c8f31e2e9d54ffea296dc69462debc8347b3e1af6a2d53bdfdfda601134f98db42b609df0a08c9347590c8d86e845bb6373d65a26ab85f67b50569c85401a396b8ad76c2b53ff62bcfbf033e435ef47b9b591d05117c6dc681d68e",
+ "d5d7316b8fdee152942148bff007c22e4b2022c6bc7be3c18c5f2e52e004e0b5dc12206bf002bd",
+ "f2c39423ee630dfe961da81909159dba018ce09b1073a12a477108316af5b7a31f86be6a0548b572d604bd115ea737dde899e0bd7f7ac9b23e38910dc457551ecc15c814a9f46d8432a1a36097dc1afe2712d1ba0838fa88cb55d9f65a2e9bece0dbf8999562503989041a2c87d7eb80ef649769d2f4978ce5cf9664f2bd0849646aa81cb976e45e1ade2f17a8126219e917aadbb4bae5e2c4b3f57bbc7f13fcc807df7842d9727a1b389e0b749e5191482adacabd812627c6eae2c7a30caf0844ad2a22e08f39edddf0ae10413e47db433dfe3febbb5a5cec9ade21fbba1e548247579395880b747669a8eb7e2ec0c1bff7fed2defdb92b07a14edf07b1bde29c31ab052ff1214e6b5ebbefcb8f21b5d6f8f6e07ee57ad6e14d4e142cb3f51bb465ab3a28a2a12f01b7514ad0463f2bde0d71d221",
+ },
+ {
+ "5394e890d37ba55ec9d5f327f15680f6a63ef5279c79331643ad0af6d2623525",
+ "815e840b7aca7af3b324583f",
+ "8e63067cd15359f796b43c68f093f55fdf3589fc5f2fdfad5f9d156668a617f7091d73da71cdd207810e6f71a165d0809a597df9885ca6e8f9bb4e616166586b83cc45f49917fc1a256b8bc7d05c476ab5c4633e20092619c4747b26dad3915e9fd65238ee4e5213badeda8a3a22f5efe6582d0762532026c89b4ca26fdd000eb45347a2a199b55b7790e6b1b2dba19833ce9f9522c0bcea5b088ccae68dd99ae0203c81b9f1dd3181c3e2339e83ccd1526b67742b235e872bea5111772aab574ae7d904d9b6355a79178e179b5ae8edc54f61f172bf789ea9c9af21f45b783e4251421b077776808f04972a5e801723cf781442378ce0e0568f014aea7a882dcbcb48d342be53d1c2ebfb206b12443a8a587cc1e55ca23beca385d61d0d03e9d84cbc1b0a",
+ "0feccdfae8ed65fa31a0858a1c466f79e8aa658c2f3ba93c3f92158b4e30955e1c62580450beff",
+ "b69a7e17bb5af688883274550a4ded0d1aff49a0b18343f4b382f745c163f7f714c9206a32a1ff012427e19431951edd0a755e5f491b0eedfd7df68bbc6085dd2888607a2f998c3e881eb1694109250db28291e71f4ad344a125624fb92e16ea9815047cd1111cabfdc9cb8c3b4b0f40aa91d31774009781231400789ed545404af6c3f76d07ddc984a7bd8f52728159782832e298cc4d529be96d17be898efd83e44dc7b0e2efc645849fd2bba61fef0ae7be0dcab233cc4e2b7ba4e887de9c64b97f2a1818aa54371a8d629dae37975f7784e5e3cc77055ed6e975b1e5f55e6bbacdc9f295ce4ada2c16113cd5b323cf78b7dde39f4a87aa8c141a31174e3584ccbd380cf5ec6d1dba539928b084fa9683e9c0953acf47cc3ac384a2c38914f1da01fb2cfd78905c2b58d36b2574b9df15535d82",
+ },
+ // These cases test non-standard tag sizes.
+ {
+ "89c54b0d3bc3c397d5039058c220685f",
+ "bc7f45c00868758d62d4bb4d",
+ "582670b0baf5540a3775b6615605bd05",
+ "48d16cda0337105a50e2ed76fd18e114",
+ "fc2d4c4eee2209ddbba6663c02765e6955e783b00156f5da0446e2970b877f",
+ },
+ {
+ "bad6049678bf75c9087b3e3ae7e72c13",
+ "a0a017b83a67d8f1b883e561",
+ "a1be93012f05a1958440f74a5311f4a1",
+ "f7c27b51d5367161dc2ff1e9e3edc6f2",
+ "36f032f7e3dc3275ca22aedcdc68436b99a2227f8bb69d45ea5d8842cd08",
+ },
+ {
+ "66a3c722ccf9709525650973ecc100a9",
+ "1621d42d3a6d42a2d2bf9494",
+ "61fa9dbbed2190fbc2ffabf5d2ea4ff8",
+ "d7a9b6523b8827068a6354a6d166c6b9",
+ "fef3b20f40e08a49637cc82f4c89b8603fd5c0132acfab97b5fff651c4",
+ },
+ {
+ "562ae8aadb8d23e0f271a99a7d1bd4d1",
+ "f7a5e2399413b89b6ad31aff",
+ "bbdc3504d803682aa08a773cde5f231a",
+ "2b9680b886b3efb7c6354b38c63b5373",
+ "e2b7e5ed5ff27fc8664148f5a628a46dcbf2015184fffb82f2651c36",
+ },
+ {
+ "11754cd72aec309bf52f7687212e8957",
+ "",
+ "",
+ "",
+ "250327c674aaf477aef2675748cf6971",
+ },
+}
+
+func TestAESGCM(t *testing.T) {
+ for i, test := range aesGCMTests {
+ key, _ := hex.DecodeString(test.key)
+ aes, err := aes.NewCipher(key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ nonce, _ := hex.DecodeString(test.nonce)
+ plaintext, _ := hex.DecodeString(test.plaintext)
+ ad, _ := hex.DecodeString(test.ad)
+ tagSize := (len(test.result) - len(test.plaintext)) / 2
+
+ var aesgcm cipher.AEAD
+ switch {
+ // Handle non-standard tag sizes
+ case tagSize != 16:
+ aesgcm, err = cipher.NewGCMWithTagSize(aes, tagSize)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Handle 0 nonce size (expect error and continue)
+ case len(nonce) == 0:
+ aesgcm, err = cipher.NewGCMWithNonceSize(aes, 0)
+ if err == nil {
+ t.Fatal("expected error for zero nonce size")
+ }
+ continue
+
+ // Handle non-standard nonce sizes
+ case len(nonce) != 12:
+ aesgcm, err = cipher.NewGCMWithNonceSize(aes, len(nonce))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ default:
+ aesgcm, err = cipher.NewGCM(aes)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ ct := aesgcm.Seal(nil, nonce, plaintext, ad)
+ if ctHex := hex.EncodeToString(ct); ctHex != test.result {
+ t.Errorf("#%d: got %s, want %s", i, ctHex, test.result)
+ continue
+ }
+
+ plaintext2, err := aesgcm.Open(nil, nonce, ct, ad)
+ if err != nil {
+ t.Errorf("#%d: Open failed", i)
+ continue
+ }
+
+ if !bytes.Equal(plaintext, plaintext2) {
+ t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
+ continue
+ }
+
+ if len(ad) > 0 {
+ ad[0] ^= 0x80
+ if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering additional data", i)
+ }
+ ad[0] ^= 0x80
+ }
+
+ nonce[0] ^= 0x80
+ if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering nonce", i)
+ }
+ nonce[0] ^= 0x80
+
+ ct[0] ^= 0x80
+ if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering ciphertext", i)
+ }
+ ct[0] ^= 0x80
+ }
+}
+
+func TestGCMInvalidTagSize(t *testing.T) {
+ key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed")
+
+ aes, _ := aes.NewCipher(key)
+
+ for _, tagSize := range []int{0, 1, aes.BlockSize() + 1} {
+ aesgcm, err := cipher.NewGCMWithTagSize(aes, tagSize)
+ if aesgcm != nil || err == nil {
+ t.Fatalf("NewGCMWithNonceAndTagSize was successful with an invalid %d-byte tag size", tagSize)
+ }
+ }
+}
+
+func TestTagFailureOverwrite(t *testing.T) {
+ // The AESNI GCM code decrypts and authenticates concurrently and so
+ // overwrites the output buffer before checking the authentication tag.
+ // In order to be consistent across platforms, all implementations
+ // should do this and this test checks that.
+
+ key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed")
+ nonce, _ := hex.DecodeString("54cc7dc2c37ec006bcc6d1db")
+ ciphertext, _ := hex.DecodeString("0e1bde206a07a9c2c1b65300f8c649972b4401346697138c7a4891ee59867d0c")
+
+ aes, _ := aes.NewCipher(key)
+ aesgcm, _ := cipher.NewGCM(aes)
+
+ dst := make([]byte, len(ciphertext)-16)
+ for i := range dst {
+ dst[i] = 42
+ }
+
+ result, err := aesgcm.Open(dst[:0], nonce, ciphertext, nil)
+ if err == nil {
+ t.Fatal("Bad Open still resulted in nil error.")
+ }
+
+ if result != nil {
+ t.Fatal("Failed Open returned non-nil result.")
+ }
+
+ for i := range dst {
+ if dst[i] != 0 {
+ t.Fatal("Failed Open didn't zero dst buffer")
+ }
+ }
+}
+
+func TestGCMCounterWrap(t *testing.T) {
+ // Test that the last 32-bits of the counter wrap correctly.
+ tests := []struct {
+ nonce, tag string
+ }{
+ {"0fa72e25", "37e1948cdfff09fbde0c40ad99fee4a7"}, // counter: 7eb59e4d961dad0dfdd75aaffffffff0
+ {"afe05cc1", "438f3aa9fee5e54903b1927bca26bbdf"}, // counter: 75d492a7e6e6bfc979ad3a8ffffffff4
+ {"9ffecbef", "7b88ca424df9703e9e8611071ec7e16e"}, // counter: c8bb108b0ecdc71747b9d57ffffffff5
+ {"ffc3e5b3", "38d49c86e0abe853ac250e66da54c01a"}, // counter: 706414d2de9b36ab3b900a9ffffffff6
+ {"cfdd729d", "e08402eaac36a1a402e09b1bd56500e8"}, // counter: cd0b96fe36b04e750584e56ffffffff7
+ {"010ae3d486", "5405bb490b1f95d01e2ba735687154bc"}, // counter: e36c18e69406c49722808104fffffff8
+ {"01b1107a9d", "939a585f342e01e17844627492d44dbf"}, // counter: e6d56eaf9127912b6d62c6dcffffffff
+ }
+ key, err := aes.NewCipher(make([]byte, 16))
+ if err != nil {
+ t.Fatal(err)
+ }
+ plaintext := make([]byte, 16*17+1)
+ for i, test := range tests {
+ nonce, _ := hex.DecodeString(test.nonce)
+ want, _ := hex.DecodeString(test.tag)
+ aead, err := cipher.NewGCMWithNonceSize(key, len(nonce))
+ if err != nil {
+ t.Fatal(err)
+ }
+ got := aead.Seal(nil, nonce, plaintext, nil)
+ if !bytes.Equal(got[len(plaintext):], want) {
+ t.Errorf("test[%v]: got: %x, want: %x", i, got[len(plaintext):], want)
+ }
+ _, err = aead.Open(nil, nonce, got, nil)
+ if err != nil {
+ t.Errorf("test[%v]: authentication failed", i)
+ }
+ }
+}
+
+var _ cipher.Block = (*wrapper)(nil)
+
+type wrapper struct {
+ block cipher.Block
+}
+
+func (w *wrapper) BlockSize() int { return w.block.BlockSize() }
+func (w *wrapper) Encrypt(dst, src []byte) { w.block.Encrypt(dst, src) }
+func (w *wrapper) Decrypt(dst, src []byte) { w.block.Decrypt(dst, src) }
+
+// wrap wraps the Block interface so that it does not fulfill
+// any optimizing interfaces such as gcmAble.
+func wrap(b cipher.Block) cipher.Block {
+ return &wrapper{b}
+}
+
+func TestGCMAsm(t *testing.T) {
+ // Create a new pair of AEADs, one using the assembly implementation
+ // and one using the generic Go implementation.
+ newAESGCM := func(key []byte) (asm, generic cipher.AEAD, err error) {
+ block, err := aes.NewCipher(key[:])
+ if err != nil {
+ return nil, nil, err
+ }
+ asm, err = cipher.NewGCM(block)
+ if err != nil {
+ return nil, nil, err
+ }
+ generic, err = cipher.NewGCM(wrap(block))
+ if err != nil {
+ return nil, nil, err
+ }
+ return asm, generic, nil
+ }
+
+ // check for assembly implementation
+ var key [16]byte
+ asm, generic, err := newAESGCM(key[:])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if reflect.TypeOf(asm) == reflect.TypeOf(generic) {
+ t.Skipf("no assembly implementation of GCM")
+ }
+
+ // generate permutations
+ type pair struct{ align, length int }
+ lengths := []int{0, 156, 8192, 8193, 8208}
+ keySizes := []int{16, 24, 32}
+ alignments := []int{0, 1, 2, 3}
+ if testing.Short() {
+ keySizes = []int{16}
+ alignments = []int{1}
+ }
+ perms := make([]pair, 0)
+ for _, l := range lengths {
+ for _, a := range alignments {
+ if a != 0 && l == 0 {
+ continue
+ }
+ perms = append(perms, pair{align: a, length: l})
+ }
+ }
+
+ // run test for all permutations
+ test := func(ks int, pt, ad []byte) error {
+ key := make([]byte, ks)
+ if _, err := io.ReadFull(rand.Reader, key); err != nil {
+ return err
+ }
+ asm, generic, err := newAESGCM(key)
+ if err != nil {
+ return err
+ }
+ if _, err := io.ReadFull(rand.Reader, pt); err != nil {
+ return err
+ }
+ if _, err := io.ReadFull(rand.Reader, ad); err != nil {
+ return err
+ }
+ nonce := make([]byte, 12)
+ if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+ return err
+ }
+ want := generic.Seal(nil, nonce, pt, ad)
+ got := asm.Seal(nil, nonce, pt, ad)
+ if !bytes.Equal(want, got) {
+ return errors.New("incorrect Seal output")
+ }
+ got, err = asm.Open(nil, nonce, want, ad)
+ if err != nil {
+ return errors.New("authentication failed")
+ }
+ if !bytes.Equal(pt, got) {
+ return errors.New("incorrect Open output")
+ }
+ return nil
+ }
+ for _, a := range perms {
+ ad := make([]byte, a.align+a.length)
+ ad = ad[a.align:]
+ for _, p := range perms {
+ pt := make([]byte, p.align+p.length)
+ pt = pt[p.align:]
+ for _, ks := range keySizes {
+ if err := test(ks, pt, ad); err != nil {
+ t.Error(err)
+ t.Errorf(" key size: %v", ks)
+ t.Errorf(" plaintext alignment: %v", p.align)
+ t.Errorf(" plaintext length: %v", p.length)
+ t.Errorf(" additionalData alignment: %v", a.align)
+ t.Fatalf(" additionalData length: %v", a.length)
+ }
+ }
+ }
+ }
+}
diff --git a/src/crypto/cipher/io.go b/src/crypto/cipher/io.go
new file mode 100644
index 0000000..0974ac7
--- /dev/null
+++ b/src/crypto/cipher/io.go
@@ -0,0 +1,53 @@
+// Copyright 2010 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.
+
+package cipher
+
+import "io"
+
+// The Stream* objects are so simple that all their members are public. Users
+// can create them themselves.
+
+// StreamReader wraps a Stream into an io.Reader. It calls XORKeyStream
+// to process each slice of data which passes through.
+type StreamReader struct {
+ S Stream
+ R io.Reader
+}
+
+func (r StreamReader) Read(dst []byte) (n int, err error) {
+ n, err = r.R.Read(dst)
+ r.S.XORKeyStream(dst[:n], dst[:n])
+ return
+}
+
+// StreamWriter wraps a Stream into an io.Writer. It calls XORKeyStream
+// to process each slice of data which passes through. If any Write call
+// returns short then the StreamWriter is out of sync and must be discarded.
+// A StreamWriter has no internal buffering; Close does not need
+// to be called to flush write data.
+type StreamWriter struct {
+ S Stream
+ W io.Writer
+ Err error // unused
+}
+
+func (w StreamWriter) Write(src []byte) (n int, err error) {
+ c := make([]byte, len(src))
+ w.S.XORKeyStream(c, src)
+ n, err = w.W.Write(c)
+ if n != len(src) && err == nil { // should never happen
+ err = io.ErrShortWrite
+ }
+ return
+}
+
+// Close closes the underlying Writer and returns its Close return value, if the Writer
+// is also an io.Closer. Otherwise it returns nil.
+func (w StreamWriter) Close() error {
+ if c, ok := w.W.(io.Closer); ok {
+ return c.Close()
+ }
+ return nil
+}
diff --git a/src/crypto/cipher/ofb.go b/src/crypto/cipher/ofb.go
new file mode 100644
index 0000000..fc47724
--- /dev/null
+++ b/src/crypto/cipher/ofb.go
@@ -0,0 +1,74 @@
+// Copyright 2011 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.
+
+// OFB (Output Feedback) Mode.
+
+package cipher
+
+import "crypto/internal/subtle"
+
+type ofb struct {
+ b Block
+ cipher []byte
+ out []byte
+ outUsed int
+}
+
+// NewOFB returns a Stream that encrypts or decrypts using the block cipher b
+// in output feedback mode. The initialization vector iv's length must be equal
+// to b's block size.
+func NewOFB(b Block, iv []byte) Stream {
+ blockSize := b.BlockSize()
+ if len(iv) != blockSize {
+ panic("cipher.NewOFB: IV length must equal block size")
+ }
+ bufSize := streamBufferSize
+ if bufSize < blockSize {
+ bufSize = blockSize
+ }
+ x := &ofb{
+ b: b,
+ cipher: make([]byte, blockSize),
+ out: make([]byte, 0, bufSize),
+ outUsed: 0,
+ }
+
+ copy(x.cipher, iv)
+ return x
+}
+
+func (x *ofb) refill() {
+ bs := x.b.BlockSize()
+ remain := len(x.out) - x.outUsed
+ if remain > x.outUsed {
+ return
+ }
+ copy(x.out, x.out[x.outUsed:])
+ x.out = x.out[:cap(x.out)]
+ for remain < len(x.out)-bs {
+ x.b.Encrypt(x.cipher, x.cipher)
+ copy(x.out[remain:], x.cipher)
+ remain += bs
+ }
+ x.out = x.out[:remain]
+ x.outUsed = 0
+}
+
+func (x *ofb) XORKeyStream(dst, src []byte) {
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
+ for len(src) > 0 {
+ if x.outUsed >= len(x.out)-x.b.BlockSize() {
+ x.refill()
+ }
+ n := xorBytes(dst, src, x.out[x.outUsed:])
+ dst = dst[n:]
+ src = src[n:]
+ x.outUsed += n
+ }
+}
diff --git a/src/crypto/cipher/ofb_test.go b/src/crypto/cipher/ofb_test.go
new file mode 100644
index 0000000..8d3c5d3
--- /dev/null
+++ b/src/crypto/cipher/ofb_test.go
@@ -0,0 +1,102 @@
+// Copyright 2009 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.
+
+// OFB AES test vectors.
+
+// See U.S. National Institute of Standards and Technology (NIST)
+// Special Publication 800-38A, ``Recommendation for Block Cipher
+// Modes of Operation,'' 2001 Edition, pp. 52-55.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "testing"
+)
+
+type ofbTest struct {
+ name string
+ key []byte
+ iv []byte
+ in []byte
+ out []byte
+}
+
+var ofbTests = []ofbTest{
+ // NIST SP 800-38A pp 52-55
+ {
+ "OFB-AES128",
+ commonKey128,
+ commonIV,
+ commonInput,
+ []byte{
+ 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
+ 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+ 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+ 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e,
+ },
+ },
+ {
+ "OFB-AES192",
+ commonKey192,
+ commonIV,
+ commonInput,
+ []byte{
+ 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
+ 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+ 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+ 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a,
+ },
+ },
+ {
+ "OFB-AES256",
+ commonKey256,
+ commonIV,
+ commonInput,
+ []byte{
+ 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
+ 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+ 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+ 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84,
+ },
+ },
+}
+
+func TestOFB(t *testing.T) {
+ for _, tt := range ofbTests {
+ test := tt.name
+
+ c, err := aes.NewCipher(tt.key)
+ if err != nil {
+ t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
+ continue
+ }
+
+ for j := 0; j <= 5; j += 5 {
+ plaintext := tt.in[0 : len(tt.in)-j]
+ ofb := cipher.NewOFB(c, tt.iv)
+ ciphertext := make([]byte, len(plaintext))
+ ofb.XORKeyStream(ciphertext, plaintext)
+ if !bytes.Equal(ciphertext, tt.out[:len(plaintext)]) {
+ t.Errorf("%s/%d: encrypting\ninput % x\nhave % x\nwant % x", test, len(plaintext), plaintext, ciphertext, tt.out)
+ }
+ }
+
+ for j := 0; j <= 5; j += 5 {
+ ciphertext := tt.out[0 : len(tt.in)-j]
+ ofb := cipher.NewOFB(c, tt.iv)
+ plaintext := make([]byte, len(ciphertext))
+ ofb.XORKeyStream(plaintext, ciphertext)
+ if !bytes.Equal(plaintext, tt.in[:len(ciphertext)]) {
+ t.Errorf("%s/%d: decrypting\nhave % x\nwant % x", test, len(ciphertext), plaintext, tt.in)
+ }
+ }
+
+ if t.Failed() {
+ break
+ }
+ }
+}
diff --git a/src/crypto/cipher/xor_amd64.go b/src/crypto/cipher/xor_amd64.go
new file mode 100644
index 0000000..a595acc
--- /dev/null
+++ b/src/crypto/cipher/xor_amd64.go
@@ -0,0 +1,27 @@
+// 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.
+
+package cipher
+
+// 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)
diff --git a/src/crypto/cipher/xor_amd64.s b/src/crypto/cipher/xor_amd64.s
new file mode 100644
index 0000000..780d37a
--- /dev/null
+++ b/src/crypto/cipher/xor_amd64.s
@@ -0,0 +1,54 @@
+// 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.
+
+#include "textflag.h"
+
+// func xorBytesSSE2(dst, a, b *byte, n int)
+TEXT ·xorBytesSSE2(SB), NOSPLIT, $0
+ MOVQ dst+0(FP), BX
+ MOVQ a+8(FP), SI
+ MOVQ b+16(FP), CX
+ MOVQ n+24(FP), DX
+ TESTQ $15, DX // AND 15 & len, if not zero jump to not_aligned.
+ JNZ not_aligned
+
+aligned:
+ MOVQ $0, AX // position in slices
+
+loop16b:
+ MOVOU (SI)(AX*1), X0 // XOR 16byte forwards.
+ MOVOU (CX)(AX*1), X1
+ PXOR X1, X0
+ MOVOU X0, (BX)(AX*1)
+ ADDQ $16, AX
+ CMPQ DX, AX
+ JNE loop16b
+ RET
+
+loop_1b:
+ SUBQ $1, DX // XOR 1byte backwards.
+ MOVB (SI)(DX*1), DI
+ MOVB (CX)(DX*1), AX
+ XORB AX, DI
+ MOVB DI, (BX)(DX*1)
+ TESTQ $7, DX // AND 7 & len, if not zero jump to loop_1b.
+ JNZ loop_1b
+ CMPQ DX, $0 // if len is 0, ret.
+ JE ret
+ TESTQ $15, DX // AND 15 & len, if zero jump to aligned.
+ JZ aligned
+
+not_aligned:
+ TESTQ $7, DX // AND $7 & len, if not zero jump to loop_1b.
+ JNE loop_1b
+ SUBQ $8, DX // XOR 8bytes backwards.
+ MOVQ (SI)(DX*1), DI
+ MOVQ (CX)(DX*1), AX
+ XORQ AX, DI
+ MOVQ DI, (BX)(DX*1)
+ CMPQ DX, $16 // if len is greater or equal 16 here, it must be aligned.
+ JGE aligned
+
+ret:
+ RET
diff --git a/src/crypto/cipher/xor_arm64.go b/src/crypto/cipher/xor_arm64.go
new file mode 100644
index 0000000..35a785a
--- /dev/null
+++ b/src/crypto/cipher/xor_arm64.go
@@ -0,0 +1,29 @@
+// Copyright 2020 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.
+
+package cipher
+
+// 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)
diff --git a/src/crypto/cipher/xor_arm64.s b/src/crypto/cipher/xor_arm64.s
new file mode 100644
index 0000000..669852d
--- /dev/null
+++ b/src/crypto/cipher/xor_arm64.s
@@ -0,0 +1,67 @@
+// Copyright 2020 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.
+
+#include "textflag.h"
+
+// func xorBytesARM64(dst, a, b *byte, n int)
+TEXT ·xorBytesARM64(SB), NOSPLIT|NOFRAME, $0
+ MOVD dst+0(FP), R0
+ MOVD a+8(FP), R1
+ MOVD b+16(FP), R2
+ MOVD n+24(FP), R3
+ CMP $64, R3
+ BLT tail
+loop_64:
+ VLD1.P 64(R1), [V0.B16, V1.B16, V2.B16, V3.B16]
+ VLD1.P 64(R2), [V4.B16, V5.B16, V6.B16, V7.B16]
+ VEOR V0.B16, V4.B16, V4.B16
+ VEOR V1.B16, V5.B16, V5.B16
+ VEOR V2.B16, V6.B16, V6.B16
+ VEOR V3.B16, V7.B16, V7.B16
+ VST1.P [V4.B16, V5.B16, V6.B16, V7.B16], 64(R0)
+ SUBS $64, R3
+ CMP $64, R3
+ BGE loop_64
+tail:
+ // quick end
+ CBZ R3, end
+ TBZ $5, R3, less_than32
+ VLD1.P 32(R1), [V0.B16, V1.B16]
+ VLD1.P 32(R2), [V2.B16, V3.B16]
+ VEOR V0.B16, V2.B16, V2.B16
+ VEOR V1.B16, V3.B16, V3.B16
+ VST1.P [V2.B16, V3.B16], 32(R0)
+less_than32:
+ TBZ $4, R3, less_than16
+ LDP.P 16(R1), (R11, R12)
+ LDP.P 16(R2), (R13, R14)
+ EOR R11, R13, R13
+ EOR R12, R14, R14
+ STP.P (R13, R14), 16(R0)
+less_than16:
+ TBZ $3, R3, less_than8
+ MOVD.P 8(R1), R11
+ MOVD.P 8(R2), R12
+ EOR R11, R12, R12
+ MOVD.P R12, 8(R0)
+less_than8:
+ TBZ $2, R3, less_than4
+ MOVWU.P 4(R1), R13
+ MOVWU.P 4(R2), R14
+ EORW R13, R14, R14
+ MOVWU.P R14, 4(R0)
+less_than4:
+ TBZ $1, R3, less_than2
+ MOVHU.P 2(R1), R15
+ MOVHU.P 2(R2), R16
+ EORW R15, R16, R16
+ MOVHU.P R16, 2(R0)
+less_than2:
+ TBZ $0, R3, end
+ MOVBU (R1), R17
+ MOVBU (R2), R19
+ EORW R17, R19, R19
+ MOVBU R19, (R0)
+end:
+ RET
diff --git a/src/crypto/cipher/xor_generic.go b/src/crypto/cipher/xor_generic.go
new file mode 100644
index 0000000..ca9c4bb
--- /dev/null
+++ b/src/crypto/cipher/xor_generic.go
@@ -0,0 +1,91 @@
+// Copyright 2013 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.
+
+// +build !amd64,!ppc64,!ppc64le,!arm64
+
+package cipher
+
+import (
+ "runtime"
+ "unsafe"
+)
+
+// 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
+ }
+
+ switch {
+ case supportsUnaligned:
+ fastXORBytes(dst, a, b, n)
+ default:
+ // TODO(hanwen): if (dst, a, b) have common alignment
+ // we could still try fastXORBytes. It is not clear
+ // how often this happens, and it's only worth it if
+ // the block encryption itself is hardware
+ // accelerated.
+ safeXORBytes(dst, a, b, 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
+// support unaligned read/writes.
+// n needs to be smaller or equal than the length of a and b.
+func fastXORBytes(dst, a, b []byte, n int) {
+ // Assert dst has enough space
+ _ = dst[n-1]
+
+ w := n / wordSize
+ if w > 0 {
+ dw := *(*[]uintptr)(unsafe.Pointer(&dst))
+ aw := *(*[]uintptr)(unsafe.Pointer(&a))
+ bw := *(*[]uintptr)(unsafe.Pointer(&b))
+ for i := 0; i < w; i++ {
+ dw[i] = aw[i] ^ bw[i]
+ }
+ }
+
+ for i := (n - n%wordSize); i < n; i++ {
+ dst[i] = a[i] ^ b[i]
+ }
+}
+
+// n needs to be smaller or equal than the length of a and b.
+func safeXORBytes(dst, a, b []byte, n int) {
+ for i := 0; i < n; 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))
+ }
+}
diff --git a/src/crypto/cipher/xor_ppc64x.go b/src/crypto/cipher/xor_ppc64x.go
new file mode 100644
index 0000000..8d2e43d
--- /dev/null
+++ b/src/crypto/cipher/xor_ppc64x.go
@@ -0,0 +1,29 @@
+// 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.
+
+// +build ppc64 ppc64le
+
+package cipher
+
+// 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]
+ xorBytesVSX(&dst[0], &a[0], &b[0], n)
+ return n
+}
+
+func xorWords(dst, a, b []byte) {
+ xorBytes(dst, a, b)
+}
+
+//go:noescape
+func xorBytesVSX(dst, a, b *byte, n int)
diff --git a/src/crypto/cipher/xor_ppc64x.s b/src/crypto/cipher/xor_ppc64x.s
new file mode 100644
index 0000000..4cef31d
--- /dev/null
+++ b/src/crypto/cipher/xor_ppc64x.s
@@ -0,0 +1,87 @@
+// 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.
+
+// +build ppc64 ppc64le
+
+#include "textflag.h"
+
+// func xorBytesVSX(dst, a, b *byte, n int)
+TEXT ·xorBytesVSX(SB), NOSPLIT, $0
+ MOVD dst+0(FP), R3 // R3 = dst
+ MOVD a+8(FP), R4 // R4 = a
+ MOVD b+16(FP), R5 // R5 = b
+ MOVD n+24(FP), R6 // R6 = n
+
+ CMPU R6, $32, CR7 // Check if n ≥ 32 bytes
+ MOVD R0, R8 // R8 = index
+ CMPU R6, $8, CR6 // Check if 8 ≤ n < 32 bytes
+ BLT CR6, small // Smaller than 8
+ BLT CR7, xor16 // Case for 16 ≤ n < 32 bytes
+
+ // Case for n ≥ 32 bytes
+preloop32:
+ SRD $5, R6, R7 // Setup loop counter
+ MOVD R7, CTR
+ MOVD $16, R10
+ ANDCC $31, R6, R9 // Check for tailing bytes for later
+loop32:
+ LXVD2X (R4)(R8), VS32 // VS32 = a[i,...,i+15]
+ LXVD2X (R4)(R10), VS34
+ LXVD2X (R5)(R8), VS33 // VS33 = b[i,...,i+15]
+ LXVD2X (R5)(R10), VS35
+ XXLXOR VS32, VS33, VS32 // VS34 = a[] ^ b[]
+ XXLXOR VS34, VS35, VS34
+ STXVD2X VS32, (R3)(R8) // Store to dst
+ STXVD2X VS34, (R3)(R10)
+ ADD $32, R8 // Update index
+ ADD $32, R10
+ BC 16, 0, loop32 // bdnz loop16
+
+ BEQ CR0, done
+
+ MOVD R9, R6
+ CMP R6, $8
+ BLT small
+xor16:
+ CMP R6, $16
+ BLT xor8
+ LXVD2X (R4)(R8), VS32
+ LXVD2X (R5)(R8), VS33
+ XXLXOR VS32, VS33, VS32
+ STXVD2X VS32, (R3)(R8)
+ ADD $16, R8
+ ADD $-16, R6
+ CMP R6, $8
+ BLT small
+xor8:
+ // Case for 8 ≤ n < 16 bytes
+ MOVD (R4)(R8), R14 // R14 = a[i,...,i+7]
+ MOVD (R5)(R8), R15 // R15 = b[i,...,i+7]
+ XOR R14, R15, R16 // R16 = a[] ^ b[]
+ SUB $8, R6 // n = n - 8
+ MOVD R16, (R3)(R8) // Store to dst
+ ADD $8, R8
+
+ // Check if we're finished
+ CMP R6, R0
+ BGT small
+ RET
+
+ // Case for n < 8 bytes and tailing bytes from the
+ // previous cases.
+small:
+ CMP R6, R0
+ BEQ done
+ MOVD R6, CTR // Setup loop counter
+
+loop:
+ MOVBZ (R4)(R8), R14 // R14 = a[i]
+ MOVBZ (R5)(R8), R15 // R15 = b[i]
+ XOR R14, R15, R16 // R16 = a[i] ^ b[i]
+ MOVB R16, (R3)(R8) // Store to dst
+ ADD $1, R8
+ BC 16, 0, loop // bdnz loop
+
+done:
+ RET
diff --git a/src/crypto/cipher/xor_test.go b/src/crypto/cipher/xor_test.go
new file mode 100644
index 0000000..4f829e9
--- /dev/null
+++ b/src/crypto/cipher/xor_test.go
@@ -0,0 +1,75 @@
+// Copyright 2013 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.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "crypto/rand"
+ "fmt"
+ "io"
+ "testing"
+)
+
+func TestXOR(t *testing.T) {
+ for j := 1; j <= 1024; j++ {
+ if testing.Short() && j > 16 {
+ break
+ }
+ for alignP := 0; alignP < 2; alignP++ {
+ for alignQ := 0; alignQ < 2; alignQ++ {
+ for alignD := 0; alignD < 2; alignD++ {
+ p := make([]byte, j)[alignP:]
+ q := make([]byte, j)[alignQ:]
+ d1 := make([]byte, j+alignD)[alignD:]
+ d2 := make([]byte, j+alignD)[alignD:]
+ if _, err := io.ReadFull(rand.Reader, p); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := io.ReadFull(rand.Reader, q); err != nil {
+ t.Fatal(err)
+ }
+ cipher.XorBytes(d1, p, q)
+ n := min(p, q)
+ for i := 0; i < n; i++ {
+ d2[i] = p[i] ^ q[i]
+ }
+ if !bytes.Equal(d1, d2) {
+ t.Logf("p: %#v", p)
+ t.Logf("q: %#v", q)
+ t.Logf("expect: %#v", d2)
+ t.Logf("result: %#v", d1)
+ t.Fatal("not equal")
+ }
+ }
+ }
+ }
+ }
+}
+
+func min(a, b []byte) int {
+ n := len(a)
+ if len(b) < n {
+ n = len(b)
+ }
+ return n
+}
+
+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++ {
+ cipher.XorBytes(dst, s0, s1)
+ }
+ })
+ }
+}