add letsencrypt to Gitea (#4189)
This commit is contained in:
6
Gopkg.lock
generated
6
Gopkg.lock
generated
@ -563,14 +563,18 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = [
|
packages = [
|
||||||
|
"acme",
|
||||||
|
"acme/autocert",
|
||||||
"curve25519",
|
"curve25519",
|
||||||
"ed25519",
|
"ed25519",
|
||||||
"ed25519/internal/edwards25519",
|
"ed25519/internal/edwards25519",
|
||||||
|
"internal/chacha20",
|
||||||
"md4",
|
"md4",
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
|
"poly1305",
|
||||||
"ssh"
|
"ssh"
|
||||||
]
|
]
|
||||||
revision = "9f005a07e0d31d45e6656d241bb5c0f2efd4bc94"
|
revision = "12dd70caea0268ac0d6c2707d0611ef601e7c64e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
|
@ -15,7 +15,7 @@ ignored = ["google.golang.org/appengine*"]
|
|||||||
name = "code.gitea.io/sdk"
|
name = "code.gitea.io/sdk"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
revision = "9f005a07e0d31d45e6656d241bb5c0f2efd4bc94"
|
revision = "12dd70caea0268ac0d6c2707d0611ef601e7c64e"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
|
33
cmd/web.go
33
cmd/web.go
@ -5,6 +5,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -22,6 +23,7 @@ import (
|
|||||||
"github.com/Unknwon/com"
|
"github.com/Unknwon/com"
|
||||||
context2 "github.com/gorilla/context"
|
context2 "github.com/gorilla/context"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
"golang.org/x/crypto/acme/autocert"
|
||||||
ini "gopkg.in/ini.v1"
|
ini "gopkg.in/ini.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -71,6 +73,33 @@ func runHTTPRedirector() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler) error {
|
||||||
|
certManager := autocert.Manager{
|
||||||
|
Prompt: autocert.AcceptTOS,
|
||||||
|
HostPolicy: autocert.HostWhitelist(domain),
|
||||||
|
Cache: autocert.DirCache(directory),
|
||||||
|
Email: email,
|
||||||
|
}
|
||||||
|
go http.ListenAndServe(listenAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler))) // all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validatio happens here)
|
||||||
|
server := &http.Server{
|
||||||
|
Addr: listenAddr,
|
||||||
|
Handler: m,
|
||||||
|
TLSConfig: &tls.Config{
|
||||||
|
GetCertificate: certManager.GetCertificate,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return server.ListenAndServeTLS("", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != "GET" && r.Method != "HEAD" {
|
||||||
|
http.Error(w, "Use HTTPS", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
target := setting.AppURL + r.URL.RequestURI()
|
||||||
|
http.Redirect(w, r, target, http.StatusFound)
|
||||||
|
}
|
||||||
|
|
||||||
func runWeb(ctx *cli.Context) error {
|
func runWeb(ctx *cli.Context) error {
|
||||||
if ctx.IsSet("config") {
|
if ctx.IsSet("config") {
|
||||||
setting.CustomConf = ctx.String("config")
|
setting.CustomConf = ctx.String("config")
|
||||||
@ -143,6 +172,10 @@ func runWeb(ctx *cli.Context) error {
|
|||||||
case setting.HTTP:
|
case setting.HTTP:
|
||||||
err = runHTTP(listenAddr, context2.ClearHandler(m))
|
err = runHTTP(listenAddr, context2.ClearHandler(m))
|
||||||
case setting.HTTPS:
|
case setting.HTTPS:
|
||||||
|
if setting.EnableLetsEncrypt {
|
||||||
|
err = runLetsEncrypt(listenAddr, setting.Domain, setting.LetsEncryptDirectory, setting.LetsEncryptEmail, context2.ClearHandler(m))
|
||||||
|
break
|
||||||
|
}
|
||||||
if setting.RedirectOtherPort {
|
if setting.RedirectOtherPort {
|
||||||
go runHTTPRedirector()
|
go runHTTPRedirector()
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,11 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
|||||||
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, redirects http requests
|
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, redirects http requests
|
||||||
on another (https) port.
|
on another (https) port.
|
||||||
- `PORT_TO_REDIRECT`: **80**: Port used when `REDIRECT_OTHER_PORT` is true.
|
- `PORT_TO_REDIRECT`: **80**: Port used when `REDIRECT_OTHER_PORT` is true.
|
||||||
|
- `ENABLE_LETSENCRYPT`: **false**: If enabled you must set `DOMAIN` to valid internet facing domain (ensure DNS is set and port 80 is accessible by letsencrypt validation server).
|
||||||
|
By using Lets Encrypt **you must consent** to their [terms of service](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf)
|
||||||
|
- `LETSENCRYPT_ACCEPTTOS`: **false**: This is an explicit check that you accept the terms of service for Let's Encrypt
|
||||||
|
- `LETSENCRYPT_DIRECTORY`: **https**: Directory that Letsencrypt will use to cache information such as certs and private keys
|
||||||
|
- `LETSENCRYPT_EMAIL`: **email@example.com**: Email used by Letsencrypt to notify about problems with issued certificates. (No default)
|
||||||
|
|
||||||
## Database (`database`)
|
## Database (`database`)
|
||||||
|
|
||||||
|
@ -32,6 +32,24 @@ KEY_FILE = key.pem
|
|||||||
```
|
```
|
||||||
To learn more about the config values, please checkout the [Config Cheat Sheet](../config-cheat-sheet#server).
|
To learn more about the config values, please checkout the [Config Cheat Sheet](../config-cheat-sheet#server).
|
||||||
|
|
||||||
|
## Using Let's Encrypt
|
||||||
|
|
||||||
|
[Let's Encrypt](https://letsencrypt.org/) is a Certificate Authority that allows you to automatically request and renew SSL/TLS certificates. In addition to starting Gitea on your configured port, to request HTTPS certificates Gitea will also need to listed on port 80, and will set up an autoredirect to HTTPS for you. Let's Encrypt will need to be able to access Gitea via the Internet to verify your ownership of the domain.
|
||||||
|
|
||||||
|
By using Lets Encrypt **you must consent** to their [terms of service](https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf)
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[server]
|
||||||
|
PROTOCOL=https
|
||||||
|
DOMAIN=git.example.com
|
||||||
|
ENABLE_LETSENCRYPT=true
|
||||||
|
LETSENCRYPT_ACCEPTTOS=true
|
||||||
|
LETSENCRYPT_DIRECTORY=https
|
||||||
|
LETSENCRYPT_EMAIL=email@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the config values, please checkout the [Config Cheat Sheet](../config-cheat-sheet#server).
|
||||||
|
|
||||||
## Using reverse proxy
|
## Using reverse proxy
|
||||||
|
|
||||||
Setup up your reverse proxy like shown in the [reverse proxy guide](../reverse-proxies).
|
Setup up your reverse proxy like shown in the [reverse proxy guide](../reverse-proxies).
|
||||||
|
@ -112,6 +112,10 @@ var (
|
|||||||
UnixSocketPermission uint32
|
UnixSocketPermission uint32
|
||||||
EnablePprof bool
|
EnablePprof bool
|
||||||
PprofDataPath string
|
PprofDataPath string
|
||||||
|
EnableLetsEncrypt bool
|
||||||
|
LetsEncryptTOS bool
|
||||||
|
LetsEncryptDirectory string
|
||||||
|
LetsEncryptEmail string
|
||||||
|
|
||||||
SSH = struct {
|
SSH = struct {
|
||||||
Disabled bool `ini:"DISABLE_SSH"`
|
Disabled bool `ini:"DISABLE_SSH"`
|
||||||
@ -737,6 +741,14 @@ func NewContext() {
|
|||||||
}
|
}
|
||||||
UnixSocketPermission = uint32(UnixSocketPermissionParsed)
|
UnixSocketPermission = uint32(UnixSocketPermissionParsed)
|
||||||
}
|
}
|
||||||
|
EnableLetsEncrypt := sec.Key("ENABLE_LETSENCRYPT").MustBool(false)
|
||||||
|
LetsEncryptTOS := sec.Key("LETSENCRYPT_ACCEPTTOS").MustBool(false)
|
||||||
|
if !LetsEncryptTOS && EnableLetsEncrypt {
|
||||||
|
log.Warn("Failed to enable Let's Encrypt due to Let's Encrypt TOS not being accepted")
|
||||||
|
EnableLetsEncrypt = false
|
||||||
|
}
|
||||||
|
LetsEncryptDirectory = sec.Key("LETSENCRYPT_DIRECTORY").MustString("https")
|
||||||
|
LetsEncryptEmail = sec.Key("LETSENCRYPT_EMAIL").MustString("")
|
||||||
Domain = sec.Key("DOMAIN").MustString("localhost")
|
Domain = sec.Key("DOMAIN").MustString("localhost")
|
||||||
HTTPAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
|
HTTPAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
|
||||||
HTTPPort = sec.Key("HTTP_PORT").MustString("3000")
|
HTTPPort = sec.Key("HTTP_PORT").MustString("3000")
|
||||||
|
1065
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
Normal file
1065
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
962
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
Normal file
962
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
130
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
Normal file
130
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package autocert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrCacheMiss is returned when a certificate is not found in cache.
|
||||||
|
var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
|
||||||
|
|
||||||
|
// Cache is used by Manager to store and retrieve previously obtained certificates
|
||||||
|
// as opaque data.
|
||||||
|
//
|
||||||
|
// The key argument of the methods refers to a domain name but need not be an FQDN.
|
||||||
|
// Cache implementations should not rely on the key naming pattern.
|
||||||
|
type Cache interface {
|
||||||
|
// Get returns a certificate data for the specified key.
|
||||||
|
// If there's no such key, Get returns ErrCacheMiss.
|
||||||
|
Get(ctx context.Context, key string) ([]byte, error)
|
||||||
|
|
||||||
|
// Put stores the data in the cache under the specified key.
|
||||||
|
// Underlying implementations may use any data storage format,
|
||||||
|
// as long as the reverse operation, Get, results in the original data.
|
||||||
|
Put(ctx context.Context, key string, data []byte) error
|
||||||
|
|
||||||
|
// Delete removes a certificate data from the cache under the specified key.
|
||||||
|
// If there's no such key in the cache, Delete returns nil.
|
||||||
|
Delete(ctx context.Context, key string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// DirCache implements Cache using a directory on the local filesystem.
|
||||||
|
// If the directory does not exist, it will be created with 0700 permissions.
|
||||||
|
type DirCache string
|
||||||
|
|
||||||
|
// Get reads a certificate data from the specified file name.
|
||||||
|
func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
|
||||||
|
name = filepath.Join(string(d), name)
|
||||||
|
var (
|
||||||
|
data []byte
|
||||||
|
err error
|
||||||
|
done = make(chan struct{})
|
||||||
|
)
|
||||||
|
go func() {
|
||||||
|
data, err = ioutil.ReadFile(name)
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, ErrCacheMiss
|
||||||
|
}
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put writes the certificate data to the specified file name.
|
||||||
|
// The file will be created with 0600 permissions.
|
||||||
|
func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
|
||||||
|
if err := os.MkdirAll(string(d), 0700); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
var err error
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
|
var tmp string
|
||||||
|
if tmp, err = d.writeTempFile(name, data); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
// Don't overwrite the file if the context was canceled.
|
||||||
|
default:
|
||||||
|
newName := filepath.Join(string(d), name)
|
||||||
|
err = os.Rename(tmp, newName)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes the specified file name.
|
||||||
|
func (d DirCache) Delete(ctx context.Context, name string) error {
|
||||||
|
name = filepath.Join(string(d), name)
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
done = make(chan struct{})
|
||||||
|
)
|
||||||
|
go func() {
|
||||||
|
err = os.Remove(name)
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeTempFile writes b to a temporary file, closes the file and returns its path.
|
||||||
|
func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
|
||||||
|
// TempFile uses 0600 permissions
|
||||||
|
f, err := ioutil.TempFile(string(d), prefix)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if _, err := f.Write(b); err != nil {
|
||||||
|
f.Close()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return f.Name(), f.Close()
|
||||||
|
}
|
160
vendor/golang.org/x/crypto/acme/autocert/listener.go
generated
vendored
Normal file
160
vendor/golang.org/x/crypto/acme/autocert/listener.go
generated
vendored
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// Copyright 2017 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package autocert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewListener returns a net.Listener that listens on the standard TLS
|
||||||
|
// port (443) on all interfaces and returns *tls.Conn connections with
|
||||||
|
// LetsEncrypt certificates for the provided domain or domains.
|
||||||
|
//
|
||||||
|
// It enables one-line HTTPS servers:
|
||||||
|
//
|
||||||
|
// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))
|
||||||
|
//
|
||||||
|
// NewListener is a convenience function for a common configuration.
|
||||||
|
// More complex or custom configurations can use the autocert.Manager
|
||||||
|
// type instead.
|
||||||
|
//
|
||||||
|
// Use of this function implies acceptance of the LetsEncrypt Terms of
|
||||||
|
// Service. If domains is not empty, the provided domains are passed
|
||||||
|
// to HostWhitelist. If domains is empty, the listener will do
|
||||||
|
// LetsEncrypt challenges for any requested domain, which is not
|
||||||
|
// recommended.
|
||||||
|
//
|
||||||
|
// Certificates are cached in a "golang-autocert" directory under an
|
||||||
|
// operating system-specific cache or temp directory. This may not
|
||||||
|
// be suitable for servers spanning multiple machines.
|
||||||
|
//
|
||||||
|
// The returned listener uses a *tls.Config that enables HTTP/2, and
|
||||||
|
// should only be used with servers that support HTTP/2.
|
||||||
|
//
|
||||||
|
// The returned Listener also enables TCP keep-alives on the accepted
|
||||||
|
// connections. The returned *tls.Conn are returned before their TLS
|
||||||
|
// handshake has completed.
|
||||||
|
func NewListener(domains ...string) net.Listener {
|
||||||
|
m := &Manager{
|
||||||
|
Prompt: AcceptTOS,
|
||||||
|
}
|
||||||
|
if len(domains) > 0 {
|
||||||
|
m.HostPolicy = HostWhitelist(domains...)
|
||||||
|
}
|
||||||
|
dir := cacheDir()
|
||||||
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||||
|
log.Printf("warning: autocert.NewListener not using a cache: %v", err)
|
||||||
|
} else {
|
||||||
|
m.Cache = DirCache(dir)
|
||||||
|
}
|
||||||
|
return m.Listener()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listener listens on the standard TLS port (443) on all interfaces
|
||||||
|
// and returns a net.Listener returning *tls.Conn connections.
|
||||||
|
//
|
||||||
|
// The returned listener uses a *tls.Config that enables HTTP/2, and
|
||||||
|
// should only be used with servers that support HTTP/2.
|
||||||
|
//
|
||||||
|
// The returned Listener also enables TCP keep-alives on the accepted
|
||||||
|
// connections. The returned *tls.Conn are returned before their TLS
|
||||||
|
// handshake has completed.
|
||||||
|
//
|
||||||
|
// Unlike NewListener, it is the caller's responsibility to initialize
|
||||||
|
// the Manager m's Prompt, Cache, HostPolicy, and other desired options.
|
||||||
|
func (m *Manager) Listener() net.Listener {
|
||||||
|
ln := &listener{
|
||||||
|
m: m,
|
||||||
|
conf: &tls.Config{
|
||||||
|
GetCertificate: m.GetCertificate, // bonus: panic on nil m
|
||||||
|
NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
|
||||||
|
return ln
|
||||||
|
}
|
||||||
|
|
||||||
|
type listener struct {
|
||||||
|
m *Manager
|
||||||
|
conf *tls.Config
|
||||||
|
|
||||||
|
tcpListener net.Listener
|
||||||
|
tcpListenErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *listener) Accept() (net.Conn, error) {
|
||||||
|
if ln.tcpListenErr != nil {
|
||||||
|
return nil, ln.tcpListenErr
|
||||||
|
}
|
||||||
|
conn, err := ln.tcpListener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tcpConn := conn.(*net.TCPConn)
|
||||||
|
|
||||||
|
// Because Listener is a convenience function, help out with
|
||||||
|
// this too. This is not possible for the caller to set once
|
||||||
|
// we return a *tcp.Conn wrapping an inaccessible net.Conn.
|
||||||
|
// If callers don't want this, they can do things the manual
|
||||||
|
// way and tweak as needed. But this is what net/http does
|
||||||
|
// itself, so copy that. If net/http changes, we can change
|
||||||
|
// here too.
|
||||||
|
tcpConn.SetKeepAlive(true)
|
||||||
|
tcpConn.SetKeepAlivePeriod(3 * time.Minute)
|
||||||
|
|
||||||
|
return tls.Server(tcpConn, ln.conf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *listener) Addr() net.Addr {
|
||||||
|
if ln.tcpListener != nil {
|
||||||
|
return ln.tcpListener.Addr()
|
||||||
|
}
|
||||||
|
// net.Listen failed. Return something non-nil in case callers
|
||||||
|
// call Addr before Accept:
|
||||||
|
return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ln *listener) Close() error {
|
||||||
|
if ln.tcpListenErr != nil {
|
||||||
|
return ln.tcpListenErr
|
||||||
|
}
|
||||||
|
return ln.tcpListener.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func homeDir() string {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
|
||||||
|
}
|
||||||
|
if h := os.Getenv("HOME"); h != "" {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
return "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
func cacheDir() string {
|
||||||
|
const base = "golang-autocert"
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
return filepath.Join(homeDir(), "Library", "Caches", base)
|
||||||
|
case "windows":
|
||||||
|
for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
|
||||||
|
if v := os.Getenv(ev); v != "" {
|
||||||
|
return filepath.Join(v, base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Worst case:
|
||||||
|
return filepath.Join(homeDir(), base)
|
||||||
|
}
|
||||||
|
if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
|
||||||
|
return filepath.Join(xdg, base)
|
||||||
|
}
|
||||||
|
return filepath.Join(homeDir(), ".cache", base)
|
||||||
|
}
|
141
vendor/golang.org/x/crypto/acme/autocert/renewal.go
generated
vendored
Normal file
141
vendor/golang.org/x/crypto/acme/autocert/renewal.go
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package autocert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// renewJitter is the maximum deviation from Manager.RenewBefore.
|
||||||
|
const renewJitter = time.Hour
|
||||||
|
|
||||||
|
// domainRenewal tracks the state used by the periodic timers
|
||||||
|
// renewing a single domain's cert.
|
||||||
|
type domainRenewal struct {
|
||||||
|
m *Manager
|
||||||
|
domain string
|
||||||
|
key crypto.Signer
|
||||||
|
|
||||||
|
timerMu sync.Mutex
|
||||||
|
timer *time.Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// start starts a cert renewal timer at the time
|
||||||
|
// defined by the certificate expiration time exp.
|
||||||
|
//
|
||||||
|
// If the timer is already started, calling start is a noop.
|
||||||
|
func (dr *domainRenewal) start(exp time.Time) {
|
||||||
|
dr.timerMu.Lock()
|
||||||
|
defer dr.timerMu.Unlock()
|
||||||
|
if dr.timer != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dr.timer = time.AfterFunc(dr.next(exp), dr.renew)
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop stops the cert renewal timer.
|
||||||
|
// If the timer is already stopped, calling stop is a noop.
|
||||||
|
func (dr *domainRenewal) stop() {
|
||||||
|
dr.timerMu.Lock()
|
||||||
|
defer dr.timerMu.Unlock()
|
||||||
|
if dr.timer == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dr.timer.Stop()
|
||||||
|
dr.timer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// renew is called periodically by a timer.
|
||||||
|
// The first renew call is kicked off by dr.start.
|
||||||
|
func (dr *domainRenewal) renew() {
|
||||||
|
dr.timerMu.Lock()
|
||||||
|
defer dr.timerMu.Unlock()
|
||||||
|
if dr.timer == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
// TODO: rotate dr.key at some point?
|
||||||
|
next, err := dr.do(ctx)
|
||||||
|
if err != nil {
|
||||||
|
next = renewJitter / 2
|
||||||
|
next += time.Duration(pseudoRand.int63n(int64(next)))
|
||||||
|
}
|
||||||
|
dr.timer = time.AfterFunc(next, dr.renew)
|
||||||
|
testDidRenewLoop(next, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateState locks and replaces the relevant Manager.state item with the given
|
||||||
|
// state. It additionally updates dr.key with the given state's key.
|
||||||
|
func (dr *domainRenewal) updateState(state *certState) {
|
||||||
|
dr.m.stateMu.Lock()
|
||||||
|
defer dr.m.stateMu.Unlock()
|
||||||
|
dr.key = state.key
|
||||||
|
dr.m.state[dr.domain] = state
|
||||||
|
}
|
||||||
|
|
||||||
|
// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
|
||||||
|
// Instead, it requests a new certificate independently and, upon success,
|
||||||
|
// replaces dr.m.state item with a new one and updates cache for the given domain.
|
||||||
|
//
|
||||||
|
// It may lock and update the Manager.state if the expiration date of the currently
|
||||||
|
// cached cert is far enough in the future.
|
||||||
|
//
|
||||||
|
// The returned value is a time interval after which the renewal should occur again.
|
||||||
|
func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
|
||||||
|
// a race is likely unavoidable in a distributed environment
|
||||||
|
// but we try nonetheless
|
||||||
|
if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil {
|
||||||
|
next := dr.next(tlscert.Leaf.NotAfter)
|
||||||
|
if next > dr.m.renewBefore()+renewJitter {
|
||||||
|
signer, ok := tlscert.PrivateKey.(crypto.Signer)
|
||||||
|
if ok {
|
||||||
|
state := &certState{
|
||||||
|
key: signer,
|
||||||
|
cert: tlscert.Certificate,
|
||||||
|
leaf: tlscert.Leaf,
|
||||||
|
}
|
||||||
|
dr.updateState(state)
|
||||||
|
return next, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
state := &certState{
|
||||||
|
key: dr.key,
|
||||||
|
cert: der,
|
||||||
|
leaf: leaf,
|
||||||
|
}
|
||||||
|
tlscert, err := state.tlscert()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if err := dr.m.cachePut(ctx, dr.domain, tlscert); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
dr.updateState(state)
|
||||||
|
return dr.next(leaf.NotAfter), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dr *domainRenewal) next(expiry time.Time) time.Duration {
|
||||||
|
d := expiry.Sub(timeNow()) - dr.m.renewBefore()
|
||||||
|
// add a bit of randomness to renew deadline
|
||||||
|
n := pseudoRand.int63n(int64(renewJitter))
|
||||||
|
d -= time.Duration(n)
|
||||||
|
if d < 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
var testDidRenewLoop = func(next time.Duration, err error) {}
|
153
vendor/golang.org/x/crypto/acme/jws.go
generated
vendored
Normal file
153
vendor/golang.org/x/crypto/acme/jws.go
generated
vendored
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package acme
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/sha256"
|
||||||
|
_ "crypto/sha512" // need for EC keys
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// jwsEncodeJSON signs claimset using provided key and a nonce.
|
||||||
|
// The result is serialized in JSON format.
|
||||||
|
// See https://tools.ietf.org/html/rfc7515#section-7.
|
||||||
|
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
|
||||||
|
jwk, err := jwkEncode(key.Public())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
alg, sha := jwsHasher(key)
|
||||||
|
if alg == "" || !sha.Available() {
|
||||||
|
return nil, ErrUnsupportedKey
|
||||||
|
}
|
||||||
|
phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce)
|
||||||
|
phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
|
||||||
|
cs, err := json.Marshal(claimset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload := base64.RawURLEncoding.EncodeToString(cs)
|
||||||
|
hash := sha.New()
|
||||||
|
hash.Write([]byte(phead + "." + payload))
|
||||||
|
sig, err := jwsSign(key, sha, hash.Sum(nil))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := struct {
|
||||||
|
Protected string `json:"protected"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
Sig string `json:"signature"`
|
||||||
|
}{
|
||||||
|
Protected: phead,
|
||||||
|
Payload: payload,
|
||||||
|
Sig: base64.RawURLEncoding.EncodeToString(sig),
|
||||||
|
}
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// jwkEncode encodes public part of an RSA or ECDSA key into a JWK.
|
||||||
|
// The result is also suitable for creating a JWK thumbprint.
|
||||||
|
// https://tools.ietf.org/html/rfc7517
|
||||||
|
func jwkEncode(pub crypto.PublicKey) (string, error) {
|
||||||
|
switch pub := pub.(type) {
|
||||||
|
case *rsa.PublicKey:
|
||||||
|
// https://tools.ietf.org/html/rfc7518#section-6.3.1
|
||||||
|
n := pub.N
|
||||||
|
e := big.NewInt(int64(pub.E))
|
||||||
|
// Field order is important.
|
||||||
|
// See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
|
||||||
|
return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`,
|
||||||
|
base64.RawURLEncoding.EncodeToString(e.Bytes()),
|
||||||
|
base64.RawURLEncoding.EncodeToString(n.Bytes()),
|
||||||
|
), nil
|
||||||
|
case *ecdsa.PublicKey:
|
||||||
|
// https://tools.ietf.org/html/rfc7518#section-6.2.1
|
||||||
|
p := pub.Curve.Params()
|
||||||
|
n := p.BitSize / 8
|
||||||
|
if p.BitSize%8 != 0 {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
x := pub.X.Bytes()
|
||||||
|
if n > len(x) {
|
||||||
|
x = append(make([]byte, n-len(x)), x...)
|
||||||
|
}
|
||||||
|
y := pub.Y.Bytes()
|
||||||
|
if n > len(y) {
|
||||||
|
y = append(make([]byte, n-len(y)), y...)
|
||||||
|
}
|
||||||
|
// Field order is important.
|
||||||
|
// See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
|
||||||
|
return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`,
|
||||||
|
p.Name,
|
||||||
|
base64.RawURLEncoding.EncodeToString(x),
|
||||||
|
base64.RawURLEncoding.EncodeToString(y),
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
return "", ErrUnsupportedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// jwsSign signs the digest using the given key.
|
||||||
|
// It returns ErrUnsupportedKey if the key type is unknown.
|
||||||
|
// The hash is used only for RSA keys.
|
||||||
|
func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) {
|
||||||
|
switch key := key.(type) {
|
||||||
|
case *rsa.PrivateKey:
|
||||||
|
return key.Sign(rand.Reader, digest, hash)
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
r, s, err := ecdsa.Sign(rand.Reader, key, digest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rb, sb := r.Bytes(), s.Bytes()
|
||||||
|
size := key.Params().BitSize / 8
|
||||||
|
if size%8 > 0 {
|
||||||
|
size++
|
||||||
|
}
|
||||||
|
sig := make([]byte, size*2)
|
||||||
|
copy(sig[size-len(rb):], rb)
|
||||||
|
copy(sig[size*2-len(sb):], sb)
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
return nil, ErrUnsupportedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// jwsHasher indicates suitable JWS algorithm name and a hash function
|
||||||
|
// to use for signing a digest with the provided key.
|
||||||
|
// It returns ("", 0) if the key is not supported.
|
||||||
|
func jwsHasher(key crypto.Signer) (string, crypto.Hash) {
|
||||||
|
switch key := key.(type) {
|
||||||
|
case *rsa.PrivateKey:
|
||||||
|
return "RS256", crypto.SHA256
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
switch key.Params().Name {
|
||||||
|
case "P-256":
|
||||||
|
return "ES256", crypto.SHA256
|
||||||
|
case "P-384":
|
||||||
|
return "ES384", crypto.SHA384
|
||||||
|
case "P-521":
|
||||||
|
return "ES512", crypto.SHA512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// JWKThumbprint creates a JWK thumbprint out of pub
|
||||||
|
// as specified in https://tools.ietf.org/html/rfc7638.
|
||||||
|
func JWKThumbprint(pub crypto.PublicKey) (string, error) {
|
||||||
|
jwk, err := jwkEncode(pub)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
b := sha256.Sum256([]byte(jwk))
|
||||||
|
return base64.RawURLEncoding.EncodeToString(b[:]), nil
|
||||||
|
}
|
329
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
Normal file
329
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
13
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
@ -171,9 +171,16 @@ func Verify(publicKey PublicKey, message, sig []byte) bool {
|
|||||||
edwards25519.ScReduce(&hReduced, &digest)
|
edwards25519.ScReduce(&hReduced, &digest)
|
||||||
|
|
||||||
var R edwards25519.ProjectiveGroupElement
|
var R edwards25519.ProjectiveGroupElement
|
||||||
var b [32]byte
|
var s [32]byte
|
||||||
copy(b[:], sig[32:])
|
copy(s[:], sig[32:])
|
||||||
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
|
|
||||||
|
// https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
|
||||||
|
// the range [0, order) in order to prevent signature malleability.
|
||||||
|
if !edwards25519.ScMinimal(&s) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
|
||||||
|
|
||||||
var checkR [32]byte
|
var checkR [32]byte
|
||||||
R.ToBytes(&checkR)
|
R.ToBytes(&checkR)
|
||||||
|
22
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
22
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
package edwards25519
|
package edwards25519
|
||||||
|
|
||||||
|
import "encoding/binary"
|
||||||
|
|
||||||
// This code is a port of the public domain, “ref10” implementation of ed25519
|
// This code is a port of the public domain, “ref10” implementation of ed25519
|
||||||
// from SUPERCOP.
|
// from SUPERCOP.
|
||||||
|
|
||||||
@ -1769,3 +1771,23 @@ func ScReduce(out *[32]byte, s *[64]byte) {
|
|||||||
out[30] = byte(s11 >> 9)
|
out[30] = byte(s11 >> 9)
|
||||||
out[31] = byte(s11 >> 17)
|
out[31] = byte(s11 >> 17)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// order is the order of Curve25519 in little-endian form.
|
||||||
|
var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000}
|
||||||
|
|
||||||
|
// ScMinimal returns true if the given scalar is less than the order of the
|
||||||
|
// curve.
|
||||||
|
func ScMinimal(scalar *[32]byte) bool {
|
||||||
|
for i := 3; ; i-- {
|
||||||
|
v := binary.LittleEndian.Uint64(scalar[i*8:])
|
||||||
|
if v > order[i] {
|
||||||
|
return false
|
||||||
|
} else if v < order[i] {
|
||||||
|
break
|
||||||
|
} else if i == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
223
vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
generated
vendored
Normal file
223
vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
generated
vendored
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package ChaCha20 implements the core ChaCha20 function as specified
|
||||||
|
// in https://tools.ietf.org/html/rfc7539#section-2.3.
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/cipher"
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
// assert that *Cipher implements cipher.Stream
|
||||||
|
var _ cipher.Stream = (*Cipher)(nil)
|
||||||
|
|
||||||
|
// Cipher is a stateful instance of ChaCha20 using a particular key
|
||||||
|
// and nonce. A *Cipher implements the cipher.Stream interface.
|
||||||
|
type Cipher struct {
|
||||||
|
key [8]uint32
|
||||||
|
nonce [3]uint32
|
||||||
|
counter uint32 // incremented after each block
|
||||||
|
buf [64]byte // buffer for unused keystream bytes
|
||||||
|
len int // number of unused keystream bytes at end of buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new ChaCha20 stream cipher with the given key and nonce.
|
||||||
|
// The initial counter value is set to 0.
|
||||||
|
func New(key [8]uint32, nonce [3]uint32) *Cipher {
|
||||||
|
return &Cipher{key: key, nonce: nonce}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XORKeyStream XORs each byte in the given slice with a byte from the
|
||||||
|
// cipher's key stream. Dst and src must overlap entirely or not at all.
|
||||||
|
//
|
||||||
|
// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
|
||||||
|
// to pass a dst bigger than src, and in that case, XORKeyStream will
|
||||||
|
// only update dst[:len(src)] and will not touch the rest of dst.
|
||||||
|
//
|
||||||
|
// Multiple calls to XORKeyStream behave as if the concatenation of
|
||||||
|
// the src buffers was passed in a single run. That is, Cipher
|
||||||
|
// maintains state and does not reset at each XORKeyStream call.
|
||||||
|
func (s *Cipher) XORKeyStream(dst, src []byte) {
|
||||||
|
// xor src with buffered keystream first
|
||||||
|
if s.len != 0 {
|
||||||
|
buf := s.buf[len(s.buf)-s.len:]
|
||||||
|
if len(src) < len(buf) {
|
||||||
|
buf = buf[:len(src)]
|
||||||
|
}
|
||||||
|
td, ts := dst[:len(buf)], src[:len(buf)] // BCE hint
|
||||||
|
for i, b := range buf {
|
||||||
|
td[i] = ts[i] ^ b
|
||||||
|
}
|
||||||
|
s.len -= len(buf)
|
||||||
|
if s.len != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.buf = [len(s.buf)]byte{} // zero the empty buffer
|
||||||
|
src = src[len(buf):]
|
||||||
|
dst = dst[len(buf):]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(src) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up a 64-byte buffer to pad out the final block if needed
|
||||||
|
// (hoisted out of the main loop to avoid spills)
|
||||||
|
rem := len(src) % 64 // length of final block
|
||||||
|
fin := len(src) - rem // index of final block
|
||||||
|
if rem > 0 {
|
||||||
|
copy(s.buf[len(s.buf)-64:], src[fin:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// qr calculates a quarter round
|
||||||
|
qr := func(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
|
||||||
|
a += b
|
||||||
|
d ^= a
|
||||||
|
d = (d << 16) | (d >> 16)
|
||||||
|
c += d
|
||||||
|
b ^= c
|
||||||
|
b = (b << 12) | (b >> 20)
|
||||||
|
a += b
|
||||||
|
d ^= a
|
||||||
|
d = (d << 8) | (d >> 24)
|
||||||
|
c += d
|
||||||
|
b ^= c
|
||||||
|
b = (b << 7) | (b >> 25)
|
||||||
|
return a, b, c, d
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChaCha20 constants
|
||||||
|
const (
|
||||||
|
j0 = 0x61707865
|
||||||
|
j1 = 0x3320646e
|
||||||
|
j2 = 0x79622d32
|
||||||
|
j3 = 0x6b206574
|
||||||
|
)
|
||||||
|
|
||||||
|
// pre-calculate most of the first round
|
||||||
|
s1, s5, s9, s13 := qr(j1, s.key[1], s.key[5], s.nonce[0])
|
||||||
|
s2, s6, s10, s14 := qr(j2, s.key[2], s.key[6], s.nonce[1])
|
||||||
|
s3, s7, s11, s15 := qr(j3, s.key[3], s.key[7], s.nonce[2])
|
||||||
|
|
||||||
|
n := len(src)
|
||||||
|
src, dst = src[:n:n], dst[:n:n] // BCE hint
|
||||||
|
for i := 0; i < n; i += 64 {
|
||||||
|
// calculate the remainder of the first round
|
||||||
|
s0, s4, s8, s12 := qr(j0, s.key[0], s.key[4], s.counter)
|
||||||
|
|
||||||
|
// execute the second round
|
||||||
|
x0, x5, x10, x15 := qr(s0, s5, s10, s15)
|
||||||
|
x1, x6, x11, x12 := qr(s1, s6, s11, s12)
|
||||||
|
x2, x7, x8, x13 := qr(s2, s7, s8, s13)
|
||||||
|
x3, x4, x9, x14 := qr(s3, s4, s9, s14)
|
||||||
|
|
||||||
|
// execute the remaining 18 rounds
|
||||||
|
for i := 0; i < 9; i++ {
|
||||||
|
x0, x4, x8, x12 = qr(x0, x4, x8, x12)
|
||||||
|
x1, x5, x9, x13 = qr(x1, x5, x9, x13)
|
||||||
|
x2, x6, x10, x14 = qr(x2, x6, x10, x14)
|
||||||
|
x3, x7, x11, x15 = qr(x3, x7, x11, x15)
|
||||||
|
|
||||||
|
x0, x5, x10, x15 = qr(x0, x5, x10, x15)
|
||||||
|
x1, x6, x11, x12 = qr(x1, x6, x11, x12)
|
||||||
|
x2, x7, x8, x13 = qr(x2, x7, x8, x13)
|
||||||
|
x3, x4, x9, x14 = qr(x3, x4, x9, x14)
|
||||||
|
}
|
||||||
|
|
||||||
|
x0 += j0
|
||||||
|
x1 += j1
|
||||||
|
x2 += j2
|
||||||
|
x3 += j3
|
||||||
|
|
||||||
|
x4 += s.key[0]
|
||||||
|
x5 += s.key[1]
|
||||||
|
x6 += s.key[2]
|
||||||
|
x7 += s.key[3]
|
||||||
|
x8 += s.key[4]
|
||||||
|
x9 += s.key[5]
|
||||||
|
x10 += s.key[6]
|
||||||
|
x11 += s.key[7]
|
||||||
|
|
||||||
|
x12 += s.counter
|
||||||
|
x13 += s.nonce[0]
|
||||||
|
x14 += s.nonce[1]
|
||||||
|
x15 += s.nonce[2]
|
||||||
|
|
||||||
|
// increment the counter
|
||||||
|
s.counter += 1
|
||||||
|
if s.counter == 0 {
|
||||||
|
panic("chacha20: counter overflow")
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad to 64 bytes if needed
|
||||||
|
in, out := src[i:], dst[i:]
|
||||||
|
if i == fin {
|
||||||
|
// src[fin:] has already been copied into s.buf before
|
||||||
|
// the main loop
|
||||||
|
in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:]
|
||||||
|
}
|
||||||
|
in, out = in[:64], out[:64] // BCE hint
|
||||||
|
|
||||||
|
// XOR the key stream with the source and write out the result
|
||||||
|
xor(out[0:], in[0:], x0)
|
||||||
|
xor(out[4:], in[4:], x1)
|
||||||
|
xor(out[8:], in[8:], x2)
|
||||||
|
xor(out[12:], in[12:], x3)
|
||||||
|
xor(out[16:], in[16:], x4)
|
||||||
|
xor(out[20:], in[20:], x5)
|
||||||
|
xor(out[24:], in[24:], x6)
|
||||||
|
xor(out[28:], in[28:], x7)
|
||||||
|
xor(out[32:], in[32:], x8)
|
||||||
|
xor(out[36:], in[36:], x9)
|
||||||
|
xor(out[40:], in[40:], x10)
|
||||||
|
xor(out[44:], in[44:], x11)
|
||||||
|
xor(out[48:], in[48:], x12)
|
||||||
|
xor(out[52:], in[52:], x13)
|
||||||
|
xor(out[56:], in[56:], x14)
|
||||||
|
xor(out[60:], in[60:], x15)
|
||||||
|
}
|
||||||
|
// copy any trailing bytes out of the buffer and into dst
|
||||||
|
if rem != 0 {
|
||||||
|
s.len = 64 - rem
|
||||||
|
copy(dst[fin:], s.buf[len(s.buf)-64:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance discards bytes in the key stream until the next 64 byte block
|
||||||
|
// boundary is reached and updates the counter accordingly. If the key
|
||||||
|
// stream is already at a block boundary no bytes will be discarded and
|
||||||
|
// the counter will be unchanged.
|
||||||
|
func (s *Cipher) Advance() {
|
||||||
|
s.len -= s.len % 64
|
||||||
|
if s.len == 0 {
|
||||||
|
s.buf = [len(s.buf)]byte{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XORKeyStream crypts bytes from in to out using the given key and counters.
|
||||||
|
// In and out must overlap entirely or not at all. Counter contains the raw
|
||||||
|
// ChaCha20 counter bytes (i.e. block counter followed by nonce).
|
||||||
|
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
|
||||||
|
s := Cipher{
|
||||||
|
key: [8]uint32{
|
||||||
|
binary.LittleEndian.Uint32(key[0:4]),
|
||||||
|
binary.LittleEndian.Uint32(key[4:8]),
|
||||||
|
binary.LittleEndian.Uint32(key[8:12]),
|
||||||
|
binary.LittleEndian.Uint32(key[12:16]),
|
||||||
|
binary.LittleEndian.Uint32(key[16:20]),
|
||||||
|
binary.LittleEndian.Uint32(key[20:24]),
|
||||||
|
binary.LittleEndian.Uint32(key[24:28]),
|
||||||
|
binary.LittleEndian.Uint32(key[28:32]),
|
||||||
|
},
|
||||||
|
nonce: [3]uint32{
|
||||||
|
binary.LittleEndian.Uint32(counter[4:8]),
|
||||||
|
binary.LittleEndian.Uint32(counter[8:12]),
|
||||||
|
binary.LittleEndian.Uint32(counter[12:16]),
|
||||||
|
},
|
||||||
|
counter: binary.LittleEndian.Uint32(counter[0:4]),
|
||||||
|
}
|
||||||
|
s.XORKeyStream(out, in)
|
||||||
|
}
|
43
vendor/golang.org/x/crypto/internal/chacha20/xor.go
generated
vendored
Normal file
43
vendor/golang.org/x/crypto/internal/chacha20/xor.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found src the LICENSE file.
|
||||||
|
|
||||||
|
package chacha20
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Platforms that have fast unaligned 32-bit little endian accesses.
|
||||||
|
const unaligned = runtime.GOARCH == "386" ||
|
||||||
|
runtime.GOARCH == "amd64" ||
|
||||||
|
runtime.GOARCH == "arm64" ||
|
||||||
|
runtime.GOARCH == "ppc64le" ||
|
||||||
|
runtime.GOARCH == "s390x"
|
||||||
|
|
||||||
|
// xor reads a little endian uint32 from src, XORs it with u and
|
||||||
|
// places the result in little endian byte order in dst.
|
||||||
|
func xor(dst, src []byte, u uint32) {
|
||||||
|
_, _ = src[3], dst[3] // eliminate bounds checks
|
||||||
|
if unaligned {
|
||||||
|
// The compiler should optimize this code into
|
||||||
|
// 32-bit unaligned little endian loads and stores.
|
||||||
|
// TODO: delete once the compiler does a reliably
|
||||||
|
// good job with the generic code below.
|
||||||
|
// See issue #25111 for more details.
|
||||||
|
v := uint32(src[0])
|
||||||
|
v |= uint32(src[1]) << 8
|
||||||
|
v |= uint32(src[2]) << 16
|
||||||
|
v |= uint32(src[3]) << 24
|
||||||
|
v ^= u
|
||||||
|
dst[0] = byte(v)
|
||||||
|
dst[1] = byte(v >> 8)
|
||||||
|
dst[2] = byte(v >> 16)
|
||||||
|
dst[3] = byte(v >> 24)
|
||||||
|
} else {
|
||||||
|
dst[0] = src[0] ^ byte(u)
|
||||||
|
dst[1] = src[1] ^ byte(u>>8)
|
||||||
|
dst[2] = src[2] ^ byte(u>>16)
|
||||||
|
dst[3] = src[3] ^ byte(u>>24)
|
||||||
|
}
|
||||||
|
}
|
33
vendor/golang.org/x/crypto/poly1305/poly1305.go
generated
vendored
Normal file
33
vendor/golang.org/x/crypto/poly1305/poly1305.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package poly1305 implements Poly1305 one-time message authentication code as
|
||||||
|
specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
|
||||||
|
|
||||||
|
Poly1305 is a fast, one-time authentication function. It is infeasible for an
|
||||||
|
attacker to generate an authenticator for a message without the key. However, a
|
||||||
|
key must only be used for a single message. Authenticating two different
|
||||||
|
messages with the same key allows an attacker to forge authenticators for other
|
||||||
|
messages with the same key.
|
||||||
|
|
||||||
|
Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
|
||||||
|
used with a fixed key in order to generate one-time keys from an nonce.
|
||||||
|
However, in this package AES isn't used and the one-time key is specified
|
||||||
|
directly.
|
||||||
|
*/
|
||||||
|
package poly1305 // import "golang.org/x/crypto/poly1305"
|
||||||
|
|
||||||
|
import "crypto/subtle"
|
||||||
|
|
||||||
|
// TagSize is the size, in bytes, of a poly1305 authenticator.
|
||||||
|
const TagSize = 16
|
||||||
|
|
||||||
|
// Verify returns true if mac is a valid authenticator for m with the given
|
||||||
|
// key.
|
||||||
|
func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
|
||||||
|
var tmp [16]byte
|
||||||
|
Sum(&tmp, m, key)
|
||||||
|
return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
|
||||||
|
}
|
22
vendor/golang.org/x/crypto/poly1305/sum_amd64.go
generated
vendored
Normal file
22
vendor/golang.org/x/crypto/poly1305/sum_amd64.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
package poly1305
|
||||||
|
|
||||||
|
// This function is implemented in sum_amd64.s
|
||||||
|
//go:noescape
|
||||||
|
func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
|
||||||
|
|
||||||
|
// Sum generates an authenticator for m using a one-time key and puts the
|
||||||
|
// 16-byte result into out. Authenticating two different messages with the same
|
||||||
|
// key allows an attacker to forge messages at will.
|
||||||
|
func Sum(out *[16]byte, m []byte, key *[32]byte) {
|
||||||
|
var mPtr *byte
|
||||||
|
if len(m) > 0 {
|
||||||
|
mPtr = &m[0]
|
||||||
|
}
|
||||||
|
poly1305(out, mPtr, uint64(len(m)), key)
|
||||||
|
}
|
125
vendor/golang.org/x/crypto/poly1305/sum_amd64.s
generated
vendored
Normal file
125
vendor/golang.org/x/crypto/poly1305/sum_amd64.s
generated
vendored
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
#define POLY1305_ADD(msg, h0, h1, h2) \
|
||||||
|
ADDQ 0(msg), h0; \
|
||||||
|
ADCQ 8(msg), h1; \
|
||||||
|
ADCQ $1, h2; \
|
||||||
|
LEAQ 16(msg), msg
|
||||||
|
|
||||||
|
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \
|
||||||
|
MOVQ r0, AX; \
|
||||||
|
MULQ h0; \
|
||||||
|
MOVQ AX, t0; \
|
||||||
|
MOVQ DX, t1; \
|
||||||
|
MOVQ r0, AX; \
|
||||||
|
MULQ h1; \
|
||||||
|
ADDQ AX, t1; \
|
||||||
|
ADCQ $0, DX; \
|
||||||
|
MOVQ r0, t2; \
|
||||||
|
IMULQ h2, t2; \
|
||||||
|
ADDQ DX, t2; \
|
||||||
|
\
|
||||||
|
MOVQ r1, AX; \
|
||||||
|
MULQ h0; \
|
||||||
|
ADDQ AX, t1; \
|
||||||
|
ADCQ $0, DX; \
|
||||||
|
MOVQ DX, h0; \
|
||||||
|
MOVQ r1, t3; \
|
||||||
|
IMULQ h2, t3; \
|
||||||
|
MOVQ r1, AX; \
|
||||||
|
MULQ h1; \
|
||||||
|
ADDQ AX, t2; \
|
||||||
|
ADCQ DX, t3; \
|
||||||
|
ADDQ h0, t2; \
|
||||||
|
ADCQ $0, t3; \
|
||||||
|
\
|
||||||
|
MOVQ t0, h0; \
|
||||||
|
MOVQ t1, h1; \
|
||||||
|
MOVQ t2, h2; \
|
||||||
|
ANDQ $3, h2; \
|
||||||
|
MOVQ t2, t0; \
|
||||||
|
ANDQ $0xFFFFFFFFFFFFFFFC, t0; \
|
||||||
|
ADDQ t0, h0; \
|
||||||
|
ADCQ t3, h1; \
|
||||||
|
ADCQ $0, h2; \
|
||||||
|
SHRQ $2, t3, t2; \
|
||||||
|
SHRQ $2, t3; \
|
||||||
|
ADDQ t2, h0; \
|
||||||
|
ADCQ t3, h1; \
|
||||||
|
ADCQ $0, h2
|
||||||
|
|
||||||
|
DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
||||||
|
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
||||||
|
GLOBL ·poly1305Mask<>(SB), RODATA, $16
|
||||||
|
|
||||||
|
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
||||||
|
TEXT ·poly1305(SB), $0-32
|
||||||
|
MOVQ out+0(FP), DI
|
||||||
|
MOVQ m+8(FP), SI
|
||||||
|
MOVQ mlen+16(FP), R15
|
||||||
|
MOVQ key+24(FP), AX
|
||||||
|
|
||||||
|
MOVQ 0(AX), R11
|
||||||
|
MOVQ 8(AX), R12
|
||||||
|
ANDQ ·poly1305Mask<>(SB), R11 // r0
|
||||||
|
ANDQ ·poly1305Mask<>+8(SB), R12 // r1
|
||||||
|
XORQ R8, R8 // h0
|
||||||
|
XORQ R9, R9 // h1
|
||||||
|
XORQ R10, R10 // h2
|
||||||
|
|
||||||
|
CMPQ R15, $16
|
||||||
|
JB bytes_between_0_and_15
|
||||||
|
|
||||||
|
loop:
|
||||||
|
POLY1305_ADD(SI, R8, R9, R10)
|
||||||
|
|
||||||
|
multiply:
|
||||||
|
POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14)
|
||||||
|
SUBQ $16, R15
|
||||||
|
CMPQ R15, $16
|
||||||
|
JAE loop
|
||||||
|
|
||||||
|
bytes_between_0_and_15:
|
||||||
|
TESTQ R15, R15
|
||||||
|
JZ done
|
||||||
|
MOVQ $1, BX
|
||||||
|
XORQ CX, CX
|
||||||
|
XORQ R13, R13
|
||||||
|
ADDQ R15, SI
|
||||||
|
|
||||||
|
flush_buffer:
|
||||||
|
SHLQ $8, BX, CX
|
||||||
|
SHLQ $8, BX
|
||||||
|
MOVB -1(SI), R13
|
||||||
|
XORQ R13, BX
|
||||||
|
DECQ SI
|
||||||
|
DECQ R15
|
||||||
|
JNZ flush_buffer
|
||||||
|
|
||||||
|
ADDQ BX, R8
|
||||||
|
ADCQ CX, R9
|
||||||
|
ADCQ $0, R10
|
||||||
|
MOVQ $16, R15
|
||||||
|
JMP multiply
|
||||||
|
|
||||||
|
done:
|
||||||
|
MOVQ R8, AX
|
||||||
|
MOVQ R9, BX
|
||||||
|
SUBQ $0xFFFFFFFFFFFFFFFB, AX
|
||||||
|
SBBQ $0xFFFFFFFFFFFFFFFF, BX
|
||||||
|
SBBQ $3, R10
|
||||||
|
CMOVQCS R8, AX
|
||||||
|
CMOVQCS R9, BX
|
||||||
|
MOVQ key+24(FP), R8
|
||||||
|
ADDQ 16(R8), AX
|
||||||
|
ADCQ 24(R8), BX
|
||||||
|
|
||||||
|
MOVQ AX, 0(DI)
|
||||||
|
MOVQ BX, 8(DI)
|
||||||
|
RET
|
22
vendor/golang.org/x/crypto/poly1305/sum_arm.go
generated
vendored
Normal file
22
vendor/golang.org/x/crypto/poly1305/sum_arm.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm,!gccgo,!appengine,!nacl
|
||||||
|
|
||||||
|
package poly1305
|
||||||
|
|
||||||
|
// This function is implemented in sum_arm.s
|
||||||
|
//go:noescape
|
||||||
|
func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
|
||||||
|
|
||||||
|
// Sum generates an authenticator for m using a one-time key and puts the
|
||||||
|
// 16-byte result into out. Authenticating two different messages with the same
|
||||||
|
// key allows an attacker to forge messages at will.
|
||||||
|
func Sum(out *[16]byte, m []byte, key *[32]byte) {
|
||||||
|
var mPtr *byte
|
||||||
|
if len(m) > 0 {
|
||||||
|
mPtr = &m[0]
|
||||||
|
}
|
||||||
|
poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
|
||||||
|
}
|
427
vendor/golang.org/x/crypto/poly1305/sum_arm.s
generated
vendored
Normal file
427
vendor/golang.org/x/crypto/poly1305/sum_arm.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
141
vendor/golang.org/x/crypto/poly1305/sum_ref.go
generated
vendored
Normal file
141
vendor/golang.org/x/crypto/poly1305/sum_ref.go
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !amd64,!arm gccgo appengine nacl
|
||||||
|
|
||||||
|
package poly1305
|
||||||
|
|
||||||
|
import "encoding/binary"
|
||||||
|
|
||||||
|
// Sum generates an authenticator for msg using a one-time key and puts the
|
||||||
|
// 16-byte result into out. Authenticating two different messages with the same
|
||||||
|
// key allows an attacker to forge messages at will.
|
||||||
|
func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
|
||||||
|
var (
|
||||||
|
h0, h1, h2, h3, h4 uint32 // the hash accumulators
|
||||||
|
r0, r1, r2, r3, r4 uint64 // the r part of the key
|
||||||
|
)
|
||||||
|
|
||||||
|
r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff)
|
||||||
|
r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03)
|
||||||
|
r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff)
|
||||||
|
r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff)
|
||||||
|
r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff)
|
||||||
|
|
||||||
|
R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
|
||||||
|
|
||||||
|
for len(msg) >= TagSize {
|
||||||
|
// h += msg
|
||||||
|
h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff
|
||||||
|
h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
|
||||||
|
h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
|
||||||
|
h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
|
||||||
|
h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24)
|
||||||
|
|
||||||
|
// h *= r
|
||||||
|
d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
|
||||||
|
d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
|
||||||
|
d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
|
||||||
|
d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
|
||||||
|
d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
|
||||||
|
|
||||||
|
// h %= p
|
||||||
|
h0 = uint32(d0) & 0x3ffffff
|
||||||
|
h1 = uint32(d1) & 0x3ffffff
|
||||||
|
h2 = uint32(d2) & 0x3ffffff
|
||||||
|
h3 = uint32(d3) & 0x3ffffff
|
||||||
|
h4 = uint32(d4) & 0x3ffffff
|
||||||
|
|
||||||
|
h0 += uint32(d4>>26) * 5
|
||||||
|
h1 += h0 >> 26
|
||||||
|
h0 = h0 & 0x3ffffff
|
||||||
|
|
||||||
|
msg = msg[TagSize:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(msg) > 0 {
|
||||||
|
var block [TagSize]byte
|
||||||
|
off := copy(block[:], msg)
|
||||||
|
block[off] = 0x01
|
||||||
|
|
||||||
|
// h += msg
|
||||||
|
h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff
|
||||||
|
h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff
|
||||||
|
h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff
|
||||||
|
h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff
|
||||||
|
h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8)
|
||||||
|
|
||||||
|
// h *= r
|
||||||
|
d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
|
||||||
|
d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
|
||||||
|
d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
|
||||||
|
d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
|
||||||
|
d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
|
||||||
|
|
||||||
|
// h %= p
|
||||||
|
h0 = uint32(d0) & 0x3ffffff
|
||||||
|
h1 = uint32(d1) & 0x3ffffff
|
||||||
|
h2 = uint32(d2) & 0x3ffffff
|
||||||
|
h3 = uint32(d3) & 0x3ffffff
|
||||||
|
h4 = uint32(d4) & 0x3ffffff
|
||||||
|
|
||||||
|
h0 += uint32(d4>>26) * 5
|
||||||
|
h1 += h0 >> 26
|
||||||
|
h0 = h0 & 0x3ffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
// h %= p reduction
|
||||||
|
h2 += h1 >> 26
|
||||||
|
h1 &= 0x3ffffff
|
||||||
|
h3 += h2 >> 26
|
||||||
|
h2 &= 0x3ffffff
|
||||||
|
h4 += h3 >> 26
|
||||||
|
h3 &= 0x3ffffff
|
||||||
|
h0 += 5 * (h4 >> 26)
|
||||||
|
h4 &= 0x3ffffff
|
||||||
|
h1 += h0 >> 26
|
||||||
|
h0 &= 0x3ffffff
|
||||||
|
|
||||||
|
// h - p
|
||||||
|
t0 := h0 + 5
|
||||||
|
t1 := h1 + (t0 >> 26)
|
||||||
|
t2 := h2 + (t1 >> 26)
|
||||||
|
t3 := h3 + (t2 >> 26)
|
||||||
|
t4 := h4 + (t3 >> 26) - (1 << 26)
|
||||||
|
t0 &= 0x3ffffff
|
||||||
|
t1 &= 0x3ffffff
|
||||||
|
t2 &= 0x3ffffff
|
||||||
|
t3 &= 0x3ffffff
|
||||||
|
|
||||||
|
// select h if h < p else h - p
|
||||||
|
t_mask := (t4 >> 31) - 1
|
||||||
|
h_mask := ^t_mask
|
||||||
|
h0 = (h0 & h_mask) | (t0 & t_mask)
|
||||||
|
h1 = (h1 & h_mask) | (t1 & t_mask)
|
||||||
|
h2 = (h2 & h_mask) | (t2 & t_mask)
|
||||||
|
h3 = (h3 & h_mask) | (t3 & t_mask)
|
||||||
|
h4 = (h4 & h_mask) | (t4 & t_mask)
|
||||||
|
|
||||||
|
// h %= 2^128
|
||||||
|
h0 |= h1 << 26
|
||||||
|
h1 = ((h1 >> 6) | (h2 << 20))
|
||||||
|
h2 = ((h2 >> 12) | (h3 << 14))
|
||||||
|
h3 = ((h3 >> 18) | (h4 << 8))
|
||||||
|
|
||||||
|
// s: the s part of the key
|
||||||
|
// tag = (h + s) % (2^128)
|
||||||
|
t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:]))
|
||||||
|
h0 = uint32(t)
|
||||||
|
t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32)
|
||||||
|
h1 = uint32(t)
|
||||||
|
t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32)
|
||||||
|
h2 = uint32(t)
|
||||||
|
t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32)
|
||||||
|
h3 = uint32(t)
|
||||||
|
|
||||||
|
binary.LittleEndian.PutUint32(out[0:], h0)
|
||||||
|
binary.LittleEndian.PutUint32(out[4:], h1)
|
||||||
|
binary.LittleEndian.PutUint32(out[8:], h2)
|
||||||
|
binary.LittleEndian.PutUint32(out[12:], h3)
|
||||||
|
}
|
8
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
8
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
@ -44,7 +44,9 @@ type Signature struct {
|
|||||||
const CertTimeInfinity = 1<<64 - 1
|
const CertTimeInfinity = 1<<64 - 1
|
||||||
|
|
||||||
// An Certificate represents an OpenSSH certificate as defined in
|
// An Certificate represents an OpenSSH certificate as defined in
|
||||||
// [PROTOCOL.certkeys]?rev=1.8.
|
// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the
|
||||||
|
// PublicKey interface, so it can be unmarshaled using
|
||||||
|
// ParsePublicKey.
|
||||||
type Certificate struct {
|
type Certificate struct {
|
||||||
Nonce []byte
|
Nonce []byte
|
||||||
Key PublicKey
|
Key PublicKey
|
||||||
@ -340,10 +342,10 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis
|
|||||||
// the signature of the certificate.
|
// the signature of the certificate.
|
||||||
func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
|
func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
|
||||||
if c.IsRevoked != nil && c.IsRevoked(cert) {
|
if c.IsRevoked != nil && c.IsRevoked(cert) {
|
||||||
return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial)
|
return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial)
|
||||||
}
|
}
|
||||||
|
|
||||||
for opt, _ := range cert.CriticalOptions {
|
for opt := range cert.CriticalOptions {
|
||||||
// sourceAddressCriticalOption will be enforced by
|
// sourceAddressCriticalOption will be enforced by
|
||||||
// serverAuthenticate
|
// serverAuthenticate
|
||||||
if opt == sourceAddressCriticalOption {
|
if opt == sourceAddressCriticalOption {
|
||||||
|
142
vendor/golang.org/x/crypto/ssh/channel.go
generated
vendored
142
vendor/golang.org/x/crypto/ssh/channel.go
generated
vendored
File diff suppressed because it is too large
Load Diff
252
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
252
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
File diff suppressed because it is too large
Load Diff
95
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
95
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
@ -11,6 +11,14 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type authResult int
|
||||||
|
|
||||||
|
const (
|
||||||
|
authFailure authResult = iota
|
||||||
|
authPartialSuccess
|
||||||
|
authSuccess
|
||||||
|
)
|
||||||
|
|
||||||
// clientAuthenticate authenticates with the remote server. See RFC 4252.
|
// clientAuthenticate authenticates with the remote server. See RFC 4252.
|
||||||
func (c *connection) clientAuthenticate(config *ClientConfig) error {
|
func (c *connection) clientAuthenticate(config *ClientConfig) error {
|
||||||
// initiate user auth session
|
// initiate user auth session
|
||||||
@ -37,11 +45,12 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if ok {
|
if ok == authSuccess {
|
||||||
// success
|
// success
|
||||||
return nil
|
return nil
|
||||||
|
} else if ok == authFailure {
|
||||||
|
tried[auth.method()] = true
|
||||||
}
|
}
|
||||||
tried[auth.method()] = true
|
|
||||||
if methods == nil {
|
if methods == nil {
|
||||||
methods = lastMethods
|
methods = lastMethods
|
||||||
}
|
}
|
||||||
@ -82,7 +91,7 @@ type AuthMethod interface {
|
|||||||
// If authentication is not successful, a []string of alternative
|
// If authentication is not successful, a []string of alternative
|
||||||
// method names is returned. If the slice is nil, it will be ignored
|
// method names is returned. If the slice is nil, it will be ignored
|
||||||
// and the previous set of possible methods will be reused.
|
// and the previous set of possible methods will be reused.
|
||||||
auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)
|
auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error)
|
||||||
|
|
||||||
// method returns the RFC 4252 method name.
|
// method returns the RFC 4252 method name.
|
||||||
method() string
|
method() string
|
||||||
@ -91,13 +100,13 @@ type AuthMethod interface {
|
|||||||
// "none" authentication, RFC 4252 section 5.2.
|
// "none" authentication, RFC 4252 section 5.2.
|
||||||
type noneAuth int
|
type noneAuth int
|
||||||
|
|
||||||
func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
|
func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
if err := c.writePacket(Marshal(&userAuthRequestMsg{
|
if err := c.writePacket(Marshal(&userAuthRequestMsg{
|
||||||
User: user,
|
User: user,
|
||||||
Service: serviceSSH,
|
Service: serviceSSH,
|
||||||
Method: "none",
|
Method: "none",
|
||||||
})); err != nil {
|
})); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleAuthResponse(c)
|
return handleAuthResponse(c)
|
||||||
@ -111,7 +120,7 @@ func (n *noneAuth) method() string {
|
|||||||
// a function call, e.g. by prompting the user.
|
// a function call, e.g. by prompting the user.
|
||||||
type passwordCallback func() (password string, err error)
|
type passwordCallback func() (password string, err error)
|
||||||
|
|
||||||
func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
|
func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
type passwordAuthMsg struct {
|
type passwordAuthMsg struct {
|
||||||
User string `sshtype:"50"`
|
User string `sshtype:"50"`
|
||||||
Service string
|
Service string
|
||||||
@ -125,7 +134,7 @@ func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
// The program may only find out that the user doesn't have a password
|
// The program may only find out that the user doesn't have a password
|
||||||
// when prompting.
|
// when prompting.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.writePacket(Marshal(&passwordAuthMsg{
|
if err := c.writePacket(Marshal(&passwordAuthMsg{
|
||||||
@ -135,7 +144,7 @@ func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
Reply: false,
|
Reply: false,
|
||||||
Password: pw,
|
Password: pw,
|
||||||
})); err != nil {
|
})); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleAuthResponse(c)
|
return handleAuthResponse(c)
|
||||||
@ -178,7 +187,7 @@ func (cb publicKeyCallback) method() string {
|
|||||||
return "publickey"
|
return "publickey"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
|
func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
// Authentication is performed by sending an enquiry to test if a key is
|
// Authentication is performed by sending an enquiry to test if a key is
|
||||||
// acceptable to the remote. If the key is acceptable, the client will
|
// acceptable to the remote. If the key is acceptable, the client will
|
||||||
// attempt to authenticate with the valid key. If not the client will repeat
|
// attempt to authenticate with the valid key. If not the client will repeat
|
||||||
@ -186,13 +195,13 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
|
|
||||||
signers, err := cb()
|
signers, err := cb()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
var methods []string
|
var methods []string
|
||||||
for _, signer := range signers {
|
for _, signer := range signers {
|
||||||
ok, err := validateKey(signer.PublicKey(), user, c)
|
ok, err := validateKey(signer.PublicKey(), user, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
@ -206,7 +215,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
Method: cb.method(),
|
Method: cb.method(),
|
||||||
}, []byte(pub.Type()), pubKey))
|
}, []byte(pub.Type()), pubKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// manually wrap the serialized signature in a string
|
// manually wrap the serialized signature in a string
|
||||||
@ -224,24 +233,24 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
}
|
}
|
||||||
p := Marshal(&msg)
|
p := Marshal(&msg)
|
||||||
if err := c.writePacket(p); err != nil {
|
if err := c.writePacket(p); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
var success bool
|
var success authResult
|
||||||
success, methods, err = handleAuthResponse(c)
|
success, methods, err = handleAuthResponse(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If authentication succeeds or the list of available methods does not
|
// If authentication succeeds or the list of available methods does not
|
||||||
// contain the "publickey" method, do not attempt to authenticate with any
|
// contain the "publickey" method, do not attempt to authenticate with any
|
||||||
// other keys. According to RFC 4252 Section 7, the latter can occur when
|
// other keys. According to RFC 4252 Section 7, the latter can occur when
|
||||||
// additional authentication methods are required.
|
// additional authentication methods are required.
|
||||||
if success || !containsMethod(methods, cb.method()) {
|
if success == authSuccess || !containsMethod(methods, cb.method()) {
|
||||||
return success, methods, err
|
return success, methods, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, methods, nil
|
return authFailure, methods, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func containsMethod(methods []string, method string) bool {
|
func containsMethod(methods []string, method string) bool {
|
||||||
@ -318,28 +327,31 @@ func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMet
|
|||||||
// handleAuthResponse returns whether the preceding authentication request succeeded
|
// handleAuthResponse returns whether the preceding authentication request succeeded
|
||||||
// along with a list of remaining authentication methods to try next and
|
// along with a list of remaining authentication methods to try next and
|
||||||
// an error if an unexpected response was received.
|
// an error if an unexpected response was received.
|
||||||
func handleAuthResponse(c packetConn) (bool, []string, error) {
|
func handleAuthResponse(c packetConn) (authResult, []string, error) {
|
||||||
for {
|
for {
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch packet[0] {
|
switch packet[0] {
|
||||||
case msgUserAuthBanner:
|
case msgUserAuthBanner:
|
||||||
if err := handleBannerResponse(c, packet); err != nil {
|
if err := handleBannerResponse(c, packet); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
case msgUserAuthFailure:
|
case msgUserAuthFailure:
|
||||||
var msg userAuthFailureMsg
|
var msg userAuthFailureMsg
|
||||||
if err := Unmarshal(packet, &msg); err != nil {
|
if err := Unmarshal(packet, &msg); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
return false, msg.Methods, nil
|
if msg.PartialSuccess {
|
||||||
|
return authPartialSuccess, msg.Methods, nil
|
||||||
|
}
|
||||||
|
return authFailure, msg.Methods, nil
|
||||||
case msgUserAuthSuccess:
|
case msgUserAuthSuccess:
|
||||||
return true, nil, nil
|
return authSuccess, nil, nil
|
||||||
default:
|
default:
|
||||||
return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
|
return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -381,7 +393,7 @@ func (cb KeyboardInteractiveChallenge) method() string {
|
|||||||
return "keyboard-interactive"
|
return "keyboard-interactive"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
|
func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
|
||||||
type initiateMsg struct {
|
type initiateMsg struct {
|
||||||
User string `sshtype:"50"`
|
User string `sshtype:"50"`
|
||||||
Service string
|
Service string
|
||||||
@ -395,20 +407,20 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||||||
Service: serviceSSH,
|
Service: serviceSSH,
|
||||||
Method: "keyboard-interactive",
|
Method: "keyboard-interactive",
|
||||||
})); err != nil {
|
})); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
packet, err := c.readPacket()
|
packet, err := c.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// like handleAuthResponse, but with less options.
|
// like handleAuthResponse, but with less options.
|
||||||
switch packet[0] {
|
switch packet[0] {
|
||||||
case msgUserAuthBanner:
|
case msgUserAuthBanner:
|
||||||
if err := handleBannerResponse(c, packet); err != nil {
|
if err := handleBannerResponse(c, packet); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
case msgUserAuthInfoRequest:
|
case msgUserAuthInfoRequest:
|
||||||
@ -416,18 +428,21 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||||||
case msgUserAuthFailure:
|
case msgUserAuthFailure:
|
||||||
var msg userAuthFailureMsg
|
var msg userAuthFailureMsg
|
||||||
if err := Unmarshal(packet, &msg); err != nil {
|
if err := Unmarshal(packet, &msg); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
return false, msg.Methods, nil
|
if msg.PartialSuccess {
|
||||||
|
return authPartialSuccess, msg.Methods, nil
|
||||||
|
}
|
||||||
|
return authFailure, msg.Methods, nil
|
||||||
case msgUserAuthSuccess:
|
case msgUserAuthSuccess:
|
||||||
return true, nil, nil
|
return authSuccess, nil, nil
|
||||||
default:
|
default:
|
||||||
return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
|
return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg userAuthInfoRequestMsg
|
var msg userAuthInfoRequestMsg
|
||||||
if err := Unmarshal(packet, &msg); err != nil {
|
if err := Unmarshal(packet, &msg); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manually unpack the prompt/echo pairs.
|
// Manually unpack the prompt/echo pairs.
|
||||||
@ -437,7 +452,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||||||
for i := 0; i < int(msg.NumPrompts); i++ {
|
for i := 0; i < int(msg.NumPrompts); i++ {
|
||||||
prompt, r, ok := parseString(rest)
|
prompt, r, ok := parseString(rest)
|
||||||
if !ok || len(r) == 0 {
|
if !ok || len(r) == 0 {
|
||||||
return false, nil, errors.New("ssh: prompt format error")
|
return authFailure, nil, errors.New("ssh: prompt format error")
|
||||||
}
|
}
|
||||||
prompts = append(prompts, string(prompt))
|
prompts = append(prompts, string(prompt))
|
||||||
echos = append(echos, r[0] != 0)
|
echos = append(echos, r[0] != 0)
|
||||||
@ -445,16 +460,16 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(rest) != 0 {
|
if len(rest) != 0 {
|
||||||
return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
|
return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
|
||||||
}
|
}
|
||||||
|
|
||||||
answers, err := cb(msg.User, msg.Instruction, prompts, echos)
|
answers, err := cb(msg.User, msg.Instruction, prompts, echos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(answers) != len(prompts) {
|
if len(answers) != len(prompts) {
|
||||||
return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
|
return authFailure, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
|
||||||
}
|
}
|
||||||
responseLength := 1 + 4
|
responseLength := 1 + 4
|
||||||
for _, a := range answers {
|
for _, a := range answers {
|
||||||
@ -470,7 +485,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := c.writePacket(serialized); err != nil {
|
if err := c.writePacket(serialized); err != nil {
|
||||||
return false, nil, err
|
return authFailure, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,10 +495,10 @@ type retryableAuthMethod struct {
|
|||||||
maxTries int
|
maxTries int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) {
|
func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) {
|
||||||
for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
|
for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
|
||||||
ok, methods, err = r.authMethod.auth(session, user, c, rand)
|
ok, methods, err = r.authMethod.auth(session, user, c, rand)
|
||||||
if ok || err != nil { // either success or error terminate
|
if ok != authFailure || err != nil { // either success, partial success or error terminate
|
||||||
return ok, methods, err
|
return ok, methods, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
20
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
@ -24,11 +24,21 @@ const (
|
|||||||
serviceSSH = "ssh-connection"
|
serviceSSH = "ssh-connection"
|
||||||
)
|
)
|
||||||
|
|
||||||
// supportedCiphers specifies the supported ciphers in preference order.
|
// supportedCiphers lists ciphers we support but might not recommend.
|
||||||
var supportedCiphers = []string{
|
var supportedCiphers = []string{
|
||||||
"aes128-ctr", "aes192-ctr", "aes256-ctr",
|
"aes128-ctr", "aes192-ctr", "aes256-ctr",
|
||||||
"aes128-gcm@openssh.com",
|
"aes128-gcm@openssh.com",
|
||||||
"arcfour256", "arcfour128",
|
chacha20Poly1305ID,
|
||||||
|
"arcfour256", "arcfour128", "arcfour",
|
||||||
|
aes128cbcID,
|
||||||
|
tripledescbcID,
|
||||||
|
}
|
||||||
|
|
||||||
|
// preferredCiphers specifies the default preference for ciphers.
|
||||||
|
var preferredCiphers = []string{
|
||||||
|
"aes128-gcm@openssh.com",
|
||||||
|
chacha20Poly1305ID,
|
||||||
|
"aes128-ctr", "aes192-ctr", "aes256-ctr",
|
||||||
}
|
}
|
||||||
|
|
||||||
// supportedKexAlgos specifies the supported key-exchange algorithms in
|
// supportedKexAlgos specifies the supported key-exchange algorithms in
|
||||||
@ -211,7 +221,7 @@ func (c *Config) SetDefaults() {
|
|||||||
c.Rand = rand.Reader
|
c.Rand = rand.Reader
|
||||||
}
|
}
|
||||||
if c.Ciphers == nil {
|
if c.Ciphers == nil {
|
||||||
c.Ciphers = supportedCiphers
|
c.Ciphers = preferredCiphers
|
||||||
}
|
}
|
||||||
var ciphers []string
|
var ciphers []string
|
||||||
for _, c := range c.Ciphers {
|
for _, c := range c.Ciphers {
|
||||||
@ -242,7 +252,7 @@ func (c *Config) SetDefaults() {
|
|||||||
|
|
||||||
// buildDataSignedForAuth returns the data that is signed in order to prove
|
// buildDataSignedForAuth returns the data that is signed in order to prove
|
||||||
// possession of a private key. See RFC 4252, section 7.
|
// possession of a private key. See RFC 4252, section 7.
|
||||||
func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
|
func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
|
||||||
data := struct {
|
data := struct {
|
||||||
Session []byte
|
Session []byte
|
||||||
Type byte
|
Type byte
|
||||||
@ -253,7 +263,7 @@ func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubK
|
|||||||
Algo []byte
|
Algo []byte
|
||||||
PubKey []byte
|
PubKey []byte
|
||||||
}{
|
}{
|
||||||
sessionId,
|
sessionID,
|
||||||
msgUserAuthRequest,
|
msgUserAuthRequest,
|
||||||
req.User,
|
req.User,
|
||||||
req.Service,
|
req.Service,
|
||||||
|
24
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
24
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
@ -119,7 +119,7 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
kInt, err := group.diffieHellman(kexDHReply.Y, x)
|
ki, err := group.diffieHellman(kexDHReply.Y, x)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -129,8 +129,8 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
writeString(h, kexDHReply.HostKey)
|
writeString(h, kexDHReply.HostKey)
|
||||||
writeInt(h, X)
|
writeInt(h, X)
|
||||||
writeInt(h, kexDHReply.Y)
|
writeInt(h, kexDHReply.Y)
|
||||||
K := make([]byte, intLength(kInt))
|
K := make([]byte, intLength(ki))
|
||||||
marshalInt(K, kInt)
|
marshalInt(K, ki)
|
||||||
h.Write(K)
|
h.Write(K)
|
||||||
|
|
||||||
return &kexResult{
|
return &kexResult{
|
||||||
@ -164,7 +164,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
}
|
}
|
||||||
|
|
||||||
Y := new(big.Int).Exp(group.g, y, group.p)
|
Y := new(big.Int).Exp(group.g, y, group.p)
|
||||||
kInt, err := group.diffieHellman(kexDHInit.X, y)
|
ki, err := group.diffieHellman(kexDHInit.X, y)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -177,8 +177,8 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
|
|||||||
writeInt(h, kexDHInit.X)
|
writeInt(h, kexDHInit.X)
|
||||||
writeInt(h, Y)
|
writeInt(h, Y)
|
||||||
|
|
||||||
K := make([]byte, intLength(kInt))
|
K := make([]byte, intLength(ki))
|
||||||
marshalInt(K, kInt)
|
marshalInt(K, ki)
|
||||||
h.Write(K)
|
h.Write(K)
|
||||||
|
|
||||||
H := h.Sum(nil)
|
H := h.Sum(nil)
|
||||||
@ -462,9 +462,9 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh
|
|||||||
writeString(h, kp.pub[:])
|
writeString(h, kp.pub[:])
|
||||||
writeString(h, reply.EphemeralPubKey)
|
writeString(h, reply.EphemeralPubKey)
|
||||||
|
|
||||||
kInt := new(big.Int).SetBytes(secret[:])
|
ki := new(big.Int).SetBytes(secret[:])
|
||||||
K := make([]byte, intLength(kInt))
|
K := make([]byte, intLength(ki))
|
||||||
marshalInt(K, kInt)
|
marshalInt(K, ki)
|
||||||
h.Write(K)
|
h.Write(K)
|
||||||
|
|
||||||
return &kexResult{
|
return &kexResult{
|
||||||
@ -510,9 +510,9 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
|
|||||||
writeString(h, kexInit.ClientPubKey)
|
writeString(h, kexInit.ClientPubKey)
|
||||||
writeString(h, kp.pub[:])
|
writeString(h, kp.pub[:])
|
||||||
|
|
||||||
kInt := new(big.Int).SetBytes(secret[:])
|
ki := new(big.Int).SetBytes(secret[:])
|
||||||
K := make([]byte, intLength(kInt))
|
K := make([]byte, intLength(ki))
|
||||||
marshalInt(K, kInt)
|
marshalInt(K, ki)
|
||||||
h.Write(K)
|
h.Write(K)
|
||||||
|
|
||||||
H := h.Sum(nil)
|
H := h.Sum(nil)
|
||||||
|
47
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
47
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
@ -276,7 +276,8 @@ type PublicKey interface {
|
|||||||
Type() string
|
Type() string
|
||||||
|
|
||||||
// Marshal returns the serialized key data in SSH wire format,
|
// Marshal returns the serialized key data in SSH wire format,
|
||||||
// with the name prefix.
|
// with the name prefix. To unmarshal the returned data, use
|
||||||
|
// the ParsePublicKey function.
|
||||||
Marshal() []byte
|
Marshal() []byte
|
||||||
|
|
||||||
// Verify that sig is a signature on the given data using this
|
// Verify that sig is a signature on the given data using this
|
||||||
@ -363,7 +364,7 @@ func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
|
|||||||
|
|
||||||
type dsaPublicKey dsa.PublicKey
|
type dsaPublicKey dsa.PublicKey
|
||||||
|
|
||||||
func (r *dsaPublicKey) Type() string {
|
func (k *dsaPublicKey) Type() string {
|
||||||
return "ssh-dss"
|
return "ssh-dss"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,12 +482,12 @@ func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
|
|||||||
|
|
||||||
type ecdsaPublicKey ecdsa.PublicKey
|
type ecdsaPublicKey ecdsa.PublicKey
|
||||||
|
|
||||||
func (key *ecdsaPublicKey) Type() string {
|
func (k *ecdsaPublicKey) Type() string {
|
||||||
return "ecdsa-sha2-" + key.nistID()
|
return "ecdsa-sha2-" + k.nistID()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (key *ecdsaPublicKey) nistID() string {
|
func (k *ecdsaPublicKey) nistID() string {
|
||||||
switch key.Params().BitSize {
|
switch k.Params().BitSize {
|
||||||
case 256:
|
case 256:
|
||||||
return "nistp256"
|
return "nistp256"
|
||||||
case 384:
|
case 384:
|
||||||
@ -499,7 +500,7 @@ func (key *ecdsaPublicKey) nistID() string {
|
|||||||
|
|
||||||
type ed25519PublicKey ed25519.PublicKey
|
type ed25519PublicKey ed25519.PublicKey
|
||||||
|
|
||||||
func (key ed25519PublicKey) Type() string {
|
func (k ed25519PublicKey) Type() string {
|
||||||
return KeyAlgoED25519
|
return KeyAlgoED25519
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,23 +519,23 @@ func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
|
|||||||
return (ed25519PublicKey)(key), w.Rest, nil
|
return (ed25519PublicKey)(key), w.Rest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (key ed25519PublicKey) Marshal() []byte {
|
func (k ed25519PublicKey) Marshal() []byte {
|
||||||
w := struct {
|
w := struct {
|
||||||
Name string
|
Name string
|
||||||
KeyBytes []byte
|
KeyBytes []byte
|
||||||
}{
|
}{
|
||||||
KeyAlgoED25519,
|
KeyAlgoED25519,
|
||||||
[]byte(key),
|
[]byte(k),
|
||||||
}
|
}
|
||||||
return Marshal(&w)
|
return Marshal(&w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error {
|
func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error {
|
||||||
if sig.Format != key.Type() {
|
if sig.Format != k.Type() {
|
||||||
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
|
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
edKey := (ed25519.PublicKey)(key)
|
edKey := (ed25519.PublicKey)(k)
|
||||||
if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
|
if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
|
||||||
return errors.New("ssh: signature did not verify")
|
return errors.New("ssh: signature did not verify")
|
||||||
}
|
}
|
||||||
@ -595,9 +596,9 @@ func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
|
|||||||
return (*ecdsaPublicKey)(key), w.Rest, nil
|
return (*ecdsaPublicKey)(key), w.Rest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (key *ecdsaPublicKey) Marshal() []byte {
|
func (k *ecdsaPublicKey) Marshal() []byte {
|
||||||
// See RFC 5656, section 3.1.
|
// See RFC 5656, section 3.1.
|
||||||
keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
|
keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
|
||||||
// ECDSA publickey struct layout should match the struct used by
|
// ECDSA publickey struct layout should match the struct used by
|
||||||
// parseECDSACert in the x/crypto/ssh/agent package.
|
// parseECDSACert in the x/crypto/ssh/agent package.
|
||||||
w := struct {
|
w := struct {
|
||||||
@ -605,20 +606,20 @@ func (key *ecdsaPublicKey) Marshal() []byte {
|
|||||||
ID string
|
ID string
|
||||||
Key []byte
|
Key []byte
|
||||||
}{
|
}{
|
||||||
key.Type(),
|
k.Type(),
|
||||||
key.nistID(),
|
k.nistID(),
|
||||||
keyBytes,
|
keyBytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
return Marshal(&w)
|
return Marshal(&w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
|
func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
|
||||||
if sig.Format != key.Type() {
|
if sig.Format != k.Type() {
|
||||||
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
|
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
|
||||||
}
|
}
|
||||||
|
|
||||||
h := ecHash(key.Curve).New()
|
h := ecHash(k.Curve).New()
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
digest := h.Sum(nil)
|
digest := h.Sum(nil)
|
||||||
|
|
||||||
@ -635,7 +636,7 @@ func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
|
if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.New("ssh: signature did not verify")
|
return errors.New("ssh: signature did not verify")
|
||||||
@ -758,7 +759,7 @@ func NewPublicKey(key interface{}) (PublicKey, error) {
|
|||||||
return (*rsaPublicKey)(key), nil
|
return (*rsaPublicKey)(key), nil
|
||||||
case *ecdsa.PublicKey:
|
case *ecdsa.PublicKey:
|
||||||
if !supportedEllipticCurve(key.Curve) {
|
if !supportedEllipticCurve(key.Curve) {
|
||||||
return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.")
|
return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported")
|
||||||
}
|
}
|
||||||
return (*ecdsaPublicKey)(key), nil
|
return (*ecdsaPublicKey)(key), nil
|
||||||
case *dsa.PublicKey:
|
case *dsa.PublicKey:
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user