-342e3b11f21a
+f618e5e0991d
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
toolexeclibgocrypto_DATA = \
crypto/aes.gox \
- crypto/block.gox \
crypto/blowfish.gox \
crypto/cast5.gox \
crypto/cipher.gox \
+ crypto/des.gox \
crypto/dsa.gox \
crypto/ecdsa.gox \
crypto/elliptic.gox \
go/os/env.go \
go/os/env_unix.go \
go/os/error.go \
+ go/os/error_posix.go \
go/os/exec.go \
+ go/os/exec_posix.go \
go/os/exec_unix.go \
go/os/file.go \
+ go/os/file_posix.go \
go/os/file_unix.go \
go/os/getwd.go \
go/os/path.go \
go/crypto/aes/block.go \
go/crypto/aes/cipher.go \
go/crypto/aes/const.go
-go_crypto_block_files = \
- go/crypto/block/cbc.go \
- go/crypto/block/cfb.go \
- go/crypto/block/cmac.go \
- go/crypto/block/cipher.go \
- go/crypto/block/ctr.go \
- go/crypto/block/eax.go \
- go/crypto/block/ecb.go \
- go/crypto/block/ofb.go \
- go/crypto/block/xor.go
go_crypto_blowfish_files = \
go/crypto/blowfish/block.go \
go/crypto/blowfish/const.go \
go/crypto/cipher/io.go \
go/crypto/cipher/ocfb.go \
go/crypto/cipher/ofb.go
+go_crypto_des_files = \
+ go/crypto/des/block.go \
+ go/crypto/des/cipher.go \
+ go/crypto/des/const.go
go_crypto_dsa_files = \
go/crypto/dsa/dsa.go
go_crypto_ecdsa_files = \
container/ring.lo \
container/vector.lo \
crypto/aes.lo \
- crypto/block.lo \
crypto/blowfish.lo \
crypto/cast5.lo \
crypto/cipher.lo \
+ crypto/des.lo \
crypto/dsa.lo \
crypto/ecdsa.lo \
crypto/elliptic.lo \
@$(CHECK)
.PHONY: crypto/aes/check
-crypto/block.lo: $(go_crypto_block_files) fmt.gox io.gox os.gox strconv.gox
- $(BUILDPACKAGE)
-crypto/block/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/block
- @$(CHECK)
-.PHONY: crypto/block/check
-
crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
$(BUILDPACKAGE)
crypto/blowfish/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/cipher/check
+crypto/des.lo: $(go_crypto_des_files) encoding/binary.gox os.gox strconv.gox
+ $(BUILDPACKAGE)
+crypto/des/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/des
+ @$(CHECK)
+.PHONY: crypto/des/check
+
crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox
$(BUILDPACKAGE)
crypto/dsa/check: $(CHECK_DEPS)
.PHONY: crypto/ripemd160/check
crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
- crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
+ crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
+ sync.gox
$(BUILDPACKAGE)
crypto/rsa/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/rsa
@$(CHECK)
.PHONY: http/cgi/check
-http/httptest.lo: $(go_http_httptest_files) bytes.gox fmt.gox http.gox \
- net.gox os.gox
+http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
+ crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
$(BUILDPACKAGE)
http/httptest/check: $(CHECK_DEPS)
@$(MKDIR_P) http/httptest
crypto/aes.gox: crypto/aes.lo
$(BUILDGOX)
-crypto/block.gox: crypto/block.lo
- $(BUILDGOX)
crypto/blowfish.gox: crypto/blowfish.lo
$(BUILDGOX)
crypto/cast5.gox: crypto/cast5.lo
$(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX)
+crypto/des.gox: crypto/des.lo
+ $(BUILDGOX)
crypto/dsa.gox: crypto/dsa.lo
$(BUILDGOX)
crypto/ecdsa.gox: crypto/ecdsa.lo
container/ring/check \
container/vector/check \
crypto/aes/check \
- crypto/block/check \
crypto/blowfish/check \
crypto/cast5/check \
crypto/cipher/check \
+ crypto/des/check \
crypto/dsa/check \
crypto/ecdsa/check \
crypto/elliptic/check \
archive/zip.lo compress/bzip2.lo compress/flate.lo \
compress/gzip.lo compress/lzw.lo compress/zlib.lo \
container/heap.lo container/list.lo container/ring.lo \
- container/vector.lo crypto/aes.lo crypto/block.lo \
- crypto/blowfish.lo crypto/cast5.lo crypto/cipher.lo \
- crypto/dsa.lo crypto/ecdsa.lo crypto/elliptic.lo \
- crypto/hmac.lo crypto/md4.lo crypto/md5.lo crypto/ocsp.lo \
- crypto/openpgp.lo crypto/rand.lo crypto/rc4.lo \
- crypto/ripemd160.lo crypto/rsa.lo crypto/sha1.lo \
- crypto/sha256.lo crypto/sha512.lo crypto/subtle.lo \
- crypto/tls.lo crypto/twofish.lo crypto/x509.lo crypto/xtea.lo \
- crypto/openpgp/armor.lo crypto/openpgp/error.lo \
- crypto/openpgp/packet.lo crypto/openpgp/s2k.lo debug/dwarf.lo \
- debug/elf.lo debug/gosym.lo debug/macho.lo debug/pe.lo \
- debug/proc.lo encoding/ascii85.lo encoding/base32.lo \
- encoding/base64.lo encoding/binary.lo encoding/git85.lo \
- encoding/hex.lo encoding/line.lo encoding/pem.lo \
- exp/datafmt.lo exp/draw.lo exp/eval.lo go/ast.lo go/doc.lo \
- go/parser.lo go/printer.lo go/scanner.lo go/token.lo \
- go/typechecker.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \
- hash/fnv.lo http/cgi.lo http/httptest.lo http/pprof.lo \
- image/jpeg.lo image/png.lo index/suffixarray.lo io/ioutil.lo \
- mime/multipart.lo net/dict.lo net/textproto.lo \
- $(am__DEPENDENCIES_1) os/signal.lo path/filepath.lo \
- rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
- sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \
- syscalls/errno.lo testing/testing.lo testing/iotest.lo \
- testing/quick.lo testing/script.lo
+ container/vector.lo crypto/aes.lo crypto/blowfish.lo \
+ crypto/cast5.lo crypto/cipher.lo crypto/des.lo crypto/dsa.lo \
+ crypto/ecdsa.lo crypto/elliptic.lo crypto/hmac.lo \
+ crypto/md4.lo crypto/md5.lo crypto/ocsp.lo crypto/openpgp.lo \
+ crypto/rand.lo crypto/rc4.lo crypto/ripemd160.lo crypto/rsa.lo \
+ crypto/sha1.lo crypto/sha256.lo crypto/sha512.lo \
+ crypto/subtle.lo crypto/tls.lo crypto/twofish.lo \
+ crypto/x509.lo crypto/xtea.lo crypto/openpgp/armor.lo \
+ crypto/openpgp/error.lo crypto/openpgp/packet.lo \
+ crypto/openpgp/s2k.lo debug/dwarf.lo debug/elf.lo \
+ debug/gosym.lo debug/macho.lo debug/pe.lo debug/proc.lo \
+ encoding/ascii85.lo encoding/base32.lo encoding/base64.lo \
+ encoding/binary.lo encoding/git85.lo encoding/hex.lo \
+ encoding/line.lo encoding/pem.lo exp/datafmt.lo exp/draw.lo \
+ exp/eval.lo go/ast.lo go/doc.lo go/parser.lo go/printer.lo \
+ go/scanner.lo go/token.lo go/typechecker.lo hash/adler32.lo \
+ hash/crc32.lo hash/crc64.lo hash/fnv.lo http/cgi.lo \
+ http/httptest.lo http/pprof.lo image/jpeg.lo image/png.lo \
+ index/suffixarray.lo io/ioutil.lo mime/multipart.lo \
+ net/dict.lo net/textproto.lo $(am__DEPENDENCIES_1) \
+ os/signal.lo path/filepath.lo rpc/jsonrpc.lo runtime/debug.lo \
+ runtime/pprof.lo sync/atomic.lo sync/atomic_c.lo \
+ syscalls/syscall.lo syscalls/errno.lo testing/testing.lo \
+ testing/iotest.lo testing/quick.lo testing/script.lo
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
toolexeclibgocrypto_DATA = \
crypto/aes.gox \
- crypto/block.gox \
crypto/blowfish.gox \
crypto/cast5.gox \
crypto/cipher.gox \
+ crypto/des.gox \
crypto/dsa.gox \
crypto/ecdsa.gox \
crypto/elliptic.gox \
go/os/env.go \
go/os/env_unix.go \
go/os/error.go \
+ go/os/error_posix.go \
go/os/exec.go \
+ go/os/exec_posix.go \
go/os/exec_unix.go \
go/os/file.go \
+ go/os/file_posix.go \
go/os/file_unix.go \
go/os/getwd.go \
go/os/path.go \
go/crypto/aes/cipher.go \
go/crypto/aes/const.go
-go_crypto_block_files = \
- go/crypto/block/cbc.go \
- go/crypto/block/cfb.go \
- go/crypto/block/cmac.go \
- go/crypto/block/cipher.go \
- go/crypto/block/ctr.go \
- go/crypto/block/eax.go \
- go/crypto/block/ecb.go \
- go/crypto/block/ofb.go \
- go/crypto/block/xor.go
-
go_crypto_blowfish_files = \
go/crypto/blowfish/block.go \
go/crypto/blowfish/const.go \
go/crypto/cipher/ocfb.go \
go/crypto/cipher/ofb.go
+go_crypto_des_files = \
+ go/crypto/des/block.go \
+ go/crypto/des/cipher.go \
+ go/crypto/des/const.go
+
go_crypto_dsa_files = \
go/crypto/dsa/dsa.go
container/ring.lo \
container/vector.lo \
crypto/aes.lo \
- crypto/block.lo \
crypto/blowfish.lo \
crypto/cast5.lo \
crypto/cipher.lo \
+ crypto/des.lo \
crypto/dsa.lo \
crypto/ecdsa.lo \
crypto/elliptic.lo \
container/ring/check \
container/vector/check \
crypto/aes/check \
- crypto/block/check \
crypto/blowfish/check \
crypto/cast5/check \
crypto/cipher/check \
+ crypto/des/check \
crypto/dsa/check \
crypto/ecdsa/check \
crypto/elliptic/check \
@$(CHECK)
.PHONY: crypto/aes/check
-crypto/block.lo: $(go_crypto_block_files) fmt.gox io.gox os.gox strconv.gox
- $(BUILDPACKAGE)
-crypto/block/check: $(CHECK_DEPS)
- @$(MKDIR_P) crypto/block
- @$(CHECK)
-.PHONY: crypto/block/check
-
crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
$(BUILDPACKAGE)
crypto/blowfish/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/cipher/check
+crypto/des.lo: $(go_crypto_des_files) encoding/binary.gox os.gox strconv.gox
+ $(BUILDPACKAGE)
+crypto/des/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/des
+ @$(CHECK)
+.PHONY: crypto/des/check
+
crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox
$(BUILDPACKAGE)
crypto/dsa/check: $(CHECK_DEPS)
.PHONY: crypto/ripemd160/check
crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
- crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
+ crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
+ sync.gox
$(BUILDPACKAGE)
crypto/rsa/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/rsa
@$(CHECK)
.PHONY: http/cgi/check
-http/httptest.lo: $(go_http_httptest_files) bytes.gox fmt.gox http.gox \
- net.gox os.gox
+http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
+ crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
$(BUILDPACKAGE)
http/httptest/check: $(CHECK_DEPS)
@$(MKDIR_P) http/httptest
crypto/aes.gox: crypto/aes.lo
$(BUILDGOX)
-crypto/block.gox: crypto/block.lo
- $(BUILDGOX)
crypto/blowfish.gox: crypto/blowfish.lo
$(BUILDGOX)
crypto/cast5.gox: crypto/cast5.lo
$(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX)
+crypto/des.gox: crypto/des.lo
+ $(BUILDGOX)
crypto/dsa.gox: crypto/dsa.lo
$(BUILDGOX)
crypto/ecdsa.gox: crypto/ecdsa.lo
nr := tr.nb + tr.pad // number of bytes to skip
tr.nb, tr.pad = 0, 0
if sr, ok := tr.r.(io.Seeker); ok {
- if _, err := sr.Seek(nr, 1); err == nil {
+ if _, err := sr.Seek(nr, os.SEEK_CUR); err == nil {
return
}
}
func TestReader(t *testing.T) {
testLoop:
for i, test := range untarTests {
- f, err := os.Open(test.file, os.O_RDONLY, 0444)
+ f, err := os.Open(test.file)
if err != nil {
t.Errorf("test %d: Unexpected error: %v", i, err)
continue
}
func TestPartialRead(t *testing.T) {
- f, err := os.Open("testdata/gnu.tar", os.O_RDONLY, 0444)
+ f, err := os.Open("testdata/gnu.tar")
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
func TestIncrementalRead(t *testing.T) {
test := gnuTarTest
- f, err := os.Open(test.file, os.O_RDONLY, 0444)
+ f, err := os.Open(test.file)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
func TestNonSeekable(t *testing.T) {
test := gnuTarTest
- f, err := os.Open(test.file, os.O_RDONLY, 0444)
+ f, err := os.Open(test.file)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// OpenReader will open the Zip file specified by name and return a Reader.
func OpenReader(name string) (*Reader, os.Error) {
- f, err := os.Open(name, os.O_RDONLY, 0644)
+ f, err := os.Open(name)
if err != nil {
return nil, err
}
Comment: end.comment,
}
rs := io.NewSectionReader(r, 0, size)
- if _, err = rs.Seek(int64(end.directoryOffset), 0); err != nil {
+ if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
return nil, err
}
buf := bufio.NewReader(rs)
if err = readFileHeader(f, r); err != nil {
return
}
- if f.bodyOffset, err = r.Seek(0, 1); err != nil {
+ if f.bodyOffset, err = r.Seek(0, os.SEEK_CUR); err != nil {
return
}
}
// If nn < len(p), it also returns an error explaining
// why the write is short.
func (b *Writer) Write(p []byte) (nn int, err os.Error) {
- if b.err != nil {
- return 0, b.err
- }
- nn = 0
- for len(p) > 0 {
- n := b.Available()
- if n <= 0 {
- if b.Flush(); b.err != nil {
- break
- }
- n = b.Available()
- }
- if b.Buffered() == 0 && len(p) >= len(b.buf) {
+ for len(p) > b.Available() && b.err == nil {
+ var n int
+ if b.Buffered() == 0 {
// Large write, empty buffer.
// Write directly from p to avoid copy.
n, b.err = b.wr.Write(p)
- nn += n
- p = p[n:]
- if b.err != nil {
- break
- }
- continue
- }
- if n > len(p) {
- n = len(p)
+ } else {
+ n = copy(b.buf[b.n:], p)
+ b.n += n
+ b.Flush()
}
- copy(b.buf[b.n:b.n+n], p[0:n])
- b.n += n
nn += n
p = p[n:]
}
- return nn, b.err
+ if b.err != nil {
+ return nn, b.err
+ }
+ n := copy(b.buf[b.n:], p)
+ b.n += n
+ nn += n
+ return nn, nil
}
// WriteByte writes a single byte.
// If the count is less than len(s), it also returns an error explaining
// why the write is short.
func (b *Writer) WriteString(s string) (int, os.Error) {
- if b.err != nil {
- return 0, b.err
- }
- // Common case, worth making fast.
- if b.Available() >= len(s) || len(b.buf) >= len(s) && b.Flush() == nil {
- for i := 0; i < len(s); i++ { // loop over bytes, not runes.
- b.buf[b.n] = s[i]
- b.n++
- }
- return len(s), nil
+ nn := 0
+ for len(s) > b.Available() && b.err == nil {
+ n := copy(b.buf[b.n:], s)
+ b.n += n
+ nn += n
+ s = s[n:]
+ b.Flush()
}
- for i := 0; i < len(s); i++ { // loop over bytes, not runes.
- b.WriteByte(s[i])
- if b.err != nil {
- return i, b.err
- }
+ if b.err != nil {
+ return nn, b.err
}
- return len(s), nil
+ n := copy(b.buf[b.n:], s)
+ b.n += n
+ nn += n
+ return nn, nil
}
// buffered input and output
// the given options yields equivalent bytes to the original file.
func testFile(t *testing.T, fn string, order Order, litWidth int) {
// Read the file, as golden output.
- golden, err := os.Open(fn, os.O_RDONLY, 0400)
+ golden, err := os.Open(fn)
if err != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
return
defer golden.Close()
// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
- raw, err := os.Open(fn, os.O_RDONLY, 0400)
+ raw, err := os.Open(fn)
if err != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
return
// yields equivalent bytes to the original file.
func testFileLevel(t *testing.T, fn string, level int) {
// Read the file, as golden output.
- golden, err := os.Open(fn, os.O_RDONLY, 0444)
+ golden, err := os.Open(fn)
if err != nil {
t.Errorf("%s (level=%d): %v", fn, level, err)
return
defer golden.Close()
// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
- raw, err := os.Open(fn, os.O_RDONLY, 0444)
+ raw, err := os.Open(fn)
if err != nil {
t.Errorf("%s (level=%d): %v", fn, level, err)
return
+++ /dev/null
-// 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 block
-
-import (
- "io"
-)
-
-type cbcCipher struct {
- c Cipher
- blockSize int
- iv []byte
- tmp []byte
-}
-
-func newCBC(c Cipher, iv []byte) *cbcCipher {
- n := c.BlockSize()
- x := new(cbcCipher)
- x.c = c
- x.blockSize = n
- x.iv = dup(iv)
- x.tmp = make([]byte, n)
- return x
-}
-
-func (x *cbcCipher) BlockSize() int { return x.blockSize }
-
-func (x *cbcCipher) Encrypt(dst, src []byte) {
- for i := 0; i < x.blockSize; i++ {
- x.iv[i] ^= src[i]
- }
- x.c.Encrypt(x.iv, x.iv)
- for i := 0; i < x.blockSize; i++ {
- dst[i] = x.iv[i]
- }
-}
-
-func (x *cbcCipher) Decrypt(dst, src []byte) {
- x.c.Decrypt(x.tmp, src)
- for i := 0; i < x.blockSize; i++ {
- x.tmp[i] ^= x.iv[i]
- x.iv[i] = src[i]
- dst[i] = x.tmp[i]
- }
-}
-
-// NewCBCDecrypter returns a reader that reads data from r and decrypts it using c
-// in cipher block chaining (CBC) mode with the initialization vector iv.
-// The returned Reader does not buffer or read ahead except
-// as required by the cipher's block size.
-func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader {
- return NewECBDecrypter(newCBC(c, iv), r)
-}
-
-// NewCBCEncrypter returns a writer that encrypts data using c
-// in cipher block chaining (CBC) mode with the initialization vector iv
-// and writes the encrypted data to w.
-// The returned Writer does no buffering except as required
-// by the cipher's block size, so there is no need for a Flush method.
-func NewCBCEncrypter(c Cipher, iv []byte, w io.Writer) io.Writer {
- return NewECBEncrypter(newCBC(c, iv), w)
-}
+++ /dev/null
-// 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 feedback (CFB) mode.
-
-// CFB provides confidentiality by feeding a fraction of
-// the previous ciphertext in as the plaintext for the next
-// block operation.
-
-// See NIST SP 800-38A, pp 11-13
-
-package block
-
-import (
- "io"
-)
-
-type cfbCipher struct {
- c Cipher
- blockSize int // our block size (s/8)
- cipherSize int // underlying cipher block size
- iv []byte
- tmp []byte
-}
-
-func newCFB(c Cipher, s int, iv []byte) *cfbCipher {
- if s == 0 || s%8 != 0 {
- panic("crypto/block: invalid CFB mode")
- }
- b := c.BlockSize()
- x := new(cfbCipher)
- x.c = c
- x.blockSize = s / 8
- x.cipherSize = b
- x.iv = dup(iv)
- x.tmp = make([]byte, b)
- return x
-}
-
-func (x *cfbCipher) BlockSize() int { return x.blockSize }
-
-func (x *cfbCipher) Encrypt(dst, src []byte) {
- // Encrypt old IV and xor prefix with src to make dst.
- x.c.Encrypt(x.tmp, x.iv)
- for i := 0; i < x.blockSize; i++ {
- dst[i] = src[i] ^ x.tmp[i]
- }
-
- // Slide unused IV pieces down and insert dst at end.
- for i := 0; i < x.cipherSize-x.blockSize; i++ {
- x.iv[i] = x.iv[i+x.blockSize]
- }
- off := x.cipherSize - x.blockSize
- for i := off; i < x.cipherSize; i++ {
- x.iv[i] = dst[i-off]
- }
-}
-
-func (x *cfbCipher) Decrypt(dst, src []byte) {
- // Encrypt [sic] old IV and xor prefix with src to make dst.
- x.c.Encrypt(x.tmp, x.iv)
- for i := 0; i < x.blockSize; i++ {
- dst[i] = src[i] ^ x.tmp[i]
- }
-
- // Slide unused IV pieces down and insert src at top.
- for i := 0; i < x.cipherSize-x.blockSize; i++ {
- x.iv[i] = x.iv[i+x.blockSize]
- }
- off := x.cipherSize - x.blockSize
- for i := off; i < x.cipherSize; i++ {
- // Reconstruct src = dst ^ x.tmp
- // in case we overwrote src (src == dst).
- x.iv[i] = dst[i-off] ^ x.tmp[i-off]
- }
-}
-
-// NewCFBDecrypter returns a reader that reads data from r and decrypts it using c
-// in s-bit cipher feedback (CFB) mode with the initialization vector iv.
-// The returned Reader does not buffer or read ahead except
-// as required by the cipher's block size.
-// Modes for s not a multiple of 8 are unimplemented.
-func NewCFBDecrypter(c Cipher, s int, iv []byte, r io.Reader) io.Reader {
- return NewECBDecrypter(newCFB(c, s, iv), r)
-}
-
-// NewCFBEncrypter returns a writer that encrypts data using c
-// in s-bit cipher feedback (CFB) mode with the initialization vector iv
-// and writes the encrypted data to w.
-// The returned Writer does no buffering except as required
-// by the cipher's block size, so there is no need for a Flush method.
-// Modes for s not a multiple of 8 are unimplemented.
-func NewCFBEncrypter(c Cipher, s int, iv []byte, w io.Writer) io.Writer {
- return NewECBEncrypter(newCFB(c, s, iv), w)
-}
+++ /dev/null
-// 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.
-
-// CFB 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. 29-52.
-
-package block
-
-import (
- "bytes"
- "crypto/aes"
- "io"
- "testing"
-)
-
-type cfbTest struct {
- name string
- s int
- key []byte
- iv []byte
- in []byte
- out []byte
-}
-
-var cfbAESTests = []cfbTest{
- {
- "CFB1-AES128",
- 1,
- commonKey128,
- commonIV,
- []byte{
- 0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
- 1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
- },
- []byte{
- 0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 0<<1,
- 1<<7 | 0<<6 | 1<<5 | 1<<4 | 0<<3 | 0<<2 | 1<<1,
- },
- },
- {
- "CFB1-AES192",
- 1,
- commonKey192,
- commonIV,
- []byte{
- 0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
- 1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
- },
- []byte{
- 1<<7 | 0<<6 | 0<<5 | 1<<4 | 0<<3 | 0<<2 | 1<<1,
- 0<<7 | 1<<6 | 0<<5 | 1<<4 | 1<<3 | 0<<2 | 0<<1,
- },
- },
- {
- "CFB1-AES256",
- 1,
- commonKey256,
- commonIV,
- []byte{
- 0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
- 1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
- },
- []byte{
- 1<<7 | 0<<6 | 0<<5 | 1<<4 | 0<<3 | 0<<2 | 0<<1,
- 0<<7 | 0<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 0<<1,
- },
- },
-
- {
- "CFB8-AES128",
- 8,
- commonKey128,
- commonIV,
- []byte{
- 0x6b,
- 0xc1,
- 0xbe,
- 0xe2,
- 0x2e,
- 0x40,
- 0x9f,
- 0x96,
- 0xe9,
- 0x3d,
- 0x7e,
- 0x11,
- 0x73,
- 0x93,
- 0x17,
- 0x2a,
- 0xae,
- 0x2d,
- },
- []byte{
- 0x3b,
- 0x79,
- 0x42,
- 0x4c,
- 0x9c,
- 0x0d,
- 0xd4,
- 0x36,
- 0xba,
- 0xce,
- 0x9e,
- 0x0e,
- 0xd4,
- 0x58,
- 0x6a,
- 0x4f,
- 0x32,
- 0xb9,
- },
- },
-
- {
- "CFB8-AES192",
- 8,
- commonKey192,
- commonIV,
- []byte{
- 0x6b,
- 0xc1,
- 0xbe,
- 0xe2,
- 0x2e,
- 0x40,
- 0x9f,
- 0x96,
- 0xe9,
- 0x3d,
- 0x7e,
- 0x11,
- 0x73,
- 0x93,
- 0x17,
- 0x2a,
- 0xae,
- 0x2d,
- },
- []byte{
- 0xcd,
- 0xa2,
- 0x52,
- 0x1e,
- 0xf0,
- 0xa9,
- 0x05,
- 0xca,
- 0x44,
- 0xcd,
- 0x05,
- 0x7c,
- 0xbf,
- 0x0d,
- 0x47,
- 0xa0,
- 0x67,
- 0x8a,
- },
- },
-
- {
- "CFB8-AES256",
- 8,
- commonKey256,
- commonIV,
- []byte{
- 0x6b,
- 0xc1,
- 0xbe,
- 0xe2,
- 0x2e,
- 0x40,
- 0x9f,
- 0x96,
- 0xe9,
- 0x3d,
- 0x7e,
- 0x11,
- 0x73,
- 0x93,
- 0x17,
- 0x2a,
- 0xae,
- 0x2d,
- },
- []byte{
- 0xdc,
- 0x1f,
- 0x1a,
- 0x85,
- 0x20,
- 0xa6,
- 0x4d,
- 0xb5,
- 0x5f,
- 0xcc,
- 0x8a,
- 0xc5,
- 0x54,
- 0x84,
- 0x4e,
- 0x88,
- 0x97,
- 0x00,
- },
- },
-
- {
- "CFB128-AES128",
- 128,
- commonKey128,
- commonIV,
- []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,
- },
- []byte{
- 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
- 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b,
- 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf,
- 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6,
- },
- },
-
- {
- "CFB128-AES192",
- 128,
- commonKey192,
- commonIV,
- []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,
- },
- []byte{
- 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
- 0x67, 0xce, 0x7f, 0x7f, 0x81, 0x17, 0x36, 0x21, 0x96, 0x1a, 0x2b, 0x70, 0x17, 0x1d, 0x3d, 0x7a,
- 0x2e, 0x1e, 0x8a, 0x1d, 0xd5, 0x9b, 0x88, 0xb1, 0xc8, 0xe6, 0x0f, 0xed, 0x1e, 0xfa, 0xc4, 0xc9,
- 0xc0, 0x5f, 0x9f, 0x9c, 0xa9, 0x83, 0x4f, 0xa0, 0x42, 0xae, 0x8f, 0xba, 0x58, 0x4b, 0x09, 0xff,
- },
- },
-
- {
- "CFB128-AES256",
- 128,
- commonKey256,
- commonIV,
- []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,
- },
- []byte{
- 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
- 0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b,
- 0xdf, 0x10, 0x13, 0x24, 0x15, 0xe5, 0x4b, 0x92, 0xa1, 0x3e, 0xd0, 0xa8, 0x26, 0x7a, 0xe2, 0xf9,
- 0x75, 0xa3, 0x85, 0x74, 0x1a, 0xb9, 0xce, 0xf8, 0x20, 0x31, 0x62, 0x3d, 0x55, 0xb1, 0xe4, 0x71,
- },
- },
-}
-
-func TestCFB_AES(t *testing.T) {
- for _, tt := range cfbAESTests {
- test := tt.name
-
- if tt.s == 1 {
- // 1-bit CFB not implemented
- continue
- }
-
- c, err := aes.NewCipher(tt.key)
- if err != nil {
- t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
- continue
- }
-
- var crypt bytes.Buffer
- w := NewCFBEncrypter(c, tt.s, tt.iv, &crypt)
- var r io.Reader = bytes.NewBuffer(tt.in)
- n, err := io.Copy(w, r)
- if n != int64(len(tt.in)) || err != nil {
- t.Errorf("%s: CFBEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
- } else if d := crypt.Bytes(); !same(tt.out, d) {
- t.Errorf("%s: CFBEncrypter\nhave %x\nwant %x", test, d, tt.out)
- }
-
- var plain bytes.Buffer
- r = NewCFBDecrypter(c, tt.s, tt.iv, bytes.NewBuffer(tt.out))
- w = &plain
- n, err = io.Copy(w, r)
- if n != int64(len(tt.out)) || err != nil {
- t.Errorf("%s: CFBDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
- } else if d := plain.Bytes(); !same(tt.in, d) {
- t.Errorf("%s: CFBDecrypter\nhave %x\nwant %x", test, d, tt.in)
- }
-
- if t.Failed() {
- break
- }
- }
-}
+++ /dev/null
-// 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.
-
-// The block package is deprecated, use cipher instead.
-// The block package implements standard block cipher modes
-// that can be wrapped around low-level block cipher implementations.
-// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
-// and NIST Special Publication 800-38A.
-package block
-
-// A Cipher 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 Cipher interface {
- // BlockSize returns the cipher's block size.
- BlockSize() int
-
- // Encrypt encrypts the first block in src into dst.
- // Src and dst may point at the same memory.
- Encrypt(dst, src []byte)
-
- // Decrypt decrypts the first block in src into dst.
- // Src and dst may point at the same memory.
- Decrypt(dst, src []byte)
-}
-
-// Utility routines
-
-func shift1(dst, src []byte) byte {
- var b byte
- for i := len(src) - 1; i >= 0; i-- {
- bb := src[i] >> 7
- dst[i] = src[i]<<1 | b
- b = bb
- }
- return b
-}
-
-func same(p, q []byte) bool {
- if len(p) != len(q) {
- return false
- }
- for i := 0; i < len(p); i++ {
- if p[i] != q[i] {
- return false
- }
- }
- return true
-}
-
-func dup(p []byte) []byte {
- q := make([]byte, len(p))
- copy(q, p)
- return q
-}
+++ /dev/null
-// 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.
-
-// CMAC message authentication code, defined in
-// NIST Special Publication SP 800-38B.
-
-package block
-
-import (
- "hash"
- "os"
-)
-
-const (
- // minimal irreducible polynomial of degree b
- r64 = 0x1b
- r128 = 0x87
-)
-
-type cmac struct {
- k1, k2, ci, digest []byte
- p int // position in ci
- c Cipher
-}
-
-// TODO(rsc): Should this return an error instead of panic?
-
-// NewCMAC returns a new instance of a CMAC message authentication code
-// digest using the given Cipher.
-func NewCMAC(c Cipher) hash.Hash {
- var r byte
- n := c.BlockSize()
- switch n {
- case 64 / 8:
- r = r64
- case 128 / 8:
- r = r128
- default:
- panic("crypto/block: NewCMAC: invalid cipher block size")
- }
-
- d := new(cmac)
- d.c = c
- d.k1 = make([]byte, n)
- d.k2 = make([]byte, n)
- d.ci = make([]byte, n)
- d.digest = make([]byte, n)
-
- // Subkey generation, p. 7
- c.Encrypt(d.k1, d.k1)
- if shift1(d.k1, d.k1) != 0 {
- d.k1[n-1] ^= r
- }
- if shift1(d.k2, d.k1) != 0 {
- d.k2[n-1] ^= r
- }
-
- return d
-}
-
-// Reset clears the digest state, starting a new digest.
-func (d *cmac) Reset() {
- for i := range d.ci {
- d.ci[i] = 0
- }
- d.p = 0
-}
-
-// Write adds the given data to the digest state.
-func (d *cmac) Write(p []byte) (n int, err os.Error) {
- // Xor input into ci.
- for _, c := range p {
- // If ci is full, encrypt and start over.
- if d.p >= len(d.ci) {
- d.c.Encrypt(d.ci, d.ci)
- d.p = 0
- }
- d.ci[d.p] ^= c
- d.p++
- }
- return len(p), nil
-}
-
-// Sum returns the CMAC digest, one cipher block in length,
-// of the data written with Write.
-func (d *cmac) Sum() []byte {
- // Finish last block, mix in key, encrypt.
- // Don't edit ci, in case caller wants
- // to keep digesting after call to Sum.
- k := d.k1
- if d.p < len(d.digest) {
- k = d.k2
- }
- for i := 0; i < len(d.ci); i++ {
- d.digest[i] = d.ci[i] ^ k[i]
- }
- if d.p < len(d.digest) {
- d.digest[d.p] ^= 0x80
- }
- d.c.Encrypt(d.digest, d.digest)
- return d.digest
-}
-
-func (d *cmac) Size() int { return len(d.digest) }
+++ /dev/null
-// 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.
-
-// CMAC test vectors. See NIST SP 800-38B, Appendix D.
-
-package block
-
-import (
- "crypto/aes"
- "testing"
-)
-
-type cmacAESTest struct {
- key []byte
- in []byte
- digest []byte
-}
-
-var cmacAESTests = []cmacAESTest{
- {
- commonKey128,
- nil,
- []byte{0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46},
- },
- {
- commonKey128,
- []byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
- []byte{0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c},
- },
- {
- commonKey128,
- []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,
- },
- []byte{0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27},
- },
- {
- commonKey128,
- []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,
- },
- []byte{0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe},
- },
- {
- commonKey192,
- nil,
- []byte{0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67},
- },
- {
- commonKey192,
- []byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
- []byte{0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84},
- },
- {
- commonKey192,
- []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,
- },
- []byte{0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad, 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e},
- },
- {
- commonKey192,
- []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,
- },
- []byte{0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11},
- },
- {
- commonKey256,
- nil,
- []byte{0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83},
- },
- {
- commonKey256,
- []byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
- []byte{0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c},
- },
- {
- commonKey256,
- []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,
- },
- []byte{0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2, 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6},
- },
- {
- commonKey256,
- []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,
- },
- []byte{0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10},
- },
-}
-
-func TestCMAC_AES(t *testing.T) {
- for i, tt := range cmacAESTests {
- c, err := aes.NewCipher(tt.key)
- if err != nil {
- t.Errorf("test %d: NewCipher: %s", i, err)
- continue
- }
- d := NewCMAC(c)
- n, err := d.Write(tt.in)
- if err != nil || n != len(tt.in) {
- t.Errorf("test %d: Write %d: %d, %s", i, len(tt.in), n, err)
- continue
- }
- sum := d.Sum()
- if !same(sum, tt.digest) {
- x := d.(*cmac)
- t.Errorf("test %d: digest mismatch\n\twant %x\n\thave %x\n\tk1 %x\n\tk2 %x", i, tt.digest, sum, x.k1, x.k2)
- continue
- }
- }
-}
+++ /dev/null
-// 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 block
-
-import (
- "io"
-)
-
-type ctrStream struct {
- c Cipher
- ctr []byte
- out []byte
-}
-
-func newCTRStream(c Cipher, ctr []byte) *ctrStream {
- x := new(ctrStream)
- x.c = c
- x.ctr = dup(ctr)
- x.out = make([]byte, len(ctr))
- return x
-}
-
-func (x *ctrStream) Next() []byte {
- // Next block is encryption of counter.
- x.c.Encrypt(x.out, x.ctr)
-
- // Increment counter
- for i := len(x.ctr) - 1; i >= 0; i-- {
- x.ctr[i]++
- if x.ctr[i] != 0 {
- break
- }
- }
-
- return x.out
-}
-
-// NewCTRReader returns a reader that reads data from r, decrypts (or encrypts)
-// it using c in counter (CTR) mode with the initialization vector iv.
-// The returned Reader does not buffer and has no block size.
-// In CTR mode, encryption and decryption are the same operation:
-// a CTR reader applied to an encrypted stream produces a decrypted
-// stream and vice versa.
-func NewCTRReader(c Cipher, iv []byte, r io.Reader) io.Reader {
- return newXorReader(newCTRStream(c, iv), r)
-}
-
-// NewCTRWriter returns a writer that encrypts (or decrypts) data using c
-// in counter (CTR) mode with the initialization vector iv
-// and writes the encrypted data to w.
-// The returned Writer does not buffer and has no block size.
-// In CTR mode, encryption and decryption are the same operation:
-// a CTR writer applied to an decrypted stream produces an encrypted
-// stream and vice versa.
-func NewCTRWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
- return newXorWriter(newCTRStream(c, iv), w)
-}
+++ /dev/null
-// 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.
-
-// EAX mode, not a NIST standard (yet).
-// EAX provides encryption and authentication.
-// EAX targets the same uses as NIST's CCM mode,
-// but EAX adds the ability to run in streaming mode.
-
-// See
-// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf
-// http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
-// What those papers call OMAC is now called CMAC.
-
-package block
-
-import (
- "fmt"
- "hash"
- "io"
- "os"
-)
-
-// An EAXTagError is returned when the message has failed to authenticate,
-// because the tag at the end of the message stream (Read) does not match
-// the tag computed from the message itself (Computed).
-type EAXTagError struct {
- Read []byte
- Computed []byte
-}
-
-func (e *EAXTagError) String() string {
- return fmt.Sprintf("crypto/block: EAX tag mismatch: read %x but computed %x", e.Read, e.Computed)
-}
-
-func setupEAX(c Cipher, iv, hdr []byte, tagBytes int) (ctrIV, tag []byte, cmac hash.Hash) {
- n := len(iv)
- if n != c.BlockSize() {
- panic(fmt.Sprintln("crypto/block: EAX: iv length", n, "!=", c.BlockSize()))
- }
- buf := make([]byte, n) // zeroed
-
- // tag = CMAC(0 + iv) ^ CMAC(1 + hdr) ^ CMAC(2 + data)
- cmac = NewCMAC(c)
- cmac.Write(buf) // 0
- cmac.Write(iv)
- sum := cmac.Sum()
- ctrIV = dup(sum)
- tag = dup(sum[0:tagBytes])
-
- cmac.Reset()
- buf[n-1] = 1
- cmac.Write(buf) // 1
- cmac.Write(hdr)
- sum = cmac.Sum()
- for i := 0; i < tagBytes; i++ {
- tag[i] ^= sum[i]
- }
-
- cmac.Reset()
- buf[n-1] = 2 // 2
- cmac.Write(buf)
-
- return
-}
-
-func finishEAX(tag []byte, cmac hash.Hash) {
- // Finish CMAC #2 and xor into tag.
- sum := cmac.Sum()
- for i := range tag {
- tag[i] ^= sum[i]
- }
-}
-
-// Writer adapter. Tees writes into both w and cmac.
-// Knows that cmac never returns write errors.
-type cmacWriter struct {
- w io.Writer
- cmac hash.Hash
-}
-
-func (cw *cmacWriter) Write(p []byte) (n int, err os.Error) {
- n, err = cw.w.Write(p)
- cw.cmac.Write(p[0:n])
- return
-}
-
-// An eaxEncrypter implements the EAX encryption mode.
-type eaxEncrypter struct {
- ctr io.Writer // CTR encrypter
- cw cmacWriter // CTR's output stream
- tag []byte
-}
-
-// NewEAXEncrypter creates and returns a new EAX encrypter
-// using the given cipher c, initialization vector iv, associated data hdr,
-// and tag length tagBytes. The encrypter's Write method encrypts
-// the data it receives and writes that data to w.
-// The encrypter's Close method writes a final authenticating tag to w.
-func NewEAXEncrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, w io.Writer) io.WriteCloser {
- x := new(eaxEncrypter)
-
- // Create new CTR instance writing to both
- // w for encrypted output and cmac for digesting.
- x.cw.w = w
- var ctrIV []byte
- ctrIV, x.tag, x.cw.cmac = setupEAX(c, iv, hdr, tagBytes)
- x.ctr = NewCTRWriter(c, ctrIV, &x.cw)
- return x
-}
-
-func (x *eaxEncrypter) Write(p []byte) (n int, err os.Error) {
- return x.ctr.Write(p)
-}
-
-func (x *eaxEncrypter) Close() os.Error {
- x.ctr = nil // crash if Write is called again
-
- // Write tag.
- finishEAX(x.tag, x.cw.cmac)
- n, err := x.cw.w.Write(x.tag)
- if n != len(x.tag) && err == nil {
- err = io.ErrShortWrite
- }
-
- return err
-}
-
-// Reader adapter. Returns data read from r but hangs
-// on to the last len(tag) bytes for itself (returns EOF len(tag)
-// bytes early). Also tees all data returned from Read into
-// the cmac digest. The "don't return the last t bytes"
-// and the "tee into digest" functionality could be separated,
-// but the latter half is trivial.
-type cmacReader struct {
- r io.Reader
- cmac hash.Hash
- tag []byte
- tmp []byte
-}
-
-func (cr *cmacReader) Read(p []byte) (n int, err os.Error) {
- // TODO(rsc): Maybe fall back to simpler code if
- // we recognize the underlying r as a ByteBuffer
- // or ByteReader. Then we can just take the last piece
- // off at the start.
-
- // First, read a tag-sized chunk.
- // It's probably not the tag (unless there's no data).
- tag := cr.tag
- if len(tag) < cap(tag) {
- nt := len(tag)
- nn, err1 := io.ReadFull(cr.r, tag[nt:cap(tag)])
- tag = tag[0 : nt+nn]
- cr.tag = tag
- if err1 != nil {
- return 0, err1
- }
- }
-
- tagBytes := len(tag)
- if len(p) > 4*tagBytes {
- // If p is big, try to read directly into p to avoid a copy.
- n, err = cr.r.Read(p[tagBytes:])
- if n == 0 {
- goto out
- }
- // copy old tag into p
- for i := 0; i < tagBytes; i++ {
- p[i] = tag[i]
- }
- // copy new tag out of p
- for i := 0; i < tagBytes; i++ {
- tag[i] = p[n+i]
- }
- goto out
- }
-
- // Otherwise, read into p and then slide data
- n, err = cr.r.Read(p)
- if n == 0 {
- goto out
- }
-
- // copy tag+p into p+tmp and then swap tmp, tag
- tmp := cr.tmp
- for i := n + tagBytes - 1; i >= 0; i-- {
- var c byte
- if i < tagBytes {
- c = tag[i]
- } else {
- c = p[i-tagBytes]
- }
- if i < n {
- p[i] = c
- } else {
- tmp[i] = c
- }
- }
- cr.tmp, cr.tag = tag, tmp
-
-out:
- cr.cmac.Write(p[0:n])
- return
-}
-
-type eaxDecrypter struct {
- ctr io.Reader
- cr cmacReader
- tag []byte
-}
-
-// NewEAXDecrypter creates and returns a new EAX decrypter
-// using the given cipher c, initialization vector iv, associated data hdr,
-// and tag length tagBytes. The encrypter's Read method decrypts and
-// returns data read from r. At r's EOF, the encrypter checks the final
-// authenticating tag and returns an EAXTagError if the tag is invalid.
-// In that case, the message should be discarded.
-// Note that the data stream returned from Read cannot be
-// assumed to be valid, authenticated data until Read returns
-// 0, nil to signal the end of the data.
-func NewEAXDecrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, r io.Reader) io.Reader {
- x := new(eaxDecrypter)
-
- x.cr.r = r
- x.cr.tag = make([]byte, 0, tagBytes)
- x.cr.tmp = make([]byte, 0, tagBytes)
- var ctrIV []byte
- ctrIV, x.tag, x.cr.cmac = setupEAX(c, iv, hdr, tagBytes)
- x.ctr = NewCTRReader(c, ctrIV, &x.cr)
- return x
-}
-
-func (x *eaxDecrypter) checkTag() os.Error {
- x.ctr = nil // crash if Read is called again
-
- finishEAX(x.tag, x.cr.cmac)
- if !same(x.tag, x.cr.tag) {
- e := new(EAXTagError)
- e.Computed = dup(x.tag)
- e.Read = dup(x.cr.tag)
- return e
- }
- return nil
-}
-
-func (x *eaxDecrypter) Read(p []byte) (n int, err os.Error) {
- n, err = x.ctr.Read(p)
- if n == 0 && err == nil {
- err = x.checkTag()
- }
- return n, err
-}
+++ /dev/null
-// 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 block
-
-import (
- "bytes"
- "crypto/aes"
- "fmt"
- "io"
- "testing"
-)
-
-// Test vectors from http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
-
-type eaxAESTest struct {
- msg []byte
- key []byte
- nonce []byte
- header []byte
- cipher []byte
-}
-
-var eaxAESTests = []eaxAESTest{
- {
- []byte{},
- []byte{0x23, 0x39, 0x52, 0xDE, 0xE4, 0xD5, 0xED, 0x5F, 0x9B, 0x9C, 0x6D, 0x6F, 0xF8, 0x0F, 0xF4, 0x78},
- []byte{0x62, 0xEC, 0x67, 0xF9, 0xC3, 0xA4, 0xA4, 0x07, 0xFC, 0xB2, 0xA8, 0xC4, 0x90, 0x31, 0xA8, 0xB3},
- []byte{0x6B, 0xFB, 0x91, 0x4F, 0xD0, 0x7E, 0xAE, 0x6B},
- []byte{0xE0, 0x37, 0x83, 0x0E, 0x83, 0x89, 0xF2, 0x7B, 0x02, 0x5A, 0x2D, 0x65, 0x27, 0xE7, 0x9D, 0x01},
- },
- {
- []byte{0xF7, 0xFB},
- []byte{0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B, 0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4},
- []byte{0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84, 0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD},
- []byte{0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA},
- []byte{0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D, 0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79, 0x67, 0xE5},
- },
- {
- []byte{0x1A, 0x47, 0xCB, 0x49, 0x33},
- []byte{0x01, 0xF7, 0x4A, 0xD6, 0x40, 0x77, 0xF2, 0xE7, 0x04, 0xC0, 0xF6, 0x0A, 0xDA, 0x3D, 0xD5, 0x23},
- []byte{0x70, 0xC3, 0xDB, 0x4F, 0x0D, 0x26, 0x36, 0x84, 0x00, 0xA1, 0x0E, 0xD0, 0x5D, 0x2B, 0xFF, 0x5E},
- []byte{0x23, 0x4A, 0x34, 0x63, 0xC1, 0x26, 0x4A, 0xC6},
- []byte{0xD8, 0x51, 0xD5, 0xBA, 0xE0, 0x3A, 0x59, 0xF2, 0x38, 0xA2, 0x3E, 0x39, 0x19, 0x9D, 0xC9, 0x26, 0x66, 0x26, 0xC4, 0x0F, 0x80},
- },
- {
- []byte{0x48, 0x1C, 0x9E, 0x39, 0xB1},
- []byte{0xD0, 0x7C, 0xF6, 0xCB, 0xB7, 0xF3, 0x13, 0xBD, 0xDE, 0x66, 0xB7, 0x27, 0xAF, 0xD3, 0xC5, 0xE8},
- []byte{0x84, 0x08, 0xDF, 0xFF, 0x3C, 0x1A, 0x2B, 0x12, 0x92, 0xDC, 0x19, 0x9E, 0x46, 0xB7, 0xD6, 0x17},
- []byte{0x33, 0xCC, 0xE2, 0xEA, 0xBF, 0xF5, 0xA7, 0x9D},
- []byte{0x63, 0x2A, 0x9D, 0x13, 0x1A, 0xD4, 0xC1, 0x68, 0xA4, 0x22, 0x5D, 0x8E, 0x1F, 0xF7, 0x55, 0x93, 0x99, 0x74, 0xA7, 0xBE, 0xDE},
- },
- {
- []byte{0x40, 0xD0, 0xC0, 0x7D, 0xA5, 0xE4},
- []byte{0x35, 0xB6, 0xD0, 0x58, 0x00, 0x05, 0xBB, 0xC1, 0x2B, 0x05, 0x87, 0x12, 0x45, 0x57, 0xD2, 0xC2},
- []byte{0xFD, 0xB6, 0xB0, 0x66, 0x76, 0xEE, 0xDC, 0x5C, 0x61, 0xD7, 0x42, 0x76, 0xE1, 0xF8, 0xE8, 0x16},
- []byte{0xAE, 0xB9, 0x6E, 0xAE, 0xBE, 0x29, 0x70, 0xE9},
- []byte{0x07, 0x1D, 0xFE, 0x16, 0xC6, 0x75, 0xCB, 0x06, 0x77, 0xE5, 0x36, 0xF7, 0x3A, 0xFE, 0x6A, 0x14, 0xB7, 0x4E, 0xE4, 0x98, 0x44, 0xDD},
- },
- {
- []byte{0x4D, 0xE3, 0xB3, 0x5C, 0x3F, 0xC0, 0x39, 0x24, 0x5B, 0xD1, 0xFB, 0x7D},
- []byte{0xBD, 0x8E, 0x6E, 0x11, 0x47, 0x5E, 0x60, 0xB2, 0x68, 0x78, 0x4C, 0x38, 0xC6, 0x2F, 0xEB, 0x22},
- []byte{0x6E, 0xAC, 0x5C, 0x93, 0x07, 0x2D, 0x8E, 0x85, 0x13, 0xF7, 0x50, 0x93, 0x5E, 0x46, 0xDA, 0x1B},
- []byte{0xD4, 0x48, 0x2D, 0x1C, 0xA7, 0x8D, 0xCE, 0x0F},
- []byte{0x83, 0x5B, 0xB4, 0xF1, 0x5D, 0x74, 0x3E, 0x35, 0x0E, 0x72, 0x84, 0x14, 0xAB, 0xB8, 0x64, 0x4F, 0xD6, 0xCC, 0xB8, 0x69, 0x47, 0xC5, 0xE1, 0x05, 0x90, 0x21, 0x0A, 0x4F},
- },
- {
- []byte{0x8B, 0x0A, 0x79, 0x30, 0x6C, 0x9C, 0xE7, 0xED, 0x99, 0xDA, 0xE4, 0xF8, 0x7F, 0x8D, 0xD6, 0x16, 0x36},
- []byte{0x7C, 0x77, 0xD6, 0xE8, 0x13, 0xBE, 0xD5, 0xAC, 0x98, 0xBA, 0xA4, 0x17, 0x47, 0x7A, 0x2E, 0x7D},
- []byte{0x1A, 0x8C, 0x98, 0xDC, 0xD7, 0x3D, 0x38, 0x39, 0x3B, 0x2B, 0xF1, 0x56, 0x9D, 0xEE, 0xFC, 0x19},
- []byte{0x65, 0xD2, 0x01, 0x79, 0x90, 0xD6, 0x25, 0x28},
- []byte{0x02, 0x08, 0x3E, 0x39, 0x79, 0xDA, 0x01, 0x48, 0x12, 0xF5, 0x9F, 0x11, 0xD5, 0x26, 0x30, 0xDA, 0x30, 0x13, 0x73, 0x27, 0xD1, 0x06, 0x49, 0xB0, 0xAA, 0x6E, 0x1C, 0x18, 0x1D, 0xB6, 0x17, 0xD7, 0xF2},
- },
- {
- []byte{0x1B, 0xDA, 0x12, 0x2B, 0xCE, 0x8A, 0x8D, 0xBA, 0xF1, 0x87, 0x7D, 0x96, 0x2B, 0x85, 0x92, 0xDD, 0x2D, 0x56},
- []byte{0x5F, 0xFF, 0x20, 0xCA, 0xFA, 0xB1, 0x19, 0xCA, 0x2F, 0xC7, 0x35, 0x49, 0xE2, 0x0F, 0x5B, 0x0D},
- []byte{0xDD, 0xE5, 0x9B, 0x97, 0xD7, 0x22, 0x15, 0x6D, 0x4D, 0x9A, 0xFF, 0x2B, 0xC7, 0x55, 0x98, 0x26},
- []byte{0x54, 0xB9, 0xF0, 0x4E, 0x6A, 0x09, 0x18, 0x9A},
- []byte{0x2E, 0xC4, 0x7B, 0x2C, 0x49, 0x54, 0xA4, 0x89, 0xAF, 0xC7, 0xBA, 0x48, 0x97, 0xED, 0xCD, 0xAE, 0x8C, 0xC3, 0x3B, 0x60, 0x45, 0x05, 0x99, 0xBD, 0x02, 0xC9, 0x63, 0x82, 0x90, 0x2A, 0xEF, 0x7F, 0x83, 0x2A},
- },
- {
- []byte{0x6C, 0xF3, 0x67, 0x20, 0x87, 0x2B, 0x85, 0x13, 0xF6, 0xEA, 0xB1, 0xA8, 0xA4, 0x44, 0x38, 0xD5, 0xEF, 0x11},
- []byte{0xA4, 0xA4, 0x78, 0x2B, 0xCF, 0xFD, 0x3E, 0xC5, 0xE7, 0xEF, 0x6D, 0x8C, 0x34, 0xA5, 0x61, 0x23},
- []byte{0xB7, 0x81, 0xFC, 0xF2, 0xF7, 0x5F, 0xA5, 0xA8, 0xDE, 0x97, 0xA9, 0xCA, 0x48, 0xE5, 0x22, 0xEC},
- []byte{0x89, 0x9A, 0x17, 0x58, 0x97, 0x56, 0x1D, 0x7E},
- []byte{0x0D, 0xE1, 0x8F, 0xD0, 0xFD, 0xD9, 0x1E, 0x7A, 0xF1, 0x9F, 0x1D, 0x8E, 0xE8, 0x73, 0x39, 0x38, 0xB1, 0xE8, 0xE7, 0xF6, 0xD2, 0x23, 0x16, 0x18, 0x10, 0x2F, 0xDB, 0x7F, 0xE5, 0x5F, 0xF1, 0x99, 0x17, 0x00},
- },
- {
- []byte{0xCA, 0x40, 0xD7, 0x44, 0x6E, 0x54, 0x5F, 0xFA, 0xED, 0x3B, 0xD1, 0x2A, 0x74, 0x0A, 0x65, 0x9F, 0xFB, 0xBB, 0x3C, 0xEA, 0xB7},
- []byte{0x83, 0x95, 0xFC, 0xF1, 0xE9, 0x5B, 0xEB, 0xD6, 0x97, 0xBD, 0x01, 0x0B, 0xC7, 0x66, 0xAA, 0xC3},
- []byte{0x22, 0xE7, 0xAD, 0xD9, 0x3C, 0xFC, 0x63, 0x93, 0xC5, 0x7E, 0xC0, 0xB3, 0xC1, 0x7D, 0x6B, 0x44},
- []byte{0x12, 0x67, 0x35, 0xFC, 0xC3, 0x20, 0xD2, 0x5A},
- []byte{0xCB, 0x89, 0x20, 0xF8, 0x7A, 0x6C, 0x75, 0xCF, 0xF3, 0x96, 0x27, 0xB5, 0x6E, 0x3E, 0xD1, 0x97, 0xC5, 0x52, 0xD2, 0x95, 0xA7, 0xCF, 0xC4, 0x6A, 0xFC, 0x25, 0x3B, 0x46, 0x52, 0xB1, 0xAF, 0x37, 0x95, 0xB1, 0x24, 0xAB, 0x6E},
- },
-}
-
-func TestEAXEncrypt_AES(t *testing.T) {
- b := new(bytes.Buffer)
- for i, tt := range eaxAESTests {
- test := fmt.Sprintf("test %d", i)
- c, err := aes.NewCipher(tt.key)
- if err != nil {
- t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
- }
- b.Reset()
- enc := NewEAXEncrypter(c, tt.nonce, tt.header, 16, b)
- n, err := io.Copy(enc, bytes.NewBuffer(tt.msg))
- if n != int64(len(tt.msg)) || err != nil {
- t.Fatalf("%s: io.Copy into encrypter: %d, %s", test, n, err)
- }
- err = enc.Close()
- if err != nil {
- t.Fatalf("%s: enc.Close: %s", test, err)
- }
- if d := b.Bytes(); !same(d, tt.cipher) {
- t.Fatalf("%s: got %x want %x", test, d, tt.cipher)
- }
- }
-}
-
-func TestEAXDecrypt_AES(t *testing.T) {
- b := new(bytes.Buffer)
- for i, tt := range eaxAESTests {
- test := fmt.Sprintf("test %d", i)
- c, err := aes.NewCipher(tt.key)
- if err != nil {
- t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
- }
- b.Reset()
- dec := NewEAXDecrypter(c, tt.nonce, tt.header, 16, bytes.NewBuffer(tt.cipher))
- n, err := io.Copy(b, dec)
- if n != int64(len(tt.msg)) || err != nil {
- t.Fatalf("%s: io.Copy into decrypter: %d, %s", test, n, err)
- }
- if d := b.Bytes(); !same(d, tt.msg) {
- t.Fatalf("%s: got %x want %x", test, d, tt.msg)
- }
- }
-}
+++ /dev/null
-// 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.
-
-// Electronic codebook (ECB) mode.
-// ECB is a fancy name for ``encrypt and decrypt each block separately.''
-// It's a pretty bad thing to do for any large amount of data (more than one block),
-// because the individual blocks can still be identified, duplicated, and reordered.
-// The ECB implementation exists mainly to provide buffering for
-// the other modes, which wrap it by providing modified Ciphers.
-
-// See NIST SP 800-38A, pp 9-10
-
-package block
-
-import (
- "io"
- "os"
- "strconv"
-)
-
-type ecbDecrypter struct {
- c Cipher
- r io.Reader
- blockSize int // block size
-
- // Buffered data.
- // The buffer buf is used as storage for both
- // plain or crypt; at least one of those is nil at any given time.
- buf []byte
- plain []byte // plain text waiting to be read
- crypt []byte // ciphertext waiting to be decrypted
-}
-
-// Read into x.crypt until it has a full block or EOF or an error happens.
-func (x *ecbDecrypter) fillCrypt() os.Error {
- var err os.Error
- for len(x.crypt) < x.blockSize {
- off := len(x.crypt)
- var m int
- m, err = x.r.Read(x.crypt[off:x.blockSize])
- x.crypt = x.crypt[0 : off+m]
- if m == 0 {
- break
- }
-
- // If an error happened but we got enough
- // data to do some decryption, we can decrypt
- // first and report the error (with some data) later.
- // But if we don't have enough to decrypt,
- // have to stop now.
- if err != nil && len(x.crypt) < x.blockSize {
- break
- }
- }
- return err
-}
-
-// Read from plain text buffer into p.
-func (x *ecbDecrypter) readPlain(p []byte) int {
- n := len(x.plain)
- if n > len(p) {
- n = len(p)
- }
- for i := 0; i < n; i++ {
- p[i] = x.plain[i]
- }
- if n < len(x.plain) {
- x.plain = x.plain[n:]
- } else {
- x.plain = nil
- }
- return n
-}
-
-type ecbFragmentError int
-
-func (n ecbFragmentError) String() string {
- return "crypto/block: " + strconv.Itoa(int(n)) + "-byte fragment at EOF"
-}
-
-func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) {
- if len(p) == 0 {
- return
- }
-
- // If there's no plaintext waiting and p is not big enough
- // to hold a whole cipher block, we'll have to work in the
- // cipher text buffer. Set it to non-nil so that the
- // code below will fill it.
- if x.plain == nil && len(p) < x.blockSize && x.crypt == nil {
- x.crypt = x.buf[0:0]
- }
-
- // If there is a leftover cipher text buffer,
- // try to accumulate a full block.
- if x.crypt != nil {
- err = x.fillCrypt()
- if err != nil || len(x.crypt) == 0 {
- return
- }
- x.c.Decrypt(x.crypt, x.crypt)
- x.plain = x.crypt
- x.crypt = nil
- }
-
- // If there is a leftover plain text buffer, read from it.
- if x.plain != nil {
- n = x.readPlain(p)
- return
- }
-
- // Read and decrypt directly in caller's buffer.
- n, err = io.ReadAtLeast(x.r, p, x.blockSize)
- if err == os.EOF && n > 0 {
- // EOF is only okay on block boundary
- err = os.ErrorString("block fragment at EOF during decryption")
- return
- }
- var i int
- for i = 0; i+x.blockSize <= n; i += x.blockSize {
- a := p[i : i+x.blockSize]
- x.c.Decrypt(a, a)
- }
-
- // There might be an encrypted fringe remaining.
- // Save it for next time.
- if i < n {
- p = p[i:n]
- copy(x.buf, p)
- x.crypt = x.buf[0:len(p)]
- n = i
- }
-
- return
-}
-
-// NewECBDecrypter returns a reader that reads data from r and decrypts it using c.
-// It decrypts by calling c.Decrypt on each block in sequence;
-// this mode is known as electronic codebook mode, or ECB.
-// The returned Reader does not buffer or read ahead except
-// as required by the cipher's block size.
-func NewECBDecrypter(c Cipher, r io.Reader) io.Reader {
- x := new(ecbDecrypter)
- x.c = c
- x.r = r
- x.blockSize = c.BlockSize()
- x.buf = make([]byte, x.blockSize)
- return x
-}
-
-type ecbEncrypter struct {
- c Cipher
- w io.Writer
- blockSize int
-
- // Buffered data.
- // The buffer buf is used as storage for both
- // plain or crypt. If both are non-nil, plain
- // follows crypt in buf.
- buf []byte
- plain []byte // plain text waiting to be encrypted
- crypt []byte // encrypted text waiting to be written
-}
-
-// Flush the x.crypt buffer to x.w.
-func (x *ecbEncrypter) flushCrypt() os.Error {
- if len(x.crypt) == 0 {
- return nil
- }
- n, err := x.w.Write(x.crypt)
- if n < len(x.crypt) {
- x.crypt = x.crypt[n:]
- if err == nil {
- err = io.ErrShortWrite
- }
- }
- if err != nil {
- return err
- }
- x.crypt = nil
- return nil
-}
-
-// Slide x.plain down to the beginning of x.buf.
-// Plain is known to have less than one block of data,
-// so this is cheap enough.
-func (x *ecbEncrypter) slidePlain() {
- if len(x.plain) == 0 {
- x.plain = x.buf[0:0]
- } else if cap(x.plain) < cap(x.buf) {
- copy(x.buf, x.plain)
- x.plain = x.buf[0:len(x.plain)]
- }
-}
-
-// Fill x.plain from the data in p.
-// Return the number of bytes copied.
-func (x *ecbEncrypter) fillPlain(p []byte) int {
- off := len(x.plain)
- n := len(p)
- if max := cap(x.plain) - off; n > max {
- n = max
- }
- x.plain = x.plain[0 : off+n]
- for i := 0; i < n; i++ {
- x.plain[off+i] = p[i]
- }
- return n
-}
-
-// Encrypt x.plain; record encrypted range as x.crypt.
-func (x *ecbEncrypter) encrypt() {
- var i int
- n := len(x.plain)
- for i = 0; i+x.blockSize <= n; i += x.blockSize {
- a := x.plain[i : i+x.blockSize]
- x.c.Encrypt(a, a)
- }
- x.crypt = x.plain[0:i]
- x.plain = x.plain[i:n]
-}
-
-func (x *ecbEncrypter) Write(p []byte) (n int, err os.Error) {
- for {
- // If there is data waiting to be written, write it.
- // This can happen on the first iteration
- // if a write failed in an earlier call.
- if err = x.flushCrypt(); err != nil {
- return
- }
-
- // Now that encrypted data is gone (flush ran),
- // perhaps we need to slide the plaintext down.
- x.slidePlain()
-
- // Fill plaintext buffer from p.
- m := x.fillPlain(p)
- if m == 0 {
- break
- }
- n += m
- p = p[m:]
-
- // Encrypt, adjusting crypt and plain.
- x.encrypt()
-
- // Write x.crypt.
- if err = x.flushCrypt(); err != nil {
- break
- }
- }
- return
-}
-
-// NewECBEncrypter returns a writer that encrypts data using c and writes it to w.
-// It encrypts by calling c.Encrypt on each block in sequence;
-// this mode is known as electronic codebook mode, or ECB.
-// The returned Writer does no buffering except as required
-// by the cipher's block size, so there is no need for a Flush method.
-func NewECBEncrypter(c Cipher, w io.Writer) io.Writer {
- x := new(ecbEncrypter)
- x.c = c
- x.w = w
- x.blockSize = c.BlockSize()
-
- // Create a buffer that is an integral number of blocks.
- x.buf = make([]byte, 8192/x.blockSize*x.blockSize)
- return x
-}
+++ /dev/null
-// 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.
-
-// ECB 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-27.
-
-package block
-
-import (
- "bytes"
- "crypto/aes"
- "io"
- "testing"
-)
-
-type ecbTest struct {
- name string
- key []byte
- in []byte
- out []byte
-}
-
-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}
-
-var ecbAESTests = []ecbTest{
- // FIPS 197, Appendix B, C
- {
- "FIPS-197 Appendix B",
- commonKey128,
- []byte{0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34},
- []byte{0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32},
- },
-
- // NIST SP 800-38A pp 24-27
- {
- "ECB-AES128",
- commonKey128,
- commonInput,
- []byte{
- 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
- 0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d, 0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf,
- 0x43, 0xb1, 0xcd, 0x7f, 0x59, 0x8e, 0xce, 0x23, 0x88, 0x1b, 0x00, 0xe3, 0xed, 0x03, 0x06, 0x88,
- 0x7b, 0x0c, 0x78, 0x5e, 0x27, 0xe8, 0xad, 0x3f, 0x82, 0x23, 0x20, 0x71, 0x04, 0x72, 0x5d, 0xd4,
- },
- },
- {
- "ECB-AES192",
- commonKey192,
- commonInput,
- []byte{
- 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc,
- 0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad, 0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef,
- 0xef, 0x7a, 0xfd, 0x22, 0x70, 0xe2, 0xe6, 0x0a, 0xdc, 0xe0, 0xba, 0x2f, 0xac, 0xe6, 0x44, 0x4e,
- 0x9a, 0x4b, 0x41, 0xba, 0x73, 0x8d, 0x6c, 0x72, 0xfb, 0x16, 0x69, 0x16, 0x03, 0xc1, 0x8e, 0x0e,
- },
- },
- {
- "ECB-AES256",
- commonKey256,
- commonInput,
- []byte{
- 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8,
- 0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26, 0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70,
- 0xb6, 0xed, 0x21, 0xb9, 0x9c, 0xa6, 0xf4, 0xf9, 0xf1, 0x53, 0xe7, 0xb1, 0xbe, 0xaf, 0xed, 0x1d,
- 0x23, 0x30, 0x4b, 0x7a, 0x39, 0xf9, 0xf3, 0xff, 0x06, 0x7d, 0x8d, 0x8f, 0x9e, 0x24, 0xec, 0xc7,
- },
- },
-}
-
-func TestECB_AES(t *testing.T) {
- for _, tt := range ecbAESTests {
- 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
- }
-
- var crypt bytes.Buffer
- w := NewECBEncrypter(c, &crypt)
- var r io.Reader = bytes.NewBuffer(tt.in)
- n, err := io.Copy(w, r)
- if n != int64(len(tt.in)) || err != nil {
- t.Errorf("%s: ECBReader io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
- } else if d := crypt.Bytes(); !same(tt.out, d) {
- t.Errorf("%s: ECBReader\nhave %x\nwant %x", test, d, tt.out)
- }
-
- var plain bytes.Buffer
- r = NewECBDecrypter(c, bytes.NewBuffer(tt.out))
- w = &plain
- n, err = io.Copy(w, r)
- if n != int64(len(tt.out)) || err != nil {
- t.Errorf("%s: ECBWriter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
- } else if d := plain.Bytes(); !same(tt.in, d) {
- t.Errorf("%s: ECBWriter\nhave %x\nwant %x", test, d, tt.in)
- }
-
- if t.Failed() {
- break
- }
- }
-}
+++ /dev/null
-// 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 block
-
-import (
- "bytes"
- "fmt"
- "io"
- "testing"
- "testing/iotest"
-)
-
-// Simple Cipher for testing: adds an incrementing amount
-// to each byte in each
-type IncCipher struct {
- blockSize int
- delta byte
- encrypting bool
-}
-
-func (c *IncCipher) BlockSize() int { return c.blockSize }
-
-func (c *IncCipher) Encrypt(dst, src []byte) {
- if !c.encrypting {
- panic("encrypt: not encrypting")
- }
- if len(src) != c.blockSize || len(dst) != c.blockSize {
- panic(fmt.Sprintln("encrypt: wrong block size", c.blockSize, len(src), len(dst)))
- }
- c.delta++
- for i, b := range src {
- dst[i] = b + c.delta
- }
-}
-
-func (c *IncCipher) Decrypt(dst, src []byte) {
- if c.encrypting {
- panic("decrypt: not decrypting")
- }
- if len(src) != c.blockSize || len(dst) != c.blockSize {
- panic(fmt.Sprintln("decrypt: wrong block size ", c.blockSize, " ", len(src), " ", len(dst)))
- }
- c.delta--
- for i, b := range src {
- dst[i] = b + c.delta
- }
-}
-
-func TestECBEncrypter(t *testing.T) {
- var plain, crypt [256]byte
- for i := 0; i < len(plain); i++ {
- plain[i] = byte(i)
- }
- b := new(bytes.Buffer)
- for block := 1; block <= 64; block *= 2 {
- // compute encrypted version
- delta := byte(0)
- for i := 0; i < len(crypt); i++ {
- if i%block == 0 {
- delta++
- }
- crypt[i] = plain[i] + delta
- }
-
- for frag := 0; frag < 2; frag++ {
- c := &IncCipher{block, 0, true}
- b.Reset()
- r := bytes.NewBuffer(plain[0:])
- w := NewECBEncrypter(c, b)
-
- // copy plain into w in increasingly large chunks: 1, 1, 2, 4, 8, ...
- // if frag != 0, move the 1 to the end to cause fragmentation.
- if frag == 0 {
- _, err := io.Copyn(w, r, 1)
- if err != nil {
- t.Errorf("block=%d frag=0: first Copyn: %s", block, err)
- continue
- }
- }
- for n := 1; n <= len(plain)/2; n *= 2 {
- _, err := io.Copyn(w, r, int64(n))
- if err != nil {
- t.Errorf("block=%d frag=%d: Copyn %d: %s", block, frag, n, err)
- }
- }
- if frag != 0 {
- _, err := io.Copyn(w, r, 1)
- if err != nil {
- t.Errorf("block=%d frag=1: last Copyn: %s", block, err)
- continue
- }
- }
-
- // check output
- data := b.Bytes()
- if len(data) != len(crypt) {
- t.Errorf("block=%d frag=%d: want %d bytes, got %d", block, frag, len(crypt), len(data))
- continue
- }
-
- if string(data) != string(crypt[0:]) {
- t.Errorf("block=%d frag=%d: want %x got %x", block, frag, data, crypt)
- }
- }
- }
-}
-
-func testECBDecrypter(t *testing.T, maxio int) {
- var readers = []func(io.Reader) io.Reader{
- func(r io.Reader) io.Reader { return r },
- iotest.OneByteReader,
- iotest.HalfReader,
- }
- var plain, crypt [256]byte
- for i := 0; i < len(plain); i++ {
- plain[i] = byte(255 - i)
- }
- b := new(bytes.Buffer)
- for block := 1; block <= 64 && block <= maxio; block *= 2 {
- // compute encrypted version
- delta := byte(0)
- for i := 0; i < len(crypt); i++ {
- if i%block == 0 {
- delta++
- }
- crypt[i] = plain[i] + delta
- }
-
- for mode := 0; mode < len(readers); mode++ {
- for frag := 0; frag < 2; frag++ {
- test := fmt.Sprintf("block=%d mode=%d frag=%d maxio=%d", block, mode, frag, maxio)
- c := &IncCipher{block, 0, false}
- b.Reset()
- r := NewECBDecrypter(c, readers[mode](bytes.NewBuffer(crypt[0:maxio])))
-
- // read from crypt in increasingly large chunks: 1, 1, 2, 4, 8, ...
- // if frag == 1, move the 1 to the end to cause fragmentation.
- if frag == 0 {
- _, err := io.Copyn(b, r, 1)
- if err != nil {
- t.Errorf("%s: first Copyn: %s", test, err)
- continue
- }
- }
- for n := 1; n <= maxio/2; n *= 2 {
- _, err := io.Copyn(b, r, int64(n))
- if err != nil {
- t.Errorf("%s: Copyn %d: %s", test, n, err)
- }
- }
- if frag != 0 {
- _, err := io.Copyn(b, r, 1)
- if err != nil {
- t.Errorf("%s: last Copyn: %s", test, err)
- continue
- }
- }
-
- // check output
- data := b.Bytes()
- if len(data) != maxio {
- t.Errorf("%s: want %d bytes, got %d", test, maxio, len(data))
- continue
- }
-
- if string(data) != string(plain[0:maxio]) {
- t.Errorf("%s: input=%x want %x got %x", test, crypt[0:maxio], plain[0:maxio], data)
- }
- }
- }
- }
-}
-
-func TestECBDecrypter(t *testing.T) {
- // Do shorter I/O sizes first; they're easier to debug.
- for n := 1; n <= 256 && !t.Failed(); n *= 2 {
- testECBDecrypter(t, n)
- }
-}
+++ /dev/null
-// 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.
-
-// Output feedback (OFB) mode.
-
-// OFB converts a block cipher into a stream cipher by
-// repeatedly encrypting an initialization vector and
-// xoring the resulting stream of data with the input.
-
-// See NIST SP 800-38A, pp 13-15
-
-package block
-
-import (
- "fmt"
- "io"
-)
-
-type ofbStream struct {
- c Cipher
- iv []byte
-}
-
-func newOFBStream(c Cipher, iv []byte) *ofbStream {
- x := new(ofbStream)
- x.c = c
- n := len(iv)
- if n != c.BlockSize() {
- panic(fmt.Sprintln("crypto/block: newOFBStream: invalid iv size", n, "!=", c.BlockSize()))
- }
- x.iv = dup(iv)
- return x
-}
-
-func (x *ofbStream) Next() []byte {
- x.c.Encrypt(x.iv, x.iv)
- return x.iv
-}
-
-// NewOFBReader returns a reader that reads data from r, decrypts (or encrypts)
-// it using c in output feedback (OFB) mode with the initialization vector iv.
-// The returned Reader does not buffer and has no block size.
-// In OFB mode, encryption and decryption are the same operation:
-// an OFB reader applied to an encrypted stream produces a decrypted
-// stream and vice versa.
-func NewOFBReader(c Cipher, iv []byte, r io.Reader) io.Reader {
- return newXorReader(newOFBStream(c, iv), r)
-}
-
-// NewOFBWriter returns a writer that encrypts (or decrypts) data using c
-// in cipher feedback (OFB) mode with the initialization vector iv
-// and writes the encrypted data to w.
-// The returned Writer does not buffer and has no block size.
-// In OFB mode, encryption and decryption are the same operation:
-// an OFB writer applied to an decrypted stream produces an encrypted
-// stream and vice versa.
-func NewOFBWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
- return newXorWriter(newOFBStream(c, iv), w)
-}
+++ /dev/null
-// 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 block
-
-import (
- "bytes"
- "crypto/aes"
- "io"
- "testing"
-)
-
-type ofbTest struct {
- name string
- key []byte
- iv []byte
- in []byte
- out []byte
-}
-
-var ofbAESTests = []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_AES(t *testing.T) {
- for _, tt := range ofbAESTests {
- 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 {
- var crypt bytes.Buffer
- in := tt.in[0 : len(tt.in)-j]
- w := NewOFBWriter(c, tt.iv, &crypt)
- var r io.Reader = bytes.NewBuffer(in)
- n, err := io.Copy(w, r)
- if n != int64(len(in)) || err != nil {
- t.Errorf("%s/%d: OFBWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in))
- } else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
- t.Errorf("%s/%d: OFBWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out)
- }
- }
-
- for j := 0; j <= 7; j += 7 {
- var plain bytes.Buffer
- out := tt.out[0 : len(tt.out)-j]
- r := NewOFBReader(c, tt.iv, bytes.NewBuffer(out))
- w := &plain
- n, err := io.Copy(w, r)
- if n != int64(len(out)) || err != nil {
- t.Errorf("%s/%d: OFBReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out))
- } else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
- t.Errorf("%s/%d: OFBReader\nhave %x\nwant %x", test, len(out), d, in)
- }
- }
-
- if t.Failed() {
- break
- }
- }
-}
+++ /dev/null
-// 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.
-
-// Encrypt/decrypt data by xor with a pseudo-random data stream.
-
-package block
-
-import (
- "io"
- "os"
-)
-
-// A dataStream is an interface to an unending stream of data,
-// used by XorReader and XorWriter to model a pseudo-random generator.
-// Calls to Next() return sequential blocks of data from the stream.
-// Each call must return at least one byte: there is no EOF.
-type dataStream interface {
- Next() []byte
-}
-
-type xorReader struct {
- r io.Reader
- rand dataStream // pseudo-random
- buf []byte // data available from last call to rand
-}
-
-func newXorReader(rand dataStream, r io.Reader) io.Reader {
- x := new(xorReader)
- x.r = r
- x.rand = rand
- return x
-}
-
-func (x *xorReader) Read(p []byte) (n int, err os.Error) {
- n, err = x.r.Read(p)
-
- // xor input with stream.
- bp := 0
- buf := x.buf
- for i := 0; i < n; i++ {
- if bp >= len(buf) {
- buf = x.rand.Next()
- bp = 0
- }
- p[i] ^= buf[bp]
- bp++
- }
- x.buf = buf[bp:]
- return n, err
-}
-
-type xorWriter struct {
- w io.Writer
- rand dataStream // pseudo-random
- buf []byte // last buffer returned by rand
- extra []byte // extra random data (use before buf)
- work []byte // work space
-}
-
-func newXorWriter(rand dataStream, w io.Writer) io.Writer {
- x := new(xorWriter)
- x.w = w
- x.rand = rand
- x.work = make([]byte, 4096)
- return x
-}
-
-func (x *xorWriter) Write(p []byte) (n int, err os.Error) {
- for len(p) > 0 {
- // Determine next chunk of random data
- // and xor with p into x.work.
- var chunk []byte
- m := len(p)
- if nn := len(x.extra); nn > 0 {
- // extra points into work, so edit directly
- if m > nn {
- m = nn
- }
- for i := 0; i < m; i++ {
- x.extra[i] ^= p[i]
- }
- chunk = x.extra[0:m]
- } else {
- // xor p ^ buf into work, refreshing buf as needed
- if nn := len(x.work); m > nn {
- m = nn
- }
- bp := 0
- buf := x.buf
- for i := 0; i < m; i++ {
- if bp >= len(buf) {
- buf = x.rand.Next()
- bp = 0
- }
- x.work[i] = buf[bp] ^ p[i]
- bp++
- }
- x.buf = buf[bp:]
- chunk = x.work[0:m]
- }
-
- // Write chunk.
- var nn int
- nn, err = x.w.Write(chunk)
- if nn != len(chunk) && err == nil {
- err = io.ErrShortWrite
- }
- if nn < len(chunk) {
- // Reconstruct the random bits from the unwritten
- // data and save them for next time.
- for i := nn; i < m; i++ {
- chunk[i] ^= p[i]
- }
- x.extra = chunk[nn:]
- }
- n += nn
- if err != nil {
- return
- }
- p = p[m:]
- }
- return
-}
+++ /dev/null
-// 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 block
-
-import (
- "bytes"
- "fmt"
- "io"
- "testing"
- "testing/iotest"
-)
-
-// Simple "pseudo-random" stream for testing.
-type incStream struct {
- buf []byte
- n byte
-}
-
-func newIncStream(blockSize int) *incStream {
- x := new(incStream)
- x.buf = make([]byte, blockSize)
- return x
-}
-
-func (x *incStream) Next() []byte {
- x.n++
- for i := range x.buf {
- x.buf[i] = x.n
- x.n++
- }
- return x.buf
-}
-
-func testXorWriter(t *testing.T, maxio int) {
- var plain, crypt [256]byte
- for i := 0; i < len(plain); i++ {
- plain[i] = byte(i)
- }
- b := new(bytes.Buffer)
- for block := 1; block <= 64 && block <= maxio; block *= 2 {
- // compute encrypted version
- n := byte(0)
- for i := 0; i < len(crypt); i++ {
- if i%block == 0 {
- n++
- }
- crypt[i] = plain[i] ^ n
- n++
- }
-
- for frag := 0; frag < 2; frag++ {
- test := fmt.Sprintf("block=%d frag=%d maxio=%d", block, frag, maxio)
- b.Reset()
- r := bytes.NewBuffer(plain[0:])
- s := newIncStream(block)
- w := newXorWriter(s, b)
-
- // copy plain into w in increasingly large chunks: 1, 1, 2, 4, 8, ...
- // if frag != 0, move the 1 to the end to cause fragmentation.
- if frag == 0 {
- _, err := io.Copyn(w, r, 1)
- if err != nil {
- t.Errorf("%s: first Copyn: %s", test, err)
- continue
- }
- }
- for n := 1; n <= len(plain)/2; n *= 2 {
- _, err := io.Copyn(w, r, int64(n))
- if err != nil {
- t.Errorf("%s: Copyn %d: %s", test, n, err)
- }
- }
-
- // check output
- crypt := crypt[0 : len(crypt)-frag]
- data := b.Bytes()
- if len(data) != len(crypt) {
- t.Errorf("%s: want %d bytes, got %d", test, len(crypt), len(data))
- continue
- }
-
- if string(data) != string(crypt) {
- t.Errorf("%s: want %x got %x", test, data, crypt)
- }
- }
- }
-}
-
-
-func TestXorWriter(t *testing.T) {
- // Do shorter I/O sizes first; they're easier to debug.
- for n := 1; n <= 256 && !t.Failed(); n *= 2 {
- testXorWriter(t, n)
- }
-}
-
-func testXorReader(t *testing.T, maxio int) {
- var readers = []func(io.Reader) io.Reader{
- func(r io.Reader) io.Reader { return r },
- iotest.OneByteReader,
- iotest.HalfReader,
- }
- var plain, crypt [256]byte
- for i := 0; i < len(plain); i++ {
- plain[i] = byte(255 - i)
- }
- b := new(bytes.Buffer)
- for block := 1; block <= 64 && block <= maxio; block *= 2 {
- // compute encrypted version
- n := byte(0)
- for i := 0; i < len(crypt); i++ {
- if i%block == 0 {
- n++
- }
- crypt[i] = plain[i] ^ n
- n++
- }
-
- for mode := 0; mode < len(readers); mode++ {
- for frag := 0; frag < 2; frag++ {
- test := fmt.Sprintf("block=%d mode=%d frag=%d maxio=%d", block, mode, frag, maxio)
- s := newIncStream(block)
- b.Reset()
- r := newXorReader(s, readers[mode](bytes.NewBuffer(crypt[0:maxio])))
-
- // read from crypt in increasingly large chunks: 1, 1, 2, 4, 8, ...
- // if frag == 1, move the 1 to the end to cause fragmentation.
- if frag == 0 {
- _, err := io.Copyn(b, r, 1)
- if err != nil {
- t.Errorf("%s: first Copyn: %s", test, err)
- continue
- }
- }
- for n := 1; n <= maxio/2; n *= 2 {
- _, err := io.Copyn(b, r, int64(n))
- if err != nil {
- t.Errorf("%s: Copyn %d: %s", test, n, err)
- }
- }
-
- // check output
- data := b.Bytes()
- crypt := crypt[0 : maxio-frag]
- plain := plain[0 : maxio-frag]
- if len(data) != len(plain) {
- t.Errorf("%s: want %d bytes, got %d", test, len(plain), len(data))
- continue
- }
-
- if string(data) != string(plain) {
- t.Errorf("%s: input=%x want %x got %x", test, crypt, plain, data)
- }
- }
- }
- }
-}
-
-func TestXorReader(t *testing.T) {
- // Do shorter I/O sizes first; they're easier to debug.
- for n := 1; n <= 256 && !t.Failed(); n *= 2 {
- testXorReader(t, n)
- }
-}
-
-// TODO(rsc): Test handling of writes after write errors.
--- /dev/null
+// 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.
+
+package des
+
+import (
+ "encoding/binary"
+)
+
+func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
+ b := binary.BigEndian.Uint64(src)
+ b = permuteBlock(b, initialPermutation[:])
+ left, right := uint32(b>>32), uint32(b)
+
+ var subkey uint64
+ for i := 0; i < 16; i++ {
+ if decrypt {
+ subkey = subkeys[15-i]
+ } else {
+ subkey = subkeys[i]
+ }
+
+ left, right = right, left^feistel(right, subkey)
+ }
+ // switch left & right and perform final permutation
+ preOutput := (uint64(right) << 32) | uint64(left)
+ binary.BigEndian.PutUint64(dst, permuteBlock(preOutput, finalPermutation[:]))
+}
+
+// Encrypt one block from src into dst, using the subkeys.
+func encryptBlock(subkeys []uint64, dst, src []byte) {
+ cryptBlock(subkeys, dst, src, false)
+}
+
+// Decrypt one block from src into dst, using the subkeys.
+func decryptBlock(subkeys []uint64, dst, src []byte) {
+ cryptBlock(subkeys, dst, src, true)
+}
+
+// DES Feistel function
+func feistel(right uint32, key uint64) (result uint32) {
+ sBoxLocations := key ^ permuteBlock(uint64(right), expansionFunction[:])
+ var sBoxResult uint32
+ for i := uint8(0); i < 8; i++ {
+ sBoxLocation := uint8(sBoxLocations>>42) & 0x3f
+ sBoxLocations <<= 6
+ // row determined by 1st and 6th bit
+ row := (sBoxLocation & 0x1) | ((sBoxLocation & 0x20) >> 4)
+ // column is middle four bits
+ column := (sBoxLocation >> 1) & 0xf
+ sBoxResult |= uint32(sBoxes[i][row][column]) << (4 * (7 - i))
+ }
+ return uint32(permuteBlock(uint64(sBoxResult), permutationFunction[:]))
+}
+
+// general purpose function to perform DES block permutations
+func permuteBlock(src uint64, permutation []uint8) (block uint64) {
+ for position, n := range permutation {
+ bit := (src >> n) & 1
+ block |= bit << uint((len(permutation)-1)-position)
+ }
+ return
+}
+
+// creates 16 28-bit blocks rotated according
+// to the rotation schedule
+func ksRotate(in uint32) (out []uint32) {
+ out = make([]uint32, 16)
+ last := in
+ for i := 0; i < 16; i++ {
+ // 28-bit circular left shift
+ left := (last << (4 + ksRotations[i])) >> 4
+ right := (last << 4) >> (32 - ksRotations[i])
+ out[i] = left | right
+ last = out[i]
+ }
+ return
+}
+
+// creates 16 56-bit subkeys from the original key
+func (c *Cipher) generateSubkeys(keyBytes []byte) {
+ // apply PC1 permutation to key
+ key := binary.BigEndian.Uint64(keyBytes)
+ permutedKey := permuteBlock(key, permutedChoice1[:])
+
+ // rotate halves of permuted key according to the rotation schedule
+ leftRotations := ksRotate(uint32(permutedKey >> 28))
+ rightRotations := ksRotate(uint32(permutedKey<<4) >> 4)
+
+ // generate subkeys
+ for i := 0; i < 16; i++ {
+ // combine halves to form 56-bit input to PC2
+ pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i])
+ // apply PC2 permutation to 7 byte input
+ c.subkeys[i] = permuteBlock(pc2Input, permutedChoice2[:])
+ }
+}
--- /dev/null
+// 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.
+
+package des
+
+import (
+ "os"
+ "strconv"
+)
+
+// The DES block size in bytes.
+const BlockSize = 8
+
+type KeySizeError int
+
+func (k KeySizeError) String() string {
+ return "crypto/des: invalid key size " + strconv.Itoa(int(k))
+}
+
+// Cipher is an instance of DES encryption.
+type Cipher struct {
+ subkeys [16]uint64
+}
+
+// NewCipher creates and returns a new Cipher.
+func NewCipher(key []byte) (*Cipher, os.Error) {
+ if len(key) != 8 {
+ return nil, KeySizeError(len(key))
+ }
+
+ c := new(Cipher)
+ c.generateSubkeys(key)
+ return c, nil
+}
+
+// BlockSize returns the DES block size, 8 bytes.
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// Encrypts the 8-byte buffer src and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
+
+// Decrypts the 8-byte buffer src and stores the result in dst.
+func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
+
+// Reset zeros the key data, so that it will no longer
+// appear in the process's memory.
+func (c *Cipher) Reset() {
+ for i := 0; i < len(c.subkeys); i++ {
+ c.subkeys[i] = 0
+ }
+}
+
+// A TripleDESCipher is an instance of TripleDES encryption.
+type TripleDESCipher struct {
+ cipher1, cipher2, cipher3 Cipher
+}
+
+// NewCipher creates and returns a new Cipher.
+func NewTripleDESCipher(key []byte) (*TripleDESCipher, os.Error) {
+ if len(key) != 24 {
+ return nil, KeySizeError(len(key))
+ }
+
+ c := new(TripleDESCipher)
+ c.cipher1.generateSubkeys(key[:8])
+ c.cipher2.generateSubkeys(key[8:16])
+ c.cipher3.generateSubkeys(key[16:])
+ return c, nil
+}
+
+// BlockSize returns the TripleDES block size, 8 bytes.
+// It is necessary to satisfy the Block interface in the
+// package "crypto/cipher".
+func (c *TripleDESCipher) BlockSize() int { return BlockSize }
+
+// Encrypts the 8-byte buffer src and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *TripleDESCipher) Encrypt(dst, src []byte) {
+ c.cipher1.Encrypt(dst, src)
+ c.cipher2.Decrypt(dst, dst)
+ c.cipher3.Encrypt(dst, dst)
+}
+
+// Decrypts the 8-byte buffer src and stores the result in dst.
+func (c *TripleDESCipher) Decrypt(dst, src []byte) {
+ c.cipher3.Decrypt(dst, src)
+ c.cipher2.Encrypt(dst, dst)
+ c.cipher1.Decrypt(dst, dst)
+}
+
+// Reset zeros the key data, so that it will no longer
+// appear in the process's memory.
+func (c *TripleDESCipher) Reset() {
+ c.cipher1.Reset()
+ c.cipher2.Reset()
+ c.cipher3.Reset()
+}
--- /dev/null
+// 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 des implements the Data Encryption Standard (DES) and the
+// Triple Data Encryption Algorithm (TDEA) as defined
+// in U.S. Federal Information Processing Standards Publication 46-3.
+package des
+
+// Used to perform an initial permutation of a 64-bit input block.
+var initialPermutation = [64]byte{
+ 6, 14, 22, 30, 38, 46, 54, 62,
+ 4, 12, 20, 28, 36, 44, 52, 60,
+ 2, 10, 18, 26, 34, 42, 50, 58,
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 7, 15, 23, 31, 39, 47, 55, 63,
+ 5, 13, 21, 29, 37, 45, 53, 61,
+ 3, 11, 19, 27, 35, 43, 51, 59,
+ 1, 9, 17, 25, 33, 41, 49, 57,
+}
+
+// Used to perform a final permutation of a 4-bit preoutput block. This is the
+// inverse of initialPermutation
+var finalPermutation = [64]byte{
+ 24, 56, 16, 48, 8, 40, 0, 32,
+ 25, 57, 17, 49, 9, 41, 1, 33,
+ 26, 58, 18, 50, 10, 42, 2, 34,
+ 27, 59, 19, 51, 11, 43, 3, 35,
+ 28, 60, 20, 52, 12, 44, 4, 36,
+ 29, 61, 21, 53, 13, 45, 5, 37,
+ 30, 62, 22, 54, 14, 46, 6, 38,
+ 31, 63, 23, 55, 15, 47, 7, 39,
+}
+
+// Used to expand an input block of 32 bits, producing an output block of 48
+// bits.
+var expansionFunction = [48]byte{
+ 0, 31, 30, 29, 28, 27, 28, 27,
+ 26, 25, 24, 23, 24, 23, 22, 21,
+ 20, 19, 20, 19, 18, 17, 16, 15,
+ 16, 15, 14, 13, 12, 11, 12, 11,
+ 10, 9, 8, 7, 8, 7, 6, 5,
+ 4, 3, 4, 3, 2, 1, 0, 31,
+}
+
+// Yields a 32-bit output from a 32-bit input
+var permutationFunction = [32]byte{
+ 16, 25, 12, 11, 3, 20, 4, 15,
+ 31, 17, 9, 6, 27, 14, 1, 22,
+ 30, 24, 8, 18, 0, 5, 29, 23,
+ 13, 19, 2, 26, 10, 21, 28, 7,
+}
+
+// Used in the key schedule to select 56 bits
+// from a 64-bit input.
+var permutedChoice1 = [56]byte{
+ 7, 15, 23, 31, 39, 47, 55, 63,
+ 6, 14, 22, 30, 38, 46, 54, 62,
+ 5, 13, 21, 29, 37, 45, 53, 61,
+ 4, 12, 20, 28, 1, 9, 17, 25,
+ 33, 41, 49, 57, 2, 10, 18, 26,
+ 34, 42, 50, 58, 3, 11, 19, 27,
+ 35, 43, 51, 59, 36, 44, 52, 60,
+}
+
+// Used in the key schedule to produce each subkey by selecting 48 bits from
+// the 56-bit input
+var permutedChoice2 = [48]byte{
+ 42, 39, 45, 32, 55, 51, 53, 28,
+ 41, 50, 35, 46, 33, 37, 44, 52,
+ 30, 48, 40, 49, 29, 36, 43, 54,
+ 15, 4, 25, 19, 9, 1, 26, 16,
+ 5, 11, 23, 8, 12, 7, 17, 0,
+ 22, 3, 10, 14, 6, 20, 27, 24,
+}
+
+// 8 S-boxes composed of 4 rows and 16 columns
+// Used in the DES cipher function
+var sBoxes = [8][4][16]uint8{
+ // S-box 1
+ {
+ {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
+ {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
+ {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
+ {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13},
+ },
+ // S-box 2
+ {
+ {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
+ {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
+ {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
+ {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9},
+ },
+ // S-box 3
+ {
+ {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
+ {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
+ {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
+ {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12},
+ },
+ // S-box 4
+ {
+ {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
+ {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
+ {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
+ {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},
+ },
+ // S-box 5
+ {
+ {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
+ {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
+ {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
+ {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3},
+ },
+ // S-box 6
+ {
+ {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
+ {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
+ {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
+ {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13},
+ },
+ // S-box 7
+ {
+ {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
+ {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
+ {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
+ {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12},
+ },
+ // S-box 8
+ {
+ {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
+ {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
+ {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
+ {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11},
+ },
+}
+
+// Size of left rotation per round in each half of the key schedule
+var ksRotations = [16]uint8{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}
--- /dev/null
+// 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.
+
+package des
+
+import (
+ "bytes"
+ "testing"
+)
+
+type CryptTest struct {
+ key []byte
+ in []byte
+ out []byte
+}
+
+// some custom tests for DES
+var encryptDESTests = []CryptTest{
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7}},
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x35, 0x55, 0x50, 0xb2, 0x15, 0x0e, 0x24, 0x51}},
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0x61, 0x7b, 0x3a, 0x0c, 0xe8, 0xf0, 0x71, 0x00}},
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0x92, 0x31, 0xf2, 0x36, 0xff, 0x9a, 0xa9, 0x5c}},
+ {
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xca, 0xaa, 0xaf, 0x4d, 0xea, 0xf1, 0xdb, 0xae}},
+ {
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x73, 0x59, 0xb2, 0x16, 0x3e, 0x4e, 0xdc, 0x58}},
+ {
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0x6d, 0xce, 0x0d, 0xc9, 0x00, 0x65, 0x56, 0xa3}},
+ {
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0x9e, 0x84, 0xc5, 0xf3, 0x17, 0x0f, 0x8e, 0xff}},
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xd5, 0xd4, 0x4f, 0xf7, 0x20, 0x68, 0x3d, 0x0d}},
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x59, 0x73, 0x23, 0x56, 0xf3, 0x6f, 0xde, 0x06}},
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0x56, 0xcc, 0x09, 0xe7, 0xcf, 0xdc, 0x4c, 0xef}},
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0x12, 0xc6, 0x26, 0xaf, 0x05, 0x8b, 0x43, 0x3b}},
+ {
+ []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xa6, 0x8c, 0xdc, 0xa9, 0x0c, 0x90, 0x21, 0xf9}},
+ {
+ []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x2a, 0x2b, 0xb0, 0x08, 0xdf, 0x97, 0xc2, 0xf2}},
+ {
+ []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0xed, 0x39, 0xd9, 0x50, 0xfa, 0x74, 0xbc, 0xc4}},
+ {
+ []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ []byte{0xa9, 0x33, 0xf6, 0x18, 0x30, 0x23, 0xb3, 0x10}},
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+ []byte{0x17, 0x66, 0x8d, 0xfc, 0x72, 0x92, 0x53, 0x2d}},
+ {
+ []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+ []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ []byte{0xb4, 0xfd, 0x23, 0x16, 0x47, 0xa5, 0xbe, 0xc0}},
+ {
+ []byte{0x0e, 0x32, 0x92, 0x32, 0xea, 0x6d, 0x0d, 0x73},
+ []byte{0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+ {
+ []byte{0x73, 0x65, 0x63, 0x52, 0x33, 0x74, 0x24, 0x3b}, // "secR3t$;"
+ []byte{0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x31, 0x32}, // "a test12"
+ []byte{0x37, 0x0d, 0xee, 0x2c, 0x1f, 0xb4, 0xf7, 0xa5}},
+ {
+ []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+ []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+ []byte{0x2a, 0x8d, 0x69, 0xde, 0x9d, 0x5f, 0xdf, 0xf9}},
+ {
+ []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+ []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+ []byte{0x21, 0xc6, 0x0d, 0xa5, 0x34, 0x24, 0x8b, 0xce}},
+ {
+ []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+ []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+ []byte{0x94, 0xd4, 0x43, 0x6b, 0xc3, 0xb5, 0xb6, 0x93}},
+ {
+ []byte{0x1f, 0x79, 0x90, 0x5f, 0x88, 0x01, 0xc8, 0x88}, // random
+ []byte{0xc7, 0x46, 0x18, 0x73, 0xaf, 0x48, 0x5f, 0xb3}, // random
+ []byte{0xb0, 0x93, 0x50, 0x88, 0xf9, 0x92, 0x44, 0x6a}},
+ {
+ []byte{0xe6, 0xf4, 0xf2, 0xdb, 0x31, 0x42, 0x53, 0x01}, // random
+ []byte{0xff, 0x3d, 0x25, 0x50, 0x12, 0xe3, 0x4a, 0xc5}, // random
+ []byte{0x86, 0x08, 0xd3, 0xd1, 0x6c, 0x2f, 0xd2, 0x55}},
+ {
+ []byte{0x69, 0xc1, 0x9d, 0xc1, 0x15, 0xc5, 0xfb, 0x2b}, // random
+ []byte{0x1a, 0x22, 0x5c, 0xaf, 0x1f, 0x1d, 0xa3, 0xf9}, // random
+ []byte{0x64, 0xba, 0x31, 0x67, 0x56, 0x91, 0x1e, 0xa7}},
+ {
+ []byte{0x6e, 0x5e, 0xe2, 0x47, 0xc4, 0xbf, 0xf6, 0x51}, // random
+ []byte{0x11, 0xc9, 0x57, 0xff, 0x66, 0x89, 0x0e, 0xf0}, // random
+ []byte{0x94, 0xc5, 0x35, 0xb2, 0xc5, 0x8b, 0x39, 0x72}},
+}
+
+var weakKeyTests = []CryptTest{
+ {
+ []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ []byte{0x55, 0x74, 0xc0, 0xbd, 0x7c, 0xdf, 0xf7, 0x39}, // random
+ nil},
+ {
+ []byte{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe},
+ []byte{0xe8, 0xe1, 0xa7, 0xc1, 0xde, 0x11, 0x89, 0xaa}, // random
+ nil},
+ {
+ []byte{0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1},
+ []byte{0x50, 0x6a, 0x4b, 0x94, 0x3b, 0xed, 0x7d, 0xdc}, // random
+ nil},
+ {
+ []byte{0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e},
+ []byte{0x88, 0x81, 0x56, 0x38, 0xec, 0x3b, 0x1c, 0x97}, // random
+ nil},
+ {
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x17, 0xa0, 0x83, 0x62, 0x32, 0xfe, 0x9a, 0x0b}, // random
+ nil},
+ {
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0xca, 0x8f, 0xca, 0x1f, 0x50, 0xc5, 0x7b, 0x49}, // random
+ nil},
+ {
+ []byte{0xe1, 0xe1, 0xe1, 0xe1, 0xf0, 0xf0, 0xf0, 0xf0},
+ []byte{0xb1, 0xea, 0xad, 0x7d, 0xe7, 0xc3, 0x7a, 0x43}, // random
+ nil},
+ {
+ []byte{0x1e, 0x1e, 0x1e, 0x1e, 0x0f, 0x0f, 0x0f, 0x0f},
+ []byte{0xae, 0x74, 0x7d, 0x6f, 0xef, 0x16, 0xbb, 0x81}, // random
+ nil},
+}
+
+var semiWeakKeyTests = []CryptTest{
+ // key and out contain the semi-weak key pair
+ {
+ []byte{0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e},
+ []byte{0x12, 0xfa, 0x31, 0x16, 0xf9, 0xc5, 0x0a, 0xe4}, // random
+ []byte{0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01}},
+ {
+ []byte{0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1},
+ []byte{0xb0, 0x4c, 0x7a, 0xee, 0xd2, 0xe5, 0x4d, 0xb7}, // random
+ []byte{0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01}},
+ {
+ []byte{0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe},
+ []byte{0xa4, 0x81, 0xcd, 0xb1, 0x64, 0x6f, 0xd3, 0xbc}, // random
+ []byte{0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01}},
+ {
+ []byte{0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1},
+ []byte{0xee, 0x27, 0xdd, 0x88, 0x4c, 0x22, 0xcd, 0xce}, // random
+ []byte{0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e}},
+ {
+ []byte{0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe},
+ []byte{0x19, 0x3d, 0xcf, 0x97, 0x70, 0xfb, 0xab, 0xe1}, // random
+ []byte{0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e}},
+ {
+ []byte{0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe},
+ []byte{0x7c, 0x82, 0x69, 0xe4, 0x1e, 0x86, 0x99, 0xd7}, // random
+ []byte{0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1}},
+}
+
+// some custom tests for TripleDES
+var encryptTripleDESTests = []CryptTest{
+ {
+ []byte{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x92, 0x95, 0xb5, 0x9b, 0xb3, 0x84, 0x73, 0x6e}},
+ {
+ []byte{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0xc1, 0x97, 0xf5, 0x58, 0x74, 0x8a, 0x20, 0xe7}},
+ {
+ []byte{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x3e, 0x68, 0x0a, 0xa7, 0x8b, 0x75, 0xdf, 0x18}},
+ {
+ []byte{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ []byte{0x6d, 0x6a, 0x4a, 0x64, 0x4c, 0x7b, 0x8c, 0x91}},
+ {
+ []byte{ // "abcdefgh12345678ABCDEFGH"
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+ []byte{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, // "00000000"
+ []byte{0xe4, 0x61, 0xb7, 0x59, 0x68, 0x8b, 0xff, 0x66}},
+ {
+ []byte{ // "abcdefgh12345678ABCDEFGH"
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+ []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+ []byte{0xdb, 0xd0, 0x92, 0xde, 0xf8, 0x34, 0xff, 0x58}},
+ {
+ []byte{ // "abcdefgh12345678ABCDEFGH"
+ 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+ []byte{0xf0, 0xc5, 0x82, 0x22, 0xd3, 0xe6, 0x12, 0xd2}, // random
+ []byte{0xba, 0xe4, 0x41, 0xb1, 0x3c, 0x37, 0x4d, 0xf4}},
+ {
+ []byte{ // random
+ 0xd3, 0x7d, 0x45, 0xee, 0x22, 0xe9, 0xcf, 0x52,
+ 0xf4, 0x65, 0xa2, 0x4f, 0x70, 0xd1, 0x81, 0x8a,
+ 0x3d, 0xbe, 0x2f, 0x39, 0xc7, 0x71, 0xd2, 0xe9},
+ []byte{0x49, 0x53, 0xc3, 0xe9, 0x78, 0xdf, 0x9f, 0xaf}, // random
+ []byte{0x53, 0x40, 0x51, 0x24, 0xd8, 0x3c, 0xf9, 0x88}},
+ {
+ []byte{ // random
+ 0xcb, 0x10, 0x7d, 0xda, 0x7e, 0x96, 0x57, 0x0a,
+ 0xe8, 0xeb, 0xe8, 0x07, 0x8e, 0x87, 0xd3, 0x57,
+ 0xb2, 0x61, 0x12, 0xb8, 0x2a, 0x90, 0xb7, 0x2f},
+ []byte{0xa3, 0xc2, 0x60, 0xb1, 0x0b, 0xb7, 0x28, 0x6e}, // random
+ []byte{0x56, 0x73, 0x7d, 0xfb, 0xb5, 0xa1, 0xc3, 0xde}},
+}
+
+// NIST Special Publication 800-20, Appendix A
+// Key for use with Table A.1 tests
+var tableA1Key = []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+}
+
+// Table A.1 Resulting Ciphertext from the Variable Plaintext Known Answer Test
+var tableA1Tests = []CryptTest{
+ {nil, // 0
+ []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x95, 0xf8, 0xa5, 0xe5, 0xdd, 0x31, 0xd9, 0x00}},
+ {nil, // 1
+ []byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xdd, 0x7f, 0x12, 0x1c, 0xa5, 0x01, 0x56, 0x19}},
+ {nil, // 2
+ []byte{0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x2e, 0x86, 0x53, 0x10, 0x4f, 0x38, 0x34, 0xea}},
+ {nil, // 3
+ []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x4b, 0xd3, 0x88, 0xff, 0x6c, 0xd8, 0x1d, 0x4f}},
+ {nil, // 4
+ []byte{0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x20, 0xb9, 0xe7, 0x67, 0xb2, 0xfb, 0x14, 0x56}},
+ {nil, // 5
+ []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x55, 0x57, 0x93, 0x80, 0xd7, 0x71, 0x38, 0xef}},
+ {nil, // 6
+ []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x6c, 0xc5, 0xde, 0xfa, 0xaf, 0x04, 0x51, 0x2f}},
+ {nil, // 7
+ []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x0d, 0x9f, 0x27, 0x9b, 0xa5, 0xd8, 0x72, 0x60}},
+ {nil, // 8
+ []byte{0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xd9, 0x03, 0x1b, 0x02, 0x71, 0xbd, 0x5a, 0x0a}},
+ {nil, // 9
+ []byte{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x42, 0x42, 0x50, 0xb3, 0x7c, 0x3d, 0xd9, 0x51}},
+ {nil, // 10
+ []byte{0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xb8, 0x06, 0x1b, 0x7e, 0xcd, 0x9a, 0x21, 0xe5}},
+ {nil, // 11
+ []byte{0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xf1, 0x5d, 0x0f, 0x28, 0x6b, 0x65, 0xbd, 0x28}},
+ {nil, // 12
+ []byte{0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xad, 0xd0, 0xcc, 0x8d, 0x6e, 0x5d, 0xeb, 0xa1}},
+ {nil, // 13
+ []byte{0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xe6, 0xd5, 0xf8, 0x27, 0x52, 0xad, 0x63, 0xd1}},
+ {nil, // 14
+ []byte{0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xec, 0xbf, 0xe3, 0xbd, 0x3f, 0x59, 0x1a, 0x5e}},
+ {nil, // 15
+ []byte{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xf3, 0x56, 0x83, 0x43, 0x79, 0xd1, 0x65, 0xcd}},
+ {nil, // 16
+ []byte{0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x2b, 0x9f, 0x98, 0x2f, 0x20, 0x03, 0x7f, 0xa9}},
+ {nil, // 17
+ []byte{0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x88, 0x9d, 0xe0, 0x68, 0xa1, 0x6f, 0x0b, 0xe6}},
+ {nil, // 18
+ []byte{0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xe1, 0x9e, 0x27, 0x5d, 0x84, 0x6a, 0x12, 0x98}},
+ {nil, // 19
+ []byte{0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x32, 0x9a, 0x8e, 0xd5, 0x23, 0xd7, 0x1a, 0xec}},
+ {nil, // 20
+ []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xe7, 0xfc, 0xe2, 0x25, 0x57, 0xd2, 0x3c, 0x97}},
+ {nil, // 21
+ []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x12, 0xa9, 0xf5, 0x81, 0x7f, 0xf2, 0xd6, 0x5d}},
+ {nil, // 22
+ []byte{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xa4, 0x84, 0xc3, 0xad, 0x38, 0xdc, 0x9c, 0x19}},
+ {nil, // 23
+ []byte{0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xfb, 0xe0, 0x0a, 0x8a, 0x1e, 0xf8, 0xad, 0x72}},
+ {nil, // 24
+ []byte{0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x75, 0x0d, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63}},
+ {nil, // 25
+ []byte{0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x64, 0xfe, 0xed, 0x9c, 0x72, 0x4c, 0x2f, 0xaf}},
+ {nil, // 26
+ []byte{0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xf0, 0x2b, 0x26, 0x3b, 0x32, 0x8e, 0x2b, 0x60}},
+ {nil, // 27
+ []byte{0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
+ []byte{0x9d, 0x64, 0x55, 0x5a, 0x9a, 0x10, 0xb8, 0x52}},
+ {nil, // 28
+ []byte{0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xd1, 0x06, 0xff, 0x0b, 0xed, 0x52, 0x55, 0xd7}},
+ {nil, // 29
+ []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xe1, 0x65, 0x2c, 0x6b, 0x13, 0x8c, 0x64, 0xa5}},
+ {nil, // 30
+ []byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xe4, 0x28, 0x58, 0x11, 0x86, 0xec, 0x8f, 0x46}},
+ {nil, // 31
+ []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
+ []byte{0xae, 0xb5, 0xf5, 0xed, 0xe2, 0x2d, 0x1a, 0x36}},
+ {nil, // 32
+ []byte{0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00},
+ []byte{0xe9, 0x43, 0xd7, 0x56, 0x8a, 0xec, 0x0c, 0x5c}},
+ {nil, // 33
+ []byte{0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00},
+ []byte{0xdf, 0x98, 0xc8, 0x27, 0x6f, 0x54, 0xb0, 0x4b}},
+ {nil, // 34
+ []byte{0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00},
+ []byte{0xb1, 0x60, 0xe4, 0x68, 0x0f, 0x6c, 0x69, 0x6f}},
+ {nil, // 35
+ []byte{0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},
+ []byte{0xfa, 0x07, 0x52, 0xb0, 0x7d, 0x9c, 0x4a, 0xb8}},
+ {nil, // 36
+ []byte{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00},
+ []byte{0xca, 0x3a, 0x2b, 0x03, 0x6d, 0xbc, 0x85, 0x02}},
+ {nil, // 37
+ []byte{0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00},
+ []byte{0x5e, 0x09, 0x05, 0x51, 0x7b, 0xb5, 0x9b, 0xcf}},
+ {nil, // 38
+ []byte{0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00},
+ []byte{0x81, 0x4e, 0xeb, 0x3b, 0x91, 0xd9, 0x07, 0x26}},
+ {nil, // 39
+ []byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
+ []byte{0x4d, 0x49, 0xdb, 0x15, 0x32, 0x91, 0x9c, 0x9f}},
+ {nil, // 40
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00},
+ []byte{0x25, 0xeb, 0x5f, 0xc3, 0xf8, 0xcf, 0x06, 0x21}},
+ {nil, // 41
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00},
+ []byte{0xab, 0x6a, 0x20, 0xc0, 0x62, 0x0d, 0x1c, 0x6f}},
+ {nil, // 42
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00},
+ []byte{0x79, 0xe9, 0x0d, 0xbc, 0x98, 0xf9, 0x2c, 0xca}},
+ {nil, // 43
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00},
+ []byte{0x86, 0x6e, 0xce, 0xdd, 0x80, 0x72, 0xbb, 0x0e}},
+ {nil, // 44
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00},
+ []byte{0x8b, 0x54, 0x53, 0x6f, 0x2f, 0x3e, 0x64, 0xa8}},
+ {nil, // 45
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00},
+ []byte{0xea, 0x51, 0xd3, 0x97, 0x55, 0x95, 0xb8, 0x6b}},
+ {nil, // 46
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00},
+ []byte{0xca, 0xff, 0xc6, 0xac, 0x45, 0x42, 0xde, 0x31}},
+ {nil, // 47
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00},
+ []byte{0x8d, 0xd4, 0x5a, 0x2d, 0xdf, 0x90, 0x79, 0x6c}},
+ {nil, // 48
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00},
+ []byte{0x10, 0x29, 0xd5, 0x5e, 0x88, 0x0e, 0xc2, 0xd0}},
+ {nil, // 49
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00},
+ []byte{0x5d, 0x86, 0xcb, 0x23, 0x63, 0x9d, 0xbe, 0xa9}},
+ {nil, // 50
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00},
+ []byte{0x1d, 0x1c, 0xa8, 0x53, 0xae, 0x7c, 0x0c, 0x5f}},
+ {nil, // 51
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00},
+ []byte{0xce, 0x33, 0x23, 0x29, 0x24, 0x8f, 0x32, 0x28}},
+ {nil, // 52
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00},
+ []byte{0x84, 0x05, 0xd1, 0xab, 0xe2, 0x4f, 0xb9, 0x42}},
+ {nil, // 53
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00},
+ []byte{0xe6, 0x43, 0xd7, 0x80, 0x90, 0xca, 0x42, 0x07}},
+ {nil, // 54
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00},
+ []byte{0x48, 0x22, 0x1b, 0x99, 0x37, 0x74, 0x8a, 0x23}},
+ {nil, // 55
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
+ []byte{0xdd, 0x7c, 0x0b, 0xbd, 0x61, 0xfa, 0xfd, 0x54}},
+ {nil, // 56
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80},
+ []byte{0x2f, 0xbc, 0x29, 0x1a, 0x57, 0x0d, 0xb5, 0xc4}},
+ {nil, // 57
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40},
+ []byte{0xe0, 0x7c, 0x30, 0xd7, 0xe4, 0xe2, 0x6e, 0x12}},
+ {nil, // 58
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20},
+ []byte{0x09, 0x53, 0xe2, 0x25, 0x8e, 0x8e, 0x90, 0xa1}},
+ {nil, // 59
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+ []byte{0x5b, 0x71, 0x1b, 0xc4, 0xce, 0xeb, 0xf2, 0xee}},
+ {nil, // 60
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08},
+ []byte{0xcc, 0x08, 0x3f, 0x1e, 0x6d, 0x9e, 0x85, 0xf6}},
+ {nil, // 61
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04},
+ []byte{0xd2, 0xfd, 0x88, 0x67, 0xd5, 0x0d, 0x2d, 0xfe}},
+ {nil, // 62
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+ []byte{0x06, 0xe7, 0xea, 0x22, 0xce, 0x92, 0x70, 0x8f}},
+ {nil, // 63
+ []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ []byte{0x16, 0x6b, 0x40, 0xb4, 0x4a, 0xba, 0x4b, 0xd6}},
+}
+
+// Plaintext for use with Table A.2 tests
+var tableA2Plaintext = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+// Table A.2 Resulting Ciphertext from the Variable Key Known Answer Test
+var tableA2Tests = []CryptTest{
+ { // 0
+ []byte{
+ 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x95, 0xa8, 0xd7, 0x28, 0x13, 0xda, 0xa9, 0x4d}},
+ { // 1
+ []byte{
+ 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x0e, 0xec, 0x14, 0x87, 0xdd, 0x8c, 0x26, 0xd5}},
+ { // 2
+ []byte{
+ 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x7a, 0xd1, 0x6f, 0xfb, 0x79, 0xc4, 0x59, 0x26}},
+ { // 3
+ []byte{
+ 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xd3, 0x74, 0x62, 0x94, 0xca, 0x6a, 0x6c, 0xf3}},
+ { // 4
+ []byte{
+ 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x80, 0x9f, 0x5f, 0x87, 0x3c, 0x1f, 0xd7, 0x61}},
+ { // 5
+ []byte{
+ 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xc0, 0x2f, 0xaf, 0xfe, 0xc9, 0x89, 0xd1, 0xfc}},
+ { // 6
+ []byte{
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x46, 0x15, 0xaa, 0x1d, 0x33, 0xe7, 0x2f, 0x10}},
+ { // 7
+ []byte{
+ 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x20, 0x55, 0x12, 0x33, 0x50, 0xc0, 0x08, 0x58}},
+ { // 8
+ []byte{
+ 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xdf, 0x3b, 0x99, 0xd6, 0x57, 0x73, 0x97, 0xc8}},
+ { // 9
+ []byte{
+ 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x31, 0xfe, 0x17, 0x36, 0x9b, 0x52, 0x88, 0xc9}},
+ { // 10
+ []byte{
+ 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xdf, 0xdd, 0x3c, 0xc6, 0x4d, 0xae, 0x16, 0x42}},
+ { // 11
+ []byte{
+ 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x17, 0x8c, 0x83, 0xce, 0x2b, 0x39, 0x9d, 0x94}},
+ { // 12
+ []byte{
+ 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x50, 0xf6, 0x36, 0x32, 0x4a, 0x9b, 0x7f, 0x80}},
+ { // 13
+ []byte{
+ 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xa8, 0x46, 0x8e, 0xe3, 0xbc, 0x18, 0xf0, 0x6d}},
+ { // 14
+ []byte{
+ 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xa2, 0xdc, 0x9e, 0x92, 0xfd, 0x3c, 0xde, 0x92}},
+ { // 15
+ []byte{
+ 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xca, 0xc0, 0x9f, 0x79, 0x7d, 0x03, 0x12, 0x87}},
+ { // 16
+ []byte{
+ 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x90, 0xba, 0x68, 0x0b, 0x22, 0xae, 0xb5, 0x25}},
+ { // 17
+ []byte{
+ 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xce, 0x7a, 0x24, 0xf3, 0x50, 0xe2, 0x80, 0xb6}},
+ { // 18
+ []byte{
+ 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x88, 0x2b, 0xff, 0x0a, 0xa0, 0x1a, 0x0b, 0x87}},
+ { // 19
+ []byte{
+ 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xc2}},
+ { // 20
+ []byte{
+ 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xc7, 0x15, 0x16, 0xc2, 0x9c, 0x75, 0xd1, 0x70}},
+ { // 21
+ []byte{
+ 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x51, 0x99, 0xc2, 0x9a, 0x52, 0xc9, 0xf0, 0x59}},
+ { // 22
+ []byte{
+ 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xc2, 0x2f, 0x0a, 0x29, 0x4a, 0x71, 0xf2, 0x9f}},
+ { // 23
+ []byte{
+ 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xee, 0x37, 0x14, 0x83, 0x71, 0x4c, 0x02, 0xea}},
+ { // 24
+ []byte{
+ 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xa8, 0x1f, 0xbd, 0x44, 0x8f, 0x9e, 0x52, 0x2f}},
+ { // 25
+ []byte{
+ 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x4f, 0x64, 0x4c, 0x92, 0xe1, 0x92, 0xdf, 0xed}},
+ { // 26
+ []byte{
+ 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x1a, 0xfa, 0x9a, 0x66, 0xa6, 0xdf, 0x92, 0xae}},
+ { // 27
+ []byte{
+ 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xb3, 0xc1, 0xcc, 0x71, 0x5c, 0xb8, 0x79, 0xd8}},
+ { // 28
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x19, 0xd0, 0x32, 0xe6, 0x4a, 0xb0, 0xbd, 0x8b}},
+ { // 29
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x3c, 0xfa, 0xa7, 0xa7, 0xdc, 0x87, 0x20, 0xdc}},
+ { // 30
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0xb7, 0x26, 0x5f, 0x7f, 0x44, 0x7a, 0xc6, 0xf3}},
+ { // 31
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x9d, 0xb7, 0x3b, 0x3c, 0x0d, 0x16, 0x3f, 0x54}},
+ { // 32
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x81, 0x81, 0xb6, 0x5b, 0xab, 0xf4, 0xa9, 0x75}},
+ { // 33
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x93, 0xc9, 0xb6, 0x40, 0x42, 0xea, 0xa2, 0x40}},
+ { // 34
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01},
+ nil,
+ []byte{0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92}},
+ { // 35
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01},
+ nil,
+ []byte{0x86, 0x38, 0x80, 0x9e, 0x87, 0x87, 0x87, 0xa0}},
+ { // 36
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01},
+ nil,
+ []byte{0x41, 0xb9, 0xa7, 0x9a, 0xf7, 0x9a, 0xc2, 0x08}},
+ { // 37
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01},
+ nil,
+ []byte{0x7a, 0x9b, 0xe4, 0x2f, 0x20, 0x09, 0xa8, 0x92}},
+ { // 38
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01},
+ nil,
+ []byte{0x29, 0x03, 0x8d, 0x56, 0xba, 0x6d, 0x27, 0x45}},
+ { // 39
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01},
+ nil,
+ []byte{0x54, 0x95, 0xc6, 0xab, 0xf1, 0xe5, 0xdf, 0x51}},
+ { // 40
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01},
+ nil,
+ []byte{0xae, 0x13, 0xdb, 0xd5, 0x61, 0x48, 0x89, 0x33}},
+ { // 41
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01},
+ nil,
+ []byte{0x02, 0x4d, 0x1f, 0xfa, 0x89, 0x04, 0xe3, 0x89}},
+ { // 42
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01},
+ nil,
+ []byte{0xd1, 0x39, 0x97, 0x12, 0xf9, 0x9b, 0xf0, 0x2e}},
+ { // 43
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01},
+ nil,
+ []byte{0x14, 0xc1, 0xd7, 0xc1, 0xcf, 0xfe, 0xc7, 0x9e}},
+ { // 44
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01},
+ nil,
+ []byte{0x1d, 0xe5, 0x27, 0x9d, 0xae, 0x3b, 0xed, 0x6f}},
+ { // 45
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01},
+ nil,
+ []byte{0xe9, 0x41, 0xa3, 0x3f, 0x85, 0x50, 0x13, 0x03}},
+ { // 46
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01},
+ nil,
+ []byte{0xda, 0x99, 0xdb, 0xbc, 0x9a, 0x03, 0xf3, 0x79}},
+ { // 47
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01},
+ nil,
+ []byte{0xb7, 0xfc, 0x92, 0xf9, 0x1d, 0x8e, 0x92, 0xe9}},
+ { // 48
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01},
+ nil,
+ []byte{0xae, 0x8e, 0x5c, 0xaa, 0x3c, 0xa0, 0x4e, 0x85}},
+ { // 49
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80},
+ nil,
+ []byte{0x9c, 0xc6, 0x2d, 0xf4, 0x3b, 0x6e, 0xed, 0x74}},
+ { // 50
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40},
+ nil,
+ []byte{0xd8, 0x63, 0xdb, 0xb5, 0xc5, 0x9a, 0x91, 0xa0}},
+ { // 50
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20},
+ nil,
+ []byte{0xa1, 0xab, 0x21, 0x90, 0x54, 0x5b, 0x91, 0xd7}},
+ { // 52
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10},
+ nil,
+ []byte{0x08, 0x75, 0x04, 0x1e, 0x64, 0xc5, 0x70, 0xf7}},
+ { // 53
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08},
+ nil,
+ []byte{0x5a, 0x59, 0x45, 0x28, 0xbe, 0xbe, 0xf1, 0xcc}},
+ { // 54
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04},
+ nil,
+ []byte{0xfc, 0xdb, 0x32, 0x91, 0xde, 0x21, 0xf0, 0xc0}},
+ { // 55
+ []byte{
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02},
+ nil,
+ []byte{0x86, 0x9e, 0xfd, 0x7f, 0x9f, 0x26, 0x5a, 0x09}},
+}
+
+// Plaintext for use with Table A.3 tests
+var tableA3Plaintext = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+// Table A.3 Values To Be Used for the Permutation Operation Known Answer Test
+var tableA3Tests = []CryptTest{
+ { // 0
+ []byte{
+ 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+ 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+ 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+ },
+ nil,
+ []byte{0x88, 0xd5, 0x5e, 0x54, 0xf5, 0x4c, 0x97, 0xb4}},
+ { // 1
+ []byte{
+ 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+ 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+ 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+ },
+ nil,
+ []byte{0x0c, 0x0c, 0xc0, 0x0c, 0x83, 0xea, 0x48, 0xfd}},
+ { // 2
+ []byte{
+ 0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+ 0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+ 0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+ },
+ nil,
+ []byte{0x83, 0xbc, 0x8e, 0xf3, 0xa6, 0x57, 0x01, 0x83}},
+ { // 3
+ []byte{
+ 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+ 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+ 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+ },
+ nil,
+ []byte{0xdf, 0x72, 0x5d, 0xca, 0xd9, 0x4e, 0xa2, 0xe9}},
+ { // 4
+ []byte{
+ 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+ 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+ 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+ },
+ nil,
+ []byte{0xe6, 0x52, 0xb5, 0x3b, 0x55, 0x0b, 0xe8, 0xb0}},
+ { // 5
+ []byte{
+ 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+ 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+ 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+ },
+ nil,
+ []byte{0xaf, 0x52, 0x71, 0x20, 0xc4, 0x85, 0xcb, 0xb0}},
+ { // 6
+ []byte{
+ 0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+ 0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+ 0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+ },
+ nil,
+ []byte{0x0f, 0x04, 0xce, 0x39, 0x3d, 0xb9, 0x26, 0xd5}},
+ { // 7
+ []byte{
+ 0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+ 0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+ 0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+ },
+ nil,
+ []byte{0xc9, 0xf0, 0x0f, 0xfc, 0x74, 0x07, 0x90, 0x67}},
+ { // 8
+ []byte{
+ 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+ 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+ 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+ },
+ nil,
+ []byte{0x7c, 0xfd, 0x82, 0xa5, 0x93, 0x25, 0x2b, 0x4e}},
+ { // 9
+ []byte{
+ 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+ 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+ 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+ },
+ nil,
+ []byte{0xcb, 0x49, 0xa2, 0xf9, 0xe9, 0x13, 0x63, 0xe3}},
+ { // 10
+ []byte{
+ 0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+ 0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+ 0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+ },
+ nil,
+ []byte{0x00, 0xb5, 0x88, 0xbe, 0x70, 0xd2, 0x3f, 0x56}},
+ { // 11
+ []byte{
+ 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+ 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+ 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+ },
+ nil,
+ []byte{0x40, 0x6a, 0x9a, 0x6a, 0xb4, 0x33, 0x99, 0xae}},
+ { // 12
+ []byte{
+ 0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+ 0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+ 0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+ },
+ nil,
+ []byte{0x6c, 0xb7, 0x73, 0x61, 0x1d, 0xca, 0x9a, 0xda}},
+ { // 13
+ []byte{
+ 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+ 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+ 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+ },
+ nil,
+ []byte{0x67, 0xfd, 0x21, 0xc1, 0x7d, 0xbb, 0x5d, 0x70}},
+ { // 14
+ []byte{
+ 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+ 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+ 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+ },
+ nil,
+ []byte{0x95, 0x92, 0xcb, 0x41, 0x10, 0x43, 0x07, 0x87}},
+ { // 15
+ []byte{
+ 0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+ 0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+ 0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+ },
+ nil,
+ []byte{0xa6, 0xb7, 0xff, 0x68, 0xa3, 0x18, 0xdd, 0xd3}},
+ { // 16
+ []byte{
+ 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+ 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+ 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+ },
+ nil,
+ []byte{0x4d, 0x10, 0x21, 0x96, 0xc9, 0x14, 0xca, 0x16}},
+ { // 17
+ []byte{
+ 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+ 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+ 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+ },
+ nil,
+ []byte{0x2d, 0xfa, 0x9f, 0x45, 0x73, 0x59, 0x49, 0x65}},
+ { // 18
+ []byte{
+ 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+ 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+ 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+ },
+ nil,
+ []byte{0xb4, 0x66, 0x04, 0x81, 0x6c, 0x0e, 0x07, 0x74}},
+ { // 19
+ []byte{
+ 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+ 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+ 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+ },
+ nil,
+ []byte{0x6e, 0x7e, 0x62, 0x21, 0xa4, 0xf3, 0x4e, 0x87}},
+ { // 20
+ []byte{
+ 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+ 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+ 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+ },
+ nil,
+ []byte{0xaa, 0x85, 0xe7, 0x46, 0x43, 0x23, 0x31, 0x99}},
+ { // 21
+ []byte{
+ 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+ 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+ 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+ },
+ nil,
+ []byte{0x2e, 0x5a, 0x19, 0xdb, 0x4d, 0x19, 0x62, 0xd6}},
+ { // 22
+ []byte{
+ 0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+ 0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+ 0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+ },
+ nil,
+ []byte{0x23, 0xa8, 0x66, 0xa8, 0x09, 0xd3, 0x08, 0x94}},
+ { // 23
+ []byte{
+ 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+ 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+ 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+ },
+ nil,
+ []byte{0xd8, 0x12, 0xd9, 0x61, 0xf0, 0x17, 0xd3, 0x20}},
+ { // 24
+ []byte{
+ 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+ 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+ 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+ },
+ nil,
+ []byte{0x05, 0x56, 0x05, 0x81, 0x6e, 0x58, 0x60, 0x8f}},
+ { // 25
+ []byte{
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+ },
+ nil,
+ []byte{0xab, 0xd8, 0x8e, 0x8b, 0x1b, 0x77, 0x16, 0xf1}},
+ { // 26
+ []byte{
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+ },
+ nil,
+ []byte{0x53, 0x7a, 0xc9, 0x5b, 0xe6, 0x9d, 0xa1, 0xe1}},
+ { // 27
+ []byte{
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+ 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+ },
+ nil,
+ []byte{0xae, 0xd0, 0xf6, 0xae, 0x3c, 0x25, 0xcd, 0xd8}},
+ { // 28
+ []byte{
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+ },
+ nil,
+ []byte{0xb3, 0xe3, 0x5a, 0x5e, 0xe5, 0x3e, 0x7b, 0x8d}},
+ { // 29
+ []byte{
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+ },
+ nil,
+ []byte{0x61, 0xc7, 0x9c, 0x71, 0x92, 0x1a, 0x2e, 0xf8}},
+ { // 30
+ []byte{
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+ 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+ },
+ nil,
+ []byte{0xe2, 0xf5, 0x72, 0x8f, 0x09, 0x95, 0x01, 0x3c}},
+ { // 31
+ []byte{
+ 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+ 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+ 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+ },
+ nil,
+ []byte{0x1a, 0xea, 0xc3, 0x9a, 0x61, 0xf0, 0xa4, 0x64}},
+}
+
+// Table A.4 Values To Be Used for the Substitution Table Known Answer Test
+var tableA4Tests = []CryptTest{
+ { // 0
+ []byte{
+ 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57,
+ 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57,
+ 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57},
+ []byte{0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42},
+ []byte{0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b}},
+ { // 1
+ []byte{
+ 0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e,
+ 0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e,
+ 0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e},
+ []byte{0x5c, 0xd5, 0x4c, 0xa8, 0x3d, 0xef, 0x57, 0xda},
+ []byte{0x7a, 0x38, 0x9d, 0x10, 0x35, 0x4b, 0xd2, 0x71}},
+ { // 2
+ []byte{
+ 0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86,
+ 0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86,
+ 0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86},
+ []byte{0x02, 0x48, 0xd4, 0x38, 0x06, 0xf6, 0x71, 0x72},
+ []byte{0x86, 0x8e, 0xbb, 0x51, 0xca, 0xb4, 0x59, 0x9a}},
+ { // 3
+ []byte{
+ 0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e,
+ 0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e,
+ 0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e},
+ []byte{0x51, 0x45, 0x4b, 0x58, 0x2d, 0xdf, 0x44, 0x0a},
+ []byte{0x71, 0x78, 0x87, 0x6e, 0x01, 0xf1, 0x9b, 0x2a}},
+ { // 4
+ []byte{
+ 0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6,
+ 0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6,
+ 0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6},
+ []byte{0x42, 0xfd, 0x44, 0x30, 0x59, 0x57, 0x7f, 0xa2},
+ []byte{0xaf, 0x37, 0xfb, 0x42, 0x1f, 0x8c, 0x40, 0x95}},
+ { // 5
+ []byte{
+ 0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce,
+ 0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce,
+ 0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce},
+ []byte{0x05, 0x9b, 0x5e, 0x08, 0x51, 0xcf, 0x14, 0x3a},
+ []byte{0x86, 0xa5, 0x60, 0xf1, 0x0e, 0xc6, 0xd8, 0x5b}},
+ { // 6
+ []byte{
+ 0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6,
+ 0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6,
+ 0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6},
+ []byte{0x07, 0x56, 0xd8, 0xe0, 0x77, 0x47, 0x61, 0xd2},
+ []byte{0x0c, 0xd3, 0xda, 0x02, 0x00, 0x21, 0xdc, 0x09}},
+ { // 7
+ []byte{
+ 0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe,
+ 0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe,
+ 0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe},
+ []byte{0x76, 0x25, 0x14, 0xb8, 0x29, 0xbf, 0x48, 0x6a},
+ []byte{0xea, 0x67, 0x6b, 0x2c, 0xb7, 0xdb, 0x2b, 0x7a}},
+ { // 8
+ []byte{
+ 0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16,
+ 0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16,
+ 0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16},
+ []byte{0x3b, 0xdd, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
+ []byte{0xdf, 0xd6, 0x4a, 0x81, 0x5c, 0xaf, 0x1a, 0x0f}},
+ { // 9
+ []byte{
+ 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+ 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+ 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f},
+ []byte{0x26, 0x95, 0x5f, 0x68, 0x35, 0xaf, 0x60, 0x9a},
+ []byte{0x5c, 0x51, 0x3c, 0x9c, 0x48, 0x86, 0xc0, 0x88}},
+ { // 10
+ []byte{
+ 0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46,
+ 0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46,
+ 0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46},
+ []byte{0x16, 0x4d, 0x5e, 0x40, 0x4f, 0x27, 0x52, 0x32},
+ []byte{0x0a, 0x2a, 0xee, 0xae, 0x3f, 0xf4, 0xab, 0x77}},
+ { // 11
+ []byte{
+ 0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e,
+ 0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e,
+ 0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e},
+ []byte{0x6b, 0x05, 0x6e, 0x18, 0x75, 0x9f, 0x5c, 0xca},
+ []byte{0xef, 0x1b, 0xf0, 0x3e, 0x5d, 0xfa, 0x57, 0x5a}},
+ { // 12
+ []byte{
+ 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+ 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+ 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76},
+ []byte{0x00, 0x4b, 0xd6, 0xef, 0x09, 0x17, 0x60, 0x62},
+ []byte{0x88, 0xbf, 0x0d, 0xb6, 0xd7, 0x0d, 0xee, 0x56}},
+ { // 13
+ []byte{
+ 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07,
+ 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07,
+ 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07},
+ []byte{0x48, 0x0d, 0x39, 0x00, 0x6e, 0xe7, 0x62, 0xf2},
+ []byte{0xa1, 0xf9, 0x91, 0x55, 0x41, 0x02, 0x0b, 0x56}},
+ { // 14
+ []byte{
+ 0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f,
+ 0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f,
+ 0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f},
+ []byte{0x43, 0x75, 0x40, 0xc8, 0x69, 0x8f, 0x3c, 0xfa},
+ []byte{0x6f, 0xbf, 0x1c, 0xaf, 0xcf, 0xfd, 0x05, 0x56}},
+ { // 15
+ []byte{
+ 0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7,
+ 0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7,
+ 0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7},
+ []byte{0x07, 0x2d, 0x43, 0xa0, 0x77, 0x07, 0x52, 0x92},
+ []byte{0x2f, 0x22, 0xe4, 0x9b, 0xab, 0x7c, 0xa1, 0xac}},
+ { // 16
+ []byte{
+ 0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf,
+ 0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf,
+ 0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf},
+ []byte{0x02, 0xfe, 0x55, 0x77, 0x81, 0x17, 0xf1, 0x2a},
+ []byte{0x5a, 0x6b, 0x61, 0x2c, 0xc2, 0x6c, 0xce, 0x4a}},
+ { // 17
+ []byte{
+ 0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6,
+ 0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6,
+ 0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6},
+ []byte{0x1d, 0x9d, 0x5c, 0x50, 0x18, 0xf7, 0x28, 0xc2},
+ []byte{0x5f, 0x4c, 0x03, 0x8e, 0xd1, 0x2b, 0x2e, 0x41}},
+ { // 18
+ []byte{
+ 0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef,
+ 0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef,
+ 0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef},
+ []byte{0x30, 0x55, 0x32, 0x28, 0x6d, 0x6f, 0x29, 0x5a},
+ []byte{0x63, 0xfa, 0xc0, 0xd0, 0x34, 0xd9, 0xf7, 0x93}},
+}
+
+// Use the known weak keys to test DES implementation
+func TestWeakKeys(t *testing.T) {
+ for i, tt := range weakKeyTests {
+ var encrypt = func(in []byte) (out []byte) {
+ c, _ := NewCipher(tt.key)
+ out = make([]byte, len(in))
+ encryptBlock(c.subkeys[:], out, in)
+ return
+ }
+
+ // Encrypting twice with a DES weak
+ // key should reproduce the original input
+ result := encrypt(tt.in)
+ result = encrypt(result)
+
+ if !bytes.Equal(result, tt.in) {
+ t.Errorf("#%d: result: %x want: %x", i, result, tt.in)
+ }
+ }
+}
+
+// Use the known semi-weak key pairs to test DES implementation
+func TestSemiWeakKeyPairs(t *testing.T) {
+ for i, tt := range semiWeakKeyTests {
+ var encrypt = func(key, in []byte) (out []byte) {
+ c, _ := NewCipher(key)
+ out = make([]byte, len(in))
+ encryptBlock(c.subkeys[:], out, in)
+ return
+ }
+
+ // Encrypting with one member of the semi-weak pair
+ // and then encrypting the result with the other member
+ // should reproduce the original input.
+ result := encrypt(tt.key, tt.in)
+ result = encrypt(tt.out, result)
+
+ if !bytes.Equal(result, tt.in) {
+ t.Errorf("#%d: result: %x want: %x", i, result, tt.in)
+ }
+ }
+}
+
+func TestDESEncryptBlock(t *testing.T) {
+ for i, tt := range encryptDESTests {
+ c, _ := NewCipher(tt.key)
+ out := make([]byte, len(tt.in))
+ encryptBlock(c.subkeys[:], out, tt.in)
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+ }
+ }
+}
+
+func TestDESDecryptBlock(t *testing.T) {
+ for i, tt := range encryptDESTests {
+ c, _ := NewCipher(tt.key)
+ plain := make([]byte, len(tt.in))
+ decryptBlock(c.subkeys[:], plain, tt.out)
+
+ if !bytes.Equal(plain, tt.in) {
+ t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+ }
+ }
+}
+
+func TestEncryptTripleDES(t *testing.T) {
+ for i, tt := range encryptTripleDESTests {
+ c, _ := NewTripleDESCipher(tt.key)
+ out := make([]byte, len(tt.in))
+ c.Encrypt(out, tt.in)
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+ }
+ }
+}
+
+func TestDecryptTripleDES(t *testing.T) {
+ for i, tt := range encryptTripleDESTests {
+ c, _ := NewTripleDESCipher(tt.key)
+
+ plain := make([]byte, len(tt.in))
+ c.Decrypt(plain, tt.out)
+
+ if !bytes.Equal(plain, tt.in) {
+ t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+func TestVariablePlaintextKnownAnswer(t *testing.T) {
+ for i, tt := range tableA1Tests {
+ c, _ := NewTripleDESCipher(tableA1Key)
+
+ out := make([]byte, len(tt.in))
+ c.Encrypt(out, tt.in)
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+func TestVariableCiphertextKnownAnswer(t *testing.T) {
+ for i, tt := range tableA1Tests {
+ c, _ := NewTripleDESCipher(tableA1Key)
+
+ plain := make([]byte, len(tt.out))
+ c.Decrypt(plain, tt.out)
+
+ if !bytes.Equal(plain, tt.in) {
+ t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+// Encrypting the Table A.1 ciphertext with the
+// 0x01... key produces the original plaintext
+func TestInversePermutationKnownAnswer(t *testing.T) {
+ for i, tt := range tableA1Tests {
+ c, _ := NewTripleDESCipher(tableA1Key)
+
+ plain := make([]byte, len(tt.in))
+ c.Encrypt(plain, tt.out)
+
+ if !bytes.Equal(plain, tt.in) {
+ t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+// Decrypting the Table A.1 plaintext with the
+// 0x01... key produces the corresponding ciphertext
+func TestInitialPermutationKnownAnswer(t *testing.T) {
+ for i, tt := range tableA1Tests {
+ c, _ := NewTripleDESCipher(tableA1Key)
+
+ out := make([]byte, len(tt.in))
+ c.Decrypt(out, tt.in)
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+func TestVariableKeyKnownAnswerEncrypt(t *testing.T) {
+ for i, tt := range tableA2Tests {
+ c, _ := NewTripleDESCipher(tt.key)
+
+ out := make([]byte, len(tableA2Plaintext))
+ c.Encrypt(out, tableA2Plaintext)
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+func TestVariableKeyKnownAnswerDecrypt(t *testing.T) {
+ for i, tt := range tableA2Tests {
+ c, _ := NewTripleDESCipher(tt.key)
+
+ out := make([]byte, len(tt.out))
+ c.Decrypt(out, tt.out)
+
+ if !bytes.Equal(out, tableA2Plaintext) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tableA2Plaintext)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+func TestPermutationOperationKnownAnswerEncrypt(t *testing.T) {
+ for i, tt := range tableA3Tests {
+ c, _ := NewTripleDESCipher(tt.key)
+
+ out := make([]byte, len(tableA3Plaintext))
+ c.Encrypt(out, tableA3Plaintext)
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+func TestPermutationOperationKnownAnswerDecrypt(t *testing.T) {
+ for i, tt := range tableA3Tests {
+ c, _ := NewTripleDESCipher(tt.key)
+
+ out := make([]byte, len(tt.out))
+ c.Decrypt(out, tt.out)
+
+ if !bytes.Equal(out, tableA3Plaintext) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tableA3Plaintext)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+func TestSubstitutionTableKnownAnswerEncrypt(t *testing.T) {
+ for i, tt := range tableA4Tests {
+ c, _ := NewTripleDESCipher(tt.key)
+
+ out := make([]byte, len(tt.in))
+ c.Encrypt(out, tt.in)
+
+ if !bytes.Equal(out, tt.out) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+ }
+ }
+}
+
+// Defined in Pub 800-20
+func TestSubstitutionTableKnownAnswerDecrypt(t *testing.T) {
+ for i, tt := range tableA4Tests {
+ c, _ := NewTripleDESCipher(tt.key)
+
+ out := make([]byte, len(tt.out))
+ c.Decrypt(out, tt.out)
+
+ if !bytes.Equal(out, tt.in) {
+ t.Errorf("#%d: result: %x want: %x", i, out, tt.in)
+ }
+ }
+}
// curve using the procedure given in [NSA] A.2.1.
func randFieldElement(c *elliptic.Curve, rand io.Reader) (k *big.Int, err os.Error) {
b := make([]byte, c.BitSize/8+8)
- _, err = rand.Read(b)
+ _, err = io.ReadFull(rand, b)
if err != nil {
return
}
r.mu.Lock()
defer r.mu.Unlock()
if r.f == nil {
- f, err := os.Open(r.name, os.O_RDONLY, 0)
+ f, err := os.Open(r.name)
if f == nil {
return 0, err
}
for i := 0; i < len(s); i++ {
for s[i] == 0 {
- _, err = rand.Read(s[i : i+1])
+ _, err = io.ReadFull(rand, s[i:i+1])
if err != nil {
return
}
"hash"
"io"
"os"
+ "sync"
)
var bigZero = big.NewInt(0)
type PrivateKey struct {
PublicKey // public part.
D *big.Int // private exponent
- P, Q *big.Int // prime factors of N
+ P, Q, R *big.Int // prime factors of N (R may be nil)
+
+ rwMutex sync.RWMutex // protects the following
+ dP, dQ, dR *big.Int // D mod (P-1) (or mod Q-1 etc)
+ qInv *big.Int // q^-1 mod p
+ pq *big.Int // P*Q
+ tr *big.Int // pq·tr ≡ 1 mod r
}
// Validate performs basic sanity checks on the key.
// It returns nil if the key is valid, or else an os.Error describing a problem.
-func (priv PrivateKey) Validate() os.Error {
- // Check that p and q are prime. Note that this is just a sanity
- // check. Since the random witnesses chosen by ProbablyPrime are
+func (priv *PrivateKey) Validate() os.Error {
+ // Check that p, q and, maybe, r are prime. Note that this is just a
+ // sanity check. Since the random witnesses chosen by ProbablyPrime are
// deterministic, given the candidate number, it's easy for an attack
// to generate composites that pass this test.
if !big.ProbablyPrime(priv.P, 20) {
if !big.ProbablyPrime(priv.Q, 20) {
return os.ErrorString("Q is composite")
}
+ if priv.R != nil && !big.ProbablyPrime(priv.R, 20) {
+ return os.ErrorString("R is composite")
+ }
- // Check that p*q == n.
+ // Check that p*q*r == n.
modulus := new(big.Int).Mul(priv.P, priv.Q)
+ if priv.R != nil {
+ modulus.Mul(modulus, priv.R)
+ }
if modulus.Cmp(priv.N) != 0 {
return os.ErrorString("invalid modulus")
}
- // Check that e and totient(p, q) are coprime.
+ // Check that e and totient(p, q, r) are coprime.
pminus1 := new(big.Int).Sub(priv.P, bigOne)
qminus1 := new(big.Int).Sub(priv.Q, bigOne)
totient := new(big.Int).Mul(pminus1, qminus1)
+ if priv.R != nil {
+ rminus1 := new(big.Int).Sub(priv.R, bigOne)
+ totient.Mul(totient, rminus1)
+ }
e := big.NewInt(int64(priv.E))
gcd := new(big.Int)
x := new(big.Int)
if gcd.Cmp(bigOne) != 0 {
return os.ErrorString("invalid public exponent E")
}
- // Check that de ≡ 1 (mod totient(p, q))
+ // Check that de ≡ 1 (mod totient(p, q, r))
de := new(big.Int).Mul(priv.D, e)
de.Mod(de, totient)
if de.Cmp(bigOne) != 0 {
return nil
}
-// GenerateKeyPair generates an RSA keypair of the given bit size.
+// GenerateKey generates an RSA keypair of the given bit size.
func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
priv = new(PrivateKey)
// Smaller public exponents lead to faster public key
return
}
+// Generate3PrimeKey generates a 3-prime RSA keypair of the given bit size, as
+// suggested in [1]. Although the public keys are compatible (actually,
+// indistinguishable) from the 2-prime case, the private keys are not. Thus it
+// may not be possible to export 3-prime private keys in certain formats or to
+// subsequently import them into other code.
+//
+// Table 1 in [2] suggests that size should be >= 1024 when using 3 primes.
+//
+// [1] US patent 4405829 (1972, expired)
+// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
+func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
+ priv = new(PrivateKey)
+ priv.E = 3
+
+ pminus1 := new(big.Int)
+ qminus1 := new(big.Int)
+ rminus1 := new(big.Int)
+ totient := new(big.Int)
+
+ for {
+ p, err := randomPrime(rand, bits/3)
+ if err != nil {
+ return nil, err
+ }
+
+ todo := bits - p.BitLen()
+ q, err := randomPrime(rand, todo/2)
+ if err != nil {
+ return nil, err
+ }
+
+ todo -= q.BitLen()
+ r, err := randomPrime(rand, todo)
+ if err != nil {
+ return nil, err
+ }
+
+ if p.Cmp(q) == 0 ||
+ q.Cmp(r) == 0 ||
+ r.Cmp(p) == 0 {
+ continue
+ }
+
+ n := new(big.Int).Mul(p, q)
+ n.Mul(n, r)
+ pminus1.Sub(p, bigOne)
+ qminus1.Sub(q, bigOne)
+ rminus1.Sub(r, bigOne)
+ totient.Mul(pminus1, qminus1)
+ totient.Mul(totient, rminus1)
+
+ g := new(big.Int)
+ priv.D = new(big.Int)
+ y := new(big.Int)
+ e := big.NewInt(int64(priv.E))
+ big.GcdInt(g, priv.D, y, e, totient)
+
+ if g.Cmp(bigOne) == 0 {
+ priv.D.Add(priv.D, totient)
+ priv.P = p
+ priv.Q = q
+ priv.R = r
+ priv.N = n
+
+ break
+ }
+ }
+
+ return
+}
+
// incCounter increments a four byte, big-endian counter.
func incCounter(c *[4]byte) {
if c[3]++; c[3] != 0 {
return x, true
}
+// precompute performs some calculations that speed up private key operations
+// in the future.
+func (priv *PrivateKey) precompute() {
+ priv.dP = new(big.Int).Sub(priv.P, bigOne)
+ priv.dP.Mod(priv.D, priv.dP)
+
+ priv.dQ = new(big.Int).Sub(priv.Q, bigOne)
+ priv.dQ.Mod(priv.D, priv.dQ)
+
+ priv.qInv = new(big.Int).ModInverse(priv.Q, priv.P)
+
+ if priv.R != nil {
+ priv.dR = new(big.Int).Sub(priv.R, bigOne)
+ priv.dR.Mod(priv.D, priv.dR)
+
+ priv.pq = new(big.Int).Mul(priv.P, priv.Q)
+ priv.tr = new(big.Int).ModInverse(priv.pq, priv.R)
+ }
+}
+
// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
// random source is given, RSA blinding is used.
func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.Error) {
c.Mod(c, priv.N)
}
- m = new(big.Int).Exp(c, priv.D, priv.N)
+ priv.rwMutex.RLock()
+
+ if priv.dP == nil && priv.P != nil {
+ priv.rwMutex.RUnlock()
+ priv.rwMutex.Lock()
+ if priv.dP == nil && priv.P != nil {
+ priv.precompute()
+ }
+ priv.rwMutex.Unlock()
+ priv.rwMutex.RLock()
+ }
+
+ if priv.dP == nil {
+ m = new(big.Int).Exp(c, priv.D, priv.N)
+ } else {
+ // We have the precalculated values needed for the CRT.
+ m = new(big.Int).Exp(c, priv.dP, priv.P)
+ m2 := new(big.Int).Exp(c, priv.dQ, priv.Q)
+ m.Sub(m, m2)
+ if m.Sign() < 0 {
+ m.Add(m, priv.P)
+ }
+ m.Mul(m, priv.qInv)
+ m.Mod(m, priv.P)
+ m.Mul(m, priv.Q)
+ m.Add(m, m2)
+
+ if priv.dR != nil {
+ // 3-prime CRT.
+ m2.Exp(c, priv.dR, priv.R)
+ m2.Sub(m2, m)
+ m2.Mul(m2, priv.tr)
+ m2.Mod(m2, priv.R)
+ if m2.Sign() < 0 {
+ m2.Add(m2, priv.R)
+ }
+ m2.Mul(m2, priv.pq)
+ m.Add(m, m2)
+ }
+ }
+
+ priv.rwMutex.RUnlock()
if ir != nil {
// Unblind.
)
func TestKeyGeneration(t *testing.T) {
- random := rand.Reader
-
size := 1024
if testing.Short() {
size = 128
}
- priv, err := GenerateKey(random, size)
+ priv, err := GenerateKey(rand.Reader, size)
+ if err != nil {
+ t.Errorf("failed to generate key")
+ }
+ testKeyBasics(t, priv)
+}
+
+func Test3PrimeKeyGeneration(t *testing.T) {
+ if testing.Short() {
+ return
+ }
+
+ size := 768
+ priv, err := Generate3PrimeKey(rand.Reader, size)
if err != nil {
t.Errorf("failed to generate key")
}
+ testKeyBasics(t, priv)
+}
+
+func testKeyBasics(t *testing.T, priv *PrivateKey) {
+ if err := priv.Validate(); err != nil {
+ t.Errorf("Validate() failed: %s", err)
+ }
+
pub := &priv.PublicKey
m := big.NewInt(42)
c := encrypt(new(big.Int), pub, m)
m2, err := decrypt(nil, priv, c)
if err != nil {
t.Errorf("error while decrypting: %s", err)
+ return
}
if m.Cmp(m2) != 0 {
- t.Errorf("got:%v, want:%v (%s)", m2, m, priv)
+ t.Errorf("got:%v, want:%v (%+v)", m2, m, priv)
}
- m3, err := decrypt(random, priv, c)
+ m3, err := decrypt(rand.Reader, priv, c)
if err != nil {
t.Errorf("error while decrypting (blind): %s", err)
}
}
}
+func fromBase10(base10 string) *big.Int {
+ i := new(big.Int)
+ i.SetString(base10, 10)
+ return i
+}
+
+func BenchmarkRSA2048Decrypt(b *testing.B) {
+ b.StopTimer()
+ priv := &PrivateKey{
+ PublicKey: PublicKey{
+ N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"),
+ E: 3,
+ },
+ D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"),
+ P: fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
+ Q: fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+ }
+ priv.precompute()
+
+ c := fromBase10("1000")
+
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ decrypt(nil, priv, c)
+ }
+}
+
+func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
+ b.StopTimer()
+ priv := &PrivateKey{
+ PublicKey: PublicKey{
+ N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
+ E: 3,
+ },
+ D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
+ P: fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+ Q: fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+ R: fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+ }
+ priv.precompute()
+
+ c := fromBase10("1000")
+
+ b.StartTimer()
+
+ for i := 0; i < b.N; i++ {
+ decrypt(nil, priv, c)
+ }
+}
+
type testEncryptOAEPMessage struct {
in []byte
seed []byte
for i, test := range testEncryptOAEPData {
n.SetString(test.modulus, 16)
d.SetString(test.d, 16)
- private := PrivateKey{PublicKey{n, test.e}, d, nil, nil}
+ private := new(PrivateKey)
+ private.PublicKey = PublicKey{n, test.e}
+ private.D = d
for j, message := range test.msgs {
- out, err := DecryptOAEP(sha1, nil, &private, message.out, nil)
+ out, err := DecryptOAEP(sha1, nil, private, message.out, nil)
if err != nil {
t.Errorf("#%d,%d error: %s", i, j, err)
} else if bytes.Compare(out, message.in) != 0 {
}
// Decrypt with blinding.
- out, err = DecryptOAEP(sha1, random, &private, message.out, nil)
+ out, err = DecryptOAEP(sha1, random, private, message.out, nil)
if err != nil {
t.Errorf("#%d,%d (blind) error: %s", i, j, err)
} else if bytes.Compare(out, message.in) != 0 {
return
}
- certOut, err := os.Open("cert.pem", os.O_WRONLY|os.O_CREAT, 0644)
+ certOut, err := os.Create("cert.pem")
if err != nil {
log.Fatalf("failed to open cert.pem for writing: %s", err)
return
certOut.Close()
log.Print("written cert.pem\n")
- keyOut, err := os.Open("key.pem", os.O_WRONLY|os.O_CREAT, 0600)
+ keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0600)
if err != nil {
log.Print("failed to open key.pem for writing:", err)
return
if err != nil {
return
}
+ keyPEMBlock, err := ioutil.ReadFile(keyFile)
+ if err != nil {
+ return
+ }
+ return X509KeyPair(certPEMBlock, keyPEMBlock)
+}
+// X509KeyPair parses a public/private key pair from a pair of
+// PEM encoded data.
+func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err os.Error) {
var certDERBlock *pem.Block
for {
certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
return
}
- keyPEMBlock, err := ioutil.ReadFile(keyFile)
- if err != nil {
- return
- }
-
keyDERBlock, _ := pem.Decode(keyPEMBlock)
if keyDERBlock == nil {
err = os.ErrorString("crypto/tls: failed to parse key PEM data")
return
}
- key = &rsa.PrivateKey{
- PublicKey: rsa.PublicKey{
- E: priv.E,
- N: new(big.Int).SetBytes(priv.N.Bytes),
- },
- D: new(big.Int).SetBytes(priv.D.Bytes),
- P: new(big.Int).SetBytes(priv.P.Bytes),
- Q: new(big.Int).SetBytes(priv.Q.Bytes),
+ key = new(rsa.PrivateKey)
+ key.PublicKey = rsa.PublicKey{
+ E: priv.E,
+ N: new(big.Int).SetBytes(priv.N.Bytes),
}
+ key.D = new(big.Int).SetBytes(priv.D.Bytes)
+ key.P = new(big.Int).SetBytes(priv.P.Bytes)
+ key.Q = new(big.Int).SetBytes(priv.Q.Bytes)
+
err = key.Validate()
if err != nil {
return nil, err
}
+
return
}
"crypto/rsa"
"encoding/hex"
"encoding/pem"
- "reflect"
"testing"
"time"
)
if err != nil {
t.Errorf("Failed to parse private key: %s", err)
}
- if !reflect.DeepEqual(priv, rsaPrivateKey) {
+ if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
+ priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
+ priv.D.Cmp(rsaPrivateKey.D) != 0 ||
+ priv.P.Cmp(rsaPrivateKey.P) != 0 ||
+ priv.Q.Cmp(rsaPrivateKey.Q) != 0 {
t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
}
}
// Open opens the named file using os.Open and prepares it for use as an ELF binary.
func Open(name string) (*File, os.Error) {
- f, err := os.Open(name, os.O_RDONLY, 0)
+ f, err := os.Open(name)
if err != nil {
return nil, err
}
switch f.Class {
case ELFCLASS32:
hdr := new(Header32)
- sr.Seek(0, 0)
+ sr.Seek(0, os.SEEK_SET)
if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
return nil, err
}
shstrndx = int(hdr.Shstrndx)
case ELFCLASS64:
hdr := new(Header64)
- sr.Seek(0, 0)
+ sr.Seek(0, os.SEEK_SET)
if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
return nil, err
}
names := make([]uint32, shnum)
for i := 0; i < shnum; i++ {
off := shoff + int64(i)*int64(shentsize)
- sr.Seek(off, 0)
+ sr.Seek(off, os.SEEK_SET)
s := new(Section)
switch f.Class {
case ELFCLASS32:
// Open opens the named file using os.Open and prepares it for use as a Mach-O binary.
func Open(name string) (*File, os.Error) {
- f, err := os.Open(name, os.O_RDONLY, 0)
+ f, err := os.Open(name)
if err != nil {
return nil, err
}
// Open opens the named file using os.Open and prepares it for use as a PE binary.
func Open(name string) (*File, os.Error) {
- f, err := os.Open(name, os.O_RDONLY, 0)
+ f, err := os.Open(name)
if err != nil {
return nil, err
}
} else {
base = int64(0)
}
- sr.Seek(base, 0)
+ sr.Seek(base, os.SEEK_SET)
if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
return nil, err
}
return nil, os.NewError("Invalid PE File Format.")
}
// get symbol string table
- sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), 0)
+ sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
var l uint32
if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
return nil, err
if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols)); err != nil {
return nil, err
}
- sr.Seek(base, 0)
+ sr.Seek(base, os.SEEK_SET)
binary.Read(sr, binary.LittleEndian, &f.FileHeader)
- sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), 1) //Skip OptionalHeader
+ sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader
f.Sections = make([]*Section, f.FileHeader.NumberOfSections)
for i := 0; i < int(f.FileHeader.NumberOfSections); i++ {
sh := new(SectionHeader32)
// attachAllThreads attaches to all threads in a process.
func (p *process) attachAllThreads() os.Error {
taskPath := "/proc/" + strconv.Itoa(p.pid) + "/task"
- taskDir, err := os.Open(taskPath, os.O_RDONLY, 0)
+ taskDir, err := os.Open(taskPath)
if err != nil {
return err
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// The exec package runs external commands.
+// The exec package runs external commands. It wraps os.StartProcess
+// to make it easier to remap stdin and stdout, connect I/O with pipes,
+// and do other adjustments.
package exec
+// BUG(r): This package should be made even easier to use or merged into os.
+
import (
"os"
"strconv"
if fd == 0 {
rw = os.O_RDONLY
}
- f, err := os.Open(os.DevNull, rw, 0)
+ f, err := os.OpenFile(os.DevNull, rw, 0)
return f, nil, err
case PassThrough:
switch fd {
}
fn = home + "/.Xauthority"
}
- r, err := os.Open(fn, os.O_RDONLY, 0444)
+ r, err := os.Open(fn)
if err != nil {
return
}
}
// Get symbols
- f, err := os.Open(fname, os.O_RDONLY, 0)
+ f, err := os.Open(fname)
if err != nil {
tproc.Detach()
return err
{"%5s", "abc", " abc"},
{"%2s", "\u263a", " \u263a"},
{"%-5s", "abc", "abc "},
+ {"%-8q", "abc", `"abc" `},
{"%05s", "abc", "00abc"},
+ {"%08q", "abc", `000"abc"`},
+ {"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
+ {"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
+ {"%.5s", "日本語日本語", "日本語日本"},
+ {"%.5s", []byte("日本語日本語"), "日本語日本"},
+ {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
+ {"%.3q", "日本語日本語", `"\u65e5\u672c\u8a9e"`},
+ {"%.3q", []byte("日本語日本語"), `"\u65e5\u672c\u8a9e"`},
+ {"%10.1q", "日本語日本語", ` "\u65e5"`},
// integers
{"%d", 12345, "12345"},
f.pad(buf[i:])
}
-// fmt_s formats a string.
-func (f *fmt) fmt_s(s string) {
- if f.precPresent {
- if f.prec < len(s) {
- s = s[0:f.prec]
+// truncate truncates the string to the specified precision, if present.
+func (f *fmt) truncate(s string) string {
+ if f.precPresent && f.prec < utf8.RuneCountInString(s) {
+ n := f.prec
+ for i := range s {
+ if n == 0 {
+ s = s[:i]
+ break
+ }
+ n--
}
}
+ return s
+}
+
+// fmt_s formats a string.
+func (f *fmt) fmt_s(s string) {
+ s = f.truncate(s)
f.padString(s)
}
// fmt_q formats a string as a double-quoted, escaped Go string constant.
func (f *fmt) fmt_q(s string) {
+ s = f.truncate(s)
var quoted string
if f.sharp && strconv.CanBackquote(s) {
quoted = "`" + s + "`"
}
func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) {
- v, ok := value.(uintptrGetter)
- if !ok { // reflect.PtrValue is a uintptrGetter, so failure means it's not a pointer at all.
+ var u uintptr
+ switch value.(type) {
+ case *reflect.ChanValue, *reflect.FuncValue, *reflect.MapValue, *reflect.PtrValue, *reflect.SliceValue, *reflect.UnsafePointerValue:
+ u = value.(uintptrGetter).Get()
+ default:
p.badVerb(verb, field)
return
}
- u := v.Get()
if goSyntax {
p.add('(')
p.buf.WriteString(reflect.Typeof(field).String())
if u == 0 {
p.buf.Write(nilBytes)
} else {
- p.fmt0x64(uint64(v.Get()), true)
+ p.fmt0x64(uint64(u), true)
}
p.add(')')
} else {
break
}
p.fmt0x64(uint64(v), true)
- case uintptrGetter:
+ case *reflect.ChanValue, *reflect.FuncValue, *reflect.UnsafePointerValue:
p.fmtPointer(field, value, verb, goSyntax)
default:
p.unknownType(f)
// error are returned.
//
func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool, mode uint) (map[string]*ast.Package, os.Error) {
- fd, err := os.Open(path, os.O_RDONLY, 0)
+ fd, err := os.Open(path)
if err != nil {
return nil, err
}
var endline int
if p.file.Line(p.pos) == line {
- // The comment is on same line as previous token; it
+ // The comment is on same line as the previous token; it
// cannot be a lead comment but may be a line comment.
comment, endline = p.consumeCommentGroup()
if p.file.Line(p.pos) != endline {
}
ident := p.parseIdent()
- typ := p.parseType()
- p.expectSemi() // call before accessing p.linecomment
// Go spec: The scope of a type identifier declared inside a function begins
// at the identifier in the TypeSpec and ends at the end of the innermost
// containing block.
// (Global identifiers are resolved in a separate phase after parsing.)
- spec := &ast.TypeSpec{doc, ident, typ, p.lineComment}
+ spec := &ast.TypeSpec{doc, ident, nil, nil}
p.declare(spec, p.topScope, ast.Typ, ident)
+ spec.Type = p.parseType()
+ p.expectSemi() // call before accessing p.linecomment
+ spec.Comment = p.lineComment
+
return spec
}
// Go spec: The package clause is not a declaration;
// the package name does not appear in any scope.
ident := p.parseIdent()
+ if ident.Name == "_" {
+ p.error(p.pos, "invalid package name _")
+ }
p.expectSemi()
var decls []ast.Decl
}
func readDat(filename string, c chan io.Reader) {
- f, err := os.Open("testdata/webkit/"+filename, os.O_RDONLY, 0600)
+ f, err := os.Open("testdata/webkit/" + filename)
if err != nil {
c <- pipeErr(err)
return
return
}
- f, err := os.Open(name, os.O_RDONLY, 0)
+ f, err := os.Open(name)
if err != nil {
// TODO expose actual error?
NotFound(w, r)
// use contents of index.html for directory, if present
if d.IsDirectory() {
index := name + filepath.FromSlash(indexPage)
- ff, err := os.Open(index, os.O_RDONLY, 0)
+ ff, err := os.Open(index)
if err == nil {
defer ff.Close()
dd, err := ff.Stat()
size := d.Size
code := StatusOK
- // use extension to find content type.
- ext := filepath.Ext(name)
- if ctype := mime.TypeByExtension(ext); ctype != "" {
- w.Header().Set("Content-Type", ctype)
- } else {
- // read first chunk to decide between utf-8 text and binary
- var buf [1024]byte
- n, _ := io.ReadFull(f, buf[:])
- b := buf[:n]
- if isText(b) {
- w.Header().Set("Content-Type", "text-plain; charset=utf-8")
- } else {
- w.Header().Set("Content-Type", "application/octet-stream") // generic binary
+ // If Content-Type isn't set, use the file's extension to find it.
+ if w.Header().Get("Content-Type") == "" {
+ ctype := mime.TypeByExtension(filepath.Ext(name))
+ if ctype == "" {
+ // read a chunk to decide between utf-8 text and binary
+ var buf [1024]byte
+ n, _ := io.ReadFull(f, buf[:])
+ b := buf[:n]
+ if isText(b) {
+ ctype = "text-plain; charset=utf-8"
+ } else {
+ // generic binary
+ ctype = "application/octet-stream"
+ }
+ f.Seek(0, os.SEEK_SET) // rewind to output whole file
}
- f.Seek(0, 0) // rewind to output whole file
+ w.Header().Set("Content-Type", ctype)
}
// handle Content-Range header.
}
if len(ranges) == 1 {
ra := ranges[0]
- if _, err := f.Seek(ra.start, 0); err != nil {
+ if _, err := f.Seek(ra.start, os.SEEK_SET); err != nil {
Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
return
}
}
}
+func TestServeFileContentType(t *testing.T) {
+ const ctype = "icecream/chocolate"
+ override := false
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if override {
+ w.Header().Set("Content-Type", ctype)
+ }
+ ServeFile(w, r, "testdata/file")
+ }))
+ defer ts.Close()
+ get := func(want string) {
+ resp, _, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if h := resp.Header.Get("Content-Type"); h != want {
+ t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
+ }
+ }
+ get("text-plain; charset=utf-8")
+ override = true
+ get(ctype)
+}
+
func getBody(t *testing.T, req Request) (*Response, []byte) {
r, err := DefaultClient.Do(&req)
if err != nil {
package httptest
import (
+ "crypto/rand"
+ "crypto/tls"
"fmt"
"http"
- "os"
"net"
+ "os"
+ "time"
)
// A Server is an HTTP server listening on a system-chosen port on the
type Server struct {
URL string // base URL of form http://ipaddr:port with no trailing slash
Listener net.Listener
+ TLS *tls.Config // nil if not using using TLS
}
// historyListener keeps track of all connections that it's ever
return
}
-// NewServer starts and returns a new Server.
-// The caller should call Close when finished, to shut it down.
-func NewServer(handler http.Handler) *Server {
- ts := new(Server)
+func newLocalListener() net.Listener {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
}
}
+ return l
+}
+
+// NewServer starts and returns a new Server.
+// The caller should call Close when finished, to shut it down.
+func NewServer(handler http.Handler) *Server {
+ ts := new(Server)
+ l := newLocalListener()
ts.Listener = &historyListener{l, make([]net.Conn, 0)}
ts.URL = "http://" + l.Addr().String()
server := &http.Server{Handler: handler}
return ts
}
+// NewTLSServer starts and returns a new Server using TLS.
+// The caller should call Close when finished, to shut it down.
+func NewTLSServer(handler http.Handler) *Server {
+ l := newLocalListener()
+ ts := new(Server)
+
+ cert, err := tls.X509KeyPair(localhostCert, localhostKey)
+ if err != nil {
+ panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
+ }
+
+ ts.TLS = &tls.Config{
+ Rand: rand.Reader,
+ Time: time.Seconds,
+ NextProtos: []string{"http/1.1"},
+ Certificates: []tls.Certificate{cert},
+ }
+ tlsListener := tls.NewListener(l, ts.TLS)
+
+ ts.Listener = &historyListener{tlsListener, make([]net.Conn, 0)}
+ ts.URL = "https://" + l.Addr().String()
+ server := &http.Server{Handler: handler}
+ go server.Serve(ts.Listener)
+ return ts
+}
+
// Close shuts down the server.
func (s *Server) Close() {
s.Listener.Close()
conn.Close()
}
}
+
+// localhostCert is a PEM-encoded TLS cert with SAN DNS names
+// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
+// of ASN.1 time).
+var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIBwTCCASugAwIBAgIBADALBgkqhkiG9w0BAQUwADAeFw0xMTAzMzEyMDI1MDda
+Fw00OTEyMzEyMzU5NTlaMAAwggCdMAsGCSqGSIb3DQEBAQOCAIwAMIIAhwKCAIB6
+oy4iT42G6qk+GGn5VL5JlnJT6ZG5cqaMNFaNGlIxNb6CPUZLKq2sM3gRaimsktIw
+nNAcNwQGHpe1tZo+J/Pl04JTt71Y/TTAxy7OX27aZf1Rpt0SjdZ7vTPnFDPNsHGe
+KBKvPt55l2+YKjkZmV7eRevsVbpkNvNGB+T5d4Ge/wIBA6NPME0wDgYDVR0PAQH/
+BAQDAgCgMA0GA1UdDgQGBAQBAgMEMA8GA1UdIwQIMAaABAECAwQwGwYDVR0RBBQw
+EoIJMTI3LjAuMC4xggVbOjoxXTALBgkqhkiG9w0BAQUDggCBAHC3gbdvc44vs+wD
+g2kONiENnx8WKc0UTGg/TOXS3gaRb+CUIQtHWja65l8rAfclEovjHgZ7gx8brO0W
+JuC6p3MUAKsgOssIrrRIx2rpnfcmFVMzguCmrMNVmKUAalw18Yp0F72xYAIitVQl
+kJrLdIhBajcJRYu/YGltHQRaXuVt
+-----END CERTIFICATE-----
+`)
+
+// localhostKey is the private key for localhostCert.
+var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIBkgIBAQKCAIB6oy4iT42G6qk+GGn5VL5JlnJT6ZG5cqaMNFaNGlIxNb6CPUZL
+Kq2sM3gRaimsktIwnNAcNwQGHpe1tZo+J/Pl04JTt71Y/TTAxy7OX27aZf1Rpt0S
+jdZ7vTPnFDPNsHGeKBKvPt55l2+YKjkZmV7eRevsVbpkNvNGB+T5d4Ge/wIBAwKC
+AIBRwh7Bil5Z8cYpZZv7jdQxDvbim7Z7ocRdeDmzZuF2I9RW04QyHHPIIlALnBvI
+YeF1veASz1gEFGUjzmbUGqKYSbCoTzXoev+F4bmbRxcX9sOmtslqvhMSHRSzA5NH
+aDVI3Hn4wvBVD8gePu8ACWqvPGbCiql11OKCMfjlPn2uuwJAx/24/F5DjXZ6hQQ7
+HxScOxKrpx5WnA9r1wZTltOTZkhRRzuLc21WJeE3M15QUdWi3zZxCKRFoth65HEs
+jy9YHQJAnPueRI44tz79b5QqVbeaOMUr7ZCb1Kp0uo6G+ANPLdlfliAupwij2eIz
+mHRJOWk0jBtXfRft1McH2H51CpXAyw==
+-----END RSA PRIVATE KEY-----
+`)
"Body here\n",
},
+ // Chunked response in response to a HEAD request (the "chunked" should
+ // be ignored, as HEAD responses never have bodies)
+ {
+ "HTTP/1.0 200 OK\r\n" +
+ "Transfer-Encoding: chunked\r\n" +
+ "\r\n",
+
+ Response{
+ Status: "200 OK",
+ StatusCode: 200,
+ Proto: "HTTP/1.0",
+ ProtoMajor: 1,
+ ProtoMinor: 0,
+ RequestMethod: "HEAD",
+ Header: Header{},
+ Close: true,
+ ContentLength: 0,
+ },
+
+ "",
+ },
+
// Status line without a Reason-Phrase, but trailing space.
// (permitted by RFC 2616)
{
t.Errorf("got unexpected body %q", string(body))
}
}
+
+func TestTLSServer(t *testing.T) {
+ ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ fmt.Fprintf(w, "tls=%v", r.TLS != nil)
+ }))
+ defer ts.Close()
+ if !strings.HasPrefix(ts.URL, "https://") {
+ t.Fatalf("expected test TLS server to start with https://, got %q", ts.URL)
+ }
+ res, _, err := Get(ts.URL)
+ if err != nil {
+ t.Error(err)
+ }
+ if res == nil {
+ t.Fatalf("got nil Response")
+ }
+ if res.Body == nil {
+ t.Fatalf("got nil Response.Body")
+ }
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Error(err)
+ }
+ if e, g := "tls=true", string(body); e != g {
+ t.Errorf("expected body %q; got %q", e, g)
+ }
+}
}
// Transfer encoding, content length
- t.TransferEncoding, err = fixTransferEncoding(t.Header)
+ t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header)
if err != nil {
return err
}
func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
// Sanitize transfer encoding
-func fixTransferEncoding(header Header) ([]string, os.Error) {
+func fixTransferEncoding(requestMethod string, header Header) ([]string, os.Error) {
raw, present := header["Transfer-Encoding"]
if !present {
return nil, nil
}
header["Transfer-Encoding"] = nil, false
+
+ // Head responses have no bodies, so the transfer encoding
+ // should be ignored.
+ if requestMethod == "HEAD" {
+ return nil, nil
+ }
+
encodings := strings.Split(raw[0], ",", -1)
te := make([]string, 0, len(encodings))
// TODO: Even though we only support "identity" and "chunked"
// environment variables.
var DefaultTransport RoundTripper = &Transport{}
+// DefaultMaxIdleConnsPerHost is the default value of Transport's
+// MaxIdleConnsPerHost.
+const DefaultMaxIdleConnsPerHost = 2
+
// Transport is an implementation of RoundTripper that supports http,
// https, and http proxies (for either http or https with CONNECT).
// Transport can also cache connections for future re-use.
lk sync.Mutex
idleConn map[string][]*persistConn
- // TODO: tunables on max cached connections (total, per-server), duration
+ // TODO: tunable on global max cached connections
+ // TODO: tunable on timeout on cached connections
// TODO: optional pipelining
IgnoreEnvironment bool // don't look at environment variables for proxy configuration
DisableKeepAlives bool
+
+ // MaxIdleConnsPerHost, if non-zero, controls the maximum idle
+ // (keep-alive) to keep to keep per-host. If zero,
+ // DefaultMaxIdleConnsPerHost is used.
+ MaxIdleConnsPerHost int
}
// RoundTrip implements the RoundTripper interface.
func (t *Transport) putIdleConn(pconn *persistConn) {
t.lk.Lock()
defer t.lk.Unlock()
- if t.DisableKeepAlives {
+ if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
pconn.close()
return
}
return
}
key := pconn.cacheKey
+ max := t.MaxIdleConnsPerHost
+ if max == 0 {
+ max = DefaultMaxIdleConnsPerHost
+ }
+ if len(t.idleConn[key]) >= max {
+ pconn.close()
+ return
+ }
t.idleConn[key] = append(t.idleConn[key], pconn)
}
rc := <-pc.reqch
resp, err := pc.cc.Read(rc.req)
- if err == nil && !rc.req.Close {
- pc.t.putIdleConn(pc)
- }
+
if err == ErrPersistEOF {
// Succeeded, but we can't send any more
// persistent connections on this again. We
// hide this error to upstream callers.
alive = false
err = nil
- } else if err != nil {
+ } else if err != nil || rc.req.Close {
alive = false
}
+
+ hasBody := resp != nil && resp.ContentLength != 0
+ var waitForBodyRead chan bool
+ if alive {
+ if hasBody {
+ waitForBodyRead = make(chan bool)
+ resp.Body.(*bodyEOFSignal).fn = func() {
+ pc.t.putIdleConn(pc)
+ waitForBodyRead <- true
+ }
+ } else {
+ pc.t.putIdleConn(pc)
+ }
+ }
+
rc.ch <- responseAndError{resp, err}
// Wait for the just-returned response body to be fully consumed
// before we race and peek on the underlying bufio reader.
- if alive {
- <-resp.Body.(*bodyEOFSignal).ch
+ if waitForBodyRead != nil {
+ <-waitForBodyRead
}
}
}
// the response body with a bodyEOFSignal-wrapped version.
func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) {
resp, err = ReadResponse(r, requestMethod)
- if err == nil {
- resp.Body = &bodyEOFSignal{resp.Body, make(chan bool, 1), false}
+ if err == nil && resp.ContentLength != 0 {
+ resp.Body = &bodyEOFSignal{resp.Body, nil}
}
return
}
-// bodyEOFSignal wraps a ReadCloser but sends on ch once once
-// the wrapped ReadCloser is fully consumed (including on Close)
+// bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
+// once, right before the final Read() or Close() call returns, but after
+// EOF has been seen.
type bodyEOFSignal struct {
body io.ReadCloser
- ch chan bool
- done bool
+ fn func()
}
func (es *bodyEOFSignal) Read(p []byte) (n int, err os.Error) {
n, err = es.body.Read(p)
- if err == os.EOF && !es.done {
- es.ch <- true
- es.done = true
+ if err == os.EOF && es.fn != nil {
+ es.fn()
+ es.fn = nil
}
return
}
func (es *bodyEOFSignal) Close() (err os.Error) {
err = es.body.Close()
- if err == nil && !es.done {
- es.ch <- true
- es.done = true
+ if err == nil && es.fn != nil {
+ es.fn()
+ es.fn = nil
}
return
}
t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
}
body, err := ioutil.ReadAll(res.Body)
+ defer res.Body.Close()
if err != nil {
t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
}
t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
}
- if _, _, err := c.Get(ts.URL); err != nil {
+ resp, _, err := c.Get(ts.URL)
+ if err != nil {
t.Error(err)
}
+ ioutil.ReadAll(resp.Body)
keys := tr.IdleConnKeysForTesting()
if e, g := 1, len(keys); e != g {
}
if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
- t.Logf("Expected idle cache key %q; got %q", e, keys[0])
+ t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
}
tr.CloseIdleConnections()
}
}
+func TestTransportMaxPerHostIdleConns(t *testing.T) {
+ ch := make(chan string)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ fmt.Fprintf(w, "%s", <-ch)
+ }))
+ defer ts.Close()
+ maxIdleConns := 2
+ tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns}
+ c := &Client{Transport: tr}
+
+ // Start 3 outstanding requests (will hang until we write to
+ // ch)
+ donech := make(chan bool)
+ doReq := func() {
+ resp, _, err := c.Get(ts.URL)
+ if err != nil {
+ t.Error(err)
+ }
+ ioutil.ReadAll(resp.Body)
+ donech <- true
+ }
+ go doReq()
+ go doReq()
+ go doReq()
+
+ if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
+ t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
+ }
+
+ ch <- "res1"
+ <-donech
+ keys := tr.IdleConnKeysForTesting()
+ if e, g := 1, len(keys); e != g {
+ t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
+ }
+ cacheKey := "|http|" + ts.Listener.Addr().String()
+ if keys[0] != cacheKey {
+ t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
+ }
+ if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g {
+ t.Errorf("after first response, expected %d idle conns; got %d", e, g)
+ }
+
+ ch <- "res2"
+ <-donech
+ if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g {
+ t.Errorf("after second response, expected %d idle conns; got %d", e, g)
+ }
+
+ ch <- "res3"
+ <-donech
+ if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g {
+ t.Errorf("after third response, still expected %d idle conns; got %d", e, g)
+ }
+}
+
func TestTransportServerClosingUnexpectedly(t *testing.T) {
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
}
}
+// TestTransportHeadResponses verifies that we deal with Content-Lengths
+// with no bodies properly
+func TestTransportHeadResponses(t *testing.T) {
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.Method != "HEAD" {
+ panic("expected HEAD; got " + r.Method)
+ }
+ w.Header().Set("Content-Length", "123")
+ w.WriteHeader(200)
+ }))
+ defer ts.Close()
+
+ tr := &Transport{DisableKeepAlives: false}
+ c := &Client{Transport: tr}
+ for i := 0; i < 2; i++ {
+ res, err := c.Head(ts.URL)
+ if err != nil {
+ t.Errorf("error on loop %d: %v", i, err)
+ }
+ if e, g := "123", res.Header.Get("Content-Length"); e != g {
+ t.Errorf("loop %d: expected Content-Length header of %q, got %q", e, g)
+ }
+ if e, g := int64(0), res.ContentLength; e != g {
+ t.Errorf("loop %d: expected res.ContentLength of %v, got %v", e, g)
+ }
+ }
+}
+
+// TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
+// on responses to HEAD requests.
+func TestTransportHeadChunkedResponse(t *testing.T) {
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.Method != "HEAD" {
+ panic("expected HEAD; got " + r.Method)
+ }
+ w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
+ w.Header().Set("x-client-ipport", r.RemoteAddr)
+ w.WriteHeader(200)
+ }))
+ defer ts.Close()
+
+ tr := &Transport{DisableKeepAlives: false}
+ c := &Client{Transport: tr}
+
+ res1, err := c.Head(ts.URL)
+ if err != nil {
+ t.Fatalf("request 1 error: %v", err)
+ }
+ res2, err := c.Head(ts.URL)
+ if err != nil {
+ t.Fatalf("request 2 error: %v", err)
+ }
+ if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
+ t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
+ }
+}
+
func TestTransportNilURL(t *testing.T) {
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "Hi")
j++
case shouldEscape(c, mode):
t[j] = '%'
- t[j+1] = "0123456789abcdef"[c>>4]
- t[j+2] = "0123456789abcdef"[c&15]
+ t[j+1] = "0123456789ABCDEF"[c>>4]
+ t[j+2] = "0123456789ABCDEF"[c&15]
j += 3
default:
t[j] = s[i]
},
{
" ?&=#+%!<>#\"{}|\\^[]`☺\t",
- "+%3f%26%3d%23%2b%25!%3c%3e%23%22%7b%7d%7c%5c%5e%5b%5d%60%e2%98%ba%09",
+ "+%3F%26%3D%23%2B%25!%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09",
nil,
},
}
var userinfoTests = []UserinfoTest{
{"user", "password", "user:password"},
{"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
- "foo%3abar:~!%40%23$%25%5e&*()_+%7b%7d%7c%5b%5d%5c-=%60%3a;'%22%3c%3e?,.%2f"},
+ "foo%3Abar:~!%40%23$%25%5E&*()_+%7B%7D%7C%5B%5D%5C-=%60%3A;'%22%3C%3E?,.%2F"},
}
func TestEscapeUserinfo(t *testing.T) {
}
func decode(filename string) (image.Image, string, os.Error) {
- f, err := os.Open(filename, os.O_RDONLY, 0400)
+ f, err := os.Open(filename)
if err != nil {
return nil, "", err
}
}
func readPng(filename string) (image.Image, os.Error) {
- f, err := os.Open(filename, os.O_RDONLY, 0444)
+ f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer piper.Close()
// Read the .sng file.
- sf, err := os.Open("testdata/pngsuite/"+fn+".sng", os.O_RDONLY, 0444)
+ sf, err := os.Open("testdata/pngsuite/" + fn + ".sng")
if err != nil {
t.Error(fn, err)
continue
// ReadFile reads the file named by filename and returns the contents.
func ReadFile(filename string) ([]byte, os.Error) {
- f, err := os.Open(filename, os.O_RDONLY, 0)
+ f, err := os.Open(filename)
if err != nil {
return nil, err
}
// If the file does not exist, WriteFile creates it with permissions perm;
// otherwise WriteFile truncates it before writing.
func WriteFile(filename string, data []byte, perm uint32) os.Error {
- f, err := os.Open(filename, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, perm)
+ f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil {
return err
}
// ReadDir reads the directory named by dirname and returns
// a list of sorted directory entries.
func ReadDir(dirname string) ([]*os.FileInfo, os.Error) {
- f, err := os.Open(dirname, os.O_RDONLY, 0)
+ f, err := os.Open(dirname)
if err != nil {
return nil, err
}
nconflict := 0
for i := 0; i < 10000; i++ {
name := filepath.Join(dir, prefix+nextSuffix())
- f, err = os.Open(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+ f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if pe, ok := err.(*os.PathError); ok && pe.Error == os.EEXIST {
if nconflict++; nconflict > 10 {
rand = reseed()
// order they appear (the order listed here) or the format they present (as
// described in the comments). A colon appears after these items:
// 2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
- Ldate = 1 << iota // the date: 2009/0123
- Ltime // the time: 01:23:23
- Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
- Llongfile // full file name and line number: /a/b/c/d.go:23
- Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
+ Ldate = 1 << iota // the date: 2009/0123
+ Ltime // the time: 01:23:23
+ Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
+ Llongfile // full file name and line number: /a/b/c/d.go:23
+ Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
+ LstdFlags = Ldate | Ltime // initial values for the standard logger
)
// A Logger represents an active logging object that generates lines of
// the Writer's Write method. A Logger can be used simultaneously from
// multiple goroutines; it guarantees to serialize access to the Writer.
type Logger struct {
- mu sync.Mutex // ensures atomic writes
- out io.Writer // destination for output
- prefix string // prefix to write at beginning of each line
- flag int // properties
+ prefix string // prefix to write at beginning of each line
+ flag int // properties
+ mu sync.Mutex // ensures atomic writes; protects the following fields
+ out io.Writer // destination for output
+ buf bytes.Buffer // for accumulating text to write
}
// New creates a new Logger. The out variable sets the
return &Logger{out: out, prefix: prefix, flag: flag}
}
-var std = New(os.Stderr, "", Ldate|Ltime)
+var std = New(os.Stderr, "", LstdFlags)
// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
// Knows the buffer has capacity.
}
}
-func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) {
+func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, file string, line int) {
buf.WriteString(l.prefix)
if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
t := time.SecondsToLocalTime(ns / 1e9)
}
}
if l.flag&(Lshortfile|Llongfile) != 0 {
- _, file, line, ok := runtime.Caller(calldepth)
- if ok {
- if l.flag&Lshortfile != 0 {
- short := file
- for i := len(file) - 1; i > 0; i-- {
- if file[i] == '/' {
- short = file[i+1:]
- break
- }
+ if l.flag&Lshortfile != 0 {
+ short := file
+ for i := len(file) - 1; i > 0; i-- {
+ if file[i] == '/' {
+ short = file[i+1:]
+ break
}
- file = short
}
- } else {
- file = "???"
- line = 0
+ file = short
}
buf.WriteString(file)
buf.WriteByte(':')
// paths it will be 2.
func (l *Logger) Output(calldepth int, s string) os.Error {
now := time.Nanoseconds() // get this early.
- buf := new(bytes.Buffer)
- l.formatHeader(buf, now, calldepth+1)
- buf.WriteString(s)
- if len(s) > 0 && s[len(s)-1] != '\n' {
- buf.WriteByte('\n')
+ // get caller info (if required) before locking - it's expensive.
+ var file string
+ var line int
+ if l.flag&(Lshortfile|Llongfile) != 0 {
+ var ok bool
+ _, file, line, ok = runtime.Caller(calldepth)
+ if !ok {
+ file = "???"
+ line = 0
+ }
}
l.mu.Lock()
defer l.mu.Unlock()
- _, err := l.out.Write(buf.Bytes())
+ l.buf.Reset()
+ l.formatHeader(&l.buf, now, file, line)
+ l.buf.WriteString(s)
+ if len(s) > 0 && s[len(s)-1] != '\n' {
+ l.buf.WriteByte('\n')
+ }
+ _, err := l.out.Write(l.buf.Bytes())
return err
}
panic(s)
}
+// Flags returns the output flags for the logger.
+func (l *Logger) Flags() int {
+ return l.flag
+}
+
+// SetFlags sets the output flags for the logger.
+func (l *Logger) SetFlags(flag int) {
+ l.flag = flag
+}
+
+// Prefix returns the output prefix for the logger.
+func (l *Logger) Prefix() string {
+ return l.prefix
+}
+
+// SetPrefix sets the output prefix for the logger.
+func (l *Logger) SetPrefix(prefix string) {
+ l.prefix = prefix
+}
+
// SetOutput sets the output destination for the standard logger.
func SetOutput(w io.Writer) {
std.out = w
}
+// Flags returns the output flags for the standard logger.
+func Flags() int {
+ return std.Flags()
+}
+
// SetFlags sets the output flags for the standard logger.
func SetFlags(flag int) {
- std.flag = flag
+ std.SetFlags(flag)
+}
+
+// Prefix returns the output prefix for the standard logger.
+func Prefix() string {
+ return std.Prefix()
}
// SetPrefix sets the output prefix for the standard logger.
func SetPrefix(prefix string) {
- std.prefix = prefix
+ std.SetPrefix(prefix)
}
// These functions write to the standard logger.
t.Errorf("log output should match %q is %q", expect, b.String())
}
}
+
+func TestFlagAndPrefixSetting(t *testing.T) {
+ var b bytes.Buffer
+ l := New(&b, "Test:", LstdFlags)
+ f := l.Flags()
+ if f != LstdFlags {
+ t.Errorf("Flags 1: expected %x got %x", LstdFlags, f)
+ }
+ l.SetFlags(f | Lmicroseconds)
+ f = l.Flags()
+ if f != LstdFlags|Lmicroseconds {
+ t.Errorf("Flags 2: expected %x got %x", LstdFlags|Lmicroseconds, f)
+ }
+ p := l.Prefix()
+ if p != "Test:" {
+ t.Errorf(`Prefix: expected "Test:" got %q`, p)
+ }
+ l.SetPrefix("Reality:")
+ p = l.Prefix()
+ if p != "Reality:" {
+ t.Errorf(`Prefix: expected "Reality:" got %q`, p)
+ }
+ // Verify a log message looks right, with our prefix and microseconds present.
+ l.Print("hello")
+ pattern := "^Reality:" + Rdate + " " + Rtime + Rmicroseconds + " hello\n"
+ matched, err := regexp.Match(pattern, b.Bytes())
+ if err != nil {
+ t.Fatalf("pattern %q did not compile: %s", pattern, err)
+ }
+ if !matched {
+ t.Error("message did not match pattern")
+ }
+}
var mimeLock sync.RWMutex
func loadMimeFile(filename string) {
- f, err := os.Open(filename, os.O_RDONLY, 0666)
+ f, err := os.Open(filename)
if err != nil {
return
}
}
}
-// lookupStaticHosts looks up the addresses for the given host from /etc/hosts.
+// lookupStaticHost looks up the addresses for the given host from /etc/hosts.
func lookupStaticHost(host string) []string {
hosts.Lock()
defer hosts.Unlock()
return nil
}
-// rlookupStaticHosts looks up the hosts for the given address from /etc/hosts.
+// lookupStaticAddr looks up the hosts for the given address from /etc/hosts.
func lookupStaticAddr(addr string) []string {
hosts.Lock()
defer hosts.Unlock()
}
func open(name string) (*file, os.Error) {
- fd, err := os.Open(name, os.O_RDONLY, 0)
+ fd, err := os.Open(name)
if err != nil {
return nil, err
}
}
filename := "/etc/services" // a nice big file
- fd, err := os.Open(filename, os.O_RDONLY, 0)
+ fd, err := os.Open(filename)
if err != nil {
t.Fatalf("open %s: %v", filename, err)
}
var hostentLock sync.Mutex
var serventLock sync.Mutex
-func LookupHost(name string) (cname string, addrs []string, err os.Error) {
+func goLookupHost(name string) (addrs []string, err os.Error) {
+ ips, err := goLookupIP(name)
+ if err != nil {
+ return
+ }
+ addrs = make([]string, 0, len(ips))
+ for _, ip := range ips {
+ addrs = append(addrs, ip.String())
+ }
+ return
+}
+
+func goLookupIP(name string) (addrs []IP, err os.Error) {
hostentLock.Lock()
defer hostentLock.Unlock()
h, e := syscall.GetHostByName(name)
if e != 0 {
- return "", nil, os.NewSyscallError("GetHostByName", e)
+ return nil, os.NewSyscallError("GetHostByName", e)
}
- cname = name
switch h.AddrType {
case syscall.AF_INET:
i := 0
- addrs = make([]string, 100) // plenty of room to grow
+ addrs = make([]IP, 100) // plenty of room to grow
for p := (*[100](*[4]byte))(unsafe.Pointer(h.AddrList)); i < cap(addrs) && p[i] != nil; i++ {
- addrs[i] = IPv4(p[i][0], p[i][1], p[i][2], p[i][3]).String()
+ addrs[i] = IPv4(p[i][0], p[i][1], p[i][2], p[i][3])
}
addrs = addrs[0:i]
default: // TODO(vcc): Implement non IPv4 address lookups.
- return "", nil, os.NewSyscallError("LookupHost", syscall.EWINDOWS)
+ return nil, os.NewSyscallError("LookupHost", syscall.EWINDOWS)
+ }
+ return addrs, nil
+}
+
+func LookupCNAME(name string) (cname string, err os.Error) {
+ var r *syscall.DNSRecord
+ e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
+ if int(e) != 0 {
+ return "", os.NewSyscallError("LookupCNAME", int(e))
+ }
+ defer syscall.DnsRecordListFree(r, 1)
+ if r != nil && r.Type == syscall.DNS_TYPE_CNAME {
+ v := (*syscall.DNSPTRData)(unsafe.Pointer(&r.Data[0]))
+ cname = syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."
}
- return cname, addrs, nil
+ return
}
type SRV struct {
return name, addrs, nil
}
-func LookupPort(network, service string) (port int, err os.Error) {
+func goLookupPort(network, service string) (port int, err os.Error) {
switch network {
case "tcp4", "tcp6":
network = "tcp"
--- /dev/null
+// 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 os
+
+import (
+ "syscall"
+)
+
+type dirInfo int
+
+var markDirectory dirInfo = ^0
+
+// Readdir reads the contents of the directory associated with file and
+// returns an array of up to count FileInfo structures, as would be returned
+// by Lstat, in directory order. Subsequent calls on the same file will yield
+// further FileInfos. A negative count means to read the entire directory.
+// Readdir returns the array and an Error, if any.
+func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
+ // If this file has no dirinfo, create one.
+ if file.dirinfo == nil {
+ file.dirinfo = &markDirectory
+ }
+
+ size := count
+ if size < 0 {
+ size = 100
+ }
+
+ result := make([]FileInfo, 0, size)
+ var buf [syscall.STATMAX]byte
+
+ for {
+ n, e := file.Read(buf[:])
+
+ if e != nil {
+ if e == EOF {
+ break
+ }
+
+ return []FileInfo{}, &PathError{"readdir", file.name, e}
+ }
+
+ if n < syscall.STATFIXLEN {
+ return []FileInfo{}, &PathError{"readdir", file.name, Eshortstat}
+ }
+
+ for i := 0; i < n; {
+ m, _ := gbit16(buf[i:])
+ m += 2
+
+ if m < syscall.STATFIXLEN {
+ return []FileInfo{}, &PathError{"readdir", file.name, Eshortstat}
+ }
+
+ d, e := UnmarshalDir(buf[i : i+int(m)])
+
+ if e != nil {
+ return []FileInfo{}, &PathError{"readdir", file.name, e}
+ }
+
+ var f FileInfo
+ fileInfoFromStat(&f, d)
+
+ result = append(result, f)
+
+ // a negative count means to read until EOF.
+ if count > 0 && len(result) >= count {
+ break
+ }
+
+ i += int(m)
+ }
+ }
+
+ return result, nil
+}
+
+// Readdirnames returns an array of up to count file names residing in the
+// directory associated with file. A negative count will return all of them.
+// Readdir returns the array and an Error, if any.
+func (file *File) Readdirnames(count int) (names []string, err Error) {
+ fi, e := file.Readdir(count)
+
+ if e != nil {
+ return []string{}, e
+ }
+
+ names = make([]string, len(fi))
+ err = nil
+
+ for i, _ := range fi {
+ names[i] = fi[i].Name
+ }
+
+ return
+}
+
+type Dir struct {
+ // system-modified data
+ Type uint16 // server type
+ Dev uint32 // server subtype
+ // file data
+ Qid Qid // unique id from server
+ Mode uint32 // permissions
+ Atime uint32 // last read time
+ Mtime uint32 // last write time
+ Length uint64 // file length
+ Name string // last element of path
+ Uid string // owner name
+ Gid string // group name
+ Muid string // last modifier name
+}
+
+type Qid struct {
+ Path uint64 // the file server's unique identification for the file
+ Vers uint32 // version number for given Path
+ Type uint8 // the type of the file (syscall.QTDIR for example)
+}
+
+var nullDir = Dir{
+ ^uint16(0),
+ ^uint32(0),
+ Qid{^uint64(0), ^uint32(0), ^uint8(0)},
+ ^uint32(0),
+ ^uint32(0),
+ ^uint32(0),
+ ^uint64(0),
+ "",
+ "",
+ "",
+ "",
+}
+
+// Null assigns members of d with special "don't care" values indicating
+// they should not be written by syscall.Wstat.
+func (d *Dir) Null() {
+ *d = nullDir
+}
+
+// pdir appends a 9P Stat message based on the contents of Dir d to a byte slice b.
+func pdir(b []byte, d *Dir) []byte {
+ n := len(b)
+ b = pbit16(b, 0) // length, filled in later
+ b = pbit16(b, d.Type)
+ b = pbit32(b, d.Dev)
+ b = pqid(b, d.Qid)
+ b = pbit32(b, d.Mode)
+ b = pbit32(b, d.Atime)
+ b = pbit32(b, d.Mtime)
+ b = pbit64(b, d.Length)
+ b = pstring(b, d.Name)
+ b = pstring(b, d.Uid)
+ b = pstring(b, d.Gid)
+ b = pstring(b, d.Muid)
+ pbit16(b[0:n], uint16(len(b)-(n+2)))
+ return b
+}
+
+// UnmarshalDir reads a 9P Stat message from a 9P protocol message strored in b,
+// returning the corresponding Dir struct.
+func UnmarshalDir(b []byte) (d *Dir, err Error) {
+ n := uint16(0)
+ n, b = gbit16(b)
+
+ if int(n) != len(b) {
+ return nil, Ebadstat
+ }
+
+ d = new(Dir)
+ d.Type, b = gbit16(b)
+ d.Dev, b = gbit32(b)
+ d.Qid, b = gqid(b)
+ d.Mode, b = gbit32(b)
+ d.Atime, b = gbit32(b)
+ d.Mtime, b = gbit32(b)
+ d.Length, b = gbit64(b)
+ d.Name, b = gstring(b)
+ d.Uid, b = gstring(b)
+ d.Gid, b = gstring(b)
+ d.Muid, b = gstring(b)
+
+ if len(b) != 0 {
+ return nil, Ebadstat
+ }
+
+ return d, nil
+}
+
+// gqid reads the qid part of a 9P Stat message from a 9P protocol message strored in b,
+// returning the corresponding Qid struct and the remaining slice of b.
+func gqid(b []byte) (Qid, []byte) {
+ var q Qid
+ q.Path, b = gbit64(b)
+ q.Vers, b = gbit32(b)
+ q.Type, b = gbit8(b)
+ return q, b
+}
+
+// pqid appends a Qid struct q to a 9P message b.
+func pqid(b []byte, q Qid) []byte {
+ b = pbit64(b, q.Path)
+ b = pbit32(b, q.Vers)
+ b = pbit8(b, q.Type)
+ return b
+}
+
+// gbit8 reads a byte-sized numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit8(b []byte) (uint8, []byte) {
+ return uint8(b[0]), b[1:]
+}
+
+// gbit16 reads a 16-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit16(b []byte) (uint16, []byte) {
+ return uint16(b[0]) | uint16(b[1])<<8, b[2:]
+}
+
+// gbit32 reads a 32-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit32(b []byte) (uint32, []byte) {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
+}
+
+// gbit64 reads a 64-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit64(b []byte) (uint64, []byte) {
+ lo, b := gbit32(b)
+ hi, b := gbit32(b)
+ return uint64(hi)<<32 | uint64(lo), b
+}
+
+// gstring reads a string from a 9P protocol message strored in b,
+// returning the value as a Go string and the remaining slice of b.
+func gstring(b []byte) (string, []byte) {
+ n, b := gbit16(b)
+ return string(b[0:n]), b[n:]
+}
+
+// pbit8 appends a byte-sized numeric value x to a 9P message b.
+func pbit8(b []byte, x uint8) []byte {
+ n := len(b)
+ if n+1 > cap(b) {
+ nb := make([]byte, n, 100+2*cap(b))
+ copy(nb, b)
+ b = nb
+ }
+ b = b[0 : n+1]
+ b[n] = x
+ return b
+}
+
+// pbit16 appends a 16-bit numeric value x to a 9P message b.
+func pbit16(b []byte, x uint16) []byte {
+ n := len(b)
+ if n+2 > cap(b) {
+ nb := make([]byte, n, 100+2*cap(b))
+ copy(nb, b)
+ b = nb
+ }
+ b = b[0 : n+2]
+ b[n] = byte(x)
+ b[n+1] = byte(x >> 8)
+ return b
+}
+
+// pbit32 appends a 32-bit numeric value x to a 9P message b.
+func pbit32(b []byte, x uint32) []byte {
+ n := len(b)
+ if n+4 > cap(b) {
+ nb := make([]byte, n, 100+2*cap(b))
+ copy(nb, b)
+ b = nb
+ }
+ b = b[0 : n+4]
+ b[n] = byte(x)
+ b[n+1] = byte(x >> 8)
+ b[n+2] = byte(x >> 16)
+ b[n+3] = byte(x >> 24)
+ return b
+}
+
+// pbit64 appends a 64-bit numeric value x to a 9P message b.
+func pbit64(b []byte, x uint64) []byte {
+ b = pbit32(b, uint32(x))
+ b = pbit32(b, uint32(x>>32))
+ return b
+}
+
+// pstring appends a Go string s to a 9P message b.
+func pstring(b []byte, s string) []byte {
+ if len(s) >= 1<<16 {
+ panic(NewError("string too long"))
+ }
+ b = pbit16(b, uint16(len(s)))
+ b = append(b, []byte(s)...)
+ return b
+}
--- /dev/null
+// 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 os
+
+import (
+ "syscall"
+)
+
+const (
+ blockSize = 4096
+)
+
+// Readdirnames reads the contents of the directory associated with file and
+// returns an array of up to count names, in directory order. Subsequent
+// calls on the same file will yield further names.
+// A negative count means to read until EOF.
+// Readdirnames returns the array and an Error, if any.
+func (file *File) Readdirnames(count int) (names []string, err Error) {
+ // If this file has no dirinfo, create one.
+ if file.dirinfo == nil {
+ file.dirinfo = new(dirInfo)
+ // The buffer must be at least a block long.
+ file.dirinfo.buf = make([]byte, blockSize)
+ }
+ d := file.dirinfo
+ size := count
+ if size < 0 {
+ size = 100
+ }
+ names = make([]string, 0, size) // Empty with room to grow.
+ for count != 0 {
+ // Refill the buffer if necessary
+ if d.bufp >= d.nbuf {
+ d.bufp = 0
+ var errno int
+ d.nbuf, errno = syscall.ReadDirent(file.fd, d.buf)
+ if errno != 0 {
+ return names, NewSyscallError("readdirent", errno)
+ }
+ if d.nbuf <= 0 {
+ break // EOF
+ }
+ }
+
+ // Drain the buffer
+ var nb, nc int
+ nb, nc, names = syscall.ParseDirent(d.buf[d.bufp:d.nbuf], count, names)
+ d.bufp += nb
+ count -= nc
+ }
+ return names, nil
+}
--- /dev/null
+// 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.
+
+// Plan 9 environment variables.
+
+package os
+
+import "syscall"
+
+// ENOENV is the Error indicating that an environment variable does not exist.
+var ENOENV = NewError("no such environment variable")
+
+// Getenverror retrieves the value of the environment variable named by the key.
+// It returns the value and an error, if any.
+func Getenverror(key string) (value string, err Error) {
+ if len(key) == 0 {
+ return "", EINVAL
+ }
+ f, e := Open("/env/" + key)
+ if iserror(e) {
+ return "", ENOENV
+ }
+ defer f.Close()
+
+ var buf [4096]byte
+ n, e := f.Read(buf[:len(buf)-1])
+ if iserror(e) {
+ return "", ENOENV
+ }
+ buf[n] = 0
+ return string(buf[0:n]), nil
+}
+
+// Getenv retrieves the value of the environment variable named by the key.
+// It returns the value, which will be empty if the variable is not present.
+func Getenv(key string) string {
+ v, _ := Getenverror(key)
+ return v
+}
+
+// Setenv sets the value of the environment variable named by the key.
+// It returns an Error, if any.
+func Setenv(key, value string) Error {
+ if len(key) == 0 {
+ return EINVAL
+ }
+
+ f, e := Create("/env/" + key)
+ if iserror(e) {
+ return e
+ }
+ defer f.Close()
+
+ _, e = f.Write(syscall.StringByteSlice(value))
+ return nil
+}
+
+// Clearenv deletes all environment variables.
+func Clearenv() {
+ syscall.RawSyscall(syscall.SYS_RFORK, syscall.RFCENVG, 0, 0)
+}
+
+// Environ returns an array of strings representing the environment,
+// in the form "key=value".
+func Environ() []string {
+ env := make([]string, 0, 100)
+
+ f, e := Open("/env")
+ if iserror(e) {
+ panic(e)
+ }
+ defer f.Close()
+
+ names, e := f.Readdirnames(-1)
+ if iserror(e) {
+ panic(e)
+ }
+
+ for _, k := range names {
+ if v, e := Getenverror(k); !iserror(e) {
+ env = append(env, k+"="+v)
+ }
+ }
+ return env[0:len(env)]
+}
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+ return "/tmp"
+}
package os
-import syscall "syscall"
-
// An Error can represent any printable error condition.
type Error interface {
String() string
// NewError converts s to an ErrorString, which satisfies the Error interface.
func NewError(s string) Error { return ErrorString(s) }
-// Errno is the Unix error number. Names such as EINVAL are simple
-// wrappers to convert the error number into an Error.
-type Errno int64
-
-func (e Errno) String() string { return syscall.Errstr(int(e)) }
-
-func (e Errno) Temporary() bool {
- return e == Errno(syscall.EINTR) || e.Timeout()
-}
-
-func (e Errno) Timeout() bool {
- return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK) || e == Errno(syscall.ETIMEDOUT)
-}
-
-// Commonly known Unix errors.
-var (
- EPERM Error = Errno(syscall.EPERM)
- ENOENT Error = Errno(syscall.ENOENT)
- ESRCH Error = Errno(syscall.ESRCH)
- EINTR Error = Errno(syscall.EINTR)
- EIO Error = Errno(syscall.EIO)
- ENXIO Error = Errno(syscall.ENXIO)
- E2BIG Error = Errno(syscall.E2BIG)
- ENOEXEC Error = Errno(syscall.ENOEXEC)
- EBADF Error = Errno(syscall.EBADF)
- ECHILD Error = Errno(syscall.ECHILD)
- EDEADLK Error = Errno(syscall.EDEADLK)
- ENOMEM Error = Errno(syscall.ENOMEM)
- EACCES Error = Errno(syscall.EACCES)
- EFAULT Error = Errno(syscall.EFAULT)
- EBUSY Error = Errno(syscall.EBUSY)
- EEXIST Error = Errno(syscall.EEXIST)
- EXDEV Error = Errno(syscall.EXDEV)
- ENODEV Error = Errno(syscall.ENODEV)
- ENOTDIR Error = Errno(syscall.ENOTDIR)
- EISDIR Error = Errno(syscall.EISDIR)
- EINVAL Error = Errno(syscall.EINVAL)
- ENFILE Error = Errno(syscall.ENFILE)
- EMFILE Error = Errno(syscall.EMFILE)
- ENOTTY Error = Errno(syscall.ENOTTY)
- EFBIG Error = Errno(syscall.EFBIG)
- ENOSPC Error = Errno(syscall.ENOSPC)
- ESPIPE Error = Errno(syscall.ESPIPE)
- EROFS Error = Errno(syscall.EROFS)
- EMLINK Error = Errno(syscall.EMLINK)
- EPIPE Error = Errno(syscall.EPIPE)
- EAGAIN Error = Errno(syscall.EAGAIN)
- EDOM Error = Errno(syscall.EDOM)
- ERANGE Error = Errno(syscall.ERANGE)
- EADDRINUSE Error = Errno(syscall.EADDRINUSE)
- ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
- ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
- EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
- ETIMEDOUT Error = Errno(syscall.ETIMEDOUT)
- ENOTCONN Error = Errno(syscall.ENOTCONN)
-)
-
// PathError records an error and the operation and file path that caused it.
type PathError struct {
Op string
}
func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
-
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
- Syscall string
- Errno Errno
-}
-
-func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
-
-// Note: If the name of the function NewSyscallError changes,
-// pkg/go/doc/doc.go should be adjusted since it hardwires
-// this name in a heuristic.
-
-// NewSyscallError returns, as an Error, a new SyscallError
-// with the given system call name and error number.
-// As a convenience, if errno is 0, NewSyscallError returns nil.
-func NewSyscallError(syscall string, errno int) Error {
- if errno == 0 {
- return nil
- }
- return &SyscallError{syscall, Errno(errno)}
-}
--- /dev/null
+// 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.
+
+package os
+
+import syscall "syscall"
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+ Syscall string
+ Err string
+}
+
+func (e *SyscallError) String() string { return e.Syscall + ": " + e.Err }
+
+// Note: If the name of the function NewSyscallError changes,
+// pkg/go/doc/doc.go should be adjusted since it hardwires
+// this name in a heuristic.
+
+// NewSyscallError returns, as an Error, a new SyscallError
+// with the given system call name and error details.
+// As a convenience, if err is nil, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err syscall.Error) Error {
+ if err == nil {
+ return nil
+ }
+ return &SyscallError{syscall, err.String()}
+}
+
+var (
+ Eshortstat = NewError("stat buffer too small")
+ Ebadstat = NewError("malformed stat buffer")
+ Ebadfd = NewError("fd out of range or not open")
+ Ebadarg = NewError("bad arg in system call")
+ Enotdir = NewError("not a directory")
+ Enonexist = NewError("file does not exist")
+ Eexist = NewError("file already exists")
+ Eio = NewError("i/o error")
+
+ EINVAL = Ebadarg
+ ENOTDIR = Enotdir
+ ENOENT = Enonexist
+ EEXIST = Eexist
+ EIO = Eio
+
+ ENAMETOOLONG = NewError("file name too long")
+ ERANGE = NewError("math result not representable")
+ EPIPE = NewError("Broken Pipe")
+ EPLAN9 = NewError("not supported by plan 9")
+)
+
+func iserror(err syscall.Error) bool {
+ return err != nil
+}
+
+func Errno(e syscall.Error) syscall.Error { return e }
--- /dev/null
+// 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 os
+
+import syscall "syscall"
+
+// Errno is the Unix error number. Names such as EINVAL are simple
+// wrappers to convert the error number into an Error.
+type Errno int64
+
+func (e Errno) String() string { return syscall.Errstr(int(e)) }
+
+func (e Errno) Temporary() bool {
+ return e == Errno(syscall.EINTR) || e.Timeout()
+}
+
+func (e Errno) Timeout() bool {
+ return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK) || e == Errno(syscall.ETIMEDOUT)
+}
+
+// Commonly known Unix errors.
+var (
+ EPERM Error = Errno(syscall.EPERM)
+ ENOENT Error = Errno(syscall.ENOENT)
+ ESRCH Error = Errno(syscall.ESRCH)
+ EINTR Error = Errno(syscall.EINTR)
+ EIO Error = Errno(syscall.EIO)
+ ENXIO Error = Errno(syscall.ENXIO)
+ E2BIG Error = Errno(syscall.E2BIG)
+ ENOEXEC Error = Errno(syscall.ENOEXEC)
+ EBADF Error = Errno(syscall.EBADF)
+ ECHILD Error = Errno(syscall.ECHILD)
+ EDEADLK Error = Errno(syscall.EDEADLK)
+ ENOMEM Error = Errno(syscall.ENOMEM)
+ EACCES Error = Errno(syscall.EACCES)
+ EFAULT Error = Errno(syscall.EFAULT)
+ EBUSY Error = Errno(syscall.EBUSY)
+ EEXIST Error = Errno(syscall.EEXIST)
+ EXDEV Error = Errno(syscall.EXDEV)
+ ENODEV Error = Errno(syscall.ENODEV)
+ ENOTDIR Error = Errno(syscall.ENOTDIR)
+ EISDIR Error = Errno(syscall.EISDIR)
+ EINVAL Error = Errno(syscall.EINVAL)
+ ENFILE Error = Errno(syscall.ENFILE)
+ EMFILE Error = Errno(syscall.EMFILE)
+ ENOTTY Error = Errno(syscall.ENOTTY)
+ EFBIG Error = Errno(syscall.EFBIG)
+ ENOSPC Error = Errno(syscall.ENOSPC)
+ ESPIPE Error = Errno(syscall.ESPIPE)
+ EROFS Error = Errno(syscall.EROFS)
+ EMLINK Error = Errno(syscall.EMLINK)
+ EPIPE Error = Errno(syscall.EPIPE)
+ EAGAIN Error = Errno(syscall.EAGAIN)
+ EDOM Error = Errno(syscall.EDOM)
+ ERANGE Error = Errno(syscall.ERANGE)
+ EADDRINUSE Error = Errno(syscall.EADDRINUSE)
+ ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
+ ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
+ EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
+ ETIMEDOUT Error = Errno(syscall.ETIMEDOUT)
+ ENOTCONN Error = Errno(syscall.ENOTCONN)
+)
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+ Syscall string
+ Errno Errno
+}
+
+func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
+
+// Note: If the name of the function NewSyscallError changes,
+// pkg/go/doc/doc.go should be adjusted since it hardwires
+// this name in a heuristic.
+
+// NewSyscallError returns, as an Error, a new SyscallError
+// with the given system call name and error details.
+// As a convenience, if errno is 0, NewSyscallError returns nil.
+func NewSyscallError(syscall string, errno int) Error {
+ if errno == 0 {
+ return nil
+ }
+ return &SyscallError{syscall, Errno(errno)}
+}
+
+func iserror(errno int) bool {
+ return errno != 0
+}
Files []*File
}
-// StartProcess starts a new process with the program, arguments and attributes
-// specified by name, argv and attr.
-func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
- sysattr := &syscall.ProcAttr{
- Dir: attr.Dir,
- Env: attr.Env,
- }
- if sysattr.Env == nil {
- sysattr.Env = Environ()
- }
- // Create array of integer (system) fds.
- intfd := make([]int, len(attr.Files))
- for i, f := range attr.Files {
- if f == nil {
- intfd[i] = -1
- } else {
- intfd[i] = f.Fd()
- }
- }
- sysattr.Files = intfd
-
- pid, h, e := syscall.StartProcess(name, argv, sysattr)
- if e != 0 {
- return nil, &PathError{"fork/exec", name, Errno(e)}
- }
- return newProcess(pid, h), nil
-}
-
-// Exec replaces the current process with an execution of the
-// named binary, with arguments argv and environment envv.
-// If successful, Exec never returns. If it fails, it returns an Error.
-// StartProcess is almost always a better way to execute a program.
-func Exec(name string, argv []string, envv []string) Error {
- if envv == nil {
- envv = Environ()
- }
- e := syscall.Exec(name, argv, envv)
- if e != 0 {
- return &PathError{"exec", name, Errno(e)}
- }
- return nil
-}
-
-// TODO(rsc): Should os implement its own syscall.WaitStatus
-// wrapper with the methods, or is exposing the underlying one enough?
-//
-// TODO(rsc): Certainly need to have Rusage struct,
-// since syscall one might have different field types across
-// different OS.
-
-// Waitmsg stores the information about an exited process as reported by Wait.
-type Waitmsg struct {
- Pid int // The process's id.
- syscall.WaitStatus // System-dependent status info.
- Rusage *syscall.Rusage // System-dependent resource usage info.
-}
-
-// Wait waits for process pid to exit or stop, and then returns a
-// Waitmsg describing its status and an Error, if any. The options
-// (WNOHANG etc.) affect the behavior of the Wait call.
-// Wait is equivalent to calling FindProcess and then Wait
-// and Release on the result.
-func Wait(pid int, options int) (w *Waitmsg, err Error) {
- p, e := FindProcess(pid)
- if e != nil {
- return nil, e
- }
- defer p.Release()
- return p.Wait(options)
-}
-
-// Convert i to decimal string.
-func itod(i int) string {
- if i == 0 {
- return "0"
- }
-
- u := uint64(i)
- if i < 0 {
- u = -u
- }
-
- // Assemble decimal in reverse order.
- var b [32]byte
- bp := len(b)
- for ; u > 0; u /= 10 {
- bp--
- b[bp] = byte(u%10) + '0'
- }
-
- if i < 0 {
- bp--
- b[bp] = '-'
- }
-
- return string(b[bp:])
-}
-
-func (w Waitmsg) String() string {
- // TODO(austin) Use signal names when possible?
- res := ""
- switch {
- case w.Exited():
- res = "exit status " + itod(w.ExitStatus())
- case w.Signaled():
- res = "signal " + itod(w.Signal())
- case w.Stopped():
- res = "stop signal " + itod(w.StopSignal())
- if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
- res += " (trap " + itod(w.TrapCause()) + ")"
- }
- case w.Continued():
- res = "continued"
- }
- if w.CoreDump() {
- res += " (core dumped)"
- }
- return res
-}
-
// Getpid returns the process id of the caller.
func Getpid() int { return syscall.Getpid() }
--- /dev/null
+// 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 os
+
+import (
+ "runtime"
+ "syscall"
+)
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+ sysattr := &syscall.ProcAttr{
+ Dir: attr.Dir,
+ Env: attr.Env,
+ }
+
+ // Create array of integer (system) fds.
+ intfd := make([]int, len(attr.Files))
+ for i, f := range attr.Files {
+ if f == nil {
+ intfd[i] = -1
+ } else {
+ intfd[i] = f.Fd()
+ }
+ }
+
+ sysattr.Files = intfd
+
+ pid, h, e := syscall.StartProcess(name, argv, sysattr)
+ if iserror(e) {
+ return nil, &PathError{"fork/exec", name, e}
+ }
+
+ return newProcess(pid, h), nil
+}
+
+// Exec replaces the current process with an execution of the
+// named binary, with arguments argv and environment envv.
+// If successful, Exec never returns. If it fails, it returns an Error.
+// ForkExec is almost always a better way to execute a program.
+func Exec(name string, argv []string, envv []string) Error {
+ e := syscall.Exec(name, argv, envv)
+ if iserror(e) {
+ return &PathError{"exec", name, e}
+ }
+
+ return nil
+}
+
+// Waitmsg stores the information about an exited process as reported by Wait.
+type Waitmsg syscall.Waitmsg
+
+// Wait waits for the Process to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
+ var waitmsg syscall.Waitmsg
+
+ if p.Pid == -1 {
+ return nil, EINVAL
+ }
+
+ for true {
+ err = syscall.Await(&waitmsg)
+
+ if iserror(err) {
+ return nil, NewSyscallError("wait", err)
+ }
+
+ if waitmsg.Pid == p.Pid {
+ break
+ }
+ }
+
+ return (*Waitmsg)(&waitmsg), nil
+}
+
+// Wait waits for process pid to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+// Wait is equivalent to calling FindProcess and then Wait
+// and Release on the result.
+func Wait(pid int, options int) (w *Waitmsg, err Error) {
+ p, e := FindProcess(pid)
+ if e != nil {
+ return nil, e
+ }
+ defer p.Release()
+ return p.Wait(options)
+}
+
+// Release releases any resources associated with the Process.
+func (p *Process) Release() Error {
+ // NOOP for Plan 9.
+ p.Pid = -1
+ // no need for a finalizer anymore
+ runtime.SetFinalizer(p, nil)
+ return nil
+}
+
+// FindProcess looks for a running process by its pid.
+// The Process it returns can be used to obtain information
+// about the underlying operating system process.
+func FindProcess(pid int) (p *Process, err Error) {
+ // NOOP for Plan 9.
+ return newProcess(pid, 0), nil
+}
+
+func (w Waitmsg) String() string {
+ return "exit status: " + w.Msg
+}
--- /dev/null
+// 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 os
+
+import "syscall"
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+ sysattr := &syscall.ProcAttr{
+ Dir: attr.Dir,
+ Env: attr.Env,
+ }
+ if sysattr.Env == nil {
+ sysattr.Env = Environ()
+ }
+ // Create array of integer (system) fds.
+ intfd := make([]int, len(attr.Files))
+ for i, f := range attr.Files {
+ if f == nil {
+ intfd[i] = -1
+ } else {
+ intfd[i] = f.Fd()
+ }
+ }
+ sysattr.Files = intfd
+
+ pid, h, e := syscall.StartProcess(name, argv, sysattr)
+ if iserror(e) {
+ return nil, &PathError{"fork/exec", name, Errno(e)}
+ }
+ return newProcess(pid, h), nil
+}
+
+// Exec replaces the current process with an execution of the
+// named binary, with arguments argv and environment envv.
+// If successful, Exec never returns. If it fails, it returns an Error.
+// StartProcess is almost always a better way to execute a program.
+func Exec(name string, argv []string, envv []string) Error {
+ if envv == nil {
+ envv = Environ()
+ }
+ e := syscall.Exec(name, argv, envv)
+ if iserror(e) {
+ return &PathError{"exec", name, Errno(e)}
+ }
+ return nil
+}
+
+// TODO(rsc): Should os implement its own syscall.WaitStatus
+// wrapper with the methods, or is exposing the underlying one enough?
+//
+// TODO(rsc): Certainly need to have Rusage struct,
+// since syscall one might have different field types across
+// different OS.
+
+// Waitmsg stores the information about an exited process as reported by Wait.
+type Waitmsg struct {
+ Pid int // The process's id.
+ syscall.WaitStatus // System-dependent status info.
+ Rusage *syscall.Rusage // System-dependent resource usage info.
+}
+
+// Wait waits for process pid to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+// Wait is equivalent to calling FindProcess and then Wait
+// and Release on the result.
+func Wait(pid int, options int) (w *Waitmsg, err Error) {
+ p, e := FindProcess(pid)
+ if e != nil {
+ return nil, e
+ }
+ defer p.Release()
+ return p.Wait(options)
+}
+
+// Convert i to decimal string.
+func itod(i int) string {
+ if i == 0 {
+ return "0"
+ }
+
+ u := uint64(i)
+ if i < 0 {
+ u = -u
+ }
+
+ // Assemble decimal in reverse order.
+ var b [32]byte
+ bp := len(b)
+ for ; u > 0; u /= 10 {
+ bp--
+ b[bp] = byte(u%10) + '0'
+ }
+
+ if i < 0 {
+ bp--
+ b[bp] = '-'
+ }
+
+ return string(b[bp:])
+}
+
+func (w Waitmsg) String() string {
+ // TODO(austin) Use signal names when possible?
+ res := ""
+ switch {
+ case w.Exited():
+ res = "exit status " + itod(w.ExitStatus())
+ case w.Signaled():
+ res = "signal " + itod(w.Signal())
+ case w.Stopped():
+ res = "stop signal " + itod(w.StopSignal())
+ if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
+ res += " (trap " + itod(w.TrapCause()) + ")"
+ }
+ case w.Continued():
+ res = "continued"
+ }
+ if w.CoreDump() {
+ res += " (core dumped)"
+ }
+ return res
+}
O_RDWR int = syscall.O_RDWR // open the file read-write.
O_APPEND int = syscall.O_APPEND // append data to the file when writing.
O_ASYNC int = syscall.O_ASYNC // generate a signal when I/O is available.
- O_CREAT int = syscall.O_CREAT // create a new file if none exists.
- O_EXCL int = syscall.O_EXCL // used with O_CREAT, file must not exist
+ O_CREATE int = syscall.O_CREAT // create a new file if none exists.
+ O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist
O_NOCTTY int = syscall.O_NOCTTY // do not make file the controlling tty.
O_NONBLOCK int = syscall.O_NONBLOCK // open in non-blocking mode.
O_NDELAY int = O_NONBLOCK // synonym for O_NONBLOCK
O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
O_TRUNC int = syscall.O_TRUNC // if possible, truncate file when opened.
- O_CREATE int = O_CREAT // create a new file if none exists.
+)
+
+// Seek whence values.
+const (
+ SEEK_SET int = 0 // seek relative to the origin of the file
+ SEEK_CUR int = 1 // seek relative to the current offset
+ SEEK_END int = 2 // seek relative to the end
)
type eofError int
if n < 0 {
n = 0
}
- if n == 0 && e == 0 {
+ if n == 0 && !iserror(e) {
return 0, EOF
}
- if e != 0 {
+ if iserror(e) {
err = &PathError{"read", file.name, Errno(e)}
}
return n, err
}
for len(b) > 0 {
m, e := syscall.Pread(file.fd, b, off)
- if m == 0 && e == 0 {
+ if m == 0 && !iserror(e) {
return n, EOF
}
- if e != 0 {
+ if iserror(e) {
err = &PathError{"read", file.name, Errno(e)}
break
}
if n < 0 {
n = 0
}
- if e == syscall.EPIPE {
- file.nepipe++
- if file.nepipe >= 10 {
- Exit(syscall.EPIPE)
- }
- } else {
- file.nepipe = 0
- }
- if e != 0 {
+
+ epipecheck(file, e)
+
+ if iserror(e) {
err = &PathError{"write", file.name, Errno(e)}
}
return n, err
}
for len(b) > 0 {
m, e := syscall.Pwrite(file.fd, b, off)
- if e != 0 {
+ if iserror(e) {
err = &PathError{"write", file.name, Errno(e)}
break
}
// It returns the new offset and an Error, if any.
func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
r, e := syscall.Seek(file.fd, offset, whence)
- if e == 0 && file.dirinfo != nil && r != 0 {
+ if !iserror(e) && file.dirinfo != nil && r != 0 {
e = syscall.EISDIR
}
- if e != 0 {
+ if iserror(e) {
return 0, &PathError{"seek", file.name, Errno(e)}
}
return r, nil
return file.Write(b)
}
-// Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an Error, if any.
-func Pipe() (r *File, w *File, err Error) {
- var p [2]int
-
- // See ../syscall/exec.go for description of lock.
- syscall.ForkLock.RLock()
- e := syscall.Pipe(p[0:])
- if e != 0 {
- syscall.ForkLock.RUnlock()
- return nil, nil, NewSyscallError("pipe", e)
- }
- syscall.CloseOnExec(p[0])
- syscall.CloseOnExec(p[1])
- syscall.ForkLock.RUnlock()
-
- return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
-}
-
// Mkdir creates a new directory with the specified name and permission bits.
// It returns an error, if any.
func Mkdir(name string, perm uint32) Error {
e := syscall.Mkdir(name, perm)
- if e != 0 {
+ if iserror(e) {
return &PathError{"mkdir", name, Errno(e)}
}
return nil
}
-// Stat returns a FileInfo structure describing the named file and an error, if any.
-// If name names a valid symbolic link, the returned FileInfo describes
-// the file pointed at by the link and has fi.FollowedSymlink set to true.
-// If name names an invalid symbolic link, the returned FileInfo describes
-// the link itself and has fi.FollowedSymlink set to false.
-func Stat(name string) (fi *FileInfo, err Error) {
- var lstat, stat syscall.Stat_t
- e := syscall.Lstat(name, &lstat)
- if e != 0 {
- return nil, &PathError{"stat", name, Errno(e)}
- }
- statp := &lstat
- if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
- e := syscall.Stat(name, &stat)
- if e == 0 {
- statp = &stat
- }
- }
- return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
-}
-
-// Lstat returns the FileInfo structure describing the named file and an
-// error, if any. If the file is a symbolic link, the returned FileInfo
-// describes the symbolic link. Lstat makes no attempt to follow the link.
-func Lstat(name string) (fi *FileInfo, err Error) {
- var stat syscall.Stat_t
- e := syscall.Lstat(name, &stat)
- if e != 0 {
- return nil, &PathError{"lstat", name, Errno(e)}
- }
- return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
-}
-
// Chdir changes the current working directory to the named directory.
func Chdir(dir string) Error {
- if e := syscall.Chdir(dir); e != 0 {
+ if e := syscall.Chdir(dir); iserror(e) {
return &PathError{"chdir", dir, Errno(e)}
}
return nil
// Chdir changes the current working directory to the file,
// which must be a directory.
func (f *File) Chdir() Error {
- if e := syscall.Fchdir(f.fd); e != 0 {
+ if e := syscall.Fchdir(f.fd); iserror(e) {
return &PathError{"chdir", f.name, Errno(e)}
}
return nil
}
-// Remove removes the named file or directory.
-func Remove(name string) Error {
- // System call interface forces us to know
- // whether name is a file or directory.
- // Try both: it is cheaper on average than
- // doing a Stat plus the right one.
- e := syscall.Unlink(name)
- if e == 0 {
- return nil
- }
- e1 := syscall.Rmdir(name)
- if e1 == 0 {
- return nil
- }
-
- // Both failed: figure out which error to return.
- // OS X and Linux differ on whether unlink(dir)
- // returns EISDIR, so can't use that. However,
- // both agree that rmdir(file) returns ENOTDIR,
- // so we can use that to decide which error is real.
- // Rmdir might also return ENOTDIR if given a bad
- // file path, like /etc/passwd/foo, but in that case,
- // both errors will be ENOTDIR, so it's okay to
- // use the error from unlink.
- // For windows syscall.ENOTDIR is set
- // to syscall.ERROR_DIRECTORY, hopefully it should
- // do the trick.
- if e1 != syscall.ENOTDIR {
- e = e1
- }
- return &PathError{"remove", name, Errno(e)}
-}
-
-// LinkError records an error during a link or symlink or rename
-// system call and the paths that caused it.
-type LinkError struct {
- Op string
- Old string
- New string
- Error Error
-}
-
-func (e *LinkError) String() string {
- return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
+// Open opens the named file for reading. If successful, methods on
+// the returned file can be used for reading; the associated file
+// descriptor has mode O_RDONLY.
+// It returns the File and an Error, if any.
+func Open(name string) (file *File, err Error) {
+ return OpenFile(name, O_RDONLY, 0)
}
-// Link creates a hard link.
-func Link(oldname, newname string) Error {
- e := syscall.Link(oldname, newname)
- if e != 0 {
- return &LinkError{"link", oldname, newname, Errno(e)}
- }
- return nil
-}
-
-// Symlink creates a symbolic link.
-func Symlink(oldname, newname string) Error {
- e := syscall.Symlink(oldname, newname)
- if e != 0 {
- return &LinkError{"symlink", oldname, newname, Errno(e)}
- }
- return nil
-}
-
-// Readlink reads the contents of a symbolic link: the destination of
-// the link. It returns the contents and an Error, if any.
-func Readlink(name string) (string, Error) {
- for len := 128; ; len *= 2 {
- b := make([]byte, len)
- n, e := syscall.Readlink(name, b)
- if e != 0 {
- return "", &PathError{"readlink", name, Errno(e)}
- }
- if n < len {
- return string(b[0:n]), nil
- }
- }
- // Silence 6g.
- return "", nil
-}
-
-// Rename renames a file.
-func Rename(oldname, newname string) Error {
- e := syscall.Rename(oldname, newname)
- if e != 0 {
- return &LinkError{"rename", oldname, newname, Errno(e)}
- }
- return nil
-}
-
-// Chmod changes the mode of the named file to mode.
-// If the file is a symbolic link, it changes the mode of the link's target.
-func Chmod(name string, mode uint32) Error {
- if e := syscall.Chmod(name, mode); e != 0 {
- return &PathError{"chmod", name, Errno(e)}
- }
- return nil
-}
-
-// Chmod changes the mode of the file to mode.
-func (f *File) Chmod(mode uint32) Error {
- if e := syscall.Fchmod(f.fd, mode); e != 0 {
- return &PathError{"chmod", f.name, Errno(e)}
- }
- return nil
-}
-
-// Chown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link's target.
-func Chown(name string, uid, gid int) Error {
- if e := syscall.Chown(name, uid, gid); e != 0 {
- return &PathError{"chown", name, Errno(e)}
- }
- return nil
-}
-
-// Lchown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link itself.
-func Lchown(name string, uid, gid int) Error {
- if e := syscall.Lchown(name, uid, gid); e != 0 {
- return &PathError{"lchown", name, Errno(e)}
- }
- return nil
-}
-
-// Chown changes the numeric uid and gid of the named file.
-func (f *File) Chown(uid, gid int) Error {
- if e := syscall.Fchown(f.fd, uid, gid); e != 0 {
- return &PathError{"chown", f.name, Errno(e)}
- }
- return nil
-}
-
-// Truncate changes the size of the file.
-// It does not change the I/O offset.
-func (f *File) Truncate(size int64) Error {
- if e := syscall.Ftruncate(f.fd, size); e != 0 {
- return &PathError{"truncate", f.name, Errno(e)}
- }
- return nil
-}
-
-// Sync commits the current contents of the file to stable storage.
-// Typically, this means flushing the file system's in-memory copy
-// of recently written data to disk.
-func (file *File) Sync() (err Error) {
- if file == nil {
- return EINVAL
- }
- if e := syscall.Fsync(file.fd); e != 0 {
- return NewSyscallError("fsync", e)
- }
- return nil
-}
-
-// Chtimes changes the access and modification times of the named
-// file, similar to the Unix utime() or utimes() functions.
-//
-// The argument times are in nanoseconds, although the underlying
-// filesystem may truncate or round the values to a more
-// coarse time unit.
-func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
- var utimes [2]syscall.Timeval
- utimes[0] = syscall.NsecToTimeval(atime_ns)
- utimes[1] = syscall.NsecToTimeval(mtime_ns)
- if e := syscall.Utimes(name, utimes[0:]); e != 0 {
- return &PathError{"chtimes", name, Errno(e)}
- }
- return nil
+// Create creates the named file mode 0666 (before umask), truncating
+// it if it already exists. If successful, methods on the returned
+// File can be used for I/O; the associated file descriptor has mode
+// O_RDWR.
+// It returns the File and an Error, if any.
+func Create(name string) (file *File, err Error) {
+ return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
--- /dev/null
+// 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.
+
+package os
+
+import (
+ "runtime"
+ "syscall"
+)
+
+func epipecheck(file *File, e syscall.Error) {
+}
+
+
+// DevNull is the name of the operating system's ``null device.''
+// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
+const DevNull = "/dev/null"
+
+// OpenFile is the generalized open call; most users will use Open
+// or Create instead. It opens the named file with specified flag
+// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful,
+// methods on the returned File can be used for I/O.
+// It returns the File and an Error, if any.
+func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
+ var fd int
+ var e syscall.Error
+
+ syscall.ForkLock.RLock()
+ if flag&O_CREATE == O_CREATE {
+ fd, e = syscall.Create(name, flag & ^O_CREATE, perm)
+ } else {
+ fd, e = syscall.Open(name, flag)
+ }
+ syscall.ForkLock.RUnlock()
+
+ if e != nil {
+ return nil, &PathError{"open", name, e}
+ }
+
+ return NewFile(fd, name), nil
+}
+
+// Close closes the File, rendering it unusable for I/O.
+// It returns an Error, if any.
+func (file *File) Close() Error {
+ if file == nil || file.fd < 0 {
+ return Ebadfd
+ }
+ var err Error
+ syscall.ForkLock.RLock()
+ if e := syscall.Close(file.fd); e != nil {
+ err = &PathError{"close", file.name, e}
+ }
+ syscall.ForkLock.RUnlock()
+ file.fd = -1 // so it can't be closed again
+
+ // no need for a finalizer anymore
+ runtime.SetFinalizer(file, nil)
+ return err
+}
+
+// Stat returns the FileInfo structure describing file.
+// It returns the FileInfo and an error, if any.
+func (file *File) Stat() (fi *FileInfo, err Error) {
+ return dirstat(file)
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+func (f *File) Truncate(size int64) Error {
+ var d Dir
+ d.Null()
+
+ d.Length = uint64(size)
+
+ if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+ return &PathError{"truncate", f.name, e}
+ }
+ return nil
+}
+
+// Chmod changes the mode of the file to mode.
+func (f *File) Chmod(mode uint32) Error {
+ var d Dir
+ d.Null()
+
+ d.Mode = mode & 0777
+
+ if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chmod", f.name, e}
+ }
+ return nil
+}
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (f *File) Sync() (err Error) {
+ if f == nil {
+ return EINVAL
+ }
+
+ var d Dir
+ d.Null()
+
+ if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+ return NewSyscallError("fsync", e)
+ }
+ return nil
+}
+
+// Truncate changes the size of the named file.
+// If the file is a symbolic link, it changes the size of the link's target.
+func Truncate(name string, size int64) Error {
+ var d Dir
+ d.Null()
+
+ d.Length = uint64(size)
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"truncate", name, e}
+ }
+ return nil
+}
+
+// Remove removes the named file or directory.
+func Remove(name string) Error {
+ if e := syscall.Remove(name); iserror(e) {
+ return &PathError{"remove", name, e}
+ }
+ return nil
+}
+
+// Rename renames a file.
+func Rename(oldname, newname string) Error {
+ var d Dir
+ d.Null()
+
+ d.Name = newname
+
+ if e := syscall.Wstat(oldname, pdir(nil, &d)); iserror(e) {
+ return &PathError{"rename", oldname, e}
+ }
+ return nil
+}
+
+// Chmod changes the mode of the named file to mode.
+func Chmod(name string, mode uint32) Error {
+ var d Dir
+ d.Null()
+
+ d.Mode = mode & 0777
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chmod", name, e}
+ }
+ return nil
+}
+
+// ChownPlan9 changes the uid and gid strings of the named file.
+func ChownPlan9(name, uid, gid string) Error {
+ var d Dir
+ d.Null()
+
+ d.Uid = uid
+ d.Gid = gid
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chown_plan9", name, e}
+ }
+ return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The argument times are in nanoseconds, although the underlying
+// filesystem may truncate or round the values to a more
+// coarse time unit.
+func Chtimes(name string, atimeNs int64, mtimeNs int64) Error {
+ var d Dir
+ d.Null()
+
+ d.Atime = uint32(atimeNs / 1e9)
+ d.Mtime = uint32(mtimeNs / 1e9)
+
+ if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+ return &PathError{"chtimes", name, e}
+ }
+ return nil
+}
+
+func Pipe() (r *File, w *File, err Error) {
+ var p [2]int
+
+ syscall.ForkLock.RLock()
+ if e := syscall.Pipe(p[0:]); iserror(e) {
+ syscall.ForkLock.RUnlock()
+ return nil, nil, NewSyscallError("pipe", e)
+ }
+ syscall.ForkLock.RUnlock()
+
+ return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
+
+
+// not supported on Plan 9
+
+// Link creates a hard link.
+func Link(oldname, newname string) Error {
+ return EPLAN9
+}
+
+func Symlink(oldname, newname string) Error {
+ return EPLAN9
+}
+
+func Readlink(name string) (string, Error) {
+ return "", EPLAN9
+}
+
+func Chown(name string, uid, gid int) Error {
+ return EPLAN9
+}
+
+func Lchown(name string, uid, gid int) Error {
+ return EPLAN9
+}
+
+func (f *File) Chown(uid, gid int) Error {
+ return EPLAN9
+}
--- /dev/null
+// 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.
+
+// The os package provides a platform-independent interface to operating
+// system functionality. The design is Unix-like.
+package os
+
+import (
+ "syscall"
+)
+
+func epipecheck(file *File, e int) {
+ if e == syscall.EPIPE {
+ file.nepipe++
+ if file.nepipe >= 10 {
+ Exit(syscall.EPIPE)
+ }
+ } else {
+ file.nepipe = 0
+ }
+}
+
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an Error, if any.
+func Pipe() (r *File, w *File, err Error) {
+ var p [2]int
+
+ // See ../syscall/exec.go for description of lock.
+ syscall.ForkLock.RLock()
+ e := syscall.Pipe(p[0:])
+ if iserror(e) {
+ syscall.ForkLock.RUnlock()
+ return nil, nil, NewSyscallError("pipe", e)
+ }
+ syscall.CloseOnExec(p[0])
+ syscall.CloseOnExec(p[1])
+ syscall.ForkLock.RUnlock()
+
+ return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
+
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+// If name names a valid symbolic link, the returned FileInfo describes
+// the file pointed at by the link and has fi.FollowedSymlink set to true.
+// If name names an invalid symbolic link, the returned FileInfo describes
+// the link itself and has fi.FollowedSymlink set to false.
+func Stat(name string) (fi *FileInfo, err Error) {
+ var lstat, stat syscall.Stat_t
+ e := syscall.Lstat(name, &lstat)
+ if iserror(e) {
+ return nil, &PathError{"stat", name, Errno(e)}
+ }
+ statp := &lstat
+ if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
+ e := syscall.Stat(name, &stat)
+ if !iserror(e) {
+ statp = &stat
+ }
+ }
+ return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
+}
+
+// Lstat returns the FileInfo structure describing the named file and an
+// error, if any. If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link. Lstat makes no attempt to follow the link.
+func Lstat(name string) (fi *FileInfo, err Error) {
+ var stat syscall.Stat_t
+ e := syscall.Lstat(name, &stat)
+ if iserror(e) {
+ return nil, &PathError{"lstat", name, Errno(e)}
+ }
+ return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
+}
+
+// Remove removes the named file or directory.
+func Remove(name string) Error {
+ // System call interface forces us to know
+ // whether name is a file or directory.
+ // Try both: it is cheaper on average than
+ // doing a Stat plus the right one.
+ e := syscall.Unlink(name)
+ if !iserror(e) {
+ return nil
+ }
+ e1 := syscall.Rmdir(name)
+ if !iserror(e1) {
+ return nil
+ }
+
+ // Both failed: figure out which error to return.
+ // OS X and Linux differ on whether unlink(dir)
+ // returns EISDIR, so can't use that. However,
+ // both agree that rmdir(file) returns ENOTDIR,
+ // so we can use that to decide which error is real.
+ // Rmdir might also return ENOTDIR if given a bad
+ // file path, like /etc/passwd/foo, but in that case,
+ // both errors will be ENOTDIR, so it's okay to
+ // use the error from unlink.
+ // For windows syscall.ENOTDIR is set
+ // to syscall.ERROR_DIRECTORY, hopefully it should
+ // do the trick.
+ if e1 != syscall.ENOTDIR {
+ e = e1
+ }
+ return &PathError{"remove", name, Errno(e)}
+}
+
+// LinkError records an error during a link or symlink or rename
+// system call and the paths that caused it.
+type LinkError struct {
+ Op string
+ Old string
+ New string
+ Error Error
+}
+
+func (e *LinkError) String() string {
+ return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
+}
+
+// Link creates a hard link.
+func Link(oldname, newname string) Error {
+ e := syscall.Link(oldname, newname)
+ if iserror(e) {
+ return &LinkError{"link", oldname, newname, Errno(e)}
+ }
+ return nil
+}
+
+// Symlink creates a symbolic link.
+func Symlink(oldname, newname string) Error {
+ e := syscall.Symlink(oldname, newname)
+ if iserror(e) {
+ return &LinkError{"symlink", oldname, newname, Errno(e)}
+ }
+ return nil
+}
+
+// Readlink reads the contents of a symbolic link: the destination of
+// the link. It returns the contents and an Error, if any.
+func Readlink(name string) (string, Error) {
+ for len := 128; ; len *= 2 {
+ b := make([]byte, len)
+ n, e := syscall.Readlink(name, b)
+ if iserror(e) {
+ return "", &PathError{"readlink", name, Errno(e)}
+ }
+ if n < len {
+ return string(b[0:n]), nil
+ }
+ }
+ // Silence 6g.
+ return "", nil
+}
+
+// Rename renames a file.
+func Rename(oldname, newname string) Error {
+ e := syscall.Rename(oldname, newname)
+ if iserror(e) {
+ return &LinkError{"rename", oldname, newname, Errno(e)}
+ }
+ return nil
+}
+
+// Chmod changes the mode of the named file to mode.
+// If the file is a symbolic link, it changes the mode of the link's target.
+func Chmod(name string, mode uint32) Error {
+ if e := syscall.Chmod(name, mode); iserror(e) {
+ return &PathError{"chmod", name, Errno(e)}
+ }
+ return nil
+}
+
+// Chmod changes the mode of the file to mode.
+func (f *File) Chmod(mode uint32) Error {
+ if e := syscall.Fchmod(f.fd, mode); iserror(e) {
+ return &PathError{"chmod", f.name, Errno(e)}
+ }
+ return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link's target.
+func Chown(name string, uid, gid int) Error {
+ if e := syscall.Chown(name, uid, gid); iserror(e) {
+ return &PathError{"chown", name, Errno(e)}
+ }
+ return nil
+}
+
+// Lchown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link itself.
+func Lchown(name string, uid, gid int) Error {
+ if e := syscall.Lchown(name, uid, gid); iserror(e) {
+ return &PathError{"lchown", name, Errno(e)}
+ }
+ return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+func (f *File) Chown(uid, gid int) Error {
+ if e := syscall.Fchown(f.fd, uid, gid); iserror(e) {
+ return &PathError{"chown", f.name, Errno(e)}
+ }
+ return nil
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+func (f *File) Truncate(size int64) Error {
+ if e := syscall.Ftruncate(f.fd, size); iserror(e) {
+ return &PathError{"truncate", f.name, Errno(e)}
+ }
+ return nil
+}
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (file *File) Sync() (err Error) {
+ if file == nil {
+ return EINVAL
+ }
+ if e := syscall.Fsync(file.fd); iserror(e) {
+ return NewSyscallError("fsync", e)
+ }
+ return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The argument times are in nanoseconds, although the underlying
+// filesystem may truncate or round the values to a more
+// coarse time unit.
+func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
+ var utimes [2]syscall.Timeval
+ utimes[0] = syscall.NsecToTimeval(atime_ns)
+ utimes[1] = syscall.NsecToTimeval(mtime_ns)
+ if e := syscall.Utimes(name, utimes[0:]); iserror(e) {
+ return &PathError{"chtimes", name, Errno(e)}
+ }
+ return nil
+}
// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
const DevNull = "/dev/null"
-// Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.)
-// if applicable. If successful, methods on the returned File can be used for I/O.
+// OpenFile is the generalized open call; most users will use Open
+// or Create instead. It opens the named file with specified flag
+// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful,
+// methods on the returned File can be used for I/O.
// It returns the File and an Error, if any.
-func Open(name string, flag int, perm uint32) (file *File, err Error) {
+func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm)
if e != 0 {
return nil, &PathError{"open", name, Errno(e)}
if len(parent) >= 1024 { // Sanity check
return "", ENAMETOOLONG
}
- fd, err := Open(parent, O_RDONLY, 0)
+ fd, err := Open(parent)
if err != nil {
return "", err
}
// Create a file
// This should add at least one event to the inotify event queue
- _, err = os.Open(testFile, os.O_WRONLY|os.O_CREAT, 0666)
+ _, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
t.Fatalf("creating test file failed: %s", err)
}
)
var dot = []string{
+ "dir_unix.go",
"env_unix.go",
"error.go",
"file.go",
}()
func size(name string, t *testing.T) int64 {
- file, err := Open(name, O_RDONLY, 0)
+ file, err := Open(name)
defer file.Close()
if err != nil {
t.Fatal("open failed:", err)
func TestFstat(t *testing.T) {
path := sfdir + "/" + sfname
- file, err1 := Open(path, O_RDONLY, 0)
+ file, err1 := Open(path)
defer file.Close()
if err1 != nil {
t.Fatal("open failed:", err1)
}
func testReaddirnames(dir string, contents []string, t *testing.T) {
- file, err := Open(dir, O_RDONLY, 0)
+ file, err := Open(dir)
defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
}
func testReaddir(dir string, contents []string, t *testing.T) {
- file, err := Open(dir, O_RDONLY, 0)
+ file, err := Open(dir)
defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
if syscall.OS == "windows" {
dir = Getenv("SystemRoot") + "\\system32"
}
- file, err := Open(dir, O_RDONLY, 0)
+ file, err := Open(dir)
defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
if err1 != nil {
t.Fatalf("readdirnames %q failed: %v", dir, err1)
}
- file1, err2 := Open(dir, O_RDONLY, 0)
+ file1, err2 := Open(dir)
if err2 != nil {
t.Fatalf("open %q failed: %v", dir, err2)
}
}
from, to := "hardlinktestfrom", "hardlinktestto"
Remove(from) // Just in case.
- file, err := Open(to, O_CREAT|O_WRONLY, 0666)
+ file, err := Create(to)
if err != nil {
t.Fatalf("open %q failed: %v", to, err)
}
}
from, to := "symlinktestfrom", "symlinktestto"
Remove(from) // Just in case.
- file, err := Open(to, O_CREAT|O_WRONLY, 0666)
+ file, err := Create(to)
if err != nil {
t.Fatalf("open %q failed: %v", to, err)
}
if s != to {
t.Fatalf("after symlink %q != %q", s, to)
}
- file, err = Open(from, O_RDONLY, 0)
+ file, err = Open(from)
if err != nil {
t.Fatalf("open %q failed: %v", from, err)
}
func TestRename(t *testing.T) {
from, to := "renamefrom", "renameto"
Remove(to) // Just in case.
- file, err := Open(from, O_CREAT|O_WRONLY, 0666)
+ file, err := Create(from)
if err != nil {
t.Fatalf("open %q failed: %v", to, err)
}
if syscall.OS == "windows" {
return
}
- fd, err := Open(".", O_RDONLY, 0)
+ fd, err := Open(".")
if err != nil {
t.Fatalf("Open .: %s", err)
}
if mode == 0 {
err = Chdir(d)
} else {
- fd1, err := Open(d, O_RDONLY, 0)
+ fd1, err := Open(d)
if err != nil {
t.Errorf("Open %s: %s", d, err)
continue
func TestOpenError(t *testing.T) {
for _, tt := range openErrorTests {
- f, err := Open(tt.path, tt.mode, 0)
+ f, err := OpenFile(tt.path, tt.mode, 0)
if err == nil {
t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
f.Close()
}
func writeFile(t *testing.T, fname string, flag int, text string) string {
- f, err := Open(fname, flag, 0666)
+ f, err := OpenFile(fname, flag, 0666)
if err != nil {
t.Fatalf("Open: %v", err)
}
func TestAppend(t *testing.T) {
const f = "append.txt"
defer Remove(f)
- s := writeFile(t, f, O_CREAT|O_TRUNC|O_RDWR, "new")
+ s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
if s != "new" {
t.Fatalf("writeFile: have %q want %q", s, "new")
}
j--
}
- if j > 0 {
+ if j > 1 {
// Create parent
err = MkdirAll(path[0:j-1], perm)
if err != nil {
}
// Directory.
- fd, err := Open(path, O_RDONLY, 0)
+ fd, err := Open(path)
if err != nil {
return err
}
// Make file.
fpath := path + "/file"
- _, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
+ _, err = Create(fpath)
if err != nil {
t.Fatalf("create %q: %s", fpath, err)
}
if err := MkdirAll(path, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", path, err)
}
- fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666)
+ fd, err := Create(fpath)
if err != nil {
t.Fatalf("create %q: %s", fpath, err)
}
if err = MkdirAll(dpath, 0777); err != nil {
t.Fatalf("MkdirAll %q: %s", dpath, err)
}
- fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
+ fd, err = Create(fpath)
if err != nil {
t.Fatalf("create %q: %s", fpath, err)
}
fd.Close()
- fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
+ fd, err = Create(dpath + "/file")
if err != nil {
t.Fatalf("create %q: %s", fpath, err)
}
}
for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
- fd, err = Open(s, O_WRONLY|O_CREAT, 0666)
+ fd, err = Create(s)
if err != nil {
t.Fatalf("create %q: %s", s, err)
}
t.Errorf("MkdirAll %q: %s", path, err)
}
}
+
+func TestMkdirAllAtSlash(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ return
+ }
+ RemoveAll("/_go_os_test")
+ err := MkdirAll("/_go_os_test/dir", 0777)
+ if err != nil {
+ pathErr, ok := err.(*PathError)
+ // common for users not to be able to write to /
+ if ok && pathErr.Error == EACCES {
+ return
+ }
+ t.Fatalf(`MkdirAll "/_go_os_test/dir": %v`, err)
+ }
+ RemoveAll("/_go_os_test")
+}
// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
func Getgroups() ([]int, Error) {
- gids, errno := syscall.Getgroups()
- return gids, NewSyscallError("getgroups", errno)
+ gids, e := syscall.Getgroups()
+ return gids, NewSyscallError("getgroups", e)
}
// Exit causes the current program to exit with the given status code.
--- /dev/null
+// 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.
+
+package os
+
+import "syscall"
+
+func fileInfoFromStat(fi *FileInfo, d *Dir) *FileInfo {
+ fi.Dev = uint64(d.Qid.Vers) | uint64(d.Qid.Type<<32)
+ fi.Ino = d.Qid.Path
+
+ fi.Mode = uint32(d.Mode) & 0777
+ if (d.Mode & syscall.DMDIR) == syscall.DMDIR {
+ fi.Mode |= syscall.S_IFDIR
+ } else {
+ fi.Mode |= syscall.S_IFREG
+ }
+
+ fi.Size = int64(d.Length)
+ fi.Atime_ns = 1e9 * int64(d.Atime)
+ fi.Mtime_ns = 1e9 * int64(d.Mtime)
+ fi.Name = d.Name
+ fi.FollowedSymlink = false
+ return fi
+}
+
+// arg is an open *File or a path string.
+func dirstat(arg interface{}) (fi *FileInfo, err Error) {
+ var name string
+ nd := syscall.STATFIXLEN + 16*4
+
+ for i := 0; i < 2; i++ { /* should work by the second try */
+ buf := make([]byte, nd)
+
+ var n int
+ var e syscall.Error
+
+ switch syscallArg := arg.(type) {
+ case *File:
+ name = syscallArg.name
+ n, e = syscall.Fstat(syscallArg.fd, buf)
+ case string:
+ name = syscallArg
+ n, e = syscall.Stat(name, buf)
+ }
+
+ if e != nil {
+ return nil, &PathError{"stat", name, e}
+ }
+
+ if n < syscall.STATFIXLEN {
+ return nil, &PathError{"stat", name, Eshortstat}
+ }
+
+ ntmp, _ := gbit16(buf)
+ nd = int(ntmp)
+
+ if nd <= n {
+ d, e := UnmarshalDir(buf[:n])
+
+ if e != nil {
+ return nil, &PathError{"stat", name, e}
+ }
+
+ return fileInfoFromStat(new(FileInfo), d), nil
+ }
+ }
+
+ return nil, &PathError{"stat", name, Ebadstat}
+}
+
+
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+func Stat(name string) (fi *FileInfo, err Error) {
+ return dirstat(name)
+}
+
+// Lstat returns the FileInfo structure describing the named file and an
+// error, if any. If the file is a symbolic link (though Plan 9 does not have symbolic links),
+// the returned FileInfo describes the symbolic link. Lstat makes no attempt to follow the link.
+func Lstat(name string) (fi *FileInfo, err Error) {
+ return dirstat(name)
+}
// Hostname returns the host name reported by the kernel.
func Hostname() (name string, err Error) {
- f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0)
+ f, err := Open("/proc/sys/kernel/hostname")
if err != nil {
return "", err
}
--- /dev/null
+// 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.
+
+// Plan 9-specific
+
+package os
+
+
+func Hostname() (name string, err Error) {
+ f, err := Open("#c/sysname")
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ var buf [128]byte
+ n, err := f.Read(buf[:len(buf)-1])
+
+ if err != nil {
+ return "", err
+ }
+ if n > 0 {
+ buf[n] = 0
+ }
+ return string(buf[0:n]), nil
+}
// time is the Unix epoch.
func Time() (sec int64, nsec int64, err Error) {
var tv syscall.Timeval
- if errno := syscall.Gettimeofday(&tv); errno != 0 {
- return 0, 0, NewSyscallError("gettimeofday", errno)
+ if e := syscall.Gettimeofday(&tv); iserror(e) {
+ return 0, 0, NewSyscallError("gettimeofday", e)
}
return int64(tv.Sec), int64(tv.Usec) * 1000, err
}
// lo '-' hi matches character c for lo <= c <= hi
//
// Match requires pattern to match all of name, not just a substring.
-// The only possible error return is when pattern is malformed.
+// The only possible error return occurs when the pattern is malformed.
//
func Match(pattern, name string) (matched bool, err os.Error) {
Pattern:
// if there is no matching file. The syntax of patterns is the same
// as in Match. The pattern may describe hierarchical names such as
// /usr/*/bin/ed (assuming the Separator is '/').
+// The only possible error return occurs when the pattern is malformed.
//
-func Glob(pattern string) (matches []string) {
+func Glob(pattern string) (matches []string, err os.Error) {
if !hasMeta(pattern) {
- if _, err := os.Stat(pattern); err == nil {
- return []string{pattern}
+ if _, err = os.Stat(pattern); err != nil {
+ return
}
- return nil
+ return []string{pattern}, nil
}
dir, file := Split(pattern)
dir = dir[0 : len(dir)-1] // chop off trailing separator
}
- if hasMeta(dir) {
- for _, d := range Glob(dir) {
- matches = glob(d, file, matches)
- }
- } else {
+ if !hasMeta(dir) {
return glob(dir, file, nil)
}
- return matches
+
+ var m []string
+ m, err = Glob(dir)
+ if err != nil {
+ return
+ }
+ for _, d := range m {
+ matches, err = glob(d, file, matches)
+ if err != nil {
+ return
+ }
+ }
+ return
}
// glob searches for files matching pattern in the directory dir
-// and appends them to matches.
-func glob(dir, pattern string, matches []string) []string {
+// and appends them to matches. If the directory cannot be
+// opened, it returns the existing matches. New matches are
+// added in lexicographical order.
+// The only possible error return occurs when the pattern is malformed.
+func glob(dir, pattern string, matches []string) (m []string, e os.Error) {
+ m = matches
fi, err := os.Stat(dir)
if err != nil {
- return nil
+ return
}
if !fi.IsDirectory() {
- return matches
+ return
}
- d, err := os.Open(dir, os.O_RDONLY, 0666)
+ d, err := os.Open(dir)
if err != nil {
- return nil
+ return
}
defer d.Close()
names, err := d.Readdirnames(-1)
if err != nil {
- return nil
+ return
}
sort.SortStrings(names)
for _, n := range names {
matched, err := Match(pattern, n)
if err != nil {
- return matches
+ return m, err
}
if matched {
- matches = append(matches, Join(dir, n))
+ m = append(m, Join(dir, n))
}
}
- return matches
+ return
}
// hasMeta returns true if path contains any of the magic characters
import (
"os"
- "path/filepath"
+ . "path/filepath"
"testing"
"runtime"
)
{"[\\-x]", "x", true, nil},
{"[\\-x]", "-", true, nil},
{"[\\-x]", "a", false, nil},
- {"[]a]", "]", false, filepath.ErrBadPattern},
- {"[-]", "-", false, filepath.ErrBadPattern},
- {"[x-]", "x", false, filepath.ErrBadPattern},
- {"[x-]", "-", false, filepath.ErrBadPattern},
- {"[x-]", "z", false, filepath.ErrBadPattern},
- {"[-x]", "x", false, filepath.ErrBadPattern},
- {"[-x]", "-", false, filepath.ErrBadPattern},
- {"[-x]", "a", false, filepath.ErrBadPattern},
- {"\\", "a", false, filepath.ErrBadPattern},
- {"[a-b-c]", "a", false, filepath.ErrBadPattern},
+ {"[]a]", "]", false, ErrBadPattern},
+ {"[-]", "-", false, ErrBadPattern},
+ {"[x-]", "x", false, ErrBadPattern},
+ {"[x-]", "-", false, ErrBadPattern},
+ {"[x-]", "z", false, ErrBadPattern},
+ {"[-x]", "x", false, ErrBadPattern},
+ {"[-x]", "-", false, ErrBadPattern},
+ {"[-x]", "a", false, ErrBadPattern},
+ {"\\", "a", false, ErrBadPattern},
+ {"[a-b-c]", "a", false, ErrBadPattern},
{"*x", "xxx", true, nil},
}
return
}
for _, tt := range matchTests {
- ok, err := filepath.Match(tt.pattern, tt.s)
+ ok, err := Match(tt.pattern, tt.s)
if ok != tt.match || err != tt.err {
t.Errorf("Match(%#q, %#q) = %v, %v want %v, nil", tt.pattern, tt.s, ok, err, tt.match)
}
// contains returns true if vector contains the string s.
func contains(vector []string, s string) bool {
- s = filepath.ToSlash(s)
+ s = ToSlash(s)
for _, elem := range vector {
if elem == s {
return true
return
}
for _, tt := range globTests {
- matches := filepath.Glob(tt.pattern)
+ matches, err := Glob(tt.pattern)
+ if err != nil {
+ t.Errorf("Glob error for %q: %s", tt.pattern, err)
+ continue
+ }
if !contains(matches, tt.result) {
t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result)
}
}
}
+
+func TestGlobError(t *testing.T) {
+ _, err := Glob("[7]")
+ if err != nil {
+ t.Error("expected error for bad pattern; got none")
+ }
+}
return Clean(b.String()), nil
}
+// Abs returns an absolute representation of path.
+// If the path is not absolute it will be joined with the current
+// working directory to turn it into an absolute path. The absolute
+// path name for a given file is not guaranteed to be unique.
+func Abs(path string) (string, os.Error) {
+ if IsAbs(path) {
+ return path, nil
+ }
+ wd, err := os.Getwd()
+ if err != nil {
+ return "", err
+ }
+ return Join(wd, path), nil
+}
+
// Visitor methods are invoked for corresponding file tree entries
// visited by Walk. The parameter path is the full path of f relative
// to root.
// a list of sorted directory entries.
// Copied from io/ioutil to avoid the circular import.
func readDir(dirname string) ([]*os.FileInfo, os.Error) {
- f, err := os.Open(dirname, os.O_RDONLY, 0)
+ f, err := os.Open(dirname)
if err != nil {
return nil, err
}
--- /dev/null
+// 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 filepath
+
+import "strings"
+
+const (
+ Separator = '/' // OS-specific path separator
+ ListSeparator = 0 // OS-specific path list separator
+)
+
+// isSeparator returns true if c is a directory separator character.
+func isSeparator(c uint8) bool {
+ return Separator == c
+}
+
+// IsAbs returns true if the path is absolute.
+func IsAbs(path string) bool {
+ return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
+}
+
+// volumeName returns the leading volume name on Windows.
+// It returns "" elsewhere
+func volumeName(path string) string {
+ return ""
+}
func makeTree(t *testing.T) {
walkTree(tree, tree.name, func(path string, n *Node) {
if n.entries == nil {
- fd, err := os.Open(path, os.O_CREAT, 0660)
+ fd, err := os.Create(path)
if err != nil {
t.Errorf("makeTree: %v", err)
}
// relative
for _, d := range EvalSymlinksTests {
if p, err := filepath.EvalSymlinks(d.path); err != nil {
- t.Errorf("EvalSymlinks(%v) error: %v", d.path, err)
+ t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
} else if p != d.dest {
- t.Errorf("EvalSymlinks(%v)=%v, want %v", d.path, p, d.dest)
+ t.Errorf("EvalSymlinks(%q)=%q, want %q", d.path, p, d.dest)
}
}
// absolute
filepath.Join(testroot, d.dest),
}
if p, err := filepath.EvalSymlinks(a.path); err != nil {
- t.Errorf("EvalSymlinks(%v) error: %v", a.path, err)
+ t.Errorf("EvalSymlinks(%q) error: %v", a.path, err)
} else if p != a.dest {
- t.Errorf("EvalSymlinks(%v)=%v, want %v", a.path, p, a.dest)
+ t.Errorf("EvalSymlinks(%q)=%q, want %q", a.path, p, a.dest)
}
}
*/
}
+
+/* These tests do not work in the gccgo test environment.
+
+// Test paths relative to $GOROOT/src
+var abstests = []string{
+ "../AUTHORS",
+ "pkg/../../AUTHORS",
+ "Make.pkg",
+ "pkg/Makefile",
+
+ // Already absolute
+ "$GOROOT/src/Make.pkg",
+}
+
+func TestAbs(t *testing.T) {
+ oldwd, err := os.Getwd()
+ if err != nil {
+ t.Fatal("Getwd failed: " + err.String())
+ }
+ defer os.Chdir(oldwd)
+ goroot := os.Getenv("GOROOT")
+ cwd := filepath.Join(goroot, "src")
+ os.Chdir(cwd)
+ for _, path := range abstests {
+ path = strings.Replace(path, "$GOROOT", goroot, -1)
+ abspath, err := filepath.Abs(path)
+ if err != nil {
+ t.Errorf("Abs(%q) error: %v", path, err)
+ }
+ info, err := os.Stat(path)
+ if err != nil {
+ t.Errorf("%s: %s", path, err)
+ }
+ absinfo, err := os.Stat(abspath)
+ if err != nil || absinfo.Ino != info.Ino {
+ t.Errorf("Abs(%q)=%q, not the same file", path, abspath)
+ }
+ if !filepath.IsAbs(abspath) {
+ t.Errorf("Abs(%q)=%q, not an absolute path", path, abspath)
+ }
+ }
+}
+
+*/
}
// volumeName returns the leading volume name on Windows.
-// It returns "" on Unix.
+// It returns "" elsewhere.
func volumeName(path string) string {
return ""
}
s.Error(s, msg)
return
}
- fmt.Fprintf(os.Stderr, "%s: %s", s.Position, msg)
+ fmt.Fprintf(os.Stderr, "%s: %s\n", s.Position, msg)
}
}
-func (s *Scanner) scanLineComment() {
- ch := s.next() // read character after "//"
- for ch != '\n' {
- if ch < 0 {
- s.error("comment not terminated")
- return
+func (s *Scanner) scanComment(ch int) int {
+ // ch == '/' || ch == '*'
+ if ch == '/' {
+ // line comment
+ ch = s.next() // read character after "//"
+ for ch != '\n' && ch >= 0 {
+ ch = s.next()
}
- ch = s.next()
+ return ch
}
-}
-
-func (s *Scanner) scanGeneralComment() {
- ch := s.next() // read character after "/*"
+ // general comment
+ ch = s.next() // read character after "/*"
for {
if ch < 0 {
s.error("comment not terminated")
- return
+ break
}
ch0 := ch
ch = s.next()
if ch0 == '*' && ch == '/' {
+ ch = s.next()
break
}
}
-}
-
-
-func (s *Scanner) scanComment(ch int) {
- // ch == '/' || ch == '*'
- if ch == '/' {
- s.scanLineComment()
- return
- }
- s.scanGeneralComment()
+ return ch
}
if (ch == '/' || ch == '*') && s.Mode&ScanComments != 0 {
if s.Mode&SkipComments != 0 {
s.tokPos = -1 // don't collect token text
- s.scanComment(ch)
- ch = s.next()
+ ch = s.scanComment(ch)
goto redo
}
- s.scanComment(ch)
+ ch = s.scanComment(ch)
tok = Comment
- ch = s.next()
}
case '`':
if s.Mode&ScanRawStrings != 0 {
var f100 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
var tokenList = []token{
- {Comment, "// line comments\n"},
- {Comment, "//\n"},
- {Comment, "////\n"},
- {Comment, "// comment\n"},
- {Comment, "// /* comment */\n"},
- {Comment, "// // comment //\n"},
- {Comment, "//" + f100 + "\n"},
-
- {Comment, "// general comments\n"},
+ {Comment, "// line comments"},
+ {Comment, "//"},
+ {Comment, "////"},
+ {Comment, "// comment"},
+ {Comment, "// /* comment */"},
+ {Comment, "// // comment //"},
+ {Comment, "//" + f100},
+
+ {Comment, "// general comments"},
{Comment, "/**/"},
{Comment, "/***/"},
{Comment, "/* comment */"},
{Comment, "/*\n comment\n*/"},
{Comment, "/*" + f100 + "*/"},
- {Comment, "// identifiers\n"},
+ {Comment, "// identifiers"},
{Ident, "a"},
{Ident, "a0"},
{Ident, "foobar"},
{Ident, "bar9876"},
{Ident, f100},
- {Comment, "// decimal ints\n"},
+ {Comment, "// decimal ints"},
{Int, "0"},
{Int, "1"},
{Int, "9"},
{Int, "42"},
{Int, "1234567890"},
- {Comment, "// octal ints\n"},
+ {Comment, "// octal ints"},
{Int, "00"},
{Int, "01"},
{Int, "07"},
{Int, "042"},
{Int, "01234567"},
- {Comment, "// hexadecimal ints\n"},
+ {Comment, "// hexadecimal ints"},
{Int, "0x0"},
{Int, "0x1"},
{Int, "0xf"},
{Int, "0X123456789abcDEF"},
{Int, "0X" + f100},
- {Comment, "// floats\n"},
+ {Comment, "// floats"},
{Float, "0."},
{Float, "1."},
{Float, "42."},
{Float, "42E+10"},
{Float, "01234567890E-10"},
- {Comment, "// chars\n"},
+ {Comment, "// chars"},
{Char, `' '`},
{Char, `'a'`},
{Char, `'本'`},
{Char, `'\U00000000'`},
{Char, `'\U0000ffAB'`},
- {Comment, "// strings\n"},
+ {Comment, "// strings"},
{String, `" "`},
{String, `"a"`},
{String, `"本"`},
{String, `"\U0000ffAB"`},
{String, `"` + f100 + `"`},
- {Comment, "// raw strings\n"},
+ {Comment, "// raw strings"},
{String, "``"},
{String, "`\\`"},
{String, "`" + "\n\n/* foobar */\n\n" + "`"},
{String, "`" + f100 + "`"},
- {Comment, "// individual characters\n"},
+ {Comment, "// individual characters"},
// NUL character is not allowed
{'\x01', "\x01"},
{' ' - 1, string(' ' - 1)},
func testScan(t *testing.T, mode uint) {
- s := new(Scanner).Init(makeSource(" \t%s\t\n\r"))
+ s := new(Scanner).Init(makeSource(" \t%s\n"))
s.Mode = mode
tok := s.Scan()
line := 1
}
line += countNewlines(k.text) + 1 // each token is on a new line
}
- checkTok(t, s, line, tok, -1, "")
+ checkTok(t, s, line, tok, EOF, "")
}
pos.Line += countNewlines(k.text) + 1 // each token is on a new line
s.Scan()
}
+ // make sure there were no token-internal errors reported by scanner
+ if s.ErrorCount != 0 {
+ t.Errorf("%d errors", s.ErrorCount)
+ }
}
if tok != EOF {
t.Fatalf("tok = %s, want EOF", TokenString(tok))
}
+ if s.ErrorCount != 0 {
+ t.Errorf("%d errors", s.ErrorCount)
+ }
}
}
tok = s.Scan()
}
+ if s.ErrorCount != 0 {
+ t.Errorf("%d errors", s.ErrorCount)
+ }
}
func TestScanNext(t *testing.T) {
- s := new(Scanner).Init(bytes.NewBufferString("if a == bcd /* comment */ {\n\ta += c\n}"))
+ s := new(Scanner).Init(bytes.NewBufferString("if a == bcd /* comment */ {\n\ta += c\n} // line comment ending in eof"))
checkTok(t, s, 1, s.Scan(), Ident, "if")
checkTok(t, s, 1, s.Scan(), Ident, "a")
checkTok(t, s, 1, s.Scan(), '=', "=")
checkTok(t, s, 2, s.Scan(), Ident, "c")
checkTok(t, s, 3, s.Scan(), '}', "}")
checkTok(t, s, 3, s.Scan(), -1, "")
+ if s.ErrorCount != 0 {
+ t.Errorf("%d errors", s.ErrorCount)
+ }
}
testError(t, `"\'"`, "illegal char escape", String)
testError(t, `"abc`, "literal not terminated", String)
testError(t, "`abc", "literal not terminated", String)
- testError(t, `//`, "comment not terminated", EOF)
testError(t, `/*/`, "comment not terminated", EOF)
testError(t, `"abc`+"\x00"+`def"`, "illegal character NUL", String)
testError(t, `"abc`+"\xff"+`def"`, "illegal UTF-8 encoding", String)
for i := 10; i > 0; i-- {
checkScanPos(t, s, 1, 2, 1, EOF)
}
+ if s.ErrorCount != 0 {
+ t.Errorf("%d errors", s.ErrorCount)
+ }
// corner case: source with only a single character
s = new(Scanner).Init(bytes.NewBufferString("本"))
for i := 10; i > 0; i-- {
checkScanPos(t, s, 3, 1, 2, EOF)
}
+ if s.ErrorCount != 0 {
+ t.Errorf("%d errors", s.ErrorCount)
+ }
// positions after calling Next
s = new(Scanner).Init(bytes.NewBufferString(" foo६४ \n\n本語\n"))
for i := 10; i > 0; i-- {
checkScanPos(t, s, 22, 4, 1, EOF)
}
+ if s.ErrorCount != 0 {
+ t.Errorf("%d errors", s.ErrorCount)
+ }
// positions after calling Scan
s = new(Scanner).Init(bytes.NewBufferString("abc\n本語\n\nx"))
for i := 10; i > 0; i-- {
checkScanPos(t, s, 13, 4, 2, EOF)
}
+ if s.ErrorCount != 0 {
+ t.Errorf("%d errors", s.ErrorCount)
+ }
}
}
func TestFp(t *testing.T) {
- f, err := os.Open("testfp.txt", os.O_RDONLY, 0)
+ f, err := os.Open("testfp.txt")
if err != nil {
t.Fatal("testfp: open testfp.txt:", err.String())
}
runtime.MemProfileRate = *memProfileRate
}
if *cpuProfile != "" {
- f, err := os.Open(*cpuProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666)
+ f, err := os.Create(*cpuProfile)
if err != nil {
fmt.Fprintf(os.Stderr, "testing: %s", err)
return
pprof.StopCPUProfile() // flushes profile to disk
}
if *memProfile != "" {
- f, err := os.Open(*memProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666)
+ f, err := os.Create(*memProfile)
if err != nil {
fmt.Fprintf(os.Stderr, "testing: %s", err)
return
#if defined(HAVE_SYS_EPOLL_H)
#include <sys/epoll.h>
#endif
+#if defined(HAVE_SYS_MMAN_H)
+#include <sys/mman.h>
+#endif
#if defined(HAVE_SYS_PTRACE_H)
#include <sys/ptrace.h>
#endif
grep '^const _S_' gen-sysinfo.go | \
sed -e 's/^\(const \)_\(S_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+# Mmap constants.
+grep '^const _PROT_' gen-sysinfo.go | \
+ sed -e 's/^\(const \)_\(PROT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _MAP_' gen-sysinfo.go | \
+ sed -e 's/^\(const \)_\(MAP_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
# Process status constants.
grep '^const _W' gen-sysinfo.go |
sed -e 's/^\(const \)_\(W[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
// the manuals for the appropriate operating system.
package syscall
-import "unsafe"
+import (
+ "sync"
+ "unsafe"
+)
func libc_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 __asm__ ("syscall");
func libc_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 __asm__ ("syscall");
}
return r, 0, uintptr(GetErrno());
}
+
+// Mmap manager, for use by operating system-specific implementations.
+
+type mmapper struct {
+ sync.Mutex
+ active map[*byte][]byte // active mappings; key is last byte in mapping
+ mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, int)
+ munmap func(addr uintptr, length uintptr) int
+}
+
+func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+ if length <= 0 {
+ return nil, EINVAL
+ }
+
+ // Map the requested memory.
+ addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
+ if errno != 0 {
+ return nil, errno
+ }
+
+ // Slice memory layout
+ var sl = struct {
+ addr uintptr
+ len int
+ cap int
+ }{addr, length, length}
+
+ // Use unsafe to turn sl into a []byte.
+ b := *(*[]byte)(unsafe.Pointer(&sl))
+
+ // Register mapping in m and return it.
+ p := &b[cap(b)-1]
+ m.Lock()
+ defer m.Unlock()
+ m.active[p] = b
+ return b, 0
+}
+
+func (m *mmapper) Munmap(data []byte) (errno int) {
+ if len(data) == 0 || len(data) != cap(data) {
+ return EINVAL
+ }
+
+ // Find the base of the mapping.
+ p := &data[cap(data)-1]
+ m.Lock()
+ defer m.Unlock()
+ b := m.active[p]
+ if b == nil || &b[0] != &data[0] {
+ return EINVAL
+ }
+
+ // Unmap the memory and update m.
+ if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != 0 {
+ return errno
+ }
+ m.active[p] = nil, false
+ return 0
+}
package syscall
+import "unsafe"
+
var (
Stdin = 0
Stdout = 1
}
return
}
+
+var mapper = &mmapper{
+ active: make(map[*byte][]byte),
+ mmap: mmap,
+ munmap: munmap,
+}
+
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+ return mapper.Mmap(fd, offset, length, prot, flags)
+}
+
+func Munmap(b []byte) (errno int) {
+ return mapper.Munmap(b)
+}
+
+func libc_munmap(*byte, Size_t) int __asm__ ("munmap")
+
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
+ r0 := libc_mmap((*byte)(unsafe.Pointer(addr)), Size_t(length), prot, flag, fd, Offset_t(pos))
+ ret = uintptr(unsafe.Pointer(r0))
+ if ret + 1 == 0 {
+ errno = GetErrno()
+ }
+ return
+}
+
+func munmap(addr uintptr, length uintptr) (errno int) {
+ if libc_munmap((*byte)(unsafe.Pointer(addr)), Size_t(length)) < 0 {
+ errno = GetErrno()
+ }
+ return
+}
func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek64")
func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate64")
func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate64")
+func libc_mmap(*byte, Size_t, int, int, int, Offset_t) *byte __asm__ ("mmap64")
func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek")
func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate")
func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate")
+func libc_mmap(*byte, Size_t, int, int, int, Offset_t) *byte __asm__ ("mmap")