OSDN Git Service

libgo: Update to weekly.2012-01-15.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Jan 2012 20:56:26 +0000 (20:56 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Jan 2012 20:56:26 +0000 (20:56 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183539 138bc75d-0d04-0410-961f-82ee72b054a4

192 files changed:
libgo/MERGE
libgo/Makefile.am
libgo/Makefile.in
libgo/config.h.in
libgo/configure
libgo/configure.ac
libgo/go/bytes/buffer.go
libgo/go/bytes/buffer_test.go
libgo/go/crypto/openpgp/armor/armor.go
libgo/go/crypto/openpgp/errors/errors.go [moved from libgo/go/crypto/openpgp/error/error.go with 94% similarity]
libgo/go/crypto/openpgp/keys.go
libgo/go/crypto/openpgp/packet/compressed.go
libgo/go/crypto/openpgp/packet/encrypted_key.go
libgo/go/crypto/openpgp/packet/one_pass_signature.go
libgo/go/crypto/openpgp/packet/packet.go
libgo/go/crypto/openpgp/packet/packet_test.go
libgo/go/crypto/openpgp/packet/private_key.go
libgo/go/crypto/openpgp/packet/public_key.go
libgo/go/crypto/openpgp/packet/reader.go
libgo/go/crypto/openpgp/packet/signature.go
libgo/go/crypto/openpgp/packet/symmetric_key_encrypted.go
libgo/go/crypto/openpgp/packet/symmetrically_encrypted.go
libgo/go/crypto/openpgp/packet/symmetrically_encrypted_test.go
libgo/go/crypto/openpgp/read.go
libgo/go/crypto/openpgp/read_test.go
libgo/go/crypto/openpgp/s2k/s2k.go
libgo/go/crypto/openpgp/write.go
libgo/go/crypto/openpgp/write_test.go
libgo/go/crypto/tls/common.go
libgo/go/crypto/tls/generate_cert.go
libgo/go/crypto/tls/handshake_client.go
libgo/go/crypto/tls/handshake_messages.go
libgo/go/crypto/tls/handshake_server.go
libgo/go/crypto/tls/handshake_server_test.go
libgo/go/crypto/tls/tls.go
libgo/go/crypto/x509/cert_pool.go
libgo/go/debug/gosym/pclntab_test.go
libgo/go/encoding/asn1/asn1.go
libgo/go/encoding/asn1/asn1_test.go
libgo/go/encoding/asn1/marshal_test.go
libgo/go/encoding/gob/decode.go
libgo/go/encoding/gob/encoder_test.go
libgo/go/encoding/json/decode.go
libgo/go/encoding/json/decode_test.go
libgo/go/encoding/json/encode.go
libgo/go/encoding/json/encode_test.go
libgo/go/encoding/xml/atom_test.go
libgo/go/encoding/xml/embed_test.go [deleted file]
libgo/go/encoding/xml/marshal.go
libgo/go/encoding/xml/marshal_test.go
libgo/go/encoding/xml/read.go
libgo/go/encoding/xml/read_test.go
libgo/go/encoding/xml/typeinfo.go [new file with mode: 0644]
libgo/go/encoding/xml/xml_test.go
libgo/go/exp/norm/input.go
libgo/go/exp/norm/normalize.go
libgo/go/exp/norm/normalize_test.go
libgo/go/exp/norm/readwriter.go
libgo/go/exp/proxy/direct.go [new file with mode: 0644]
libgo/go/exp/proxy/per_host.go [new file with mode: 0644]
libgo/go/exp/proxy/per_host_test.go [new file with mode: 0644]
libgo/go/exp/proxy/proxy.go [new file with mode: 0644]
libgo/go/exp/proxy/proxy_test.go [new file with mode: 0644]
libgo/go/exp/proxy/socks5.go [new file with mode: 0644]
libgo/go/exp/sql/convert_test.go
libgo/go/exp/sql/driver/driver.go
libgo/go/exp/sql/driver/types.go
libgo/go/exp/sql/driver/types_test.go
libgo/go/exp/sql/fakedb_test.go
libgo/go/exp/sql/sql.go
libgo/go/exp/sql/sql_test.go
libgo/go/exp/ssh/client.go
libgo/go/exp/ssh/doc.go
libgo/go/exp/ssh/server_shell.go [deleted file]
libgo/go/exp/ssh/server_shell_test.go [deleted file]
libgo/go/exp/ssh/server_terminal.go [new file with mode: 0644]
libgo/go/exp/ssh/session_test.go
libgo/go/exp/ssh/transport.go
libgo/go/exp/terminal/terminal.go
libgo/go/exp/terminal/terminal_test.go
libgo/go/exp/types/check_test.go
libgo/go/exp/types/universe.go
libgo/go/flag/flag.go
libgo/go/flag/flag_test.go
libgo/go/fmt/doc.go
libgo/go/fmt/fmt_test.go
libgo/go/go/ast/ast.go
libgo/go/go/ast/filter.go
libgo/go/go/ast/print.go
libgo/go/go/ast/print_test.go
libgo/go/go/ast/scope.go
libgo/go/go/build/build.go
libgo/go/go/build/dir.go
libgo/go/go/build/path.go
libgo/go/go/doc/comment.go
libgo/go/go/doc/doc.go
libgo/go/go/doc/doc_test.go [new file with mode: 0644]
libgo/go/go/doc/example.go
libgo/go/go/doc/exports.go
libgo/go/go/doc/filter.go
libgo/go/go/doc/headscan.go
libgo/go/go/doc/reader.go [new file with mode: 0644]
libgo/go/go/parser/interface.go
libgo/go/go/parser/parser.go
libgo/go/go/parser/parser_test.go
libgo/go/go/printer/printer.go
libgo/go/go/printer/printer_test.go
libgo/go/go/scanner/scanner.go
libgo/go/go/scanner/scanner_test.go
libgo/go/go/token/token.go
libgo/go/html/foreign.go
libgo/go/html/node.go
libgo/go/html/parse.go
libgo/go/html/parse_test.go
libgo/go/html/render.go
libgo/go/html/template/escape_test.go
libgo/go/html/token.go
libgo/go/image/names.go
libgo/go/log/syslog/syslog.go
libgo/go/math/all_test.go
libgo/go/math/big/nat.go
libgo/go/net/file_test.go
libgo/go/net/http/cookie.go
libgo/go/net/http/request.go
libgo/go/net/interface.go
libgo/go/net/iprawsock_plan9.go
libgo/go/net/iprawsock_posix.go
libgo/go/net/ipsock_posix.go
libgo/go/net/multicast_test.go
libgo/go/net/rpc/server_test.go
libgo/go/net/server_test.go
libgo/go/net/sock.go
libgo/go/net/sock_bsd.go
libgo/go/net/sock_linux.go
libgo/go/net/sock_windows.go
libgo/go/net/sockopt.go [new file with mode: 0644]
libgo/go/net/sockopt_bsd.go [new file with mode: 0644]
libgo/go/net/sockopt_linux.go [new file with mode: 0644]
libgo/go/net/sockopt_windows.go [new file with mode: 0644]
libgo/go/net/sockoptip.go [new file with mode: 0644]
libgo/go/net/sockoptip_bsd.go [new file with mode: 0644]
libgo/go/net/sockoptip_darwin.go [new file with mode: 0644]
libgo/go/net/sockoptip_freebsd.go [new file with mode: 0644]
libgo/go/net/sockoptip_linux.go [new file with mode: 0644]
libgo/go/net/sockoptip_openbsd.go [new file with mode: 0644]
libgo/go/net/sockoptip_windows.go [new file with mode: 0644]
libgo/go/net/tcpsock_posix.go
libgo/go/net/textproto/reader.go
libgo/go/net/textproto/reader_test.go
libgo/go/net/udpsock_posix.go
libgo/go/net/unicast_test.go [new file with mode: 0644]
libgo/go/net/unixsock_posix.go
libgo/go/os/env_test.go
libgo/go/os/os_test.go
libgo/go/os/os_unix_test.go
libgo/go/os/path_test.go
libgo/go/os/stat_openbsd.go
libgo/go/os/types.go
libgo/go/runtime/debug.go
libgo/go/runtime/extern.go
libgo/go/sort/sort.go
libgo/go/strconv/extfloat.go
libgo/go/strconv/fp_test.go
libgo/go/strconv/ftoa.go
libgo/go/strconv/ftoa_test.go
libgo/go/strconv/quote.go
libgo/go/strconv/quote_test.go
libgo/go/syscall/env_unix.go
libgo/go/syscall/exec_bsd.go [new file with mode: 0644]
libgo/go/syscall/exec_linux.go [new file with mode: 0644]
libgo/go/syscall/exec_unix.go
libgo/go/syscall/socket.go
libgo/go/syscall/syscall_unix.go
libgo/go/testing/benchmark.go
libgo/go/testing/testing.go
libgo/go/testing/wrapper.go [deleted file]
libgo/go/text/template/doc.go
libgo/go/text/template/exec.go
libgo/go/text/template/exec_test.go
libgo/go/time/format.go
libgo/go/time/sleep.go
libgo/go/time/tick.go
libgo/go/time/time_test.go
libgo/mksysinfo.sh
libgo/runtime/malloc.goc
libgo/runtime/malloc.h
libgo/runtime/mgc0.c
libgo/runtime/runtime.c
libgo/runtime/runtime.h
libgo/runtime/runtime1.goc
libgo/runtime/thread-linux.c
libgo/testsuite/gotest

index 96fb7f6..b72962f 100644 (file)
@@ -1,4 +1,4 @@
-4a8268927758
+354b17404643
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
index 348a1ca..770a849 100644 (file)
@@ -188,7 +188,7 @@ toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
 toolexeclibgocryptoopenpgp_DATA = \
        crypto/openpgp/armor.gox \
        crypto/openpgp/elgamal.gox \
-       crypto/openpgp/error.gox \
+       crypto/openpgp/errors.gox \
        crypto/openpgp/packet.gox \
        crypto/openpgp/s2k.gox
 
@@ -235,6 +235,7 @@ toolexeclibgoexp_DATA = \
        exp/ebnf.gox \
        $(exp_inotify_gox) \
        exp/norm.gox \
+       exp/proxy.gox \
        exp/spdy.gox \
        exp/sql.gox \
        exp/ssh.gox \
@@ -669,17 +670,25 @@ endif # !LIBGO_IS_RTEMS
 if LIBGO_IS_LINUX
 go_net_cgo_file = go/net/cgo_linux.go
 go_net_sock_file = go/net/sock_linux.go
+go_net_sockopt_file = go/net/sockopt_linux.go
+go_net_sockoptip_file = go/net/sockoptip_linux.go
 else
 if LIBGO_IS_IRIX
 go_net_cgo_file = go/net/cgo_linux.go
 go_net_sock_file = go/net/sock_linux.go
+go_net_sockopt_file = go/net/sockopt_linux.go
+go_net_sockoptip_file = go/net/sockoptip_linux.go
 else
 if LIBGO_IS_SOLARIS
 go_net_cgo_file = go/net/cgo_linux.go
 go_net_sock_file = go/net/sock_linux.go
+go_net_sockopt_file = go/net/sockopt_linux.go
+go_net_sockoptip_file = go/net/sockoptip_linux.go
 else
 go_net_cgo_file = go/net/cgo_bsd.go
 go_net_sock_file = go/net/sock_bsd.go
+go_net_sockopt_file = go/net/sockopt_bsd.go
+go_net_sockoptip_file = go/net/sockoptip_bsd.go
 endif
 endif
 endif
@@ -728,6 +737,10 @@ go_net_files = \
        $(go_net_sendfile_file) \
        go/net/sock.go \
        $(go_net_sock_file) \
+       go/net/sockopt.go \
+       $(go_net_sockopt_file) \
+       go/net/sockoptip.go \
+       $(go_net_sockoptip_file) \
        go/net/tcpsock.go \
        go/net/tcpsock_posix.go \
        go/net/udpsock.go \
@@ -890,8 +903,7 @@ go_syslog_c_files = \
 go_testing_files = \
        go/testing/benchmark.go \
        go/testing/example.go \
-       go/testing/testing.go \
-       go/testing/wrapper.go
+       go/testing/testing.go
 
 go_time_files = \
        go/time/format.go \
@@ -1061,8 +1073,8 @@ go_crypto_openpgp_armor_files = \
        go/crypto/openpgp/armor/encode.go
 go_crypto_openpgp_elgamal_files = \
        go/crypto/openpgp/elgamal/elgamal.go
-go_crypto_openpgp_error_files = \
-       go/crypto/openpgp/error/error.go
+go_crypto_openpgp_errors_files = \
+       go/crypto/openpgp/errors/errors.go
 go_crypto_openpgp_packet_files = \
        go/crypto/openpgp/packet/compressed.go \
        go/crypto/openpgp/packet/encrypted_key.go \
@@ -1142,6 +1154,7 @@ go_encoding_pem_files = \
 go_encoding_xml_files = \
        go/encoding/xml/marshal.go \
        go/encoding/xml/read.go \
+       go/encoding/xml/typeinfo.go \
        go/encoding/xml/xml.go
 
 go_exp_ebnf_files = \
@@ -1157,6 +1170,11 @@ go_exp_norm_files = \
        go/exp/norm/readwriter.go \
        go/exp/norm/tables.go \
        go/exp/norm/trie.go
+go_exp_proxy_files = \
+       go/exp/proxy/direct.go \
+       go/exp/proxy/per_host.go \
+       go/exp/proxy/proxy.go \
+       go/exp/proxy/socks5.go
 go_exp_spdy_files = \
        go/exp/spdy/read.go \
        go/exp/spdy/types.go \
@@ -1173,7 +1191,7 @@ go_exp_ssh_files = \
        go/exp/ssh/doc.go \
        go/exp/ssh/messages.go \
        go/exp/ssh/server.go \
-       go/exp/ssh/server_shell.go \
+       go/exp/ssh/server_terminal.go \
        go/exp/ssh/session.go \
        go/exp/ssh/tcpip.go \
        go/exp/ssh/transport.go
@@ -1210,7 +1228,8 @@ go_go_doc_files = \
        go/go/doc/doc.go \
        go/go/doc/example.go \
        go/go/doc/exports.go \
-       go/go/doc/filter.go
+       go/go/doc/filter.go \
+       go/go/doc/reader.go
 go_go_parser_files = \
        go/go/parser/interface.go \
        go/go/parser/parser.go
@@ -1461,8 +1480,15 @@ endif
 # Define ForkExec and Exec.
 if LIBGO_IS_RTEMS
 syscall_exec_file = go/syscall/exec_stubs.go
+syscall_exec_os_file =
+else
+if LIBGO_IS_LINUX
+syscall_exec_file = go/syscall/exec_unix.go
+syscall_exec_os_file = go/syscall/exec_linux.go
 else
 syscall_exec_file = go/syscall/exec_unix.go
+syscall_exec_os_file = go/syscall/exec_bsd.go
+endif
 endif
 
 # Define Wait4.
@@ -1573,6 +1599,7 @@ go_base_syscall_files = \
        go/syscall/syscall.go \
        $(syscall_syscall_file) \
        $(syscall_exec_file) \
+       $(syscall_exec_os_file) \
        $(syscall_wait_file) \
        $(syscall_sleep_file) \
        $(syscall_errstr_file) \
@@ -1720,7 +1747,7 @@ libgo_go_objs = \
        crypto/xtea.lo \
        crypto/openpgp/armor.lo \
        crypto/openpgp/elgamal.lo \
-       crypto/openpgp/error.lo \
+       crypto/openpgp/errors.lo \
        crypto/openpgp/packet.lo \
        crypto/openpgp/s2k.lo \
        crypto/x509/pkix.lo \
@@ -1743,6 +1770,7 @@ libgo_go_objs = \
        encoding/xml.lo \
        exp/ebnf.lo \
        exp/norm.lo \
+       exp/proxy.lo \
        exp/spdy.lo \
        exp/sql.lo \
        exp/ssh.lo \
@@ -2578,15 +2606,15 @@ crypto/openpgp/elgamal/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/openpgp/elgamal/check
 
-@go_include@ crypto/openpgp/error.lo.dep
-crypto/openpgp/error.lo.dep: $(go_crypto_openpgp_error_files)
+@go_include@ crypto/openpgp/errors.lo.dep
+crypto/openpgp/errors.lo.dep: $(go_crypto_openpgp_errors_files)
        $(BUILDDEPS)
-crypto/openpgp/error.lo: $(go_crypto_openpgp_error_files)
+crypto/openpgp/errors.lo: $(go_crypto_openpgp_errors_files)
        $(BUILDPACKAGE)
-crypto/openpgp/error/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/error
+crypto/openpgp/errors/check: $(CHECK_DEPS)
+       @$(MKDIR_P) crypto/openpgp/errors
        @$(CHECK)
-.PHONY: crypto/openpgp/error/check
+.PHONY: crypto/openpgp/errors/check
 
 @go_include@ crypto/openpgp/packet.lo.dep
 crypto/openpgp/packet.lo.dep: $(go_crypto_openpgp_packet_files)
@@ -2808,6 +2836,16 @@ exp/norm/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: exp/norm/check
 
+@go_include@ exp/proxy.lo.dep
+exp/proxy.lo.dep: $(go_exp_proxy_files)
+       $(BUILDDEPS)
+exp/proxy.lo: $(go_exp_proxy_files)
+       $(BUILDPACKAGE)
+exp/proxy/check: $(CHECK_DEPS)
+       @$(MKDIR_P) exp/proxy
+       @$(CHECK)
+.PHONY: exp/proxy/check
+
 @go_include@ exp/spdy.lo.dep
 exp/spdy.lo.dep: $(go_exp_spdy_files)
        $(BUILDDEPS)
@@ -3622,7 +3660,7 @@ crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
        $(BUILDGOX)
 crypto/openpgp/elgamal.gox: crypto/openpgp/elgamal.lo
        $(BUILDGOX)
-crypto/openpgp/error.gox: crypto/openpgp/error.lo
+crypto/openpgp/errors.gox: crypto/openpgp/errors.lo
        $(BUILDGOX)
 crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
        $(BUILDGOX)
@@ -3674,6 +3712,8 @@ exp/inotify.gox: exp/inotify.lo
        $(BUILDGOX)
 exp/norm.gox: exp/norm.lo
        $(BUILDGOX)
+exp/proxy.gox: exp/proxy.lo
+       $(BUILDGOX)
 exp/spdy.gox: exp/spdy.lo
        $(BUILDGOX)
 exp/sql.gox: exp/sql.lo
@@ -3920,6 +3960,7 @@ TEST_PACKAGES = \
        exp/ebnf/check \
        $(exp_inotify_check) \
        exp/norm/check \
+       exp/proxy/check \
        exp/spdy/check \
        exp/sql/check \
        exp/ssh/check \
index 6bf1847..b82bf42 100644 (file)
@@ -153,33 +153,34 @@ am__DEPENDENCIES_2 = bufio/bufio.lo bytes/bytes.lo bytes/index.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/elgamal.lo \
-       crypto/openpgp/error.lo crypto/openpgp/packet.lo \
+       crypto/openpgp/errors.lo crypto/openpgp/packet.lo \
        crypto/openpgp/s2k.lo crypto/x509/pkix.lo debug/dwarf.lo \
        debug/elf.lo debug/gosym.lo debug/macho.lo debug/pe.lo \
        encoding/ascii85.lo encoding/asn1.lo encoding/base32.lo \
        encoding/base64.lo encoding/binary.lo encoding/csv.lo \
        encoding/git85.lo encoding/gob.lo encoding/hex.lo \
        encoding/json.lo encoding/pem.lo encoding/xml.lo exp/ebnf.lo \
-       exp/norm.lo exp/spdy.lo exp/sql.lo exp/ssh.lo exp/terminal.lo \
-       exp/types.lo exp/sql/driver.lo html/template.lo go/ast.lo \
-       go/build.lo go/doc.lo go/parser.lo go/printer.lo go/scanner.lo \
-       go/token.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \
-       hash/fnv.lo net/http/cgi.lo net/http/fcgi.lo \
-       net/http/httptest.lo net/http/httputil.lo net/http/pprof.lo \
-       image/bmp.lo image/color.lo image/draw.lo image/gif.lo \
-       image/jpeg.lo image/png.lo image/tiff.lo index/suffixarray.lo \
-       io/ioutil.lo log/syslog.lo log/syslog/syslog_c.lo math/big.lo \
-       math/cmplx.lo math/rand.lo mime/mime.lo mime/multipart.lo \
-       net/dict.lo net/http.lo net/mail.lo net/rpc.lo net/smtp.lo \
-       net/textproto.lo net/url.lo old/netchan.lo old/regexp.lo \
-       old/template.lo $(am__DEPENDENCIES_1) os/user.lo os/signal.lo \
-       path/filepath.lo regexp/syntax.lo net/rpc/jsonrpc.lo \
-       runtime/debug.lo runtime/pprof.lo sync/atomic.lo \
-       sync/atomic_c.lo syscall/syscall.lo syscall/errno.lo \
-       syscall/wait.lo text/scanner.lo text/tabwriter.lo \
-       text/template.lo text/template/parse.lo testing/testing.lo \
-       testing/iotest.lo testing/quick.lo testing/script.lo \
-       unicode/utf16.lo unicode/utf8.lo
+       exp/norm.lo exp/proxy.lo exp/spdy.lo exp/sql.lo exp/ssh.lo \
+       exp/terminal.lo exp/types.lo exp/sql/driver.lo \
+       html/template.lo go/ast.lo go/build.lo go/doc.lo go/parser.lo \
+       go/printer.lo go/scanner.lo go/token.lo hash/adler32.lo \
+       hash/crc32.lo hash/crc64.lo hash/fnv.lo net/http/cgi.lo \
+       net/http/fcgi.lo net/http/httptest.lo net/http/httputil.lo \
+       net/http/pprof.lo image/bmp.lo image/color.lo image/draw.lo \
+       image/gif.lo image/jpeg.lo image/png.lo image/tiff.lo \
+       index/suffixarray.lo io/ioutil.lo log/syslog.lo \
+       log/syslog/syslog_c.lo math/big.lo math/cmplx.lo math/rand.lo \
+       mime/mime.lo mime/multipart.lo net/dict.lo net/http.lo \
+       net/mail.lo net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \
+       old/netchan.lo old/regexp.lo old/template.lo \
+       $(am__DEPENDENCIES_1) os/user.lo os/signal.lo path/filepath.lo \
+       regexp/syntax.lo net/rpc/jsonrpc.lo runtime/debug.lo \
+       runtime/pprof.lo sync/atomic.lo sync/atomic_c.lo \
+       syscall/syscall.lo syscall/errno.lo syscall/wait.lo \
+       text/scanner.lo text/tabwriter.lo text/template.lo \
+       text/template/parse.lo testing/testing.lo testing/iotest.lo \
+       testing/quick.lo testing/script.lo unicode/utf16.lo \
+       unicode/utf8.lo
 libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1)
@@ -652,7 +653,7 @@ toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
 toolexeclibgocryptoopenpgp_DATA = \
        crypto/openpgp/armor.gox \
        crypto/openpgp/elgamal.gox \
-       crypto/openpgp/error.gox \
+       crypto/openpgp/errors.gox \
        crypto/openpgp/packet.gox \
        crypto/openpgp/s2k.gox
 
@@ -692,6 +693,7 @@ toolexeclibgoexp_DATA = \
        exp/ebnf.gox \
        $(exp_inotify_gox) \
        exp/norm.gox \
+       exp/proxy.gox \
        exp/spdy.gox \
        exp/sql.gox \
        exp/ssh.gox \
@@ -1049,6 +1051,14 @@ go_mime_files = \
 @LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sock_file = go/net/sock_linux.go
 @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sock_file = go/net/sock_linux.go
 @LIBGO_IS_LINUX_TRUE@go_net_sock_file = go/net/sock_linux.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockopt_file = go/net/sockopt_linux.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockopt_file = go/net/sockopt_linux.go
+@LIBGO_IS_LINUX_TRUE@go_net_sockopt_file = go/net/sockopt_linux.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go
+@LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go
 @LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
 @LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go
 @LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_stub.go
@@ -1082,6 +1092,10 @@ go_net_files = \
        $(go_net_sendfile_file) \
        go/net/sock.go \
        $(go_net_sock_file) \
+       go/net/sockopt.go \
+       $(go_net_sockopt_file) \
+       go/net/sockoptip.go \
+       $(go_net_sockoptip_file) \
        go/net/tcpsock.go \
        go/net/tcpsock_posix.go \
        go/net/udpsock.go \
@@ -1197,8 +1211,7 @@ go_syslog_c_files = \
 go_testing_files = \
        go/testing/benchmark.go \
        go/testing/example.go \
-       go/testing/testing.go \
-       go/testing/wrapper.go
+       go/testing/testing.go
 
 go_time_files = \
        go/time/format.go \
@@ -1394,8 +1407,8 @@ go_crypto_openpgp_armor_files = \
 go_crypto_openpgp_elgamal_files = \
        go/crypto/openpgp/elgamal/elgamal.go
 
-go_crypto_openpgp_error_files = \
-       go/crypto/openpgp/error/error.go
+go_crypto_openpgp_errors_files = \
+       go/crypto/openpgp/errors/errors.go
 
 go_crypto_openpgp_packet_files = \
        go/crypto/openpgp/packet/compressed.go \
@@ -1492,6 +1505,7 @@ go_encoding_pem_files = \
 go_encoding_xml_files = \
        go/encoding/xml/marshal.go \
        go/encoding/xml/read.go \
+       go/encoding/xml/typeinfo.go \
        go/encoding/xml/xml.go
 
 go_exp_ebnf_files = \
@@ -1510,6 +1524,12 @@ go_exp_norm_files = \
        go/exp/norm/tables.go \
        go/exp/norm/trie.go
 
+go_exp_proxy_files = \
+       go/exp/proxy/direct.go \
+       go/exp/proxy/per_host.go \
+       go/exp/proxy/proxy.go \
+       go/exp/proxy/socks5.go
+
 go_exp_spdy_files = \
        go/exp/spdy/read.go \
        go/exp/spdy/types.go \
@@ -1528,7 +1548,7 @@ go_exp_ssh_files = \
        go/exp/ssh/doc.go \
        go/exp/ssh/messages.go \
        go/exp/ssh/server.go \
-       go/exp/ssh/server_shell.go \
+       go/exp/ssh/server_terminal.go \
        go/exp/ssh/session.go \
        go/exp/ssh/tcpip.go \
        go/exp/ssh/transport.go
@@ -1569,7 +1589,8 @@ go_go_doc_files = \
        go/go/doc/doc.go \
        go/go/doc/example.go \
        go/go/doc/exports.go \
-       go/go/doc/filter.go
+       go/go/doc/filter.go \
+       go/go/doc/reader.go
 
 go_go_parser_files = \
        go/go/parser/interface.go \
@@ -1840,10 +1861,14 @@ go_unicode_utf8_files = \
 
 # Define Syscall and Syscall6.
 @LIBGO_IS_RTEMS_TRUE@syscall_syscall_file = go/syscall/syscall_stubs.go
-@LIBGO_IS_RTEMS_FALSE@syscall_exec_file = go/syscall/exec_unix.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_exec_file = go/syscall/exec_unix.go
+@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_exec_file = go/syscall/exec_unix.go
 
 # Define ForkExec and Exec.
 @LIBGO_IS_RTEMS_TRUE@syscall_exec_file = go/syscall/exec_stubs.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_exec_os_file = go/syscall/exec_bsd.go
+@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_exec_os_file = go/syscall/exec_linux.go
+@LIBGO_IS_RTEMS_TRUE@syscall_exec_os_file = 
 @HAVE_WAIT4_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_wait_file = go/syscall/libcall_waitpid.go
 @HAVE_WAIT4_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_wait_file = go/syscall/libcall_wait4.go
 
@@ -1901,6 +1926,7 @@ go_base_syscall_files = \
        go/syscall/syscall.go \
        $(syscall_syscall_file) \
        $(syscall_exec_file) \
+       $(syscall_exec_os_file) \
        $(syscall_wait_file) \
        $(syscall_sleep_file) \
        $(syscall_errstr_file) \
@@ -1995,7 +2021,7 @@ libgo_go_objs = \
        crypto/xtea.lo \
        crypto/openpgp/armor.lo \
        crypto/openpgp/elgamal.lo \
-       crypto/openpgp/error.lo \
+       crypto/openpgp/errors.lo \
        crypto/openpgp/packet.lo \
        crypto/openpgp/s2k.lo \
        crypto/x509/pkix.lo \
@@ -2018,6 +2044,7 @@ libgo_go_objs = \
        encoding/xml.lo \
        exp/ebnf.lo \
        exp/norm.lo \
+       exp/proxy.lo \
        exp/spdy.lo \
        exp/sql.lo \
        exp/ssh.lo \
@@ -2286,6 +2313,7 @@ TEST_PACKAGES = \
        exp/ebnf/check \
        $(exp_inotify_check) \
        exp/norm/check \
+       exp/proxy/check \
        exp/spdy/check \
        exp/sql/check \
        exp/ssh/check \
@@ -5162,15 +5190,15 @@ crypto/openpgp/elgamal/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/openpgp/elgamal/check
 
-@go_include@ crypto/openpgp/error.lo.dep
-crypto/openpgp/error.lo.dep: $(go_crypto_openpgp_error_files)
+@go_include@ crypto/openpgp/errors.lo.dep
+crypto/openpgp/errors.lo.dep: $(go_crypto_openpgp_errors_files)
        $(BUILDDEPS)
-crypto/openpgp/error.lo: $(go_crypto_openpgp_error_files)
+crypto/openpgp/errors.lo: $(go_crypto_openpgp_errors_files)
        $(BUILDPACKAGE)
-crypto/openpgp/error/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/error
+crypto/openpgp/errors/check: $(CHECK_DEPS)
+       @$(MKDIR_P) crypto/openpgp/errors
        @$(CHECK)
-.PHONY: crypto/openpgp/error/check
+.PHONY: crypto/openpgp/errors/check
 
 @go_include@ crypto/openpgp/packet.lo.dep
 crypto/openpgp/packet.lo.dep: $(go_crypto_openpgp_packet_files)
@@ -5392,6 +5420,16 @@ exp/norm/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: exp/norm/check
 
+@go_include@ exp/proxy.lo.dep
+exp/proxy.lo.dep: $(go_exp_proxy_files)
+       $(BUILDDEPS)
+exp/proxy.lo: $(go_exp_proxy_files)
+       $(BUILDPACKAGE)
+exp/proxy/check: $(CHECK_DEPS)
+       @$(MKDIR_P) exp/proxy
+       @$(CHECK)
+.PHONY: exp/proxy/check
+
 @go_include@ exp/spdy.lo.dep
 exp/spdy.lo.dep: $(go_exp_spdy_files)
        $(BUILDDEPS)
@@ -6201,7 +6239,7 @@ crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
        $(BUILDGOX)
 crypto/openpgp/elgamal.gox: crypto/openpgp/elgamal.lo
        $(BUILDGOX)
-crypto/openpgp/error.gox: crypto/openpgp/error.lo
+crypto/openpgp/errors.gox: crypto/openpgp/errors.lo
        $(BUILDGOX)
 crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
        $(BUILDGOX)
@@ -6253,6 +6291,8 @@ exp/inotify.gox: exp/inotify.lo
        $(BUILDGOX)
 exp/norm.gox: exp/norm.lo
        $(BUILDGOX)
+exp/proxy.gox: exp/proxy.lo
+       $(BUILDGOX)
 exp/spdy.gox: exp/spdy.lo
        $(BUILDGOX)
 exp/sql.gox: exp/sql.lo
index f30af59..e4a2569 100644 (file)
@@ -74,6 +74,9 @@
 /* Define to 1 if you have the <sys/mman.h> header file. */
 #undef HAVE_SYS_MMAN_H
 
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
 /* Define to 1 if you have the <sys/ptrace.h> header file. */
 #undef HAVE_SYS_PTRACE_H
 
index 8c8fe38..5ebed80 100755 (executable)
@@ -14505,7 +14505,7 @@ no)
   ;;
 esac
 
