diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-04-07 17:09:10 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-04-07 17:09:10 +0000 |
commit | 405ca10418216fc078ecb29ff13a39c911e8d806 (patch) | |
tree | 39c2c0da7b6c220dd344f134fae07fba0d0266b2 | |
parent | a751005d50fa7347131660e562c5fd9ce3dff75d (diff) | |
download | gcc-405ca10418216fc078ecb29ff13a39c911e8d806.zip gcc-405ca10418216fc078ecb29ff13a39c911e8d806.tar.gz gcc-405ca10418216fc078ecb29ff13a39c911e8d806.tar.bz2 |
libgo: Update to current Go library.
From-SVN: r172106
110 files changed, 4609 insertions, 3137 deletions
diff --git a/libgo/MERGE b/libgo/MERGE index b78ba69..237a0c2 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -342e3b11f21a +f618e5e0991d The first line of this file holds the Mercurial revision number of the last merge done from the master library sources. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index c40456f..3c94331 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -177,10 +177,10 @@ 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 \ @@ -727,9 +727,12 @@ go_os_files = \ 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 \ @@ -932,16 +935,6 @@ go_crypto_aes_files = \ 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 \ @@ -956,6 +949,10 @@ go_crypto_cipher_files = \ 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 = \ @@ -1428,10 +1425,10 @@ libgo_go_objs = \ 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 \ @@ -2026,13 +2023,6 @@ crypto/aes/check: $(CHECK_DEPS) @$(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) @@ -2054,6 +2044,13 @@ crypto/cipher/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) @@ -2139,7 +2136,8 @@ crypto/ripemd160/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 @@ -2475,8 +2473,8 @@ http/cgi/check: $(CHECK_DEPS) @$(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 @@ -2767,14 +2765,14 @@ container/vector.gox: container/vector.lo 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 @@ -3002,10 +3000,10 @@ TEST_PACKAGES = \ 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 \ diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 10f86f1..da881d5 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -140,31 +140,30 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \ 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) @@ -624,10 +623,10 @@ toolexeclibgocontainer_DATA = \ 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 \ @@ -1087,9 +1086,12 @@ go_os_files = \ 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 \ @@ -1279,17 +1281,6 @@ go_crypto_aes_files = \ 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 \ @@ -1307,6 +1298,11 @@ go_crypto_cipher_files = \ 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 @@ -1766,10 +1762,10 @@ libgo_go_objs = \ 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 \ @@ -2008,10 +2004,10 @@ TEST_PACKAGES = \ 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 \ @@ -4436,13 +4432,6 @@ crypto/aes/check: $(CHECK_DEPS) @$(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) @@ -4464,6 +4453,13 @@ crypto/cipher/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) @@ -4549,7 +4545,8 @@ crypto/ripemd160/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 @@ -4885,8 +4882,8 @@ http/cgi/check: $(CHECK_DEPS) @$(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 @@ -5172,14 +5169,14 @@ container/vector.gox: container/vector.lo 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 diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go index 35a15f7..1b41196 100644 --- a/libgo/go/archive/tar/reader.go +++ b/libgo/go/archive/tar/reader.go @@ -95,7 +95,7 @@ func (tr *Reader) skipUnread() { 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 } } diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go index aa4c797..32fc8f9 100644 --- a/libgo/go/archive/tar/reader_test.go +++ b/libgo/go/archive/tar/reader_test.go @@ -113,7 +113,7 @@ var untarTests = []*untarTest{ 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 @@ -143,7 +143,7 @@ testLoop: } 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) } @@ -181,7 +181,7 @@ func TestPartialRead(t *testing.T) { 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) } @@ -235,7 +235,7 @@ func TestIncrementalRead(t *testing.T) { 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) } diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go index 3b265c9..543007a 100644 --- a/libgo/go/archive/zip/reader.go +++ b/libgo/go/archive/zip/reader.go @@ -49,7 +49,7 @@ func (f *File) hasDataDescriptor() bool { // 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 } @@ -73,7 +73,7 @@ func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) { 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) @@ -94,7 +94,7 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) { 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 } } diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go index eae5c5c..cd08be3 100644 --- a/libgo/go/bufio/bufio.go +++ b/libgo/go/bufio/bufio.go @@ -415,38 +415,27 @@ func (b *Writer) Buffered() int { return b.n } // 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. @@ -496,24 +485,21 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) { // 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 diff --git a/libgo/go/compress/lzw/writer_test.go b/libgo/go/compress/lzw/writer_test.go index 2e0a8de..e5815a0 100644 --- a/libgo/go/compress/lzw/writer_test.go +++ b/libgo/go/compress/lzw/writer_test.go @@ -21,7 +21,7 @@ var filenames = []string{ // 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 @@ -29,7 +29,7 @@ func testFile(t *testing.T, fn string, order Order, litWidth int) { 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 diff --git a/libgo/go/compress/zlib/writer_test.go b/libgo/go/compress/zlib/writer_test.go index 5a13ba8..7eb1cd4 100644 --- a/libgo/go/compress/zlib/writer_test.go +++ b/libgo/go/compress/zlib/writer_test.go @@ -20,7 +20,7 @@ var filenames = []string{ // 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 @@ -28,7 +28,7 @@ func testFileLevel(t *testing.T, fn string, level int) { 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 diff --git a/libgo/go/crypto/block/cbc.go b/libgo/go/crypto/block/cbc.go deleted file mode 100644 index 23229c0..0000000 --- a/libgo/go/crypto/block/cbc.go +++ /dev/null @@ -1,71 +0,0 @@ -// 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) -} diff --git a/libgo/go/crypto/block/cfb.go b/libgo/go/crypto/block/cfb.go deleted file mode 100644 index f20c0a0..0000000 --- a/libgo/go/crypto/block/cfb.go +++ /dev/null @@ -1,96 +0,0 @@ -// 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) -} diff --git a/libgo/go/crypto/block/cfb_aes_test.go b/libgo/go/crypto/block/cfb_aes_test.go deleted file mode 100644 index e400c18..0000000 --- a/libgo/go/crypto/block/cfb_aes_test.go +++ /dev/null @@ -1,311 +0,0 @@ -// 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 - } - } -} diff --git a/libgo/go/crypto/block/cipher.go b/libgo/go/crypto/block/cipher.go deleted file mode 100644 index e1099e9..0000000 --- a/libgo/go/crypto/block/cipher.go +++ /dev/null @@ -1,57 +0,0 @@ -// 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 -} diff --git a/libgo/go/crypto/block/cmac.go b/libgo/go/crypto/block/cmac.go deleted file mode 100644 index b85cde7..0000000 --- a/libgo/go/crypto/block/cmac.go +++ /dev/null @@ -1,105 +0,0 @@ -// 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) } diff --git a/libgo/go/crypto/block/cmac_aes_test.go b/libgo/go/crypto/block/cmac_aes_test.go deleted file mode 100644 index 0a4a1a4..0000000 --- a/libgo/go/crypto/block/cmac_aes_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// 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 - } - } -} diff --git a/libgo/go/crypto/block/ctr.go b/libgo/go/crypto/block/ctr.go deleted file mode 100644 index 5d65c0c..0000000 --- a/libgo/go/crypto/block/ctr.go +++ /dev/null @@ -1,67 +0,0 @@ -// 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) -} diff --git a/libgo/go/crypto/block/eax.go b/libgo/go/crypto/block/eax.go deleted file mode 100644 index 3f3b964..0000000 --- a/libgo/go/crypto/block/eax.go +++ /dev/null @@ -1,253 +0,0 @@ -// 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 -} diff --git a/libgo/go/crypto/block/eax_aes_test.go b/libgo/go/crypto/block/eax_aes_test.go deleted file mode 100644 index 93aa771..0000000 --- a/libgo/go/crypto/block/eax_aes_test.go +++ /dev/null @@ -1,140 +0,0 @@ -// 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) - } - } -} diff --git a/libgo/go/crypto/block/ecb.go b/libgo/go/crypto/block/ecb.go deleted file mode 100644 index cf09f7c..0000000 --- a/libgo/go/crypto/block/ecb.go +++ /dev/null @@ -1,270 +0,0 @@ -// 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 -} diff --git a/libgo/go/crypto/block/ecb_aes_test.go b/libgo/go/crypto/block/ecb_aes_test.go deleted file mode 100644 index 14481d0..0000000 --- a/libgo/go/crypto/block/ecb_aes_test.go +++ /dev/null @@ -1,127 +0,0 @@ -// 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 - } - } -} diff --git a/libgo/go/crypto/block/ecb_test.go b/libgo/go/crypto/block/ecb_test.go deleted file mode 100644 index 6f79d92..0000000 --- a/libgo/go/crypto/block/ecb_test.go +++ /dev/null @@ -1,181 +0,0 @@ -// 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) - } -} diff --git a/libgo/go/crypto/block/ofb.go b/libgo/go/crypto/block/ofb.go deleted file mode 100644 index 11aaaa4..0000000 --- a/libgo/go/crypto/block/ofb.go +++ /dev/null @@ -1,60 +0,0 @@ -// 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) -} diff --git a/libgo/go/crypto/block/ofb_aes_test.go b/libgo/go/crypto/block/ofb_aes_test.go deleted file mode 100644 index 9c527a6..0000000 --- a/libgo/go/crypto/block/ofb_aes_test.go +++ /dev/null @@ -1,108 +0,0 @@ -// 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 - } - } -} diff --git a/libgo/go/crypto/block/xor.go b/libgo/go/crypto/block/xor.go deleted file mode 100644 index 9d8b172..0000000 --- a/libgo/go/crypto/block/xor.go +++ /dev/null @@ -1,124 +0,0 @@ -// 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 -} diff --git a/libgo/go/crypto/block/xor_test.go b/libgo/go/crypto/block/xor_test.go deleted file mode 100644 index 50f6bb0..0000000 --- a/libgo/go/crypto/block/xor_test.go +++ /dev/null @@ -1,168 +0,0 @@ -// 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. diff --git a/libgo/go/crypto/des/block.go b/libgo/go/crypto/des/block.go new file mode 100644 index 0000000..e18eaed --- /dev/null +++ b/libgo/go/crypto/des/block.go @@ -0,0 +1,98 @@ +// 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[:]) + } +} diff --git a/libgo/go/crypto/des/cipher.go b/libgo/go/crypto/des/cipher.go new file mode 100644 index 0000000..d17a1a7 --- /dev/null +++ b/libgo/go/crypto/des/cipher.go @@ -0,0 +1,103 @@ +// 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() +} diff --git a/libgo/go/crypto/des/const.go b/libgo/go/crypto/des/const.go new file mode 100644 index 0000000..2bd485e --- /dev/null +++ b/libgo/go/crypto/des/const.go @@ -0,0 +1,139 @@ +// 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} diff --git a/libgo/go/crypto/des/des_test.go b/libgo/go/crypto/des/des_test.go new file mode 100644 index 0000000..d1f3aa7 --- /dev/null +++ b/libgo/go/crypto/des/des_test.go @@ -0,0 +1,1497 @@ +// 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) + } + } +} diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index 1f37849..7bce1bc 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -37,7 +37,7 @@ var one = new(big.Int).SetInt64(1) // 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 } diff --git a/libgo/go/crypto/rand/rand_unix.go b/libgo/go/crypto/rand/rand_unix.go index 66b72c0..3a06aa8 100644 --- a/libgo/go/crypto/rand/rand_unix.go +++ b/libgo/go/crypto/rand/rand_unix.go @@ -32,7 +32,7 @@ func (r *devReader) Read(b []byte) (n int, err os.Error) { 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 } diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go index 2eaadee..9a71841 100644 --- a/libgo/go/crypto/rsa/pkcs1v15.go +++ b/libgo/go/crypto/rsa/pkcs1v15.go @@ -127,7 +127,7 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) { 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 } diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go index faf9149..b3b212c 100644 --- a/libgo/go/crypto/rsa/rsa.go +++ b/libgo/go/crypto/rsa/rsa.go @@ -13,6 +13,7 @@ import ( "hash" "io" "os" + "sync" ) var bigZero = big.NewInt(0) @@ -91,15 +92,21 @@ type PublicKey struct { 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) { @@ -108,16 +115,26 @@ func (priv PrivateKey) Validate() os.Error { 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) @@ -126,7 +143,7 @@ func (priv PrivateKey) Validate() os.Error { 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 { @@ -135,7 +152,7 @@ func (priv PrivateKey) Validate() os.Error { 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 @@ -191,6 +208,77 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) { 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 { @@ -321,6 +409,26 @@ func modInverse(a, n *big.Int) (ia *big.Int, ok bool) { 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) { @@ -359,7 +467,48 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E 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. diff --git a/libgo/go/crypto/rsa/rsa_test.go b/libgo/go/crypto/rsa/rsa_test.go index bf7c051..d8a936e 100644 --- a/libgo/go/crypto/rsa/rsa_test.go +++ b/libgo/go/crypto/rsa/rsa_test.go @@ -13,28 +13,48 @@ import ( ) 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) } @@ -43,6 +63,57 @@ func TestKeyGeneration(t *testing.T) { } } +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 @@ -85,10 +156,12 @@ func TestDecryptOAEP(t *testing.T) { 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 { @@ -96,7 +169,7 @@ func TestDecryptOAEP(t *testing.T) { } // 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 { diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go index ee77f94..5b8c700 100644 --- a/libgo/go/crypto/tls/generate_cert.go +++ b/libgo/go/crypto/tls/generate_cert.go @@ -50,7 +50,7 @@ func main() { 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 @@ -59,7 +59,7 @@ func main() { 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 diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go index f66449c..7de44bb 100644 --- a/libgo/go/crypto/tls/tls.go +++ b/libgo/go/crypto/tls/tls.go @@ -124,7 +124,16 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os. 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) @@ -141,11 +150,6 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os. 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") diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go index 853bcde..6825030 100644 --- a/libgo/go/crypto/x509/x509.go +++ b/libgo/go/crypto/x509/x509.go @@ -54,20 +54,21 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) { 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 } diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go index 57889e7..d9511b8 100644 --- a/libgo/go/crypto/x509/x509_test.go +++ b/libgo/go/crypto/x509/x509_test.go @@ -11,7 +11,6 @@ import ( "crypto/rsa" "encoding/hex" "encoding/pem" - "reflect" "testing" "time" ) @@ -22,7 +21,11 @@ func TestParsePKCS1PrivateKey(t *testing.T) { 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) } } diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go index e69317a..6fdcda6 100644 --- a/libgo/go/debug/elf/file.go +++ b/libgo/go/debug/elf/file.go @@ -144,7 +144,7 @@ func (e *FormatError) String() string { // 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 } @@ -228,7 +228,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { 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 } @@ -243,7 +243,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { 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 } @@ -269,7 +269,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { 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: diff --git a/libgo/go/debug/macho/file.go b/libgo/go/debug/macho/file.go index fd8da94..a777d87 100644 --- a/libgo/go/debug/macho/file.go +++ b/libgo/go/debug/macho/file.go @@ -159,7 +159,7 @@ func (e *FormatError) String() string { // 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 } diff --git a/libgo/go/debug/pe/file.go b/libgo/go/debug/pe/file.go index 1bcbdc5..6a14e50 100644 --- a/libgo/go/debug/pe/file.go +++ b/libgo/go/debug/pe/file.go @@ -87,7 +87,7 @@ func (e *FormatError) String() string { // 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 } @@ -132,7 +132,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { } 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 } @@ -140,7 +140,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { 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 @@ -149,9 +149,9 @@ func NewFile(r io.ReaderAt) (*File, os.Error) { 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) diff --git a/libgo/go/debug/proc/proc_linux.go b/libgo/go/debug/proc/proc_linux.go index 6890a22..17c8fa5 100644 --- a/libgo/go/debug/proc/proc_linux.go +++ b/libgo/go/debug/proc/proc_linux.go @@ -1184,7 +1184,7 @@ func (p *process) attachThread(tid int) (*thread, os.Error) { // 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 } diff --git a/libgo/go/exec/exec.go b/libgo/go/exec/exec.go index 44e3b65..5398eb8 100644 --- a/libgo/go/exec/exec.go +++ b/libgo/go/exec/exec.go @@ -2,9 +2,13 @@ // 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" @@ -49,7 +53,7 @@ func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) { 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 { diff --git a/libgo/go/exp/draw/x11/auth.go b/libgo/go/exp/draw/x11/auth.go index 896dedf0..d48936a 100644 --- a/libgo/go/exp/draw/x11/auth.go +++ b/libgo/go/exp/draw/x11/auth.go @@ -53,7 +53,7 @@ func readAuth(displayStr string) (name, data string, err os.Error) { } fn = home + "/.Xauthority" } - r, err := os.Open(fn, os.O_RDONLY, 0444) + r, err := os.Open(fn) if err != nil { return } diff --git a/libgo/go/exp/ogle/cmd.go b/libgo/go/exp/ogle/cmd.go index ba056e8..813d3a8 100644 --- a/libgo/go/exp/ogle/cmd.go +++ b/libgo/go/exp/ogle/cmd.go @@ -170,7 +170,7 @@ func cmdLoad(args []byte) os.Error { } // Get symbols - f, err := os.Open(fname, os.O_RDONLY, 0) + f, err := os.Open(fname) if err != nil { tproc.Detach() return err diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go index 4d308ac..3766c838 100644 --- a/libgo/go/fmt/fmt_test.go +++ b/libgo/go/fmt/fmt_test.go @@ -139,7 +139,17 @@ var fmttests = []struct { {"%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"}, diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index caaa7ac..f9d2b4f 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -235,13 +235,24 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { 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) } @@ -275,6 +286,7 @@ func (f *fmt) fmt_sX(s string) { // 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 + "`" diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go index 4e14fda..4b68051 100644 --- a/libgo/go/fmt/print.go +++ b/libgo/go/fmt/print.go @@ -520,12 +520,14 @@ func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interf } 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()) @@ -534,7 +536,7 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt if u == 0 { p.buf.Write(nilBytes) } else { - p.fmt0x64(uint64(v.Get()), true) + p.fmt0x64(uint64(u), true) } p.add(')') } else { @@ -811,7 +813,7 @@ BigSwitch: 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) diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go index fc4ae09..b4780e0 100644 --- a/libgo/go/go/parser/interface.go +++ b/libgo/go/go/parser/interface.go @@ -183,7 +183,7 @@ func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[st // 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 } diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go index ad7e4cd..84a0da6 100644 --- a/libgo/go/go/parser/parser.go +++ b/libgo/go/go/parser/parser.go @@ -332,7 +332,7 @@ func (p *parser) next() { 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 { @@ -2016,16 +2016,18 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec { } 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 } @@ -2207,6 +2209,9 @@ func (p *parser) parseFile() *ast.File { // 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 diff --git a/libgo/go/html/parse_test.go b/libgo/go/html/parse_test.go index d153533..fe95543 100644 --- a/libgo/go/html/parse_test.go +++ b/libgo/go/html/parse_test.go @@ -28,7 +28,7 @@ func pipeErr(err os.Error) io.Reader { } 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 diff --git a/libgo/go/http/fs.go b/libgo/go/http/fs.go index 8b5c477..c5efffc 100644 --- a/libgo/go/http/fs.go +++ b/libgo/go/http/fs.go @@ -72,7 +72,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { 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) @@ -113,7 +113,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { // 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() @@ -134,21 +134,23 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { 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. @@ -163,7 +165,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) { } 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 } diff --git a/libgo/go/http/fs_test.go b/libgo/go/http/fs_test.go index a89c76d..692b986 100644 --- a/libgo/go/http/fs_test.go +++ b/libgo/go/http/fs_test.go @@ -85,6 +85,30 @@ func TestServeFile(t *testing.T) { } } +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 { diff --git a/libgo/go/http/httptest/server.go b/libgo/go/http/httptest/server.go index 6e825a8..8e385d0 100644 --- a/libgo/go/http/httptest/server.go +++ b/libgo/go/http/httptest/server.go @@ -7,10 +7,13 @@ 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 @@ -18,6 +21,7 @@ import ( 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 @@ -35,16 +39,21 @@ func (hs *historyListener) Accept() (c net.Conn, err os.Error) { 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} @@ -52,6 +61,32 @@ func NewServer(handler http.Handler) *Server { 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() @@ -68,3 +103,34 @@ func (s *Server) CloseClientConnections() { 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----- +`) diff --git a/libgo/go/http/response_test.go b/libgo/go/http/response_test.go index bf63ccb..ef67fdd 100644 --- a/libgo/go/http/response_test.go +++ b/libgo/go/http/response_test.go @@ -164,6 +164,28 @@ var respTests = []respTest{ "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) { diff --git a/libgo/go/http/serve_test.go b/libgo/go/http/serve_test.go index b0e26e5..cf88955 100644 --- a/libgo/go/http/serve_test.go +++ b/libgo/go/http/serve_test.go @@ -507,3 +507,30 @@ func TestHeadResponses(t *testing.T) { 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) + } +} diff --git a/libgo/go/http/transfer.go b/libgo/go/http/transfer.go index 996e289..41614f1 100644 --- a/libgo/go/http/transfer.go +++ b/libgo/go/http/transfer.go @@ -215,7 +215,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) { } // Transfer encoding, content length - t.TransferEncoding, err = fixTransferEncoding(t.Header) + t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header) if err != nil { return err } @@ -289,13 +289,20 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) { 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" diff --git a/libgo/go/http/transport.go b/libgo/go/http/transport.go index ed7843b..797d134 100644 --- a/libgo/go/http/transport.go +++ b/libgo/go/http/transport.go @@ -24,6 +24,10 @@ import ( // 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. @@ -31,11 +35,17 @@ type Transport struct { 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. @@ -147,7 +157,7 @@ func (cm *connectMethod) proxyAuth() string { 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 } @@ -155,6 +165,14 @@ func (t *Transport) putIdleConn(pconn *persistConn) { 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) } @@ -406,24 +424,37 @@ func (pc *persistConn) readLoop() { 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 } } } @@ -494,34 +525,34 @@ func responseIsKeepAlive(res *Response) bool { // 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 } diff --git a/libgo/go/http/transport_test.go b/libgo/go/http/transport_test.go index 5c3e1cd..e46f830 100644 --- a/libgo/go/http/transport_test.go +++ b/libgo/go/http/transport_test.go @@ -85,6 +85,7 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) { 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) } @@ -154,9 +155,11 @@ func TestTransportIdleCacheKeys(t *testing.T) { 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 { @@ -164,7 +167,7 @@ func TestTransportIdleCacheKeys(t *testing.T) { } 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() @@ -173,6 +176,62 @@ func TestTransportIdleCacheKeys(t *testing.T) { } } +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() @@ -209,6 +268,63 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) { } } +// 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") diff --git a/libgo/go/http/url.go b/libgo/go/http/url.go index efd90d8..0fc0cb2 100644 --- a/libgo/go/http/url.go +++ b/libgo/go/http/url.go @@ -213,8 +213,8 @@ func urlEscape(s string, mode encoding) string { 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] diff --git a/libgo/go/http/url_test.go b/libgo/go/http/url_test.go index 0801f7f..d8863f3 100644 --- a/libgo/go/http/url_test.go +++ b/libgo/go/http/url_test.go @@ -490,7 +490,7 @@ var escapeTests = []URLEscapeTest{ }, { " ?&=#+%!<>#\"{}|\\^[]`☺\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, }, } @@ -519,7 +519,7 @@ type UserinfoTest struct { 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) { diff --git a/libgo/go/image/decode_test.go b/libgo/go/image/decode_test.go index 5b87344..0716ad9 100644 --- a/libgo/go/image/decode_test.go +++ b/libgo/go/image/decode_test.go @@ -34,7 +34,7 @@ var imageTests = []imageTest{ } 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 } diff --git a/libgo/go/image/png/reader_test.go b/libgo/go/image/png/reader_test.go index 0b2058d..efa6336 100644 --- a/libgo/go/image/png/reader_test.go +++ b/libgo/go/image/png/reader_test.go @@ -41,7 +41,7 @@ var filenamesShort = []string{ } 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 } @@ -191,7 +191,7 @@ func TestReader(t *testing.T) { 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 diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go index ed6c310..57d797e 100644 --- a/libgo/go/io/ioutil/ioutil.go +++ b/libgo/go/io/ioutil/ioutil.go @@ -28,7 +28,7 @@ func ReadAll(r io.Reader) ([]byte, os.Error) { // 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 } @@ -52,7 +52,7 @@ func ReadFile(filename string) ([]byte, os.Error) { // 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 } @@ -74,7 +74,7 @@ func (f fileInfoList) Swap(i, j int) { f[i], f[j] = f[j], f[i] } // 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 } diff --git a/libgo/go/io/ioutil/tempfile.go b/libgo/go/io/ioutil/tempfile.go index 62f8849..8e681bd 100644 --- a/libgo/go/io/ioutil/tempfile.go +++ b/libgo/go/io/ioutil/tempfile.go @@ -48,7 +48,7 @@ func TempFile(dir, prefix string) (f *os.File, err os.Error) { 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() diff --git a/libgo/go/log/log.go b/libgo/go/log/log.go index 658e3bd..33140ee 100644 --- a/libgo/go/log/log.go +++ b/libgo/go/log/log.go @@ -28,11 +28,12 @@ const ( // 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 @@ -40,10 +41,11 @@ const ( // 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 @@ -54,7 +56,7 @@ func New(out io.Writer, prefix string, flag int) *Logger { 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. @@ -81,7 +83,7 @@ func itoa(buf *bytes.Buffer, i int, wid int) { } } -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) @@ -107,21 +109,15 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) { } } 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(':') @@ -138,15 +134,26 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) { // 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 } @@ -203,19 +210,49 @@ func (l *Logger) Panicln(v ...interface{}) { 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. diff --git a/libgo/go/log/log_test.go b/libgo/go/log/log_test.go index bd4d1a9..72ebf39 100644 --- a/libgo/go/log/log_test.go +++ b/libgo/go/log/log_test.go @@ -84,3 +84,36 @@ func TestOutput(t *testing.T) { 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") + } +} diff --git a/libgo/go/mime/type.go b/libgo/go/mime/type.go index a10b780..6fe0ed5 100644 --- a/libgo/go/mime/type.go +++ b/libgo/go/mime/type.go @@ -33,7 +33,7 @@ var mimeTypes = map[string]string{ 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 } diff --git a/libgo/go/net/hosts.go b/libgo/go/net/hosts.go index 8525f57..d75e9e0 100644 --- a/libgo/go/net/hosts.go +++ b/libgo/go/net/hosts.go @@ -59,7 +59,7 @@ func readHosts() { } } -// 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() @@ -72,7 +72,7 @@ func lookupStaticHost(host string) []string { 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() diff --git a/libgo/go/net/parse.go b/libgo/go/net/parse.go index 2bc0db4..de46830 100644 --- a/libgo/go/net/parse.go +++ b/libgo/go/net/parse.go @@ -63,7 +63,7 @@ func (f *file) readLine() (s string, ok bool) { } 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 } diff --git a/libgo/go/net/parse_test.go b/libgo/go/net/parse_test.go index 2b7784e..226f354 100644 --- a/libgo/go/net/parse_test.go +++ b/libgo/go/net/parse_test.go @@ -18,7 +18,7 @@ func TestReadLine(t *testing.T) { } 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) } diff --git a/libgo/go/net/resolv_windows.go b/libgo/go/net/resolv_windows.go index f3d854f..000c306 100644 --- a/libgo/go/net/resolv_windows.go +++ b/libgo/go/net/resolv_windows.go @@ -14,26 +14,51 @@ import ( 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 { @@ -62,7 +87,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os. 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" diff --git a/libgo/go/os/dir_plan9.go b/libgo/go/os/dir_plan9.go new file mode 100644 index 0000000..7bb0642 --- /dev/null +++ b/libgo/go/os/dir_plan9.go @@ -0,0 +1,300 @@ +// 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 +} diff --git a/libgo/go/os/dir_unix.go b/libgo/go/os/dir_unix.go new file mode 100644 index 0000000..f5b8223 --- /dev/null +++ b/libgo/go/os/dir_unix.go @@ -0,0 +1,54 @@ +// 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 +} diff --git a/libgo/go/os/env_plan9.go b/libgo/go/os/env_plan9.go new file mode 100644 index 0000000..14df55e --- /dev/null +++ b/libgo/go/os/env_plan9.go @@ -0,0 +1,91 @@ +// 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" +} diff --git a/libgo/go/os/error.go b/libgo/go/os/error.go index 635a3fe..2c4516c 100644 --- a/libgo/go/os/error.go +++ b/libgo/go/os/error.go @@ -4,8 +4,6 @@ package os -import syscall "syscall" - // An Error can represent any printable error condition. type Error interface { String() string @@ -26,63 +24,6 @@ func (e ErrorString) Timeout() bool { return false } // 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 @@ -91,25 +32,3 @@ type PathError struct { } 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)} -} diff --git a/libgo/go/os/error_plan9.go b/libgo/go/os/error_plan9.go new file mode 100644 index 0000000..d657586 --- /dev/null +++ b/libgo/go/os/error_plan9.go @@ -0,0 +1,57 @@ +// 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 } diff --git a/libgo/go/os/error_posix.go b/libgo/go/os/error_posix.go new file mode 100644 index 0000000..0ee34e4 --- /dev/null +++ b/libgo/go/os/error_posix.go @@ -0,0 +1,90 @@ +// 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 +} diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go index 9d80ccf..f62caf9 100644 --- a/libgo/go/os/exec.go +++ b/libgo/go/os/exec.go @@ -39,126 +39,6 @@ type ProcAttr struct { 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() } diff --git a/libgo/go/os/exec_plan9.go b/libgo/go/os/exec_plan9.go new file mode 100644 index 0000000..11874ab --- /dev/null +++ b/libgo/go/os/exec_plan9.go @@ -0,0 +1,114 @@ +// 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 +} diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go new file mode 100644 index 0000000..9102dc0 --- /dev/null +++ b/libgo/go/os/exec_posix.go @@ -0,0 +1,127 @@ +// 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 +} diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go index 3f73f1d..3aad802 100644 --- a/libgo/go/os/file.go +++ b/libgo/go/os/file.go @@ -51,14 +51,20 @@ const ( 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 @@ -83,10 +89,10 @@ func (file *File) Read(b []byte) (n int, err Error) { 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 @@ -102,10 +108,10 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) { } 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 } @@ -127,15 +133,10 @@ func (file *File) Write(b []byte) (n int, err Error) { 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 @@ -150,7 +151,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) { } 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 } @@ -167,10 +168,10 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) { // 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 @@ -187,71 +188,19 @@ func (file *File) WriteString(s string) (ret int, err Error) { 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 @@ -260,179 +209,25 @@ func Chdir(dir string) Error { // 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) } diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go new file mode 100644 index 0000000..b79256c5 --- /dev/null +++ b/libgo/go/os/file_plan9.go @@ -0,0 +1,233 @@ +// 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 +} diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go new file mode 100644 index 0000000..5151df4 --- /dev/null +++ b/libgo/go/os/file_posix.go @@ -0,0 +1,246 @@ +// 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 +} diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go index 01268e5..f80f1d5 100644 --- a/libgo/go/os/file_unix.go +++ b/libgo/go/os/file_unix.go @@ -19,10 +19,12 @@ type dirInfo struct { // 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)} diff --git a/libgo/go/os/getwd.go b/libgo/go/os/getwd.go index 49aaea8..4c142ad 100644 --- a/libgo/go/os/getwd.go +++ b/libgo/go/os/getwd.go @@ -54,7 +54,7 @@ func Getwd() (string, Error) { if len(parent) >= 1024 { // Sanity check return "", ENAMETOOLONG } - fd, err := Open(parent, O_RDONLY, 0) + fd, err := Open(parent) if err != nil { return "", err } diff --git a/libgo/go/os/inotify/inotify_linux_test.go b/libgo/go/os/inotify/inotify_linux_test.go index 79c3bfa..f5d1f83 100644 --- a/libgo/go/os/inotify/inotify_linux_test.go +++ b/libgo/go/os/inotify/inotify_linux_test.go @@ -51,7 +51,7 @@ func TestInotifyEvents(t *testing.T) { // 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) } diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go index bb1b8e3..607a11b 100644 --- a/libgo/go/os/os_test.go +++ b/libgo/go/os/os_test.go @@ -17,6 +17,7 @@ import ( ) var dot = []string{ + "dir_unix.go", "env_unix.go", "error.go", "file.go", @@ -56,7 +57,7 @@ var sysdir = func() (sd *sysDir) { }() 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) @@ -121,7 +122,7 @@ func TestStat(t *testing.T) { 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) @@ -155,7 +156,7 @@ func TestLstat(t *testing.T) { } 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) @@ -184,7 +185,7 @@ func testReaddirnames(dir string, contents []string, t *testing.T) { } 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) @@ -245,7 +246,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) { 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) @@ -254,7 +255,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) { 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) } @@ -273,7 +274,7 @@ func TestHardLink(t *testing.T) { } 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) } @@ -306,7 +307,7 @@ func TestSymLink(t *testing.T) { } 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) } @@ -354,7 +355,7 @@ func TestSymLink(t *testing.T) { 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) } @@ -388,7 +389,7 @@ func TestLongSymlink(t *testing.T) { 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) } @@ -615,7 +616,7 @@ func TestChdirAndGetwd(t *testing.T) { if syscall.OS == "windows" { return } - fd, err := Open(".", O_RDONLY, 0) + fd, err := Open(".") if err != nil { t.Fatalf("Open .: %s", err) } @@ -627,7 +628,7 @@ func TestChdirAndGetwd(t *testing.T) { 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 @@ -736,7 +737,7 @@ var openErrorTests = []openErrorTest{ 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() @@ -842,7 +843,7 @@ func TestWriteAt(t *testing.T) { } 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) } @@ -861,7 +862,7 @@ func writeFile(t *testing.T, fname string, flag int, text string) string { 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") } diff --git a/libgo/go/os/path.go b/libgo/go/os/path.go index b762971..0eb3ee5 100644 --- a/libgo/go/os/path.go +++ b/libgo/go/os/path.go @@ -33,7 +33,7 @@ func MkdirAll(path string, perm uint32) Error { j-- } - if j > 0 { + if j > 1 { // Create parent err = MkdirAll(path[0:j-1], perm) if err != nil { @@ -80,7 +80,7 @@ func RemoveAll(path string) Error { } // Directory. - fd, err := Open(path, O_RDONLY, 0) + fd, err := Open(path) if err != nil { return err } diff --git a/libgo/go/os/path_test.go b/libgo/go/os/path_test.go index 799e3ec..483bb63 100644 --- a/libgo/go/os/path_test.go +++ b/libgo/go/os/path_test.go @@ -29,7 +29,7 @@ func TestMkdirAll(t *testing.T) { // 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) } @@ -72,7 +72,7 @@ func TestRemoveAll(t *testing.T) { 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) } @@ -88,12 +88,12 @@ func TestRemoveAll(t *testing.T) { 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) } @@ -121,7 +121,7 @@ func TestRemoveAll(t *testing.T) { } 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) } @@ -179,3 +179,20 @@ func TestMkdirAllWithSymlink(t *testing.T) { 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") +} diff --git a/libgo/go/os/proc.go b/libgo/go/os/proc.go index dfddab6..481ef60 100644 --- a/libgo/go/os/proc.go +++ b/libgo/go/os/proc.go @@ -26,8 +26,8 @@ func Getegid() int { return syscall.Getegid() } // 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. diff --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go new file mode 100644 index 0000000..e96749d --- /dev/null +++ b/libgo/go/os/stat_plan9.go @@ -0,0 +1,84 @@ +// 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) +} diff --git a/libgo/go/os/sys_linux.go b/libgo/go/os/sys_linux.go index b82d295..408d667 100644 --- a/libgo/go/os/sys_linux.go +++ b/libgo/go/os/sys_linux.go @@ -9,7 +9,7 @@ package os // 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 } diff --git a/libgo/go/os/sys_plan9.go b/libgo/go/os/sys_plan9.go new file mode 100644 index 0000000..f6af28b --- /dev/null +++ b/libgo/go/os/sys_plan9.go @@ -0,0 +1,27 @@ +// 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 +} diff --git a/libgo/go/os/time.go b/libgo/go/os/time.go index 380345f..8e87a49 100644 --- a/libgo/go/os/time.go +++ b/libgo/go/os/time.go @@ -13,8 +13,8 @@ import "syscall" // 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 } diff --git a/libgo/go/path/filepath/match.go b/libgo/go/path/filepath/match.go index ad4053f..a05bb5f 100644 --- a/libgo/go/path/filepath/match.go +++ b/libgo/go/path/filepath/match.go @@ -32,7 +32,7 @@ var ErrBadPattern = os.NewError("syntax error in pattern") // 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: @@ -211,13 +211,14 @@ func getEsc(chunk string) (r int, nchunk string, err os.Error) { // 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) @@ -230,48 +231,60 @@ func Glob(pattern string) (matches []string) { 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 diff --git a/libgo/go/path/filepath/match_test.go b/libgo/go/path/filepath/match_test.go index a1e6316..0b594fa 100644 --- a/libgo/go/path/filepath/match_test.go +++ b/libgo/go/path/filepath/match_test.go @@ -6,7 +6,7 @@ package filepath_test import ( "os" - "path/filepath" + . "path/filepath" "testing" "runtime" ) @@ -56,16 +56,16 @@ var matchTests = []MatchTest{ {"[\\-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}, } @@ -75,7 +75,7 @@ func TestMatch(t *testing.T) { 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) } @@ -84,7 +84,7 @@ func TestMatch(t *testing.T) { // 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 @@ -109,9 +109,20 @@ func TestGlob(t *testing.T) { 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") + } +} diff --git a/libgo/go/path/filepath/path.go b/libgo/go/path/filepath/path.go index 6cd6cf2..de673a7 100644 --- a/libgo/go/path/filepath/path.go +++ b/libgo/go/path/filepath/path.go @@ -231,6 +231,21 @@ func EvalSymlinks(path string) (string, os.Error) { 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. @@ -265,7 +280,7 @@ func walk(path string, f *os.FileInfo, v Visitor, errors chan<- os.Error) { // 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 } diff --git a/libgo/go/path/filepath/path_plan9.go b/libgo/go/path/filepath/path_plan9.go new file mode 100644 index 0000000..e400083 --- /dev/null +++ b/libgo/go/path/filepath/path_plan9.go @@ -0,0 +1,28 @@ +// 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 "" +} diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go index 0249af4..37078f6 100644 --- a/libgo/go/path/filepath/path_test.go +++ b/libgo/go/path/filepath/path_test.go @@ -248,7 +248,7 @@ func walkTree(n *Node, path string, f func(path string, n *Node)) { 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) } @@ -459,9 +459,9 @@ func TestEvalSymlinks(t *testing.T) { // 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 @@ -477,10 +477,54 @@ func TestEvalSymlinks(t *testing.T) { 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) + } + } +} + +*/ diff --git a/libgo/go/path/filepath/path_unix.go b/libgo/go/path/filepath/path_unix.go index 1bb21ec..f8ac248 100644 --- a/libgo/go/path/filepath/path_unix.go +++ b/libgo/go/path/filepath/path_unix.go @@ -22,7 +22,7 @@ func IsAbs(path string) bool { } // volumeName returns the leading volume name on Windows. -// It returns "" on Unix. +// It returns "" elsewhere. func volumeName(path string) string { return "" } diff --git a/libgo/go/scanner/scanner.go b/libgo/go/scanner/scanner.go index 2396cdd..560e595 100644 --- a/libgo/go/scanner/scanner.go +++ b/libgo/go/scanner/scanner.go @@ -331,7 +331,7 @@ func (s *Scanner) error(msg string) { s.Error(s, msg) return } - fmt.Fprintf(os.Stderr, "%s: %s", s.Position, msg) + fmt.Fprintf(os.Stderr, "%s: %s\n", s.Position, msg) } @@ -503,41 +503,32 @@ func (s *Scanner) scanChar() { } -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 } @@ -619,13 +610,11 @@ redo: 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 { diff --git a/libgo/go/scanner/scanner_test.go b/libgo/go/scanner/scanner_test.go index 002252d..cf9ad01 100644 --- a/libgo/go/scanner/scanner_test.go +++ b/libgo/go/scanner/scanner_test.go @@ -77,15 +77,15 @@ type token struct { 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 */"}, @@ -94,7 +94,7 @@ var tokenList = []token{ {Comment, "/*\n comment\n*/"}, {Comment, "/*" + f100 + "*/"}, - {Comment, "// identifiers\n"}, + {Comment, "// identifiers"}, {Ident, "a"}, {Ident, "a0"}, {Ident, "foobar"}, @@ -116,21 +116,21 @@ var tokenList = []token{ {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"}, @@ -144,7 +144,7 @@ var tokenList = []token{ {Int, "0X123456789abcDEF"}, {Int, "0X" + f100}, - {Comment, "// floats\n"}, + {Comment, "// floats"}, {Float, "0."}, {Float, "1."}, {Float, "42."}, @@ -174,7 +174,7 @@ var tokenList = []token{ {Float, "42E+10"}, {Float, "01234567890E-10"}, - {Comment, "// chars\n"}, + {Comment, "// chars"}, {Char, `' '`}, {Char, `'a'`}, {Char, `'本'`}, @@ -195,7 +195,7 @@ var tokenList = []token{ {Char, `'\U00000000'`}, {Char, `'\U0000ffAB'`}, - {Comment, "// strings\n"}, + {Comment, "// strings"}, {String, `" "`}, {String, `"a"`}, {String, `"本"`}, @@ -217,13 +217,13 @@ var tokenList = []token{ {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)}, @@ -276,7 +276,7 @@ func countNewlines(s string) int { 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 @@ -287,7 +287,7 @@ func testScan(t *testing.T, mode uint) { } line += countNewlines(k.text) + 1 // each token is on a new line } - checkTok(t, s, line, tok, -1, "") + checkTok(t, s, line, tok, EOF, "") } @@ -317,6 +317,10 @@ func TestPosition(t *testing.T) { 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) + } } @@ -336,6 +340,9 @@ func TestScanZeroMode(t *testing.T) { if tok != EOF { t.Fatalf("tok = %s, want EOF", TokenString(tok)) } + if s.ErrorCount != 0 { + t.Errorf("%d errors", s.ErrorCount) + } } @@ -350,6 +357,9 @@ func testScanSelectedMode(t *testing.T, mode uint, class int) { } tok = s.Scan() } + if s.ErrorCount != 0 { + t.Errorf("%d errors", s.ErrorCount) + } } @@ -367,7 +377,7 @@ func TestScanSelectedMask(t *testing.T) { 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(), '=', "=") @@ -382,6 +392,9 @@ func TestScanNext(t *testing.T) { 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) + } } @@ -441,7 +454,6 @@ func TestError(t *testing.T) { 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) @@ -493,6 +505,9 @@ func TestPos(t *testing.T) { 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("本")) @@ -502,6 +517,9 @@ func TestPos(t *testing.T) { 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")) @@ -524,6 +542,9 @@ func TestPos(t *testing.T) { 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")) @@ -543,4 +564,7 @@ func TestPos(t *testing.T) { for i := 10; i > 0; i-- { checkScanPos(t, s, 13, 4, 2, EOF) } + if s.ErrorCount != 0 { + t.Errorf("%d errors", s.ErrorCount) + } } diff --git a/libgo/go/strconv/fp_test.go b/libgo/go/strconv/fp_test.go index 305adcc..34baeee 100644 --- a/libgo/go/strconv/fp_test.go +++ b/libgo/go/strconv/fp_test.go @@ -94,7 +94,7 @@ func myatof32(s string) (f float32, ok bool) { } 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()) } diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go index 6d303cc..1e65528 100644 --- a/libgo/go/testing/testing.go +++ b/libgo/go/testing/testing.go @@ -212,7 +212,7 @@ func before() { 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 @@ -233,7 +233,7 @@ func after() { 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 diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh index 77d699e..05f4af0 100755 --- a/libgo/mksysinfo.sh +++ b/libgo/mksysinfo.sh @@ -57,6 +57,9 @@ cat > sysinfo.c <<EOF #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 @@ -131,6 +134,12 @@ grep '^const _SYS_' gen-sysinfo.go | \ 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} diff --git a/libgo/syscalls/syscall.go b/libgo/syscalls/syscall.go index fa7d9d0..8c7a7ba 100644 --- a/libgo/syscalls/syscall.go +++ b/libgo/syscalls/syscall.go @@ -13,7 +13,10 @@ // 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"); @@ -46,3 +49,63 @@ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { } 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 +} diff --git a/libgo/syscalls/syscall_unix.go b/libgo/syscalls/syscall_unix.go index a29b6b5..b5a660e 100644 --- a/libgo/syscalls/syscall_unix.go +++ b/libgo/syscalls/syscall_unix.go @@ -4,6 +4,8 @@ package syscall +import "unsafe" + var ( Stdin = 0 Stdout = 1 @@ -22,3 +24,35 @@ func Uname(buf *Utsname) (errno int) { } 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 +} diff --git a/libgo/syscalls/sysfile_largefile.go b/libgo/syscalls/sysfile_largefile.go index 963a624..c0c4e55 100644 --- a/libgo/syscalls/sysfile_largefile.go +++ b/libgo/syscalls/sysfile_largefile.go @@ -11,3 +11,4 @@ func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm 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") diff --git a/libgo/syscalls/sysfile_regfile.go b/libgo/syscalls/sysfile_regfile.go index 731c59c..fcbf254 100644 --- a/libgo/syscalls/sysfile_regfile.go +++ b/libgo/syscalls/sysfile_regfile.go @@ -11,3 +11,4 @@ func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm 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") |