├── .dockerignore ├── .gitignore ├── Dockerfile ├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── Makefile ├── README.md ├── cmd ├── vex │ └── main.go └── vexd │ └── main.go ├── server ├── http_server.go ├── rsa.go ├── server.go ├── ssh_server.go └── ssh_types.go └── vendor ├── github.com └── yhat │ └── wsutil │ ├── LICENSE │ ├── README.md │ └── wsutil.go └── golang.org └── x └── crypto ├── AUTHORS ├── CONTRIBUTORS ├── LICENSE ├── PATENTS ├── curve25519 ├── const_amd64.h ├── const_amd64.s ├── cswap_amd64.s ├── curve25519.go ├── doc.go ├── freeze_amd64.s ├── ladderstep_amd64.s ├── mont25519_amd64.go ├── mul_amd64.s └── square_amd64.s ├── ed25519 ├── ed25519.go └── internal │ └── edwards25519 │ ├── const.go │ └── edwards25519.go ├── internal └── chacha20 │ └── chacha_generic.go ├── poly1305 ├── poly1305.go ├── sum_amd64.go ├── sum_amd64.s ├── sum_arm.go ├── sum_arm.s └── sum_ref.go └── ssh ├── buffer.go ├── certs.go ├── channel.go ├── cipher.go ├── client.go ├── client_auth.go ├── common.go ├── connection.go ├── doc.go ├── handshake.go ├── kex.go ├── keys.go ├── mac.go ├── messages.go ├── mux.go ├── server.go ├── session.go ├── streamlocal.go ├── tcpip.go └── transport.go /.dockerignore: -------------------------------------------------------------------------------- 1 | build/ 2 | id_rsa 3 | id_rsa.pub 4 | .DS_Store 5 | LICENSE 6 | Makefile 7 | README.md 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | id_rsa 3 | id_rsa.pub 4 | .DS_Store 5 | 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Stage 1 - build program 2 | FROM golang:1.10-alpine3.7 as program 3 | 4 | RUN apk --no-cache add curl git && curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh 5 | RUN mkdir -p $GOPATH/src/github.com/bleenco/vex 6 | 7 | COPY . /go/src/github.com/bleenco/vex 8 | 9 | WORKDIR /go/src/github.com/bleenco/vex/ 10 | 11 | RUN dep ensure && CGO_ENABLED=0 go build -o vexd cmd/vexd/main.go 12 | 13 | # Stage 2 - image 14 | FROM scratch 15 | 16 | ENV VEX_DOMAIN bleenco.space 17 | 18 | COPY --from=program /go/src/github.com/bleenco/vex/vexd /vexd 19 | 20 | EXPOSE 2200 2000 21 | 22 | CMD [ "/vexd" ] 23 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | branch = "master" 6 | name = "github.com/yhat/wsutil" 7 | packages = ["."] 8 | revision = "1d66fa95c997864ba4d8479f56609620fe542928" 9 | 10 | [[projects]] 11 | branch = "master" 12 | name = "golang.org/x/crypto" 13 | packages = [ 14 | "curve25519", 15 | "ed25519", 16 | "ed25519/internal/edwards25519", 17 | "internal/chacha20", 18 | "poly1305", 19 | "ssh" 20 | ] 21 | revision = "d6449816ce06963d9d136eee5a56fca5b0616e7e" 22 | 23 | [solve-meta] 24 | analyzer-name = "dep" 25 | analyzer-version = 1 26 | inputs-digest = "382a965f91a3b1571095276388e70ddc45ab8e6b784f9590b757c424fa2dcea6" 27 | solver-name = "gps-cdcl" 28 | solver-version = 1 29 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [[constraint]] 29 | branch = "master" 30 | name = "github.com/yhat/wsutil" 31 | 32 | [[constraint]] 33 | branch = "master" 34 | name = "golang.org/x/crypto" 35 | 36 | [prune] 37 | go-tests = true 38 | unused-packages = true 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2018 Bleenco GmbH https://bleenco.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OUTPUT_DIR = build 2 | OS = "darwin freebsd linux windows" 3 | ARCH = "amd64 arm" 4 | OSARCH = "!darwin/arm !windows/arm" 5 | 6 | build: 7 | mkdir -p ${OUTPUT_DIR} 8 | GOARM=5 gox -os=${OS} -arch=${ARCH} -osarch=${OSARCH} -output "${OUTPUT_DIR}/{{.Dir}}_{{.OS}}_{{.Arch}}" ./cmd/vexd ./cmd/vex 9 | 10 | clean: 11 | rm -rf ${OUTPUT_DIR} 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## vex 2 | 3 | Vex is a reverse HTTP proxy tunnel via secure SSH connections. 4 | 5 | ### Establish tunnel with vexd server on bleenco.space. 6 | 7 | Let's say you are running HTTP server locally on port 6500, then command would be: 8 | 9 | ```sh 10 | $ vex -s bleenco.space -p 2200 -ls localhost -lp 6500 11 | ``` 12 | 13 | 2200 is port where vex daemon (server) is running and localhost:6500 is local HTTP server. 14 | 15 | Example output: 16 | 17 | ```sh 18 | $ vex -s bleenco.space -p 2200 -ls localhost -lp 6500 19 | [vexd] Generated URL: http://23c41c01.bleenco.space 20 | ``` 21 | 22 | Then open generated URL in the browser to check if works, then share the URL if needed. 23 | 24 | ### Establish tunnel with vexd server on bleenco.space (vex client) 25 | 26 | ```sh 27 | $ vex -s bleenco.space -p 2200 -ls localhost -lp 7500 28 | ``` 29 | 30 | `vex` client options: 31 | 32 | ``` 33 | Usage: vex [options] 34 | 35 | Options: 36 | 37 | -s, SSH server remote host (default: bleenco.space) 38 | 39 | -p, SSH server remote port (default: 2200) 40 | 41 | -ls, Local HTTP server host (default: localhost) 42 | 43 | -lp, Local HTTP server port (default: 7500) 44 | 45 | -a, Keep tunnel connection alive (default: false) 46 | ``` 47 | 48 | ### Run cross-compilation build 49 | 50 | ```sh 51 | make clean && make build 52 | ``` 53 | 54 | ### Running server 55 | 56 | ```sh 57 | ./build/vex-server-linux_amd64 --help 58 | ``` 59 | 60 | ``` 61 | Usage: vexd [options] 62 | 63 | Options: 64 | 65 | -d, Domain name that HTTP server is hosted on. It is 66 | used for generating subdomain IDs (defaults to the 67 | environment variable VEX_DOMAIN and falls back to local.net) 68 | 69 | -k, Path to file of a ECDSA private key. All SSH communication 70 | will be secured using this key (defaults to the VEX_KEY environment 71 | variable falls back to id_rsa) 72 | 73 | -s, SSH server listen address (defaults to VEX_SSH_SERVER and 74 | falls back to 0.0.0.0:2200) 75 | 76 | -http, HTTP server listen address (defaults to VEX_HTTP_SERVER and 77 | falls back to 0.0.0.0:2000) 78 | ``` 79 | 80 | ### Licence 81 | 82 | ``` 83 | The MIT License 84 | 85 | Copyright (c) 2018 Bleenco GmbH https://bleenco.com 86 | 87 | Permission is hereby granted, free of charge, to any person obtaining a copy 88 | of this software and associated documentation files (the "Software"), to deal 89 | in the Software without restriction, including without limitation the rights 90 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 91 | copies of the Software, and to permit persons to whom the Software is 92 | furnished to do so, subject to the following conditions: 93 | 94 | The above copyright notice and this permission notice shall be included in 95 | all copies or substantial portions of the Software. 96 | 97 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 98 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 99 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 100 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 101 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 102 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 103 | THE SOFTWARE. 104 | ``` 105 | -------------------------------------------------------------------------------- /cmd/vex/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io" 7 | "log" 8 | "math/rand" 9 | "net" 10 | "os" 11 | "os/signal" 12 | "time" 13 | 14 | "github.com/pkg/errors" 15 | "golang.org/x/crypto/ssh" 16 | ) 17 | 18 | type Endpoint struct { 19 | Host string 20 | Port int 21 | } 22 | 23 | func (endpoint *Endpoint) String() string { 24 | return fmt.Sprintf("%s:%d", endpoint.Host, endpoint.Port) 25 | } 26 | 27 | var help = ` 28 | Usage: vex [options] 29 | 30 | Options: 31 | 32 | -s, SSH server remote host (default: bleenco.space) 33 | 34 | -p, SSH server remote port (default: 2200) 35 | 36 | -ls, Local HTTP server host (default: localhost) 37 | 38 | -lp, Local HTTP server port (default: 7500) 39 | 40 | -a, Keep tunnel connection alive (default: false) 41 | 42 | Read more: 43 | https://github.com/bleenco/vex 44 | ` 45 | 46 | var ( 47 | remoteServer = flag.String("s", "bleenco.space", "") 48 | remotePort = flag.Int("p", 2200, "") 49 | localServer = flag.String("ls", "localhost", "") 50 | localPort = flag.Int("lp", 7500, "") 51 | keepAlive = flag.Bool("a", false, "") 52 | ) 53 | 54 | func main() { 55 | flag.Usage = func() { 56 | fmt.Print(help) 57 | os.Exit(1) 58 | } 59 | flag.Parse() 60 | 61 | // local service to be forwarded 62 | var localEndpoint = Endpoint{ 63 | Host: *localServer, 64 | Port: *localPort, 65 | } 66 | 67 | // remote SSH server 68 | var serverEndpoint = Endpoint{ 69 | Host: *remoteServer, 70 | Port: *remotePort, 71 | } 72 | 73 | // remote forwarding port (on remote SSH server network) 74 | var remoteEndpoint = Endpoint{ 75 | Host: "localhost", 76 | Port: randomPort(11000, 65000), 77 | } 78 | 79 | sshConfig := &ssh.ClientConfig{ 80 | HostKeyCallback: ssh.InsecureIgnoreHostKey(), 81 | } 82 | 83 | // Connect to SSH remote server using serverEndpoint 84 | serverConn, err := ssh.Dial("tcp", serverEndpoint.String(), sshConfig) 85 | if err != nil { 86 | log.Fatalln(fmt.Printf("Dial INTO remote server error: %s", err)) 87 | } 88 | 89 | connectionDone := make(chan struct{}) 90 | if *keepAlive { 91 | go func() { 92 | err = keepAliveTicker(serverConn, connectionDone) 93 | if err != nil { 94 | log.Fatalln(fmt.Printf("Cannot initialize keep alive on connection: %s", err)) 95 | } 96 | }() 97 | } 98 | 99 | go func() { 100 | session, err := serverConn.NewSession() 101 | if err != nil { 102 | log.Fatalln(fmt.Printf("Cannot create session error: %s", err)) 103 | } 104 | 105 | stdout, err := session.StdoutPipe() 106 | if err != nil { 107 | log.Fatalln(fmt.Printf("Unable to setup stdout for session: %s", err)) 108 | } 109 | 110 | go io.Copy(os.Stdout, stdout) 111 | }() 112 | 113 | // Listen on remote server port 114 | listener, err := serverConn.Listen("tcp", remoteEndpoint.String()) 115 | if err != nil { 116 | log.Fatalln(fmt.Printf("Listen open port ON remote server error: %s", err)) 117 | } 118 | defer listener.Close() 119 | 120 | c := make(chan os.Signal, 1) 121 | signal.Notify(c, os.Interrupt) 122 | 123 | go func() { 124 | for { 125 | // Open a (local) connection to localEndpoint whose content will be forwarded to serverEndpoint 126 | local, err := net.Dial("tcp", localEndpoint.String()) 127 | if err != nil { 128 | log.Fatalln(fmt.Printf("Dial INTO local service error: %s", err)) 129 | } 130 | 131 | client, err := listener.Accept() 132 | if err != nil { 133 | log.Fatalln(err) 134 | } 135 | 136 | go handleClient(client, local) 137 | } 138 | }() 139 | 140 | <-c 141 | } 142 | 143 | func handleClient(client net.Conn, remote net.Conn) { 144 | defer client.Close() 145 | chDone := make(chan bool) 146 | 147 | go func() { 148 | _, err := io.Copy(client, remote) 149 | if err != nil { 150 | log.Println(fmt.Sprintf("error while copy remote->local: %s", err)) 151 | } 152 | chDone <- true 153 | }() 154 | 155 | go func() { 156 | _, err := io.Copy(remote, client) 157 | if err != nil { 158 | log.Println(fmt.Sprintf("error while copy local->remote: %s", err)) 159 | } 160 | chDone <- true 161 | }() 162 | 163 | <-chDone 164 | } 165 | 166 | func keepAliveTicker(cl *ssh.Client, done <-chan struct{}) error { 167 | t := time.NewTicker(time.Minute) 168 | defer t.Stop() 169 | for { 170 | select { 171 | case <-t.C: 172 | _, _, err := cl.SendRequest("keepalive", true, nil) 173 | if err != nil { 174 | return errors.Wrap(err, "failed to send keep alive") 175 | } 176 | case <-done: 177 | return nil 178 | } 179 | } 180 | } 181 | 182 | func randomPort(min, max int) int { 183 | rand.Seed(time.Now().Unix()) 184 | return rand.Intn(max-min) + min 185 | } 186 | -------------------------------------------------------------------------------- /cmd/vexd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/bleenco/vex/server" 9 | ) 10 | 11 | var help = ` 12 | Usage: vexd [options] 13 | 14 | Options: 15 | 16 | -d, Domain name that HTTP server is hosted on. It is 17 | used for generating subdomain IDs (defaults to the 18 | environment variable VEX_DOMAIN and falls back to local.net) 19 | 20 | -k, Path to file of a ECDSA private key. All SSH communication 21 | will be secured using this key (defaults to the VEX_KEY environment 22 | variable falls back to id_rsa) 23 | 24 | -s, SSH server listen address (defaults to VEX_SSH_SERVER and 25 | falls back to 0.0.0.0:2200) 26 | 27 | -http, HTTP server listen address (defaults to VEX_HTTP_SERVER and 28 | falls back to 0.0.0.0:2000) 29 | 30 | Read more: 31 | https://github.com/bleenco/vex 32 | ` 33 | 34 | var ( 35 | domain = flag.String("d", "", "Domain name") 36 | privatekeyfile = flag.String("k", "", "Private Key File") 37 | sshlistenaddr = flag.String("s", "", "SSH server listen address") 38 | httplistenaddr = flag.String("http", "", "HTTP server listen address") 39 | ) 40 | 41 | func main() { 42 | flag.Usage = func() { 43 | fmt.Print(help) 44 | os.Exit(1) 45 | } 46 | flag.Parse() 47 | 48 | if *domain == "" { 49 | *domain = os.Getenv("VEX_DOMAIN") 50 | } 51 | if *domain == "" { 52 | *domain = "local.net" 53 | } 54 | if *privatekeyfile == "" { 55 | *privatekeyfile = os.Getenv("VEX_KEY") 56 | } 57 | if *privatekeyfile == "" { 58 | *privatekeyfile = "id_rsa" 59 | } 60 | if *sshlistenaddr == "" { 61 | *sshlistenaddr = os.Getenv("VEX_SSH_SERVER") 62 | } 63 | if *sshlistenaddr == "" { 64 | *sshlistenaddr = "0.0.0.0:2200" 65 | } 66 | if *httplistenaddr == "" { 67 | *httplistenaddr = os.Getenv("VEX_HTTP_SERVER") 68 | } 69 | if *httplistenaddr == "" { 70 | *httplistenaddr = "0.0.0.0:2000" 71 | } 72 | 73 | if _, err := os.Stat(*privatekeyfile); os.IsNotExist(err) { 74 | vexserver.GenerateRSA() 75 | } 76 | 77 | config := &vexserver.Config{ 78 | Domain: *domain, 79 | PrivateKeyFile: *privatekeyfile, 80 | SSHListenAddr: *sshlistenaddr, 81 | HTTPListenAddr: *httplistenaddr, 82 | } 83 | 84 | server := vexserver.NewServer(config) 85 | server.Run() 86 | } 87 | -------------------------------------------------------------------------------- /server/http_server.go: -------------------------------------------------------------------------------- 1 | package vexserver 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "net" 7 | "net/http" 8 | "sync" 9 | ) 10 | 11 | // HTTPServer extends net/http server and 12 | // adds graceful shutdowns 13 | type HTTPServer struct { 14 | *http.Server 15 | listener net.Listener 16 | running chan error 17 | isRunning bool 18 | closer sync.Once 19 | } 20 | 21 | // NewHTTPServer creates a new HTTPServer instance 22 | func NewHTTPServer() *HTTPServer { 23 | return &HTTPServer{ 24 | Server: &http.Server{}, 25 | listener: nil, 26 | running: make(chan error, 1), 27 | } 28 | } 29 | 30 | // GoListenAndServe starts HTTPServer instance and listens on 31 | // specified addr 32 | func (h *HTTPServer) GoListenAndServe(addr string, handler http.Handler) error { 33 | l, err := net.Listen("tcp", addr) 34 | if err != nil { 35 | return err 36 | } 37 | h.isRunning = true 38 | h.Handler = handler 39 | h.listener = l 40 | 41 | log.Printf("HTTP server listening on %s...\n", addr) 42 | 43 | go func() { 44 | h.closeWith(h.Serve(l)) 45 | }() 46 | return nil 47 | } 48 | 49 | func (h *HTTPServer) closeWith(err error) { 50 | if !h.isRunning { 51 | return 52 | } 53 | h.isRunning = false 54 | h.running <- err 55 | } 56 | 57 | // Close closes the HTTPServer instance 58 | func (h *HTTPServer) Close() error { 59 | h.closeWith(nil) 60 | return h.listener.Close() 61 | } 62 | 63 | // Wait waits for server to be stopped 64 | func (h *HTTPServer) Wait() error { 65 | if !h.isRunning { 66 | return errors.New("already closed") 67 | } 68 | return <-h.running 69 | } 70 | -------------------------------------------------------------------------------- /server/rsa.go: -------------------------------------------------------------------------------- 1 | package vexserver 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "crypto/x509" 7 | "encoding/asn1" 8 | "encoding/gob" 9 | "encoding/pem" 10 | "fmt" 11 | "os" 12 | ) 13 | 14 | func GenerateRSA() { 15 | reader := rand.Reader 16 | bitSize := 2048 17 | 18 | key, err := rsa.GenerateKey(reader, bitSize) 19 | checkError(err) 20 | 21 | publicKey := key.PublicKey 22 | 23 | savePEMKey("id_rsa", key) 24 | savePublicPEMKey("id_rsa.pub", publicKey) 25 | } 26 | 27 | func saveGobKey(fileName string, key interface{}) { 28 | outFile, err := os.Create(fileName) 29 | checkError(err) 30 | defer outFile.Close() 31 | 32 | encoder := gob.NewEncoder(outFile) 33 | err = encoder.Encode(key) 34 | checkError(err) 35 | } 36 | 37 | func savePEMKey(fileName string, key *rsa.PrivateKey) { 38 | outFile, err := os.Create(fileName) 39 | checkError(err) 40 | defer outFile.Close() 41 | 42 | var privateKey = &pem.Block{ 43 | Type: "RSA PRIVATE KEY", 44 | Bytes: x509.MarshalPKCS1PrivateKey(key), 45 | } 46 | 47 | err = pem.Encode(outFile, privateKey) 48 | checkError(err) 49 | } 50 | 51 | func savePublicPEMKey(fileName string, pubkey rsa.PublicKey) { 52 | asn1Bytes, err := asn1.Marshal(pubkey) 53 | checkError(err) 54 | 55 | var pemkey = &pem.Block{ 56 | Type: "RSA PUBLIC KEY", 57 | Bytes: asn1Bytes, 58 | } 59 | 60 | pemfile, err := os.Create(fileName) 61 | checkError(err) 62 | defer pemfile.Close() 63 | 64 | err = pem.Encode(pemfile, pemkey) 65 | checkError(err) 66 | } 67 | 68 | func checkError(err error) { 69 | if err != nil { 70 | fmt.Println("Fatal error ", err.Error()) 71 | os.Exit(1) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /server/server.go: -------------------------------------------------------------------------------- 1 | package vexserver 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httputil" 6 | "net/url" 7 | "strconv" 8 | "strings" 9 | 10 | "github.com/yhat/wsutil" 11 | ) 12 | 13 | type Config struct { 14 | Domain string 15 | PrivateKeyFile string 16 | SSHListenAddr string 17 | HTTPListenAddr string 18 | } 19 | 20 | type Server struct { 21 | sshServer *SSHServer 22 | httpServer *HTTPServer 23 | config *Config 24 | } 25 | 26 | func NewServer(config *Config) *Server { 27 | return &Server{ 28 | sshServer: NewSSHServer(), 29 | httpServer: NewHTTPServer(), 30 | config: config, 31 | } 32 | } 33 | 34 | func (s *Server) Run() error { 35 | err := s.sshServer.Start(s.config.SSHListenAddr, s.config.PrivateKeyFile, s.config.Domain) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | var h http.Handler = http.HandlerFunc(s.handleHTTP) 41 | err = s.httpServer.GoListenAndServe(s.config.HTTPListenAddr, h) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | return s.httpServer.Wait() 47 | } 48 | 49 | func (s *Server) handleHTTP(w http.ResponseWriter, r *http.Request) { 50 | host := r.Host 51 | userID := host 52 | pos := strings.IndexByte(host, '.') 53 | if pos > 0 { 54 | userID = host[:pos] 55 | } 56 | 57 | if client, ok := s.sshServer.clients[userID]; ok { 58 | w.Header().Set("X-Proxy", "vexd") 59 | if strings.ToLower(r.Header.Get("Upgrade")) == "websocket" { 60 | url := &url.URL{Scheme: "ws://", Host: client.Addr + ":" + strconv.Itoa(int(client.Port))} 61 | proxy := wsutil.NewSingleHostReverseProxy(url) 62 | proxy.ServeHTTP(w, r) 63 | return 64 | } else { 65 | url, _ := url.Parse("http://" + client.Addr + ":" + strconv.Itoa(int(client.Port))) 66 | proxy := httputil.NewSingleHostReverseProxy(url) 67 | proxy.ServeHTTP(w, r) 68 | return 69 | } 70 | } 71 | 72 | w.WriteHeader(http.StatusNotFound) 73 | w.Write([]byte("Not found")) 74 | } 75 | -------------------------------------------------------------------------------- /server/ssh_server.go: -------------------------------------------------------------------------------- 1 | package vexserver 2 | 3 | import ( 4 | "crypto/rand" 5 | "errors" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "log" 10 | "net" 11 | "sync" 12 | "time" 13 | 14 | "golang.org/x/crypto/ssh" 15 | ) 16 | 17 | type SSHServer struct { 18 | listener net.Listener 19 | config *ssh.ServerConfig 20 | running chan error 21 | isRunning bool 22 | closer sync.Once 23 | clients map[string]Client 24 | domain string 25 | } 26 | 27 | type Client struct { 28 | ID string 29 | net.Conn 30 | *ssh.ServerConn 31 | Listeners map[string]net.Listener 32 | Addr string 33 | Port uint32 34 | ListenMutex *sync.Mutex 35 | } 36 | 37 | func NewSSHServer() *SSHServer { 38 | return &SSHServer{ 39 | listener: nil, 40 | config: &ssh.ServerConfig{ 41 | NoClientAuth: true, 42 | }, 43 | running: make(chan error, 1), 44 | clients: make(map[string]Client), 45 | } 46 | } 47 | 48 | func (s *SSHServer) Start(addr string, privateKey string, domain string) error { 49 | privateBytes, err := ioutil.ReadFile(privateKey) 50 | if err != nil { 51 | log.Fatalf("Failed to load private key %s\n", privateKey) 52 | } 53 | 54 | private, err := ssh.ParsePrivateKey(privateBytes) 55 | if err != nil { 56 | log.Fatalf("Failed to parse private key") 57 | } 58 | 59 | s.config.AddHostKey(private) 60 | 61 | go func() { 62 | s.closeWith(s.listen(addr, domain)) 63 | }() 64 | return nil 65 | } 66 | 67 | func (s *SSHServer) listen(addr string, domain string) error { 68 | listener, err := net.Listen("tcp", addr) 69 | if err != nil { 70 | log.Fatalf("Failed to listen on %s (%s)", addr, err) 71 | } 72 | s.listener = listener 73 | s.domain = domain 74 | 75 | log.Printf("SSH server listening on %s, generating urls on *.%s ...\n", addr, domain) 76 | 77 | for { 78 | tcpConn, err := s.listener.Accept() 79 | if err != nil { 80 | log.Printf("Failed to accept incoming connection (%s)\n", err) 81 | continue 82 | } 83 | 84 | sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, s.config) 85 | if err != nil { 86 | log.Printf("Failed to handshake (%s)\n", err) 87 | continue 88 | } 89 | 90 | client := &Client{randID(), tcpConn, sshConn, make(map[string]net.Listener), "", 0, &sync.Mutex{}} 91 | log.Printf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion()) 92 | 93 | go func() { 94 | err := client.ServerConn.Wait() 95 | client.ListenMutex.Lock() 96 | log.Printf("[%s] SSH connection closed: %s", client.ID, err) 97 | 98 | for bind, listener := range client.Listeners { 99 | log.Printf("[%s] Closing listener bound to %s", client.ID, bind) 100 | listener.Close() 101 | } 102 | }() 103 | 104 | go s.handleRequests(client, reqs) 105 | go s.handleChannels(client, chans) 106 | } 107 | } 108 | 109 | func (s *SSHServer) closeWith(err error) { 110 | if !s.isRunning { 111 | return 112 | } 113 | s.isRunning = false 114 | s.running <- err 115 | } 116 | 117 | func (s *SSHServer) Close() error { 118 | s.closeWith(nil) 119 | return s.listener.Close() 120 | } 121 | 122 | func (s *SSHServer) Wait() error { 123 | if !s.isRunning { 124 | return errors.New("already closed") 125 | } 126 | return <-s.running 127 | } 128 | 129 | func (s *SSHServer) handleChannels(client *Client, chans <-chan ssh.NewChannel) { 130 | for newChannel := range chans { 131 | channelConn, _, err := newChannel.Accept() 132 | if err != nil { 133 | log.Printf("Could not accept channel (%s)", err) 134 | return 135 | } 136 | 137 | generatedURL := "http://" + client.ID + "." + s.domain 138 | io.WriteString(channelConn, "[vexd] Generated URL: "+generatedURL+"\n") 139 | } 140 | } 141 | 142 | func (s *SSHServer) handleRequests(client *Client, reqs <-chan *ssh.Request) { 143 | for req := range reqs { 144 | client.Conn.SetDeadline(time.Now().Add(2 * time.Minute)) 145 | 146 | log.Printf("[%s] Out of band request: %v %v", client.ID, req.Type, req.WantReply) 147 | 148 | if req.Type == "tcpip-forward" { 149 | client.ListenMutex.Lock() 150 | 151 | listener, bindinfo, err := handleForward(client, req) 152 | if err != nil { 153 | fmt.Printf("[%s] Error, disconnecting ...\n", client.ID) 154 | client.ListenMutex.Unlock() 155 | client.Conn.Close() 156 | } 157 | 158 | client.Addr = bindinfo.Addr 159 | client.Port = bindinfo.Port 160 | client.Listeners[bindinfo.Bound] = listener 161 | s.clients[client.ID] = *client 162 | client.ListenMutex.Unlock() 163 | 164 | go handleListener(client, bindinfo, listener) 165 | continue 166 | // client.Conn.Close() 167 | } else { 168 | req.Reply(false, []byte{}) 169 | } 170 | } 171 | } 172 | 173 | func handleListener(client *Client, bindinfo *bindInfo, listener net.Listener) { 174 | for { 175 | lconn, err := listener.Accept() 176 | if err != nil { 177 | neterr := err.(net.Error) 178 | if neterr.Timeout() { 179 | log.Printf("[%s] Accept failed with timeout: %s", client.ID, err) 180 | continue 181 | } 182 | if neterr.Temporary() { 183 | log.Printf("[%s] Accept failed with temporary: %s", client.ID, err) 184 | continue 185 | } 186 | 187 | break 188 | } 189 | 190 | go handleForwardTCPIP(client, bindinfo, lconn) 191 | } 192 | } 193 | 194 | func handleForwardTCPIP(client *Client, bindinfo *bindInfo, lconn net.Conn) { 195 | remotetcpaddr := lconn.RemoteAddr().(*net.TCPAddr) 196 | raddr := remotetcpaddr.IP.String() 197 | rport := uint32(remotetcpaddr.Port) 198 | 199 | payload := forwardedTCPPayload{bindinfo.Addr, bindinfo.Port, raddr, uint32(rport)} 200 | mpayload := ssh.Marshal(&payload) 201 | 202 | // Open channel with client 203 | c, requests, err := client.ServerConn.OpenChannel("forwarded-tcpip", mpayload) 204 | if err != nil { 205 | log.Printf("[%s] Unable to get channel: %s. Hanging up requesting party!", client.ID, err) 206 | lconn.Close() 207 | return 208 | } 209 | log.Printf("[%s] Channel opened for client", client.ID) 210 | go ssh.DiscardRequests(requests) 211 | 212 | go handleForwardTCPIPTransfer(c, lconn) 213 | } 214 | 215 | func handleForwardTCPIPTransfer(c ssh.Channel, lconn net.Conn) { 216 | defer lconn.Close() 217 | done := make(chan bool) 218 | 219 | go func() { 220 | io.Copy(c, lconn) 221 | done <- true 222 | }() 223 | 224 | go func() { 225 | io.Copy(lconn, c) 226 | done <- true 227 | }() 228 | 229 | <-done 230 | } 231 | 232 | func handleForward(client *Client, req *ssh.Request) (net.Listener, *bindInfo, error) { 233 | var payload tcpIPForwardPayload 234 | if err := ssh.Unmarshal(req.Payload, &payload); err != nil { 235 | log.Printf("[%s] Unable to unmarshal payload", client.ID) 236 | req.Reply(false, []byte{}) 237 | return nil, nil, fmt.Errorf("Unable to parse payload") 238 | } 239 | 240 | log.Printf("[%s] Request: %s %v %v", client.ID, req.Type, req.WantReply, payload) 241 | 242 | bind := fmt.Sprintf("%s:%d", payload.Addr, payload.Port) 243 | ln, err := net.Listen("tcp", bind) 244 | if err != nil { 245 | log.Printf("[%s] Listen failed for %s", client.ID, bind) 246 | req.Reply(false, []byte{}) 247 | return nil, nil, err 248 | } 249 | 250 | log.Printf("[%s] Listening on %s:%d", client.ID, payload.Addr, payload.Port) 251 | 252 | reply := tcpIPForwardPayloadReply{payload.Port} 253 | req.Reply(true, ssh.Marshal(&reply)) 254 | 255 | return ln, &bindInfo{bind, payload.Port, payload.Addr}, nil 256 | } 257 | 258 | func randID() string { 259 | b := make([]byte, 4) 260 | rand.Read(b) 261 | return fmt.Sprintf("%x", b) 262 | } 263 | -------------------------------------------------------------------------------- /server/ssh_types.go: -------------------------------------------------------------------------------- 1 | package vexserver 2 | 3 | // Structure contains data of what address/port 4 | // we should bind forwarded-tcpip connections 5 | type bindInfo struct { 6 | Bound string 7 | Port uint32 8 | Addr string 9 | } 10 | 11 | // Information parsed from the authorized_keys file 12 | type deviceInfo struct { 13 | LocalPorts string 14 | RemotePorts string 15 | Comment string 16 | } 17 | 18 | // RFC4254 7.2 19 | type directTCPPayload struct { 20 | Addr string // Connect to 21 | Port uint32 22 | OriginAddr string 23 | OriginPort uint32 24 | } 25 | 26 | type forwardedTCPPayload struct { 27 | Addr string // Connected to 28 | Port uint32 29 | OriginAddr string 30 | OriginPort uint32 31 | } 32 | 33 | type tcpIPForwardPayload struct { 34 | Addr string 35 | Port uint32 36 | } 37 | 38 | type tcpIPForwardPayloadReply struct { 39 | Port uint32 40 | } 41 | 42 | type tcpIPForwardCancelPayload struct { 43 | Addr string 44 | Port uint32 45 | } 46 | -------------------------------------------------------------------------------- /vendor/github.com/yhat/wsutil/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Yhat, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /vendor/github.com/yhat/wsutil/README.md: -------------------------------------------------------------------------------- 1 | # wsutil 2 | 3 | Like `net/http/httputil` but for WebSockets. 4 | 5 | [![GoDoc](https://godoc.org/github.com/yhat/wsutil?status.svg)](https://godoc.org/github.com/yhat/wsutil) 6 | 7 | ## A Reverse Proxy Example 8 | 9 | ```go 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "io" 15 | "log" 16 | "net/http" 17 | "net/url" 18 | "time" 19 | 20 | "github.com/yhat/wsutil" 21 | "golang.org/x/net/websocket" 22 | ) 23 | 24 | func main() { 25 | backend := ":8001" 26 | proxy := ":8002" 27 | 28 | // an webscket echo server 29 | backendHandler := websocket.Handler(func(ws *websocket.Conn) { 30 | io.Copy(ws, ws) 31 | }) 32 | 33 | // make a proxy pointing at that backend url 34 | backendURL := &url.URL{Scheme: "ws://", Host: backend} 35 | p := wsutil.NewSingleHostReverseProxy(backendURL) 36 | 37 | // run both servers and give them a second to start up 38 | go http.ListenAndServe(backend, backendHandler) 39 | go http.ListenAndServe(proxy, p) 40 | time.Sleep(1 * time.Second) 41 | 42 | // connect to the proxy 43 | origin := "http://localhost/" 44 | ws, err := websocket.Dial("ws://"+proxy, "", origin) 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | 49 | // send a message along the websocket 50 | msg := []byte("isn't yhat awesome?") 51 | if _, err := ws.Write(msg); err != nil { 52 | log.Fatal(err) 53 | } 54 | 55 | // read the response from the proxy 56 | resp := make([]byte, 4096) 57 | if n, err := ws.Read(resp); err != nil { 58 | log.Fatal(err) 59 | } else { 60 | fmt.Printf("%s\n", resp[:n]) 61 | } 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /vendor/github.com/yhat/wsutil/wsutil.go: -------------------------------------------------------------------------------- 1 | package wsutil 2 | 3 | import ( 4 | "crypto/tls" 5 | "io" 6 | "log" 7 | "net" 8 | "net/http" 9 | "net/url" 10 | "strings" 11 | ) 12 | 13 | // ReverseProxy is a WebSocket reverse proxy. It will not work with a regular 14 | // HTTP request, so it is the caller's responsiblity to ensure the incoming 15 | // request is a WebSocket request. 16 | type ReverseProxy struct { 17 | // Director must be a function which modifies 18 | // the request into a new request to be sent 19 | // using Transport. Its response is then copied 20 | // back to the original client unmodified. 21 | Director func(*http.Request) 22 | 23 | // Dial specifies the dial function for dialing the proxied 24 | // server over tcp. 25 | // If Dial is nil, net.Dial is used. 26 | Dial func(network, addr string) (net.Conn, error) 27 | 28 | // TLSClientConfig specifies the TLS configuration to use for 'wss'. 29 | // If nil, the default configuration is used. 30 | TLSClientConfig *tls.Config 31 | 32 | // ErrorLog specifies an optional logger for errors 33 | // that occur when attempting to proxy the request. 34 | // If nil, logging goes to os.Stderr via the log package's 35 | // standard logger. 36 | ErrorLog *log.Logger 37 | } 38 | 39 | // stolen from net/http/httputil. singleJoiningSlash ensures that the route 40 | // '/a/' joined with '/b' becomes '/a/b'. 41 | func singleJoiningSlash(a, b string) string { 42 | aslash := strings.HasSuffix(a, "/") 43 | bslash := strings.HasPrefix(b, "/") 44 | switch { 45 | case aslash && bslash: 46 | return a + b[1:] 47 | case !aslash && !bslash: 48 | return a + "/" + b 49 | } 50 | return a + b 51 | } 52 | 53 | // NewSingleHostReverseProxy returns a new websocket ReverseProxy. The path 54 | // rewrites follow the same rules as the httputil.ReverseProxy. If the target 55 | // url has the path '/foo' and the incoming request '/bar', the request path 56 | // will be updated to '/foo/bar' before forwarding. 57 | // Scheme should specify if 'ws' or 'wss' should be used. 58 | func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy { 59 | targetQuery := target.RawQuery 60 | director := func(req *http.Request) { 61 | req.URL.Scheme = target.Scheme 62 | req.URL.Host = target.Host 63 | req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path) 64 | if targetQuery == "" || req.URL.RawQuery == "" { 65 | req.URL.RawQuery = targetQuery + req.URL.RawQuery 66 | } else { 67 | req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery 68 | } 69 | } 70 | return &ReverseProxy{Director: director} 71 | } 72 | 73 | // Function to implement the http.Handler interface. 74 | func (p *ReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { 75 | logFunc := log.Printf 76 | if p.ErrorLog != nil { 77 | logFunc = p.ErrorLog.Printf 78 | } 79 | 80 | if !IsWebSocketRequest(r) { 81 | http.Error(w, "Cannot handle non-WebSocket requests", 500) 82 | logFunc("Received a request that was not a WebSocket request") 83 | return 84 | } 85 | 86 | outreq := new(http.Request) 87 | // shallow copying 88 | *outreq = *r 89 | p.Director(outreq) 90 | host := outreq.URL.Host 91 | 92 | if clientIP, _, err := net.SplitHostPort(r.RemoteAddr); err == nil { 93 | // If we aren't the first proxy retain prior 94 | // X-Forwarded-For information as a comma+space 95 | // separated list and fold multiple headers into one. 96 | if prior, ok := outreq.Header["X-Forwarded-For"]; ok { 97 | clientIP = strings.Join(prior, ", ") + ", " + clientIP 98 | } 99 | outreq.Header.Set("X-Forwarded-For", clientIP) 100 | } 101 | 102 | dial := p.Dial 103 | if dial == nil { 104 | dial = net.Dial 105 | } 106 | 107 | // if host does not specify a port, use the default http port 108 | if !strings.Contains(host, ":") { 109 | if outreq.URL.Scheme == "wss" { 110 | host = host + ":443" 111 | } else { 112 | host = host + ":80" 113 | } 114 | } 115 | 116 | if outreq.URL.Scheme == "wss" { 117 | var tlsConfig *tls.Config 118 | if p.TLSClientConfig == nil { 119 | tlsConfig = &tls.Config{} 120 | } else { 121 | tlsConfig = p.TLSClientConfig 122 | } 123 | dial = func(network, address string) (net.Conn, error) { 124 | return tls.Dial("tcp", host, tlsConfig) 125 | } 126 | } 127 | 128 | d, err := dial("tcp", host) 129 | if err != nil { 130 | http.Error(w, "Error forwarding request.", 500) 131 | logFunc("Error dialing websocket backend %s: %v", outreq.URL, err) 132 | return 133 | } 134 | // All request generated by the http package implement this interface. 135 | hj, ok := w.(http.Hijacker) 136 | if !ok { 137 | http.Error(w, "Not a hijacker?", 500) 138 | return 139 | } 140 | // Hijack() tells the http package not to do anything else with the connection. 141 | // After, it bcomes this functions job to manage it. `nc` is of type *net.Conn. 142 | nc, _, err := hj.Hijack() 143 | if err != nil { 144 | logFunc("Hijack error: %v", err) 145 | return 146 | } 147 | defer nc.Close() // must close the underlying net connection after hijacking 148 | defer d.Close() 149 | 150 | // write the modified incoming request to the dialed connection 151 | err = outreq.Write(d) 152 | if err != nil { 153 | logFunc("Error copying request to target: %v", err) 154 | return 155 | } 156 | errc := make(chan error, 2) 157 | cp := func(dst io.Writer, src io.Reader) { 158 | _, err := io.Copy(dst, src) 159 | errc <- err 160 | } 161 | go cp(d, nc) 162 | go cp(nc, d) 163 | <-errc 164 | } 165 | 166 | // IsWebSocketRequest returns a boolean indicating whether the request has the 167 | // headers of a WebSocket handshake request. 168 | func IsWebSocketRequest(r *http.Request) bool { 169 | contains := func(key, val string) bool { 170 | vv := strings.Split(r.Header.Get(key), ",") 171 | for _, v := range vv { 172 | if val == strings.ToLower(strings.TrimSpace(v)) { 173 | return true 174 | } 175 | } 176 | return false 177 | } 178 | if !contains("Connection", "upgrade") { 179 | return false 180 | } 181 | if !contains("Upgrade", "websocket") { 182 | return false 183 | } 184 | return true 185 | } 186 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at https://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at https://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/curve25519/const_amd64.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html 7 | 8 | #define REDMASK51 0x0007FFFFFFFFFFFF 9 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/curve25519/const_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | // These constants cannot be encoded in non-MOVQ immediates. 11 | // We access them directly from memory instead. 12 | 13 | DATA ·_121666_213(SB)/8, $996687872 14 | GLOBL ·_121666_213(SB), 8, $8 15 | 16 | DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA 17 | GLOBL ·_2P0(SB), 8, $8 18 | 19 | DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE 20 | GLOBL ·_2P1234(SB), 8, $8 21 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/curve25519/cswap_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64,!gccgo,!appengine 6 | 7 | // func cswap(inout *[4][5]uint64, v uint64) 8 | TEXT ·cswap(SB),7,$0 9 | MOVQ inout+0(FP),DI 10 | MOVQ v+8(FP),SI 11 | 12 | SUBQ $1, SI 13 | NOTQ SI 14 | MOVQ SI, X15 15 | PSHUFD $0x44, X15, X15 16 | 17 | MOVOU 0(DI), X0 18 | MOVOU 16(DI), X2 19 | MOVOU 32(DI), X4 20 | MOVOU 48(DI), X6 21 | MOVOU 64(DI), X8 22 | MOVOU 80(DI), X1 23 | MOVOU 96(DI), X3 24 | MOVOU 112(DI), X5 25 | MOVOU 128(DI), X7 26 | MOVOU 144(DI), X9 27 | 28 | MOVO X1, X10 29 | MOVO X3, X11 30 | MOVO X5, X12 31 | MOVO X7, X13 32 | MOVO X9, X14 33 | 34 | PXOR X0, X10 35 | PXOR X2, X11 36 | PXOR X4, X12 37 | PXOR X6, X13 38 | PXOR X8, X14 39 | PAND X15, X10 40 | PAND X15, X11 41 | PAND X15, X12 42 | PAND X15, X13 43 | PAND X15, X14 44 | PXOR X10, X0 45 | PXOR X10, X1 46 | PXOR X11, X2 47 | PXOR X11, X3 48 | PXOR X12, X4 49 | PXOR X12, X5 50 | PXOR X13, X6 51 | PXOR X13, X7 52 | PXOR X14, X8 53 | PXOR X14, X9 54 | 55 | MOVOU X0, 0(DI) 56 | MOVOU X2, 16(DI) 57 | MOVOU X4, 32(DI) 58 | MOVOU X6, 48(DI) 59 | MOVOU X8, 64(DI) 60 | MOVOU X1, 80(DI) 61 | MOVOU X3, 96(DI) 62 | MOVOU X5, 112(DI) 63 | MOVOU X7, 128(DI) 64 | MOVOU X9, 144(DI) 65 | RET 66 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/curve25519/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package curve25519 provides an implementation of scalar multiplication on 6 | // the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html 7 | package curve25519 // import "golang.org/x/crypto/curve25519" 8 | 9 | // basePoint is the x coordinate of the generator of the curve. 10 | var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 11 | 12 | // ScalarMult sets dst to the product in*base where dst and base are the x 13 | // coordinates of group points and all values are in little-endian form. 14 | func ScalarMult(dst, in, base *[32]byte) { 15 | scalarMult(dst, in, base) 16 | } 17 | 18 | // ScalarBaseMult sets dst to the product in*base where dst and base are the x 19 | // coordinates of group points, base is the standard generator and all values 20 | // are in little-endian form. 21 | func ScalarBaseMult(dst, in *[32]byte) { 22 | ScalarMult(dst, in, &basePoint) 23 | } 24 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/curve25519/freeze_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | #include "const_amd64.h" 11 | 12 | // func freeze(inout *[5]uint64) 13 | TEXT ·freeze(SB),7,$0-8 14 | MOVQ inout+0(FP), DI 15 | 16 | MOVQ 0(DI),SI 17 | MOVQ 8(DI),DX 18 | MOVQ 16(DI),CX 19 | MOVQ 24(DI),R8 20 | MOVQ 32(DI),R9 21 | MOVQ $REDMASK51,AX 22 | MOVQ AX,R10 23 | SUBQ $18,R10 24 | MOVQ $3,R11 25 | REDUCELOOP: 26 | MOVQ SI,R12 27 | SHRQ $51,R12 28 | ANDQ AX,SI 29 | ADDQ R12,DX 30 | MOVQ DX,R12 31 | SHRQ $51,R12 32 | ANDQ AX,DX 33 | ADDQ R12,CX 34 | MOVQ CX,R12 35 | SHRQ $51,R12 36 | ANDQ AX,CX 37 | ADDQ R12,R8 38 | MOVQ R8,R12 39 | SHRQ $51,R12 40 | ANDQ AX,R8 41 | ADDQ R12,R9 42 | MOVQ R9,R12 43 | SHRQ $51,R12 44 | ANDQ AX,R9 45 | IMUL3Q $19,R12,R12 46 | ADDQ R12,SI 47 | SUBQ $1,R11 48 | JA REDUCELOOP 49 | MOVQ $1,R12 50 | CMPQ R10,SI 51 | CMOVQLT R11,R12 52 | CMPQ AX,DX 53 | CMOVQNE R11,R12 54 | CMPQ AX,CX 55 | CMOVQNE R11,R12 56 | CMPQ AX,R8 57 | CMOVQNE R11,R12 58 | CMPQ AX,R9 59 | CMOVQNE R11,R12 60 | NEGQ R12 61 | ANDQ R12,AX 62 | ANDQ R12,R10 63 | SUBQ R10,SI 64 | SUBQ AX,DX 65 | SUBQ AX,CX 66 | SUBQ AX,R8 67 | SUBQ AX,R9 68 | MOVQ SI,0(DI) 69 | MOVQ DX,8(DI) 70 | MOVQ CX,16(DI) 71 | MOVQ R8,24(DI) 72 | MOVQ R9,32(DI) 73 | RET 74 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64,!gccgo,!appengine 6 | 7 | package curve25519 8 | 9 | // These functions are implemented in the .s files. The names of the functions 10 | // in the rest of the file are also taken from the SUPERCOP sources to help 11 | // people following along. 12 | 13 | //go:noescape 14 | 15 | func cswap(inout *[5]uint64, v uint64) 16 | 17 | //go:noescape 18 | 19 | func ladderstep(inout *[5][5]uint64) 20 | 21 | //go:noescape 22 | 23 | func freeze(inout *[5]uint64) 24 | 25 | //go:noescape 26 | 27 | func mul(dest, a, b *[5]uint64) 28 | 29 | //go:noescape 30 | 31 | func square(out, in *[5]uint64) 32 | 33 | // mladder uses a Montgomery ladder to calculate (xr/zr) *= s. 34 | func mladder(xr, zr *[5]uint64, s *[32]byte) { 35 | var work [5][5]uint64 36 | 37 | work[0] = *xr 38 | setint(&work[1], 1) 39 | setint(&work[2], 0) 40 | work[3] = *xr 41 | setint(&work[4], 1) 42 | 43 | j := uint(6) 44 | var prevbit byte 45 | 46 | for i := 31; i >= 0; i-- { 47 | for j < 8 { 48 | bit := ((*s)[i] >> j) & 1 49 | swap := bit ^ prevbit 50 | prevbit = bit 51 | cswap(&work[1], uint64(swap)) 52 | ladderstep(&work) 53 | j-- 54 | } 55 | j = 7 56 | } 57 | 58 | *xr = work[1] 59 | *zr = work[2] 60 | } 61 | 62 | func scalarMult(out, in, base *[32]byte) { 63 | var e [32]byte 64 | copy(e[:], (*in)[:]) 65 | e[0] &= 248 66 | e[31] &= 127 67 | e[31] |= 64 68 | 69 | var t, z [5]uint64 70 | unpack(&t, base) 71 | mladder(&t, &z, &e) 72 | invert(&z, &z) 73 | mul(&t, &t, &z) 74 | pack(out, &t) 75 | } 76 | 77 | func setint(r *[5]uint64, v uint64) { 78 | r[0] = v 79 | r[1] = 0 80 | r[2] = 0 81 | r[3] = 0 82 | r[4] = 0 83 | } 84 | 85 | // unpack sets r = x where r consists of 5, 51-bit limbs in little-endian 86 | // order. 87 | func unpack(r *[5]uint64, x *[32]byte) { 88 | r[0] = uint64(x[0]) | 89 | uint64(x[1])<<8 | 90 | uint64(x[2])<<16 | 91 | uint64(x[3])<<24 | 92 | uint64(x[4])<<32 | 93 | uint64(x[5])<<40 | 94 | uint64(x[6]&7)<<48 95 | 96 | r[1] = uint64(x[6])>>3 | 97 | uint64(x[7])<<5 | 98 | uint64(x[8])<<13 | 99 | uint64(x[9])<<21 | 100 | uint64(x[10])<<29 | 101 | uint64(x[11])<<37 | 102 | uint64(x[12]&63)<<45 103 | 104 | r[2] = uint64(x[12])>>6 | 105 | uint64(x[13])<<2 | 106 | uint64(x[14])<<10 | 107 | uint64(x[15])<<18 | 108 | uint64(x[16])<<26 | 109 | uint64(x[17])<<34 | 110 | uint64(x[18])<<42 | 111 | uint64(x[19]&1)<<50 112 | 113 | r[3] = uint64(x[19])>>1 | 114 | uint64(x[20])<<7 | 115 | uint64(x[21])<<15 | 116 | uint64(x[22])<<23 | 117 | uint64(x[23])<<31 | 118 | uint64(x[24])<<39 | 119 | uint64(x[25]&15)<<47 120 | 121 | r[4] = uint64(x[25])>>4 | 122 | uint64(x[26])<<4 | 123 | uint64(x[27])<<12 | 124 | uint64(x[28])<<20 | 125 | uint64(x[29])<<28 | 126 | uint64(x[30])<<36 | 127 | uint64(x[31]&127)<<44 128 | } 129 | 130 | // pack sets out = x where out is the usual, little-endian form of the 5, 131 | // 51-bit limbs in x. 132 | func pack(out *[32]byte, x *[5]uint64) { 133 | t := *x 134 | freeze(&t) 135 | 136 | out[0] = byte(t[0]) 137 | out[1] = byte(t[0] >> 8) 138 | out[2] = byte(t[0] >> 16) 139 | out[3] = byte(t[0] >> 24) 140 | out[4] = byte(t[0] >> 32) 141 | out[5] = byte(t[0] >> 40) 142 | out[6] = byte(t[0] >> 48) 143 | 144 | out[6] ^= byte(t[1]<<3) & 0xf8 145 | out[7] = byte(t[1] >> 5) 146 | out[8] = byte(t[1] >> 13) 147 | out[9] = byte(t[1] >> 21) 148 | out[10] = byte(t[1] >> 29) 149 | out[11] = byte(t[1] >> 37) 150 | out[12] = byte(t[1] >> 45) 151 | 152 | out[12] ^= byte(t[2]<<6) & 0xc0 153 | out[13] = byte(t[2] >> 2) 154 | out[14] = byte(t[2] >> 10) 155 | out[15] = byte(t[2] >> 18) 156 | out[16] = byte(t[2] >> 26) 157 | out[17] = byte(t[2] >> 34) 158 | out[18] = byte(t[2] >> 42) 159 | out[19] = byte(t[2] >> 50) 160 | 161 | out[19] ^= byte(t[3]<<1) & 0xfe 162 | out[20] = byte(t[3] >> 7) 163 | out[21] = byte(t[3] >> 15) 164 | out[22] = byte(t[3] >> 23) 165 | out[23] = byte(t[3] >> 31) 166 | out[24] = byte(t[3] >> 39) 167 | out[25] = byte(t[3] >> 47) 168 | 169 | out[25] ^= byte(t[4]<<4) & 0xf0 170 | out[26] = byte(t[4] >> 4) 171 | out[27] = byte(t[4] >> 12) 172 | out[28] = byte(t[4] >> 20) 173 | out[29] = byte(t[4] >> 28) 174 | out[30] = byte(t[4] >> 36) 175 | out[31] = byte(t[4] >> 44) 176 | } 177 | 178 | // invert calculates r = x^-1 mod p using Fermat's little theorem. 179 | func invert(r *[5]uint64, x *[5]uint64) { 180 | var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 181 | 182 | square(&z2, x) /* 2 */ 183 | square(&t, &z2) /* 4 */ 184 | square(&t, &t) /* 8 */ 185 | mul(&z9, &t, x) /* 9 */ 186 | mul(&z11, &z9, &z2) /* 11 */ 187 | square(&t, &z11) /* 22 */ 188 | mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ 189 | 190 | square(&t, &z2_5_0) /* 2^6 - 2^1 */ 191 | for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ 192 | square(&t, &t) 193 | } 194 | mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ 195 | 196 | square(&t, &z2_10_0) /* 2^11 - 2^1 */ 197 | for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ 198 | square(&t, &t) 199 | } 200 | mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ 201 | 202 | square(&t, &z2_20_0) /* 2^21 - 2^1 */ 203 | for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ 204 | square(&t, &t) 205 | } 206 | mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ 207 | 208 | square(&t, &t) /* 2^41 - 2^1 */ 209 | for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ 210 | square(&t, &t) 211 | } 212 | mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ 213 | 214 | square(&t, &z2_50_0) /* 2^51 - 2^1 */ 215 | for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ 216 | square(&t, &t) 217 | } 218 | mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ 219 | 220 | square(&t, &z2_100_0) /* 2^101 - 2^1 */ 221 | for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ 222 | square(&t, &t) 223 | } 224 | mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ 225 | 226 | square(&t, &t) /* 2^201 - 2^1 */ 227 | for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ 228 | square(&t, &t) 229 | } 230 | mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ 231 | 232 | square(&t, &t) /* 2^251 - 2^1 */ 233 | square(&t, &t) /* 2^252 - 2^2 */ 234 | square(&t, &t) /* 2^253 - 2^3 */ 235 | 236 | square(&t, &t) /* 2^254 - 2^4 */ 237 | 238 | square(&t, &t) /* 2^255 - 2^5 */ 239 | mul(r, &t, &z11) /* 2^255 - 21 */ 240 | } 241 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/curve25519/mul_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | #include "const_amd64.h" 11 | 12 | // func mul(dest, a, b *[5]uint64) 13 | TEXT ·mul(SB),0,$16-24 14 | MOVQ dest+0(FP), DI 15 | MOVQ a+8(FP), SI 16 | MOVQ b+16(FP), DX 17 | 18 | MOVQ DX,CX 19 | MOVQ 24(SI),DX 20 | IMUL3Q $19,DX,AX 21 | MOVQ AX,0(SP) 22 | MULQ 16(CX) 23 | MOVQ AX,R8 24 | MOVQ DX,R9 25 | MOVQ 32(SI),DX 26 | IMUL3Q $19,DX,AX 27 | MOVQ AX,8(SP) 28 | MULQ 8(CX) 29 | ADDQ AX,R8 30 | ADCQ DX,R9 31 | MOVQ 0(SI),AX 32 | MULQ 0(CX) 33 | ADDQ AX,R8 34 | ADCQ DX,R9 35 | MOVQ 0(SI),AX 36 | MULQ 8(CX) 37 | MOVQ AX,R10 38 | MOVQ DX,R11 39 | MOVQ 0(SI),AX 40 | MULQ 16(CX) 41 | MOVQ AX,R12 42 | MOVQ DX,R13 43 | MOVQ 0(SI),AX 44 | MULQ 24(CX) 45 | MOVQ AX,R14 46 | MOVQ DX,R15 47 | MOVQ 0(SI),AX 48 | MULQ 32(CX) 49 | MOVQ AX,BX 50 | MOVQ DX,BP 51 | MOVQ 8(SI),AX 52 | MULQ 0(CX) 53 | ADDQ AX,R10 54 | ADCQ DX,R11 55 | MOVQ 8(SI),AX 56 | MULQ 8(CX) 57 | ADDQ AX,R12 58 | ADCQ DX,R13 59 | MOVQ 8(SI),AX 60 | MULQ 16(CX) 61 | ADDQ AX,R14 62 | ADCQ DX,R15 63 | MOVQ 8(SI),AX 64 | MULQ 24(CX) 65 | ADDQ AX,BX 66 | ADCQ DX,BP 67 | MOVQ 8(SI),DX 68 | IMUL3Q $19,DX,AX 69 | MULQ 32(CX) 70 | ADDQ AX,R8 71 | ADCQ DX,R9 72 | MOVQ 16(SI),AX 73 | MULQ 0(CX) 74 | ADDQ AX,R12 75 | ADCQ DX,R13 76 | MOVQ 16(SI),AX 77 | MULQ 8(CX) 78 | ADDQ AX,R14 79 | ADCQ DX,R15 80 | MOVQ 16(SI),AX 81 | MULQ 16(CX) 82 | ADDQ AX,BX 83 | ADCQ DX,BP 84 | MOVQ 16(SI),DX 85 | IMUL3Q $19,DX,AX 86 | MULQ 24(CX) 87 | ADDQ AX,R8 88 | ADCQ DX,R9 89 | MOVQ 16(SI),DX 90 | IMUL3Q $19,DX,AX 91 | MULQ 32(CX) 92 | ADDQ AX,R10 93 | ADCQ DX,R11 94 | MOVQ 24(SI),AX 95 | MULQ 0(CX) 96 | ADDQ AX,R14 97 | ADCQ DX,R15 98 | MOVQ 24(SI),AX 99 | MULQ 8(CX) 100 | ADDQ AX,BX 101 | ADCQ DX,BP 102 | MOVQ 0(SP),AX 103 | MULQ 24(CX) 104 | ADDQ AX,R10 105 | ADCQ DX,R11 106 | MOVQ 0(SP),AX 107 | MULQ 32(CX) 108 | ADDQ AX,R12 109 | ADCQ DX,R13 110 | MOVQ 32(SI),AX 111 | MULQ 0(CX) 112 | ADDQ AX,BX 113 | ADCQ DX,BP 114 | MOVQ 8(SP),AX 115 | MULQ 16(CX) 116 | ADDQ AX,R10 117 | ADCQ DX,R11 118 | MOVQ 8(SP),AX 119 | MULQ 24(CX) 120 | ADDQ AX,R12 121 | ADCQ DX,R13 122 | MOVQ 8(SP),AX 123 | MULQ 32(CX) 124 | ADDQ AX,R14 125 | ADCQ DX,R15 126 | MOVQ $REDMASK51,SI 127 | SHLQ $13,R9:R8 128 | ANDQ SI,R8 129 | SHLQ $13,R11:R10 130 | ANDQ SI,R10 131 | ADDQ R9,R10 132 | SHLQ $13,R13:R12 133 | ANDQ SI,R12 134 | ADDQ R11,R12 135 | SHLQ $13,R15:R14 136 | ANDQ SI,R14 137 | ADDQ R13,R14 138 | SHLQ $13,BP:BX 139 | ANDQ SI,BX 140 | ADDQ R15,BX 141 | IMUL3Q $19,BP,DX 142 | ADDQ DX,R8 143 | MOVQ R8,DX 144 | SHRQ $51,DX 145 | ADDQ R10,DX 146 | MOVQ DX,CX 147 | SHRQ $51,DX 148 | ANDQ SI,R8 149 | ADDQ R12,DX 150 | MOVQ DX,R9 151 | SHRQ $51,DX 152 | ANDQ SI,CX 153 | ADDQ R14,DX 154 | MOVQ DX,AX 155 | SHRQ $51,DX 156 | ANDQ SI,R9 157 | ADDQ BX,DX 158 | MOVQ DX,R10 159 | SHRQ $51,DX 160 | ANDQ SI,AX 161 | IMUL3Q $19,DX,DX 162 | ADDQ DX,R8 163 | ANDQ SI,R10 164 | MOVQ R8,0(DI) 165 | MOVQ CX,8(DI) 166 | MOVQ R9,16(DI) 167 | MOVQ AX,24(DI) 168 | MOVQ R10,32(DI) 169 | RET 170 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/curve25519/square_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | #include "const_amd64.h" 11 | 12 | // func square(out, in *[5]uint64) 13 | TEXT ·square(SB),7,$0-16 14 | MOVQ out+0(FP), DI 15 | MOVQ in+8(FP), SI 16 | 17 | MOVQ 0(SI),AX 18 | MULQ 0(SI) 19 | MOVQ AX,CX 20 | MOVQ DX,R8 21 | MOVQ 0(SI),AX 22 | SHLQ $1,AX 23 | MULQ 8(SI) 24 | MOVQ AX,R9 25 | MOVQ DX,R10 26 | MOVQ 0(SI),AX 27 | SHLQ $1,AX 28 | MULQ 16(SI) 29 | MOVQ AX,R11 30 | MOVQ DX,R12 31 | MOVQ 0(SI),AX 32 | SHLQ $1,AX 33 | MULQ 24(SI) 34 | MOVQ AX,R13 35 | MOVQ DX,R14 36 | MOVQ 0(SI),AX 37 | SHLQ $1,AX 38 | MULQ 32(SI) 39 | MOVQ AX,R15 40 | MOVQ DX,BX 41 | MOVQ 8(SI),AX 42 | MULQ 8(SI) 43 | ADDQ AX,R11 44 | ADCQ DX,R12 45 | MOVQ 8(SI),AX 46 | SHLQ $1,AX 47 | MULQ 16(SI) 48 | ADDQ AX,R13 49 | ADCQ DX,R14 50 | MOVQ 8(SI),AX 51 | SHLQ $1,AX 52 | MULQ 24(SI) 53 | ADDQ AX,R15 54 | ADCQ DX,BX 55 | MOVQ 8(SI),DX 56 | IMUL3Q $38,DX,AX 57 | MULQ 32(SI) 58 | ADDQ AX,CX 59 | ADCQ DX,R8 60 | MOVQ 16(SI),AX 61 | MULQ 16(SI) 62 | ADDQ AX,R15 63 | ADCQ DX,BX 64 | MOVQ 16(SI),DX 65 | IMUL3Q $38,DX,AX 66 | MULQ 24(SI) 67 | ADDQ AX,CX 68 | ADCQ DX,R8 69 | MOVQ 16(SI),DX 70 | IMUL3Q $38,DX,AX 71 | MULQ 32(SI) 72 | ADDQ AX,R9 73 | ADCQ DX,R10 74 | MOVQ 24(SI),DX 75 | IMUL3Q $19,DX,AX 76 | MULQ 24(SI) 77 | ADDQ AX,R9 78 | ADCQ DX,R10 79 | MOVQ 24(SI),DX 80 | IMUL3Q $38,DX,AX 81 | MULQ 32(SI) 82 | ADDQ AX,R11 83 | ADCQ DX,R12 84 | MOVQ 32(SI),DX 85 | IMUL3Q $19,DX,AX 86 | MULQ 32(SI) 87 | ADDQ AX,R13 88 | ADCQ DX,R14 89 | MOVQ $REDMASK51,SI 90 | SHLQ $13,R8:CX 91 | ANDQ SI,CX 92 | SHLQ $13,R10:R9 93 | ANDQ SI,R9 94 | ADDQ R8,R9 95 | SHLQ $13,R12:R11 96 | ANDQ SI,R11 97 | ADDQ R10,R11 98 | SHLQ $13,R14:R13 99 | ANDQ SI,R13 100 | ADDQ R12,R13 101 | SHLQ $13,BX:R15 102 | ANDQ SI,R15 103 | ADDQ R14,R15 104 | IMUL3Q $19,BX,DX 105 | ADDQ DX,CX 106 | MOVQ CX,DX 107 | SHRQ $51,DX 108 | ADDQ R9,DX 109 | ANDQ SI,CX 110 | MOVQ DX,R8 111 | SHRQ $51,DX 112 | ADDQ R11,DX 113 | ANDQ SI,R8 114 | MOVQ DX,R9 115 | SHRQ $51,DX 116 | ADDQ R13,DX 117 | ANDQ SI,R9 118 | MOVQ DX,AX 119 | SHRQ $51,DX 120 | ADDQ R15,DX 121 | ANDQ SI,AX 122 | MOVQ DX,R10 123 | SHRQ $51,DX 124 | IMUL3Q $19,DX,DX 125 | ADDQ DX,CX 126 | ANDQ SI,R10 127 | MOVQ CX,0(DI) 128 | MOVQ R8,8(DI) 129 | MOVQ R9,16(DI) 130 | MOVQ AX,24(DI) 131 | MOVQ R10,32(DI) 132 | RET 133 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ed25519/ed25519.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package ed25519 implements the Ed25519 signature algorithm. See 6 | // https://ed25519.cr.yp.to/. 7 | // 8 | // These functions are also compatible with the “Ed25519” function defined in 9 | // RFC 8032. 10 | package ed25519 11 | 12 | // This code is a port of the public domain, “ref10” implementation of ed25519 13 | // from SUPERCOP. 14 | 15 | import ( 16 | "bytes" 17 | "crypto" 18 | cryptorand "crypto/rand" 19 | "crypto/sha512" 20 | "errors" 21 | "io" 22 | "strconv" 23 | 24 | "golang.org/x/crypto/ed25519/internal/edwards25519" 25 | ) 26 | 27 | const ( 28 | // PublicKeySize is the size, in bytes, of public keys as used in this package. 29 | PublicKeySize = 32 30 | // PrivateKeySize is the size, in bytes, of private keys as used in this package. 31 | PrivateKeySize = 64 32 | // SignatureSize is the size, in bytes, of signatures generated and verified by this package. 33 | SignatureSize = 64 34 | ) 35 | 36 | // PublicKey is the type of Ed25519 public keys. 37 | type PublicKey []byte 38 | 39 | // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. 40 | type PrivateKey []byte 41 | 42 | // Public returns the PublicKey corresponding to priv. 43 | func (priv PrivateKey) Public() crypto.PublicKey { 44 | publicKey := make([]byte, PublicKeySize) 45 | copy(publicKey, priv[32:]) 46 | return PublicKey(publicKey) 47 | } 48 | 49 | // Sign signs the given message with priv. 50 | // Ed25519 performs two passes over messages to be signed and therefore cannot 51 | // handle pre-hashed messages. Thus opts.HashFunc() must return zero to 52 | // indicate the message hasn't been hashed. This can be achieved by passing 53 | // crypto.Hash(0) as the value for opts. 54 | func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { 55 | if opts.HashFunc() != crypto.Hash(0) { 56 | return nil, errors.New("ed25519: cannot sign hashed message") 57 | } 58 | 59 | return Sign(priv, message), nil 60 | } 61 | 62 | // GenerateKey generates a public/private key pair using entropy from rand. 63 | // If rand is nil, crypto/rand.Reader will be used. 64 | func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) { 65 | if rand == nil { 66 | rand = cryptorand.Reader 67 | } 68 | 69 | privateKey = make([]byte, PrivateKeySize) 70 | publicKey = make([]byte, PublicKeySize) 71 | _, err = io.ReadFull(rand, privateKey[:32]) 72 | if err != nil { 73 | return nil, nil, err 74 | } 75 | 76 | digest := sha512.Sum512(privateKey[:32]) 77 | digest[0] &= 248 78 | digest[31] &= 127 79 | digest[31] |= 64 80 | 81 | var A edwards25519.ExtendedGroupElement 82 | var hBytes [32]byte 83 | copy(hBytes[:], digest[:]) 84 | edwards25519.GeScalarMultBase(&A, &hBytes) 85 | var publicKeyBytes [32]byte 86 | A.ToBytes(&publicKeyBytes) 87 | 88 | copy(privateKey[32:], publicKeyBytes[:]) 89 | copy(publicKey, publicKeyBytes[:]) 90 | 91 | return publicKey, privateKey, nil 92 | } 93 | 94 | // Sign signs the message with privateKey and returns a signature. It will 95 | // panic if len(privateKey) is not PrivateKeySize. 96 | func Sign(privateKey PrivateKey, message []byte) []byte { 97 | if l := len(privateKey); l != PrivateKeySize { 98 | panic("ed25519: bad private key length: " + strconv.Itoa(l)) 99 | } 100 | 101 | h := sha512.New() 102 | h.Write(privateKey[:32]) 103 | 104 | var digest1, messageDigest, hramDigest [64]byte 105 | var expandedSecretKey [32]byte 106 | h.Sum(digest1[:0]) 107 | copy(expandedSecretKey[:], digest1[:]) 108 | expandedSecretKey[0] &= 248 109 | expandedSecretKey[31] &= 63 110 | expandedSecretKey[31] |= 64 111 | 112 | h.Reset() 113 | h.Write(digest1[32:]) 114 | h.Write(message) 115 | h.Sum(messageDigest[:0]) 116 | 117 | var messageDigestReduced [32]byte 118 | edwards25519.ScReduce(&messageDigestReduced, &messageDigest) 119 | var R edwards25519.ExtendedGroupElement 120 | edwards25519.GeScalarMultBase(&R, &messageDigestReduced) 121 | 122 | var encodedR [32]byte 123 | R.ToBytes(&encodedR) 124 | 125 | h.Reset() 126 | h.Write(encodedR[:]) 127 | h.Write(privateKey[32:]) 128 | h.Write(message) 129 | h.Sum(hramDigest[:0]) 130 | var hramDigestReduced [32]byte 131 | edwards25519.ScReduce(&hramDigestReduced, &hramDigest) 132 | 133 | var s [32]byte 134 | edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) 135 | 136 | signature := make([]byte, SignatureSize) 137 | copy(signature[:], encodedR[:]) 138 | copy(signature[32:], s[:]) 139 | 140 | return signature 141 | } 142 | 143 | // Verify reports whether sig is a valid signature of message by publicKey. It 144 | // will panic if len(publicKey) is not PublicKeySize. 145 | func Verify(publicKey PublicKey, message, sig []byte) bool { 146 | if l := len(publicKey); l != PublicKeySize { 147 | panic("ed25519: bad public key length: " + strconv.Itoa(l)) 148 | } 149 | 150 | if len(sig) != SignatureSize || sig[63]&224 != 0 { 151 | return false 152 | } 153 | 154 | var A edwards25519.ExtendedGroupElement 155 | var publicKeyBytes [32]byte 156 | copy(publicKeyBytes[:], publicKey) 157 | if !A.FromBytes(&publicKeyBytes) { 158 | return false 159 | } 160 | edwards25519.FeNeg(&A.X, &A.X) 161 | edwards25519.FeNeg(&A.T, &A.T) 162 | 163 | h := sha512.New() 164 | h.Write(sig[:32]) 165 | h.Write(publicKey[:]) 166 | h.Write(message) 167 | var digest [64]byte 168 | h.Sum(digest[:0]) 169 | 170 | var hReduced [32]byte 171 | edwards25519.ScReduce(&hReduced, &digest) 172 | 173 | var R edwards25519.ProjectiveGroupElement 174 | var s [32]byte 175 | copy(s[:], sig[32:]) 176 | 177 | // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in 178 | // the range [0, order) in order to prevent signature malleability. 179 | if !edwards25519.ScMinimal(&s) { 180 | return false 181 | } 182 | 183 | edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s) 184 | 185 | var checkR [32]byte 186 | R.ToBytes(&checkR) 187 | return bytes.Equal(sig[:32], checkR[:]) 188 | } 189 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package ChaCha20 implements the core ChaCha20 function as specified in https://tools.ietf.org/html/rfc7539#section-2.3. 6 | package chacha20 7 | 8 | import "encoding/binary" 9 | 10 | const rounds = 20 11 | 12 | // core applies the ChaCha20 core function to 16-byte input in, 32-byte key k, 13 | // and 16-byte constant c, and puts the result into 64-byte array out. 14 | func core(out *[64]byte, in *[16]byte, k *[32]byte) { 15 | j0 := uint32(0x61707865) 16 | j1 := uint32(0x3320646e) 17 | j2 := uint32(0x79622d32) 18 | j3 := uint32(0x6b206574) 19 | j4 := binary.LittleEndian.Uint32(k[0:4]) 20 | j5 := binary.LittleEndian.Uint32(k[4:8]) 21 | j6 := binary.LittleEndian.Uint32(k[8:12]) 22 | j7 := binary.LittleEndian.Uint32(k[12:16]) 23 | j8 := binary.LittleEndian.Uint32(k[16:20]) 24 | j9 := binary.LittleEndian.Uint32(k[20:24]) 25 | j10 := binary.LittleEndian.Uint32(k[24:28]) 26 | j11 := binary.LittleEndian.Uint32(k[28:32]) 27 | j12 := binary.LittleEndian.Uint32(in[0:4]) 28 | j13 := binary.LittleEndian.Uint32(in[4:8]) 29 | j14 := binary.LittleEndian.Uint32(in[8:12]) 30 | j15 := binary.LittleEndian.Uint32(in[12:16]) 31 | 32 | x0, x1, x2, x3, x4, x5, x6, x7 := j0, j1, j2, j3, j4, j5, j6, j7 33 | x8, x9, x10, x11, x12, x13, x14, x15 := j8, j9, j10, j11, j12, j13, j14, j15 34 | 35 | for i := 0; i < rounds; i += 2 { 36 | x0 += x4 37 | x12 ^= x0 38 | x12 = (x12 << 16) | (x12 >> (16)) 39 | x8 += x12 40 | x4 ^= x8 41 | x4 = (x4 << 12) | (x4 >> (20)) 42 | x0 += x4 43 | x12 ^= x0 44 | x12 = (x12 << 8) | (x12 >> (24)) 45 | x8 += x12 46 | x4 ^= x8 47 | x4 = (x4 << 7) | (x4 >> (25)) 48 | x1 += x5 49 | x13 ^= x1 50 | x13 = (x13 << 16) | (x13 >> 16) 51 | x9 += x13 52 | x5 ^= x9 53 | x5 = (x5 << 12) | (x5 >> 20) 54 | x1 += x5 55 | x13 ^= x1 56 | x13 = (x13 << 8) | (x13 >> 24) 57 | x9 += x13 58 | x5 ^= x9 59 | x5 = (x5 << 7) | (x5 >> 25) 60 | x2 += x6 61 | x14 ^= x2 62 | x14 = (x14 << 16) | (x14 >> 16) 63 | x10 += x14 64 | x6 ^= x10 65 | x6 = (x6 << 12) | (x6 >> 20) 66 | x2 += x6 67 | x14 ^= x2 68 | x14 = (x14 << 8) | (x14 >> 24) 69 | x10 += x14 70 | x6 ^= x10 71 | x6 = (x6 << 7) | (x6 >> 25) 72 | x3 += x7 73 | x15 ^= x3 74 | x15 = (x15 << 16) | (x15 >> 16) 75 | x11 += x15 76 | x7 ^= x11 77 | x7 = (x7 << 12) | (x7 >> 20) 78 | x3 += x7 79 | x15 ^= x3 80 | x15 = (x15 << 8) | (x15 >> 24) 81 | x11 += x15 82 | x7 ^= x11 83 | x7 = (x7 << 7) | (x7 >> 25) 84 | x0 += x5 85 | x15 ^= x0 86 | x15 = (x15 << 16) | (x15 >> 16) 87 | x10 += x15 88 | x5 ^= x10 89 | x5 = (x5 << 12) | (x5 >> 20) 90 | x0 += x5 91 | x15 ^= x0 92 | x15 = (x15 << 8) | (x15 >> 24) 93 | x10 += x15 94 | x5 ^= x10 95 | x5 = (x5 << 7) | (x5 >> 25) 96 | x1 += x6 97 | x12 ^= x1 98 | x12 = (x12 << 16) | (x12 >> 16) 99 | x11 += x12 100 | x6 ^= x11 101 | x6 = (x6 << 12) | (x6 >> 20) 102 | x1 += x6 103 | x12 ^= x1 104 | x12 = (x12 << 8) | (x12 >> 24) 105 | x11 += x12 106 | x6 ^= x11 107 | x6 = (x6 << 7) | (x6 >> 25) 108 | x2 += x7 109 | x13 ^= x2 110 | x13 = (x13 << 16) | (x13 >> 16) 111 | x8 += x13 112 | x7 ^= x8 113 | x7 = (x7 << 12) | (x7 >> 20) 114 | x2 += x7 115 | x13 ^= x2 116 | x13 = (x13 << 8) | (x13 >> 24) 117 | x8 += x13 118 | x7 ^= x8 119 | x7 = (x7 << 7) | (x7 >> 25) 120 | x3 += x4 121 | x14 ^= x3 122 | x14 = (x14 << 16) | (x14 >> 16) 123 | x9 += x14 124 | x4 ^= x9 125 | x4 = (x4 << 12) | (x4 >> 20) 126 | x3 += x4 127 | x14 ^= x3 128 | x14 = (x14 << 8) | (x14 >> 24) 129 | x9 += x14 130 | x4 ^= x9 131 | x4 = (x4 << 7) | (x4 >> 25) 132 | } 133 | 134 | x0 += j0 135 | x1 += j1 136 | x2 += j2 137 | x3 += j3 138 | x4 += j4 139 | x5 += j5 140 | x6 += j6 141 | x7 += j7 142 | x8 += j8 143 | x9 += j9 144 | x10 += j10 145 | x11 += j11 146 | x12 += j12 147 | x13 += j13 148 | x14 += j14 149 | x15 += j15 150 | 151 | binary.LittleEndian.PutUint32(out[0:4], x0) 152 | binary.LittleEndian.PutUint32(out[4:8], x1) 153 | binary.LittleEndian.PutUint32(out[8:12], x2) 154 | binary.LittleEndian.PutUint32(out[12:16], x3) 155 | binary.LittleEndian.PutUint32(out[16:20], x4) 156 | binary.LittleEndian.PutUint32(out[20:24], x5) 157 | binary.LittleEndian.PutUint32(out[24:28], x6) 158 | binary.LittleEndian.PutUint32(out[28:32], x7) 159 | binary.LittleEndian.PutUint32(out[32:36], x8) 160 | binary.LittleEndian.PutUint32(out[36:40], x9) 161 | binary.LittleEndian.PutUint32(out[40:44], x10) 162 | binary.LittleEndian.PutUint32(out[44:48], x11) 163 | binary.LittleEndian.PutUint32(out[48:52], x12) 164 | binary.LittleEndian.PutUint32(out[52:56], x13) 165 | binary.LittleEndian.PutUint32(out[56:60], x14) 166 | binary.LittleEndian.PutUint32(out[60:64], x15) 167 | } 168 | 169 | // XORKeyStream crypts bytes from in to out using the given key and counters. 170 | // In and out must overlap entirely or not at all. Counter contains the raw 171 | // ChaCha20 counter bytes (i.e. block counter followed by nonce). 172 | func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { 173 | var block [64]byte 174 | var counterCopy [16]byte 175 | copy(counterCopy[:], counter[:]) 176 | 177 | for len(in) >= 64 { 178 | core(&block, &counterCopy, key) 179 | for i, x := range block { 180 | out[i] = in[i] ^ x 181 | } 182 | u := uint32(1) 183 | for i := 0; i < 4; i++ { 184 | u += uint32(counterCopy[i]) 185 | counterCopy[i] = byte(u) 186 | u >>= 8 187 | } 188 | in = in[64:] 189 | out = out[64:] 190 | } 191 | 192 | if len(in) > 0 { 193 | core(&block, &counterCopy, key) 194 | for i, v := range in { 195 | out[i] = v ^ block[i] 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/poly1305/poly1305.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package poly1305 implements Poly1305 one-time message authentication code as 7 | specified in https://cr.yp.to/mac/poly1305-20050329.pdf. 8 | 9 | Poly1305 is a fast, one-time authentication function. It is infeasible for an 10 | attacker to generate an authenticator for a message without the key. However, a 11 | key must only be used for a single message. Authenticating two different 12 | messages with the same key allows an attacker to forge authenticators for other 13 | messages with the same key. 14 | 15 | Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was 16 | used with a fixed key in order to generate one-time keys from an nonce. 17 | However, in this package AES isn't used and the one-time key is specified 18 | directly. 19 | */ 20 | package poly1305 // import "golang.org/x/crypto/poly1305" 21 | 22 | import "crypto/subtle" 23 | 24 | // TagSize is the size, in bytes, of a poly1305 authenticator. 25 | const TagSize = 16 26 | 27 | // Verify returns true if mac is a valid authenticator for m with the given 28 | // key. 29 | func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { 30 | var tmp [16]byte 31 | Sum(&tmp, m, key) 32 | return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 33 | } 34 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/poly1305/sum_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64,!gccgo,!appengine 6 | 7 | package poly1305 8 | 9 | // This function is implemented in sum_amd64.s 10 | //go:noescape 11 | func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte) 12 | 13 | // Sum generates an authenticator for m using a one-time key and puts the 14 | // 16-byte result into out. Authenticating two different messages with the same 15 | // key allows an attacker to forge messages at will. 16 | func Sum(out *[16]byte, m []byte, key *[32]byte) { 17 | var mPtr *byte 18 | if len(m) > 0 { 19 | mPtr = &m[0] 20 | } 21 | poly1305(out, mPtr, uint64(len(m)), key) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/poly1305/sum_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64,!gccgo,!appengine 6 | 7 | #include "textflag.h" 8 | 9 | #define POLY1305_ADD(msg, h0, h1, h2) \ 10 | ADDQ 0(msg), h0; \ 11 | ADCQ 8(msg), h1; \ 12 | ADCQ $1, h2; \ 13 | LEAQ 16(msg), msg 14 | 15 | #define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \ 16 | MOVQ r0, AX; \ 17 | MULQ h0; \ 18 | MOVQ AX, t0; \ 19 | MOVQ DX, t1; \ 20 | MOVQ r0, AX; \ 21 | MULQ h1; \ 22 | ADDQ AX, t1; \ 23 | ADCQ $0, DX; \ 24 | MOVQ r0, t2; \ 25 | IMULQ h2, t2; \ 26 | ADDQ DX, t2; \ 27 | \ 28 | MOVQ r1, AX; \ 29 | MULQ h0; \ 30 | ADDQ AX, t1; \ 31 | ADCQ $0, DX; \ 32 | MOVQ DX, h0; \ 33 | MOVQ r1, t3; \ 34 | IMULQ h2, t3; \ 35 | MOVQ r1, AX; \ 36 | MULQ h1; \ 37 | ADDQ AX, t2; \ 38 | ADCQ DX, t3; \ 39 | ADDQ h0, t2; \ 40 | ADCQ $0, t3; \ 41 | \ 42 | MOVQ t0, h0; \ 43 | MOVQ t1, h1; \ 44 | MOVQ t2, h2; \ 45 | ANDQ $3, h2; \ 46 | MOVQ t2, t0; \ 47 | ANDQ $0xFFFFFFFFFFFFFFFC, t0; \ 48 | ADDQ t0, h0; \ 49 | ADCQ t3, h1; \ 50 | ADCQ $0, h2; \ 51 | SHRQ $2, t3, t2; \ 52 | SHRQ $2, t3; \ 53 | ADDQ t2, h0; \ 54 | ADCQ t3, h1; \ 55 | ADCQ $0, h2 56 | 57 | DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF 58 | DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC 59 | GLOBL ·poly1305Mask<>(SB), RODATA, $16 60 | 61 | // func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key) 62 | TEXT ·poly1305(SB), $0-32 63 | MOVQ out+0(FP), DI 64 | MOVQ m+8(FP), SI 65 | MOVQ mlen+16(FP), R15 66 | MOVQ key+24(FP), AX 67 | 68 | MOVQ 0(AX), R11 69 | MOVQ 8(AX), R12 70 | ANDQ ·poly1305Mask<>(SB), R11 // r0 71 | ANDQ ·poly1305Mask<>+8(SB), R12 // r1 72 | XORQ R8, R8 // h0 73 | XORQ R9, R9 // h1 74 | XORQ R10, R10 // h2 75 | 76 | CMPQ R15, $16 77 | JB bytes_between_0_and_15 78 | 79 | loop: 80 | POLY1305_ADD(SI, R8, R9, R10) 81 | 82 | multiply: 83 | POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14) 84 | SUBQ $16, R15 85 | CMPQ R15, $16 86 | JAE loop 87 | 88 | bytes_between_0_and_15: 89 | TESTQ R15, R15 90 | JZ done 91 | MOVQ $1, BX 92 | XORQ CX, CX 93 | XORQ R13, R13 94 | ADDQ R15, SI 95 | 96 | flush_buffer: 97 | SHLQ $8, BX, CX 98 | SHLQ $8, BX 99 | MOVB -1(SI), R13 100 | XORQ R13, BX 101 | DECQ SI 102 | DECQ R15 103 | JNZ flush_buffer 104 | 105 | ADDQ BX, R8 106 | ADCQ CX, R9 107 | ADCQ $0, R10 108 | MOVQ $16, R15 109 | JMP multiply 110 | 111 | done: 112 | MOVQ R8, AX 113 | MOVQ R9, BX 114 | SUBQ $0xFFFFFFFFFFFFFFFB, AX 115 | SBBQ $0xFFFFFFFFFFFFFFFF, BX 116 | SBBQ $3, R10 117 | CMOVQCS R8, AX 118 | CMOVQCS R9, BX 119 | MOVQ key+24(FP), R8 120 | ADDQ 16(R8), AX 121 | ADCQ 24(R8), BX 122 | 123 | MOVQ AX, 0(DI) 124 | MOVQ BX, 8(DI) 125 | RET 126 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/poly1305/sum_arm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build arm,!gccgo,!appengine,!nacl 6 | 7 | package poly1305 8 | 9 | // This function is implemented in sum_arm.s 10 | //go:noescape 11 | func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte) 12 | 13 | // Sum generates an authenticator for m using a one-time key and puts the 14 | // 16-byte result into out. Authenticating two different messages with the same 15 | // key allows an attacker to forge messages at will. 16 | func Sum(out *[16]byte, m []byte, key *[32]byte) { 17 | var mPtr *byte 18 | if len(m) > 0 { 19 | mPtr = &m[0] 20 | } 21 | poly1305_auth_armv6(out, mPtr, uint32(len(m)), key) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/poly1305/sum_arm.s: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build arm,!gccgo,!appengine,!nacl 6 | 7 | #include "textflag.h" 8 | 9 | // This code was translated into a form compatible with 5a from the public 10 | // domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305. 11 | 12 | DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff 13 | DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03 14 | DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff 15 | DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff 16 | DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff 17 | GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20 18 | 19 | // Warning: the linker may use R11 to synthesize certain instructions. Please 20 | // take care and verify that no synthetic instructions use it. 21 | 22 | TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0 23 | // Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It 24 | // might look like it's only 60 bytes of space but the final four bytes 25 | // will be written by another function.) We need to skip over four 26 | // bytes of stack because that's saving the value of 'g'. 27 | ADD $4, R13, R8 28 | MOVM.IB [R4-R7], (R8) 29 | MOVM.IA.W (R1), [R2-R5] 30 | MOVW $·poly1305_init_constants_armv6<>(SB), R7 31 | MOVW R2, R8 32 | MOVW R2>>26, R9 33 | MOVW R3>>20, g 34 | MOVW R4>>14, R11 35 | MOVW R5>>8, R12 36 | ORR R3<<6, R9, R9 37 | ORR R4<<12, g, g 38 | ORR R5<<18, R11, R11 39 | MOVM.IA (R7), [R2-R6] 40 | AND R8, R2, R2 41 | AND R9, R3, R3 42 | AND g, R4, R4 43 | AND R11, R5, R5 44 | AND R12, R6, R6 45 | MOVM.IA.W [R2-R6], (R0) 46 | EOR R2, R2, R2 47 | EOR R3, R3, R3 48 | EOR R4, R4, R4 49 | EOR R5, R5, R5 50 | EOR R6, R6, R6 51 | MOVM.IA.W [R2-R6], (R0) 52 | MOVM.IA.W (R1), [R2-R5] 53 | MOVM.IA [R2-R6], (R0) 54 | ADD $20, R13, R0 55 | MOVM.DA (R0), [R4-R7] 56 | RET 57 | 58 | #define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \ 59 | MOVBU (offset+0)(Rsrc), Rtmp; \ 60 | MOVBU Rtmp, (offset+0)(Rdst); \ 61 | MOVBU (offset+1)(Rsrc), Rtmp; \ 62 | MOVBU Rtmp, (offset+1)(Rdst); \ 63 | MOVBU (offset+2)(Rsrc), Rtmp; \ 64 | MOVBU Rtmp, (offset+2)(Rdst); \ 65 | MOVBU (offset+3)(Rsrc), Rtmp; \ 66 | MOVBU Rtmp, (offset+3)(Rdst) 67 | 68 | TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0 69 | // Needs 24 bytes of stack for saved registers and then 88 bytes of 70 | // scratch space after that. We assume that 24 bytes at (R13) have 71 | // already been used: four bytes for the link register saved in the 72 | // prelude of poly1305_auth_armv6, four bytes for saving the value of g 73 | // in that function and 16 bytes of scratch space used around 74 | // poly1305_finish_ext_armv6_skip1. 75 | ADD $24, R13, R12 76 | MOVM.IB [R4-R8, R14], (R12) 77 | MOVW R0, 88(R13) 78 | MOVW R1, 92(R13) 79 | MOVW R2, 96(R13) 80 | MOVW R1, R14 81 | MOVW R2, R12 82 | MOVW 56(R0), R8 83 | WORD $0xe1180008 // TST R8, R8 not working see issue 5921 84 | EOR R6, R6, R6 85 | MOVW.EQ $(1<<24), R6 86 | MOVW R6, 84(R13) 87 | ADD $116, R13, g 88 | MOVM.IA (R0), [R0-R9] 89 | MOVM.IA [R0-R4], (g) 90 | CMP $16, R12 91 | BLO poly1305_blocks_armv6_done 92 | 93 | poly1305_blocks_armv6_mainloop: 94 | WORD $0xe31e0003 // TST R14, #3 not working see issue 5921 95 | BEQ poly1305_blocks_armv6_mainloop_aligned 96 | ADD $100, R13, g 97 | MOVW_UNALIGNED(R14, g, R0, 0) 98 | MOVW_UNALIGNED(R14, g, R0, 4) 99 | MOVW_UNALIGNED(R14, g, R0, 8) 100 | MOVW_UNALIGNED(R14, g, R0, 12) 101 | MOVM.IA (g), [R0-R3] 102 | ADD $16, R14 103 | B poly1305_blocks_armv6_mainloop_loaded 104 | 105 | poly1305_blocks_armv6_mainloop_aligned: 106 | MOVM.IA.W (R14), [R0-R3] 107 | 108 | poly1305_blocks_armv6_mainloop_loaded: 109 | MOVW R0>>26, g 110 | MOVW R1>>20, R11 111 | MOVW R2>>14, R12 112 | MOVW R14, 92(R13) 113 | MOVW R3>>8, R4 114 | ORR R1<<6, g, g 115 | ORR R2<<12, R11, R11 116 | ORR R3<<18, R12, R12 117 | BIC $0xfc000000, R0, R0 118 | BIC $0xfc000000, g, g 119 | MOVW 84(R13), R3 120 | BIC $0xfc000000, R11, R11 121 | BIC $0xfc000000, R12, R12 122 | ADD R0, R5, R5 123 | ADD g, R6, R6 124 | ORR R3, R4, R4 125 | ADD R11, R7, R7 126 | ADD $116, R13, R14 127 | ADD R12, R8, R8 128 | ADD R4, R9, R9 129 | MOVM.IA (R14), [R0-R4] 130 | MULLU R4, R5, (R11, g) 131 | MULLU R3, R5, (R14, R12) 132 | MULALU R3, R6, (R11, g) 133 | MULALU R2, R6, (R14, R12) 134 | MULALU R2, R7, (R11, g) 135 | MULALU R1, R7, (R14, R12) 136 | ADD R4<<2, R4, R4 137 | ADD R3<<2, R3, R3 138 | MULALU R1, R8, (R11, g) 139 | MULALU R0, R8, (R14, R12) 140 | MULALU R0, R9, (R11, g) 141 | MULALU R4, R9, (R14, R12) 142 | MOVW g, 76(R13) 143 | MOVW R11, 80(R13) 144 | MOVW R12, 68(R13) 145 | MOVW R14, 72(R13) 146 | MULLU R2, R5, (R11, g) 147 | MULLU R1, R5, (R14, R12) 148 | MULALU R1, R6, (R11, g) 149 | MULALU R0, R6, (R14, R12) 150 | MULALU R0, R7, (R11, g) 151 | MULALU R4, R7, (R14, R12) 152 | ADD R2<<2, R2, R2 153 | ADD R1<<2, R1, R1 154 | MULALU R4, R8, (R11, g) 155 | MULALU R3, R8, (R14, R12) 156 | MULALU R3, R9, (R11, g) 157 | MULALU R2, R9, (R14, R12) 158 | MOVW g, 60(R13) 159 | MOVW R11, 64(R13) 160 | MOVW R12, 52(R13) 161 | MOVW R14, 56(R13) 162 | MULLU R0, R5, (R11, g) 163 | MULALU R4, R6, (R11, g) 164 | MULALU R3, R7, (R11, g) 165 | MULALU R2, R8, (R11, g) 166 | MULALU R1, R9, (R11, g) 167 | ADD $52, R13, R0 168 | MOVM.IA (R0), [R0-R7] 169 | MOVW g>>26, R12 170 | MOVW R4>>26, R14 171 | ORR R11<<6, R12, R12 172 | ORR R5<<6, R14, R14 173 | BIC $0xfc000000, g, g 174 | BIC $0xfc000000, R4, R4 175 | ADD.S R12, R0, R0 176 | ADC $0, R1, R1 177 | ADD.S R14, R6, R6 178 | ADC $0, R7, R7 179 | MOVW R0>>26, R12 180 | MOVW R6>>26, R14 181 | ORR R1<<6, R12, R12 182 | ORR R7<<6, R14, R14 183 | BIC $0xfc000000, R0, R0 184 | BIC $0xfc000000, R6, R6 185 | ADD R14<<2, R14, R14 186 | ADD.S R12, R2, R2 187 | ADC $0, R3, R3 188 | ADD R14, g, g 189 | MOVW R2>>26, R12 190 | MOVW g>>26, R14 191 | ORR R3<<6, R12, R12 192 | BIC $0xfc000000, g, R5 193 | BIC $0xfc000000, R2, R7 194 | ADD R12, R4, R4 195 | ADD R14, R0, R0 196 | MOVW R4>>26, R12 197 | BIC $0xfc000000, R4, R8 198 | ADD R12, R6, R9 199 | MOVW 96(R13), R12 200 | MOVW 92(R13), R14 201 | MOVW R0, R6 202 | CMP $32, R12 203 | SUB $16, R12, R12 204 | MOVW R12, 96(R13) 205 | BHS poly1305_blocks_armv6_mainloop 206 | 207 | poly1305_blocks_armv6_done: 208 | MOVW 88(R13), R12 209 | MOVW R5, 20(R12) 210 | MOVW R6, 24(R12) 211 | MOVW R7, 28(R12) 212 | MOVW R8, 32(R12) 213 | MOVW R9, 36(R12) 214 | ADD $48, R13, R0 215 | MOVM.DA (R0), [R4-R8, R14] 216 | RET 217 | 218 | #define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \ 219 | MOVBU.P 1(Rsrc), Rtmp; \ 220 | MOVBU.P Rtmp, 1(Rdst); \ 221 | MOVBU.P 1(Rsrc), Rtmp; \ 222 | MOVBU.P Rtmp, 1(Rdst) 223 | 224 | #define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \ 225 | MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \ 226 | MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) 227 | 228 | // func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key) 229 | TEXT ·poly1305_auth_armv6(SB), $196-16 230 | // The value 196, just above, is the sum of 64 (the size of the context 231 | // structure) and 132 (the amount of stack needed). 232 | // 233 | // At this point, the stack pointer (R13) has been moved down. It 234 | // points to the saved link register and there's 196 bytes of free 235 | // space above it. 236 | // 237 | // The stack for this function looks like: 238 | // 239 | // +--------------------- 240 | // | 241 | // | 64 bytes of context structure 242 | // | 243 | // +--------------------- 244 | // | 245 | // | 112 bytes for poly1305_blocks_armv6 246 | // | 247 | // +--------------------- 248 | // | 16 bytes of final block, constructed at 249 | // | poly1305_finish_ext_armv6_skip8 250 | // +--------------------- 251 | // | four bytes of saved 'g' 252 | // +--------------------- 253 | // | lr, saved by prelude <- R13 points here 254 | // +--------------------- 255 | MOVW g, 4(R13) 256 | 257 | MOVW out+0(FP), R4 258 | MOVW m+4(FP), R5 259 | MOVW mlen+8(FP), R6 260 | MOVW key+12(FP), R7 261 | 262 | ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112 263 | MOVW R7, R1 264 | 265 | // poly1305_init_ext_armv6 will write to the stack from R13+4, but 266 | // that's ok because none of the other values have been written yet. 267 | BL poly1305_init_ext_armv6<>(SB) 268 | BIC.S $15, R6, R2 269 | BEQ poly1305_auth_armv6_noblocks 270 | ADD $136, R13, R0 271 | MOVW R5, R1 272 | ADD R2, R5, R5 273 | SUB R2, R6, R6 274 | BL poly1305_blocks_armv6<>(SB) 275 | 276 | poly1305_auth_armv6_noblocks: 277 | ADD $136, R13, R0 278 | MOVW R5, R1 279 | MOVW R6, R2 280 | MOVW R4, R3 281 | 282 | MOVW R0, R5 283 | MOVW R1, R6 284 | MOVW R2, R7 285 | MOVW R3, R8 286 | AND.S R2, R2, R2 287 | BEQ poly1305_finish_ext_armv6_noremaining 288 | EOR R0, R0 289 | ADD $8, R13, R9 // 8 = offset to 16 byte scratch space 290 | MOVW R0, (R9) 291 | MOVW R0, 4(R9) 292 | MOVW R0, 8(R9) 293 | MOVW R0, 12(R9) 294 | WORD $0xe3110003 // TST R1, #3 not working see issue 5921 295 | BEQ poly1305_finish_ext_armv6_aligned 296 | WORD $0xe3120008 // TST R2, #8 not working see issue 5921 297 | BEQ poly1305_finish_ext_armv6_skip8 298 | MOVWP_UNALIGNED(R1, R9, g) 299 | MOVWP_UNALIGNED(R1, R9, g) 300 | 301 | poly1305_finish_ext_armv6_skip8: 302 | WORD $0xe3120004 // TST $4, R2 not working see issue 5921 303 | BEQ poly1305_finish_ext_armv6_skip4 304 | MOVWP_UNALIGNED(R1, R9, g) 305 | 306 | poly1305_finish_ext_armv6_skip4: 307 | WORD $0xe3120002 // TST $2, R2 not working see issue 5921 308 | BEQ poly1305_finish_ext_armv6_skip2 309 | MOVHUP_UNALIGNED(R1, R9, g) 310 | B poly1305_finish_ext_armv6_skip2 311 | 312 | poly1305_finish_ext_armv6_aligned: 313 | WORD $0xe3120008 // TST R2, #8 not working see issue 5921 314 | BEQ poly1305_finish_ext_armv6_skip8_aligned 315 | MOVM.IA.W (R1), [g-R11] 316 | MOVM.IA.W [g-R11], (R9) 317 | 318 | poly1305_finish_ext_armv6_skip8_aligned: 319 | WORD $0xe3120004 // TST $4, R2 not working see issue 5921 320 | BEQ poly1305_finish_ext_armv6_skip4_aligned 321 | MOVW.P 4(R1), g 322 | MOVW.P g, 4(R9) 323 | 324 | poly1305_finish_ext_armv6_skip4_aligned: 325 | WORD $0xe3120002 // TST $2, R2 not working see issue 5921 326 | BEQ poly1305_finish_ext_armv6_skip2 327 | MOVHU.P 2(R1), g 328 | MOVH.P g, 2(R9) 329 | 330 | poly1305_finish_ext_armv6_skip2: 331 | WORD $0xe3120001 // TST $1, R2 not working see issue 5921 332 | BEQ poly1305_finish_ext_armv6_skip1 333 | MOVBU.P 1(R1), g 334 | MOVBU.P g, 1(R9) 335 | 336 | poly1305_finish_ext_armv6_skip1: 337 | MOVW $1, R11 338 | MOVBU R11, 0(R9) 339 | MOVW R11, 56(R5) 340 | MOVW R5, R0 341 | ADD $8, R13, R1 342 | MOVW $16, R2 343 | BL poly1305_blocks_armv6<>(SB) 344 | 345 | poly1305_finish_ext_armv6_noremaining: 346 | MOVW 20(R5), R0 347 | MOVW 24(R5), R1 348 | MOVW 28(R5), R2 349 | MOVW 32(R5), R3 350 | MOVW 36(R5), R4 351 | MOVW R4>>26, R12 352 | BIC $0xfc000000, R4, R4 353 | ADD R12<<2, R12, R12 354 | ADD R12, R0, R0 355 | MOVW R0>>26, R12 356 | BIC $0xfc000000, R0, R0 357 | ADD R12, R1, R1 358 | MOVW R1>>26, R12 359 | BIC $0xfc000000, R1, R1 360 | ADD R12, R2, R2 361 | MOVW R2>>26, R12 362 | BIC $0xfc000000, R2, R2 363 | ADD R12, R3, R3 364 | MOVW R3>>26, R12 365 | BIC $0xfc000000, R3, R3 366 | ADD R12, R4, R4 367 | ADD $5, R0, R6 368 | MOVW R6>>26, R12 369 | BIC $0xfc000000, R6, R6 370 | ADD R12, R1, R7 371 | MOVW R7>>26, R12 372 | BIC $0xfc000000, R7, R7 373 | ADD R12, R2, g 374 | MOVW g>>26, R12 375 | BIC $0xfc000000, g, g 376 | ADD R12, R3, R11 377 | MOVW $-(1<<26), R12 378 | ADD R11>>26, R12, R12 379 | BIC $0xfc000000, R11, R11 380 | ADD R12, R4, R9 381 | MOVW R9>>31, R12 382 | SUB $1, R12 383 | AND R12, R6, R6 384 | AND R12, R7, R7 385 | AND R12, g, g 386 | AND R12, R11, R11 387 | AND R12, R9, R9 388 | MVN R12, R12 389 | AND R12, R0, R0 390 | AND R12, R1, R1 391 | AND R12, R2, R2 392 | AND R12, R3, R3 393 | AND R12, R4, R4 394 | ORR R6, R0, R0 395 | ORR R7, R1, R1 396 | ORR g, R2, R2 397 | ORR R11, R3, R3 398 | ORR R9, R4, R4 399 | ORR R1<<26, R0, R0 400 | MOVW R1>>6, R1 401 | ORR R2<<20, R1, R1 402 | MOVW R2>>12, R2 403 | ORR R3<<14, R2, R2 404 | MOVW R3>>18, R3 405 | ORR R4<<8, R3, R3 406 | MOVW 40(R5), R6 407 | MOVW 44(R5), R7 408 | MOVW 48(R5), g 409 | MOVW 52(R5), R11 410 | ADD.S R6, R0, R0 411 | ADC.S R7, R1, R1 412 | ADC.S g, R2, R2 413 | ADC.S R11, R3, R3 414 | MOVM.IA [R0-R3], (R8) 415 | MOVW R5, R12 416 | EOR R0, R0, R0 417 | EOR R1, R1, R1 418 | EOR R2, R2, R2 419 | EOR R3, R3, R3 420 | EOR R4, R4, R4 421 | EOR R5, R5, R5 422 | EOR R6, R6, R6 423 | EOR R7, R7, R7 424 | MOVM.IA.W [R0-R7], (R12) 425 | MOVM.IA [R0-R7], (R12) 426 | MOVW 4(R13), g 427 | RET 428 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/poly1305/sum_ref.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !amd64,!arm gccgo appengine nacl 6 | 7 | package poly1305 8 | 9 | import "encoding/binary" 10 | 11 | // Sum generates an authenticator for msg using a one-time key and puts the 12 | // 16-byte result into out. Authenticating two different messages with the same 13 | // key allows an attacker to forge messages at will. 14 | func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) { 15 | var ( 16 | h0, h1, h2, h3, h4 uint32 // the hash accumulators 17 | r0, r1, r2, r3, r4 uint64 // the r part of the key 18 | ) 19 | 20 | r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff) 21 | r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03) 22 | r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff) 23 | r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff) 24 | r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff) 25 | 26 | R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5 27 | 28 | for len(msg) >= TagSize { 29 | // h += msg 30 | h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff 31 | h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff 32 | h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff 33 | h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff 34 | h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24) 35 | 36 | // h *= r 37 | d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1) 38 | d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2) 39 | d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3) 40 | d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4) 41 | d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0) 42 | 43 | // h %= p 44 | h0 = uint32(d0) & 0x3ffffff 45 | h1 = uint32(d1) & 0x3ffffff 46 | h2 = uint32(d2) & 0x3ffffff 47 | h3 = uint32(d3) & 0x3ffffff 48 | h4 = uint32(d4) & 0x3ffffff 49 | 50 | h0 += uint32(d4>>26) * 5 51 | h1 += h0 >> 26 52 | h0 = h0 & 0x3ffffff 53 | 54 | msg = msg[TagSize:] 55 | } 56 | 57 | if len(msg) > 0 { 58 | var block [TagSize]byte 59 | off := copy(block[:], msg) 60 | block[off] = 0x01 61 | 62 | // h += msg 63 | h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff 64 | h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff 65 | h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff 66 | h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff 67 | h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8) 68 | 69 | // h *= r 70 | d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1) 71 | d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2) 72 | d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3) 73 | d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4) 74 | d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0) 75 | 76 | // h %= p 77 | h0 = uint32(d0) & 0x3ffffff 78 | h1 = uint32(d1) & 0x3ffffff 79 | h2 = uint32(d2) & 0x3ffffff 80 | h3 = uint32(d3) & 0x3ffffff 81 | h4 = uint32(d4) & 0x3ffffff 82 | 83 | h0 += uint32(d4>>26) * 5 84 | h1 += h0 >> 26 85 | h0 = h0 & 0x3ffffff 86 | } 87 | 88 | // h %= p reduction 89 | h2 += h1 >> 26 90 | h1 &= 0x3ffffff 91 | h3 += h2 >> 26 92 | h2 &= 0x3ffffff 93 | h4 += h3 >> 26 94 | h3 &= 0x3ffffff 95 | h0 += 5 * (h4 >> 26) 96 | h4 &= 0x3ffffff 97 | h1 += h0 >> 26 98 | h0 &= 0x3ffffff 99 | 100 | // h - p 101 | t0 := h0 + 5 102 | t1 := h1 + (t0 >> 26) 103 | t2 := h2 + (t1 >> 26) 104 | t3 := h3 + (t2 >> 26) 105 | t4 := h4 + (t3 >> 26) - (1 << 26) 106 | t0 &= 0x3ffffff 107 | t1 &= 0x3ffffff 108 | t2 &= 0x3ffffff 109 | t3 &= 0x3ffffff 110 | 111 | // select h if h < p else h - p 112 | t_mask := (t4 >> 31) - 1 113 | h_mask := ^t_mask 114 | h0 = (h0 & h_mask) | (t0 & t_mask) 115 | h1 = (h1 & h_mask) | (t1 & t_mask) 116 | h2 = (h2 & h_mask) | (t2 & t_mask) 117 | h3 = (h3 & h_mask) | (t3 & t_mask) 118 | h4 = (h4 & h_mask) | (t4 & t_mask) 119 | 120 | // h %= 2^128 121 | h0 |= h1 << 26 122 | h1 = ((h1 >> 6) | (h2 << 20)) 123 | h2 = ((h2 >> 12) | (h3 << 14)) 124 | h3 = ((h3 >> 18) | (h4 << 8)) 125 | 126 | // s: the s part of the key 127 | // tag = (h + s) % (2^128) 128 | t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:])) 129 | h0 = uint32(t) 130 | t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32) 131 | h1 = uint32(t) 132 | t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32) 133 | h2 = uint32(t) 134 | t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32) 135 | h3 = uint32(t) 136 | 137 | binary.LittleEndian.PutUint32(out[0:], h0) 138 | binary.LittleEndian.PutUint32(out[4:], h1) 139 | binary.LittleEndian.PutUint32(out[8:], h2) 140 | binary.LittleEndian.PutUint32(out[12:], h3) 141 | } 142 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/buffer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "io" 9 | "sync" 10 | ) 11 | 12 | // buffer provides a linked list buffer for data exchange 13 | // between producer and consumer. Theoretically the buffer is 14 | // of unlimited capacity as it does no allocation of its own. 15 | type buffer struct { 16 | // protects concurrent access to head, tail and closed 17 | *sync.Cond 18 | 19 | head *element // the buffer that will be read first 20 | tail *element // the buffer that will be read last 21 | 22 | closed bool 23 | } 24 | 25 | // An element represents a single link in a linked list. 26 | type element struct { 27 | buf []byte 28 | next *element 29 | } 30 | 31 | // newBuffer returns an empty buffer that is not closed. 32 | func newBuffer() *buffer { 33 | e := new(element) 34 | b := &buffer{ 35 | Cond: newCond(), 36 | head: e, 37 | tail: e, 38 | } 39 | return b 40 | } 41 | 42 | // write makes buf available for Read to receive. 43 | // buf must not be modified after the call to write. 44 | func (b *buffer) write(buf []byte) { 45 | b.Cond.L.Lock() 46 | e := &element{buf: buf} 47 | b.tail.next = e 48 | b.tail = e 49 | b.Cond.Signal() 50 | b.Cond.L.Unlock() 51 | } 52 | 53 | // eof closes the buffer. Reads from the buffer once all 54 | // the data has been consumed will receive io.EOF. 55 | func (b *buffer) eof() { 56 | b.Cond.L.Lock() 57 | b.closed = true 58 | b.Cond.Signal() 59 | b.Cond.L.Unlock() 60 | } 61 | 62 | // Read reads data from the internal buffer in buf. Reads will block 63 | // if no data is available, or until the buffer is closed. 64 | func (b *buffer) Read(buf []byte) (n int, err error) { 65 | b.Cond.L.Lock() 66 | defer b.Cond.L.Unlock() 67 | 68 | for len(buf) > 0 { 69 | // if there is data in b.head, copy it 70 | if len(b.head.buf) > 0 { 71 | r := copy(buf, b.head.buf) 72 | buf, b.head.buf = buf[r:], b.head.buf[r:] 73 | n += r 74 | continue 75 | } 76 | // if there is a next buffer, make it the head 77 | if len(b.head.buf) == 0 && b.head != b.tail { 78 | b.head = b.head.next 79 | continue 80 | } 81 | 82 | // if at least one byte has been copied, return 83 | if n > 0 { 84 | break 85 | } 86 | 87 | // if nothing was read, and there is nothing outstanding 88 | // check to see if the buffer is closed. 89 | if b.closed { 90 | err = io.EOF 91 | break 92 | } 93 | // out of buffers, wait for producer 94 | b.Cond.Wait() 95 | } 96 | return 97 | } 98 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/certs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "errors" 10 | "fmt" 11 | "io" 12 | "net" 13 | "sort" 14 | "time" 15 | ) 16 | 17 | // These constants from [PROTOCOL.certkeys] represent the algorithm names 18 | // for certificate types supported by this package. 19 | const ( 20 | CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" 21 | CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" 22 | CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" 23 | CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" 24 | CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" 25 | CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" 26 | ) 27 | 28 | // Certificate types distinguish between host and user 29 | // certificates. The values can be set in the CertType field of 30 | // Certificate. 31 | const ( 32 | UserCert = 1 33 | HostCert = 2 34 | ) 35 | 36 | // Signature represents a cryptographic signature. 37 | type Signature struct { 38 | Format string 39 | Blob []byte 40 | } 41 | 42 | // CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that 43 | // a certificate does not expire. 44 | const CertTimeInfinity = 1<<64 - 1 45 | 46 | // An Certificate represents an OpenSSH certificate as defined in 47 | // [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the 48 | // PublicKey interface, so it can be unmarshaled using 49 | // ParsePublicKey. 50 | type Certificate struct { 51 | Nonce []byte 52 | Key PublicKey 53 | Serial uint64 54 | CertType uint32 55 | KeyId string 56 | ValidPrincipals []string 57 | ValidAfter uint64 58 | ValidBefore uint64 59 | Permissions 60 | Reserved []byte 61 | SignatureKey PublicKey 62 | Signature *Signature 63 | } 64 | 65 | // genericCertData holds the key-independent part of the certificate data. 66 | // Overall, certificates contain an nonce, public key fields and 67 | // key-independent fields. 68 | type genericCertData struct { 69 | Serial uint64 70 | CertType uint32 71 | KeyId string 72 | ValidPrincipals []byte 73 | ValidAfter uint64 74 | ValidBefore uint64 75 | CriticalOptions []byte 76 | Extensions []byte 77 | Reserved []byte 78 | SignatureKey []byte 79 | Signature []byte 80 | } 81 | 82 | func marshalStringList(namelist []string) []byte { 83 | var to []byte 84 | for _, name := range namelist { 85 | s := struct{ N string }{name} 86 | to = append(to, Marshal(&s)...) 87 | } 88 | return to 89 | } 90 | 91 | type optionsTuple struct { 92 | Key string 93 | Value []byte 94 | } 95 | 96 | type optionsTupleValue struct { 97 | Value string 98 | } 99 | 100 | // serialize a map of critical options or extensions 101 | // issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, 102 | // we need two length prefixes for a non-empty string value 103 | func marshalTuples(tups map[string]string) []byte { 104 | keys := make([]string, 0, len(tups)) 105 | for key := range tups { 106 | keys = append(keys, key) 107 | } 108 | sort.Strings(keys) 109 | 110 | var ret []byte 111 | for _, key := range keys { 112 | s := optionsTuple{Key: key} 113 | if value := tups[key]; len(value) > 0 { 114 | s.Value = Marshal(&optionsTupleValue{value}) 115 | } 116 | ret = append(ret, Marshal(&s)...) 117 | } 118 | return ret 119 | } 120 | 121 | // issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, 122 | // we need two length prefixes for a non-empty option value 123 | func parseTuples(in []byte) (map[string]string, error) { 124 | tups := map[string]string{} 125 | var lastKey string 126 | var haveLastKey bool 127 | 128 | for len(in) > 0 { 129 | var key, val, extra []byte 130 | var ok bool 131 | 132 | if key, in, ok = parseString(in); !ok { 133 | return nil, errShortRead 134 | } 135 | keyStr := string(key) 136 | // according to [PROTOCOL.certkeys], the names must be in 137 | // lexical order. 138 | if haveLastKey && keyStr <= lastKey { 139 | return nil, fmt.Errorf("ssh: certificate options are not in lexical order") 140 | } 141 | lastKey, haveLastKey = keyStr, true 142 | // the next field is a data field, which if non-empty has a string embedded 143 | if val, in, ok = parseString(in); !ok { 144 | return nil, errShortRead 145 | } 146 | if len(val) > 0 { 147 | val, extra, ok = parseString(val) 148 | if !ok { 149 | return nil, errShortRead 150 | } 151 | if len(extra) > 0 { 152 | return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value") 153 | } 154 | tups[keyStr] = string(val) 155 | } else { 156 | tups[keyStr] = "" 157 | } 158 | } 159 | return tups, nil 160 | } 161 | 162 | func parseCert(in []byte, privAlgo string) (*Certificate, error) { 163 | nonce, rest, ok := parseString(in) 164 | if !ok { 165 | return nil, errShortRead 166 | } 167 | 168 | key, rest, err := parsePubKey(rest, privAlgo) 169 | if err != nil { 170 | return nil, err 171 | } 172 | 173 | var g genericCertData 174 | if err := Unmarshal(rest, &g); err != nil { 175 | return nil, err 176 | } 177 | 178 | c := &Certificate{ 179 | Nonce: nonce, 180 | Key: key, 181 | Serial: g.Serial, 182 | CertType: g.CertType, 183 | KeyId: g.KeyId, 184 | ValidAfter: g.ValidAfter, 185 | ValidBefore: g.ValidBefore, 186 | } 187 | 188 | for principals := g.ValidPrincipals; len(principals) > 0; { 189 | principal, rest, ok := parseString(principals) 190 | if !ok { 191 | return nil, errShortRead 192 | } 193 | c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) 194 | principals = rest 195 | } 196 | 197 | c.CriticalOptions, err = parseTuples(g.CriticalOptions) 198 | if err != nil { 199 | return nil, err 200 | } 201 | c.Extensions, err = parseTuples(g.Extensions) 202 | if err != nil { 203 | return nil, err 204 | } 205 | c.Reserved = g.Reserved 206 | k, err := ParsePublicKey(g.SignatureKey) 207 | if err != nil { 208 | return nil, err 209 | } 210 | 211 | c.SignatureKey = k 212 | c.Signature, rest, ok = parseSignatureBody(g.Signature) 213 | if !ok || len(rest) > 0 { 214 | return nil, errors.New("ssh: signature parse error") 215 | } 216 | 217 | return c, nil 218 | } 219 | 220 | type openSSHCertSigner struct { 221 | pub *Certificate 222 | signer Signer 223 | } 224 | 225 | // NewCertSigner returns a Signer that signs with the given Certificate, whose 226 | // private key is held by signer. It returns an error if the public key in cert 227 | // doesn't match the key used by signer. 228 | func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { 229 | if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { 230 | return nil, errors.New("ssh: signer and cert have different public key") 231 | } 232 | 233 | return &openSSHCertSigner{cert, signer}, nil 234 | } 235 | 236 | func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { 237 | return s.signer.Sign(rand, data) 238 | } 239 | 240 | func (s *openSSHCertSigner) PublicKey() PublicKey { 241 | return s.pub 242 | } 243 | 244 | const sourceAddressCriticalOption = "source-address" 245 | 246 | // CertChecker does the work of verifying a certificate. Its methods 247 | // can be plugged into ClientConfig.HostKeyCallback and 248 | // ServerConfig.PublicKeyCallback. For the CertChecker to work, 249 | // minimally, the IsAuthority callback should be set. 250 | type CertChecker struct { 251 | // SupportedCriticalOptions lists the CriticalOptions that the 252 | // server application layer understands. These are only used 253 | // for user certificates. 254 | SupportedCriticalOptions []string 255 | 256 | // IsUserAuthority should return true if the key is recognized as an 257 | // authority for the given user certificate. This allows for 258 | // certificates to be signed by other certificates. This must be set 259 | // if this CertChecker will be checking user certificates. 260 | IsUserAuthority func(auth PublicKey) bool 261 | 262 | // IsHostAuthority should report whether the key is recognized as 263 | // an authority for this host. This allows for certificates to be 264 | // signed by other keys, and for those other keys to only be valid 265 | // signers for particular hostnames. This must be set if this 266 | // CertChecker will be checking host certificates. 267 | IsHostAuthority func(auth PublicKey, address string) bool 268 | 269 | // Clock is used for verifying time stamps. If nil, time.Now 270 | // is used. 271 | Clock func() time.Time 272 | 273 | // UserKeyFallback is called when CertChecker.Authenticate encounters a 274 | // public key that is not a certificate. It must implement validation 275 | // of user keys or else, if nil, all such keys are rejected. 276 | UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) 277 | 278 | // HostKeyFallback is called when CertChecker.CheckHostKey encounters a 279 | // public key that is not a certificate. It must implement host key 280 | // validation or else, if nil, all such keys are rejected. 281 | HostKeyFallback HostKeyCallback 282 | 283 | // IsRevoked is called for each certificate so that revocation checking 284 | // can be implemented. It should return true if the given certificate 285 | // is revoked and false otherwise. If nil, no certificates are 286 | // considered to have been revoked. 287 | IsRevoked func(cert *Certificate) bool 288 | } 289 | 290 | // CheckHostKey checks a host key certificate. This method can be 291 | // plugged into ClientConfig.HostKeyCallback. 292 | func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { 293 | cert, ok := key.(*Certificate) 294 | if !ok { 295 | if c.HostKeyFallback != nil { 296 | return c.HostKeyFallback(addr, remote, key) 297 | } 298 | return errors.New("ssh: non-certificate host key") 299 | } 300 | if cert.CertType != HostCert { 301 | return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) 302 | } 303 | if !c.IsHostAuthority(cert.SignatureKey, addr) { 304 | return fmt.Errorf("ssh: no authorities for hostname: %v", addr) 305 | } 306 | 307 | hostname, _, err := net.SplitHostPort(addr) 308 | if err != nil { 309 | return err 310 | } 311 | 312 | // Pass hostname only as principal for host certificates (consistent with OpenSSH) 313 | return c.CheckCert(hostname, cert) 314 | } 315 | 316 | // Authenticate checks a user certificate. Authenticate can be used as 317 | // a value for ServerConfig.PublicKeyCallback. 318 | func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { 319 | cert, ok := pubKey.(*Certificate) 320 | if !ok { 321 | if c.UserKeyFallback != nil { 322 | return c.UserKeyFallback(conn, pubKey) 323 | } 324 | return nil, errors.New("ssh: normal key pairs not accepted") 325 | } 326 | 327 | if cert.CertType != UserCert { 328 | return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) 329 | } 330 | if !c.IsUserAuthority(cert.SignatureKey) { 331 | return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") 332 | } 333 | 334 | if err := c.CheckCert(conn.User(), cert); err != nil { 335 | return nil, err 336 | } 337 | 338 | return &cert.Permissions, nil 339 | } 340 | 341 | // CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and 342 | // the signature of the certificate. 343 | func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { 344 | if c.IsRevoked != nil && c.IsRevoked(cert) { 345 | return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial) 346 | } 347 | 348 | for opt := range cert.CriticalOptions { 349 | // sourceAddressCriticalOption will be enforced by 350 | // serverAuthenticate 351 | if opt == sourceAddressCriticalOption { 352 | continue 353 | } 354 | 355 | found := false 356 | for _, supp := range c.SupportedCriticalOptions { 357 | if supp == opt { 358 | found = true 359 | break 360 | } 361 | } 362 | if !found { 363 | return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) 364 | } 365 | } 366 | 367 | if len(cert.ValidPrincipals) > 0 { 368 | // By default, certs are valid for all users/hosts. 369 | found := false 370 | for _, p := range cert.ValidPrincipals { 371 | if p == principal { 372 | found = true 373 | break 374 | } 375 | } 376 | if !found { 377 | return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) 378 | } 379 | } 380 | 381 | clock := c.Clock 382 | if clock == nil { 383 | clock = time.Now 384 | } 385 | 386 | unixNow := clock().Unix() 387 | if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { 388 | return fmt.Errorf("ssh: cert is not yet valid") 389 | } 390 | if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { 391 | return fmt.Errorf("ssh: cert has expired") 392 | } 393 | if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { 394 | return fmt.Errorf("ssh: certificate signature does not verify") 395 | } 396 | 397 | return nil 398 | } 399 | 400 | // SignCert sets c.SignatureKey to the authority's public key and stores a 401 | // Signature, by authority, in the certificate. 402 | func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { 403 | c.Nonce = make([]byte, 32) 404 | if _, err := io.ReadFull(rand, c.Nonce); err != nil { 405 | return err 406 | } 407 | c.SignatureKey = authority.PublicKey() 408 | 409 | sig, err := authority.Sign(rand, c.bytesForSigning()) 410 | if err != nil { 411 | return err 412 | } 413 | c.Signature = sig 414 | return nil 415 | } 416 | 417 | var certAlgoNames = map[string]string{ 418 | KeyAlgoRSA: CertAlgoRSAv01, 419 | KeyAlgoDSA: CertAlgoDSAv01, 420 | KeyAlgoECDSA256: CertAlgoECDSA256v01, 421 | KeyAlgoECDSA384: CertAlgoECDSA384v01, 422 | KeyAlgoECDSA521: CertAlgoECDSA521v01, 423 | KeyAlgoED25519: CertAlgoED25519v01, 424 | } 425 | 426 | // certToPrivAlgo returns the underlying algorithm for a certificate algorithm. 427 | // Panics if a non-certificate algorithm is passed. 428 | func certToPrivAlgo(algo string) string { 429 | for privAlgo, pubAlgo := range certAlgoNames { 430 | if pubAlgo == algo { 431 | return privAlgo 432 | } 433 | } 434 | panic("unknown cert algorithm") 435 | } 436 | 437 | func (cert *Certificate) bytesForSigning() []byte { 438 | c2 := *cert 439 | c2.Signature = nil 440 | out := c2.Marshal() 441 | // Drop trailing signature length. 442 | return out[:len(out)-4] 443 | } 444 | 445 | // Marshal serializes c into OpenSSH's wire format. It is part of the 446 | // PublicKey interface. 447 | func (c *Certificate) Marshal() []byte { 448 | generic := genericCertData{ 449 | Serial: c.Serial, 450 | CertType: c.CertType, 451 | KeyId: c.KeyId, 452 | ValidPrincipals: marshalStringList(c.ValidPrincipals), 453 | ValidAfter: uint64(c.ValidAfter), 454 | ValidBefore: uint64(c.ValidBefore), 455 | CriticalOptions: marshalTuples(c.CriticalOptions), 456 | Extensions: marshalTuples(c.Extensions), 457 | Reserved: c.Reserved, 458 | SignatureKey: c.SignatureKey.Marshal(), 459 | } 460 | if c.Signature != nil { 461 | generic.Signature = Marshal(c.Signature) 462 | } 463 | genericBytes := Marshal(&generic) 464 | keyBytes := c.Key.Marshal() 465 | _, keyBytes, _ = parseString(keyBytes) 466 | prefix := Marshal(&struct { 467 | Name string 468 | Nonce []byte 469 | Key []byte `ssh:"rest"` 470 | }{c.Type(), c.Nonce, keyBytes}) 471 | 472 | result := make([]byte, 0, len(prefix)+len(genericBytes)) 473 | result = append(result, prefix...) 474 | result = append(result, genericBytes...) 475 | return result 476 | } 477 | 478 | // Type returns the key name. It is part of the PublicKey interface. 479 | func (c *Certificate) Type() string { 480 | algo, ok := certAlgoNames[c.Key.Type()] 481 | if !ok { 482 | panic("unknown cert key type " + c.Key.Type()) 483 | } 484 | return algo 485 | } 486 | 487 | // Verify verifies a signature against the certificate's public 488 | // key. It is part of the PublicKey interface. 489 | func (c *Certificate) Verify(data []byte, sig *Signature) error { 490 | return c.Key.Verify(data, sig) 491 | } 492 | 493 | func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { 494 | format, in, ok := parseString(in) 495 | if !ok { 496 | return 497 | } 498 | 499 | out = &Signature{ 500 | Format: string(format), 501 | } 502 | 503 | if out.Blob, in, ok = parseString(in); !ok { 504 | return 505 | } 506 | 507 | return out, in, ok 508 | } 509 | 510 | func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { 511 | sigBytes, rest, ok := parseString(in) 512 | if !ok { 513 | return 514 | } 515 | 516 | out, trailing, ok := parseSignatureBody(sigBytes) 517 | if !ok || len(trailing) > 0 { 518 | return nil, nil, false 519 | } 520 | return 521 | } 522 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "errors" 10 | "fmt" 11 | "net" 12 | "os" 13 | "sync" 14 | "time" 15 | ) 16 | 17 | // Client implements a traditional SSH client that supports shells, 18 | // subprocesses, TCP port/streamlocal forwarding and tunneled dialing. 19 | type Client struct { 20 | Conn 21 | 22 | forwards forwardList // forwarded tcpip connections from the remote side 23 | mu sync.Mutex 24 | channelHandlers map[string]chan NewChannel 25 | } 26 | 27 | // HandleChannelOpen returns a channel on which NewChannel requests 28 | // for the given type are sent. If the type already is being handled, 29 | // nil is returned. The channel is closed when the connection is closed. 30 | func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel { 31 | c.mu.Lock() 32 | defer c.mu.Unlock() 33 | if c.channelHandlers == nil { 34 | // The SSH channel has been closed. 35 | c := make(chan NewChannel) 36 | close(c) 37 | return c 38 | } 39 | 40 | ch := c.channelHandlers[channelType] 41 | if ch != nil { 42 | return nil 43 | } 44 | 45 | ch = make(chan NewChannel, chanSize) 46 | c.channelHandlers[channelType] = ch 47 | return ch 48 | } 49 | 50 | // NewClient creates a Client on top of the given connection. 51 | func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { 52 | conn := &Client{ 53 | Conn: c, 54 | channelHandlers: make(map[string]chan NewChannel, 1), 55 | } 56 | 57 | go conn.handleGlobalRequests(reqs) 58 | go conn.handleChannelOpens(chans) 59 | go func() { 60 | conn.Wait() 61 | conn.forwards.closeAll() 62 | }() 63 | go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip")) 64 | go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com")) 65 | return conn 66 | } 67 | 68 | // NewClientConn establishes an authenticated SSH connection using c 69 | // as the underlying transport. The Request and NewChannel channels 70 | // must be serviced or the connection will hang. 71 | func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) { 72 | fullConf := *config 73 | fullConf.SetDefaults() 74 | if fullConf.HostKeyCallback == nil { 75 | c.Close() 76 | return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback") 77 | } 78 | 79 | conn := &connection{ 80 | sshConn: sshConn{conn: c}, 81 | } 82 | 83 | if err := conn.clientHandshake(addr, &fullConf); err != nil { 84 | c.Close() 85 | return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) 86 | } 87 | conn.mux = newMux(conn.transport) 88 | return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil 89 | } 90 | 91 | // clientHandshake performs the client side key exchange. See RFC 4253 Section 92 | // 7. 93 | func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { 94 | if config.ClientVersion != "" { 95 | c.clientVersion = []byte(config.ClientVersion) 96 | } else { 97 | c.clientVersion = []byte(packageVersion) 98 | } 99 | var err error 100 | c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) 101 | if err != nil { 102 | return err 103 | } 104 | 105 | c.transport = newClientTransport( 106 | newTransport(c.sshConn.conn, config.Rand, true /* is client */), 107 | c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr()) 108 | if err := c.transport.waitSession(); err != nil { 109 | return err 110 | } 111 | 112 | c.sessionID = c.transport.getSessionID() 113 | return c.clientAuthenticate(config) 114 | } 115 | 116 | // verifyHostKeySignature verifies the host key obtained in the key 117 | // exchange. 118 | func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error { 119 | sig, rest, ok := parseSignatureBody(result.Signature) 120 | if len(rest) > 0 || !ok { 121 | return errors.New("ssh: signature parse error") 122 | } 123 | 124 | return hostKey.Verify(result.H, sig) 125 | } 126 | 127 | // NewSession opens a new Session for this client. (A session is a remote 128 | // execution of a program.) 129 | func (c *Client) NewSession() (*Session, error) { 130 | ch, in, err := c.OpenChannel("session", nil) 131 | if err != nil { 132 | return nil, err 133 | } 134 | return newSession(ch, in) 135 | } 136 | 137 | func (c *Client) handleGlobalRequests(incoming <-chan *Request) { 138 | for r := range incoming { 139 | // This handles keepalive messages and matches 140 | // the behaviour of OpenSSH. 141 | r.Reply(false, nil) 142 | } 143 | } 144 | 145 | // handleChannelOpens channel open messages from the remote side. 146 | func (c *Client) handleChannelOpens(in <-chan NewChannel) { 147 | for ch := range in { 148 | c.mu.Lock() 149 | handler := c.channelHandlers[ch.ChannelType()] 150 | c.mu.Unlock() 151 | 152 | if handler != nil { 153 | handler <- ch 154 | } else { 155 | ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType())) 156 | } 157 | } 158 | 159 | c.mu.Lock() 160 | for _, ch := range c.channelHandlers { 161 | close(ch) 162 | } 163 | c.channelHandlers = nil 164 | c.mu.Unlock() 165 | } 166 | 167 | // Dial starts a client connection to the given SSH server. It is a 168 | // convenience function that connects to the given network address, 169 | // initiates the SSH handshake, and then sets up a Client. For access 170 | // to incoming channels and requests, use net.Dial with NewClientConn 171 | // instead. 172 | func Dial(network, addr string, config *ClientConfig) (*Client, error) { 173 | conn, err := net.DialTimeout(network, addr, config.Timeout) 174 | if err != nil { 175 | return nil, err 176 | } 177 | c, chans, reqs, err := NewClientConn(conn, addr, config) 178 | if err != nil { 179 | return nil, err 180 | } 181 | return NewClient(c, chans, reqs), nil 182 | } 183 | 184 | // HostKeyCallback is the function type used for verifying server 185 | // keys. A HostKeyCallback must return nil if the host key is OK, or 186 | // an error to reject it. It receives the hostname as passed to Dial 187 | // or NewClientConn. The remote address is the RemoteAddr of the 188 | // net.Conn underlying the the SSH connection. 189 | type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error 190 | 191 | // BannerCallback is the function type used for treat the banner sent by 192 | // the server. A BannerCallback receives the message sent by the remote server. 193 | type BannerCallback func(message string) error 194 | 195 | // A ClientConfig structure is used to configure a Client. It must not be 196 | // modified after having been passed to an SSH function. 197 | type ClientConfig struct { 198 | // Config contains configuration that is shared between clients and 199 | // servers. 200 | Config 201 | 202 | // User contains the username to authenticate as. 203 | User string 204 | 205 | // Auth contains possible authentication methods to use with the 206 | // server. Only the first instance of a particular RFC 4252 method will 207 | // be used during authentication. 208 | Auth []AuthMethod 209 | 210 | // HostKeyCallback is called during the cryptographic 211 | // handshake to validate the server's host key. The client 212 | // configuration must supply this callback for the connection 213 | // to succeed. The functions InsecureIgnoreHostKey or 214 | // FixedHostKey can be used for simplistic host key checks. 215 | HostKeyCallback HostKeyCallback 216 | 217 | // BannerCallback is called during the SSH dance to display a custom 218 | // server's message. The client configuration can supply this callback to 219 | // handle it as wished. The function BannerDisplayStderr can be used for 220 | // simplistic display on Stderr. 221 | BannerCallback BannerCallback 222 | 223 | // ClientVersion contains the version identification string that will 224 | // be used for the connection. If empty, a reasonable default is used. 225 | ClientVersion string 226 | 227 | // HostKeyAlgorithms lists the key types that the client will 228 | // accept from the server as host key, in order of 229 | // preference. If empty, a reasonable default is used. Any 230 | // string returned from PublicKey.Type method may be used, or 231 | // any of the CertAlgoXxxx and KeyAlgoXxxx constants. 232 | HostKeyAlgorithms []string 233 | 234 | // Timeout is the maximum amount of time for the TCP connection to establish. 235 | // 236 | // A Timeout of zero means no timeout. 237 | Timeout time.Duration 238 | } 239 | 240 | // InsecureIgnoreHostKey returns a function that can be used for 241 | // ClientConfig.HostKeyCallback to accept any host key. It should 242 | // not be used for production code. 243 | func InsecureIgnoreHostKey() HostKeyCallback { 244 | return func(hostname string, remote net.Addr, key PublicKey) error { 245 | return nil 246 | } 247 | } 248 | 249 | type fixedHostKey struct { 250 | key PublicKey 251 | } 252 | 253 | func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error { 254 | if f.key == nil { 255 | return fmt.Errorf("ssh: required host key was nil") 256 | } 257 | if !bytes.Equal(key.Marshal(), f.key.Marshal()) { 258 | return fmt.Errorf("ssh: host key mismatch") 259 | } 260 | return nil 261 | } 262 | 263 | // FixedHostKey returns a function for use in 264 | // ClientConfig.HostKeyCallback to accept only a specific host key. 265 | func FixedHostKey(key PublicKey) HostKeyCallback { 266 | hk := &fixedHostKey{key} 267 | return hk.check 268 | } 269 | 270 | // BannerDisplayStderr returns a function that can be used for 271 | // ClientConfig.BannerCallback to display banners on os.Stderr. 272 | func BannerDisplayStderr() BannerCallback { 273 | return func(banner string) error { 274 | _, err := os.Stderr.WriteString(banner) 275 | 276 | return err 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/client_auth.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "bytes" 9 | "errors" 10 | "fmt" 11 | "io" 12 | ) 13 | 14 | type authResult int 15 | 16 | const ( 17 | authFailure authResult = iota 18 | authPartialSuccess 19 | authSuccess 20 | ) 21 | 22 | // clientAuthenticate authenticates with the remote server. See RFC 4252. 23 | func (c *connection) clientAuthenticate(config *ClientConfig) error { 24 | // initiate user auth session 25 | if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil { 26 | return err 27 | } 28 | packet, err := c.transport.readPacket() 29 | if err != nil { 30 | return err 31 | } 32 | var serviceAccept serviceAcceptMsg 33 | if err := Unmarshal(packet, &serviceAccept); err != nil { 34 | return err 35 | } 36 | 37 | // during the authentication phase the client first attempts the "none" method 38 | // then any untried methods suggested by the server. 39 | tried := make(map[string]bool) 40 | var lastMethods []string 41 | 42 | sessionID := c.transport.getSessionID() 43 | for auth := AuthMethod(new(noneAuth)); auth != nil; { 44 | ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand) 45 | if err != nil { 46 | return err 47 | } 48 | if ok == authSuccess { 49 | // success 50 | return nil 51 | } else if ok == authFailure { 52 | tried[auth.method()] = true 53 | } 54 | if methods == nil { 55 | methods = lastMethods 56 | } 57 | lastMethods = methods 58 | 59 | auth = nil 60 | 61 | findNext: 62 | for _, a := range config.Auth { 63 | candidateMethod := a.method() 64 | if tried[candidateMethod] { 65 | continue 66 | } 67 | for _, meth := range methods { 68 | if meth == candidateMethod { 69 | auth = a 70 | break findNext 71 | } 72 | } 73 | } 74 | } 75 | return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried)) 76 | } 77 | 78 | func keys(m map[string]bool) []string { 79 | s := make([]string, 0, len(m)) 80 | 81 | for key := range m { 82 | s = append(s, key) 83 | } 84 | return s 85 | } 86 | 87 | // An AuthMethod represents an instance of an RFC 4252 authentication method. 88 | type AuthMethod interface { 89 | // auth authenticates user over transport t. 90 | // Returns true if authentication is successful. 91 | // If authentication is not successful, a []string of alternative 92 | // method names is returned. If the slice is nil, it will be ignored 93 | // and the previous set of possible methods will be reused. 94 | auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error) 95 | 96 | // method returns the RFC 4252 method name. 97 | method() string 98 | } 99 | 100 | // "none" authentication, RFC 4252 section 5.2. 101 | type noneAuth int 102 | 103 | func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { 104 | if err := c.writePacket(Marshal(&userAuthRequestMsg{ 105 | User: user, 106 | Service: serviceSSH, 107 | Method: "none", 108 | })); err != nil { 109 | return authFailure, nil, err 110 | } 111 | 112 | return handleAuthResponse(c) 113 | } 114 | 115 | func (n *noneAuth) method() string { 116 | return "none" 117 | } 118 | 119 | // passwordCallback is an AuthMethod that fetches the password through 120 | // a function call, e.g. by prompting the user. 121 | type passwordCallback func() (password string, err error) 122 | 123 | func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { 124 | type passwordAuthMsg struct { 125 | User string `sshtype:"50"` 126 | Service string 127 | Method string 128 | Reply bool 129 | Password string 130 | } 131 | 132 | pw, err := cb() 133 | // REVIEW NOTE: is there a need to support skipping a password attempt? 134 | // The program may only find out that the user doesn't have a password 135 | // when prompting. 136 | if err != nil { 137 | return authFailure, nil, err 138 | } 139 | 140 | if err := c.writePacket(Marshal(&passwordAuthMsg{ 141 | User: user, 142 | Service: serviceSSH, 143 | Method: cb.method(), 144 | Reply: false, 145 | Password: pw, 146 | })); err != nil { 147 | return authFailure, nil, err 148 | } 149 | 150 | return handleAuthResponse(c) 151 | } 152 | 153 | func (cb passwordCallback) method() string { 154 | return "password" 155 | } 156 | 157 | // Password returns an AuthMethod using the given password. 158 | func Password(secret string) AuthMethod { 159 | return passwordCallback(func() (string, error) { return secret, nil }) 160 | } 161 | 162 | // PasswordCallback returns an AuthMethod that uses a callback for 163 | // fetching a password. 164 | func PasswordCallback(prompt func() (secret string, err error)) AuthMethod { 165 | return passwordCallback(prompt) 166 | } 167 | 168 | type publickeyAuthMsg struct { 169 | User string `sshtype:"50"` 170 | Service string 171 | Method string 172 | // HasSig indicates to the receiver packet that the auth request is signed and 173 | // should be used for authentication of the request. 174 | HasSig bool 175 | Algoname string 176 | PubKey []byte 177 | // Sig is tagged with "rest" so Marshal will exclude it during 178 | // validateKey 179 | Sig []byte `ssh:"rest"` 180 | } 181 | 182 | // publicKeyCallback is an AuthMethod that uses a set of key 183 | // pairs for authentication. 184 | type publicKeyCallback func() ([]Signer, error) 185 | 186 | func (cb publicKeyCallback) method() string { 187 | return "publickey" 188 | } 189 | 190 | func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { 191 | // Authentication is performed by sending an enquiry to test if a key is 192 | // acceptable to the remote. If the key is acceptable, the client will 193 | // attempt to authenticate with the valid key. If not the client will repeat 194 | // the process with the remaining keys. 195 | 196 | signers, err := cb() 197 | if err != nil { 198 | return authFailure, nil, err 199 | } 200 | var methods []string 201 | for _, signer := range signers { 202 | ok, err := validateKey(signer.PublicKey(), user, c) 203 | if err != nil { 204 | return authFailure, nil, err 205 | } 206 | if !ok { 207 | continue 208 | } 209 | 210 | pub := signer.PublicKey() 211 | pubKey := pub.Marshal() 212 | sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{ 213 | User: user, 214 | Service: serviceSSH, 215 | Method: cb.method(), 216 | }, []byte(pub.Type()), pubKey)) 217 | if err != nil { 218 | return authFailure, nil, err 219 | } 220 | 221 | // manually wrap the serialized signature in a string 222 | s := Marshal(sign) 223 | sig := make([]byte, stringLength(len(s))) 224 | marshalString(sig, s) 225 | msg := publickeyAuthMsg{ 226 | User: user, 227 | Service: serviceSSH, 228 | Method: cb.method(), 229 | HasSig: true, 230 | Algoname: pub.Type(), 231 | PubKey: pubKey, 232 | Sig: sig, 233 | } 234 | p := Marshal(&msg) 235 | if err := c.writePacket(p); err != nil { 236 | return authFailure, nil, err 237 | } 238 | var success authResult 239 | success, methods, err = handleAuthResponse(c) 240 | if err != nil { 241 | return authFailure, nil, err 242 | } 243 | 244 | // If authentication succeeds or the list of available methods does not 245 | // contain the "publickey" method, do not attempt to authenticate with any 246 | // other keys. According to RFC 4252 Section 7, the latter can occur when 247 | // additional authentication methods are required. 248 | if success == authSuccess || !containsMethod(methods, cb.method()) { 249 | return success, methods, err 250 | } 251 | } 252 | 253 | return authFailure, methods, nil 254 | } 255 | 256 | func containsMethod(methods []string, method string) bool { 257 | for _, m := range methods { 258 | if m == method { 259 | return true 260 | } 261 | } 262 | 263 | return false 264 | } 265 | 266 | // validateKey validates the key provided is acceptable to the server. 267 | func validateKey(key PublicKey, user string, c packetConn) (bool, error) { 268 | pubKey := key.Marshal() 269 | msg := publickeyAuthMsg{ 270 | User: user, 271 | Service: serviceSSH, 272 | Method: "publickey", 273 | HasSig: false, 274 | Algoname: key.Type(), 275 | PubKey: pubKey, 276 | } 277 | if err := c.writePacket(Marshal(&msg)); err != nil { 278 | return false, err 279 | } 280 | 281 | return confirmKeyAck(key, c) 282 | } 283 | 284 | func confirmKeyAck(key PublicKey, c packetConn) (bool, error) { 285 | pubKey := key.Marshal() 286 | algoname := key.Type() 287 | 288 | for { 289 | packet, err := c.readPacket() 290 | if err != nil { 291 | return false, err 292 | } 293 | switch packet[0] { 294 | case msgUserAuthBanner: 295 | if err := handleBannerResponse(c, packet); err != nil { 296 | return false, err 297 | } 298 | case msgUserAuthPubKeyOk: 299 | var msg userAuthPubKeyOkMsg 300 | if err := Unmarshal(packet, &msg); err != nil { 301 | return false, err 302 | } 303 | if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) { 304 | return false, nil 305 | } 306 | return true, nil 307 | case msgUserAuthFailure: 308 | return false, nil 309 | default: 310 | return false, unexpectedMessageError(msgUserAuthSuccess, packet[0]) 311 | } 312 | } 313 | } 314 | 315 | // PublicKeys returns an AuthMethod that uses the given key 316 | // pairs. 317 | func PublicKeys(signers ...Signer) AuthMethod { 318 | return publicKeyCallback(func() ([]Signer, error) { return signers, nil }) 319 | } 320 | 321 | // PublicKeysCallback returns an AuthMethod that runs the given 322 | // function to obtain a list of key pairs. 323 | func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod { 324 | return publicKeyCallback(getSigners) 325 | } 326 | 327 | // handleAuthResponse returns whether the preceding authentication request succeeded 328 | // along with a list of remaining authentication methods to try next and 329 | // an error if an unexpected response was received. 330 | func handleAuthResponse(c packetConn) (authResult, []string, error) { 331 | for { 332 | packet, err := c.readPacket() 333 | if err != nil { 334 | return authFailure, nil, err 335 | } 336 | 337 | switch packet[0] { 338 | case msgUserAuthBanner: 339 | if err := handleBannerResponse(c, packet); err != nil { 340 | return authFailure, nil, err 341 | } 342 | case msgUserAuthFailure: 343 | var msg userAuthFailureMsg 344 | if err := Unmarshal(packet, &msg); err != nil { 345 | return authFailure, nil, err 346 | } 347 | if msg.PartialSuccess { 348 | return authPartialSuccess, msg.Methods, nil 349 | } 350 | return authFailure, msg.Methods, nil 351 | case msgUserAuthSuccess: 352 | return authSuccess, nil, nil 353 | default: 354 | return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) 355 | } 356 | } 357 | } 358 | 359 | func handleBannerResponse(c packetConn, packet []byte) error { 360 | var msg userAuthBannerMsg 361 | if err := Unmarshal(packet, &msg); err != nil { 362 | return err 363 | } 364 | 365 | transport, ok := c.(*handshakeTransport) 366 | if !ok { 367 | return nil 368 | } 369 | 370 | if transport.bannerCallback != nil { 371 | return transport.bannerCallback(msg.Message) 372 | } 373 | 374 | return nil 375 | } 376 | 377 | // KeyboardInteractiveChallenge should print questions, optionally 378 | // disabling echoing (e.g. for passwords), and return all the answers. 379 | // Challenge may be called multiple times in a single session. After 380 | // successful authentication, the server may send a challenge with no 381 | // questions, for which the user and instruction messages should be 382 | // printed. RFC 4256 section 3.3 details how the UI should behave for 383 | // both CLI and GUI environments. 384 | type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error) 385 | 386 | // KeyboardInteractive returns an AuthMethod using a prompt/response 387 | // sequence controlled by the server. 388 | func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod { 389 | return challenge 390 | } 391 | 392 | func (cb KeyboardInteractiveChallenge) method() string { 393 | return "keyboard-interactive" 394 | } 395 | 396 | func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { 397 | type initiateMsg struct { 398 | User string `sshtype:"50"` 399 | Service string 400 | Method string 401 | Language string 402 | Submethods string 403 | } 404 | 405 | if err := c.writePacket(Marshal(&initiateMsg{ 406 | User: user, 407 | Service: serviceSSH, 408 | Method: "keyboard-interactive", 409 | })); err != nil { 410 | return authFailure, nil, err 411 | } 412 | 413 | for { 414 | packet, err := c.readPacket() 415 | if err != nil { 416 | return authFailure, nil, err 417 | } 418 | 419 | // like handleAuthResponse, but with less options. 420 | switch packet[0] { 421 | case msgUserAuthBanner: 422 | if err := handleBannerResponse(c, packet); err != nil { 423 | return authFailure, nil, err 424 | } 425 | continue 426 | case msgUserAuthInfoRequest: 427 | // OK 428 | case msgUserAuthFailure: 429 | var msg userAuthFailureMsg 430 | if err := Unmarshal(packet, &msg); err != nil { 431 | return authFailure, nil, err 432 | } 433 | if msg.PartialSuccess { 434 | return authPartialSuccess, msg.Methods, nil 435 | } 436 | return authFailure, msg.Methods, nil 437 | case msgUserAuthSuccess: 438 | return authSuccess, nil, nil 439 | default: 440 | return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) 441 | } 442 | 443 | var msg userAuthInfoRequestMsg 444 | if err := Unmarshal(packet, &msg); err != nil { 445 | return authFailure, nil, err 446 | } 447 | 448 | // Manually unpack the prompt/echo pairs. 449 | rest := msg.Prompts 450 | var prompts []string 451 | var echos []bool 452 | for i := 0; i < int(msg.NumPrompts); i++ { 453 | prompt, r, ok := parseString(rest) 454 | if !ok || len(r) == 0 { 455 | return authFailure, nil, errors.New("ssh: prompt format error") 456 | } 457 | prompts = append(prompts, string(prompt)) 458 | echos = append(echos, r[0] != 0) 459 | rest = r[1:] 460 | } 461 | 462 | if len(rest) != 0 { 463 | return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs") 464 | } 465 | 466 | answers, err := cb(msg.User, msg.Instruction, prompts, echos) 467 | if err != nil { 468 | return authFailure, nil, err 469 | } 470 | 471 | if len(answers) != len(prompts) { 472 | return authFailure, nil, errors.New("ssh: not enough answers from keyboard-interactive callback") 473 | } 474 | responseLength := 1 + 4 475 | for _, a := range answers { 476 | responseLength += stringLength(len(a)) 477 | } 478 | serialized := make([]byte, responseLength) 479 | p := serialized 480 | p[0] = msgUserAuthInfoResponse 481 | p = p[1:] 482 | p = marshalUint32(p, uint32(len(answers))) 483 | for _, a := range answers { 484 | p = marshalString(p, []byte(a)) 485 | } 486 | 487 | if err := c.writePacket(serialized); err != nil { 488 | return authFailure, nil, err 489 | } 490 | } 491 | } 492 | 493 | type retryableAuthMethod struct { 494 | authMethod AuthMethod 495 | maxTries int 496 | } 497 | 498 | func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) { 499 | for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ { 500 | ok, methods, err = r.authMethod.auth(session, user, c, rand) 501 | if ok != authFailure || err != nil { // either success, partial success or error terminate 502 | return ok, methods, err 503 | } 504 | } 505 | return ok, methods, err 506 | } 507 | 508 | func (r *retryableAuthMethod) method() string { 509 | return r.authMethod.method() 510 | } 511 | 512 | // RetryableAuthMethod is a decorator for other auth methods enabling them to 513 | // be retried up to maxTries before considering that AuthMethod itself failed. 514 | // If maxTries is <= 0, will retry indefinitely 515 | // 516 | // This is useful for interactive clients using challenge/response type 517 | // authentication (e.g. Keyboard-Interactive, Password, etc) where the user 518 | // could mistype their response resulting in the server issuing a 519 | // SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4 520 | // [keyboard-interactive]); Without this decorator, the non-retryable 521 | // AuthMethod would be removed from future consideration, and never tried again 522 | // (and so the user would never be able to retry their entry). 523 | func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod { 524 | return &retryableAuthMethod{authMethod: auth, maxTries: maxTries} 525 | } 526 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/common.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "crypto" 9 | "crypto/rand" 10 | "fmt" 11 | "io" 12 | "math" 13 | "sync" 14 | 15 | _ "crypto/sha1" 16 | _ "crypto/sha256" 17 | _ "crypto/sha512" 18 | ) 19 | 20 | // These are string constants in the SSH protocol. 21 | const ( 22 | compressionNone = "none" 23 | serviceUserAuth = "ssh-userauth" 24 | serviceSSH = "ssh-connection" 25 | ) 26 | 27 | // supportedCiphers lists ciphers we support but might not recommend. 28 | var supportedCiphers = []string{ 29 | "aes128-ctr", "aes192-ctr", "aes256-ctr", 30 | "aes128-gcm@openssh.com", 31 | chacha20Poly1305ID, 32 | "arcfour256", "arcfour128", "arcfour", 33 | aes128cbcID, 34 | tripledescbcID, 35 | } 36 | 37 | // preferredCiphers specifies the default preference for ciphers. 38 | var preferredCiphers = []string{ 39 | "aes128-gcm@openssh.com", 40 | chacha20Poly1305ID, 41 | "aes128-ctr", "aes192-ctr", "aes256-ctr", 42 | } 43 | 44 | // supportedKexAlgos specifies the supported key-exchange algorithms in 45 | // preference order. 46 | var supportedKexAlgos = []string{ 47 | kexAlgoCurve25519SHA256, 48 | // P384 and P521 are not constant-time yet, but since we don't 49 | // reuse ephemeral keys, using them for ECDH should be OK. 50 | kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, 51 | kexAlgoDH14SHA1, kexAlgoDH1SHA1, 52 | } 53 | 54 | // supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods 55 | // of authenticating servers) in preference order. 56 | var supportedHostKeyAlgos = []string{ 57 | CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, 58 | CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, 59 | 60 | KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, 61 | KeyAlgoRSA, KeyAlgoDSA, 62 | 63 | KeyAlgoED25519, 64 | } 65 | 66 | // supportedMACs specifies a default set of MAC algorithms in preference order. 67 | // This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed 68 | // because they have reached the end of their useful life. 69 | var supportedMACs = []string{ 70 | "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96", 71 | } 72 | 73 | var supportedCompressions = []string{compressionNone} 74 | 75 | // hashFuncs keeps the mapping of supported algorithms to their respective 76 | // hashes needed for signature verification. 77 | var hashFuncs = map[string]crypto.Hash{ 78 | KeyAlgoRSA: crypto.SHA1, 79 | KeyAlgoDSA: crypto.SHA1, 80 | KeyAlgoECDSA256: crypto.SHA256, 81 | KeyAlgoECDSA384: crypto.SHA384, 82 | KeyAlgoECDSA521: crypto.SHA512, 83 | CertAlgoRSAv01: crypto.SHA1, 84 | CertAlgoDSAv01: crypto.SHA1, 85 | CertAlgoECDSA256v01: crypto.SHA256, 86 | CertAlgoECDSA384v01: crypto.SHA384, 87 | CertAlgoECDSA521v01: crypto.SHA512, 88 | } 89 | 90 | // unexpectedMessageError results when the SSH message that we received didn't 91 | // match what we wanted. 92 | func unexpectedMessageError(expected, got uint8) error { 93 | return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected) 94 | } 95 | 96 | // parseError results from a malformed SSH message. 97 | func parseError(tag uint8) error { 98 | return fmt.Errorf("ssh: parse error in message type %d", tag) 99 | } 100 | 101 | func findCommon(what string, client []string, server []string) (common string, err error) { 102 | for _, c := range client { 103 | for _, s := range server { 104 | if c == s { 105 | return c, nil 106 | } 107 | } 108 | } 109 | return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) 110 | } 111 | 112 | type directionAlgorithms struct { 113 | Cipher string 114 | MAC string 115 | Compression string 116 | } 117 | 118 | // rekeyBytes returns a rekeying intervals in bytes. 119 | func (a *directionAlgorithms) rekeyBytes() int64 { 120 | // According to RFC4344 block ciphers should rekey after 121 | // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is 122 | // 128. 123 | switch a.Cipher { 124 | case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID: 125 | return 16 * (1 << 32) 126 | 127 | } 128 | 129 | // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data. 130 | return 1 << 30 131 | } 132 | 133 | type algorithms struct { 134 | kex string 135 | hostKey string 136 | w directionAlgorithms 137 | r directionAlgorithms 138 | } 139 | 140 | func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { 141 | result := &algorithms{} 142 | 143 | result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) 144 | if err != nil { 145 | return 146 | } 147 | 148 | result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) 149 | if err != nil { 150 | return 151 | } 152 | 153 | result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) 154 | if err != nil { 155 | return 156 | } 157 | 158 | result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) 159 | if err != nil { 160 | return 161 | } 162 | 163 | result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) 164 | if err != nil { 165 | return 166 | } 167 | 168 | result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) 169 | if err != nil { 170 | return 171 | } 172 | 173 | result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) 174 | if err != nil { 175 | return 176 | } 177 | 178 | result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) 179 | if err != nil { 180 | return 181 | } 182 | 183 | return result, nil 184 | } 185 | 186 | // If rekeythreshold is too small, we can't make any progress sending 187 | // stuff. 188 | const minRekeyThreshold uint64 = 256 189 | 190 | // Config contains configuration data common to both ServerConfig and 191 | // ClientConfig. 192 | type Config struct { 193 | // Rand provides the source of entropy for cryptographic 194 | // primitives. If Rand is nil, the cryptographic random reader 195 | // in package crypto/rand will be used. 196 | Rand io.Reader 197 | 198 | // The maximum number of bytes sent or received after which a 199 | // new key is negotiated. It must be at least 256. If 200 | // unspecified, a size suitable for the chosen cipher is used. 201 | RekeyThreshold uint64 202 | 203 | // The allowed key exchanges algorithms. If unspecified then a 204 | // default set of algorithms is used. 205 | KeyExchanges []string 206 | 207 | // The allowed cipher algorithms. If unspecified then a sensible 208 | // default is used. 209 | Ciphers []string 210 | 211 | // The allowed MAC algorithms. If unspecified then a sensible default 212 | // is used. 213 | MACs []string 214 | } 215 | 216 | // SetDefaults sets sensible values for unset fields in config. This is 217 | // exported for testing: Configs passed to SSH functions are copied and have 218 | // default values set automatically. 219 | func (c *Config) SetDefaults() { 220 | if c.Rand == nil { 221 | c.Rand = rand.Reader 222 | } 223 | if c.Ciphers == nil { 224 | c.Ciphers = preferredCiphers 225 | } 226 | var ciphers []string 227 | for _, c := range c.Ciphers { 228 | if cipherModes[c] != nil { 229 | // reject the cipher if we have no cipherModes definition 230 | ciphers = append(ciphers, c) 231 | } 232 | } 233 | c.Ciphers = ciphers 234 | 235 | if c.KeyExchanges == nil { 236 | c.KeyExchanges = supportedKexAlgos 237 | } 238 | 239 | if c.MACs == nil { 240 | c.MACs = supportedMACs 241 | } 242 | 243 | if c.RekeyThreshold == 0 { 244 | // cipher specific default 245 | } else if c.RekeyThreshold < minRekeyThreshold { 246 | c.RekeyThreshold = minRekeyThreshold 247 | } else if c.RekeyThreshold >= math.MaxInt64 { 248 | // Avoid weirdness if somebody uses -1 as a threshold. 249 | c.RekeyThreshold = math.MaxInt64 250 | } 251 | } 252 | 253 | // buildDataSignedForAuth returns the data that is signed in order to prove 254 | // possession of a private key. See RFC 4252, section 7. 255 | func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { 256 | data := struct { 257 | Session []byte 258 | Type byte 259 | User string 260 | Service string 261 | Method string 262 | Sign bool 263 | Algo []byte 264 | PubKey []byte 265 | }{ 266 | sessionID, 267 | msgUserAuthRequest, 268 | req.User, 269 | req.Service, 270 | req.Method, 271 | true, 272 | algo, 273 | pubKey, 274 | } 275 | return Marshal(data) 276 | } 277 | 278 | func appendU16(buf []byte, n uint16) []byte { 279 | return append(buf, byte(n>>8), byte(n)) 280 | } 281 | 282 | func appendU32(buf []byte, n uint32) []byte { 283 | return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) 284 | } 285 | 286 | func appendU64(buf []byte, n uint64) []byte { 287 | return append(buf, 288 | byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), 289 | byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) 290 | } 291 | 292 | func appendInt(buf []byte, n int) []byte { 293 | return appendU32(buf, uint32(n)) 294 | } 295 | 296 | func appendString(buf []byte, s string) []byte { 297 | buf = appendU32(buf, uint32(len(s))) 298 | buf = append(buf, s...) 299 | return buf 300 | } 301 | 302 | func appendBool(buf []byte, b bool) []byte { 303 | if b { 304 | return append(buf, 1) 305 | } 306 | return append(buf, 0) 307 | } 308 | 309 | // newCond is a helper to hide the fact that there is no usable zero 310 | // value for sync.Cond. 311 | func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } 312 | 313 | // window represents the buffer available to clients 314 | // wishing to write to a channel. 315 | type window struct { 316 | *sync.Cond 317 | win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 318 | writeWaiters int 319 | closed bool 320 | } 321 | 322 | // add adds win to the amount of window available 323 | // for consumers. 324 | func (w *window) add(win uint32) bool { 325 | // a zero sized window adjust is a noop. 326 | if win == 0 { 327 | return true 328 | } 329 | w.L.Lock() 330 | if w.win+win < win { 331 | w.L.Unlock() 332 | return false 333 | } 334 | w.win += win 335 | // It is unusual that multiple goroutines would be attempting to reserve 336 | // window space, but not guaranteed. Use broadcast to notify all waiters 337 | // that additional window is available. 338 | w.Broadcast() 339 | w.L.Unlock() 340 | return true 341 | } 342 | 343 | // close sets the window to closed, so all reservations fail 344 | // immediately. 345 | func (w *window) close() { 346 | w.L.Lock() 347 | w.closed = true 348 | w.Broadcast() 349 | w.L.Unlock() 350 | } 351 | 352 | // reserve reserves win from the available window capacity. 353 | // If no capacity remains, reserve will block. reserve may 354 | // return less than requested. 355 | func (w *window) reserve(win uint32) (uint32, error) { 356 | var err error 357 | w.L.Lock() 358 | w.writeWaiters++ 359 | w.Broadcast() 360 | for w.win == 0 && !w.closed { 361 | w.Wait() 362 | } 363 | w.writeWaiters-- 364 | if w.win < win { 365 | win = w.win 366 | } 367 | w.win -= win 368 | if w.closed { 369 | err = io.EOF 370 | } 371 | w.L.Unlock() 372 | return win, err 373 | } 374 | 375 | // waitWriterBlocked waits until some goroutine is blocked for further 376 | // writes. It is used in tests only. 377 | func (w *window) waitWriterBlocked() { 378 | w.Cond.L.Lock() 379 | for w.writeWaiters == 0 { 380 | w.Cond.Wait() 381 | } 382 | w.Cond.L.Unlock() 383 | } 384 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/connection.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "fmt" 9 | "net" 10 | ) 11 | 12 | // OpenChannelError is returned if the other side rejects an 13 | // OpenChannel request. 14 | type OpenChannelError struct { 15 | Reason RejectionReason 16 | Message string 17 | } 18 | 19 | func (e *OpenChannelError) Error() string { 20 | return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) 21 | } 22 | 23 | // ConnMetadata holds metadata for the connection. 24 | type ConnMetadata interface { 25 | // User returns the user ID for this connection. 26 | User() string 27 | 28 | // SessionID returns the session hash, also denoted by H. 29 | SessionID() []byte 30 | 31 | // ClientVersion returns the client's version string as hashed 32 | // into the session ID. 33 | ClientVersion() []byte 34 | 35 | // ServerVersion returns the server's version string as hashed 36 | // into the session ID. 37 | ServerVersion() []byte 38 | 39 | // RemoteAddr returns the remote address for this connection. 40 | RemoteAddr() net.Addr 41 | 42 | // LocalAddr returns the local address for this connection. 43 | LocalAddr() net.Addr 44 | } 45 | 46 | // Conn represents an SSH connection for both server and client roles. 47 | // Conn is the basis for implementing an application layer, such 48 | // as ClientConn, which implements the traditional shell access for 49 | // clients. 50 | type Conn interface { 51 | ConnMetadata 52 | 53 | // SendRequest sends a global request, and returns the 54 | // reply. If wantReply is true, it returns the response status 55 | // and payload. See also RFC4254, section 4. 56 | SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) 57 | 58 | // OpenChannel tries to open an channel. If the request is 59 | // rejected, it returns *OpenChannelError. On success it returns 60 | // the SSH Channel and a Go channel for incoming, out-of-band 61 | // requests. The Go channel must be serviced, or the 62 | // connection will hang. 63 | OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) 64 | 65 | // Close closes the underlying network connection 66 | Close() error 67 | 68 | // Wait blocks until the connection has shut down, and returns the 69 | // error causing the shutdown. 70 | Wait() error 71 | 72 | // TODO(hanwen): consider exposing: 73 | // RequestKeyChange 74 | // Disconnect 75 | } 76 | 77 | // DiscardRequests consumes and rejects all requests from the 78 | // passed-in channel. 79 | func DiscardRequests(in <-chan *Request) { 80 | for req := range in { 81 | if req.WantReply { 82 | req.Reply(false, nil) 83 | } 84 | } 85 | } 86 | 87 | // A connection represents an incoming connection. 88 | type connection struct { 89 | transport *handshakeTransport 90 | sshConn 91 | 92 | // The connection protocol. 93 | *mux 94 | } 95 | 96 | func (c *connection) Close() error { 97 | return c.sshConn.conn.Close() 98 | } 99 | 100 | // sshconn provides net.Conn metadata, but disallows direct reads and 101 | // writes. 102 | type sshConn struct { 103 | conn net.Conn 104 | 105 | user string 106 | sessionID []byte 107 | clientVersion []byte 108 | serverVersion []byte 109 | } 110 | 111 | func dup(src []byte) []byte { 112 | dst := make([]byte, len(src)) 113 | copy(dst, src) 114 | return dst 115 | } 116 | 117 | func (c *sshConn) User() string { 118 | return c.user 119 | } 120 | 121 | func (c *sshConn) RemoteAddr() net.Addr { 122 | return c.conn.RemoteAddr() 123 | } 124 | 125 | func (c *sshConn) Close() error { 126 | return c.conn.Close() 127 | } 128 | 129 | func (c *sshConn) LocalAddr() net.Addr { 130 | return c.conn.LocalAddr() 131 | } 132 | 133 | func (c *sshConn) SessionID() []byte { 134 | return dup(c.sessionID) 135 | } 136 | 137 | func (c *sshConn) ClientVersion() []byte { 138 | return dup(c.clientVersion) 139 | } 140 | 141 | func (c *sshConn) ServerVersion() []byte { 142 | return dup(c.serverVersion) 143 | } 144 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package ssh implements an SSH client and server. 7 | 8 | SSH is a transport security protocol, an authentication protocol and a 9 | family of application protocols. The most typical application level 10 | protocol is a remote shell and this is specifically implemented. However, 11 | the multiplexed nature of SSH is exposed to users that wish to support 12 | others. 13 | 14 | References: 15 | [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD 16 | [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 17 | 18 | This package does not fall under the stability promise of the Go language itself, 19 | so its API may be changed when pressing needs arise. 20 | */ 21 | package ssh // import "golang.org/x/crypto/ssh" 22 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/kex.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "crypto" 9 | "crypto/ecdsa" 10 | "crypto/elliptic" 11 | "crypto/rand" 12 | "crypto/subtle" 13 | "errors" 14 | "io" 15 | "math/big" 16 | 17 | "golang.org/x/crypto/curve25519" 18 | ) 19 | 20 | const ( 21 | kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" 22 | kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" 23 | kexAlgoECDH256 = "ecdh-sha2-nistp256" 24 | kexAlgoECDH384 = "ecdh-sha2-nistp384" 25 | kexAlgoECDH521 = "ecdh-sha2-nistp521" 26 | kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" 27 | ) 28 | 29 | // kexResult captures the outcome of a key exchange. 30 | type kexResult struct { 31 | // Session hash. See also RFC 4253, section 8. 32 | H []byte 33 | 34 | // Shared secret. See also RFC 4253, section 8. 35 | K []byte 36 | 37 | // Host key as hashed into H. 38 | HostKey []byte 39 | 40 | // Signature of H. 41 | Signature []byte 42 | 43 | // A cryptographic hash function that matches the security 44 | // level of the key exchange algorithm. It is used for 45 | // calculating H, and for deriving keys from H and K. 46 | Hash crypto.Hash 47 | 48 | // The session ID, which is the first H computed. This is used 49 | // to derive key material inside the transport. 50 | SessionID []byte 51 | } 52 | 53 | // handshakeMagics contains data that is always included in the 54 | // session hash. 55 | type handshakeMagics struct { 56 | clientVersion, serverVersion []byte 57 | clientKexInit, serverKexInit []byte 58 | } 59 | 60 | func (m *handshakeMagics) write(w io.Writer) { 61 | writeString(w, m.clientVersion) 62 | writeString(w, m.serverVersion) 63 | writeString(w, m.clientKexInit) 64 | writeString(w, m.serverKexInit) 65 | } 66 | 67 | // kexAlgorithm abstracts different key exchange algorithms. 68 | type kexAlgorithm interface { 69 | // Server runs server-side key agreement, signing the result 70 | // with a hostkey. 71 | Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error) 72 | 73 | // Client runs the client-side key agreement. Caller is 74 | // responsible for verifying the host key signature. 75 | Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) 76 | } 77 | 78 | // dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. 79 | type dhGroup struct { 80 | g, p, pMinus1 *big.Int 81 | } 82 | 83 | func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { 84 | if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 { 85 | return nil, errors.New("ssh: DH parameter out of bounds") 86 | } 87 | return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil 88 | } 89 | 90 | func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { 91 | hashFunc := crypto.SHA1 92 | 93 | var x *big.Int 94 | for { 95 | var err error 96 | if x, err = rand.Int(randSource, group.pMinus1); err != nil { 97 | return nil, err 98 | } 99 | if x.Sign() > 0 { 100 | break 101 | } 102 | } 103 | 104 | X := new(big.Int).Exp(group.g, x, group.p) 105 | kexDHInit := kexDHInitMsg{ 106 | X: X, 107 | } 108 | if err := c.writePacket(Marshal(&kexDHInit)); err != nil { 109 | return nil, err 110 | } 111 | 112 | packet, err := c.readPacket() 113 | if err != nil { 114 | return nil, err 115 | } 116 | 117 | var kexDHReply kexDHReplyMsg 118 | if err = Unmarshal(packet, &kexDHReply); err != nil { 119 | return nil, err 120 | } 121 | 122 | ki, err := group.diffieHellman(kexDHReply.Y, x) 123 | if err != nil { 124 | return nil, err 125 | } 126 | 127 | h := hashFunc.New() 128 | magics.write(h) 129 | writeString(h, kexDHReply.HostKey) 130 | writeInt(h, X) 131 | writeInt(h, kexDHReply.Y) 132 | K := make([]byte, intLength(ki)) 133 | marshalInt(K, ki) 134 | h.Write(K) 135 | 136 | return &kexResult{ 137 | H: h.Sum(nil), 138 | K: K, 139 | HostKey: kexDHReply.HostKey, 140 | Signature: kexDHReply.Signature, 141 | Hash: crypto.SHA1, 142 | }, nil 143 | } 144 | 145 | func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { 146 | hashFunc := crypto.SHA1 147 | packet, err := c.readPacket() 148 | if err != nil { 149 | return 150 | } 151 | var kexDHInit kexDHInitMsg 152 | if err = Unmarshal(packet, &kexDHInit); err != nil { 153 | return 154 | } 155 | 156 | var y *big.Int 157 | for { 158 | if y, err = rand.Int(randSource, group.pMinus1); err != nil { 159 | return 160 | } 161 | if y.Sign() > 0 { 162 | break 163 | } 164 | } 165 | 166 | Y := new(big.Int).Exp(group.g, y, group.p) 167 | ki, err := group.diffieHellman(kexDHInit.X, y) 168 | if err != nil { 169 | return nil, err 170 | } 171 | 172 | hostKeyBytes := priv.PublicKey().Marshal() 173 | 174 | h := hashFunc.New() 175 | magics.write(h) 176 | writeString(h, hostKeyBytes) 177 | writeInt(h, kexDHInit.X) 178 | writeInt(h, Y) 179 | 180 | K := make([]byte, intLength(ki)) 181 | marshalInt(K, ki) 182 | h.Write(K) 183 | 184 | H := h.Sum(nil) 185 | 186 | // H is already a hash, but the hostkey signing will apply its 187 | // own key-specific hash algorithm. 188 | sig, err := signAndMarshal(priv, randSource, H) 189 | if err != nil { 190 | return nil, err 191 | } 192 | 193 | kexDHReply := kexDHReplyMsg{ 194 | HostKey: hostKeyBytes, 195 | Y: Y, 196 | Signature: sig, 197 | } 198 | packet = Marshal(&kexDHReply) 199 | 200 | err = c.writePacket(packet) 201 | return &kexResult{ 202 | H: H, 203 | K: K, 204 | HostKey: hostKeyBytes, 205 | Signature: sig, 206 | Hash: crypto.SHA1, 207 | }, nil 208 | } 209 | 210 | // ecdh performs Elliptic Curve Diffie-Hellman key exchange as 211 | // described in RFC 5656, section 4. 212 | type ecdh struct { 213 | curve elliptic.Curve 214 | } 215 | 216 | func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { 217 | ephKey, err := ecdsa.GenerateKey(kex.curve, rand) 218 | if err != nil { 219 | return nil, err 220 | } 221 | 222 | kexInit := kexECDHInitMsg{ 223 | ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), 224 | } 225 | 226 | serialized := Marshal(&kexInit) 227 | if err := c.writePacket(serialized); err != nil { 228 | return nil, err 229 | } 230 | 231 | packet, err := c.readPacket() 232 | if err != nil { 233 | return nil, err 234 | } 235 | 236 | var reply kexECDHReplyMsg 237 | if err = Unmarshal(packet, &reply); err != nil { 238 | return nil, err 239 | } 240 | 241 | x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey) 242 | if err != nil { 243 | return nil, err 244 | } 245 | 246 | // generate shared secret 247 | secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes()) 248 | 249 | h := ecHash(kex.curve).New() 250 | magics.write(h) 251 | writeString(h, reply.HostKey) 252 | writeString(h, kexInit.ClientPubKey) 253 | writeString(h, reply.EphemeralPubKey) 254 | K := make([]byte, intLength(secret)) 255 | marshalInt(K, secret) 256 | h.Write(K) 257 | 258 | return &kexResult{ 259 | H: h.Sum(nil), 260 | K: K, 261 | HostKey: reply.HostKey, 262 | Signature: reply.Signature, 263 | Hash: ecHash(kex.curve), 264 | }, nil 265 | } 266 | 267 | // unmarshalECKey parses and checks an EC key. 268 | func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) { 269 | x, y = elliptic.Unmarshal(curve, pubkey) 270 | if x == nil { 271 | return nil, nil, errors.New("ssh: elliptic.Unmarshal failure") 272 | } 273 | if !validateECPublicKey(curve, x, y) { 274 | return nil, nil, errors.New("ssh: public key not on curve") 275 | } 276 | return x, y, nil 277 | } 278 | 279 | // validateECPublicKey checks that the point is a valid public key for 280 | // the given curve. See [SEC1], 3.2.2 281 | func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { 282 | if x.Sign() == 0 && y.Sign() == 0 { 283 | return false 284 | } 285 | 286 | if x.Cmp(curve.Params().P) >= 0 { 287 | return false 288 | } 289 | 290 | if y.Cmp(curve.Params().P) >= 0 { 291 | return false 292 | } 293 | 294 | if !curve.IsOnCurve(x, y) { 295 | return false 296 | } 297 | 298 | // We don't check if N * PubKey == 0, since 299 | // 300 | // - the NIST curves have cofactor = 1, so this is implicit. 301 | // (We don't foresee an implementation that supports non NIST 302 | // curves) 303 | // 304 | // - for ephemeral keys, we don't need to worry about small 305 | // subgroup attacks. 306 | return true 307 | } 308 | 309 | func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { 310 | packet, err := c.readPacket() 311 | if err != nil { 312 | return nil, err 313 | } 314 | 315 | var kexECDHInit kexECDHInitMsg 316 | if err = Unmarshal(packet, &kexECDHInit); err != nil { 317 | return nil, err 318 | } 319 | 320 | clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey) 321 | if err != nil { 322 | return nil, err 323 | } 324 | 325 | // We could cache this key across multiple users/multiple 326 | // connection attempts, but the benefit is small. OpenSSH 327 | // generates a new key for each incoming connection. 328 | ephKey, err := ecdsa.GenerateKey(kex.curve, rand) 329 | if err != nil { 330 | return nil, err 331 | } 332 | 333 | hostKeyBytes := priv.PublicKey().Marshal() 334 | 335 | serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) 336 | 337 | // generate shared secret 338 | secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) 339 | 340 | h := ecHash(kex.curve).New() 341 | magics.write(h) 342 | writeString(h, hostKeyBytes) 343 | writeString(h, kexECDHInit.ClientPubKey) 344 | writeString(h, serializedEphKey) 345 | 346 | K := make([]byte, intLength(secret)) 347 | marshalInt(K, secret) 348 | h.Write(K) 349 | 350 | H := h.Sum(nil) 351 | 352 | // H is already a hash, but the hostkey signing will apply its 353 | // own key-specific hash algorithm. 354 | sig, err := signAndMarshal(priv, rand, H) 355 | if err != nil { 356 | return nil, err 357 | } 358 | 359 | reply := kexECDHReplyMsg{ 360 | EphemeralPubKey: serializedEphKey, 361 | HostKey: hostKeyBytes, 362 | Signature: sig, 363 | } 364 | 365 | serialized := Marshal(&reply) 366 | if err := c.writePacket(serialized); err != nil { 367 | return nil, err 368 | } 369 | 370 | return &kexResult{ 371 | H: H, 372 | K: K, 373 | HostKey: reply.HostKey, 374 | Signature: sig, 375 | Hash: ecHash(kex.curve), 376 | }, nil 377 | } 378 | 379 | var kexAlgoMap = map[string]kexAlgorithm{} 380 | 381 | func init() { 382 | // This is the group called diffie-hellman-group1-sha1 in RFC 383 | // 4253 and Oakley Group 2 in RFC 2409. 384 | p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) 385 | kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ 386 | g: new(big.Int).SetInt64(2), 387 | p: p, 388 | pMinus1: new(big.Int).Sub(p, bigOne), 389 | } 390 | 391 | // This is the group called diffie-hellman-group14-sha1 in RFC 392 | // 4253 and Oakley Group 14 in RFC 3526. 393 | p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) 394 | 395 | kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ 396 | g: new(big.Int).SetInt64(2), 397 | p: p, 398 | pMinus1: new(big.Int).Sub(p, bigOne), 399 | } 400 | 401 | kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} 402 | kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} 403 | kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} 404 | kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} 405 | } 406 | 407 | // curve25519sha256 implements the curve25519-sha256@libssh.org key 408 | // agreement protocol, as described in 409 | // https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt 410 | type curve25519sha256 struct{} 411 | 412 | type curve25519KeyPair struct { 413 | priv [32]byte 414 | pub [32]byte 415 | } 416 | 417 | func (kp *curve25519KeyPair) generate(rand io.Reader) error { 418 | if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { 419 | return err 420 | } 421 | curve25519.ScalarBaseMult(&kp.pub, &kp.priv) 422 | return nil 423 | } 424 | 425 | // curve25519Zeros is just an array of 32 zero bytes so that we have something 426 | // convenient to compare against in order to reject curve25519 points with the 427 | // wrong order. 428 | var curve25519Zeros [32]byte 429 | 430 | func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { 431 | var kp curve25519KeyPair 432 | if err := kp.generate(rand); err != nil { 433 | return nil, err 434 | } 435 | if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil { 436 | return nil, err 437 | } 438 | 439 | packet, err := c.readPacket() 440 | if err != nil { 441 | return nil, err 442 | } 443 | 444 | var reply kexECDHReplyMsg 445 | if err = Unmarshal(packet, &reply); err != nil { 446 | return nil, err 447 | } 448 | if len(reply.EphemeralPubKey) != 32 { 449 | return nil, errors.New("ssh: peer's curve25519 public value has wrong length") 450 | } 451 | 452 | var servPub, secret [32]byte 453 | copy(servPub[:], reply.EphemeralPubKey) 454 | curve25519.ScalarMult(&secret, &kp.priv, &servPub) 455 | if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { 456 | return nil, errors.New("ssh: peer's curve25519 public value has wrong order") 457 | } 458 | 459 | h := crypto.SHA256.New() 460 | magics.write(h) 461 | writeString(h, reply.HostKey) 462 | writeString(h, kp.pub[:]) 463 | writeString(h, reply.EphemeralPubKey) 464 | 465 | ki := new(big.Int).SetBytes(secret[:]) 466 | K := make([]byte, intLength(ki)) 467 | marshalInt(K, ki) 468 | h.Write(K) 469 | 470 | return &kexResult{ 471 | H: h.Sum(nil), 472 | K: K, 473 | HostKey: reply.HostKey, 474 | Signature: reply.Signature, 475 | Hash: crypto.SHA256, 476 | }, nil 477 | } 478 | 479 | func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { 480 | packet, err := c.readPacket() 481 | if err != nil { 482 | return 483 | } 484 | var kexInit kexECDHInitMsg 485 | if err = Unmarshal(packet, &kexInit); err != nil { 486 | return 487 | } 488 | 489 | if len(kexInit.ClientPubKey) != 32 { 490 | return nil, errors.New("ssh: peer's curve25519 public value has wrong length") 491 | } 492 | 493 | var kp curve25519KeyPair 494 | if err := kp.generate(rand); err != nil { 495 | return nil, err 496 | } 497 | 498 | var clientPub, secret [32]byte 499 | copy(clientPub[:], kexInit.ClientPubKey) 500 | curve25519.ScalarMult(&secret, &kp.priv, &clientPub) 501 | if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { 502 | return nil, errors.New("ssh: peer's curve25519 public value has wrong order") 503 | } 504 | 505 | hostKeyBytes := priv.PublicKey().Marshal() 506 | 507 | h := crypto.SHA256.New() 508 | magics.write(h) 509 | writeString(h, hostKeyBytes) 510 | writeString(h, kexInit.ClientPubKey) 511 | writeString(h, kp.pub[:]) 512 | 513 | ki := new(big.Int).SetBytes(secret[:]) 514 | K := make([]byte, intLength(ki)) 515 | marshalInt(K, ki) 516 | h.Write(K) 517 | 518 | H := h.Sum(nil) 519 | 520 | sig, err := signAndMarshal(priv, rand, H) 521 | if err != nil { 522 | return nil, err 523 | } 524 | 525 | reply := kexECDHReplyMsg{ 526 | EphemeralPubKey: kp.pub[:], 527 | HostKey: hostKeyBytes, 528 | Signature: sig, 529 | } 530 | if err := c.writePacket(Marshal(&reply)); err != nil { 531 | return nil, err 532 | } 533 | return &kexResult{ 534 | H: H, 535 | K: K, 536 | HostKey: hostKeyBytes, 537 | Signature: sig, 538 | Hash: crypto.SHA256, 539 | }, nil 540 | } 541 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/mac.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | // Message authentication support 8 | 9 | import ( 10 | "crypto/hmac" 11 | "crypto/sha1" 12 | "crypto/sha256" 13 | "hash" 14 | ) 15 | 16 | type macMode struct { 17 | keySize int 18 | etm bool 19 | new func(key []byte) hash.Hash 20 | } 21 | 22 | // truncatingMAC wraps around a hash.Hash and truncates the output digest to 23 | // a given size. 24 | type truncatingMAC struct { 25 | length int 26 | hmac hash.Hash 27 | } 28 | 29 | func (t truncatingMAC) Write(data []byte) (int, error) { 30 | return t.hmac.Write(data) 31 | } 32 | 33 | func (t truncatingMAC) Sum(in []byte) []byte { 34 | out := t.hmac.Sum(in) 35 | return out[:len(in)+t.length] 36 | } 37 | 38 | func (t truncatingMAC) Reset() { 39 | t.hmac.Reset() 40 | } 41 | 42 | func (t truncatingMAC) Size() int { 43 | return t.length 44 | } 45 | 46 | func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } 47 | 48 | var macModes = map[string]*macMode{ 49 | "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash { 50 | return hmac.New(sha256.New, key) 51 | }}, 52 | "hmac-sha2-256": {32, false, func(key []byte) hash.Hash { 53 | return hmac.New(sha256.New, key) 54 | }}, 55 | "hmac-sha1": {20, false, func(key []byte) hash.Hash { 56 | return hmac.New(sha1.New, key) 57 | }}, 58 | "hmac-sha1-96": {20, false, func(key []byte) hash.Hash { 59 | return truncatingMAC{12, hmac.New(sha1.New, key)} 60 | }}, 61 | } 62 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/mux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "encoding/binary" 9 | "fmt" 10 | "io" 11 | "log" 12 | "sync" 13 | "sync/atomic" 14 | ) 15 | 16 | // debugMux, if set, causes messages in the connection protocol to be 17 | // logged. 18 | const debugMux = false 19 | 20 | // chanList is a thread safe channel list. 21 | type chanList struct { 22 | // protects concurrent access to chans 23 | sync.Mutex 24 | 25 | // chans are indexed by the local id of the channel, which the 26 | // other side should send in the PeersId field. 27 | chans []*channel 28 | 29 | // This is a debugging aid: it offsets all IDs by this 30 | // amount. This helps distinguish otherwise identical 31 | // server/client muxes 32 | offset uint32 33 | } 34 | 35 | // Assigns a channel ID to the given channel. 36 | func (c *chanList) add(ch *channel) uint32 { 37 | c.Lock() 38 | defer c.Unlock() 39 | for i := range c.chans { 40 | if c.chans[i] == nil { 41 | c.chans[i] = ch 42 | return uint32(i) + c.offset 43 | } 44 | } 45 | c.chans = append(c.chans, ch) 46 | return uint32(len(c.chans)-1) + c.offset 47 | } 48 | 49 | // getChan returns the channel for the given ID. 50 | func (c *chanList) getChan(id uint32) *channel { 51 | id -= c.offset 52 | 53 | c.Lock() 54 | defer c.Unlock() 55 | if id < uint32(len(c.chans)) { 56 | return c.chans[id] 57 | } 58 | return nil 59 | } 60 | 61 | func (c *chanList) remove(id uint32) { 62 | id -= c.offset 63 | c.Lock() 64 | if id < uint32(len(c.chans)) { 65 | c.chans[id] = nil 66 | } 67 | c.Unlock() 68 | } 69 | 70 | // dropAll forgets all channels it knows, returning them in a slice. 71 | func (c *chanList) dropAll() []*channel { 72 | c.Lock() 73 | defer c.Unlock() 74 | var r []*channel 75 | 76 | for _, ch := range c.chans { 77 | if ch == nil { 78 | continue 79 | } 80 | r = append(r, ch) 81 | } 82 | c.chans = nil 83 | return r 84 | } 85 | 86 | // mux represents the state for the SSH connection protocol, which 87 | // multiplexes many channels onto a single packet transport. 88 | type mux struct { 89 | conn packetConn 90 | chanList chanList 91 | 92 | incomingChannels chan NewChannel 93 | 94 | globalSentMu sync.Mutex 95 | globalResponses chan interface{} 96 | incomingRequests chan *Request 97 | 98 | errCond *sync.Cond 99 | err error 100 | } 101 | 102 | // When debugging, each new chanList instantiation has a different 103 | // offset. 104 | var globalOff uint32 105 | 106 | func (m *mux) Wait() error { 107 | m.errCond.L.Lock() 108 | defer m.errCond.L.Unlock() 109 | for m.err == nil { 110 | m.errCond.Wait() 111 | } 112 | return m.err 113 | } 114 | 115 | // newMux returns a mux that runs over the given connection. 116 | func newMux(p packetConn) *mux { 117 | m := &mux{ 118 | conn: p, 119 | incomingChannels: make(chan NewChannel, chanSize), 120 | globalResponses: make(chan interface{}, 1), 121 | incomingRequests: make(chan *Request, chanSize), 122 | errCond: newCond(), 123 | } 124 | if debugMux { 125 | m.chanList.offset = atomic.AddUint32(&globalOff, 1) 126 | } 127 | 128 | go m.loop() 129 | return m 130 | } 131 | 132 | func (m *mux) sendMessage(msg interface{}) error { 133 | p := Marshal(msg) 134 | if debugMux { 135 | log.Printf("send global(%d): %#v", m.chanList.offset, msg) 136 | } 137 | return m.conn.writePacket(p) 138 | } 139 | 140 | func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { 141 | if wantReply { 142 | m.globalSentMu.Lock() 143 | defer m.globalSentMu.Unlock() 144 | } 145 | 146 | if err := m.sendMessage(globalRequestMsg{ 147 | Type: name, 148 | WantReply: wantReply, 149 | Data: payload, 150 | }); err != nil { 151 | return false, nil, err 152 | } 153 | 154 | if !wantReply { 155 | return false, nil, nil 156 | } 157 | 158 | msg, ok := <-m.globalResponses 159 | if !ok { 160 | return false, nil, io.EOF 161 | } 162 | switch msg := msg.(type) { 163 | case *globalRequestFailureMsg: 164 | return false, msg.Data, nil 165 | case *globalRequestSuccessMsg: 166 | return true, msg.Data, nil 167 | default: 168 | return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg) 169 | } 170 | } 171 | 172 | // ackRequest must be called after processing a global request that 173 | // has WantReply set. 174 | func (m *mux) ackRequest(ok bool, data []byte) error { 175 | if ok { 176 | return m.sendMessage(globalRequestSuccessMsg{Data: data}) 177 | } 178 | return m.sendMessage(globalRequestFailureMsg{Data: data}) 179 | } 180 | 181 | func (m *mux) Close() error { 182 | return m.conn.Close() 183 | } 184 | 185 | // loop runs the connection machine. It will process packets until an 186 | // error is encountered. To synchronize on loop exit, use mux.Wait. 187 | func (m *mux) loop() { 188 | var err error 189 | for err == nil { 190 | err = m.onePacket() 191 | } 192 | 193 | for _, ch := range m.chanList.dropAll() { 194 | ch.close() 195 | } 196 | 197 | close(m.incomingChannels) 198 | close(m.incomingRequests) 199 | close(m.globalResponses) 200 | 201 | m.conn.Close() 202 | 203 | m.errCond.L.Lock() 204 | m.err = err 205 | m.errCond.Broadcast() 206 | m.errCond.L.Unlock() 207 | 208 | if debugMux { 209 | log.Println("loop exit", err) 210 | } 211 | } 212 | 213 | // onePacket reads and processes one packet. 214 | func (m *mux) onePacket() error { 215 | packet, err := m.conn.readPacket() 216 | if err != nil { 217 | return err 218 | } 219 | 220 | if debugMux { 221 | if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData { 222 | log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet)) 223 | } else { 224 | p, _ := decode(packet) 225 | log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet)) 226 | } 227 | } 228 | 229 | switch packet[0] { 230 | case msgChannelOpen: 231 | return m.handleChannelOpen(packet) 232 | case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: 233 | return m.handleGlobalPacket(packet) 234 | } 235 | 236 | // assume a channel packet. 237 | if len(packet) < 5 { 238 | return parseError(packet[0]) 239 | } 240 | id := binary.BigEndian.Uint32(packet[1:]) 241 | ch := m.chanList.getChan(id) 242 | if ch == nil { 243 | return fmt.Errorf("ssh: invalid channel %d", id) 244 | } 245 | 246 | return ch.handlePacket(packet) 247 | } 248 | 249 | func (m *mux) handleGlobalPacket(packet []byte) error { 250 | msg, err := decode(packet) 251 | if err != nil { 252 | return err 253 | } 254 | 255 | switch msg := msg.(type) { 256 | case *globalRequestMsg: 257 | m.incomingRequests <- &Request{ 258 | Type: msg.Type, 259 | WantReply: msg.WantReply, 260 | Payload: msg.Data, 261 | mux: m, 262 | } 263 | case *globalRequestSuccessMsg, *globalRequestFailureMsg: 264 | m.globalResponses <- msg 265 | default: 266 | panic(fmt.Sprintf("not a global message %#v", msg)) 267 | } 268 | 269 | return nil 270 | } 271 | 272 | // handleChannelOpen schedules a channel to be Accept()ed. 273 | func (m *mux) handleChannelOpen(packet []byte) error { 274 | var msg channelOpenMsg 275 | if err := Unmarshal(packet, &msg); err != nil { 276 | return err 277 | } 278 | 279 | if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { 280 | failMsg := channelOpenFailureMsg{ 281 | PeersID: msg.PeersID, 282 | Reason: ConnectionFailed, 283 | Message: "invalid request", 284 | Language: "en_US.UTF-8", 285 | } 286 | return m.sendMessage(failMsg) 287 | } 288 | 289 | c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) 290 | c.remoteId = msg.PeersID 291 | c.maxRemotePayload = msg.MaxPacketSize 292 | c.remoteWin.add(msg.PeersWindow) 293 | m.incomingChannels <- c 294 | return nil 295 | } 296 | 297 | func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) { 298 | ch, err := m.openChannel(chanType, extra) 299 | if err != nil { 300 | return nil, nil, err 301 | } 302 | 303 | return ch, ch.incomingRequests, nil 304 | } 305 | 306 | func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { 307 | ch := m.newChannel(chanType, channelOutbound, extra) 308 | 309 | ch.maxIncomingPayload = channelMaxPacket 310 | 311 | open := channelOpenMsg{ 312 | ChanType: chanType, 313 | PeersWindow: ch.myWindow, 314 | MaxPacketSize: ch.maxIncomingPayload, 315 | TypeSpecificData: extra, 316 | PeersID: ch.localId, 317 | } 318 | if err := m.sendMessage(open); err != nil { 319 | return nil, err 320 | } 321 | 322 | switch msg := (<-ch.msg).(type) { 323 | case *channelOpenConfirmMsg: 324 | return ch, nil 325 | case *channelOpenFailureMsg: 326 | return nil, &OpenChannelError{msg.Reason, msg.Message} 327 | default: 328 | return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) 329 | } 330 | } 331 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/streamlocal.go: -------------------------------------------------------------------------------- 1 | package ssh 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "net" 7 | ) 8 | 9 | // streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message 10 | // with "direct-streamlocal@openssh.com" string. 11 | // 12 | // See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding 13 | // https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235 14 | type streamLocalChannelOpenDirectMsg struct { 15 | socketPath string 16 | reserved0 string 17 | reserved1 uint32 18 | } 19 | 20 | // forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message 21 | // with "forwarded-streamlocal@openssh.com" string. 22 | type forwardedStreamLocalPayload struct { 23 | SocketPath string 24 | Reserved0 string 25 | } 26 | 27 | // streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message 28 | // with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string. 29 | type streamLocalChannelForwardMsg struct { 30 | socketPath string 31 | } 32 | 33 | // ListenUnix is similar to ListenTCP but uses a Unix domain socket. 34 | func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { 35 | m := streamLocalChannelForwardMsg{ 36 | socketPath, 37 | } 38 | // send message 39 | ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m)) 40 | if err != nil { 41 | return nil, err 42 | } 43 | if !ok { 44 | return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer") 45 | } 46 | ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"}) 47 | 48 | return &unixListener{socketPath, c, ch}, nil 49 | } 50 | 51 | func (c *Client) dialStreamLocal(socketPath string) (Channel, error) { 52 | msg := streamLocalChannelOpenDirectMsg{ 53 | socketPath: socketPath, 54 | } 55 | ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg)) 56 | if err != nil { 57 | return nil, err 58 | } 59 | go DiscardRequests(in) 60 | return ch, err 61 | } 62 | 63 | type unixListener struct { 64 | socketPath string 65 | 66 | conn *Client 67 | in <-chan forward 68 | } 69 | 70 | // Accept waits for and returns the next connection to the listener. 71 | func (l *unixListener) Accept() (net.Conn, error) { 72 | s, ok := <-l.in 73 | if !ok { 74 | return nil, io.EOF 75 | } 76 | ch, incoming, err := s.newCh.Accept() 77 | if err != nil { 78 | return nil, err 79 | } 80 | go DiscardRequests(incoming) 81 | 82 | return &chanConn{ 83 | Channel: ch, 84 | laddr: &net.UnixAddr{ 85 | Name: l.socketPath, 86 | Net: "unix", 87 | }, 88 | raddr: &net.UnixAddr{ 89 | Name: "@", 90 | Net: "unix", 91 | }, 92 | }, nil 93 | } 94 | 95 | // Close closes the listener. 96 | func (l *unixListener) Close() error { 97 | // this also closes the listener. 98 | l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"}) 99 | m := streamLocalChannelForwardMsg{ 100 | l.socketPath, 101 | } 102 | ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m)) 103 | if err == nil && !ok { 104 | err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed") 105 | } 106 | return err 107 | } 108 | 109 | // Addr returns the listener's network address. 110 | func (l *unixListener) Addr() net.Addr { 111 | return &net.UnixAddr{ 112 | Name: l.socketPath, 113 | Net: "unix", 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/tcpip.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | "io" 11 | "math/rand" 12 | "net" 13 | "strconv" 14 | "strings" 15 | "sync" 16 | "time" 17 | ) 18 | 19 | // Listen requests the remote peer open a listening socket on 20 | // addr. Incoming connections will be available by calling Accept on 21 | // the returned net.Listener. The listener must be serviced, or the 22 | // SSH connection may hang. 23 | // N must be "tcp", "tcp4", "tcp6", or "unix". 24 | func (c *Client) Listen(n, addr string) (net.Listener, error) { 25 | switch n { 26 | case "tcp", "tcp4", "tcp6": 27 | laddr, err := net.ResolveTCPAddr(n, addr) 28 | if err != nil { 29 | return nil, err 30 | } 31 | return c.ListenTCP(laddr) 32 | case "unix": 33 | return c.ListenUnix(addr) 34 | default: 35 | return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) 36 | } 37 | } 38 | 39 | // Automatic port allocation is broken with OpenSSH before 6.0. See 40 | // also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In 41 | // particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0, 42 | // rather than the actual port number. This means you can never open 43 | // two different listeners with auto allocated ports. We work around 44 | // this by trying explicit ports until we succeed. 45 | 46 | const openSSHPrefix = "OpenSSH_" 47 | 48 | var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano())) 49 | 50 | // isBrokenOpenSSHVersion returns true if the given version string 51 | // specifies a version of OpenSSH that is known to have a bug in port 52 | // forwarding. 53 | func isBrokenOpenSSHVersion(versionStr string) bool { 54 | i := strings.Index(versionStr, openSSHPrefix) 55 | if i < 0 { 56 | return false 57 | } 58 | i += len(openSSHPrefix) 59 | j := i 60 | for ; j < len(versionStr); j++ { 61 | if versionStr[j] < '0' || versionStr[j] > '9' { 62 | break 63 | } 64 | } 65 | version, _ := strconv.Atoi(versionStr[i:j]) 66 | return version < 6 67 | } 68 | 69 | // autoPortListenWorkaround simulates automatic port allocation by 70 | // trying random ports repeatedly. 71 | func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) { 72 | var sshListener net.Listener 73 | var err error 74 | const tries = 10 75 | for i := 0; i < tries; i++ { 76 | addr := *laddr 77 | addr.Port = 1024 + portRandomizer.Intn(60000) 78 | sshListener, err = c.ListenTCP(&addr) 79 | if err == nil { 80 | laddr.Port = addr.Port 81 | return sshListener, err 82 | } 83 | } 84 | return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err) 85 | } 86 | 87 | // RFC 4254 7.1 88 | type channelForwardMsg struct { 89 | addr string 90 | rport uint32 91 | } 92 | 93 | // ListenTCP requests the remote peer open a listening socket 94 | // on laddr. Incoming connections will be available by calling 95 | // Accept on the returned net.Listener. 96 | func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { 97 | if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { 98 | return c.autoPortListenWorkaround(laddr) 99 | } 100 | 101 | m := channelForwardMsg{ 102 | laddr.IP.String(), 103 | uint32(laddr.Port), 104 | } 105 | // send message 106 | ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m)) 107 | if err != nil { 108 | return nil, err 109 | } 110 | if !ok { 111 | return nil, errors.New("ssh: tcpip-forward request denied by peer") 112 | } 113 | 114 | // If the original port was 0, then the remote side will 115 | // supply a real port number in the response. 116 | if laddr.Port == 0 { 117 | var p struct { 118 | Port uint32 119 | } 120 | if err := Unmarshal(resp, &p); err != nil { 121 | return nil, err 122 | } 123 | laddr.Port = int(p.Port) 124 | } 125 | 126 | // Register this forward, using the port number we obtained. 127 | ch := c.forwards.add(laddr) 128 | 129 | return &tcpListener{laddr, c, ch}, nil 130 | } 131 | 132 | // forwardList stores a mapping between remote 133 | // forward requests and the tcpListeners. 134 | type forwardList struct { 135 | sync.Mutex 136 | entries []forwardEntry 137 | } 138 | 139 | // forwardEntry represents an established mapping of a laddr on a 140 | // remote ssh server to a channel connected to a tcpListener. 141 | type forwardEntry struct { 142 | laddr net.Addr 143 | c chan forward 144 | } 145 | 146 | // forward represents an incoming forwarded tcpip connection. The 147 | // arguments to add/remove/lookup should be address as specified in 148 | // the original forward-request. 149 | type forward struct { 150 | newCh NewChannel // the ssh client channel underlying this forward 151 | raddr net.Addr // the raddr of the incoming connection 152 | } 153 | 154 | func (l *forwardList) add(addr net.Addr) chan forward { 155 | l.Lock() 156 | defer l.Unlock() 157 | f := forwardEntry{ 158 | laddr: addr, 159 | c: make(chan forward, 1), 160 | } 161 | l.entries = append(l.entries, f) 162 | return f.c 163 | } 164 | 165 | // See RFC 4254, section 7.2 166 | type forwardedTCPPayload struct { 167 | Addr string 168 | Port uint32 169 | OriginAddr string 170 | OriginPort uint32 171 | } 172 | 173 | // parseTCPAddr parses the originating address from the remote into a *net.TCPAddr. 174 | func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) { 175 | if port == 0 || port > 65535 { 176 | return nil, fmt.Errorf("ssh: port number out of range: %d", port) 177 | } 178 | ip := net.ParseIP(string(addr)) 179 | if ip == nil { 180 | return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr) 181 | } 182 | return &net.TCPAddr{IP: ip, Port: int(port)}, nil 183 | } 184 | 185 | func (l *forwardList) handleChannels(in <-chan NewChannel) { 186 | for ch := range in { 187 | var ( 188 | laddr net.Addr 189 | raddr net.Addr 190 | err error 191 | ) 192 | switch channelType := ch.ChannelType(); channelType { 193 | case "forwarded-tcpip": 194 | var payload forwardedTCPPayload 195 | if err = Unmarshal(ch.ExtraData(), &payload); err != nil { 196 | ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error()) 197 | continue 198 | } 199 | 200 | // RFC 4254 section 7.2 specifies that incoming 201 | // addresses should list the address, in string 202 | // format. It is implied that this should be an IP 203 | // address, as it would be impossible to connect to it 204 | // otherwise. 205 | laddr, err = parseTCPAddr(payload.Addr, payload.Port) 206 | if err != nil { 207 | ch.Reject(ConnectionFailed, err.Error()) 208 | continue 209 | } 210 | raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort) 211 | if err != nil { 212 | ch.Reject(ConnectionFailed, err.Error()) 213 | continue 214 | } 215 | 216 | case "forwarded-streamlocal@openssh.com": 217 | var payload forwardedStreamLocalPayload 218 | if err = Unmarshal(ch.ExtraData(), &payload); err != nil { 219 | ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error()) 220 | continue 221 | } 222 | laddr = &net.UnixAddr{ 223 | Name: payload.SocketPath, 224 | Net: "unix", 225 | } 226 | raddr = &net.UnixAddr{ 227 | Name: "@", 228 | Net: "unix", 229 | } 230 | default: 231 | panic(fmt.Errorf("ssh: unknown channel type %s", channelType)) 232 | } 233 | if ok := l.forward(laddr, raddr, ch); !ok { 234 | // Section 7.2, implementations MUST reject spurious incoming 235 | // connections. 236 | ch.Reject(Prohibited, "no forward for address") 237 | continue 238 | } 239 | 240 | } 241 | } 242 | 243 | // remove removes the forward entry, and the channel feeding its 244 | // listener. 245 | func (l *forwardList) remove(addr net.Addr) { 246 | l.Lock() 247 | defer l.Unlock() 248 | for i, f := range l.entries { 249 | if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() { 250 | l.entries = append(l.entries[:i], l.entries[i+1:]...) 251 | close(f.c) 252 | return 253 | } 254 | } 255 | } 256 | 257 | // closeAll closes and clears all forwards. 258 | func (l *forwardList) closeAll() { 259 | l.Lock() 260 | defer l.Unlock() 261 | for _, f := range l.entries { 262 | close(f.c) 263 | } 264 | l.entries = nil 265 | } 266 | 267 | func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool { 268 | l.Lock() 269 | defer l.Unlock() 270 | for _, f := range l.entries { 271 | if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() { 272 | f.c <- forward{newCh: ch, raddr: raddr} 273 | return true 274 | } 275 | } 276 | return false 277 | } 278 | 279 | type tcpListener struct { 280 | laddr *net.TCPAddr 281 | 282 | conn *Client 283 | in <-chan forward 284 | } 285 | 286 | // Accept waits for and returns the next connection to the listener. 287 | func (l *tcpListener) Accept() (net.Conn, error) { 288 | s, ok := <-l.in 289 | if !ok { 290 | return nil, io.EOF 291 | } 292 | ch, incoming, err := s.newCh.Accept() 293 | if err != nil { 294 | return nil, err 295 | } 296 | go DiscardRequests(incoming) 297 | 298 | return &chanConn{ 299 | Channel: ch, 300 | laddr: l.laddr, 301 | raddr: s.raddr, 302 | }, nil 303 | } 304 | 305 | // Close closes the listener. 306 | func (l *tcpListener) Close() error { 307 | m := channelForwardMsg{ 308 | l.laddr.IP.String(), 309 | uint32(l.laddr.Port), 310 | } 311 | 312 | // this also closes the listener. 313 | l.conn.forwards.remove(l.laddr) 314 | ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m)) 315 | if err == nil && !ok { 316 | err = errors.New("ssh: cancel-tcpip-forward failed") 317 | } 318 | return err 319 | } 320 | 321 | // Addr returns the listener's network address. 322 | func (l *tcpListener) Addr() net.Addr { 323 | return l.laddr 324 | } 325 | 326 | // Dial initiates a connection to the addr from the remote host. 327 | // The resulting connection has a zero LocalAddr() and RemoteAddr(). 328 | func (c *Client) Dial(n, addr string) (net.Conn, error) { 329 | var ch Channel 330 | switch n { 331 | case "tcp", "tcp4", "tcp6": 332 | // Parse the address into host and numeric port. 333 | host, portString, err := net.SplitHostPort(addr) 334 | if err != nil { 335 | return nil, err 336 | } 337 | port, err := strconv.ParseUint(portString, 10, 16) 338 | if err != nil { 339 | return nil, err 340 | } 341 | ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port)) 342 | if err != nil { 343 | return nil, err 344 | } 345 | // Use a zero address for local and remote address. 346 | zeroAddr := &net.TCPAddr{ 347 | IP: net.IPv4zero, 348 | Port: 0, 349 | } 350 | return &chanConn{ 351 | Channel: ch, 352 | laddr: zeroAddr, 353 | raddr: zeroAddr, 354 | }, nil 355 | case "unix": 356 | var err error 357 | ch, err = c.dialStreamLocal(addr) 358 | if err != nil { 359 | return nil, err 360 | } 361 | return &chanConn{ 362 | Channel: ch, 363 | laddr: &net.UnixAddr{ 364 | Name: "@", 365 | Net: "unix", 366 | }, 367 | raddr: &net.UnixAddr{ 368 | Name: addr, 369 | Net: "unix", 370 | }, 371 | }, nil 372 | default: 373 | return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) 374 | } 375 | } 376 | 377 | // DialTCP connects to the remote address raddr on the network net, 378 | // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used 379 | // as the local address for the connection. 380 | func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) { 381 | if laddr == nil { 382 | laddr = &net.TCPAddr{ 383 | IP: net.IPv4zero, 384 | Port: 0, 385 | } 386 | } 387 | ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port) 388 | if err != nil { 389 | return nil, err 390 | } 391 | return &chanConn{ 392 | Channel: ch, 393 | laddr: laddr, 394 | raddr: raddr, 395 | }, nil 396 | } 397 | 398 | // RFC 4254 7.2 399 | type channelOpenDirectMsg struct { 400 | raddr string 401 | rport uint32 402 | laddr string 403 | lport uint32 404 | } 405 | 406 | func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) { 407 | msg := channelOpenDirectMsg{ 408 | raddr: raddr, 409 | rport: uint32(rport), 410 | laddr: laddr, 411 | lport: uint32(lport), 412 | } 413 | ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg)) 414 | if err != nil { 415 | return nil, err 416 | } 417 | go DiscardRequests(in) 418 | return ch, err 419 | } 420 | 421 | type tcpChan struct { 422 | Channel // the backing channel 423 | } 424 | 425 | // chanConn fulfills the net.Conn interface without 426 | // the tcpChan having to hold laddr or raddr directly. 427 | type chanConn struct { 428 | Channel 429 | laddr, raddr net.Addr 430 | } 431 | 432 | // LocalAddr returns the local network address. 433 | func (t *chanConn) LocalAddr() net.Addr { 434 | return t.laddr 435 | } 436 | 437 | // RemoteAddr returns the remote network address. 438 | func (t *chanConn) RemoteAddr() net.Addr { 439 | return t.raddr 440 | } 441 | 442 | // SetDeadline sets the read and write deadlines associated 443 | // with the connection. 444 | func (t *chanConn) SetDeadline(deadline time.Time) error { 445 | if err := t.SetReadDeadline(deadline); err != nil { 446 | return err 447 | } 448 | return t.SetWriteDeadline(deadline) 449 | } 450 | 451 | // SetReadDeadline sets the read deadline. 452 | // A zero value for t means Read will not time out. 453 | // After the deadline, the error from Read will implement net.Error 454 | // with Timeout() == true. 455 | func (t *chanConn) SetReadDeadline(deadline time.Time) error { 456 | // for compatibility with previous version, 457 | // the error message contains "tcpChan" 458 | return errors.New("ssh: tcpChan: deadline not supported") 459 | } 460 | 461 | // SetWriteDeadline exists to satisfy the net.Conn interface 462 | // but is not implemented by this type. It always returns an error. 463 | func (t *chanConn) SetWriteDeadline(deadline time.Time) error { 464 | return errors.New("ssh: tcpChan: deadline not supported") 465 | } 466 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/transport.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ssh 6 | 7 | import ( 8 | "bufio" 9 | "bytes" 10 | "errors" 11 | "io" 12 | "log" 13 | ) 14 | 15 | // debugTransport if set, will print packet types as they go over the 16 | // wire. No message decoding is done, to minimize the impact on timing. 17 | const debugTransport = false 18 | 19 | const ( 20 | gcmCipherID = "aes128-gcm@openssh.com" 21 | aes128cbcID = "aes128-cbc" 22 | tripledescbcID = "3des-cbc" 23 | ) 24 | 25 | // packetConn represents a transport that implements packet based 26 | // operations. 27 | type packetConn interface { 28 | // Encrypt and send a packet of data to the remote peer. 29 | writePacket(packet []byte) error 30 | 31 | // Read a packet from the connection. The read is blocking, 32 | // i.e. if error is nil, then the returned byte slice is 33 | // always non-empty. 34 | readPacket() ([]byte, error) 35 | 36 | // Close closes the write-side of the connection. 37 | Close() error 38 | } 39 | 40 | // transport is the keyingTransport that implements the SSH packet 41 | // protocol. 42 | type transport struct { 43 | reader connectionState 44 | writer connectionState 45 | 46 | bufReader *bufio.Reader 47 | bufWriter *bufio.Writer 48 | rand io.Reader 49 | isClient bool 50 | io.Closer 51 | } 52 | 53 | // packetCipher represents a combination of SSH encryption/MAC 54 | // protocol. A single instance should be used for one direction only. 55 | type packetCipher interface { 56 | // writePacket encrypts the packet and writes it to w. The 57 | // contents of the packet are generally scrambled. 58 | writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error 59 | 60 | // readPacket reads and decrypts a packet of data. The 61 | // returned packet may be overwritten by future calls of 62 | // readPacket. 63 | readPacket(seqnum uint32, r io.Reader) ([]byte, error) 64 | } 65 | 66 | // connectionState represents one side (read or write) of the 67 | // connection. This is necessary because each direction has its own 68 | // keys, and can even have its own algorithms 69 | type connectionState struct { 70 | packetCipher 71 | seqNum uint32 72 | dir direction 73 | pendingKeyChange chan packetCipher 74 | } 75 | 76 | // prepareKeyChange sets up key material for a keychange. The key changes in 77 | // both directions are triggered by reading and writing a msgNewKey packet 78 | // respectively. 79 | func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { 80 | ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult) 81 | if err != nil { 82 | return err 83 | } 84 | t.reader.pendingKeyChange <- ciph 85 | 86 | ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult) 87 | if err != nil { 88 | return err 89 | } 90 | t.writer.pendingKeyChange <- ciph 91 | 92 | return nil 93 | } 94 | 95 | func (t *transport) printPacket(p []byte, write bool) { 96 | if len(p) == 0 { 97 | return 98 | } 99 | who := "server" 100 | if t.isClient { 101 | who = "client" 102 | } 103 | what := "read" 104 | if write { 105 | what = "write" 106 | } 107 | 108 | log.Println(what, who, p[0]) 109 | } 110 | 111 | // Read and decrypt next packet. 112 | func (t *transport) readPacket() (p []byte, err error) { 113 | for { 114 | p, err = t.reader.readPacket(t.bufReader) 115 | if err != nil { 116 | break 117 | } 118 | if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) { 119 | break 120 | } 121 | } 122 | if debugTransport { 123 | t.printPacket(p, false) 124 | } 125 | 126 | return p, err 127 | } 128 | 129 | func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { 130 | packet, err := s.packetCipher.readPacket(s.seqNum, r) 131 | s.seqNum++ 132 | if err == nil && len(packet) == 0 { 133 | err = errors.New("ssh: zero length packet") 134 | } 135 | 136 | if len(packet) > 0 { 137 | switch packet[0] { 138 | case msgNewKeys: 139 | select { 140 | case cipher := <-s.pendingKeyChange: 141 | s.packetCipher = cipher 142 | default: 143 | return nil, errors.New("ssh: got bogus newkeys message") 144 | } 145 | 146 | case msgDisconnect: 147 | // Transform a disconnect message into an 148 | // error. Since this is lowest level at which 149 | // we interpret message types, doing it here 150 | // ensures that we don't have to handle it 151 | // elsewhere. 152 | var msg disconnectMsg 153 | if err := Unmarshal(packet, &msg); err != nil { 154 | return nil, err 155 | } 156 | return nil, &msg 157 | } 158 | } 159 | 160 | // The packet may point to an internal buffer, so copy the 161 | // packet out here. 162 | fresh := make([]byte, len(packet)) 163 | copy(fresh, packet) 164 | 165 | return fresh, err 166 | } 167 | 168 | func (t *transport) writePacket(packet []byte) error { 169 | if debugTransport { 170 | t.printPacket(packet, true) 171 | } 172 | return t.writer.writePacket(t.bufWriter, t.rand, packet) 173 | } 174 | 175 | func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { 176 | changeKeys := len(packet) > 0 && packet[0] == msgNewKeys 177 | 178 | err := s.packetCipher.writePacket(s.seqNum, w, rand, packet) 179 | if err != nil { 180 | return err 181 | } 182 | if err = w.Flush(); err != nil { 183 | return err 184 | } 185 | s.seqNum++ 186 | if changeKeys { 187 | select { 188 | case cipher := <-s.pendingKeyChange: 189 | s.packetCipher = cipher 190 | default: 191 | panic("ssh: no key material for msgNewKeys") 192 | } 193 | } 194 | return err 195 | } 196 | 197 | func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport { 198 | t := &transport{ 199 | bufReader: bufio.NewReader(rwc), 200 | bufWriter: bufio.NewWriter(rwc), 201 | rand: rand, 202 | reader: connectionState{ 203 | packetCipher: &streamPacketCipher{cipher: noneCipher{}}, 204 | pendingKeyChange: make(chan packetCipher, 1), 205 | }, 206 | writer: connectionState{ 207 | packetCipher: &streamPacketCipher{cipher: noneCipher{}}, 208 | pendingKeyChange: make(chan packetCipher, 1), 209 | }, 210 | Closer: rwc, 211 | } 212 | t.isClient = isClient 213 | 214 | if isClient { 215 | t.reader.dir = serverKeys 216 | t.writer.dir = clientKeys 217 | } else { 218 | t.reader.dir = clientKeys 219 | t.writer.dir = serverKeys 220 | } 221 | 222 | return t 223 | } 224 | 225 | type direction struct { 226 | ivTag []byte 227 | keyTag []byte 228 | macKeyTag []byte 229 | } 230 | 231 | var ( 232 | serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} 233 | clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} 234 | ) 235 | 236 | // setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as 237 | // described in RFC 4253, section 6.4. direction should either be serverKeys 238 | // (to setup server->client keys) or clientKeys (for client->server keys). 239 | func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { 240 | cipherMode := cipherModes[algs.Cipher] 241 | macMode := macModes[algs.MAC] 242 | 243 | iv := make([]byte, cipherMode.ivSize) 244 | key := make([]byte, cipherMode.keySize) 245 | macKey := make([]byte, macMode.keySize) 246 | 247 | generateKeyMaterial(iv, d.ivTag, kex) 248 | generateKeyMaterial(key, d.keyTag, kex) 249 | generateKeyMaterial(macKey, d.macKeyTag, kex) 250 | 251 | return cipherModes[algs.Cipher].create(key, iv, macKey, algs) 252 | } 253 | 254 | // generateKeyMaterial fills out with key material generated from tag, K, H 255 | // and sessionId, as specified in RFC 4253, section 7.2. 256 | func generateKeyMaterial(out, tag []byte, r *kexResult) { 257 | var digestsSoFar []byte 258 | 259 | h := r.Hash.New() 260 | for len(out) > 0 { 261 | h.Reset() 262 | h.Write(r.K) 263 | h.Write(r.H) 264 | 265 | if len(digestsSoFar) == 0 { 266 | h.Write(tag) 267 | h.Write(r.SessionID) 268 | } else { 269 | h.Write(digestsSoFar) 270 | } 271 | 272 | digest := h.Sum(nil) 273 | n := copy(out, digest) 274 | out = out[n:] 275 | if len(out) > 0 { 276 | digestsSoFar = append(digestsSoFar, digest...) 277 | } 278 | } 279 | } 280 | 281 | const packageVersion = "SSH-2.0-Go" 282 | 283 | // Sends and receives a version line. The versionLine string should 284 | // be US ASCII, start with "SSH-2.0-", and should not include a 285 | // newline. exchangeVersions returns the other side's version line. 286 | func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) { 287 | // Contrary to the RFC, we do not ignore lines that don't 288 | // start with "SSH-2.0-" to make the library usable with 289 | // nonconforming servers. 290 | for _, c := range versionLine { 291 | // The spec disallows non US-ASCII chars, and 292 | // specifically forbids null chars. 293 | if c < 32 { 294 | return nil, errors.New("ssh: junk character in version line") 295 | } 296 | } 297 | if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil { 298 | return 299 | } 300 | 301 | them, err = readVersion(rw) 302 | return them, err 303 | } 304 | 305 | // maxVersionStringBytes is the maximum number of bytes that we'll 306 | // accept as a version string. RFC 4253 section 4.2 limits this at 255 307 | // chars 308 | const maxVersionStringBytes = 255 309 | 310 | // Read version string as specified by RFC 4253, section 4.2. 311 | func readVersion(r io.Reader) ([]byte, error) { 312 | versionString := make([]byte, 0, 64) 313 | var ok bool 314 | var buf [1]byte 315 | 316 | for length := 0; length < maxVersionStringBytes; length++ { 317 | _, err := io.ReadFull(r, buf[:]) 318 | if err != nil { 319 | return nil, err 320 | } 321 | // The RFC says that the version should be terminated with \r\n 322 | // but several SSH servers actually only send a \n. 323 | if buf[0] == '\n' { 324 | if !bytes.HasPrefix(versionString, []byte("SSH-")) { 325 | // RFC 4253 says we need to ignore all version string lines 326 | // except the one containing the SSH version (provided that 327 | // all the lines do not exceed 255 bytes in total). 328 | versionString = versionString[:0] 329 | continue 330 | } 331 | ok = true 332 | break 333 | } 334 | 335 | // non ASCII chars are disallowed, but we are lenient, 336 | // since Go doesn't use null-terminated strings. 337 | 338 | // The RFC allows a comment after a space, however, 339 | // all of it (version and comments) goes into the 340 | // session hash. 341 | versionString = append(versionString, buf[0]) 342 | } 343 | 344 | if !ok { 345 | return nil, errors.New("ssh: overflow reading version string") 346 | } 347 | 348 | // There might be a '\r' on the end which we should remove. 349 | if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { 350 | versionString = versionString[:len(versionString)-1] 351 | } 352 | return versionString, nil 353 | } 354 | --------------------------------------------------------------------------------