-for ac_header in sys/mman.h syscall.h sys/epoll.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h
+for ac_header in sys/mman.h syscall.h sys/epoll.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h sys/prctl.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
index cd6b1a9..9795332 100644 (file)
@@ -451,7 +451,7 @@ no)
   ;;
 esac
 
-AC_CHECK_HEADERS(sys/mman.h syscall.h sys/epoll.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h)
+AC_CHECK_HEADERS(sys/mman.h syscall.h sys/epoll.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h sys/prctl.h)
 
 AC_CHECK_HEADERS([linux/filter.h linux/netlink.h linux/rtnetlink.h], [], [],
 [#ifdef HAVE_SYS_SOCKET_H
index e66ac02..77757af 100644 (file)
@@ -97,8 +97,7 @@ func (b *Buffer) grow(n int) int {
 func (b *Buffer) Write(p []byte) (n int, err error) {
        b.lastRead = opInvalid
        m := b.grow(len(p))
-       copy(b.buf[m:], p)
-       return len(p), nil
+       return copy(b.buf[m:], p), nil
 }
 
 // WriteString appends the contents of s to the buffer.  The return
@@ -200,13 +199,16 @@ func (b *Buffer) WriteRune(r rune) (n int, err error) {
 
 // Read reads the next len(p) bytes from the buffer or until the buffer
 // is drained.  The return value n is the number of bytes read.  If the
-// buffer has no data to return, err is io.EOF even if len(p) is zero;
+// buffer has no data to return, err is io.EOF (unless len(p) is zero);
 // otherwise it is nil.
 func (b *Buffer) Read(p []byte) (n int, err error) {
        b.lastRead = opInvalid
        if b.off >= len(b.buf) {
                // Buffer is empty, reset to recover space.
                b.Truncate(0)
+               if len(p) == 0 {
+                       return
+               }
                return 0, io.EOF
        }
        n = copy(p, b.buf[b.off:])
index adb9330..d0af11f 100644 (file)
@@ -373,3 +373,16 @@ func TestReadBytes(t *testing.T) {
                }
        }
 }
+
+// Was a bug: used to give EOF reading empty slice at EOF.
+func TestReadEmptyAtEOF(t *testing.T) {
+       b := new(Buffer)
+       slice := make([]byte, 0)
+       n, err := b.Read(slice)
+       if err != nil {
+               t.Errorf("read error: %v", err)
+       }
+       if n != 0 {
+               t.Errorf("wrong count; got %d want 0", n)
+       }
+}
index 3bbb5dc..96957ab 100644 (file)
@@ -9,7 +9,7 @@ package armor
 import (
        "bufio"
        "bytes"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "encoding/base64"
        "io"
 )
@@ -35,7 +35,7 @@ type Block struct {
        oReader openpgpReader
 }
 
-var ArmorCorrupt error = error_.StructuralError("armor invalid")
+var ArmorCorrupt error = errors.StructuralError("armor invalid")
 
 const crc24Init = 0xb704ce
 const crc24Poly = 0x1864cfb
similarity index 94%
rename from libgo/go/crypto/openpgp/error/error.go
rename to libgo/go/crypto/openpgp/errors/errors.go
index ceeb054..c434b76 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package error contains common error types for the OpenPGP packages.
-package error
+// Package errors contains common error types for the OpenPGP packages.
+package errors
 
 import (
        "strconv"
index 74e7d23..624a5ea 100644 (file)
@@ -7,8 +7,9 @@ package openpgp
 import (
        "crypto"
        "crypto/openpgp/armor"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/openpgp/packet"
+       "crypto/rand"
        "crypto/rsa"
        "io"
        "time"
@@ -181,13 +182,13 @@ func (el EntityList) DecryptionKeys() (keys []Key) {
 func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
        block, err := armor.Decode(r)
        if err == io.EOF {
-               return nil, error_.InvalidArgumentError("no armored data found")
+               return nil, errors.InvalidArgumentError("no armored data found")
        }
        if err != nil {
                return nil, err
        }
        if block.Type != PublicKeyType && block.Type != PrivateKeyType {
-               return nil, error_.InvalidArgumentError("expected public or private key block, got: " + block.Type)
+               return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
        }
 
        return ReadKeyRing(block.Body)
@@ -203,7 +204,7 @@ func ReadKeyRing(r io.Reader) (el EntityList, err error) {
                var e *Entity
                e, err = readEntity(packets)
                if err != nil {
-                       if _, ok := err.(error_.UnsupportedError); ok {
+                       if _, ok := err.(errors.UnsupportedError); ok {
                                lastUnsupportedError = err
                                err = readToNextPublicKey(packets)
                        }
@@ -235,7 +236,7 @@ func readToNextPublicKey(packets *packet.Reader) (err error) {
                if err == io.EOF {
                        return
                } else if err != nil {
-                       if _, ok := err.(error_.UnsupportedError); ok {
+                       if _, ok := err.(errors.UnsupportedError); ok {
                                err = nil
                                continue
                        }
@@ -266,14 +267,14 @@ func readEntity(packets *packet.Reader) (*Entity, error) {
        if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
                if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
                        packets.Unread(p)
-                       return nil, error_.StructuralError("first packet was not a public/private key")
+                       return nil, errors.StructuralError("first packet was not a public/private key")
                } else {
                        e.PrimaryKey = &e.PrivateKey.PublicKey
                }
        }
 
        if !e.PrimaryKey.PubKeyAlgo.CanSign() {
-               return nil, error_.StructuralError("primary key cannot be used for signatures")
+               return nil, errors.StructuralError("primary key cannot be used for signatures")
        }
 
        var current *Identity
@@ -303,12 +304,12 @@ EachPacket:
 
                                sig, ok := p.(*packet.Signature)
                                if !ok {
-                                       return nil, error_.StructuralError("user ID packet not followed by self-signature")
+                                       return nil, errors.StructuralError("user ID packet not followed by self-signature")
                                }
 
                                if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
                                        if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil {
-                                               return nil, error_.StructuralError("user ID self-signature invalid: " + err.Error())
+                                               return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
                                        }
                                        current.SelfSignature = sig
                                        break
@@ -317,7 +318,7 @@ EachPacket:
                        }
                case *packet.Signature:
                        if current == nil {
-                               return nil, error_.StructuralError("signature packet found before user id packet")
+                               return nil, errors.StructuralError("signature packet found before user id packet")
                        }
                        current.Signatures = append(current.Signatures, pkt)
                case *packet.PrivateKey:
@@ -344,7 +345,7 @@ EachPacket:
        }
 
        if len(e.Identities) == 0 {
-               return nil, error_.StructuralError("entity without any identities")
+               return nil, errors.StructuralError("entity without any identities")
        }
 
        return e, nil
@@ -359,19 +360,19 @@ func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *p
                return io.ErrUnexpectedEOF
        }
        if err != nil {
-               return error_.StructuralError("subkey signature invalid: " + err.Error())
+               return errors.StructuralError("subkey signature invalid: " + err.Error())
        }
        var ok bool
        subKey.Sig, ok = p.(*packet.Signature)
        if !ok {
-               return error_.StructuralError("subkey packet not followed by signature")
+               return errors.StructuralError("subkey packet not followed by signature")
        }
        if subKey.Sig.SigType != packet.SigTypeSubkeyBinding {
-               return error_.StructuralError("subkey signature with wrong type")
+               return errors.StructuralError("subkey signature with wrong type")
        }
        err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
        if err != nil {
-               return error_.StructuralError("subkey signature invalid: " + err.Error())
+               return errors.StructuralError("subkey signature invalid: " + err.Error())
        }
        e.Subkeys = append(e.Subkeys, subKey)
        return nil
@@ -385,7 +386,7 @@ const defaultRSAKeyBits = 2048
 func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email string) (*Entity, error) {
        uid := packet.NewUserId(name, comment, email)
        if uid == nil {
-               return nil, error_.InvalidArgumentError("user id field contained invalid characters")
+               return nil, errors.InvalidArgumentError("user id field contained invalid characters")
        }
        signingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
        if err != nil {
@@ -397,8 +398,8 @@ func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email strin
        }
 
        e := &Entity{
-               PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey, false /* not a subkey */ ),
-               PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv, false /* not a subkey */ ),
+               PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
+               PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
                Identities: make(map[string]*Identity),
        }
        isPrimaryId := true
@@ -420,8 +421,8 @@ func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email strin
 
        e.Subkeys = make([]Subkey, 1)
        e.Subkeys[0] = Subkey{
-               PublicKey:  packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey, true /* is a subkey */ ),
-               PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv, true /* is a subkey */ ),
+               PublicKey:  packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
+               PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
                Sig: &packet.Signature{
                        CreationTime:              currentTime,
                        SigType:                   packet.SigTypeSubkeyBinding,
@@ -433,6 +434,8 @@ func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email strin
                        IssuerKeyId:               &e.PrimaryKey.KeyId,
                },
        }
+       e.Subkeys[0].PublicKey.IsSubkey = true
+       e.Subkeys[0].PrivateKey.IsSubkey = true
 
        return e, nil
 }
@@ -450,7 +453,7 @@ func (e *Entity) SerializePrivate(w io.Writer) (err error) {
                if err != nil {
                        return
                }
-               err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey)
+               err = ident.SelfSignature.SignUserId(rand.Reader, ident.UserId.Id, e.PrimaryKey, e.PrivateKey)
                if err != nil {
                        return
                }
@@ -464,7 +467,7 @@ func (e *Entity) SerializePrivate(w io.Writer) (err error) {
                if err != nil {
                        return
                }
-               err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey)
+               err = subkey.Sig.SignKey(rand.Reader, subkey.PublicKey, e.PrivateKey)
                if err != nil {
                        return
                }
@@ -518,14 +521,14 @@ func (e *Entity) Serialize(w io.Writer) error {
 // necessary.
 func (e *Entity) SignIdentity(identity string, signer *Entity) error {
        if signer.PrivateKey == nil {
-               return error_.InvalidArgumentError("signing Entity must have a private key")
+               return errors.InvalidArgumentError("signing Entity must have a private key")
        }
        if signer.PrivateKey.Encrypted {
-               return error_.InvalidArgumentError("signing Entity's private key must be decrypted")
+               return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
        }
        ident, ok := e.Identities[identity]
        if !ok {
-               return error_.InvalidArgumentError("given identity string not found in Entity")
+               return errors.InvalidArgumentError("given identity string not found in Entity")
        }
 
        sig := &packet.Signature{
@@ -535,7 +538,7 @@ func (e *Entity) SignIdentity(identity string, signer *Entity) error {
                CreationTime: time.Now(),
                IssuerKeyId:  &signer.PrivateKey.KeyId,
        }
-       if err := sig.SignKey(e.PrimaryKey, signer.PrivateKey); err != nil {
+       if err := sig.SignKey(rand.Reader, e.PrimaryKey, signer.PrivateKey); err != nil {
                return err
        }
        ident.Signatures = append(ident.Signatures, sig)
index f80d798..36736e3 100644 (file)
@@ -7,7 +7,7 @@ package packet
 import (
        "compress/flate"
        "compress/zlib"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "io"
        "strconv"
 )
@@ -31,7 +31,7 @@ func (c *Compressed) parse(r io.Reader) error {
        case 2:
                c.Body, err = zlib.NewReader(r)
        default:
-               err = error_.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
+               err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
        }
 
        return err
index b24fa3a..479a643 100644 (file)
@@ -6,7 +6,7 @@ package packet
 
 import (
        "crypto/openpgp/elgamal"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/rand"
        "crypto/rsa"
        "encoding/binary"
@@ -35,7 +35,7 @@ func (e *EncryptedKey) parse(r io.Reader) (err error) {
                return
        }
        if buf[0] != encryptedKeyVersion {
-               return error_.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
+               return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
        }
        e.KeyId = binary.BigEndian.Uint64(buf[1:9])
        e.Algo = PublicKeyAlgorithm(buf[9])
@@ -77,7 +77,7 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey) error {
                c2 := new(big.Int).SetBytes(e.encryptedMPI2)
                b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
        default:
-               err = error_.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
+               err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
        }
 
        if err != nil {
@@ -89,7 +89,7 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey) error {
        expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
        checksum := checksumKeyMaterial(e.Key)
        if checksum != expectedChecksum {
-               return error_.StructuralError("EncryptedKey checksum incorrect")
+               return errors.StructuralError("EncryptedKey checksum incorrect")
        }
 
        return nil
@@ -116,16 +116,16 @@ func SerializeEncryptedKey(w io.Writer, rand io.Reader, pub *PublicKey, cipherFu
        case PubKeyAlgoElGamal:
                return serializeEncryptedKeyElGamal(w, rand, buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
        case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
-               return error_.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
+               return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
        }
 
-       return error_.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
+       return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
 }
 
 func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
        cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
        if err != nil {
-               return error_.InvalidArgumentError("RSA encryption failed: " + err.Error())
+               return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
        }
 
        packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
@@ -144,7 +144,7 @@ func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub
 func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
        c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
        if err != nil {
-               return error_.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
+               return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
        }
 
        packetLen := 10 /* header length */
index 13e6aa5..822cfe9 100644 (file)
@@ -6,7 +6,7 @@ package packet
 
 import (
        "crypto"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/openpgp/s2k"
        "encoding/binary"
        "io"
@@ -33,13 +33,13 @@ func (ops *OnePassSignature) parse(r io.Reader) (err error) {
                return
        }
        if buf[0] != onePassSignatureVersion {
-               err = error_.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
+               err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
        }
 
        var ok bool
        ops.Hash, ok = s2k.HashIdToHash(buf[2])
        if !ok {
-               return error_.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
+               return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
        }
 
        ops.SigType = SignatureType(buf[1])
@@ -57,7 +57,7 @@ func (ops *OnePassSignature) Serialize(w io.Writer) error {
        var ok bool
        buf[2], ok = s2k.HashToHashId(ops.Hash)
        if !ok {
-               return error_.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
+               return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
        }
        buf[3] = uint8(ops.PubKeyAlgo)
        binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
index 778df15..f7c1964 100644 (file)
@@ -10,7 +10,7 @@ import (
        "crypto/aes"
        "crypto/cast5"
        "crypto/cipher"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "io"
        "math/big"
 )
@@ -162,7 +162,7 @@ func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader,
                return
        }
        if buf[0]&0x80 == 0 {
-               err = error_.StructuralError("tag byte does not have MSB set")
+               err = errors.StructuralError("tag byte does not have MSB set")
                return
        }
        if buf[0]&0x40 == 0 {
@@ -337,7 +337,7 @@ func Read(r io.Reader) (p Packet, err error) {
                se.MDC = true
                p = se
        default:
-               err = error_.UnknownPacketTypeError(tag)
+               err = errors.UnknownPacketTypeError(tag)
        }
        if p != nil {
                err = p.parse(contents)
index 5326641..e4b8691 100644 (file)
@@ -6,7 +6,7 @@ package packet
 
 import (
        "bytes"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "encoding/hex"
        "fmt"
        "io"
@@ -152,7 +152,7 @@ func TestReadHeader(t *testing.T) {
        for i, test := range readHeaderTests {
                tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
                if test.structuralError {
-                       if _, ok := err.(error_.StructuralError); ok {
+                       if _, ok := err.(errors.StructuralError); ok {
                                continue
                        }
                        t.Errorf("%d: expected StructuralError, got:%s", i, err)
index d67e968..5a90d06 100644 (file)
@@ -9,7 +9,7 @@ import (
        "crypto/cipher"
        "crypto/dsa"
        "crypto/openpgp/elgamal"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/openpgp/s2k"
        "crypto/rsa"
        "crypto/sha1"
@@ -28,14 +28,21 @@ type PrivateKey struct {
        encryptedData []byte
        cipher        CipherFunction
        s2k           func(out, in []byte)
-       PrivateKey    interface{} // An *rsa.PrivateKey.
+       PrivateKey    interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
        sha1Checksum  bool
        iv            []byte
 }
 
-func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey, isSubkey bool) *PrivateKey {
+func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
        pk := new(PrivateKey)
-       pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey, isSubkey)
+       pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
+       pk.PrivateKey = priv
+       return pk
+}
+
+func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
+       pk := new(PrivateKey)
+       pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
        pk.PrivateKey = priv
        return pk
 }
@@ -72,13 +79,13 @@ func (pk *PrivateKey) parse(r io.Reader) (err error) {
                        pk.sha1Checksum = true
                }
        default:
-               return error_.UnsupportedError("deprecated s2k function in private key")
+               return errors.UnsupportedError("deprecated s2k function in private key")
        }
 
        if pk.Encrypted {
                blockSize := pk.cipher.blockSize()
                if blockSize == 0 {
-                       return error_.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
+                       return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
                }
                pk.iv = make([]byte, blockSize)
                _, err = readFull(r, pk.iv)
@@ -121,8 +128,10 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
        switch priv := pk.PrivateKey.(type) {
        case *rsa.PrivateKey:
                err = serializeRSAPrivateKey(privateKeyBuf, priv)
+       case *dsa.PrivateKey:
+               err = serializeDSAPrivateKey(privateKeyBuf, priv)
        default:
-               err = error_.InvalidArgumentError("non-RSA private key")
+               err = errors.InvalidArgumentError("unknown private key type")
        }
        if err != nil {
                return
@@ -172,6 +181,10 @@ func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
        return writeBig(w, priv.Precomputed.Qinv)
 }
 
+func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
+       return writeBig(w, priv.X)
+}
+
 // Decrypt decrypts an encrypted private key using a passphrase.
 func (pk *PrivateKey) Decrypt(passphrase []byte) error {
        if !pk.Encrypted {
@@ -188,18 +201,18 @@ func (pk *PrivateKey) Decrypt(passphrase []byte) error {
 
        if pk.sha1Checksum {
                if len(data) < sha1.Size {
-                       return error_.StructuralError("truncated private key data")
+                       return errors.StructuralError("truncated private key data")
                }
                h := sha1.New()
                h.Write(data[:len(data)-sha1.Size])
                sum := h.Sum(nil)
                if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
-                       return error_.StructuralError("private key checksum failure")
+                       return errors.StructuralError("private key checksum failure")
                }
                data = data[:len(data)-sha1.Size]
        } else {
                if len(data) < 2 {
-                       return error_.StructuralError("truncated private key data")
+                       return errors.StructuralError("truncated private key data")
                }
                var sum uint16
                for i := 0; i < len(data)-2; i++ {
@@ -207,7 +220,7 @@ func (pk *PrivateKey) Decrypt(passphrase []byte) error {
                }
                if data[len(data)-2] != uint8(sum>>8) ||
                        data[len(data)-1] != uint8(sum) {
-                       return error_.StructuralError("private key checksum failure")
+                       return errors.StructuralError("private key checksum failure")
                }
                data = data[:len(data)-2]
        }
index 9aa30e0..ba178b5 100644 (file)
@@ -7,7 +7,7 @@ package packet
 import (
        "crypto/dsa"
        "crypto/openpgp/elgamal"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/rsa"
        "crypto/sha1"
        "encoding/binary"
@@ -39,12 +39,11 @@ func fromBig(n *big.Int) parsedMPI {
 }
 
 // NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
-func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey, isSubkey bool) *PublicKey {
+func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
        pk := &PublicKey{
                CreationTime: creationTime,
                PubKeyAlgo:   PubKeyAlgoRSA,
                PublicKey:    pub,
-               IsSubkey:     isSubkey,
                n:            fromBig(pub.N),
                e:            fromBig(big.NewInt(int64(pub.E))),
        }
@@ -53,6 +52,22 @@ func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey, isSubkey bool)
        return pk
 }
 
+// NewDSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
+func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
+       pk := &PublicKey{
+               CreationTime: creationTime,
+               PubKeyAlgo:   PubKeyAlgoDSA,
+               PublicKey:    pub,
+               p:            fromBig(pub.P),
+               q:            fromBig(pub.Q),
+               g:            fromBig(pub.G),
+               y:            fromBig(pub.Y),
+       }
+
+       pk.setFingerPrintAndKeyId()
+       return pk
+}
+
 func (pk *PublicKey) parse(r io.Reader) (err error) {
        // RFC 4880, section 5.5.2
        var buf [6]byte
@@ -61,7 +76,7 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
                return
        }
        if buf[0] != 4 {
-               return error_.UnsupportedError("public key version")
+               return errors.UnsupportedError("public key version")
        }
        pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
        pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
@@ -73,7 +88,7 @@ func (pk *PublicKey) parse(r io.Reader) (err error) {
        case PubKeyAlgoElGamal:
                err = pk.parseElGamal(r)
        default:
-               err = error_.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
+               err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
        }
        if err != nil {
                return
@@ -105,7 +120,7 @@ func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
        }
 
        if len(pk.e.bytes) > 3 {
-               err = error_.UnsupportedError("large public exponent")
+               err = errors.UnsupportedError("large public exponent")
                return
        }
        rsa := &rsa.PublicKey{
@@ -255,7 +270,7 @@ func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
        case PubKeyAlgoElGamal:
                return writeMPIs(w, pk.p, pk.g, pk.y)
        }
-       return error_.InvalidArgumentError("bad public-key algorithm")
+       return errors.InvalidArgumentError("bad public-key algorithm")
 }
 
 // CanSign returns true iff this public key can generate signatures
@@ -267,18 +282,18 @@ func (pk *PublicKey) CanSign() bool {
 // public key, of the data hashed into signed. signed is mutated by this call.
 func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
        if !pk.CanSign() {
-               return error_.InvalidArgumentError("public key cannot generate signatures")
+               return errors.InvalidArgumentError("public key cannot generate signatures")
        }
 
        signed.Write(sig.HashSuffix)
        hashBytes := signed.Sum(nil)
 
        if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
-               return error_.SignatureError("hash tag doesn't match")
+               return errors.SignatureError("hash tag doesn't match")
        }
 
        if pk.PubKeyAlgo != sig.PubKeyAlgo {
-               return error_.InvalidArgumentError("public key and signature use different algorithms")
+               return errors.InvalidArgumentError("public key and signature use different algorithms")
        }
 
        switch pk.PubKeyAlgo {
@@ -286,13 +301,18 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
                rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
                err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
                if err != nil {
-                       return error_.SignatureError("RSA verification failure")
+                       return errors.SignatureError("RSA verification failure")
                }
                return nil
        case PubKeyAlgoDSA:
                dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
+               // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+               subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
+               if len(hashBytes) > subgroupSize {
+                       hashBytes = hashBytes[:subgroupSize]
+               }
                if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
-                       return error_.SignatureError("DSA verification failure")
+                       return errors.SignatureError("DSA verification failure")
                }
                return nil
        default:
@@ -306,7 +326,7 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
 func keySignatureHash(pk, signed *PublicKey, sig *Signature) (h hash.Hash, err error) {
        h = sig.Hash.New()
        if h == nil {
-               return nil, error_.UnsupportedError("hash function")
+               return nil, errors.UnsupportedError("hash function")
        }
 
        // RFC 4880, section 5.2.4
@@ -332,7 +352,7 @@ func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err
 func userIdSignatureHash(id string, pk *PublicKey, sig *Signature) (h hash.Hash, err error) {
        h = sig.Hash.New()
        if h == nil {
-               return nil, error_.UnsupportedError("hash function")
+               return nil, errors.UnsupportedError("hash function")
        }
 
        // RFC 4880, section 5.2.4
index e3d733c..1a3e8e2 100644 (file)
@@ -5,7 +5,7 @@
 package packet
 
 import (
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "io"
 )
 
@@ -34,7 +34,7 @@ func (r *Reader) Next() (p Packet, err error) {
                        r.readers = r.readers[:len(r.readers)-1]
                        continue
                }
-               if _, ok := err.(error_.UnknownPacketTypeError); !ok {
+               if _, ok := err.(errors.UnknownPacketTypeError); !ok {
                        return nil, err
                }
        }
index 1cdc1ee..c3ffb3a 100644 (file)
@@ -7,9 +7,8 @@ package packet
 import (
        "crypto"
        "crypto/dsa"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/openpgp/s2k"
-       "crypto/rand"
        "crypto/rsa"
        "encoding/binary"
        "hash"
@@ -61,7 +60,7 @@ func (sig *Signature) parse(r io.Reader) (err error) {
                return
        }
        if buf[0] != 4 {
-               err = error_.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
+               err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
                return
        }
 
@@ -74,14 +73,14 @@ func (sig *Signature) parse(r io.Reader) (err error) {
        switch sig.PubKeyAlgo {
        case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
        default:
-               err = error_.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
+               err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
                return
        }
 
        var ok bool
        sig.Hash, ok = s2k.HashIdToHash(buf[2])
        if !ok {
-               return error_.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
+               return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
        }
 
        hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
@@ -153,7 +152,7 @@ func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool)
        }
 
        if sig.CreationTime.IsZero() {
-               err = error_.StructuralError("no creation time in signature")
+               err = errors.StructuralError("no creation time in signature")
        }
 
        return
@@ -164,7 +163,7 @@ type signatureSubpacketType uint8
 const (
        creationTimeSubpacket        signatureSubpacketType = 2
        signatureExpirationSubpacket signatureSubpacketType = 3
-       keyExpirySubpacket           signatureSubpacketType = 9
+       keyExpirationSubpacket       signatureSubpacketType = 9
        prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
        issuerSubpacket              signatureSubpacketType = 16
        prefHashAlgosSubpacket       signatureSubpacketType = 21
@@ -207,7 +206,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
        rest = subpacket[length:]
        subpacket = subpacket[:length]
        if len(subpacket) == 0 {
-               err = error_.StructuralError("zero length signature subpacket")
+               err = errors.StructuralError("zero length signature subpacket")
                return
        }
        packetType = signatureSubpacketType(subpacket[0] & 0x7f)
@@ -217,37 +216,33 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
        switch packetType {
        case creationTimeSubpacket:
                if !isHashed {
-                       err = error_.StructuralError("signature creation time in non-hashed area")
+                       err = errors.StructuralError("signature creation time in non-hashed area")
                        return
                }
                if len(subpacket) != 4 {
-                       err = error_.StructuralError("signature creation time not four bytes")
+                       err = errors.StructuralError("signature creation time not four bytes")
                        return
                }
                t := binary.BigEndian.Uint32(subpacket)
-               if t == 0 {
-                       sig.CreationTime = time.Time{}
-               } else {
-                       sig.CreationTime = time.Unix(int64(t), 0)
-               }
+               sig.CreationTime = time.Unix(int64(t), 0)
        case signatureExpirationSubpacket:
                // Signature expiration time, section 5.2.3.10
                if !isHashed {
                        return
                }
                if len(subpacket) != 4 {
-                       err = error_.StructuralError("expiration subpacket with bad length")
+                       err = errors.StructuralError("expiration subpacket with bad length")
                        return
                }
                sig.SigLifetimeSecs = new(uint32)
                *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
-       case keyExpirySubpacket:
+       case keyExpirationSubpacket:
                // Key expiration time, section 5.2.3.6
                if !isHashed {
                        return
                }
                if len(subpacket) != 4 {
-                       err = error_.StructuralError("key expiration subpacket with bad length")
+                       err = errors.StructuralError("key expiration subpacket with bad length")
                        return
                }
                sig.KeyLifetimeSecs = new(uint32)
@@ -262,7 +257,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
        case issuerSubpacket:
                // Issuer, section 5.2.3.5
                if len(subpacket) != 8 {
-                       err = error_.StructuralError("issuer subpacket with bad length")
+                       err = errors.StructuralError("issuer subpacket with bad length")
                        return
                }
                sig.IssuerKeyId = new(uint64)
@@ -287,7 +282,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
                        return
                }
                if len(subpacket) != 1 {
-                       err = error_.StructuralError("primary user id subpacket with bad length")
+                       err = errors.StructuralError("primary user id subpacket with bad length")
                        return
                }
                sig.IsPrimaryId = new(bool)
@@ -300,7 +295,7 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
                        return
                }
                if len(subpacket) == 0 {
-                       err = error_.StructuralError("empty key flags subpacket")
+                       err = errors.StructuralError("empty key flags subpacket")
                        return
                }
                sig.FlagsValid = true
@@ -319,14 +314,14 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
 
        default:
                if isCritical {
-                       err = error_.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
+                       err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
                        return
                }
        }
        return
 
 Truncated:
-       err = error_.StructuralError("signature subpacket truncated")
+       err = errors.StructuralError("signature subpacket truncated")
        return
 }
 
@@ -401,7 +396,7 @@ func (sig *Signature) buildHashSuffix() (err error) {
        sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
        if !ok {
                sig.HashSuffix = nil
-               return error_.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
+               return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
        }
        sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
        sig.HashSuffix[5] = byte(hashedSubpacketsLen)
@@ -431,7 +426,7 @@ func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
 // Sign signs a message with a private key. The hash, h, must contain
 // the hash of the message to be signed and will be mutated by this function.
 // On success, the signature is stored in sig. Call Serialize to write it out.
-func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err error) {
+func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err error) {
        sig.outSubpackets = sig.buildSubpackets()
        digest, err := sig.signPrepareHash(h)
        if err != nil {
@@ -440,10 +435,17 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err error) {
 
        switch priv.PubKeyAlgo {
        case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-               sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
+               sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
                sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
        case PubKeyAlgoDSA:
-               r, s, err := dsa.Sign(rand.Reader, priv.PrivateKey.(*dsa.PrivateKey), digest)
+               dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
+
+               // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
+               subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
+               if len(digest) > subgroupSize {
+                       digest = digest[:subgroupSize]
+               }
+               r, s, err := dsa.Sign(rand, dsaPriv, digest)
                if err == nil {
                        sig.DSASigR.bytes = r.Bytes()
                        sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
@@ -451,7 +453,7 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err error) {
                        sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
                }
        default:
-               err = error_.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
+               err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
        }
 
        return
@@ -460,22 +462,22 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey) (err error) {
 // SignUserId computes a signature from priv, asserting that pub is a valid
 // key for the identity id.  On success, the signature is stored in sig. Call
 // Serialize to write it out.
-func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey) error {
+func (sig *Signature) SignUserId(rand io.Reader, id string, pub *PublicKey, priv *PrivateKey) error {
        h, err := userIdSignatureHash(id, pub, sig)
        if err != nil {
                return nil
        }
-       return sig.Sign(h, priv)
+       return sig.Sign(rand, h, priv)
 }
 
 // SignKey computes a signature from priv, asserting that pub is a subkey.  On
 // success, the signature is stored in sig. Call Serialize to write it out.
-func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey) error {
+func (sig *Signature) SignKey(rand io.Reader, pub *PublicKey, priv *PrivateKey) error {
        h, err := keySignatureHash(&priv.PublicKey, pub, sig)
        if err != nil {
                return err
        }
-       return sig.Sign(h, priv)
+       return sig.Sign(rand, h, priv)
 }
 
 // Serialize marshals sig to w. SignRSA or SignDSA must have been called first.
@@ -484,7 +486,7 @@ func (sig *Signature) Serialize(w io.Writer) (err error) {
                sig.outSubpackets = sig.rawSubpackets
        }
        if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
-               return error_.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize")
+               return errors.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize")
        }
 
        sigLength := 0
@@ -556,5 +558,54 @@ func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
                subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
        }
 
+       if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
+               sigLifetime := make([]byte, 4)
+               binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
+               subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
+       }
+
+       // Key flags may only appear in self-signatures or certification signatures.
+
+       if sig.FlagsValid {
+               var flags byte
+               if sig.FlagCertify {
+                       flags |= 1
+               }
+               if sig.FlagSign {
+                       flags |= 2
+               }
+               if sig.FlagEncryptCommunications {
+                       flags |= 4
+               }
+               if sig.FlagEncryptStorage {
+                       flags |= 8
+               }
+               subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
+       }
+
+       // The following subpackets may only appear in self-signatures
+
+       if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
+               keyLifetime := make([]byte, 4)
+               binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
+               subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
+       }
+
+       if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
+               subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
+       }
+
+       if len(sig.PreferredSymmetric) > 0 {
+               subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
+       }
+
+       if len(sig.PreferredHash) > 0 {
+               subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
+       }
+
+       if len(sig.PreferredCompression) > 0 {
+               subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
+       }
+
        return
 }
index 76d5151..94e0705 100644 (file)
@@ -7,7 +7,7 @@ package packet
 import (
        "bytes"
        "crypto/cipher"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/openpgp/s2k"
        "io"
        "strconv"
@@ -37,12 +37,12 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err error) {
                return
        }
        if buf[0] != symmetricKeyEncryptedVersion {
-               return error_.UnsupportedError("SymmetricKeyEncrypted version")
+               return errors.UnsupportedError("SymmetricKeyEncrypted version")
        }
        ske.CipherFunc = CipherFunction(buf[1])
 
        if ske.CipherFunc.KeySize() == 0 {
-               return error_.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
+               return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
        }
 
        ske.s2k, err = s2k.Parse(r)
@@ -60,7 +60,7 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err error) {
        err = nil
        if n != 0 {
                if n == maxSessionKeySizeInBytes {
-                       return error_.UnsupportedError("oversized encrypted session key")
+                       return errors.UnsupportedError("oversized encrypted session key")
                }
                ske.encryptedKey = encryptedKey[:n]
        }
@@ -89,13 +89,13 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error {
                c.XORKeyStream(ske.encryptedKey, ske.encryptedKey)
                ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
                if ske.CipherFunc.blockSize() == 0 {
-                       return error_.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
+                       return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
                }
                ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
                ske.Key = ske.encryptedKey[1:]
                if len(ske.Key)%ske.CipherFunc.blockSize() != 0 {
                        ske.Key = nil
-                       return error_.StructuralError("length of decrypted key not a multiple of block size")
+                       return errors.StructuralError("length of decrypted key not a multiple of block size")
                }
        }
 
@@ -110,7 +110,7 @@ func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error {
 func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []byte, cipherFunc CipherFunction) (key []byte, err error) {
        keySize := cipherFunc.KeySize()
        if keySize == 0 {
-               return nil, error_.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
+               return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
        }
 
        s2kBuf := new(bytes.Buffer)
index dff776e..e99a23b 100644 (file)
@@ -6,8 +6,7 @@ package packet
 
 import (
        "crypto/cipher"
-       error_ "crypto/openpgp/error"
-       "crypto/rand"
+       "crypto/openpgp/errors"
        "crypto/sha1"
        "crypto/subtle"
        "hash"
@@ -35,7 +34,7 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
                        return err
                }
                if buf[0] != symmetricallyEncryptedVersion {
-                       return error_.UnsupportedError("unknown SymmetricallyEncrypted version")
+                       return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
                }
        }
        se.contents = r
@@ -48,10 +47,10 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
 func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
        keySize := c.KeySize()
        if keySize == 0 {
-               return nil, error_.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
+               return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
        }
        if len(key) != keySize {
-               return nil, error_.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
+               return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
        }
 
        if se.prefix == nil {
@@ -61,7 +60,7 @@ func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.Read
                        return nil, err
                }
        } else if len(se.prefix) != c.blockSize()+2 {
-               return nil, error_.InvalidArgumentError("can't try ciphers with different block lengths")
+               return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
        }
 
        ocfbResync := cipher.OCFBResync
@@ -72,7 +71,7 @@ func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.Read
 
        s := cipher.NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
        if s == nil {
-               return nil, error_.KeyIncorrectError
+               return nil, errors.KeyIncorrectError
        }
 
        plaintext := cipher.StreamReader{S: s, R: se.contents}
@@ -181,7 +180,7 @@ const mdcPacketTagByte = byte(0x80) | 0x40 | 19
 
 func (ser *seMDCReader) Close() error {
        if ser.error {
-               return error_.SignatureError("error during reading")
+               return errors.SignatureError("error during reading")
        }
 
        for !ser.eof {
@@ -192,18 +191,18 @@ func (ser *seMDCReader) Close() error {
                        break
                }
                if err != nil {
-                       return error_.SignatureError("error during reading")
+                       return errors.SignatureError("error during reading")
                }
        }
 
        if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
-               return error_.SignatureError("MDC packet not found")
+               return errors.SignatureError("MDC packet not found")
        }
        ser.h.Write(ser.trailer[:2])
 
        final := ser.h.Sum(nil)
        if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
-               return error_.SignatureError("hash mismatch")
+               return errors.SignatureError("hash mismatch")
        }
        return nil
 }
@@ -253,9 +252,9 @@ func (c noOpCloser) Close() error {
 // SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
 // to w and returns a WriteCloser to which the to-be-encrypted packets can be
 // written.
-func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte) (contents io.WriteCloser, err error) {
+func SerializeSymmetricallyEncrypted(w io.Writer, rand io.Reader, c CipherFunction, key []byte) (contents io.WriteCloser, err error) {
        if c.KeySize() != len(key) {
-               return nil, error_.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
+               return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
        }
        writeCloser := noOpCloser{w}
        ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
@@ -271,7 +270,7 @@ func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte)
        block := c.new(key)
        blockSize := block.BlockSize()
        iv := make([]byte, blockSize)
-       _, err = rand.Reader.Read(iv)
+       _, err = rand.Read(iv)
        if err != nil {
                return
        }
index 8eee971..f7d133d 100644 (file)
@@ -6,7 +6,8 @@ package packet
 
 import (
        "bytes"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
+       "crypto/rand"
        "crypto/sha1"
        "encoding/hex"
        "io"
@@ -70,7 +71,7 @@ func testMDCReader(t *testing.T) {
        err = mdcReader.Close()
        if err == nil {
                t.Error("corruption: no error")
-       } else if _, ok := err.(*error_.SignatureError); !ok {
+       } else if _, ok := err.(*errors.SignatureError); !ok {
                t.Errorf("corruption: expected SignatureError, got: %s", err)
        }
 }
@@ -82,7 +83,7 @@ func TestSerialize(t *testing.T) {
        c := CipherAES128
        key := make([]byte, c.KeySize())
 
-       w, err := SerializeSymmetricallyEncrypted(buf, c, key)
+       w, err := SerializeSymmetricallyEncrypted(buf, rand.Reader, c, key)
        if err != nil {
                t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
                return
index 76fb1ea..1d23434 100644 (file)
@@ -8,7 +8,7 @@ package openpgp
 import (
        "crypto"
        "crypto/openpgp/armor"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/openpgp/packet"
        _ "crypto/sha256"
        "hash"
@@ -27,7 +27,7 @@ func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
        }
 
        if block.Type != expectedType {
-               return nil, error_.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
+               return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
        }
 
        return block.Body, nil
@@ -130,7 +130,7 @@ ParsePackets:
                case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
                        // This message isn't encrypted.
                        if len(symKeys) != 0 || len(pubKeys) != 0 {
-                               return nil, error_.StructuralError("key material not followed by encrypted message")
+                               return nil, errors.StructuralError("key material not followed by encrypted message")
                        }
                        packets.Unread(p)
                        return readSignedMessage(packets, nil, keyring)
@@ -161,7 +161,7 @@ FindKey:
                                        continue
                                }
                                decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
-                               if err != nil && err != error_.KeyIncorrectError {
+                               if err != nil && err != errors.KeyIncorrectError {
                                        return nil, err
                                }
                                if decrypted != nil {
@@ -179,11 +179,11 @@ FindKey:
                }
 
                if len(candidates) == 0 && len(symKeys) == 0 {
-                       return nil, error_.KeyIncorrectError
+                       return nil, errors.KeyIncorrectError
                }
 
                if prompt == nil {
-                       return nil, error_.KeyIncorrectError
+                       return nil, errors.KeyIncorrectError
                }
 
                passphrase, err := prompt(candidates, len(symKeys) != 0)
@@ -197,7 +197,7 @@ FindKey:
                                err = s.Decrypt(passphrase)
                                if err == nil && !s.Encrypted {
                                        decrypted, err = se.Decrypt(s.CipherFunc, s.Key)
-                                       if err != nil && err != error_.KeyIncorrectError {
+                                       if err != nil && err != errors.KeyIncorrectError {
                                                return nil, err
                                        }
                                        if decrypted != nil {
@@ -237,7 +237,7 @@ FindLiteralData:
                        packets.Push(p.Body)
                case *packet.OnePassSignature:
                        if !p.IsLast {
-                               return nil, error_.UnsupportedError("nested signatures")
+                               return nil, errors.UnsupportedError("nested signatures")
                        }
 
                        h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
@@ -281,7 +281,7 @@ FindLiteralData:
 func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
        h := hashId.New()
        if h == nil {
-               return nil, nil, error_.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
+               return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
        }
 
        switch sigType {
@@ -291,7 +291,7 @@ func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Ha
                return h, NewCanonicalTextHash(h), nil
        }
 
-       return nil, nil, error_.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
+       return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
 }
 
 // checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
@@ -333,7 +333,7 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
 
                var ok bool
                if scr.md.Signature, ok = p.(*packet.Signature); !ok {
-                       scr.md.SignatureError = error_.StructuralError("LiteralData not followed by Signature")
+                       scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
                        return
                }
 
@@ -363,16 +363,16 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe
 
        sig, ok := p.(*packet.Signature)
        if !ok {
-               return nil, error_.StructuralError("non signature packet found")
+               return nil, errors.StructuralError("non signature packet found")
        }
 
        if sig.IssuerKeyId == nil {
-               return nil, error_.StructuralError("signature doesn't have an issuer")
+               return nil, errors.StructuralError("signature doesn't have an issuer")
        }
 
        keys := keyring.KeysById(*sig.IssuerKeyId)
        if len(keys) == 0 {
-               return nil, error_.UnknownIssuerError
+               return nil, errors.UnknownIssuerError
        }
 
        h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
@@ -399,7 +399,7 @@ func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signe
                return
        }
 
-       return nil, error_.UnknownIssuerError
+       return nil, errors.UnknownIssuerError
 }
 
 // CheckArmoredDetachedSignature performs the same actions as
index e8a6bf5..d1ecad3 100644 (file)
@@ -6,7 +6,8 @@ package openpgp
 
 import (
        "bytes"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
+       _ "crypto/sha512"
        "encoding/hex"
        "io"
        "io/ioutil"
@@ -77,6 +78,15 @@ func TestReadDSAKey(t *testing.T) {
        }
 }
 
+func TestDSAHashTruncatation(t *testing.T) {
+       // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo
+       // SHA512 in order to require DSA hash truncation to verify correctly.
+       _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512))
+       if err != nil {
+               t.Error(err)
+       }
+}
+
 func TestGetKeyById(t *testing.T) {
        kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
 
@@ -151,18 +161,18 @@ func TestSignedEncryptedMessage(t *testing.T) {
                prompt := func(keys []Key, symmetric bool) ([]byte, error) {
                        if symmetric {
                                t.Errorf("prompt: message was marked as symmetrically encrypted")
-                               return nil, error_.KeyIncorrectError
+                               return nil, errors.KeyIncorrectError
                        }
 
                        if len(keys) == 0 {
                                t.Error("prompt: no keys requested")
-                               return nil, error_.KeyIncorrectError
+                               return nil, errors.KeyIncorrectError
                        }
 
                        err := keys[0].PrivateKey.Decrypt([]byte("passphrase"))
                        if err != nil {
                                t.Errorf("prompt: error decrypting key: %s", err)
-                               return nil, error_.KeyIncorrectError
+                               return nil, errors.KeyIncorrectError
                        }
 
                        return nil, nil
@@ -286,7 +296,7 @@ func TestReadingArmoredPrivateKey(t *testing.T) {
 
 func TestNoArmoredData(t *testing.T) {
        _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
-       if _, ok := err.(error_.InvalidArgumentError); !ok {
+       if _, ok := err.(errors.InvalidArgumentError); !ok {
                t.Errorf("error was not an InvalidArgumentError: %s", err)
        }
 }
@@ -358,3 +368,5 @@ AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
 VrM0m72/jnpKo04=
 =zNCn
 -----END PGP PRIVATE KEY BLOCK-----`
+
+const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003`
index 8bc0bb3..39479a1 100644 (file)
@@ -8,7 +8,7 @@ package s2k
 
 import (
        "crypto"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "hash"
        "io"
        "strconv"
@@ -89,11 +89,11 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) {
 
        hash, ok := HashIdToHash(buf[1])
        if !ok {
-               return nil, error_.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
+               return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
        }
        h := hash.New()
        if h == nil {
-               return nil, error_.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
+               return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
        }
 
        switch buf[0] {
@@ -123,7 +123,7 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) {
                return f, nil
        }
 
-       return nil, error_.UnsupportedError("S2K function")
+       return nil, errors.UnsupportedError("S2K function")
 }
 
 // Serialize salts and stretches the given passphrase and writes the resulting
index bdee57d..73daa11 100644 (file)
@@ -7,7 +7,7 @@ package openpgp
 import (
        "crypto"
        "crypto/openpgp/armor"
-       error_ "crypto/openpgp/error"
+       "crypto/openpgp/errors"
        "crypto/openpgp/packet"
        "crypto/openpgp/s2k"
        "crypto/rand"
@@ -58,10 +58,10 @@ func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType p
 
 func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err error) {
        if signer.PrivateKey == nil {
-               return error_.InvalidArgumentError("signing key doesn't have a private key")
+               return errors.InvalidArgumentError("signing key doesn't have a private key")
        }
        if signer.PrivateKey.Encrypted {
-               return error_.InvalidArgumentError("signing key is encrypted")
+               return errors.InvalidArgumentError("signing key is encrypted")
        }
 
        sig := new(packet.Signature)
@@ -77,7 +77,7 @@ func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.S
        }
        io.Copy(wrappedHash, message)
 
-       err = sig.Sign(h, signer.PrivateKey)
+       err = sig.Sign(rand.Reader, h, signer.PrivateKey)
        if err != nil {
                return
        }
@@ -111,7 +111,7 @@ func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHi
        if err != nil {
                return
        }
-       w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, packet.CipherAES128, key)
+       w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, rand.Reader, packet.CipherAES128, key)
        if err != nil {
                return
        }
@@ -156,7 +156,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
        if signed != nil {
                signer = signed.signingKey().PrivateKey
                if signer == nil || signer.Encrypted {
-                       return nil, error_.InvalidArgumentError("signing key must be decrypted")
+                       return nil, errors.InvalidArgumentError("signing key must be decrypted")
                }
        }
 
@@ -183,7 +183,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
        for i := range to {
                encryptKeys[i] = to[i].encryptionKey()
                if encryptKeys[i].PublicKey == nil {
-                       return nil, error_.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
+                       return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
                }
 
                sig := to[i].primaryIdentity().SelfSignature
@@ -201,7 +201,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
        }
 
        if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
-               return nil, error_.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
+               return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
        }
 
        cipher := packet.CipherFunction(candidateCiphers[0])
@@ -217,7 +217,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
                }
        }
 
-       encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey)
+       encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, rand.Reader, cipher, symKey)
        if err != nil {
                return
        }
@@ -287,7 +287,7 @@ func (s signatureWriter) Close() error {
                IssuerKeyId:  &s.signer.KeyId,
        }
 
-       if err := sig.Sign(s.h, s.signer); err != nil {
+       if err := sig.Sign(rand.Reader, s.h, s.signer); err != nil {
                return err
        }
        if err := s.literalData.Close(); err != nil {
index 02fa5b7..7df02e7 100644 (file)
@@ -222,7 +222,7 @@ func TestEncryption(t *testing.T) {
 
                if test.isSigned {
                        if md.SignatureError != nil {
-                               t.Errorf("#%d: signature error: %s", i, err)
+                               t.Errorf("#%d: signature error: %s", i, md.SignatureError)
                        }
                        if md.Signature == nil {
                                t.Error("signature missing")
index a461ad9..25f7a92 100644 (file)
@@ -111,6 +111,18 @@ type ConnectionState struct {
        VerifiedChains [][]*x509.Certificate
 }
 
+// ClientAuthType declares the policy the server will follow for
+// TLS Client Authentication.
+type ClientAuthType int
+
+const (
+       NoClientCert ClientAuthType = iota
+       RequestClientCert
+       RequireAnyClientCert
+       VerifyClientCertIfGiven
+       RequireAndVerifyClientCert
+)
+
 // A Config structure is used to configure a TLS client or server. After one
 // has been passed to a TLS function it must not be modified.
 type Config struct {
@@ -120,7 +132,7 @@ type Config struct {
        Rand io.Reader
 
        // Time returns the current time as the number of seconds since the epoch.
-       // If Time is nil, TLS uses the system time.Seconds.
+       // If Time is nil, TLS uses time.Now.
        Time func() time.Time
 
        // Certificates contains one or more certificate chains
@@ -148,11 +160,14 @@ type Config struct {
        // hosting.
        ServerName string
 
-       // AuthenticateClient controls whether a server will request a certificate
-       // from the client. It does not require that the client send a
-       // certificate nor does it require that the certificate sent be
-       // anything more than self-signed.
-       AuthenticateClient bool
+       // ClientAuth determines the server's policy for
+       // TLS Client Authentication. The default is NoClientCert.
+       ClientAuth ClientAuthType
+
+       // ClientCAs defines the set of root certificate authorities
+       // that servers use if required to verify a client certificate
+       // by the policy in ClientAuth.
+       ClientCAs *x509.CertPool
 
        // InsecureSkipVerify controls whether a client verifies the
        // server's certificate chain and host name.
@@ -259,6 +274,11 @@ type Certificate struct {
        // OCSPStaple contains an optional OCSP response which will be served
        // to clients that request it.
        OCSPStaple []byte
+       // Leaf is the parsed form of the leaf certificate, which may be
+       // initialized using x509.ParseCertificate to reduce per-handshake
+       // processing for TLS clients doing client authentication. If nil, the
+       // leaf certificate will be parsed as needed.
+       Leaf *x509.Certificate
 }
 
 // A TLS record.
index c4463ff..7c0718b 100644 (file)
@@ -31,7 +31,7 @@ func main() {
                return
        }
 
-       now := time.Seconds()
+       now := time.Now()
 
        template := x509.Certificate{
                SerialNumber: new(big.Int).SetInt64(0),
@@ -39,8 +39,8 @@ func main() {
                        CommonName:   *hostName,
                        Organization: []string{"Acme Co"},
                },
-               NotBefore: time.SecondsToUTC(now - 300),
-               NotAfter:  time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.
+               NotBefore: now.Add(-5 * time.Minute).UTC(),
+               NotAfter:  now.AddDate(1, 0, 0).UTC(), // valid for 1 year.
 
                SubjectKeyId: []byte{1, 2, 3, 4},
                KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
index 7364800..632ceea 100644 (file)
@@ -5,12 +5,14 @@
 package tls
 
 import (
+       "bytes"
        "crypto"
        "crypto/rsa"
        "crypto/subtle"
        "crypto/x509"
        "errors"
        "io"
+       "strconv"
 )
 
 func (c *Conn) clientHandshake() error {
@@ -162,10 +164,23 @@ func (c *Conn) clientHandshake() error {
                }
        }
 
-       transmitCert := false
+       var certToSend *Certificate
        certReq, ok := msg.(*certificateRequestMsg)
        if ok {
-               // We only accept certificates with RSA keys.
+               // RFC 4346 on the certificateAuthorities field:
+               // A list of the distinguished names of acceptable certificate
+               // authorities. These distinguished names may specify a desired
+               // distinguished name for a root CA or for a subordinate CA;
+               // thus, this message can be used to describe both known roots
+               // and a desired authorization space. If the
+               // certificate_authorities list is empty then the client MAY
+               // send any certificate of the appropriate
+               // ClientCertificateType, unless there is some external
+               // arrangement to the contrary.
+
+               finishedHash.Write(certReq.marshal())
+
+               // For now, we only know how to sign challenges with RSA
                rsaAvail := false
                for _, certType := range certReq.certificateTypes {
                        if certType == certTypeRSASign {
@@ -174,23 +189,41 @@ func (c *Conn) clientHandshake() error {
                        }
                }
 
-               // For now, only send a certificate back if the server gives us an
-               // empty list of certificateAuthorities.
-               //
-               // RFC 4346 on the certificateAuthorities field:
-               // A list of the distinguished names of acceptable certificate
-               // authorities.  These distinguished names may specify a desired
-               // distinguished name for a root CA or for a subordinate CA; thus,
-               // this message can be used to describe both known roots and a
-               // desired authorization space.  If the certificate_authorities
-               // list is empty then the client MAY send any certificate of the
-               // appropriate ClientCertificateType, unless there is some
-               // external arrangement to the contrary.
-               if rsaAvail && len(certReq.certificateAuthorities) == 0 {
-                       transmitCert = true
-               }
+               // We need to search our list of client certs for one
+               // where SignatureAlgorithm is RSA and the Issuer is in
+               // certReq.certificateAuthorities
+       findCert:
+               for i, cert := range c.config.Certificates {
+                       if !rsaAvail {
+                               continue
+                       }
 
-               finishedHash.Write(certReq.marshal())
+                       leaf := cert.Leaf
+                       if leaf == nil {
+                               if leaf, err = x509.ParseCertificate(cert.Certificate[0]); err != nil {
+                                       c.sendAlert(alertInternalError)
+                                       return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+                               }
+                       }
+
+                       if leaf.PublicKeyAlgorithm != x509.RSA {
+                               continue
+                       }
+
+                       if len(certReq.certificateAuthorities) == 0 {
+                               // they gave us an empty list, so just take the
+                               // first RSA cert from c.config.Certificates
+                               certToSend = &cert
+                               break
+                       }
+
+                       for _, ca := range certReq.certificateAuthorities {
+                               if bytes.Equal(leaf.RawIssuer, ca) {
+                                       certToSend = &cert
+                                       break findCert
+                               }
+                       }
+               }
 
                msg, err = c.readHandshake()
                if err != nil {
@@ -204,17 +237,9 @@ func (c *Conn) clientHandshake() error {
        }
        finishedHash.Write(shd.marshal())
 
-       var cert *x509.Certificate
-       if transmitCert {
+       if certToSend != nil {
                certMsg = new(certificateMsg)
-               if len(c.config.Certificates) > 0 {
-                       cert, err = x509.ParseCertificate(c.config.Certificates[0].Certificate[0])
-                       if err == nil && cert.PublicKeyAlgorithm == x509.RSA {
-                               certMsg.certificates = c.config.Certificates[0].Certificate
-                       } else {
-                               cert = nil
-                       }
-               }
+               certMsg.certificates = certToSend.Certificate
                finishedHash.Write(certMsg.marshal())
                c.writeRecord(recordTypeHandshake, certMsg.marshal())
        }
@@ -229,7 +254,7 @@ func (c *Conn) clientHandshake() error {
                c.writeRecord(recordTypeHandshake, ckx.marshal())
        }
 
-       if cert != nil {
+       if certToSend != nil {
                certVerify := new(certificateVerifyMsg)
                digest := make([]byte, 0, 36)
                digest = finishedHash.serverMD5.Sum(digest)
index 5438e74..e1517cc 100644 (file)
@@ -881,9 +881,11 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
 
        // See http://tools.ietf.org/html/rfc4346#section-7.4.4
        length := 1 + len(m.certificateTypes) + 2
+       casLength := 0
        for _, ca := range m.certificateAuthorities {
-               length += 2 + len(ca)
+               casLength += 2 + len(ca)
        }
+       length += casLength
 
        x = make([]byte, 4+length)
        x[0] = typeCertificateRequest
@@ -895,10 +897,8 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
 
        copy(x[5:], m.certificateTypes)
        y := x[5+len(m.certificateTypes):]
-
-       numCA := len(m.certificateAuthorities)
-       y[0] = uint8(numCA >> 8)
-       y[1] = uint8(numCA)
+       y[0] = uint8(casLength >> 8)
+       y[1] = uint8(casLength)
        y = y[2:]
        for _, ca := range m.certificateAuthorities {
                y[0] = uint8(len(ca) >> 8)
@@ -909,7 +909,6 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
        }
 
        m.raw = x
-
        return
 }
 
@@ -937,31 +936,34 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
        }
 
        data = data[numCertTypes:]
+
        if len(data) < 2 {
                return false
        }
-
-       numCAs := uint16(data[0])<<16 | uint16(data[1])
+       casLength := uint16(data[0])<<8 | uint16(data[1])
        data = data[2:]
+       if len(data) < int(casLength) {
+               return false
+       }
+       cas := make([]byte, casLength)
+       copy(cas, data)
+       data = data[casLength:]
 
-       m.certificateAuthorities = make([][]byte, numCAs)
-       for i := uint16(0); i < numCAs; i++ {
-               if len(data) < 2 {
+       m.certificateAuthorities = nil
+       for len(cas) > 0 {
+               if len(cas) < 2 {
                        return false
                }
-               caLen := uint16(data[0])<<16 | uint16(data[1])
+               caLen := uint16(cas[0])<<8 | uint16(cas[1])
+               cas = cas[2:]
 
-               data = data[2:]
-               if len(data) < int(caLen) {
+               if len(cas) < int(caLen) {
                        return false
                }
 
-               ca := make([]byte, caLen)
-               copy(ca, data)
-               m.certificateAuthorities[i] = ca
-               data = data[caLen:]
+               m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
+               cas = cas[caLen:]
        }
-
        if len(data) > 0 {
                return false
        }
index 89c000d..fb53767 100644 (file)
@@ -150,14 +150,19 @@ FindCipherSuite:
                c.writeRecord(recordTypeHandshake, skx.marshal())
        }
 
-       if config.AuthenticateClient {
+       if config.ClientAuth >= RequestClientCert {
                // Request a client certificate
                certReq := new(certificateRequestMsg)
                certReq.certificateTypes = []byte{certTypeRSASign}
+
                // An empty list of certificateAuthorities signals to
                // the client that it may send any certificate in response
-               // to our request.
-
+               // to our request. When we know the CAs we trust, then
+               // we can send them down, so that the client can choose
+               // an appropriate certificate to give to us.
+               if config.ClientCAs != nil {
+                       certReq.certificateAuthorities = config.ClientCAs.Subjects()
+               }
                finishedHash.Write(certReq.marshal())
                c.writeRecord(recordTypeHandshake, certReq.marshal())
        }
@@ -166,52 +171,87 @@ FindCipherSuite:
        finishedHash.Write(helloDone.marshal())
        c.writeRecord(recordTypeHandshake, helloDone.marshal())
 
-       var pub *rsa.PublicKey
-       if config.AuthenticateClient {
-               // Get client certificate
-               msg, err = c.readHandshake()
-               if err != nil {
-                       return err
-               }
-               certMsg, ok = msg.(*certificateMsg)
-               if !ok {
-                       return c.sendAlert(alertUnexpectedMessage)
+       var pub *rsa.PublicKey // public key for client auth, if any
+
+       msg, err = c.readHandshake()
+       if err != nil {
+               return err
+       }
+
+       // If we requested a client certificate, then the client must send a
+       // certificate message, even if it's empty.
+       if config.ClientAuth >= RequestClientCert {
+               if certMsg, ok = msg.(*certificateMsg); !ok {
+                       return c.sendAlert(alertHandshakeFailure)
                }
                finishedHash.Write(certMsg.marshal())
 
+               if len(certMsg.certificates) == 0 {
+                       // The client didn't actually send a certificate
+                       switch config.ClientAuth {
+                       case RequireAnyClientCert, RequireAndVerifyClientCert:
+                               c.sendAlert(alertBadCertificate)
+                               return errors.New("tls: client didn't provide a certificate")
+                       }
+               }
+
                certs := make([]*x509.Certificate, len(certMsg.certificates))
                for i, asn1Data := range certMsg.certificates {
-                       cert, err := x509.ParseCertificate(asn1Data)
-                       if err != nil {
+                       if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
                                c.sendAlert(alertBadCertificate)
-                               return errors.New("could not parse client's certificate: " + err.Error())
+                               return errors.New("tls: failed to parse client certificate: " + err.Error())
                        }
-                       certs[i] = cert
                }
 
-               // TODO(agl): do better validation of certs: max path length, name restrictions etc.
-               for i := 1; i < len(certs); i++ {
-                       if err := certs[i-1].CheckSignatureFrom(certs[i]); err != nil {
+               if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
+                       opts := x509.VerifyOptions{
+                               Roots:         c.config.ClientCAs,
+                               CurrentTime:   c.config.time(),
+                               Intermediates: x509.NewCertPool(),
+                       }
+
+                       for i, cert := range certs {
+                               if i == 0 {
+                                       continue
+                               }
+                               opts.Intermediates.AddCert(cert)
+                       }
+
+                       chains, err := certs[0].Verify(opts)
+                       if err != nil {
                                c.sendAlert(alertBadCertificate)
-                               return errors.New("could not validate certificate signature: " + err.Error())
+                               return errors.New("tls: failed to verify client's certificate: " + err.Error())
                        }
+
+                       ok := false
+                       for _, ku := range certs[0].ExtKeyUsage {
+                               if ku == x509.ExtKeyUsageClientAuth {
+                                       ok = true
+                                       break
+                               }
+                       }
+                       if !ok {
+                               c.sendAlert(alertHandshakeFailure)
+                               return errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
+                       }
+
+                       c.verifiedChains = chains
                }
 
                if len(certs) > 0 {
-                       key, ok := certs[0].PublicKey.(*rsa.PublicKey)
-                       if !ok {
+                       if pub, ok = certs[0].PublicKey.(*rsa.PublicKey); !ok {
                                return c.sendAlert(alertUnsupportedCertificate)
                        }
-                       pub = key
                        c.peerCertificates = certs
                }
+
+               msg, err = c.readHandshake()
+               if err != nil {
+                       return err
+               }
        }
 
        // Get client key exchange
-       msg, err = c.readHandshake()
-       if err != nil {
-               return err
-       }
        ckx, ok := msg.(*clientKeyExchangeMsg)
        if !ok {
                return c.sendAlert(alertUnexpectedMessage)
index d98e13d..4bff532 100644 (file)
@@ -7,9 +7,12 @@ package tls
 import (
        "bytes"
        "crypto/rsa"
+       "crypto/x509"
        "encoding/hex"
+       "encoding/pem"
        "flag"
        "io"
+       "log"
        "math/big"
        "net"
        "strconv"
@@ -109,16 +112,18 @@ func TestClose(t *testing.T) {
        }
 }
 
-func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config) {
+func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config, peers []*x509.Certificate) {
        c, s := net.Pipe()
        srv := Server(s, config)
+       pchan := make(chan []*x509.Certificate, 1)
        go func() {
                srv.Write([]byte("hello, world\n"))
                srv.Close()
                s.Close()
+               st := srv.ConnectionState()
+               pchan <- st.PeerCertificates
        }()
 
-       defer c.Close()
        for i, b := range serverScript {
                if i%2 == 0 {
                        c.Write(b)
@@ -133,34 +138,66 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config *
                        t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
                }
        }
+       c.Close()
+
+       if peers != nil {
+               gotpeers := <-pchan
+               if len(peers) == len(gotpeers) {
+                       for i, _ := range peers {
+                               if !peers[i].Equal(gotpeers[i]) {
+                                       t.Fatalf("%s: mismatch on peer cert %d", name, i)
+                               }
+                       }
+               } else {
+                       t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", name, len(peers), len(gotpeers))
+               }
+       }
 }
 
 func TestHandshakeServerRC4(t *testing.T) {
-       testServerScript(t, "RC4", rc4ServerScript, testConfig)
+       testServerScript(t, "RC4", rc4ServerScript, testConfig, nil)
 }
 
 func TestHandshakeServer3DES(t *testing.T) {
        des3Config := new(Config)
        *des3Config = *testConfig
        des3Config.CipherSuites = []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA}
-       testServerScript(t, "3DES", des3ServerScript, des3Config)
+       testServerScript(t, "3DES", des3ServerScript, des3Config, nil)
 }
 
 func TestHandshakeServerAES(t *testing.T) {
        aesConfig := new(Config)
        *aesConfig = *testConfig
        aesConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}
-       testServerScript(t, "AES", aesServerScript, aesConfig)
+       testServerScript(t, "AES", aesServerScript, aesConfig, nil)
 }
 
 func TestHandshakeServerSSLv3(t *testing.T) {
-       testServerScript(t, "SSLv3", sslv3ServerScript, testConfig)
+       testServerScript(t, "SSLv3", sslv3ServerScript, testConfig, nil)
+}
+
+type clientauthTest struct {
+       name       string
+       clientauth ClientAuthType
+       peers      []*x509.Certificate
+       script     [][]byte
+}
+
+func TestClientAuth(t *testing.T) {
+       for _, cat := range clientauthTests {
+               t.Log("running", cat.name)
+               cfg := new(Config)
+               *cfg = *testConfig
+               cfg.ClientAuth = cat.clientauth
+               testServerScript(t, cat.name, cat.script, cfg, cat.peers)
+       }
 }
 
 var serve = flag.Bool("serve", false, "run a TLS server on :10443")
 var testCipherSuites = flag.String("ciphersuites",
        "0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
        "cipher suites to accept in serving mode")
+var testClientAuth = flag.Int("clientauth", 0, "value for tls.Config.ClientAuth")
 
 func TestRunServer(t *testing.T) {
        if !*serve {
@@ -177,6 +214,8 @@ func TestRunServer(t *testing.T) {
                testConfig.CipherSuites[i] = uint16(suite)
        }
 
+       testConfig.ClientAuth = ClientAuthType(*testClientAuth)
+
        l, err := Listen("tcp", ":10443", testConfig)
        if err != nil {
                t.Fatal(err)
@@ -185,13 +224,23 @@ func TestRunServer(t *testing.T) {
        for {
                c, err := l.Accept()
                if err != nil {
+                       log.Printf("error from TLS handshake: %s", err)
                        break
                }
+
                _, err = c.Write([]byte("hello, world\n"))
                if err != nil {
-                       t.Errorf("error from TLS: %s", err)
-                       break
+                       log.Printf("error from TLS: %s", err)
+                       continue
                }
+
+               st := c.(*Conn).ConnectionState()
+               if len(st.PeerCertificates) > 0 {
+                       log.Print("Handling request from client ", st.PeerCertificates[0].Subject.CommonName)
+               } else {
+                       log.Print("Handling request from anon client")
+               }
+
                c.Close()
        }
 }
@@ -221,6 +270,18 @@ var testPrivateKey = &rsa.PrivateKey{
        },
 }
 
+func loadPEMCert(in string) *x509.Certificate {
+       block, _ := pem.Decode([]byte(in))
+       if block.Type == "CERTIFICATE" && len(block.Headers) == 0 {
+               cert, err := x509.ParseCertificate(block.Bytes)
+               if err == nil {
+                       return cert
+               }
+               panic("error parsing cert")
+       }
+       panic("error parsing PEM")
+}
+
 // Script of interaction with gnutls implementation.
 // The values for this test are obtained by building and running in server mode:
 //   % gotest -test.run "TestRunServer" -serve
@@ -229,23 +290,22 @@ var testPrivateKey = &rsa.PrivateKey{
 //   % python parse-gnutls-cli-debug-log.py < /tmp/log
 var rc4ServerScript = [][]byte{
        {
-               0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
-               0x7b, 0x03, 0x02, 0x4d, 0x08, 0x1f, 0x5a, 0x7a,
-               0x0a, 0x92, 0x2f, 0xf0, 0x73, 0x16, 0x3a, 0x88,
-               0x14, 0x85, 0x4c, 0x98, 0x15, 0x7b, 0x65, 0xe0,
-               0x78, 0xd0, 0xed, 0xd0, 0xf3, 0x65, 0x20, 0xeb,
-               0x80, 0xd1, 0x0b, 0x00, 0x00, 0x34, 0x00, 0x33,
+               0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+               0x76, 0x03, 0x02, 0x4e, 0xdd, 0xe6, 0xa5, 0xf7,
+               0x00, 0x36, 0xf7, 0x83, 0xec, 0x93, 0x7c, 0xd2,
+               0x4d, 0xe7, 0x7b, 0xf5, 0x4c, 0xf7, 0xe3, 0x86,
+               0xe8, 0xec, 0x3b, 0xbd, 0x2c, 0x9a, 0x3f, 0x57,
+               0xf0, 0xa4, 0xd4, 0x00, 0x00, 0x34, 0x00, 0x33,
                0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
                0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
                0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
                0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
                0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
                0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
-               0x00, 0x8a, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x09,
+               0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
                0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
-               0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0xff,
-               0x01, 0x00, 0x01, 0x00,
+               0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
        },
 
        {
@@ -349,38 +409,46 @@ var rc4ServerScript = [][]byte{
 
        {
                0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
-               0x82, 0x00, 0x80, 0x3c, 0x13, 0xd7, 0x12, 0xc1,
-               0x6a, 0xf0, 0x3f, 0x8c, 0xa1, 0x35, 0x5d, 0xc5,
-               0x89, 0x1e, 0x9e, 0xcd, 0x32, 0xc7, 0x9e, 0xe6,
-               0xae, 0xd5, 0xf1, 0xbf, 0x70, 0xd7, 0xa9, 0xef,
-               0x2c, 0x4c, 0xf4, 0x22, 0xbc, 0x17, 0x17, 0xaa,
-               0x05, 0xf3, 0x9f, 0x80, 0xf2, 0xe9, 0x82, 0x2f,
-               0x2a, 0x15, 0x54, 0x0d, 0x16, 0x0e, 0x77, 0x4c,
-               0x28, 0x3c, 0x03, 0x2d, 0x2d, 0xd7, 0xc8, 0x64,
-               0xd9, 0x59, 0x4b, 0x1c, 0xf4, 0xde, 0xff, 0x2f,
-               0xbc, 0x94, 0xaf, 0x18, 0x26, 0x37, 0xce, 0x4f,
-               0x84, 0x74, 0x2e, 0x45, 0x66, 0x7c, 0x0c, 0x54,
-               0x46, 0x36, 0x5f, 0x65, 0x21, 0x7b, 0x83, 0x8c,
-               0x6d, 0x76, 0xcd, 0x0d, 0x9f, 0xda, 0x1c, 0xa4,
-               0x6e, 0xfe, 0xb1, 0xf7, 0x09, 0x0d, 0xfb, 0x74,
-               0x66, 0x34, 0x99, 0x89, 0x7f, 0x5f, 0x77, 0x87,
-               0x4a, 0x66, 0x4b, 0xa9, 0x59, 0x57, 0xe3, 0x56,
-               0x0d, 0xdd, 0xd8, 0x14, 0x03, 0x01, 0x00, 0x01,
-               0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc0, 0x4e,
-               0xd3, 0x0f, 0xb5, 0xc0, 0x57, 0xa6, 0x18, 0x80,
-               0x80, 0x6b, 0x49, 0xfe, 0xbd, 0x3a, 0x7a, 0x2c,
-               0xef, 0x70, 0xb5, 0x1c, 0xd2, 0xdf, 0x5f, 0x78,
-               0x5a, 0xd8, 0x4f, 0xa0, 0x95, 0xb4, 0xb3, 0xb5,
-               0xaa, 0x3b,
+               0x82, 0x00, 0x80, 0x39, 0xe2, 0x0f, 0x49, 0xa0,
+               0xe6, 0xe4, 0x3b, 0x0c, 0x5f, 0xce, 0x39, 0x97,
+               0x6c, 0xb6, 0x41, 0xd9, 0xe1, 0x52, 0x8f, 0x43,
+               0xb3, 0xc6, 0x4f, 0x9a, 0xe2, 0x1e, 0xb9, 0x3b,
+               0xe3, 0x72, 0x17, 0x68, 0xb2, 0x0d, 0x7b, 0x71,
+               0x33, 0x96, 0x5c, 0xf9, 0xfe, 0x18, 0x8f, 0x2f,
+               0x2b, 0x82, 0xec, 0x03, 0xf2, 0x16, 0xa8, 0xf8,
+               0x39, 0xf9, 0xbb, 0x5a, 0xd3, 0x0c, 0xc1, 0x2a,
+               0x52, 0xa1, 0x90, 0x20, 0x6b, 0x24, 0xc9, 0x55,
+               0xee, 0x05, 0xd8, 0xb3, 0x43, 0x58, 0xf6, 0x7f,
+               0x68, 0x2d, 0xb3, 0xd1, 0x1b, 0x30, 0xaa, 0xdf,
+               0xfc, 0x85, 0xf1, 0xab, 0x14, 0x51, 0x91, 0x78,
+               0x29, 0x35, 0x65, 0xe0, 0x9c, 0xf6, 0xb7, 0x35,
+               0x33, 0xdb, 0x28, 0x93, 0x4d, 0x86, 0xbc, 0xfe,
+               0xaa, 0xd1, 0xc0, 0x2e, 0x4d, 0xec, 0xa2, 0x98,
+               0xca, 0x08, 0xb2, 0x91, 0x14, 0xde, 0x97, 0x3a,
+               0xc4, 0x6b, 0x49, 0x14, 0x03, 0x01, 0x00, 0x01,
+               0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x7a, 0xcb,
+               0x3b, 0x0e, 0xbb, 0x7a, 0x56, 0x39, 0xaf, 0x83,
+               0xae, 0xfd, 0x25, 0xfd, 0x64, 0xb4, 0x0c, 0x0c,
+               0x17, 0x46, 0x54, 0x2c, 0x6a, 0x07, 0x83, 0xc6,
+               0x46, 0x08, 0x0b, 0xcd, 0x15, 0x53, 0xef, 0x40,
+               0x4e, 0x56,
        },
 
        {
                0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
-               0x01, 0x00, 0x24, 0x9d, 0xc9, 0xda, 0xdf, 0xeb,
-               0xc8, 0xdb, 0xf8, 0x94, 0xa5, 0xef, 0xd5, 0xfc,
-               0x89, 0x01, 0x64, 0x30, 0x77, 0x5a, 0x18, 0x4b,
-               0x16, 0x79, 0x9c, 0xf6, 0xf5, 0x09, 0x22, 0x12,
-               0x4c, 0x3e, 0xa8, 0x8e, 0x91, 0xa5, 0x24,
+               0x01, 0x00, 0x24, 0xd3, 0x72, 0xeb, 0x29, 0xb9,
+               0x15, 0x29, 0xb5, 0xe5, 0xb7, 0xef, 0x5c, 0xb2,
+               0x9d, 0xf6, 0xc8, 0x47, 0xd6, 0xa0, 0x84, 0xf0,
+               0x8c, 0xcb, 0xe6, 0xbe, 0xbc, 0xfb, 0x38, 0x90,
+               0x89, 0x60, 0xa2, 0xe8, 0xaa, 0xb3, 0x12, 0x17,
+               0x03, 0x01, 0x00, 0x21, 0x67, 0x4a, 0x3d, 0x31,
+               0x6c, 0x5a, 0x1c, 0xf9, 0x6e, 0xf1, 0xd8, 0x12,
+               0x0e, 0xb9, 0xfd, 0xfc, 0x66, 0x91, 0xd1, 0x1d,
+               0x6e, 0xe4, 0x55, 0xdd, 0x11, 0xb9, 0xb8, 0xa2,
+               0x65, 0xa1, 0x95, 0x64, 0x1c, 0x15, 0x03, 0x01,
+               0x00, 0x16, 0x9b, 0xa0, 0x24, 0xe3, 0xcb, 0xae,
+               0xad, 0x51, 0xb3, 0x63, 0x59, 0x78, 0x49, 0x24,
+               0x06, 0x6e, 0xee, 0x7a, 0xd7, 0x74, 0x53, 0x04,
        },
 }
 
@@ -878,3 +946,625 @@ var sslv3ServerScript = [][]byte{
                0xaf, 0xd3, 0xb7, 0xa3, 0xcc, 0x4a, 0x1d, 0x2e,
        },
 }
+
+var clientauthTests = []clientauthTest{
+       // Server doesn't asks for cert
+       // gotest -test.run "TestRunServer" -serve -clientauth 0
+       // gnutls-cli --insecure --debug 100 -p 10443 localhost 2>&1 |
+       //   python parse-gnutls-cli-debug-log.py
+       {"NoClientCert", NoClientCert, nil,
+               [][]byte{{
+                       0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+                       0x76, 0x03, 0x02, 0x4e, 0xe0, 0x92, 0x5d, 0xcd,
+                       0xfe, 0x0c, 0x69, 0xd4, 0x7d, 0x8e, 0xa6, 0x88,
+                       0xde, 0x72, 0x04, 0x29, 0x6a, 0x4a, 0x16, 0x23,
+                       0xd7, 0x8f, 0xbc, 0xfa, 0x80, 0x73, 0x2e, 0x12,
+                       0xb7, 0x0b, 0x39, 0x00, 0x00, 0x34, 0x00, 0x33,
+                       0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+                       0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+                       0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+                       0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+                       0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+                       0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+                       0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+                       0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+                       0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+                       0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+               },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+                               0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+                               0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+                               0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+                               0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+                               0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+                               0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+                               0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+                               0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+                               0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+                               0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+                               0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+                               0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+                               0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+                               0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+                               0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+                               0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+                               0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+                               0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+                               0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+                               0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+                               0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+                               0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+                               0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+                               0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+                               0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+                               0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+                               0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+                               0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+                               0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+                               0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+                               0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+                               0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+                               0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+                               0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+                               0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+                               0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+                               0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+                               0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+                               0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+                               0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+                               0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+                               0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+                               0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+                               0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+                               0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+                               0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+                               0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+                               0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+                               0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+                               0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+                               0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+                               0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+                               0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+                               0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+                               0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+                               0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+                               0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+                               0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+                               0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+                               0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+                               0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+                               0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+                               0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+                               0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+                               0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+                               0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+                               0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+                               0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+                               0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+                               0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+                               0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+                               0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+                               0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+                               0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+                               0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+                               0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+                               0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+                               0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+                               0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+                               0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+                               0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+                               0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+                               0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+                               0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+                               0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
+                               0x00, 0x00, 0x00,
+                       },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+                               0x82, 0x00, 0x80, 0x10, 0xe1, 0x00, 0x3d, 0x0a,
+                               0x6b, 0x02, 0x7f, 0x97, 0xde, 0xfb, 0x65, 0x46,
+                               0x1a, 0x50, 0x4e, 0x34, 0x9a, 0xae, 0x14, 0x7e,
+                               0xec, 0xef, 0x85, 0x15, 0x3b, 0x39, 0xc2, 0x45,
+                               0x04, 0x40, 0x92, 0x71, 0xd6, 0x7e, 0xf6, 0xfd,
+                               0x4d, 0x84, 0xf7, 0xc4, 0x77, 0x99, 0x3d, 0xe2,
+                               0xc3, 0x8d, 0xb0, 0x4c, 0x74, 0xc8, 0x51, 0xec,
+                               0xb2, 0xe8, 0x6b, 0xa1, 0xd2, 0x4d, 0xd8, 0x61,
+                               0x92, 0x7a, 0x24, 0x57, 0x44, 0x4f, 0xa2, 0x1e,
+                               0x74, 0x0b, 0x06, 0x4b, 0x80, 0x34, 0x8b, 0xfe,
+                               0xc2, 0x0e, 0xc1, 0xcd, 0xab, 0x0c, 0x3f, 0x54,
+                               0xe2, 0x44, 0xe9, 0x6c, 0x2b, 0xba, 0x7b, 0x64,
+                               0xf1, 0x93, 0x65, 0x75, 0xf2, 0x35, 0xff, 0x27,
+                               0x03, 0xd5, 0x64, 0xe6, 0x8e, 0xe7, 0x7b, 0x56,
+                               0xb6, 0x61, 0x73, 0xeb, 0xa2, 0xdc, 0xa4, 0x6e,
+                               0x52, 0xac, 0xbc, 0xba, 0x11, 0xa3, 0xd2, 0x61,
+                               0x4a, 0xe0, 0xbb, 0x14, 0x03, 0x01, 0x00, 0x01,
+                               0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xd2, 0x5a,
+                               0x0c, 0x2a, 0x27, 0x96, 0xba, 0xa9, 0x67, 0xd2,
+                               0x51, 0x68, 0x32, 0x68, 0x22, 0x1f, 0xb9, 0x27,
+                               0x79, 0x59, 0x28, 0xdf, 0x38, 0x1f, 0x92, 0x21,
+                               0x5d, 0x0f, 0xf4, 0xc0, 0xee, 0xb7, 0x10, 0x5a,
+                               0xa9, 0x45,
+                       },
+
+                       {
+                               0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+                               0x01, 0x00, 0x24, 0x13, 0x6f, 0x6c, 0x71, 0x83,
+                               0x59, 0xcf, 0x32, 0x72, 0xe9, 0xce, 0xcc, 0x7a,
+                               0x6c, 0xf0, 0x72, 0x39, 0x16, 0xae, 0x40, 0x61,
+                               0xfa, 0x92, 0x4c, 0xe7, 0xf2, 0x1a, 0xd7, 0x0c,
+                               0x84, 0x76, 0x6c, 0xe9, 0x11, 0x43, 0x19, 0x17,
+                               0x03, 0x01, 0x00, 0x21, 0xc0, 0xa2, 0x13, 0x28,
+                               0x94, 0x8c, 0x5c, 0xd6, 0x79, 0xb9, 0xfe, 0xae,
+                               0x45, 0x4b, 0xc0, 0x7c, 0xae, 0x2d, 0xb4, 0x0d,
+                               0x31, 0xc4, 0xad, 0x22, 0xd7, 0x1e, 0x99, 0x1c,
+                               0x4c, 0x69, 0xab, 0x42, 0x61, 0x15, 0x03, 0x01,
+                               0x00, 0x16, 0xe1, 0x0c, 0x67, 0xf3, 0xf4, 0xb9,
+                               0x8e, 0x81, 0x8e, 0x01, 0xb8, 0xa0, 0x69, 0x8c,
+                               0x03, 0x11, 0x43, 0x3e, 0xee, 0xb7, 0x4d, 0x69,
+                       }}},
+       // Server asks for cert with empty CA list, client doesn't give it.
+       // gotest -test.run "TestRunServer" -serve -clientauth 1
+       // gnutls-cli --insecure --debug 100 -p 10443 localhost
+       {"RequestClientCert, none given", RequestClientCert, nil,
+               [][]byte{{
+                       0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+                       0x76, 0x03, 0x02, 0x4e, 0xe0, 0x93, 0xe2, 0x47,
+                       0x06, 0xa0, 0x61, 0x0c, 0x51, 0xdd, 0xf0, 0xef,
+                       0xf4, 0x30, 0x72, 0xe1, 0xa6, 0x50, 0x68, 0x82,
+                       0x3c, 0xfb, 0xcb, 0x72, 0x5e, 0x73, 0x9d, 0xda,
+                       0x27, 0x35, 0x72, 0x00, 0x00, 0x34, 0x00, 0x33,
+                       0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+                       0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+                       0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+                       0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+                       0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+                       0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+                       0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+                       0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+                       0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+                       0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+               },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+                               0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+                               0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+                               0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+                               0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+                               0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+                               0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+                               0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+                               0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+                               0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+                               0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+                               0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+                               0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+                               0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+                               0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+                               0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+                               0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+                               0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+                               0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+                               0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+                               0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+                               0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+                               0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+                               0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+                               0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+                               0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+                               0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+                               0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+                               0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+                               0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+                               0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+                               0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+                               0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+                               0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+                               0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+                               0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+                               0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+                               0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+                               0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+                               0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+                               0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+                               0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+                               0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+                               0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+                               0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+                               0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+                               0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+                               0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+                               0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+                               0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+                               0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+                               0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+                               0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+                               0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+                               0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+                               0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+                               0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+                               0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+                               0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+                               0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+                               0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+                               0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+                               0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+                               0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+                               0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+                               0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+                               0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+                               0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+                               0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+                               0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+                               0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+                               0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+                               0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+                               0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+                               0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+                               0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+                               0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+                               0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+                               0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+                               0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+                               0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+                               0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+                               0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+                               0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+                               0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+                               0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+                               0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+                               0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+                       },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00,
+                               0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00,
+                               0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x64,
+                               0x28, 0xb9, 0x3f, 0x48, 0xaf, 0x06, 0x22, 0x39,
+                               0x56, 0xd8, 0x6f, 0x63, 0x5d, 0x03, 0x48, 0x63,
+                               0x01, 0x13, 0xa2, 0xd6, 0x76, 0xc0, 0xab, 0xda,
+                               0x25, 0x30, 0x75, 0x6c, 0xaa, 0xb4, 0xdc, 0x35,
+                               0x72, 0xdc, 0xf2, 0x43, 0xe4, 0x1d, 0x82, 0xfb,
+                               0x6c, 0x64, 0xe2, 0xa7, 0x8f, 0x32, 0x67, 0x6b,
+                               0xcd, 0xd2, 0xb2, 0x36, 0x94, 0xbc, 0x6f, 0x46,
+                               0x79, 0x29, 0x42, 0xe3, 0x1a, 0xbf, 0xfb, 0x41,
+                               0xd5, 0xe3, 0xb4, 0x2a, 0xf6, 0x95, 0x6f, 0x0c,
+                               0x87, 0xb9, 0x03, 0x18, 0xa1, 0xea, 0x4a, 0xe2,
+                               0x2e, 0x0f, 0x50, 0x00, 0xc1, 0xe8, 0x8c, 0xc8,
+                               0xa2, 0xf6, 0xa4, 0x05, 0xf4, 0x38, 0x3e, 0xd9,
+                               0x6e, 0x63, 0x96, 0x0c, 0x34, 0x73, 0x90, 0x03,
+                               0x55, 0xa6, 0x34, 0xb0, 0x5e, 0x8c, 0x48, 0x40,
+                               0x25, 0x45, 0x84, 0xa6, 0x21, 0x3f, 0x81, 0x97,
+                               0xa7, 0x11, 0x09, 0x14, 0x95, 0xa5, 0xe5, 0x14,
+                               0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+                               0x00, 0x24, 0x16, 0xaa, 0x01, 0x2c, 0xa8, 0xc1,
+                               0x28, 0xaf, 0x35, 0xc1, 0xc1, 0xf3, 0x0a, 0x25,
+                               0x66, 0x6e, 0x27, 0x11, 0xa3, 0xa4, 0xd9, 0xe9,
+                               0xea, 0x15, 0x09, 0x9d, 0x28, 0xe3, 0x5b, 0x2b,
+                               0xa6, 0x25, 0xa7, 0x14, 0x24, 0x3a,
+                       },
+
+                       {
+                               0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+                               0x01, 0x00, 0x24, 0x9a, 0xa8, 0xd6, 0x77, 0x46,
+                               0x45, 0x68, 0x9d, 0x5d, 0xa9, 0x68, 0x03, 0xe5,
+                               0xaf, 0xe8, 0xc8, 0x21, 0xc5, 0xc6, 0xc1, 0x50,
+                               0xe0, 0xd8, 0x52, 0xce, 0xa3, 0x4f, 0x2d, 0xf4,
+                               0xe3, 0xa7, 0x7d, 0x35, 0x80, 0x84, 0x12, 0x17,
+                               0x03, 0x01, 0x00, 0x21, 0x8a, 0x82, 0x0c, 0x54,
+                               0x1b, 0xeb, 0x77, 0x90, 0x2c, 0x3e, 0xbc, 0xf0,
+                               0x23, 0xcc, 0xa8, 0x9f, 0x25, 0x08, 0x12, 0xed,
+                               0x43, 0xf1, 0xf9, 0x06, 0xad, 0xa9, 0x4b, 0x97,
+                               0x82, 0xb7, 0xc4, 0x0b, 0x4c, 0x15, 0x03, 0x01,
+                               0x00, 0x16, 0x05, 0x2d, 0x9d, 0x45, 0x03, 0xb7,
+                               0xc2, 0xd1, 0xb5, 0x1a, 0x43, 0xcf, 0x1a, 0x37,
+                               0xf4, 0x70, 0xcc, 0xb4, 0xed, 0x07, 0x76, 0x3a,
+                       }}},
+       // Server asks for cert with empty CA list, client gives one
+       // gotest -test.run "TestRunServer" -serve -clientauth 1
+       // gnutls-cli --insecure --debug 100 -p 10443 localhost
+       {"RequestClientCert, client gives it", RequestClientCert,
+               []*x509.Certificate{clicert},
+               [][]byte{{
+                       0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+                       0x76, 0x03, 0x02, 0x4e, 0xe7, 0x44, 0xda, 0x58,
+                       0x7d, 0x46, 0x4a, 0x48, 0x97, 0x9f, 0xe5, 0x91,
+                       0x11, 0x64, 0xa7, 0x1e, 0x4d, 0xb7, 0xfe, 0x9b,
+                       0xc6, 0x63, 0xf8, 0xa4, 0xb5, 0x0b, 0x18, 0xb5,
+                       0xbd, 0x19, 0xb3, 0x00, 0x00, 0x34, 0x00, 0x33,
+                       0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+                       0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+                       0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+                       0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+                       0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+                       0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+                       0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+                       0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+                       0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+                       0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+               },
+
+                       {
+                               0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+                               0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+                               0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+                               0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+                               0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+                               0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+                               0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+                               0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+                               0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+                               0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+                               0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+                               0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+                               0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+                               0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+                               0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+                               0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+                               0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+                               0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+                               0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+                               0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+                               0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+                               0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+                               0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+                               0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+                               0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+                               0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+                               0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+                               0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+                               0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+                               0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                               0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+                               0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+                               0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+                               0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+                               0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+                               0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+                               0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+                               0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+                               0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+                               0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+                               0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+                               0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+                               0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+                               0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+                               0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+                               0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+                               0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+                               0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+                               0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+                               0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+                               0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+                               0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+                               0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+                               0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+                               0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+                               0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+                               0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+                               0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+                               0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+                               0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+                               0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+                               0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+                               0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+                               0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+                               0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+                               0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+                               0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+                               0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+                               0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+                               0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+                               0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+                               0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+                               0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+                               0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+                               0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+                               0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+                               0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+                               0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+                               0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+                               0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+                               0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+                               0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+                               0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+                               0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+                               0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+                               0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+                               0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+                               0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
+                               0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
+                               0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+                       },
+
+                       {
+                               0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01,
+                               0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30,
+                               0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0,
+                               0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30,
+                               0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10,
+                               0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+                               0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+                               0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+                               0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+                               0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d,
+                               0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37,
+                               0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31,
+                               0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30,
+                               0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10,
+                               0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+                               0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+                               0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+                               0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+                               0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30,
+                               0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00,
+                               0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0,
+                               0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0,
+                               0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33,
+                               0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84,
+                               0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d,
+                               0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5,
+                               0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c,
+                               0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87,
+                               0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec,
+                               0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01,
+                               0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab,
+                               0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e,
+                               0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b,
+                               0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec,
+                               0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c,
+                               0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13,
+                               0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03,
+                               0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30,
+                               0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+                               0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30,
+                               0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06,
+                               0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f,
+                               0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30,
+                               0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30,
+                               0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+                               0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00,
+                               0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e,
+                               0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7,
+                               0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85,
+                               0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32,
+                               0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9,
+                               0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15,
+                               0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9,
+                               0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84,
+                               0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd,
+                               0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6,
+                               0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0,
+                               0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c,
+                               0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96,
+                               0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18,
+                               0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
+                               0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
+                               0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+                               0x82, 0x00, 0x80, 0xa7, 0x2f, 0xed, 0xfa, 0xc2,
+                               0xbd, 0x46, 0xa1, 0xf2, 0x69, 0xc5, 0x1d, 0xa1,
+                               0x34, 0xd6, 0xd0, 0x84, 0xf5, 0x5d, 0x8c, 0x82,
+                               0x8d, 0x98, 0x82, 0x9c, 0xd9, 0x07, 0xe0, 0xf7,
+                               0x55, 0x49, 0x4d, 0xa1, 0x48, 0x59, 0x02, 0xd3,
+                               0x84, 0x37, 0xaf, 0x01, 0xb3, 0x3a, 0xf4, 0xed,
+                               0x99, 0xbe, 0x67, 0x36, 0x19, 0x55, 0xf3, 0xf9,
+                               0xcb, 0x94, 0xe5, 0x7b, 0x8b, 0x77, 0xf2, 0x5f,
+                               0x4c, 0xfe, 0x01, 0x1f, 0x7b, 0xd7, 0x23, 0x49,
+                               0x0c, 0xcb, 0x6c, 0xb0, 0xe7, 0x77, 0xd6, 0xcf,
+                               0xa8, 0x7d, 0xdb, 0xa7, 0x14, 0xe2, 0xf5, 0xf3,
+                               0xff, 0xba, 0x23, 0xd2, 0x9a, 0x36, 0x14, 0x60,
+                               0x2a, 0x91, 0x5d, 0x2b, 0x35, 0x3b, 0xb6, 0xdd,
+                               0xcb, 0x6b, 0xdc, 0x18, 0xdc, 0x33, 0xb8, 0xb3,
+                               0xc7, 0x27, 0x7e, 0xfc, 0xd2, 0xf7, 0x97, 0x90,
+                               0x5e, 0x17, 0xac, 0x14, 0x8e, 0x0f, 0xca, 0xb5,
+                               0x6f, 0xc9, 0x2d, 0x16, 0x03, 0x01, 0x00, 0x86,
+                               0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x44, 0x7f,
+                               0xa2, 0x59, 0x60, 0x0b, 0x5a, 0xc4, 0xaf, 0x1e,
+                               0x60, 0xa5, 0x24, 0xea, 0xc1, 0xc3, 0x22, 0x21,
+                               0x6b, 0x22, 0x8b, 0x2a, 0x11, 0x82, 0x68, 0x7d,
+                               0xb9, 0xdd, 0x9c, 0x27, 0x4c, 0xc2, 0xc8, 0xa2,
+                               0x8b, 0x6b, 0x77, 0x8d, 0x3a, 0x2b, 0x8d, 0x2f,
+                               0x6a, 0x2b, 0x43, 0xd2, 0xd1, 0xc6, 0x41, 0x79,
+                               0xa2, 0x4f, 0x2b, 0xc2, 0xf7, 0xb2, 0x10, 0xad,
+                               0xa6, 0x01, 0x51, 0x51, 0x25, 0xe7, 0x58, 0x7a,
+                               0xcf, 0x3b, 0xc4, 0x29, 0xb5, 0xe5, 0xa7, 0x83,
+                               0xe6, 0xcb, 0x1e, 0xf3, 0x02, 0x0f, 0x53, 0x3b,
+                               0xb5, 0x39, 0xef, 0x9c, 0x42, 0xe0, 0xa6, 0x9b,
+                               0x2b, 0xdd, 0x60, 0xae, 0x0a, 0x73, 0x35, 0xbe,
+                               0x26, 0x10, 0x1b, 0xe9, 0xe9, 0x61, 0xab, 0x20,
+                               0xa5, 0x48, 0xc6, 0x60, 0xa6, 0x50, 0x3c, 0xfb,
+                               0xa7, 0xca, 0xb0, 0x80, 0x95, 0x1e, 0xce, 0xc7,
+                               0xbb, 0x68, 0x44, 0xdc, 0x0e, 0x0e, 0x14, 0x03,
+                               0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
+                               0x24, 0xb6, 0xcd, 0x0c, 0x78, 0xfd, 0xd6, 0xff,
+                               0xbe, 0x97, 0xd5, 0x0a, 0x7d, 0x4f, 0xa1, 0x03,
+                               0x78, 0xc8, 0x61, 0x6f, 0xf2, 0x4b, 0xa8, 0x56,
+                               0x4f, 0x3c, 0xa2, 0xd9, 0xd0, 0x20, 0x13, 0x1b,
+                               0x8b, 0x36, 0xb7, 0x33, 0x9c,
+                       },
+
+                       {
+                               0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+                               0x01, 0x00, 0x24, 0xa3, 0x43, 0x94, 0xe7, 0xdf,
+                               0xb6, 0xc3, 0x03, 0x9f, 0xc1, 0x59, 0x0c, 0xc3,
+                               0x13, 0xae, 0xed, 0xcf, 0xff, 0xf1, 0x80, 0xf3,
+                               0x13, 0x63, 0x1c, 0xf0, 0xca, 0xad, 0x9e, 0x71,
+                               0x46, 0x5f, 0x6b, 0xeb, 0x10, 0x3f, 0xe3, 0x17,
+                               0x03, 0x01, 0x00, 0x21, 0xe9, 0x80, 0x95, 0x6e,
+                               0x05, 0x55, 0x2f, 0xed, 0x4d, 0xde, 0x17, 0x3a,
+                               0x32, 0x9b, 0x2a, 0x74, 0x30, 0x4f, 0xe0, 0x9f,
+                               0x4e, 0xd3, 0x06, 0xbd, 0x3a, 0x43, 0x75, 0x8b,
+                               0x5b, 0x9a, 0xd8, 0x2e, 0x56, 0x15, 0x03, 0x01,
+                               0x00, 0x16, 0x53, 0xf5, 0xff, 0xe0, 0xa1, 0x6c,
+                               0x33, 0xf4, 0x4e, 0x89, 0x68, 0xe1, 0xf7, 0x61,
+                               0x13, 0xb3, 0x12, 0xa1, 0x8e, 0x5a, 0x7a, 0x02,
+                       }}},
+}
+
+// cert.pem and key.pem were generated with generate_cert.go
+// Thus, they have no ExtKeyUsage fields and trigger an error
+// when verification is turned on.
+
+var clicert = loadPEMCert(`
+-----BEGIN CERTIFICATE-----
+MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
+bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
+MDAxMlowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGc
+MAsGCSqGSIb3DQEBAQOBjAAwgYgCgYBO0Hsx44Jk2VnAwoekXh6LczPHY1PfZpIG
+hPZk1Y/kNqcdK+izIDZFI7Xjla7t4PUgnI2V339aEu+H5Fto5OkOdOwEin/ekyfE
+ARl6vfLcPRSr0FTKIQzQTW6HLlzF0rtNS0/Otiz3fojsfNcCkXSmHgwa2uNKWi7e
+E5xMQIhZkwIDAQABozIwMDAOBgNVHQ8BAf8EBAMCAKAwDQYDVR0OBAYEBAECAwQw
+DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A
+p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4
+hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE
+GFGNEH5PlGffo05wc46QkYU=
+-----END CERTIFICATE-----
+`)
+
+/* corresponding key.pem for cert.pem is:
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
+NkUjteOVru3g9SCcjZXff1oS74fkW2jk6Q507ASKf96TJ8QBGXq98tw9FKvQVMoh
+DNBNbocuXMXSu01LT862LPd+iOx81wKRdKYeDBra40paLt4TnExAiFmTAgMBAAEC
+gYBxvXd8yNteFTns8A/2yomEMC4yeosJJSpp1CsN3BJ7g8/qTnrVPxBy+RU+qr63
+t2WquaOu/cr5P8iEsa6lk20tf8pjKLNXeX0b1RTzK8rJLbS7nGzP3tvOhL096VtQ
+dAo4ROEaro0TzYpHmpciSvxVIeEIAAdFDObDJPKqcJAxyQJBAJizfYgK8Gzx9fsx
+hxp+VteCbVPg2euASH5Yv3K5LukRdKoSzHE2grUVQgN/LafC0eZibRanxHegYSr7
+7qaswKUCQQCEIWor/X4XTMdVj3Oj+vpiw75y/S9gh682+myZL+d/02IEkwnB098P
+RkKVpenBHyrGg0oeN5La7URILWKj7CPXAkBKo6F+d+phNjwIFoN1Xb/RA32w/D1I
+saG9sF+UEhRt9AxUfW/U/tIQ9V0ZHHcSg1XaCM5Nvp934brdKdvTOKnJAkBD5h/3
+Rybatlvg/fzBEaJFyq09zhngkxlZOUtBVTqzl17RVvY2orgH02U4HbCHy4phxOn7
+qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN
+1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvAMAA=
+-----END RSA PRIVATE KEY-----
+*/
index 79ab502..28e93a0 100644 (file)
@@ -120,7 +120,7 @@ func Dial(network, addr string, config *Config) (*Conn, error) {
 
 // LoadX509KeyPair reads and parses a public/private key pair from a pair of
 // files. The files must contain PEM encoded data.
-func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err error) {
+func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) {
        certPEMBlock, err := ioutil.ReadFile(certFile)
        if err != nil {
                return
index 5a0a876..616a0b3 100644 (file)
@@ -101,3 +101,13 @@ func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
 
        return
 }
+
+// Subjects returns a list of the DER-encoded subjects of
+// all of the certificates in the pool. 
+func (s *CertPool) Subjects() (res [][]byte) {
+       res = make([][]byte, len(s.certs))
+       for i, c := range s.certs {
+               res[i] = c.RawSubject
+       }
+       return
+}
index e5c2988..b90181b 100644 (file)
@@ -7,14 +7,14 @@ package gosym
 import (
        "debug/elf"
        "os"
-       "syscall"
+       "runtime"
        "testing"
 )
 
 func dotest() bool {
        // For now, only works on ELF platforms.
        // TODO: convert to work with new go tool
-       return false && syscall.OS == "linux" && os.Getenv("GOARCH") == "amd64"
+       return false && runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
 }
 
 func getTable(t *testing.T) *Table {
index 22a0dde..4d1ae38 100644 (file)
@@ -786,7 +786,8 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
 // Because Unmarshal uses the reflect package, the structs
 // being written to must use upper case field names.
 //
-// An ASN.1 INTEGER can be written to an int, int32 or int64.
+// An ASN.1 INTEGER can be written to an int, int32, int64,
+// or *big.Int (from the math/big package).
 // If the encoded value does not fit in the Go type,
 // Unmarshal returns a parse error.
 //
index 09f9413..92c9eb6 100644 (file)
@@ -6,6 +6,7 @@ package asn1
 
 import (
        "bytes"
+       "math/big"
        "reflect"
        "testing"
        "time"
@@ -351,6 +352,10 @@ type TestElementsAfterString struct {
        A, B int
 }
 
+type TestBigInt struct {
+       X *big.Int
+}
+
 var unmarshalTestData = []struct {
        in  []byte
        out interface{}
@@ -369,6 +374,7 @@ var unmarshalTestData = []struct {
        {[]byte{0x01, 0x01, 0x00}, newBool(false)},
        {[]byte{0x01, 0x01, 0x01}, newBool(true)},
        {[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
+       {[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}},
 }
 
 func TestUnmarshal(t *testing.T) {
index d05b5d8..a7447f9 100644 (file)
@@ -7,6 +7,7 @@ package asn1
 import (
        "bytes"
        "encoding/hex"
+       "math/big"
        "testing"
        "time"
 )
@@ -20,6 +21,10 @@ type twoIntStruct struct {
        B int
 }
 
+type bigIntStruct struct {
+       A *big.Int
+}
+
 type nestedStruct struct {
        A intStruct
 }
@@ -65,6 +70,7 @@ var marshalTests = []marshalTest{
        {-128, "020180"},
        {-129, "0202ff7f"},
        {intStruct{64}, "3003020140"},
+       {bigIntStruct{big.NewInt(0x123456)}, "30050203123456"},
        {twoIntStruct{64, 65}, "3006020140020141"},
        {nestedStruct{intStruct{127}}, "3005300302017f"},
        {[]byte{1, 2, 3}, "0403010203"},
index ba1f2eb..4d1325d 100644 (file)
@@ -1039,9 +1039,9 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[re
                // Extract and compare element types.
                var sw *sliceType
                if tt, ok := builtinIdToType[fw]; ok {
-                       sw = tt.(*sliceType)
-               } else {
-                       sw = dec.wireType[fw].SliceT
+                       sw, _ = tt.(*sliceType)
+               } else if wire != nil {
+                       sw = wire.SliceT
                }
                elem := userType(t.Elem()).base
                return sw != nil && dec.compatibleType(elem, sw.Elem, inProgress)
index cd1500d..7a30f91 100644 (file)
@@ -678,3 +678,11 @@ func TestUnexportedChan(t *testing.T) {
                t.Fatalf("error encoding unexported channel: %s", err)
        }
 }
+
+func TestSliceIncompatibility(t *testing.T) {
+       var in = []byte{1, 2, 3}
+       var out []int
+       if err := encAndDec(in, &out); err == nil {
+               t.Error("expected compatibility error")
+       }
+}
index 8287b33..87076b5 100644 (file)
@@ -10,6 +10,7 @@ package json
 import (
        "encoding/base64"
        "errors"
+       "fmt"
        "reflect"
        "runtime"
        "strconv"
@@ -538,7 +539,7 @@ func (d *decodeState) object(v reflect.Value) {
                // Read value.
                if destring {
                        d.value(reflect.ValueOf(&d.tempstr))
-                       d.literalStore([]byte(d.tempstr), subv)
+                       d.literalStore([]byte(d.tempstr), subv, true)
                } else {
                        d.value(subv)
                }
@@ -571,11 +572,15 @@ func (d *decodeState) literal(v reflect.Value) {
        d.off--
        d.scan.undo(op)
 
-       d.literalStore(d.data[start:d.off], v)
+       d.literalStore(d.data[start:d.off], v, false)
 }
 
 // literalStore decodes a literal stored in item into v.
-func (d *decodeState) literalStore(item []byte, v reflect.Value) {
+//
+// fromQuoted indicates whether this literal came from unwrapping a
+// string from the ",string" struct tag option. this is used only to
+// produce more helpful error messages.
+func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) {
        // Check for unmarshaler.
        wantptr := item[0] == 'n' // null
        unmarshaler, pv := d.indirect(v, wantptr)
@@ -601,7 +606,11 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
                value := c == 't'
                switch v.Kind() {
                default:
-                       d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+                       if fromQuoted {
+                               d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+                       } else {
+                               d.saveError(&UnmarshalTypeError{"bool", v.Type()})
+                       }
                case reflect.Bool:
                        v.SetBool(value)
                case reflect.Interface:
@@ -611,7 +620,11 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
        case '"': // string
                s, ok := unquoteBytes(item)
                if !ok {
-                       d.error(errPhase)
+                       if fromQuoted {
+                               d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+                       } else {
+                               d.error(errPhase)
+                       }
                }
                switch v.Kind() {
                default:
@@ -636,12 +649,20 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
 
        default: // number
                if c != '-' && (c < '0' || c > '9') {
-                       d.error(errPhase)
+                       if fromQuoted {
+                               d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+                       } else {
+                               d.error(errPhase)
+                       }
                }
                s := string(item)
                switch v.Kind() {
                default:
-                       d.error(&UnmarshalTypeError{"number", v.Type()})
+                       if fromQuoted {
+                               d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+                       } else {
+                               d.error(&UnmarshalTypeError{"number", v.Type()})
+                       }
                case reflect.Interface:
                        n, err := strconv.ParseFloat(s, 64)
                        if err != nil {
index 05c8a06..cc3103f 100644 (file)
@@ -258,13 +258,10 @@ type wrongStringTest struct {
        in, err string
 }
 
-// TODO(bradfitz): as part of Issue 2331, fix these tests' expected
-// error values to be helpful, rather than the confusing messages they
-// are now.
 var wrongStringTests = []wrongStringTest{
-       {`{"result":"x"}`, "JSON decoder out of sync - data changing underfoot?"},
-       {`{"result":"foo"}`, "json: cannot unmarshal bool into Go value of type string"},
-       {`{"result":"123"}`, "json: cannot unmarshal number into Go value of type string"},
+       {`{"result":"x"}`, `json: invalid use of ,string struct tag, trying to unmarshal "x" into string`},
+       {`{"result":"foo"}`, `json: invalid use of ,string struct tag, trying to unmarshal "foo" into string`},
+       {`{"result":"123"}`, `json: invalid use of ,string struct tag, trying to unmarshal "123" into string`},
 }
 
 // If people misuse the ,string modifier, the error message should be
index 3d2f4fc..033da2d 100644 (file)
@@ -12,6 +12,7 @@ package json
 import (
        "bytes"
        "encoding/base64"
+       "math"
        "reflect"
        "runtime"
        "sort"
@@ -170,6 +171,15 @@ func (e *UnsupportedTypeError) Error() string {
        return "json: unsupported type: " + e.Type.String()
 }
 
+type UnsupportedValueError struct {
+       Value reflect.Value
+       Str   string
+}
+
+func (e *UnsupportedValueError) Error() string {
+       return "json: unsupported value: " + e.Str
+}
+
 type InvalidUTF8Error struct {
        S string
 }
@@ -290,7 +300,11 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
                        e.Write(b)
                }
        case reflect.Float32, reflect.Float64:
-               b := strconv.AppendFloat(e.scratch[:0], v.Float(), 'g', -1, v.Type().Bits())
+               f := v.Float()
+               if math.IsInf(f, 0) || math.IsNaN(f) {
+                       e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, v.Type().Bits())})
+               }
+               b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, v.Type().Bits())
                if quoted {
                        writeString(e, string(b))
                } else {
index 9366589..0e39559 100644 (file)
@@ -6,6 +6,7 @@ package json
 
 import (
        "bytes"
+       "math"
        "reflect"
        "testing"
 )
@@ -107,3 +108,21 @@ func TestEncodeRenamedByteSlice(t *testing.T) {
                t.Errorf(" got %s want %s", result, expect)
        }
 }
+
+var unsupportedValues = []interface{}{
+       math.NaN(),
+       math.Inf(-1),
+       math.Inf(1),
+}
+
+func TestUnsupportedValues(t *testing.T) {
+       for _, v := range unsupportedValues {
+               if _, err := Marshal(v); err != nil {
+                       if _, ok := err.(*UnsupportedValueError); !ok {
+                               t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
+                       }
+               } else {
+                       t.Errorf("for %v, expected error", v)
+               }
+       }
+}
index d365510..8d003aa 100644 (file)
@@ -5,6 +5,7 @@
 package xml
 
 var atomValue = &Feed{
+       XMLName: Name{"http://www.w3.org/2005/Atom", "feed"},
        Title:   "Example Feed",
        Link:    []Link{{Href: "http://example.org/"}},
        Updated: ParseTime("2003-12-13T18:30:02Z"),
@@ -24,19 +25,19 @@ var atomValue = &Feed{
 
 var atomXml = `` +
        `<feed xmlns="http://www.w3.org/2005/Atom">` +
-       `<Title>Example Feed</Title>` +
-       `<Id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</Id>` +
-       `<Link href="http://example.org/"></Link>` +
-       `<Updated>2003-12-13T18:30:02Z</Updated>` +
-       `<Author><Name>John Doe</Name><URI></URI><Email></Email></Author>` +
-       `<Entry>` +
-       `<Title>Atom-Powered Robots Run Amok</Title>` +
-       `<Id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</Id>` +
-       `<Link href="http://example.org/2003/12/13/atom03"></Link>` +
-       `<Updated>2003-12-13T18:30:02Z</Updated>` +
-       `<Author><Name></Name><URI></URI><Email></Email></Author>` +
-       `<Summary>Some text.</Summary>` +
-       `</Entry>` +
+       `<title>Example Feed</title>` +
+       `<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>` +
+       `<link href="http://example.org/"></link>` +
+       `<updated>2003-12-13T18:30:02Z</updated>` +
+       `<author><name>John Doe</name><uri></uri><email></email></author>` +
+       `<entry>` +
+       `<title>Atom-Powered Robots Run Amok</title>` +
+       `<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>` +
+       `<link href="http://example.org/2003/12/13/atom03"></link>` +
+       `<updated>2003-12-13T18:30:02Z</updated>` +
+       `<author><name></name><uri></uri><email></email></author>` +
+       `<summary>Some text.</summary>` +
+       `</entry>` +
        `</feed>`
 
 func ParseTime(str string) Time {
diff --git a/libgo/go/encoding/xml/embed_test.go b/libgo/go/encoding/xml/embed_test.go
deleted file mode 100644 (file)
index ec7f478..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-// 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 xml
-
-import "testing"
-
-type C struct {
-       Name string
-       Open bool
-}
-
-type A struct {
-       XMLName Name `xml:"http://domain a"`
-       C
-       B      B
-       FieldA string
-}
-
-type B struct {
-       XMLName Name `xml:"b"`
-       C
-       FieldB string
-}
-
-const _1a = `
-<?xml version="1.0" encoding="UTF-8"?>
-<a xmlns="http://domain">
-  <name>KmlFile</name>
-  <open>1</open>
-  <b>
-    <name>Absolute</name>
-    <open>0</open>
-    <fieldb>bar</fieldb>
-  </b>
-  <fielda>foo</fielda>
-</a>
-`
-
-// Tests that embedded structs are marshalled.
-func TestEmbedded1(t *testing.T) {
-       var a A
-       if e := Unmarshal(StringReader(_1a), &a); e != nil {
-               t.Fatalf("Unmarshal: %s", e)
-       }
-       if a.FieldA != "foo" {
-               t.Fatalf("Unmarshal: expected 'foo' but found '%s'", a.FieldA)
-       }
-       if a.Name != "KmlFile" {
-               t.Fatalf("Unmarshal: expected 'KmlFile' but found '%s'", a.Name)
-       }
-       if !a.Open {
-               t.Fatal("Unmarshal: expected 'true' but found otherwise")
-       }
-       if a.B.FieldB != "bar" {
-               t.Fatalf("Unmarshal: expected 'bar' but found '%s'", a.B.FieldB)
-       }
-       if a.B.Name != "Absolute" {
-               t.Fatalf("Unmarshal: expected 'Absolute' but found '%s'", a.B.Name)
-       }
-       if a.B.Open {
-               t.Fatal("Unmarshal: expected 'false' but found otherwise")
-       }
-}
-
-type A2 struct {
-       XMLName Name `xml:"http://domain a"`
-       XY      string
-       Xy      string
-}
-
-const _2a = `
-<?xml version="1.0" encoding="UTF-8"?>
-<a xmlns="http://domain">
-  <xy>foo</xy>
-</a>
-`
-
-// Tests that conflicting field names get excluded.
-func TestEmbedded2(t *testing.T) {
-       var a A2
-       if e := Unmarshal(StringReader(_2a), &a); e != nil {
-               t.Fatalf("Unmarshal: %s", e)
-       }
-       if a.XY != "" {
-               t.Fatalf("Unmarshal: expected empty string but found '%s'", a.XY)
-       }
-       if a.Xy != "" {
-               t.Fatalf("Unmarshal: expected empty string but found '%s'", a.Xy)
-       }
-}
-
-type A3 struct {
-       XMLName Name `xml:"http://domain a"`
-       xy      string
-}
-
-// Tests that private fields are not set.
-func TestEmbedded3(t *testing.T) {
-       var a A3
-       if e := Unmarshal(StringReader(_2a), &a); e != nil {
-               t.Fatalf("Unmarshal: %s", e)
-       }
-       if a.xy != "" {
-               t.Fatalf("Unmarshal: expected empty string but found '%s'", a.xy)
-       }
-}
-
-type A4 struct {
-       XMLName Name `xml:"http://domain a"`
-       Any     string
-}
-
-// Tests that private fields are not set.
-func TestEmbedded4(t *testing.T) {
-       var a A4
-       if e := Unmarshal(StringReader(_2a), &a); e != nil {
-               t.Fatalf("Unmarshal: %s", e)
-       }
-       if a.Any != "foo" {
-               t.Fatalf("Unmarshal: expected 'foo' but found '%s'", a.Any)
-       }
-}
index e94fdbc..d25ee30 100644 (file)
@@ -6,6 +6,8 @@ package xml
 
 import (
        "bufio"
+       "bytes"
+       "fmt"
        "io"
        "reflect"
        "strconv"
@@ -42,20 +44,26 @@ type printer struct {
 // elements containing the data.
 //
 // The name for the XML elements is taken from, in order of preference:
-//     - the tag on an XMLName field, if the data is a struct
-//     - the value of an XMLName field of type xml.Name
+//     - the tag on the XMLName field, if the data is a struct
+//     - the value of the XMLName field of type xml.Name
 //     - the tag of the struct field used to obtain the data
 //     - the name of the struct field used to obtain the data
-//     - the name '???'.
+//     - the name of the marshalled type
 //
 // The XML element for a struct contains marshalled elements for each of the
 // exported fields of the struct, with these exceptions:
 //     - the XMLName field, described above, is omitted.
-//     - a field with tag "attr" becomes an attribute in the XML element.
-//     - a field with tag "chardata" is written as character data,
-//        not as an XML element.
-//     - a field with tag "innerxml" is written verbatim,
-//        not subject to the usual marshalling procedure.
+//     - a field with tag "name,attr" becomes an attribute with
+//       the given name in the XML element.
+//     - a field with tag ",attr" becomes an attribute with the
+//       field name in the in the XML element.
+//     - a field with tag ",chardata" is written as character data,
+//       not as an XML element.
+//     - a field with tag ",innerxml" is written verbatim, not subject
+//       to the usual marshalling procedure.
+//     - a field with tag ",comment" is written as an XML comment, not
+//       subject to the usual marshalling procedure. It must not contain
+//       the "--" string within it.
 //
 // If a field uses a tag "a>b>c", then the element c will be nested inside
 // parent elements a and b.  Fields that appear next to each other that name
@@ -63,17 +71,18 @@ type printer struct {
 //
 //     type Result struct {
 //             XMLName   xml.Name `xml:"result"`
+//             Id        int      `xml:"id,attr"`
 //             FirstName string   `xml:"person>name>first"`
 //             LastName  string   `xml:"person>name>last"`
 //             Age       int      `xml:"person>age"`
 //     }
 //
-//     xml.Marshal(w, &Result{FirstName: "John", LastName: "Doe", Age: 42})
+//     xml.Marshal(w, &Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42})
 //
 // would be marshalled as:
 //
 //     <result>
-//             <person>
+//             <person id="13">
 //                     <name>
 //                             <first>John</first>
 //                             <last>Doe</last>
@@ -85,12 +94,12 @@ type printer struct {
 // Marshal will return an error if asked to marshal a channel, function, or map.
 func Marshal(w io.Writer, v interface{}) (err error) {
        p := &printer{bufio.NewWriter(w)}
-       err = p.marshalValue(reflect.ValueOf(v), "???")
+       err = p.marshalValue(reflect.ValueOf(v), nil)
        p.Flush()
        return err
 }
 
-func (p *printer) marshalValue(val reflect.Value, name string) error {
+func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
        if !val.IsValid() {
                return nil
        }
@@ -115,58 +124,75 @@ func (p *printer) marshalValue(val reflect.Value, name string) error {
                if val.IsNil() {
                        return nil
                }
-               return p.marshalValue(val.Elem(), name)
+               return p.marshalValue(val.Elem(), finfo)
        }
 
        // Slices and arrays iterate over the elements. They do not have an enclosing tag.
        if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
                for i, n := 0, val.Len(); i < n; i++ {
-                       if err := p.marshalValue(val.Index(i), name); err != nil {
+                       if err := p.marshalValue(val.Index(i), finfo); err != nil {
                                return err
                        }
                }
                return nil
        }
 
-       // Find XML name
-       xmlns := ""
-       if kind == reflect.Struct {
-               if f, ok := typ.FieldByName("XMLName"); ok {
-                       if tag := f.Tag.Get("xml"); tag != "" {
-                               if i := strings.Index(tag, " "); i >= 0 {
-                                       xmlns, name = tag[:i], tag[i+1:]
-                               } else {
-                                       name = tag
-                               }
-                       } else if v, ok := val.FieldByIndex(f.Index).Interface().(Name); ok && v.Local != "" {
-                               xmlns, name = v.Space, v.Local
-                       }
+       tinfo, err := getTypeInfo(typ)
+       if err != nil {
+               return err
+       }
+
+       // Precedence for the XML element name is:
+       // 1. XMLName field in underlying struct;
+       // 2. field name/tag in the struct field; and
+       // 3. type name
+       var xmlns, name string
+       if tinfo.xmlname != nil {
+               xmlname := tinfo.xmlname
+               if xmlname.name != "" {
+                       xmlns, name = xmlname.xmlns, xmlname.name
+               } else if v, ok := val.FieldByIndex(xmlname.idx).Interface().(Name); ok && v.Local != "" {
+                       xmlns, name = v.Space, v.Local
+               }
+       }
+       if name == "" && finfo != nil {
+               xmlns, name = finfo.xmlns, finfo.name
+       }
+       if name == "" {
+               name = typ.Name()
+               if name == "" {
+                       return &UnsupportedTypeError{typ}
                }
        }
 
        p.WriteByte('<')
        p.WriteString(name)
 
+       if xmlns != "" {
+               p.WriteString(` xmlns="`)
+               // TODO: EscapeString, to avoid the allocation.
+               Escape(p, []byte(xmlns))
+               p.WriteByte('"')
+       }
+
        // Attributes
-       if kind == reflect.Struct {
-               if len(xmlns) > 0 {
-                       p.WriteString(` xmlns="`)
-                       Escape(p, []byte(xmlns))
-                       p.WriteByte('"')
+       for i := range tinfo.fields {
+               finfo := &tinfo.fields[i]
+               if finfo.flags&fAttr == 0 {
+                       continue
                }
-
-               for i, n := 0, typ.NumField(); i < n; i++ {
-                       if f := typ.Field(i); f.PkgPath == "" && f.Tag.Get("xml") == "attr" {
-                               if f.Type.Kind() == reflect.String {
-                                       if str := val.Field(i).String(); str != "" {
-                                               p.WriteByte(' ')
-                                               p.WriteString(strings.ToLower(f.Name))
-                                               p.WriteString(`="`)
-                                               Escape(p, []byte(str))
-                                               p.WriteByte('"')
-                                       }
-                               }
-                       }
+               var str string
+               if fv := val.FieldByIndex(finfo.idx); fv.Kind() == reflect.String {
+                       str = fv.String()
+               } else {
+                       str = fmt.Sprint(fv.Interface())
+               }
+               if str != "" {
+                       p.WriteByte(' ')
+                       p.WriteString(finfo.name)
+                       p.WriteString(`="`)
+                       Escape(p, []byte(str))
+                       p.WriteByte('"')
                }
        }
        p.WriteByte('>')
@@ -194,58 +220,9 @@ func (p *printer) marshalValue(val reflect.Value, name string) error {
                bytes := val.Interface().([]byte)
                Escape(p, bytes)
        case reflect.Struct:
-               s := parentStack{printer: p}
-               for i, n := 0, val.NumField(); i < n; i++ {
-                       if f := typ.Field(i); f.Name != "XMLName" && f.PkgPath == "" {
-                               name := f.Name
-                               vf := val.Field(i)
-                               switch tag := f.Tag.Get("xml"); tag {
-                               case "":
-                                       s.trim(nil)
-                               case "chardata":
-                                       if tk := f.Type.Kind(); tk == reflect.String {
-                                               Escape(p, []byte(vf.String()))
-                                       } else if tk == reflect.Slice {
-                                               if elem, ok := vf.Interface().([]byte); ok {
-                                                       Escape(p, elem)
-                                               }
-                                       }
-                                       continue
-                               case "innerxml":
-                                       iface := vf.Interface()
-                                       switch raw := iface.(type) {
-                                       case []byte:
-                                               p.Write(raw)
-                                               continue
-                                       case string:
-                                               p.WriteString(raw)
-                                               continue
-                                       }
-                               case "attr":
-                                       continue
-                               default:
-                                       parents := strings.Split(tag, ">")
-                                       if len(parents) == 1 {
-                                               parents, name = nil, tag
-                                       } else {
-                                               parents, name = parents[:len(parents)-1], parents[len(parents)-1]
-                                               if parents[0] == "" {
-                                                       parents[0] = f.Name
-                                               }
-                                       }
-
-                                       s.trim(parents)
-                                       if !(vf.Kind() == reflect.Ptr || vf.Kind() == reflect.Interface) || !vf.IsNil() {
-                                               s.push(parents[len(s.stack):])
-                                       }
-                               }
-
-                               if err := p.marshalValue(vf, name); err != nil {
-                                       return err
-                               }
-                       }
+               if err := p.marshalStruct(tinfo, val); err != nil {
+                       return err
                }
-               s.trim(nil)
        default:
                return &UnsupportedTypeError{typ}
        }
@@ -258,6 +235,94 @@ func (p *printer) marshalValue(val reflect.Value, name string) error {
        return nil
 }
 
+var ddBytes = []byte("--")
+
+func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
+       s := parentStack{printer: p}
+       for i := range tinfo.fields {
+               finfo := &tinfo.fields[i]
+               if finfo.flags&(fAttr|fAny) != 0 {
+                       continue
+               }
+               vf := val.FieldByIndex(finfo.idx)
+               switch finfo.flags & fMode {
+               case fCharData:
+                       switch vf.Kind() {
+                       case reflect.String:
+                               Escape(p, []byte(vf.String()))
+                       case reflect.Slice:
+                               if elem, ok := vf.Interface().([]byte); ok {
+                                       Escape(p, elem)
+                               }
+                       }
+                       continue
+
+               case fComment:
+                       k := vf.Kind()
+                       if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
+                               return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
+                       }
+                       if vf.Len() == 0 {
+                               continue
+                       }
+                       p.WriteString("<!--")
+                       dashDash := false
+                       dashLast := false
+                       switch k {
+                       case reflect.String:
+                               s := vf.String()
+                               dashDash = strings.Index(s, "--") >= 0
+                               dashLast = s[len(s)-1] == '-'
+                               if !dashDash {
+                                       p.WriteString(s)
+                               }
+                       case reflect.Slice:
+                               b := vf.Bytes()
+                               dashDash = bytes.Index(b, ddBytes) >= 0
+                               dashLast = b[len(b)-1] == '-'
+                               if !dashDash {
+                                       p.Write(b)
+                               }
+                       default:
+                               panic("can't happen")
+                       }
+                       if dashDash {
+                               return fmt.Errorf(`xml: comments must not contain "--"`)
+                       }
+                       if dashLast {
+                               // "--->" is invalid grammar. Make it "- -->"
+                               p.WriteByte(' ')
+                       }
+                       p.WriteString("-->")
+                       continue
+
+               case fInnerXml:
+                       iface := vf.Interface()
+                       switch raw := iface.(type) {
+                       case []byte:
+                               p.Write(raw)
+                               continue
+                       case string:
+                               p.WriteString(raw)
+                               continue
+                       }
+
+               case fElement:
+                       s.trim(finfo.parents)
+                       if len(finfo.parents) > len(s.stack) {
+                               if vf.Kind() != reflect.Ptr && vf.Kind() != reflect.Interface || !vf.IsNil() {
+                                       s.push(finfo.parents[len(s.stack):])
+                               }
+                       }
+               }
+               if err := p.marshalValue(vf, finfo); err != nil {
+                       return err
+               }
+       }
+       s.trim(nil)
+       return nil
+}
+
 type parentStack struct {
        *printer
        stack []string
index 6a24169..bec5376 100644 (file)
@@ -25,10 +25,10 @@ type Passenger struct {
 }
 
 type Ship struct {
-       XMLName Name `xml:"spaceship"`
+       XMLName struct{} `xml:"spaceship"`
 
-       Name      string       `xml:"attr"`
-       Pilot     string       `xml:"attr"`
+       Name      string       `xml:"name,attr"`
+       Pilot     string       `xml:"pilot,attr"`
        Drive     DriveType    `xml:"drive"`
        Age       uint         `xml:"age"`
        Passenger []*Passenger `xml:"passenger"`
@@ -44,48 +44,50 @@ func (rx RawXML) MarshalXML() ([]byte, error) {
 type NamedType string
 
 type Port struct {
-       XMLName Name   `xml:"port"`
-       Type    string `xml:"attr"`
-       Number  string `xml:"chardata"`
+       XMLName struct{} `xml:"port"`
+       Type    string   `xml:"type,attr"`
+       Comment string   `xml:",comment"`
+       Number  string   `xml:",chardata"`
 }
 
 type Domain struct {
-       XMLName Name   `xml:"domain"`
-       Country string `xml:"attr"`
-       Name    []byte `xml:"chardata"`
+       XMLName struct{} `xml:"domain"`
+       Country string   `xml:",attr"`
+       Name    []byte   `xml:",chardata"`
+       Comment []byte   `xml:",comment"`
 }
 
 type Book struct {
-       XMLName Name   `xml:"book"`
-       Title   string `xml:"chardata"`
+       XMLName struct{} `xml:"book"`
+       Title   string   `xml:",chardata"`
 }
 
 type SecretAgent struct {
-       XMLName   Name   `xml:"agent"`
-       Handle    string `xml:"attr"`
+       XMLName   struct{} `xml:"agent"`
+       Handle    string   `xml:"handle,attr"`
        Identity  string
-       Obfuscate string `xml:"innerxml"`
+       Obfuscate string `xml:",innerxml"`
 }
 
 type NestedItems struct {
-       XMLName Name     `xml:"result"`
+       XMLName struct{} `xml:"result"`
        Items   []string `xml:">item"`
        Item1   []string `xml:"Items>item1"`
 }
 
 type NestedOrder struct {
-       XMLName Name   `xml:"result"`
-       Field1  string `xml:"parent>c"`
-       Field2  string `xml:"parent>b"`
-       Field3  string `xml:"parent>a"`
+       XMLName struct{} `xml:"result"`
+       Field1  string   `xml:"parent>c"`
+       Field2  string   `xml:"parent>b"`
+       Field3  string   `xml:"parent>a"`
 }
 
 type MixedNested struct {
-       XMLName Name   `xml:"result"`
-       A       string `xml:"parent1>a"`
-       B       string `xml:"b"`
-       C       string `xml:"parent1>parent2>c"`
-       D       string `xml:"parent1>d"`
+       XMLName struct{} `xml:"result"`
+       A       string   `xml:"parent1>a"`
+       B       string   `xml:"b"`
+       C       string   `xml:"parent1>parent2>c"`
+       D       string   `xml:"parent1>d"`
 }
 
 type NilTest struct {
@@ -95,62 +97,165 @@ type NilTest struct {
 }
 
 type Service struct {
-       XMLName Name    `xml:"service"`
-       Domain  *Domain `xml:"host>domain"`
-       Port    *Port   `xml:"host>port"`
+       XMLName struct{} `xml:"service"`
+       Domain  *Domain  `xml:"host>domain"`
+       Port    *Port    `xml:"host>port"`
        Extra1  interface{}
        Extra2  interface{} `xml:"host>extra2"`
 }
 
 var nilStruct *Ship
 
+type EmbedA struct {
+       EmbedC
+       EmbedB EmbedB
+       FieldA string
+}
+
+type EmbedB struct {
+       FieldB string
+       EmbedC
+}
+
+type EmbedC struct {
+       FieldA1 string `xml:"FieldA>A1"`
+       FieldA2 string `xml:"FieldA>A2"`
+       FieldB  string
+       FieldC  string
+}
+
+type NameCasing struct {
+       XMLName struct{} `xml:"casing"`
+       Xy      string
+       XY      string
+       XyA     string `xml:"Xy,attr"`
+       XYA     string `xml:"XY,attr"`
+}
+
+type NamePrecedence struct {
+       XMLName     Name              `xml:"Parent"`
+       FromTag     XMLNameWithoutTag `xml:"InTag"`
+       FromNameVal XMLNameWithoutTag
+       FromNameTag XMLNameWithTag
+       InFieldName string
+}
+
+type XMLNameWithTag struct {
+       XMLName Name   `xml:"InXMLNameTag"`
+       Value   string ",chardata"
+}
+
+type XMLNameWithoutTag struct {
+       XMLName Name
+       Value   string ",chardata"
+}
+
+type AttrTest struct {
+       Int   int     `xml:",attr"`
+       Lower int     `xml:"int,attr"`
+       Float float64 `xml:",attr"`
+       Uint8 uint8   `xml:",attr"`
+       Bool  bool    `xml:",attr"`
+       Str   string  `xml:",attr"`
+}
+
+type AnyTest struct {
+       XMLName  struct{}  `xml:"a"`
+       Nested   string    `xml:"nested>value"`
+       AnyField AnyHolder `xml:",any"`
+}
+
+type AnyHolder struct {
+       XMLName Name
+       XML     string `xml:",innerxml"`
+}
+
+type RecurseA struct {
+       A string
+       B *RecurseB
+}
+
+type RecurseB struct {
+       A *RecurseA
+       B string
+}
+
+type Plain struct {
+       V interface{}
+}
+
+// Unless explicitly stated as such (or *Plain), all of the
+// tests below are two-way tests. When introducing new tests,
+// please try to make them two-way as well to ensure that
+// marshalling and unmarshalling are as symmetrical as feasible.
 var marshalTests = []struct {
-       Value     interface{}
-       ExpectXML string
+       Value         interface{}
+       ExpectXML     string
+       MarshalOnly   bool
+       UnmarshalOnly bool
 }{
        // Test nil marshals to nothing
-       {Value: nil, ExpectXML: ``},
-       {Value: nilStruct, ExpectXML: ``},
-
-       // Test value types (no tag name, so ???)
-       {Value: true, ExpectXML: `<???>true</???>`},
-       {Value: int(42), ExpectXML: `<???>42</???>`},
-       {Value: int8(42), ExpectXML: `<???>42</???>`},
-       {Value: int16(42), ExpectXML: `<???>42</???>`},
-       {Value: int32(42), ExpectXML: `<???>42</???>`},
-       {Value: uint(42), ExpectXML: `<???>42</???>`},
-       {Value: uint8(42), ExpectXML: `<???>42</???>`},
-       {Value: uint16(42), ExpectXML: `<???>42</???>`},
-       {Value: uint32(42), ExpectXML: `<???>42</???>`},
-       {Value: float32(1.25), ExpectXML: `<???>1.25</???>`},
-       {Value: float64(1.25), ExpectXML: `<???>1.25</???>`},
-       {Value: uintptr(0xFFDD), ExpectXML: `<???>65501</???>`},
-       {Value: "gopher", ExpectXML: `<???>gopher</???>`},
-       {Value: []byte("gopher"), ExpectXML: `<???>gopher</???>`},
-       {Value: "</>", ExpectXML: `<???>&lt;/&gt;</???>`},
-       {Value: []byte("</>"), ExpectXML: `<???>&lt;/&gt;</???>`},
-       {Value: [3]byte{'<', '/', '>'}, ExpectXML: `<???>&lt;/&gt;</???>`},
-       {Value: NamedType("potato"), ExpectXML: `<???>potato</???>`},
-       {Value: []int{1, 2, 3}, ExpectXML: `<???>1</???><???>2</???><???>3</???>`},
-       {Value: [3]int{1, 2, 3}, ExpectXML: `<???>1</???><???>2</???><???>3</???>`},
+       {Value: nil, ExpectXML: ``, MarshalOnly: true},
+       {Value: nilStruct, ExpectXML: ``, MarshalOnly: true},
+
+       // Test value types
+       {Value: &Plain{true}, ExpectXML: `<Plain><V>true</V></Plain>`},
+       {Value: &Plain{false}, ExpectXML: `<Plain><V>false</V></Plain>`},
+       {Value: &Plain{int(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+       {Value: &Plain{int8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+       {Value: &Plain{int16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+       {Value: &Plain{int32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+       {Value: &Plain{uint(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+       {Value: &Plain{uint8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+       {Value: &Plain{uint16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+       {Value: &Plain{uint32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
+       {Value: &Plain{float32(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
+       {Value: &Plain{float64(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
+       {Value: &Plain{uintptr(0xFFDD)}, ExpectXML: `<Plain><V>65501</V></Plain>`},
+       {Value: &Plain{"gopher"}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
+       {Value: &Plain{[]byte("gopher")}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
+       {Value: &Plain{"</>"}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+       {Value: &Plain{[]byte("</>")}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+       {Value: &Plain{[3]byte{'<', '/', '>'}}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
+       {Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},
+       {Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+       {Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
 
        // Test innerxml
-       {Value: RawXML("</>"), ExpectXML: `</>`},
        {
                Value: &SecretAgent{
                        Handle:    "007",
                        Identity:  "James Bond",
                        Obfuscate: "<redacted/>",
                },
-               //ExpectXML: `<agent handle="007"><redacted/></agent>`,
-               ExpectXML: `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+               ExpectXML:   `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+               MarshalOnly: true,
+       },
+       {
+               Value: &SecretAgent{
+                       Handle:    "007",
+                       Identity:  "James Bond",
+                       Obfuscate: "<Identity>James Bond</Identity><redacted/>",
+               },
+               ExpectXML:     `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
+               UnmarshalOnly: true,
+       },
+
+       // Test marshaller interface
+       {
+               Value:       RawXML("</>"),
+               ExpectXML:   `</>`,
+               MarshalOnly: true,
        },
 
        // Test structs
        {Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
        {Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
        {Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="&lt;unix&gt;"></port>`},
+       {Value: &Port{Number: "443", Comment: "https"}, ExpectXML: `<port><!--https-->443</port>`},
+       {Value: &Port{Number: "443", Comment: "add space-"}, ExpectXML: `<port><!--add space- -->443</port>`, MarshalOnly: true},
        {Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&amp;friends</domain>`},
+       {Value: &Domain{Name: []byte("google.com"), Comment: []byte(" &friends ")}, ExpectXML: `<domain>google.com<!-- &friends --></domain>`},
        {Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride &amp; Prejudice</book>`},
        {Value: atomValue, ExpectXML: atomXml},
        {
@@ -203,16 +308,25 @@ var marshalTests = []struct {
                        `</passenger>` +
                        `</spaceship>`,
        },
+
        // Test a>b
        {
-               Value: NestedItems{Items: []string{}, Item1: []string{}},
+               Value: &NestedItems{Items: nil, Item1: nil},
+               ExpectXML: `<result>` +
+                       `<Items>` +
+                       `</Items>` +
+                       `</result>`,
+       },
+       {
+               Value: &NestedItems{Items: []string{}, Item1: []string{}},
                ExpectXML: `<result>` +
                        `<Items>` +
                        `</Items>` +
                        `</result>`,
+               MarshalOnly: true,
        },
        {
-               Value: NestedItems{Items: []string{}, Item1: []string{"A"}},
+               Value: &NestedItems{Items: nil, Item1: []string{"A"}},
                ExpectXML: `<result>` +
                        `<Items>` +
                        `<item1>A</item1>` +
@@ -220,7 +334,7 @@ var marshalTests = []struct {
                        `</result>`,
        },
        {
-               Value: NestedItems{Items: []string{"A", "B"}, Item1: []string{}},
+               Value: &NestedItems{Items: []string{"A", "B"}, Item1: nil},
                ExpectXML: `<result>` +
                        `<Items>` +
                        `<item>A</item>` +
@@ -229,7 +343,7 @@ var marshalTests = []struct {
                        `</result>`,
        },
        {
-               Value: NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},
+               Value: &NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},
                ExpectXML: `<result>` +
                        `<Items>` +
                        `<item>A</item>` +
@@ -239,7 +353,7 @@ var marshalTests = []struct {
                        `</result>`,
        },
        {
-               Value: NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
+               Value: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
                ExpectXML: `<result>` +
                        `<parent>` +
                        `<c>C</c>` +
@@ -249,16 +363,17 @@ var marshalTests = []struct {
                        `</result>`,
        },
        {
-               Value: NilTest{A: "A", B: nil, C: "C"},
-               ExpectXML: `<???>` +
+               Value: &NilTest{A: "A", B: nil, C: "C"},
+               ExpectXML: `<NilTest>` +
                        `<parent1>` +
                        `<parent2><a>A</a></parent2>` +
                        `<parent2><c>C</c></parent2>` +
                        `</parent1>` +
-                       `</???>`,
+                       `</NilTest>`,
+               MarshalOnly: true, // Uses interface{}
        },
        {
-               Value: MixedNested{A: "A", B: "B", C: "C", D: "D"},
+               Value: &MixedNested{A: "A", B: "B", C: "C", D: "D"},
                ExpectXML: `<result>` +
                        `<parent1><a>A</a></parent1>` +
                        `<b>B</b>` +
@@ -269,32 +384,154 @@ var marshalTests = []struct {
                        `</result>`,
        },
        {
-               Value:     Service{Port: &Port{Number: "80"}},
+               Value:     &Service{Port: &Port{Number: "80"}},
                ExpectXML: `<service><host><port>80</port></host></service>`,
        },
        {
-               Value:     Service{},
+               Value:     &Service{},
                ExpectXML: `<service></service>`,
        },
        {
-               Value: Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},
+               Value: &Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},
                ExpectXML: `<service>` +
                        `<host><port>80</port></host>` +
                        `<Extra1>A</Extra1>` +
                        `<host><extra2>B</extra2></host>` +
                        `</service>`,
+               MarshalOnly: true,
        },
        {
-               Value: Service{Port: &Port{Number: "80"}, Extra2: "example"},
+               Value: &Service{Port: &Port{Number: "80"}, Extra2: "example"},
                ExpectXML: `<service>` +
                        `<host><port>80</port></host>` +
                        `<host><extra2>example</extra2></host>` +
                        `</service>`,
+               MarshalOnly: true,
+       },
+
+       // Test struct embedding
+       {
+               Value: &EmbedA{
+                       EmbedC: EmbedC{
+                               FieldA1: "", // Shadowed by A.A
+                               FieldA2: "", // Shadowed by A.A
+                               FieldB:  "A.C.B",
+                               FieldC:  "A.C.C",
+                       },
+                       EmbedB: EmbedB{
+                               FieldB: "A.B.B",
+                               EmbedC: EmbedC{
+                                       FieldA1: "A.B.C.A1",
+                                       FieldA2: "A.B.C.A2",
+                                       FieldB:  "", // Shadowed by A.B.B
+                                       FieldC:  "A.B.C.C",
+                               },
+                       },
+                       FieldA: "A.A",
+               },
+               ExpectXML: `<EmbedA>` +
+                       `<FieldB>A.C.B</FieldB>` +
+                       `<FieldC>A.C.C</FieldC>` +
+                       `<EmbedB>` +
+                       `<FieldB>A.B.B</FieldB>` +
+                       `<FieldA>` +
+                       `<A1>A.B.C.A1</A1>` +
+                       `<A2>A.B.C.A2</A2>` +
+                       `</FieldA>` +
+                       `<FieldC>A.B.C.C</FieldC>` +
+                       `</EmbedB>` +
+                       `<FieldA>A.A</FieldA>` +
+                       `</EmbedA>`,
+       },
+
+       // Test that name casing matters
+       {
+               Value:     &NameCasing{Xy: "mixed", XY: "upper", XyA: "mixedA", XYA: "upperA"},
+               ExpectXML: `<casing Xy="mixedA" XY="upperA"><Xy>mixed</Xy><XY>upper</XY></casing>`,
+       },
+
+       // Test the order in which the XML element name is chosen
+       {
+               Value: &NamePrecedence{
+                       FromTag:     XMLNameWithoutTag{Value: "A"},
+                       FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "InXMLName"}, Value: "B"},
+                       FromNameTag: XMLNameWithTag{Value: "C"},
+                       InFieldName: "D",
+               },
+               ExpectXML: `<Parent>` +
+                       `<InTag><Value>A</Value></InTag>` +
+                       `<InXMLName><Value>B</Value></InXMLName>` +
+                       `<InXMLNameTag><Value>C</Value></InXMLNameTag>` +
+                       `<InFieldName>D</InFieldName>` +
+                       `</Parent>`,
+               MarshalOnly: true,
+       },
+       {
+               Value: &NamePrecedence{
+                       XMLName:     Name{Local: "Parent"},
+                       FromTag:     XMLNameWithoutTag{XMLName: Name{Local: "InTag"}, Value: "A"},
+                       FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "FromNameVal"}, Value: "B"},
+                       FromNameTag: XMLNameWithTag{XMLName: Name{Local: "InXMLNameTag"}, Value: "C"},
+                       InFieldName: "D",
+               },
+               ExpectXML: `<Parent>` +
+                       `<InTag><Value>A</Value></InTag>` +
+                       `<FromNameVal><Value>B</Value></FromNameVal>` +
+                       `<InXMLNameTag><Value>C</Value></InXMLNameTag>` +
+                       `<InFieldName>D</InFieldName>` +
+                       `</Parent>`,
+               UnmarshalOnly: true,
+       },
+
+       // Test attributes
+       {
+               Value: &AttrTest{
+                       Int:   8,
+                       Lower: 9,
+                       Float: 23.5,
+                       Uint8: 255,
+                       Bool:  true,
+                       Str:   "s",
+               },
+               ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="s"></AttrTest>`,
+       },
+
+       // Test ",any"
+       {
+               ExpectXML: `<a><nested><value>known</value></nested><other><sub>unknown</sub></other></a>`,
+               Value: &AnyTest{
+                       Nested: "known",
+                       AnyField: AnyHolder{
+                               XMLName: Name{Local: "other"},
+                               XML:     "<sub>unknown</sub>",
+                       },
+               },
+               UnmarshalOnly: true,
+       },
+       {
+               Value:       &AnyTest{Nested: "known", AnyField: AnyHolder{XML: "<unknown/>"}},
+               ExpectXML:   `<a><nested><value>known</value></nested></a>`,
+               MarshalOnly: true,
+       },
+
+       // Test recursive types.
+       {
+               Value: &RecurseA{