Add support for Let's Encrypt http-01 challenge
This commit is contained in:
parent
3884a33b36
commit
12ff562d31
32 changed files with 2049 additions and 293 deletions
78
Gopkg.lock
generated
78
Gopkg.lock
generated
|
@ -34,7 +34,11 @@
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/lib/pq"
|
name = "github.com/lib/pq"
|
||||||
packages = [".","hstore","oid"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"hstore",
|
||||||
|
"oid"
|
||||||
|
]
|
||||||
revision = "83612a56d3dd153a94a629cd64925371c9adad78"
|
revision = "83612a56d3dd153a94a629cd64925371c9adad78"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
@ -45,13 +49,23 @@
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/tdewolff/minify"
|
name = "github.com/tdewolff/minify"
|
||||||
packages = [".","css","js"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"css",
|
||||||
|
"js"
|
||||||
|
]
|
||||||
revision = "222672169d634c440a73abc47685074e1a9daa60"
|
revision = "222672169d634c440a73abc47685074e1a9daa60"
|
||||||
version = "v2.3.4"
|
version = "v2.3.4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/tdewolff/parse"
|
name = "github.com/tdewolff/parse"
|
||||||
packages = [".","buffer","css","js","strconv"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"buffer",
|
||||||
|
"css",
|
||||||
|
"js",
|
||||||
|
"strconv"
|
||||||
|
]
|
||||||
revision = "639f6272aec6b52094db77b9ec488214b0b4b1a1"
|
revision = "639f6272aec6b52094db77b9ec488214b0b4b1a1"
|
||||||
version = "v2.3.2"
|
version = "v2.3.2"
|
||||||
|
|
||||||
|
@ -64,36 +78,80 @@
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["acme","acme/autocert","bcrypt","blowfish","ssh/terminal"]
|
packages = [
|
||||||
revision = "94eea52f7b742c7cbe0b03b22f0c4c8631ece122"
|
"acme",
|
||||||
|
"acme/autocert",
|
||||||
|
"bcrypt",
|
||||||
|
"blowfish",
|
||||||
|
"ssh/terminal"
|
||||||
|
]
|
||||||
|
revision = "1875d0a70c90e57f11972aefd42276df65e895b9"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = ["context","context/ctxhttp","html","html/atom","html/charset"]
|
packages = [
|
||||||
|
"context",
|
||||||
|
"context/ctxhttp",
|
||||||
|
"html",
|
||||||
|
"html/atom",
|
||||||
|
"html/charset"
|
||||||
|
]
|
||||||
revision = "d866cfc389cec985d6fda2859936a575a55a3ab6"
|
revision = "d866cfc389cec985d6fda2859936a575a55a3ab6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/oauth2"
|
name = "golang.org/x/oauth2"
|
||||||
packages = [".","internal"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"internal"
|
||||||
|
]
|
||||||
revision = "462316686f20eb6df426961c1c131bdaa5dfa68e"
|
revision = "462316686f20eb6df426961c1c131bdaa5dfa68e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = ["unix","windows"]
|
packages = [
|
||||||
|
"unix",
|
||||||
|
"windows"
|
||||||
|
]
|
||||||
revision = "571f7bbbe08da2a8955aed9d4db316e78630e9a3"
|
revision = "571f7bbbe08da2a8955aed9d4db316e78630e9a3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/text"
|
name = "golang.org/x/text"
|
||||||
packages = ["encoding","encoding/charmap","encoding/htmlindex","encoding/internal","encoding/internal/identifier","encoding/japanese","encoding/korean","encoding/simplifiedchinese","encoding/traditionalchinese","encoding/unicode","internal/gen","internal/tag","internal/utf8internal","language","runes","transform","unicode/cldr"]
|
packages = [
|
||||||
|
"encoding",
|
||||||
|
"encoding/charmap",
|
||||||
|
"encoding/htmlindex",
|
||||||
|
"encoding/internal",
|
||||||
|
"encoding/internal/identifier",
|
||||||
|
"encoding/japanese",
|
||||||
|
"encoding/korean",
|
||||||
|
"encoding/simplifiedchinese",
|
||||||
|
"encoding/traditionalchinese",
|
||||||
|
"encoding/unicode",
|
||||||
|
"internal/gen",
|
||||||
|
"internal/tag",
|
||||||
|
"internal/utf8internal",
|
||||||
|
"language",
|
||||||
|
"runes",
|
||||||
|
"transform",
|
||||||
|
"unicode/cldr"
|
||||||
|
]
|
||||||
revision = "d5a9226ed7dd70cade6ccae9d37517fe14dd9fee"
|
revision = "d5a9226ed7dd70cade6ccae9d37517fe14dd9fee"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "google.golang.org/appengine"
|
name = "google.golang.org/appengine"
|
||||||
packages = ["internal","internal/base","internal/datastore","internal/log","internal/remote_api","internal/urlfetch","urlfetch"]
|
packages = [
|
||||||
|
"internal",
|
||||||
|
"internal/base",
|
||||||
|
"internal/datastore",
|
||||||
|
"internal/log",
|
||||||
|
"internal/remote_api",
|
||||||
|
"internal/urlfetch",
|
||||||
|
"urlfetch"
|
||||||
|
]
|
||||||
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,13 @@ func newServer(cfg *config.Config, store *storage.Storage, pool *scheduler.Worke
|
||||||
HostPolicy: autocert.HostWhitelist(certDomain),
|
HostPolicy: autocert.HostWhitelist(certDomain),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle http-01 challenge.
|
||||||
|
s := &http.Server{
|
||||||
|
Handler: certManager.HTTPHandler(nil),
|
||||||
|
Addr: ":http",
|
||||||
|
}
|
||||||
|
go s.ListenAndServe()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
logger.Info(`Listening on "%s" by using auto-configured certificate for "%s"`, server.Addr, certDomain)
|
logger.Info(`Listening on "%s" by using auto-configured certificate for "%s"`, server.Addr, certDomain)
|
||||||
logger.Fatal(server.Serve(certManager.Listener()).Error())
|
logger.Fatal(server.Serve(certManager.Listener()).Error())
|
||||||
|
|
330
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
330
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
|
@ -24,7 +24,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
mathrand "math/rand"
|
mathrand "math/rand"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -80,8 +82,9 @@ func defaultHostPolicy(context.Context, string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manager is a stateful certificate manager built on top of acme.Client.
|
// Manager is a stateful certificate manager built on top of acme.Client.
|
||||||
// It obtains and refreshes certificates automatically,
|
// It obtains and refreshes certificates automatically using "tls-sni-01",
|
||||||
// as well as providing them to a TLS server via tls.Config.
|
// "tls-sni-02" and "http-01" challenge types, as well as providing them
|
||||||
|
// to a TLS server via tls.Config.
|
||||||
//
|
//
|
||||||
// You must specify a cache implementation, such as DirCache,
|
// You must specify a cache implementation, such as DirCache,
|
||||||
// to reuse obtained certificates across program restarts.
|
// to reuse obtained certificates across program restarts.
|
||||||
|
@ -150,15 +153,26 @@ type Manager struct {
|
||||||
stateMu sync.Mutex
|
stateMu sync.Mutex
|
||||||
state map[string]*certState // keyed by domain name
|
state map[string]*certState // keyed by domain name
|
||||||
|
|
||||||
// tokenCert is keyed by token domain name, which matches server name
|
|
||||||
// of ClientHello. Keys always have ".acme.invalid" suffix.
|
|
||||||
tokenCertMu sync.RWMutex
|
|
||||||
tokenCert map[string]*tls.Certificate
|
|
||||||
|
|
||||||
// renewal tracks the set of domains currently running renewal timers.
|
// renewal tracks the set of domains currently running renewal timers.
|
||||||
// It is keyed by domain name.
|
// It is keyed by domain name.
|
||||||
renewalMu sync.Mutex
|
renewalMu sync.Mutex
|
||||||
renewal map[string]*domainRenewal
|
renewal map[string]*domainRenewal
|
||||||
|
|
||||||
|
// tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens.
|
||||||
|
tokensMu sync.RWMutex
|
||||||
|
// tryHTTP01 indicates whether the Manager should try "http-01" challenge type
|
||||||
|
// during the authorization flow.
|
||||||
|
tryHTTP01 bool
|
||||||
|
// httpTokens contains response body values for http-01 challenges
|
||||||
|
// and is keyed by the URL path at which a challenge response is expected
|
||||||
|
// to be provisioned.
|
||||||
|
// The entries are stored for the duration of the authorization flow.
|
||||||
|
httpTokens map[string][]byte
|
||||||
|
// certTokens contains temporary certificates for tls-sni challenges
|
||||||
|
// and is keyed by token domain name, which matches server name of ClientHello.
|
||||||
|
// Keys always have ".acme.invalid" suffix.
|
||||||
|
// The entries are stored for the duration of the authorization flow.
|
||||||
|
certTokens map[string]*tls.Certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCertificate implements the tls.Config.GetCertificate hook.
|
// GetCertificate implements the tls.Config.GetCertificate hook.
|
||||||
|
@ -185,14 +199,16 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
||||||
return nil, errors.New("acme/autocert: server name contains invalid character")
|
return nil, errors.New("acme/autocert: server name contains invalid character")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In the worst-case scenario, the timeout needs to account for caching, host policy,
|
||||||
|
// domain ownership verification and certificate issuance.
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// check whether this is a token cert requested for TLS-SNI challenge
|
// check whether this is a token cert requested for TLS-SNI challenge
|
||||||
if strings.HasSuffix(name, ".acme.invalid") {
|
if strings.HasSuffix(name, ".acme.invalid") {
|
||||||
m.tokenCertMu.RLock()
|
m.tokensMu.RLock()
|
||||||
defer m.tokenCertMu.RUnlock()
|
defer m.tokensMu.RUnlock()
|
||||||
if cert := m.tokenCert[name]; cert != nil {
|
if cert := m.certTokens[name]; cert != nil {
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
if cert, err := m.cacheGet(ctx, name); err == nil {
|
if cert, err := m.cacheGet(ctx, name); err == nil {
|
||||||
|
@ -224,6 +240,68 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPHandler configures the Manager to provision ACME "http-01" challenge responses.
|
||||||
|
// It returns an http.Handler that responds to the challenges and must be
|
||||||
|
// running on port 80. If it receives a request that is not an ACME challenge,
|
||||||
|
// it delegates the request to the optional fallback handler.
|
||||||
|
//
|
||||||
|
// If fallback is nil, the returned handler redirects all GET and HEAD requests
|
||||||
|
// to the default TLS port 443 with 302 Found status code, preserving the original
|
||||||
|
// request path and query. It responds with 400 Bad Request to all other HTTP methods.
|
||||||
|
// The fallback is not protected by the optional HostPolicy.
|
||||||
|
//
|
||||||
|
// Because the fallback handler is run with unencrypted port 80 requests,
|
||||||
|
// the fallback should not serve TLS-only requests.
|
||||||
|
//
|
||||||
|
// If HTTPHandler is never called, the Manager will only use TLS SNI
|
||||||
|
// challenges for domain verification.
|
||||||
|
func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler {
|
||||||
|
m.tokensMu.Lock()
|
||||||
|
defer m.tokensMu.Unlock()
|
||||||
|
m.tryHTTP01 = true
|
||||||
|
|
||||||
|
if fallback == nil {
|
||||||
|
fallback = http.HandlerFunc(handleHTTPRedirect)
|
||||||
|
}
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !strings.HasPrefix(r.URL.Path, "/.well-known/acme-challenge/") {
|
||||||
|
fallback.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// A reasonable context timeout for cache and host policy only,
|
||||||
|
// because we don't wait for a new certificate issuance here.
|
||||||
|
ctx, cancel := context.WithTimeout(r.Context(), time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
if err := m.hostPolicy()(ctx, r.Host); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data, err := m.httpToken(ctx, r.URL.Path)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Write(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleHTTPRedirect(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != "GET" && r.Method != "HEAD" {
|
||||||
|
http.Error(w, "Use HTTPS", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
target := "https://" + stripPort(r.Host) + r.URL.RequestURI()
|
||||||
|
http.Redirect(w, r, target, http.StatusFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func stripPort(hostport string) string {
|
||||||
|
host, _, err := net.SplitHostPort(hostport)
|
||||||
|
if err != nil {
|
||||||
|
return hostport
|
||||||
|
}
|
||||||
|
return net.JoinHostPort(host, "443")
|
||||||
|
}
|
||||||
|
|
||||||
// cert returns an existing certificate either from m.state or cache.
|
// cert returns an existing certificate either from m.state or cache.
|
||||||
// If a certificate is found in cache but not in m.state, the latter will be filled
|
// If a certificate is found in cache but not in m.state, the latter will be filled
|
||||||
// with the cached value.
|
// with the cached value.
|
||||||
|
@ -442,13 +520,14 @@ func (m *Manager) certState(domain string) (*certState, error) {
|
||||||
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
|
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
|
||||||
// The key argument is the certificate private key.
|
// The key argument is the certificate private key.
|
||||||
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
|
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
|
||||||
if err := m.verify(ctx, domain); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
client, err := m.acmeClient(ctx)
|
client, err := m.acmeClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := m.verify(ctx, client, domain); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
csr, err := certRequest(key, domain)
|
csr, err := certRequest(key, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -464,98 +543,171 @@ func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain
|
||||||
return der, leaf, nil
|
return der, leaf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify starts a new identifier (domain) authorization flow.
|
// verify runs the identifier (domain) authorization flow
|
||||||
// It prepares a challenge response and then blocks until the authorization
|
// using each applicable ACME challenge type.
|
||||||
// is marked as "completed" by the CA (either succeeded or failed).
|
func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error {
|
||||||
//
|
// The list of challenge types we'll try to fulfill
|
||||||
// verify returns nil iff the verification was successful.
|
// in this specific order.
|
||||||
func (m *Manager) verify(ctx context.Context, domain string) error {
|
challengeTypes := []string{"tls-sni-02", "tls-sni-01"}
|
||||||
client, err := m.acmeClient(ctx)
|
m.tokensMu.RLock()
|
||||||
if err != nil {
|
if m.tryHTTP01 {
|
||||||
return err
|
challengeTypes = append(challengeTypes, "http-01")
|
||||||
}
|
}
|
||||||
|
m.tokensMu.RUnlock()
|
||||||
|
|
||||||
// start domain authorization and get the challenge
|
var nextTyp int // challengeType index of the next challenge type to try
|
||||||
authz, err := client.Authorize(ctx, domain)
|
for {
|
||||||
if err != nil {
|
// Start domain authorization and get the challenge.
|
||||||
return err
|
authz, err := client.Authorize(ctx, domain)
|
||||||
}
|
if err != nil {
|
||||||
// maybe don't need to at all
|
return err
|
||||||
if authz.Status == acme.StatusValid {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// pick a challenge: prefer tls-sni-02 over tls-sni-01
|
|
||||||
// TODO: consider authz.Combinations
|
|
||||||
var chal *acme.Challenge
|
|
||||||
for _, c := range authz.Challenges {
|
|
||||||
if c.Type == "tls-sni-02" {
|
|
||||||
chal = c
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
if c.Type == "tls-sni-01" {
|
// No point in accepting challenges if the authorization status
|
||||||
chal = c
|
// is in a final state.
|
||||||
|
switch authz.Status {
|
||||||
|
case acme.StatusValid:
|
||||||
|
return nil // already authorized
|
||||||
|
case acme.StatusInvalid:
|
||||||
|
return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick the next preferred challenge.
|
||||||
|
var chal *acme.Challenge
|
||||||
|
for chal == nil && nextTyp < len(challengeTypes) {
|
||||||
|
chal = pickChallenge(challengeTypes[nextTyp], authz.Challenges)
|
||||||
|
nextTyp++
|
||||||
|
}
|
||||||
|
if chal == nil {
|
||||||
|
return fmt.Errorf("acme/autocert: unable to authorize %q; tried %q", domain, challengeTypes)
|
||||||
|
}
|
||||||
|
cleanup, err := m.fulfill(ctx, client, chal)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
if _, err := client.Accept(ctx, chal); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// A challenge is fulfilled and accepted: wait for the CA to validate.
|
||||||
|
if _, err := client.WaitAuthorization(ctx, authz.URI); err == nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if chal == nil {
|
|
||||||
return errors.New("acme/autocert: no supported challenge type found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a token cert for the challenge response
|
|
||||||
var (
|
|
||||||
cert tls.Certificate
|
|
||||||
name string
|
|
||||||
)
|
|
||||||
switch chal.Type {
|
|
||||||
case "tls-sni-01":
|
|
||||||
cert, name, err = client.TLSSNI01ChallengeCert(chal.Token)
|
|
||||||
case "tls-sni-02":
|
|
||||||
cert, name, err = client.TLSSNI02ChallengeCert(chal.Token)
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
m.putTokenCert(ctx, name, &cert)
|
|
||||||
defer func() {
|
|
||||||
// verification has ended at this point
|
|
||||||
// don't need token cert anymore
|
|
||||||
go m.deleteTokenCert(name)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// ready to fulfill the challenge
|
|
||||||
if _, err := client.Accept(ctx, chal); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// wait for the CA to validate
|
|
||||||
_, err = client.WaitAuthorization(ctx, authz.URI)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// putTokenCert stores the cert under the named key in both m.tokenCert map
|
// fulfill provisions a response to the challenge chal.
|
||||||
// and m.Cache.
|
// The cleanup is non-nil only if provisioning succeeded.
|
||||||
func (m *Manager) putTokenCert(ctx context.Context, name string, cert *tls.Certificate) {
|
func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge) (cleanup func(), err error) {
|
||||||
m.tokenCertMu.Lock()
|
switch chal.Type {
|
||||||
defer m.tokenCertMu.Unlock()
|
case "tls-sni-01":
|
||||||
if m.tokenCert == nil {
|
cert, name, err := client.TLSSNI01ChallengeCert(chal.Token)
|
||||||
m.tokenCert = make(map[string]*tls.Certificate)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m.putCertToken(ctx, name, &cert)
|
||||||
|
return func() { go m.deleteCertToken(name) }, nil
|
||||||
|
case "tls-sni-02":
|
||||||
|
cert, name, err := client.TLSSNI02ChallengeCert(chal.Token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m.putCertToken(ctx, name, &cert)
|
||||||
|
return func() { go m.deleteCertToken(name) }, nil
|
||||||
|
case "http-01":
|
||||||
|
resp, err := client.HTTP01ChallengeResponse(chal.Token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p := client.HTTP01ChallengePath(chal.Token)
|
||||||
|
m.putHTTPToken(ctx, p, resp)
|
||||||
|
return func() { go m.deleteHTTPToken(p) }, nil
|
||||||
}
|
}
|
||||||
m.tokenCert[name] = cert
|
return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge {
|
||||||
|
for _, c := range chal {
|
||||||
|
if c.Type == typ {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// putCertToken stores the cert under the named key in both m.certTokens map
|
||||||
|
// and m.Cache.
|
||||||
|
func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) {
|
||||||
|
m.tokensMu.Lock()
|
||||||
|
defer m.tokensMu.Unlock()
|
||||||
|
if m.certTokens == nil {
|
||||||
|
m.certTokens = make(map[string]*tls.Certificate)
|
||||||
|
}
|
||||||
|
m.certTokens[name] = cert
|
||||||
m.cachePut(ctx, name, cert)
|
m.cachePut(ctx, name, cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteTokenCert removes the token certificate for the specified domain name
|
// deleteCertToken removes the token certificate for the specified domain name
|
||||||
// from both m.tokenCert map and m.Cache.
|
// from both m.certTokens map and m.Cache.
|
||||||
func (m *Manager) deleteTokenCert(name string) {
|
func (m *Manager) deleteCertToken(name string) {
|
||||||
m.tokenCertMu.Lock()
|
m.tokensMu.Lock()
|
||||||
defer m.tokenCertMu.Unlock()
|
defer m.tokensMu.Unlock()
|
||||||
delete(m.tokenCert, name)
|
delete(m.certTokens, name)
|
||||||
if m.Cache != nil {
|
if m.Cache != nil {
|
||||||
m.Cache.Delete(context.Background(), name)
|
m.Cache.Delete(context.Background(), name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// httpToken retrieves an existing http-01 token value from an in-memory map
|
||||||
|
// or the optional cache.
|
||||||
|
func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) {
|
||||||
|
m.tokensMu.RLock()
|
||||||
|
defer m.tokensMu.RUnlock()
|
||||||
|
if v, ok := m.httpTokens[tokenPath]; ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
if m.Cache == nil {
|
||||||
|
return nil, fmt.Errorf("acme/autocert: no token at %q", tokenPath)
|
||||||
|
}
|
||||||
|
return m.Cache.Get(ctx, httpTokenCacheKey(tokenPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
// putHTTPToken stores an http-01 token value using tokenPath as key
|
||||||
|
// in both in-memory map and the optional Cache.
|
||||||
|
//
|
||||||
|
// It ignores any error returned from Cache.Put.
|
||||||
|
func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) {
|
||||||
|
m.tokensMu.Lock()
|
||||||
|
defer m.tokensMu.Unlock()
|
||||||
|
if m.httpTokens == nil {
|
||||||
|
m.httpTokens = make(map[string][]byte)
|
||||||
|
}
|
||||||
|
b := []byte(val)
|
||||||
|
m.httpTokens[tokenPath] = b
|
||||||
|
if m.Cache != nil {
|
||||||
|
m.Cache.Put(ctx, httpTokenCacheKey(tokenPath), b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteHTTPToken removes an http-01 token value from both in-memory map
|
||||||
|
// and the optional Cache, ignoring any error returned from the latter.
|
||||||
|
//
|
||||||
|
// If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout.
|
||||||
|
func (m *Manager) deleteHTTPToken(tokenPath string) {
|
||||||
|
m.tokensMu.Lock()
|
||||||
|
defer m.tokensMu.Unlock()
|
||||||
|
delete(m.httpTokens, tokenPath)
|
||||||
|
if m.Cache != nil {
|
||||||
|
m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// httpTokenCacheKey returns a key at which an http-01 token value may be stored
|
||||||
|
// in the Manager's optional Cache.
|
||||||
|
func httpTokenCacheKey(tokenPath string) string {
|
||||||
|
return "http-01-" + path.Base(tokenPath)
|
||||||
|
}
|
||||||
|
|
||||||
// renew starts a cert renewal timer loop, one per domain.
|
// renew starts a cert renewal timer loop, one per domain.
|
||||||
//
|
//
|
||||||
// The loop is scheduled in two cases:
|
// The loop is scheduled in two cases:
|
||||||
|
|
151
vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
generated
vendored
151
vendor/golang.org/x/crypto/acme/autocert/autocert_test.go
generated
vendored
|
@ -23,6 +23,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -48,6 +49,16 @@ var authzTmpl = template.Must(template.New("authz").Parse(`{
|
||||||
"uri": "{{.}}/challenge/2",
|
"uri": "{{.}}/challenge/2",
|
||||||
"type": "tls-sni-02",
|
"type": "tls-sni-02",
|
||||||
"token": "token-02"
|
"token": "token-02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "{{.}}/challenge/dns-01",
|
||||||
|
"type": "dns-01",
|
||||||
|
"token": "token-dns-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "{{.}}/challenge/http-01",
|
||||||
|
"type": "http-01",
|
||||||
|
"token": "token-http-01"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`))
|
}`))
|
||||||
|
@ -419,6 +430,146 @@ func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.Cl
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVerifyHTTP01(t *testing.T) {
|
||||||
|
var (
|
||||||
|
http01 http.Handler
|
||||||
|
|
||||||
|
authzCount int // num. of created authorizations
|
||||||
|
didAcceptHTTP01 bool
|
||||||
|
)
|
||||||
|
|
||||||
|
verifyHTTPToken := func() {
|
||||||
|
r := httptest.NewRequest("GET", "/.well-known/acme-challenge/token-http-01", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
http01.ServeHTTP(w, r)
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK)
|
||||||
|
}
|
||||||
|
if v := string(w.Body.Bytes()); !strings.HasPrefix(v, "token-http-01.") {
|
||||||
|
t.Errorf("http token value = %q; want 'token-http-01.' prefix", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACME CA server stub, only the needed bits.
|
||||||
|
// TODO: Merge this with startACMEServerStub, making it a configurable CA for testing.
|
||||||
|
var ca *httptest.Server
|
||||||
|
ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Replay-Nonce", "nonce")
|
||||||
|
if r.Method == "HEAD" {
|
||||||
|
// a nonce request
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r.URL.Path {
|
||||||
|
// Discovery.
|
||||||
|
case "/":
|
||||||
|
if err := discoTmpl.Execute(w, ca.URL); err != nil {
|
||||||
|
t.Errorf("discoTmpl: %v", err)
|
||||||
|
}
|
||||||
|
// Client key registration.
|
||||||
|
case "/new-reg":
|
||||||
|
w.Write([]byte("{}"))
|
||||||
|
// New domain authorization.
|
||||||
|
case "/new-authz":
|
||||||
|
authzCount++
|
||||||
|
w.Header().Set("Location", fmt.Sprintf("%s/authz/%d", ca.URL, authzCount))
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
if err := authzTmpl.Execute(w, ca.URL); err != nil {
|
||||||
|
t.Errorf("authzTmpl: %v", err)
|
||||||
|
}
|
||||||
|
// Accept tls-sni-02.
|
||||||
|
case "/challenge/2":
|
||||||
|
w.Write([]byte("{}"))
|
||||||
|
// Reject tls-sni-01.
|
||||||
|
case "/challenge/1":
|
||||||
|
http.Error(w, "won't accept tls-sni-01", http.StatusBadRequest)
|
||||||
|
// Should not accept dns-01.
|
||||||
|
case "/challenge/dns-01":
|
||||||
|
t.Errorf("dns-01 challenge was accepted")
|
||||||
|
http.Error(w, "won't accept dns-01", http.StatusBadRequest)
|
||||||
|
// Accept http-01.
|
||||||
|
case "/challenge/http-01":
|
||||||
|
didAcceptHTTP01 = true
|
||||||
|
verifyHTTPToken()
|
||||||
|
w.Write([]byte("{}"))
|
||||||
|
// Authorization statuses.
|
||||||
|
// Make tls-sni-xxx invalid.
|
||||||
|
case "/authz/1", "/authz/2":
|
||||||
|
w.Write([]byte(`{"status": "invalid"}`))
|
||||||
|
case "/authz/3", "/authz/4":
|
||||||
|
w.Write([]byte(`{"status": "valid"}`))
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
defer ca.Close()
|
||||||
|
|
||||||
|
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
m := &Manager{
|
||||||
|
Client: &acme.Client{
|
||||||
|
Key: key,
|
||||||
|
DirectoryURL: ca.URL,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
http01 = m.HTTPHandler(nil)
|
||||||
|
if err := m.verify(context.Background(), m.Client, "example.org"); err != nil {
|
||||||
|
t.Errorf("m.verify: %v", err)
|
||||||
|
}
|
||||||
|
// Only tls-sni-01, tls-sni-02 and http-01 must be accepted
|
||||||
|
// The dns-01 challenge is unsupported.
|
||||||
|
if authzCount != 3 {
|
||||||
|
t.Errorf("authzCount = %d; want 3", authzCount)
|
||||||
|
}
|
||||||
|
if !didAcceptHTTP01 {
|
||||||
|
t.Error("did not accept http-01 challenge")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHTTPHandlerDefaultFallback(t *testing.T) {
|
||||||
|
tt := []struct {
|
||||||
|
method, url string
|
||||||
|
wantCode int
|
||||||
|
wantLocation string
|
||||||
|
}{
|
||||||
|
{"GET", "http://example.org", 302, "https://example.org/"},
|
||||||
|
{"GET", "http://example.org/foo", 302, "https://example.org/foo"},
|
||||||
|
{"GET", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"},
|
||||||
|
{"GET", "http://example.org/?a=b", 302, "https://example.org/?a=b"},
|
||||||
|
{"GET", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"},
|
||||||
|
{"GET", "http://example.org:80/foo?a=b", 302, "https://example.org:443/foo?a=b"},
|
||||||
|
{"GET", "http://example.org:80/foo%20bar", 302, "https://example.org:443/foo%20bar"},
|
||||||
|
{"GET", "http://[2602:d1:xxxx::c60a]:1234", 302, "https://[2602:d1:xxxx::c60a]:443/"},
|
||||||
|
{"GET", "http://[2602:d1:xxxx::c60a]", 302, "https://[2602:d1:xxxx::c60a]/"},
|
||||||
|
{"GET", "http://[2602:d1:xxxx::c60a]/foo?a=b", 302, "https://[2602:d1:xxxx::c60a]/foo?a=b"},
|
||||||
|
{"HEAD", "http://example.org", 302, "https://example.org/"},
|
||||||
|
{"HEAD", "http://example.org/foo", 302, "https://example.org/foo"},
|
||||||
|
{"HEAD", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"},
|
||||||
|
{"HEAD", "http://example.org/?a=b", 302, "https://example.org/?a=b"},
|
||||||
|
{"HEAD", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"},
|
||||||
|
{"POST", "http://example.org", 400, ""},
|
||||||
|
{"PUT", "http://example.org", 400, ""},
|
||||||
|
{"GET", "http://example.org/.well-known/acme-challenge/x", 404, ""},
|
||||||
|
}
|
||||||
|
var m Manager
|
||||||
|
h := m.HTTPHandler(nil)
|
||||||
|
for i, test := range tt {
|
||||||
|
r := httptest.NewRequest(test.method, test.url, nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
if w.Code != test.wantCode {
|
||||||
|
t.Errorf("%d: w.Code = %d; want %d", i, w.Code, test.wantCode)
|
||||||
|
t.Errorf("%d: body: %s", i, w.Body.Bytes())
|
||||||
|
}
|
||||||
|
if v := w.Header().Get("Location"); v != test.wantLocation {
|
||||||
|
t.Errorf("%d: Location = %q; want %q", i, v, test.wantLocation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAccountKeyCache(t *testing.T) {
|
func TestAccountKeyCache(t *testing.T) {
|
||||||
m := Manager{Cache: newMemCache()}
|
m := Manager{Cache: newMemCache()}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
3
vendor/golang.org/x/crypto/acme/autocert/example_test.go
generated
vendored
3
vendor/golang.org/x/crypto/acme/autocert/example_test.go
generated
vendored
|
@ -22,11 +22,12 @@ func ExampleNewListener() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleManager() {
|
func ExampleManager() {
|
||||||
m := autocert.Manager{
|
m := &autocert.Manager{
|
||||||
Cache: autocert.DirCache("secret-dir"),
|
Cache: autocert.DirCache("secret-dir"),
|
||||||
Prompt: autocert.AcceptTOS,
|
Prompt: autocert.AcceptTOS,
|
||||||
HostPolicy: autocert.HostWhitelist("example.org"),
|
HostPolicy: autocert.HostWhitelist("example.org"),
|
||||||
}
|
}
|
||||||
|
go http.ListenAndServe(":http", m.HTTPHandler(nil))
|
||||||
s := &http.Server{
|
s := &http.Server{
|
||||||
Addr: ":https",
|
Addr: ":https",
|
||||||
TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
|
TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
|
||||||
|
|
228
vendor/golang.org/x/crypto/argon2/argon2.go
generated
vendored
Normal file
228
vendor/golang.org/x/crypto/argon2/argon2.go
generated
vendored
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
// 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 argon2 implements the key derivation function Argon2.
|
||||||
|
// Argon2 was selected as the winner of the Password Hashing Competition and can
|
||||||
|
// be used to derive cryptographic keys from passwords.
|
||||||
|
// Argon2 is specfifed at https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
|
||||||
|
package argon2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/blake2b"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The Argon2 version implemented by this package.
|
||||||
|
const Version = 0x13
|
||||||
|
|
||||||
|
const (
|
||||||
|
argon2d = iota
|
||||||
|
argon2i
|
||||||
|
argon2id
|
||||||
|
)
|
||||||
|
|
||||||
|
// Key derives a key from the password, salt, and cost parameters using Argon2i
|
||||||
|
// returning a byte slice of length keyLen that can be used as cryptographic key.
|
||||||
|
// The CPU cost and parallism degree must be greater than zero.
|
||||||
|
//
|
||||||
|
// For example, you can get a derived key for e.g. AES-256 (which needs a 32-byte key) by doing:
|
||||||
|
// `key := argon2.Key([]byte("some password"), salt, 4, 32*1024, 4, 32)`
|
||||||
|
//
|
||||||
|
// The recommended parameters for interactive logins as of 2017 are time=4, memory=32*1024.
|
||||||
|
// The number of threads can be adjusted to the numbers of available CPUs.
|
||||||
|
// The time parameter specifies the number of passes over the memory and the memory
|
||||||
|
// parameter specifies the size of the memory in KiB. For example memory=32*1024 sets the
|
||||||
|
// memory cost to ~32 MB.
|
||||||
|
// The cost parameters should be increased as memory latency and CPU parallelism increases.
|
||||||
|
// Remember to get a good random salt.
|
||||||
|
func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
|
||||||
|
return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
|
||||||
|
if time < 1 {
|
||||||
|
panic("argon2: number of rounds too small")
|
||||||
|
}
|
||||||
|
if threads < 1 {
|
||||||
|
panic("argon2: parallelism degree too low")
|
||||||
|
}
|
||||||
|
h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode)
|
||||||
|
|
||||||
|
memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads))
|
||||||
|
if memory < 2*syncPoints*uint32(threads) {
|
||||||
|
memory = 2 * syncPoints * uint32(threads)
|
||||||
|
}
|
||||||
|
B := initBlocks(&h0, memory, uint32(threads))
|
||||||
|
processBlocks(B, time, memory, uint32(threads), mode)
|
||||||
|
return extractKey(B, memory, uint32(threads), keyLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
blockLength = 128
|
||||||
|
syncPoints = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
type block [blockLength]uint64
|
||||||
|
|
||||||
|
func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte {
|
||||||
|
var (
|
||||||
|
h0 [blake2b.Size + 8]byte
|
||||||
|
params [24]byte
|
||||||
|
tmp [4]byte
|
||||||
|
)
|
||||||
|
|
||||||
|
b2, _ := blake2b.New512(nil)
|
||||||
|
binary.LittleEndian.PutUint32(params[0:4], threads)
|
||||||
|
binary.LittleEndian.PutUint32(params[4:8], keyLen)
|
||||||
|
binary.LittleEndian.PutUint32(params[8:12], memory)
|
||||||
|
binary.LittleEndian.PutUint32(params[12:16], time)
|
||||||
|
binary.LittleEndian.PutUint32(params[16:20], uint32(Version))
|
||||||
|
binary.LittleEndian.PutUint32(params[20:24], uint32(mode))
|
||||||
|
b2.Write(params[:])
|
||||||
|
binary.LittleEndian.PutUint32(tmp[:], uint32(len(password)))
|
||||||
|
b2.Write(tmp[:])
|
||||||
|
b2.Write(password)
|
||||||
|
binary.LittleEndian.PutUint32(tmp[:], uint32(len(salt)))
|
||||||
|
b2.Write(tmp[:])
|
||||||
|
b2.Write(salt)
|
||||||
|
binary.LittleEndian.PutUint32(tmp[:], uint32(len(key)))
|
||||||
|
b2.Write(tmp[:])
|
||||||
|
b2.Write(key)
|
||||||
|
binary.LittleEndian.PutUint32(tmp[:], uint32(len(data)))
|
||||||
|
b2.Write(tmp[:])
|
||||||
|
b2.Write(data)
|
||||||
|
b2.Sum(h0[:0])
|
||||||
|
return h0
|
||||||
|
}
|
||||||
|
|
||||||
|
func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block {
|
||||||
|
var block0 [1024]byte
|
||||||
|
B := make([]block, memory)
|
||||||
|
for lane := uint32(0); lane < threads; lane++ {
|
||||||
|
j := lane * (memory / threads)
|
||||||
|
binary.LittleEndian.PutUint32(h0[blake2b.Size+4:], lane)
|
||||||
|
|
||||||
|
binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0)
|
||||||
|
blake2bHash(block0[:], h0[:])
|
||||||
|
for i := range B[j+0] {
|
||||||
|
B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:])
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1)
|
||||||
|
blake2bHash(block0[:], h0[:])
|
||||||
|
for i := range B[j+1] {
|
||||||
|
B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBlocks(B []block, time, memory, threads uint32, mode int) {
|
||||||
|
lanes := memory / threads
|
||||||
|
segments := lanes / syncPoints
|
||||||
|
|
||||||
|
processSegment := func(n, slice, lane uint32, wg *sync.WaitGroup) {
|
||||||
|
var addresses, in, zero block
|
||||||
|
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
|
||||||
|
in[0] = uint64(n)
|
||||||
|
in[1] = uint64(lane)
|
||||||
|
in[2] = uint64(slice)
|
||||||
|
in[3] = uint64(memory)
|
||||||
|
in[4] = uint64(time)
|
||||||
|
in[5] = uint64(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
index := uint32(0)
|
||||||
|
if n == 0 && slice == 0 {
|
||||||
|
index = 2 // we have already generated the first two blocks
|
||||||
|
if mode == argon2i || mode == argon2id {
|
||||||
|
in[6]++
|
||||||
|
processBlock(&addresses, &in, &zero)
|
||||||
|
processBlock(&addresses, &addresses, &zero)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := lane*lanes + slice*segments + index
|
||||||
|
var random uint64
|
||||||
|
for index < segments {
|
||||||
|
prev := offset - 1
|
||||||
|
if index == 0 && slice == 0 {
|
||||||
|
prev += lanes // last block in lane
|
||||||
|
}
|
||||||
|
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
|
||||||
|
if index%blockLength == 0 {
|
||||||
|
in[6]++
|
||||||
|
processBlock(&addresses, &in, &zero)
|
||||||
|
processBlock(&addresses, &addresses, &zero)
|
||||||
|
}
|
||||||
|
random = addresses[index%blockLength]
|
||||||
|
} else {
|
||||||
|
random = B[prev][0]
|
||||||
|
}
|
||||||
|
newOffset := indexAlpha(random, lanes, segments, threads, n, slice, lane, index)
|
||||||
|
processBlockXOR(&B[offset], &B[prev], &B[newOffset])
|
||||||
|
index, offset = index+1, offset+1
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
for n := uint32(0); n < time; n++ {
|
||||||
|
for slice := uint32(0); slice < syncPoints; slice++ {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for lane := uint32(0); lane < threads; lane++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go processSegment(n, slice, lane, &wg)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractKey(B []block, memory, threads, keyLen uint32) []byte {
|
||||||
|
lanes := memory / threads
|
||||||
|
for lane := uint32(0); lane < threads-1; lane++ {
|
||||||
|
for i, v := range B[(lane*lanes)+lanes-1] {
|
||||||
|
B[memory-1][i] ^= v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var block [1024]byte
|
||||||
|
for i, v := range B[memory-1] {
|
||||||
|
binary.LittleEndian.PutUint64(block[i*8:], v)
|
||||||
|
}
|
||||||
|
key := make([]byte, keyLen)
|
||||||
|
blake2bHash(key, block[:])
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 {
|
||||||
|
refLane := uint32(rand>>32) % threads
|
||||||
|
if n == 0 && slice == 0 {
|
||||||
|
refLane = lane
|
||||||
|
}
|
||||||
|
m, s := 3*segments, ((slice+1)%syncPoints)*segments
|
||||||
|
if lane == refLane {
|
||||||
|
m += index
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
m, s = slice*segments, 0
|
||||||
|
if slice == 0 || lane == refLane {
|
||||||
|
m += index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index == 0 || lane == refLane {
|
||||||
|
m--
|
||||||
|
}
|
||||||
|
return phi(rand, uint64(m), uint64(s), refLane, lanes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func phi(rand, m, s uint64, lane, lanes uint32) uint32 {
|
||||||
|
p := rand & 0xFFFFFFFF
|
||||||
|
p = (p * p) >> 32
|
||||||
|
p = (p * m) >> 32
|
||||||
|
return lane*lanes + uint32((s+m-(p+1))%uint64(lanes))
|
||||||
|
}
|
233
vendor/golang.org/x/crypto/argon2/argon2_test.go
generated
vendored
Normal file
233
vendor/golang.org/x/crypto/argon2/argon2_test.go
generated
vendored
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
// 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 argon2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
genKatPassword = []byte{
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||||
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||||
|
}
|
||||||
|
genKatSalt = []byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}
|
||||||
|
genKatSecret = []byte{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}
|
||||||
|
genKatAAD = []byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestArgon2(t *testing.T) {
|
||||||
|
defer func(sse4 bool) { useSSE4 = sse4 }(useSSE4)
|
||||||
|
|
||||||
|
if useSSE4 {
|
||||||
|
t.Log("SSE4.1 version")
|
||||||
|
testArgon2i(t)
|
||||||
|
testArgon2d(t)
|
||||||
|
testArgon2id(t)
|
||||||
|
useSSE4 = false
|
||||||
|
}
|
||||||
|
t.Log("generic version")
|
||||||
|
testArgon2i(t)
|
||||||
|
testArgon2d(t)
|
||||||
|
testArgon2id(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testArgon2d(t *testing.T) {
|
||||||
|
want := []byte{
|
||||||
|
0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97,
|
||||||
|
0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94,
|
||||||
|
0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1,
|
||||||
|
0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb,
|
||||||
|
}
|
||||||
|
hash := deriveKey(argon2d, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
|
||||||
|
if !bytes.Equal(hash, want) {
|
||||||
|
t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testArgon2i(t *testing.T) {
|
||||||
|
want := []byte{
|
||||||
|
0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa,
|
||||||
|
0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1,
|
||||||
|
0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2,
|
||||||
|
0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8,
|
||||||
|
}
|
||||||
|
hash := deriveKey(argon2i, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
|
||||||
|
if !bytes.Equal(hash, want) {
|
||||||
|
t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testArgon2id(t *testing.T) {
|
||||||
|
want := []byte{
|
||||||
|
0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c,
|
||||||
|
0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9,
|
||||||
|
0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e,
|
||||||
|
0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59,
|
||||||
|
}
|
||||||
|
hash := deriveKey(argon2id, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32)
|
||||||
|
if !bytes.Equal(hash, want) {
|
||||||
|
t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVectors(t *testing.T) {
|
||||||
|
password, salt := []byte("password"), []byte("somesalt")
|
||||||
|
for i, v := range testVectors {
|
||||||
|
want, err := hex.DecodeString(v.hash)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Test %d: failed to decode hash: %v", i, err)
|
||||||
|
}
|
||||||
|
hash := deriveKey(v.mode, password, salt, nil, nil, v.time, v.memory, v.threads, uint32(len(want)))
|
||||||
|
if !bytes.Equal(hash, want) {
|
||||||
|
t.Errorf("Test %d - got: %s want: %s", i, hex.EncodeToString(hash), hex.EncodeToString(want))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkArgon2(mode int, time, memory uint32, threads uint8, keyLen uint32, b *testing.B) {
|
||||||
|
password := []byte("password")
|
||||||
|
salt := []byte("choosing random salts is hard")
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
deriveKey(mode, password, salt, nil, nil, time, memory, threads, keyLen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArgon2i(b *testing.B) {
|
||||||
|
b.Run(" Time: 3 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 4 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 5 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 3 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 64*1024, 4, 32, b) })
|
||||||
|
b.Run(" Time: 4 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 64*1024, 4, 32, b) })
|
||||||
|
b.Run(" Time: 5 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 64*1024, 4, 32, b) })
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArgon2d(b *testing.B) {
|
||||||
|
b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 64*1024, 4, 32, b) })
|
||||||
|
b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 64*1024, 4, 32, b) })
|
||||||
|
b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 64*1024, 4, 32, b) })
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkArgon2id(b *testing.B) {
|
||||||
|
b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 32*1024, 1, 32, b) })
|
||||||
|
b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 64*1024, 4, 32, b) })
|
||||||
|
b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 64*1024, 4, 32, b) })
|
||||||
|
b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 64*1024, 4, 32, b) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generated with the CLI of https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
|
||||||
|
var testVectors = []struct {
|
||||||
|
mode int
|
||||||
|
time, memory uint32
|
||||||
|
threads uint8
|
||||||
|
hash string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
mode: argon2i, time: 1, memory: 64, threads: 1,
|
||||||
|
hash: "b9c401d1844a67d50eae3967dc28870b22e508092e861a37",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2d, time: 1, memory: 64, threads: 1,
|
||||||
|
hash: "8727405fd07c32c78d64f547f24150d3f2e703a89f981a19",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2id, time: 1, memory: 64, threads: 1,
|
||||||
|
hash: "655ad15eac652dc59f7170a7332bf49b8469be1fdb9c28bb",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2i, time: 2, memory: 64, threads: 1,
|
||||||
|
hash: "8cf3d8f76a6617afe35fac48eb0b7433a9a670ca4a07ed64",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2d, time: 2, memory: 64, threads: 1,
|
||||||
|
hash: "3be9ec79a69b75d3752acb59a1fbb8b295a46529c48fbb75",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2id, time: 2, memory: 64, threads: 1,
|
||||||
|
hash: "068d62b26455936aa6ebe60060b0a65870dbfa3ddf8d41f7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2i, time: 2, memory: 64, threads: 2,
|
||||||
|
hash: "2089f3e78a799720f80af806553128f29b132cafe40d059f",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2d, time: 2, memory: 64, threads: 2,
|
||||||
|
hash: "68e2462c98b8bc6bb60ec68db418ae2c9ed24fc6748a40e9",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2id, time: 2, memory: 64, threads: 2,
|
||||||
|
hash: "350ac37222f436ccb5c0972f1ebd3bf6b958bf2071841362",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2i, time: 3, memory: 256, threads: 2,
|
||||||
|
hash: "f5bbf5d4c3836af13193053155b73ec7476a6a2eb93fd5e6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2d, time: 3, memory: 256, threads: 2,
|
||||||
|
hash: "f4f0669218eaf3641f39cc97efb915721102f4b128211ef2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2id, time: 3, memory: 256, threads: 2,
|
||||||
|
hash: "4668d30ac4187e6878eedeacf0fd83c5a0a30db2cc16ef0b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2i, time: 4, memory: 4096, threads: 4,
|
||||||
|
hash: "a11f7b7f3f93f02ad4bddb59ab62d121e278369288a0d0e7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2d, time: 4, memory: 4096, threads: 4,
|
||||||
|
hash: "935598181aa8dc2b720914aa6435ac8d3e3a4210c5b0fb2d",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2id, time: 4, memory: 4096, threads: 4,
|
||||||
|
hash: "145db9733a9f4ee43edf33c509be96b934d505a4efb33c5a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2i, time: 4, memory: 1024, threads: 8,
|
||||||
|
hash: "0cdd3956aa35e6b475a7b0c63488822f774f15b43f6e6e17",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2d, time: 4, memory: 1024, threads: 8,
|
||||||
|
hash: "83604fc2ad0589b9d055578f4d3cc55bc616df3578a896e9",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2id, time: 4, memory: 1024, threads: 8,
|
||||||
|
hash: "8dafa8e004f8ea96bf7c0f93eecf67a6047476143d15577f",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2i, time: 2, memory: 64, threads: 3,
|
||||||
|
hash: "5cab452fe6b8479c8661def8cd703b611a3905a6d5477fe6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2d, time: 2, memory: 64, threads: 3,
|
||||||
|
hash: "22474a423bda2ccd36ec9afd5119e5c8949798cadf659f51",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2id, time: 2, memory: 64, threads: 3,
|
||||||
|
hash: "4a15b31aec7c2590b87d1f520be7d96f56658172deaa3079",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2i, time: 3, memory: 1024, threads: 6,
|
||||||
|
hash: "d236b29c2b2a09babee842b0dec6aa1e83ccbdea8023dced",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2d, time: 3, memory: 1024, threads: 6,
|
||||||
|
hash: "a3351b0319a53229152023d9206902f4ef59661cdca89481",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: argon2id, time: 3, memory: 1024, threads: 6,
|
||||||
|
hash: "1640b932f4b60e272f5d2207b9a9c626ffa1bd88d2349016",
|
||||||
|
},
|
||||||
|
}
|
53
vendor/golang.org/x/crypto/argon2/blake2b.go
generated
vendored
Normal file
53
vendor/golang.org/x/crypto/argon2/blake2b.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// 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 argon2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"hash"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/blake2b"
|
||||||
|
)
|
||||||
|
|
||||||
|
// blake2bHash computes an arbitrary long hash value of in
|
||||||
|
// and writes the hash to out.
|
||||||
|
func blake2bHash(out []byte, in []byte) {
|
||||||
|
var b2 hash.Hash
|
||||||
|
if n := len(out); n < blake2b.Size {
|
||||||
|
b2, _ = blake2b.New(n, nil)
|
||||||
|
} else {
|
||||||
|
b2, _ = blake2b.New512(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buffer [blake2b.Size]byte
|
||||||
|
binary.LittleEndian.PutUint32(buffer[:4], uint32(len(out)))
|
||||||
|
b2.Write(buffer[:4])
|
||||||
|
b2.Write(in)
|
||||||
|
|
||||||
|
if len(out) <= blake2b.Size {
|
||||||
|
b2.Sum(out[:0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
outLen := len(out)
|
||||||
|
b2.Sum(buffer[:0])
|
||||||
|
b2.Reset()
|
||||||
|
copy(out, buffer[:32])
|
||||||
|
out = out[32:]
|
||||||
|
for len(out) > blake2b.Size {
|
||||||
|
b2.Write(buffer[:])
|
||||||
|
b2.Sum(buffer[:0])
|
||||||
|
copy(out, buffer[:32])
|
||||||
|
out = out[32:]
|
||||||
|
b2.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
if outLen%blake2b.Size > 0 { // outLen > 64
|
||||||
|
r := ((outLen + 31) / 32) - 2 // ⌈τ /32⌉-2
|
||||||
|
b2, _ = blake2b.New(outLen-32*r, nil)
|
||||||
|
}
|
||||||
|
b2.Write(buffer[:])
|
||||||
|
b2.Sum(out[:0])
|
||||||
|
}
|
61
vendor/golang.org/x/crypto/argon2/blamka_amd64.go
generated
vendored
Normal file
61
vendor/golang.org/x/crypto/argon2/blamka_amd64.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
package argon2
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
useSSE4 = supportsSSE4()
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func supportsSSE4() bool
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func mixBlocksSSE2(out, a, b, c *block)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func xorBlocksSSE2(out, a, b, c *block)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func blamkaSSE4(b *block)
|
||||||
|
|
||||||
|
func processBlockSSE(out, in1, in2 *block, xor bool) {
|
||||||
|
var t block
|
||||||
|
mixBlocksSSE2(&t, in1, in2, &t)
|
||||||
|
if useSSE4 {
|
||||||
|
blamkaSSE4(&t)
|
||||||
|
} else {
|
||||||
|
for i := 0; i < blockLength; i += 16 {
|
||||||
|
blamkaGeneric(
|
||||||
|
&t[i+0], &t[i+1], &t[i+2], &t[i+3],
|
||||||
|
&t[i+4], &t[i+5], &t[i+6], &t[i+7],
|
||||||
|
&t[i+8], &t[i+9], &t[i+10], &t[i+11],
|
||||||
|
&t[i+12], &t[i+13], &t[i+14], &t[i+15],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
for i := 0; i < blockLength/8; i += 2 {
|
||||||
|
blamkaGeneric(
|
||||||
|
&t[i], &t[i+1], &t[16+i], &t[16+i+1],
|
||||||
|
&t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1],
|
||||||
|
&t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1],
|
||||||
|
&t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if xor {
|
||||||
|
xorBlocksSSE2(out, in1, in2, &t)
|
||||||
|
} else {
|
||||||
|
mixBlocksSSE2(out, in1, in2, &t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBlock(out, in1, in2 *block) {
|
||||||
|
processBlockSSE(out, in1, in2, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBlockXOR(out, in1, in2 *block) {
|
||||||
|
processBlockSSE(out, in1, in2, true)
|
||||||
|
}
|
252
vendor/golang.org/x/crypto/argon2/blamka_amd64.s
generated
vendored
Normal file
252
vendor/golang.org/x/crypto/argon2/blamka_amd64.s
generated
vendored
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
DATA ·c40<>+0x00(SB)/8, $0x0201000706050403
|
||||||
|
DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
|
||||||
|
GLOBL ·c40<>(SB), (NOPTR+RODATA), $16
|
||||||
|
|
||||||
|
DATA ·c48<>+0x00(SB)/8, $0x0100070605040302
|
||||||
|
DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
|
||||||
|
GLOBL ·c48<>(SB), (NOPTR+RODATA), $16
|
||||||
|
|
||||||
|
#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \
|
||||||
|
MOVO v4, t1; \
|
||||||
|
MOVO v5, v4; \
|
||||||
|
MOVO t1, v5; \
|
||||||
|
MOVO v6, t1; \
|
||||||
|
PUNPCKLQDQ v6, t2; \
|
||||||
|
PUNPCKHQDQ v7, v6; \
|
||||||
|
PUNPCKHQDQ t2, v6; \
|
||||||
|
PUNPCKLQDQ v7, t2; \
|
||||||
|
MOVO t1, v7; \
|
||||||
|
MOVO v2, t1; \
|
||||||
|
PUNPCKHQDQ t2, v7; \
|
||||||
|
PUNPCKLQDQ v3, t2; \
|
||||||
|
PUNPCKHQDQ t2, v2; \
|
||||||
|
PUNPCKLQDQ t1, t2; \
|
||||||
|
PUNPCKHQDQ t2, v3
|
||||||
|
|
||||||
|
#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \
|
||||||
|
MOVO v4, t1; \
|
||||||
|
MOVO v5, v4; \
|
||||||
|
MOVO t1, v5; \
|
||||||
|
MOVO v2, t1; \
|
||||||
|
PUNPCKLQDQ v2, t2; \
|
||||||
|
PUNPCKHQDQ v3, v2; \
|
||||||
|
PUNPCKHQDQ t2, v2; \
|
||||||
|
PUNPCKLQDQ v3, t2; \
|
||||||
|
MOVO t1, v3; \
|
||||||
|
MOVO v6, t1; \
|
||||||
|
PUNPCKHQDQ t2, v3; \
|
||||||
|
PUNPCKLQDQ v7, t2; \
|
||||||
|
PUNPCKHQDQ t2, v6; \
|
||||||
|
PUNPCKLQDQ t1, t2; \
|
||||||
|
PUNPCKHQDQ t2, v7
|
||||||
|
|
||||||
|
#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48) \
|
||||||
|
MOVO v0, t0; \
|
||||||
|
PMULULQ v2, t0; \
|
||||||
|
PADDQ v2, v0; \
|
||||||
|
PADDQ t0, v0; \
|
||||||
|
PADDQ t0, v0; \
|
||||||
|
PXOR v0, v6; \
|
||||||
|
PSHUFD $0xB1, v6, v6; \
|
||||||
|
MOVO v4, t0; \
|
||||||
|
PMULULQ v6, t0; \
|
||||||
|
PADDQ v6, v4; \
|
||||||
|
PADDQ t0, v4; \
|
||||||
|
PADDQ t0, v4; \
|
||||||
|
PXOR v4, v2; \
|
||||||
|
PSHUFB c40, v2; \
|
||||||
|
MOVO v0, t0; \
|
||||||
|
PMULULQ v2, t0; \
|
||||||
|
PADDQ v2, v0; \
|
||||||
|
PADDQ t0, v0; \
|
||||||
|
PADDQ t0, v0; \
|
||||||
|
PXOR v0, v6; \
|
||||||
|
PSHUFB c48, v6; \
|
||||||
|
MOVO v4, t0; \
|
||||||
|
PMULULQ v6, t0; \
|
||||||
|
PADDQ v6, v4; \
|
||||||
|
PADDQ t0, v4; \
|
||||||
|
PADDQ t0, v4; \
|
||||||
|
PXOR v4, v2; \
|
||||||
|
MOVO v2, t0; \
|
||||||
|
PADDQ v2, t0; \
|
||||||
|
PSRLQ $63, v2; \
|
||||||
|
PXOR t0, v2; \
|
||||||
|
MOVO v1, t0; \
|
||||||
|
PMULULQ v3, t0; \
|
||||||
|
PADDQ v3, v1; \
|
||||||
|
PADDQ t0, v1; \
|
||||||
|
PADDQ t0, v1; \
|
||||||
|
PXOR v1, v7; \
|
||||||
|
PSHUFD $0xB1, v7, v7; \
|
||||||
|
MOVO v5, t0; \
|
||||||
|
PMULULQ v7, t0; \
|
||||||
|
PADDQ v7, v5; \
|
||||||
|
PADDQ t0, v5; \
|
||||||
|
PADDQ t0, v5; \
|
||||||
|
PXOR v5, v3; \
|
||||||
|
PSHUFB c40, v3; \
|
||||||
|
MOVO v1, t0; \
|
||||||
|
PMULULQ v3, t0; \
|
||||||
|
PADDQ v3, v1; \
|
||||||
|
PADDQ t0, v1; \
|
||||||
|
PADDQ t0, v1; \
|
||||||
|
PXOR v1, v7; \
|
||||||
|
PSHUFB c48, v7; \
|
||||||
|
MOVO v5, t0; \
|
||||||
|
PMULULQ v7, t0; \
|
||||||
|
PADDQ v7, v5; \
|
||||||
|
PADDQ t0, v5; \
|
||||||
|
PADDQ t0, v5; \
|
||||||
|
PXOR v5, v3; \
|
||||||
|
MOVO v3, t0; \
|
||||||
|
PADDQ v3, t0; \
|
||||||
|
PSRLQ $63, v3; \
|
||||||
|
PXOR t0, v3
|
||||||
|
|
||||||
|
#define LOAD_MSG_0(block, off) \
|
||||||
|
MOVOU 8*(off+0)(block), X0; \
|
||||||
|
MOVOU 8*(off+2)(block), X1; \
|
||||||
|
MOVOU 8*(off+4)(block), X2; \
|
||||||
|
MOVOU 8*(off+6)(block), X3; \
|
||||||
|
MOVOU 8*(off+8)(block), X4; \
|
||||||
|
MOVOU 8*(off+10)(block), X5; \
|
||||||
|
MOVOU 8*(off+12)(block), X6; \
|
||||||
|
MOVOU 8*(off+14)(block), X7
|
||||||
|
|
||||||
|
#define STORE_MSG_0(block, off) \
|
||||||
|
MOVOU X0, 8*(off+0)(block); \
|
||||||
|
MOVOU X1, 8*(off+2)(block); \
|
||||||
|
MOVOU X2, 8*(off+4)(block); \
|
||||||
|
MOVOU X3, 8*(off+6)(block); \
|
||||||
|
MOVOU X4, 8*(off+8)(block); \
|
||||||
|
MOVOU X5, 8*(off+10)(block); \
|
||||||
|
MOVOU X6, 8*(off+12)(block); \
|
||||||
|
MOVOU X7, 8*(off+14)(block)
|
||||||
|
|
||||||
|
#define LOAD_MSG_1(block, off) \
|
||||||
|
MOVOU 8*off+0*8(block), X0; \
|
||||||
|
MOVOU 8*off+16*8(block), X1; \
|
||||||
|
MOVOU 8*off+32*8(block), X2; \
|
||||||
|
MOVOU 8*off+48*8(block), X3; \
|
||||||
|
MOVOU 8*off+64*8(block), X4; \
|
||||||
|
MOVOU 8*off+80*8(block), X5; \
|
||||||
|
MOVOU 8*off+96*8(block), X6; \
|
||||||
|
MOVOU 8*off+112*8(block), X7
|
||||||
|
|
||||||
|
#define STORE_MSG_1(block, off) \
|
||||||
|
MOVOU X0, 8*off+0*8(block); \
|
||||||
|
MOVOU X1, 8*off+16*8(block); \
|
||||||
|
MOVOU X2, 8*off+32*8(block); \
|
||||||
|
MOVOU X3, 8*off+48*8(block); \
|
||||||
|
MOVOU X4, 8*off+64*8(block); \
|
||||||
|
MOVOU X5, 8*off+80*8(block); \
|
||||||
|
MOVOU X6, 8*off+96*8(block); \
|
||||||
|
MOVOU X7, 8*off+112*8(block)
|
||||||
|
|
||||||
|
#define BLAMKA_ROUND_0(block, off, t0, t1, c40, c48) \
|
||||||
|
LOAD_MSG_0(block, off); \
|
||||||
|
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \
|
||||||
|
SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \
|
||||||
|
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \
|
||||||
|
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \
|
||||||
|
STORE_MSG_0(block, off)
|
||||||
|
|
||||||
|
#define BLAMKA_ROUND_1(block, off, t0, t1, c40, c48) \
|
||||||
|
LOAD_MSG_1(block, off); \
|
||||||
|
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \
|
||||||
|
SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \
|
||||||
|
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \
|
||||||
|
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \
|
||||||
|
STORE_MSG_1(block, off)
|
||||||
|
|
||||||
|
// func blamkaSSE4(b *block)
|
||||||
|
TEXT ·blamkaSSE4(SB), 4, $0-8
|
||||||
|
MOVQ b+0(FP), AX
|
||||||
|
|
||||||
|
MOVOU ·c40<>(SB), X10
|
||||||
|
MOVOU ·c48<>(SB), X11
|
||||||
|
|
||||||
|
BLAMKA_ROUND_0(AX, 0, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_0(AX, 16, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_0(AX, 32, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_0(AX, 48, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_0(AX, 64, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_0(AX, 80, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_0(AX, 96, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_0(AX, 112, X8, X9, X10, X11)
|
||||||
|
|
||||||
|
BLAMKA_ROUND_1(AX, 0, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_1(AX, 2, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_1(AX, 4, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_1(AX, 6, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_1(AX, 8, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_1(AX, 10, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_1(AX, 12, X8, X9, X10, X11)
|
||||||
|
BLAMKA_ROUND_1(AX, 14, X8, X9, X10, X11)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func mixBlocksSSE2(out, a, b, c *block)
|
||||||
|
TEXT ·mixBlocksSSE2(SB), 4, $0-32
|
||||||
|
MOVQ out+0(FP), DX
|
||||||
|
MOVQ a+8(FP), AX
|
||||||
|
MOVQ b+16(FP), BX
|
||||||
|
MOVQ a+24(FP), CX
|
||||||
|
MOVQ $128, BP
|
||||||
|
|
||||||
|
loop:
|
||||||
|
MOVOU 0(AX), X0
|
||||||
|
MOVOU 0(BX), X1
|
||||||
|
MOVOU 0(CX), X2
|
||||||
|
PXOR X1, X0
|
||||||
|
PXOR X2, X0
|
||||||
|
MOVOU X0, 0(DX)
|
||||||
|
ADDQ $16, AX
|
||||||
|
ADDQ $16, BX
|
||||||
|
ADDQ $16, CX
|
||||||
|
ADDQ $16, DX
|
||||||
|
SUBQ $2, BP
|
||||||
|
JA loop
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func xorBlocksSSE2(out, a, b, c *block)
|
||||||
|
TEXT ·xorBlocksSSE2(SB), 4, $0-32
|
||||||
|
MOVQ out+0(FP), DX
|
||||||
|
MOVQ a+8(FP), AX
|
||||||
|
MOVQ b+16(FP), BX
|
||||||
|
MOVQ a+24(FP), CX
|
||||||
|
MOVQ $128, BP
|
||||||
|
|
||||||
|
loop:
|
||||||
|
MOVOU 0(AX), X0
|
||||||
|
MOVOU 0(BX), X1
|
||||||
|
MOVOU 0(CX), X2
|
||||||
|
MOVOU 0(DX), X3
|
||||||
|
PXOR X1, X0
|
||||||
|
PXOR X2, X0
|
||||||
|
PXOR X3, X0
|
||||||
|
MOVOU X0, 0(DX)
|
||||||
|
ADDQ $16, AX
|
||||||
|
ADDQ $16, BX
|
||||||
|
ADDQ $16, CX
|
||||||
|
ADDQ $16, DX
|
||||||
|
SUBQ $2, BP
|
||||||
|
JA loop
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func supportsSSE4() bool
|
||||||
|
TEXT ·supportsSSE4(SB), 4, $0-1
|
||||||
|
MOVL $1, AX
|
||||||
|
CPUID
|
||||||
|
SHRL $19, CX // Bit 19 indicates SSE4 support
|
||||||
|
ANDL $1, CX // CX != 0 if support SSE4
|
||||||
|
MOVB CX, ret+0(FP)
|
||||||
|
RET
|
163
vendor/golang.org/x/crypto/argon2/blamka_generic.go
generated
vendored
Normal file
163
vendor/golang.org/x/crypto/argon2/blamka_generic.go
generated
vendored
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
// 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 argon2
|
||||||
|
|
||||||
|
var useSSE4 bool
|
||||||
|
|
||||||
|
func processBlockGeneric(out, in1, in2 *block, xor bool) {
|
||||||
|
var t block
|
||||||
|
for i := range t {
|
||||||
|
t[i] = in1[i] ^ in2[i]
|
||||||
|
}
|
||||||
|
for i := 0; i < blockLength; i += 16 {
|
||||||
|
blamkaGeneric(
|
||||||
|
&t[i+0], &t[i+1], &t[i+2], &t[i+3],
|
||||||
|
&t[i+4], &t[i+5], &t[i+6], &t[i+7],
|
||||||
|
&t[i+8], &t[i+9], &t[i+10], &t[i+11],
|
||||||
|
&t[i+12], &t[i+13], &t[i+14], &t[i+15],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
for i := 0; i < blockLength/8; i += 2 {
|
||||||
|
blamkaGeneric(
|
||||||
|
&t[i], &t[i+1], &t[16+i], &t[16+i+1],
|
||||||
|
&t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1],
|
||||||
|
&t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1],
|
||||||
|
&t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if xor {
|
||||||
|
for i := range t {
|
||||||
|
out[i] ^= in1[i] ^ in2[i] ^ t[i]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := range t {
|
||||||
|
out[i] = in1[i] ^ in2[i] ^ t[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func blamkaGeneric(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15 *uint64) {
|
||||||
|
v00, v01, v02, v03 := *t00, *t01, *t02, *t03
|
||||||
|
v04, v05, v06, v07 := *t04, *t05, *t06, *t07
|
||||||
|
v08, v09, v10, v11 := *t08, *t09, *t10, *t11
|
||||||
|
v12, v13, v14, v15 := *t12, *t13, *t14, *t15
|
||||||
|
|
||||||
|
v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04))
|
||||||
|
v12 ^= v00
|
||||||
|
v12 = v12>>32 | v12<<32
|
||||||
|
v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12))
|
||||||
|
v04 ^= v08
|
||||||
|
v04 = v04>>24 | v04<<40
|
||||||
|
|
||||||
|
v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04))
|
||||||
|
v12 ^= v00
|
||||||
|
v12 = v12>>16 | v12<<48
|
||||||
|
v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12))
|
||||||
|
v04 ^= v08
|
||||||
|
v04 = v04>>63 | v04<<1
|
||||||
|
|
||||||
|
v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05))
|
||||||
|
v13 ^= v01
|
||||||
|
v13 = v13>>32 | v13<<32
|
||||||
|
v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13))
|
||||||
|
v05 ^= v09
|
||||||
|
v05 = v05>>24 | v05<<40
|
||||||
|
|
||||||
|
v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05))
|
||||||
|
v13 ^= v01
|
||||||
|
v13 = v13>>16 | v13<<48
|
||||||
|
v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13))
|
||||||
|
v05 ^= v09
|
||||||
|
v05 = v05>>63 | v05<<1
|
||||||
|
|
||||||
|
v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06))
|
||||||
|
v14 ^= v02
|
||||||
|
v14 = v14>>32 | v14<<32
|
||||||
|
v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14))
|
||||||
|
v06 ^= v10
|
||||||
|
v06 = v06>>24 | v06<<40
|
||||||
|
|
||||||
|
v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06))
|
||||||
|
v14 ^= v02
|
||||||
|
v14 = v14>>16 | v14<<48
|
||||||
|
v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14))
|
||||||
|
v06 ^= v10
|
||||||
|
v06 = v06>>63 | v06<<1
|
||||||
|
|
||||||
|
v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07))
|
||||||
|
v15 ^= v03
|
||||||
|
v15 = v15>>32 | v15<<32
|
||||||
|
v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15))
|
||||||
|
v07 ^= v11
|
||||||
|
v07 = v07>>24 | v07<<40
|
||||||
|
|
||||||
|
v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07))
|
||||||
|
v15 ^= v03
|
||||||
|
v15 = v15>>16 | v15<<48
|
||||||
|
v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15))
|
||||||
|
v07 ^= v11
|
||||||
|
v07 = v07>>63 | v07<<1
|
||||||
|
|
||||||
|
v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05))
|
||||||
|
v15 ^= v00
|
||||||
|
v15 = v15>>32 | v15<<32
|
||||||
|
v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15))
|
||||||
|
v05 ^= v10
|
||||||
|
v05 = v05>>24 | v05<<40
|
||||||
|
|
||||||
|
v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05))
|
||||||
|
v15 ^= v00
|
||||||
|
v15 = v15>>16 | v15<<48
|
||||||
|
v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15))
|
||||||
|
v05 ^= v10
|
||||||
|
v05 = v05>>63 | v05<<1
|
||||||
|
|
||||||
|
v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06))
|
||||||
|
v12 ^= v01
|
||||||
|
v12 = v12>>32 | v12<<32
|
||||||
|
v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12))
|
||||||
|
v06 ^= v11
|
||||||
|
v06 = v06>>24 | v06<<40
|
||||||
|
|
||||||
|
v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06))
|
||||||
|
v12 ^= v01
|
||||||
|
v12 = v12>>16 | v12<<48
|
||||||
|
v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12))
|
||||||
|
v06 ^= v11
|
||||||
|
v06 = v06>>63 | v06<<1
|
||||||
|
|
||||||
|
v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07))
|
||||||
|
v13 ^= v02
|
||||||
|
v13 = v13>>32 | v13<<32
|
||||||
|
v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13))
|
||||||
|
v07 ^= v08
|
||||||
|
v07 = v07>>24 | v07<<40
|
||||||
|
|
||||||
|
v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07))
|
||||||
|
v13 ^= v02
|
||||||
|
v13 = v13>>16 | v13<<48
|
||||||
|
v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13))
|
||||||
|
v07 ^= v08
|
||||||
|
v07 = v07>>63 | v07<<1
|
||||||
|
|
||||||
|
v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04))
|
||||||
|
v14 ^= v03
|
||||||
|
v14 = v14>>32 | v14<<32
|
||||||
|
v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14))
|
||||||
|
v04 ^= v09
|
||||||
|
v04 = v04>>24 | v04<<40
|
||||||
|
|
||||||
|
v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04))
|
||||||
|
v14 ^= v03
|
||||||
|
v14 = v14>>16 | v14<<48
|
||||||
|
v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14))
|
||||||
|
v04 ^= v09
|
||||||
|
v04 = v04>>63 | v04<<1
|
||||||
|
|
||||||
|
*t00, *t01, *t02, *t03 = v00, v01, v02, v03
|
||||||
|
*t04, *t05, *t06, *t07 = v04, v05, v06, v07
|
||||||
|
*t08, *t09, *t10, *t11 = v08, v09, v10, v11
|
||||||
|
*t12, *t13, *t14, *t15 = v12, v13, v14, v15
|
||||||
|
}
|
15
vendor/golang.org/x/crypto/argon2/blamka_ref.go
generated
vendored
Normal file
15
vendor/golang.org/x/crypto/argon2/blamka_ref.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !amd64 appengine gccgo
|
||||||
|
|
||||||
|
package argon2
|
||||||
|
|
||||||
|
func processBlock(out, in1, in2 *block) {
|
||||||
|
processBlockGeneric(out, in1, in2, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBlockXOR(out, in1, in2 *block) {
|
||||||
|
processBlockGeneric(out, in1, in2, true)
|
||||||
|
}
|
16
vendor/golang.org/x/crypto/blake2b/blake2b.go
generated
vendored
16
vendor/golang.org/x/crypto/blake2b/blake2b.go
generated
vendored
|
@ -39,7 +39,10 @@ var (
|
||||||
useSSE4 bool
|
useSSE4 bool
|
||||||
)
|
)
|
||||||
|
|
||||||
var errKeySize = errors.New("blake2b: invalid key size")
|
var (
|
||||||
|
errKeySize = errors.New("blake2b: invalid key size")
|
||||||
|
errHashSize = errors.New("blake2b: invalid hash size")
|
||||||
|
)
|
||||||
|
|
||||||
var iv = [8]uint64{
|
var iv = [8]uint64{
|
||||||
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
|
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
|
||||||
|
@ -83,7 +86,18 @@ func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) }
|
||||||
// key turns the hash into a MAC. The key must between zero and 64 bytes long.
|
// key turns the hash into a MAC. The key must between zero and 64 bytes long.
|
||||||
func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
|
func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
|
||||||
|
|
||||||
|
// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length.
|
||||||
|
// A non-nil key turns the hash into a MAC. The key must between zero and 64 bytes long.
|
||||||
|
// The hash size can be a value between 1 and 64 but it is highly recommended to use
|
||||||
|
// values equal or greater than:
|
||||||
|
// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long).
|
||||||
|
// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long).
|
||||||
|
func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) }
|
||||||
|
|
||||||
func newDigest(hashSize int, key []byte) (*digest, error) {
|
func newDigest(hashSize int, key []byte) (*digest, error) {
|
||||||
|
if hashSize < 1 || hashSize > Size {
|
||||||
|
return nil, errHashSize
|
||||||
|
}
|
||||||
if len(key) > Size {
|
if len(key) > Size {
|
||||||
return nil, errKeySize
|
return nil, errKeySize
|
||||||
}
|
}
|
||||||
|
|
6
vendor/golang.org/x/crypto/bn256/bn256.go
generated
vendored
6
vendor/golang.org/x/crypto/bn256/bn256.go
generated
vendored
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package bn256 implements a particular bilinear group at the 128-bit security level.
|
// Package bn256 implements a particular bilinear group.
|
||||||
//
|
//
|
||||||
// Bilinear groups are the basis of many of the new cryptographic protocols
|
// Bilinear groups are the basis of many of the new cryptographic protocols
|
||||||
// that have been proposed over the past decade. They consist of a triplet of
|
// that have been proposed over the past decade. They consist of a triplet of
|
||||||
|
@ -14,6 +14,10 @@
|
||||||
// Barreto-Naehrig curve as described in
|
// Barreto-Naehrig curve as described in
|
||||||
// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
|
// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
|
||||||
// with the implementation described in that paper.
|
// with the implementation described in that paper.
|
||||||
|
//
|
||||||
|
// (This package previously claimed to operate at a 128-bit security level.
|
||||||
|
// However, recent improvements in attacks mean that is no longer true. See
|
||||||
|
// https://moderncrypto.org/mail-archive/curves/2016/000740.html.)
|
||||||
package bn256 // import "golang.org/x/crypto/bn256"
|
package bn256 // import "golang.org/x/crypto/bn256"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
2
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
generated
vendored
2
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
generated
vendored
|
@ -7,7 +7,7 @@ package chacha20poly1305
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
"golang.org/x/crypto/chacha20poly1305/internal/chacha20"
|
"golang.org/x/crypto/internal/chacha20"
|
||||||
"golang.org/x/crypto/poly1305"
|
"golang.org/x/crypto/poly1305"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
19
vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go
generated
vendored
19
vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go
generated
vendored
|
@ -155,3 +155,22 @@ func TestWithHMACSHA1(t *testing.T) {
|
||||||
func TestWithHMACSHA256(t *testing.T) {
|
func TestWithHMACSHA256(t *testing.T) {
|
||||||
testHash(t, sha256.New, "SHA256", sha256TestVectors)
|
testHash(t, sha256.New, "SHA256", sha256TestVectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sink uint8
|
||||||
|
|
||||||
|
func benchmark(b *testing.B, h func() hash.Hash) {
|
||||||
|
password := make([]byte, h().Size())
|
||||||
|
salt := make([]byte, 8)
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
password = Key(password, salt, 4096, len(password), h)
|
||||||
|
}
|
||||||
|
sink += password[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHMACSHA1(b *testing.B) {
|
||||||
|
benchmark(b, sha1.New)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHMACSHA256(b *testing.B) {
|
||||||
|
benchmark(b, sha256.New)
|
||||||
|
}
|
||||||
|
|
3
vendor/golang.org/x/crypto/ssh/benchmark_test.go
generated
vendored
3
vendor/golang.org/x/crypto/ssh/benchmark_test.go
generated
vendored
|
@ -40,7 +40,8 @@ func sshPipe() (Conn, *server, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConf := ClientConfig{
|
clientConf := ClientConfig{
|
||||||
User: "user",
|
User: "user",
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
serverConf := ServerConfig{
|
serverConf := ServerConfig{
|
||||||
NoClientAuth: true,
|
NoClientAuth: true,
|
||||||
|
|
2
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
|
@ -340,7 +340,7 @@ 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 {
|
||||||
|
|
113
vendor/golang.org/x/crypto/ssh/certs_test.go
generated
vendored
113
vendor/golang.org/x/crypto/ssh/certs_test.go
generated
vendored
|
@ -6,10 +6,15 @@ package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh/testdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cert generated by ssh-keygen 6.0p1 Debian-4.
|
// Cert generated by ssh-keygen 6.0p1 Debian-4.
|
||||||
|
@ -220,3 +225,111 @@ func TestHostKeyCert(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCertTypes(t *testing.T) {
|
||||||
|
var testVars = []struct {
|
||||||
|
name string
|
||||||
|
keys func() Signer
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: CertAlgoECDSA256v01,
|
||||||
|
keys: func() Signer {
|
||||||
|
s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap256"])
|
||||||
|
return s
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: CertAlgoECDSA384v01,
|
||||||
|
keys: func() Signer {
|
||||||
|
s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap384"])
|
||||||
|
return s
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: CertAlgoECDSA521v01,
|
||||||
|
keys: func() Signer {
|
||||||
|
s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap521"])
|
||||||
|
return s
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: CertAlgoED25519v01,
|
||||||
|
keys: func() Signer {
|
||||||
|
s, _ := ParsePrivateKey(testdata.PEMBytes["ed25519"])
|
||||||
|
return s
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: CertAlgoRSAv01,
|
||||||
|
keys: func() Signer {
|
||||||
|
s, _ := ParsePrivateKey(testdata.PEMBytes["rsa"])
|
||||||
|
return s
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: CertAlgoDSAv01,
|
||||||
|
keys: func() Signer {
|
||||||
|
s, _ := ParsePrivateKey(testdata.PEMBytes["dsa"])
|
||||||
|
return s
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error generating host key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
signer, err := NewSignerFromKey(k)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error generating signer for ssh listener: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := &ServerConfig{
|
||||||
|
PublicKeyCallback: func(c ConnMetadata, k PublicKey) (*Permissions, error) {
|
||||||
|
return new(Permissions), nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
conf.AddHostKey(signer)
|
||||||
|
|
||||||
|
for _, m := range testVars {
|
||||||
|
t.Run(m.name, func(t *testing.T) {
|
||||||
|
|
||||||
|
c1, c2, err := netPipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("netPipe: %v", err)
|
||||||
|
}
|
||||||
|
defer c1.Close()
|
||||||
|
defer c2.Close()
|
||||||
|
|
||||||
|
go NewServerConn(c1, conf)
|
||||||
|
|
||||||
|
priv := m.keys()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error generating ssh pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cert := &Certificate{
|
||||||
|
CertType: UserCert,
|
||||||
|
Key: priv.PublicKey(),
|
||||||
|
}
|
||||||
|
cert.SignCert(rand.Reader, priv)
|
||||||
|
|
||||||
|
certSigner, err := NewCertSigner(cert, priv)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error generating cert signer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &ClientConfig{
|
||||||
|
User: "user",
|
||||||
|
HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil },
|
||||||
|
Auth: []AuthMethod{PublicKeys(certSigner)},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, _, err = NewClientConn(c2, "", config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error connecting: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
244
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
244
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
|
@ -16,6 +16,9 @@ import (
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/internal/chacha20"
|
||||||
|
"golang.org/x/crypto/poly1305"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -53,78 +56,78 @@ func newRC4(key, iv []byte) (cipher.Stream, error) {
|
||||||
return rc4.NewCipher(key)
|
return rc4.NewCipher(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
type streamCipherMode struct {
|
type cipherMode struct {
|
||||||
keySize int
|
keySize int
|
||||||
ivSize int
|
ivSize int
|
||||||
skip int
|
create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error)
|
||||||
createFunc func(key, iv []byte) (cipher.Stream, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) {
|
func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||||
if len(key) < c.keySize {
|
return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||||
panic("ssh: key length too small for cipher")
|
stream, err := createFunc(key, iv)
|
||||||
}
|
if err != nil {
|
||||||
if len(iv) < c.ivSize {
|
return nil, err
|
||||||
panic("ssh: iv too small for cipher")
|
|
||||||
}
|
|
||||||
|
|
||||||
stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var streamDump []byte
|
|
||||||
if c.skip > 0 {
|
|
||||||
streamDump = make([]byte, 512)
|
|
||||||
}
|
|
||||||
|
|
||||||
for remainingToDump := c.skip; remainingToDump > 0; {
|
|
||||||
dumpThisTime := remainingToDump
|
|
||||||
if dumpThisTime > len(streamDump) {
|
|
||||||
dumpThisTime = len(streamDump)
|
|
||||||
}
|
}
|
||||||
stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
|
|
||||||
remainingToDump -= dumpThisTime
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream, nil
|
var streamDump []byte
|
||||||
|
if skip > 0 {
|
||||||
|
streamDump = make([]byte, 512)
|
||||||
|
}
|
||||||
|
|
||||||
|
for remainingToDump := skip; remainingToDump > 0; {
|
||||||
|
dumpThisTime := remainingToDump
|
||||||
|
if dumpThisTime > len(streamDump) {
|
||||||
|
dumpThisTime = len(streamDump)
|
||||||
|
}
|
||||||
|
stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
|
||||||
|
remainingToDump -= dumpThisTime
|
||||||
|
}
|
||||||
|
|
||||||
|
mac := macModes[algs.MAC].new(macKey)
|
||||||
|
return &streamPacketCipher{
|
||||||
|
mac: mac,
|
||||||
|
etm: macModes[algs.MAC].etm,
|
||||||
|
macResult: make([]byte, mac.Size()),
|
||||||
|
cipher: stream,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cipherModes documents properties of supported ciphers. Ciphers not included
|
// cipherModes documents properties of supported ciphers. Ciphers not included
|
||||||
// are not supported and will not be negotiated, even if explicitly requested in
|
// are not supported and will not be negotiated, even if explicitly requested in
|
||||||
// ClientConfig.Crypto.Ciphers.
|
// ClientConfig.Crypto.Ciphers.
|
||||||
var cipherModes = map[string]*streamCipherMode{
|
var cipherModes = map[string]*cipherMode{
|
||||||
// Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
|
// Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
|
||||||
// are defined in the order specified in the RFC.
|
// are defined in the order specified in the RFC.
|
||||||
"aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
|
"aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
|
||||||
"aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
|
"aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
|
||||||
"aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
|
"aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
|
||||||
|
|
||||||
// Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
|
// Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
|
||||||
// They are defined in the order specified in the RFC.
|
// They are defined in the order specified in the RFC.
|
||||||
"arcfour128": {16, 0, 1536, newRC4},
|
"arcfour128": {16, 0, streamCipherMode(1536, newRC4)},
|
||||||
"arcfour256": {32, 0, 1536, newRC4},
|
"arcfour256": {32, 0, streamCipherMode(1536, newRC4)},
|
||||||
|
|
||||||
// Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
|
// Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
|
||||||
// Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
|
// Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
|
||||||
// RC4) has problems with weak keys, and should be used with caution."
|
// RC4) has problems with weak keys, and should be used with caution."
|
||||||
// RFC4345 introduces improved versions of Arcfour.
|
// RFC4345 introduces improved versions of Arcfour.
|
||||||
"arcfour": {16, 0, 0, newRC4},
|
"arcfour": {16, 0, streamCipherMode(0, newRC4)},
|
||||||
|
|
||||||
// AES-GCM is not a stream cipher, so it is constructed with a
|
// AEAD ciphers
|
||||||
// special case. If we add any more non-stream ciphers, we
|
gcmCipherID: {16, 12, newGCMCipher},
|
||||||
// should invest a cleaner way to do this.
|
chacha20Poly1305ID: {64, 0, newChaCha20Cipher},
|
||||||
gcmCipherID: {16, 12, 0, nil},
|
|
||||||
|
|
||||||
// CBC mode is insecure and so is not included in the default config.
|
// CBC mode is insecure and so is not included in the default config.
|
||||||
// (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely
|
// (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely
|
||||||
// needed, it's possible to specify a custom Config to enable it.
|
// needed, it's possible to specify a custom Config to enable it.
|
||||||
// You should expect that an active attacker can recover plaintext if
|
// You should expect that an active attacker can recover plaintext if
|
||||||
// you do.
|
// you do.
|
||||||
aes128cbcID: {16, aes.BlockSize, 0, nil},
|
aes128cbcID: {16, aes.BlockSize, newAESCBCCipher},
|
||||||
|
|
||||||
// 3des-cbc is insecure and is disabled by default.
|
// 3des-cbc is insecure and is not included in the default
|
||||||
tripledescbcID: {24, des.BlockSize, 0, nil},
|
// config.
|
||||||
|
tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher},
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefixLen is the length of the packet prefix that contains the packet length
|
// prefixLen is the length of the packet prefix that contains the packet length
|
||||||
|
@ -304,7 +307,7 @@ type gcmCipher struct {
|
||||||
buf []byte
|
buf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGCMCipher(iv, key []byte) (packetCipher, error) {
|
func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
|
||||||
c, err := aes.NewCipher(key)
|
c, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -422,7 +425,7 @@ type cbcCipher struct {
|
||||||
oracleCamouflage uint32
|
oracleCamouflage uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||||
cbc := &cbcCipher{
|
cbc := &cbcCipher{
|
||||||
mac: macModes[algs.MAC].new(macKey),
|
mac: macModes[algs.MAC].new(macKey),
|
||||||
decrypter: cipher.NewCBCDecrypter(c, iv),
|
decrypter: cipher.NewCBCDecrypter(c, iv),
|
||||||
|
@ -436,13 +439,13 @@ func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorith
|
||||||
return cbc, nil
|
return cbc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||||
c, err := aes.NewCipher(key)
|
c, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cbc, err := newCBCCipher(c, iv, key, macKey, algs)
|
cbc, err := newCBCCipher(c, key, iv, macKey, algs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -450,13 +453,13 @@ func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCi
|
||||||
return cbc, nil
|
return cbc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||||
c, err := des.NewTripleDESCipher(key)
|
c, err := des.NewTripleDESCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cbc, err := newCBCCipher(c, iv, key, macKey, algs)
|
cbc, err := newCBCCipher(c, key, iv, macKey, algs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -627,3 +630,142 @@ func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, pack
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
|
||||||
|
|
||||||
|
// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com
|
||||||
|
// AEAD, which is described here:
|
||||||
|
//
|
||||||
|
// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00
|
||||||
|
//
|
||||||
|
// the methods here also implement padding, which RFC4253 Section 6
|
||||||
|
// also requires of stream ciphers.
|
||||||
|
type chacha20Poly1305Cipher struct {
|
||||||
|
lengthKey [32]byte
|
||||||
|
contentKey [32]byte
|
||||||
|
buf []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
|
||||||
|
if len(key) != 64 {
|
||||||
|
panic(len(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &chacha20Poly1305Cipher{
|
||||||
|
buf: make([]byte, 256),
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(c.contentKey[:], key[:32])
|
||||||
|
copy(c.lengthKey[:], key[32:])
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Poly1305 key is obtained by encrypting 32 0-bytes.
|
||||||
|
var chacha20PolyKeyInput [32]byte
|
||||||
|
|
||||||
|
func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
|
||||||
|
var counter [16]byte
|
||||||
|
binary.BigEndian.PutUint64(counter[8:], uint64(seqNum))
|
||||||
|
|
||||||
|
var polyKey [32]byte
|
||||||
|
chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey)
|
||||||
|
|
||||||
|
encryptedLength := c.buf[:4]
|
||||||
|
if _, err := io.ReadFull(r, encryptedLength); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var lenBytes [4]byte
|
||||||
|
chacha20.XORKeyStream(lenBytes[:], encryptedLength, &counter, &c.lengthKey)
|
||||||
|
|
||||||
|
length := binary.BigEndian.Uint32(lenBytes[:])
|
||||||
|
if length > maxPacket {
|
||||||
|
return nil, errors.New("ssh: invalid packet length, packet too large")
|
||||||
|
}
|
||||||
|
|
||||||
|
contentEnd := 4 + length
|
||||||
|
packetEnd := contentEnd + poly1305.TagSize
|
||||||
|
if uint32(cap(c.buf)) < packetEnd {
|
||||||
|
c.buf = make([]byte, packetEnd)
|
||||||
|
copy(c.buf[:], encryptedLength)
|
||||||
|
} else {
|
||||||
|
c.buf = c.buf[:packetEnd]
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var mac [poly1305.TagSize]byte
|
||||||
|
copy(mac[:], c.buf[contentEnd:packetEnd])
|
||||||
|
if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) {
|
||||||
|
return nil, errors.New("ssh: MAC failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
counter[0] = 1
|
||||||
|
|
||||||
|
plain := c.buf[4:contentEnd]
|
||||||
|
chacha20.XORKeyStream(plain, plain, &counter, &c.contentKey)
|
||||||
|
|
||||||
|
padding := plain[0]
|
||||||
|
if padding < 4 {
|
||||||
|
// padding is a byte, so it automatically satisfies
|
||||||
|
// the maximum size, which is 255.
|
||||||
|
return nil, fmt.Errorf("ssh: illegal padding %d", padding)
|
||||||
|
}
|
||||||
|
|
||||||
|
if int(padding)+1 >= len(plain) {
|
||||||
|
return nil, fmt.Errorf("ssh: padding %d too large", padding)
|
||||||
|
}
|
||||||
|
|
||||||
|
plain = plain[1 : len(plain)-int(padding)]
|
||||||
|
|
||||||
|
return plain, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
|
||||||
|
var counter [16]byte
|
||||||
|
binary.BigEndian.PutUint64(counter[8:], uint64(seqNum))
|
||||||
|
|
||||||
|
var polyKey [32]byte
|
||||||
|
chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey)
|
||||||
|
|
||||||
|
// There is no blocksize, so fall back to multiple of 8 byte
|
||||||
|
// padding, as described in RFC 4253, Sec 6.
|
||||||
|
const packetSizeMultiple = 8
|
||||||
|
|
||||||
|
padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple
|
||||||
|
if padding < 4 {
|
||||||
|
padding += packetSizeMultiple
|
||||||
|
}
|
||||||
|
|
||||||
|
// size (4 bytes), padding (1), payload, padding, tag.
|
||||||
|
totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize
|
||||||
|
if cap(c.buf) < totalLength {
|
||||||
|
c.buf = make([]byte, totalLength)
|
||||||
|
} else {
|
||||||
|
c.buf = c.buf[:totalLength]
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding))
|
||||||
|
chacha20.XORKeyStream(c.buf, c.buf[:4], &counter, &c.lengthKey)
|
||||||
|
c.buf[4] = byte(padding)
|
||||||
|
copy(c.buf[5:], payload)
|
||||||
|
packetEnd := 5 + len(payload) + padding
|
||||||
|
if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counter[0] = 1
|
||||||
|
chacha20.XORKeyStream(c.buf[4:], c.buf[4:packetEnd], &counter, &c.contentKey)
|
||||||
|
|
||||||
|
var mac [poly1305.TagSize]byte
|
||||||
|
poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey)
|
||||||
|
|
||||||
|
copy(c.buf[packetEnd:], mac[:])
|
||||||
|
|
||||||
|
if _, err := w.Write(c.buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
86
vendor/golang.org/x/crypto/ssh/cipher_test.go
generated
vendored
86
vendor/golang.org/x/crypto/ssh/cipher_test.go
generated
vendored
|
@ -7,7 +7,6 @@ package ssh
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/aes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -15,60 +14,63 @@ import (
|
||||||
func TestDefaultCiphersExist(t *testing.T) {
|
func TestDefaultCiphersExist(t *testing.T) {
|
||||||
for _, cipherAlgo := range supportedCiphers {
|
for _, cipherAlgo := range supportedCiphers {
|
||||||
if _, ok := cipherModes[cipherAlgo]; !ok {
|
if _, ok := cipherModes[cipherAlgo]; !ok {
|
||||||
t.Errorf("default cipher %q is unknown", cipherAlgo)
|
t.Errorf("supported cipher %q is unknown", cipherAlgo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, cipherAlgo := range preferredCiphers {
|
||||||
|
if _, ok := cipherModes[cipherAlgo]; !ok {
|
||||||
|
t.Errorf("preferred cipher %q is unknown", cipherAlgo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPacketCiphers(t *testing.T) {
|
func TestPacketCiphers(t *testing.T) {
|
||||||
// Still test aes128cbc cipher although it's commented out.
|
defaultMac := "hmac-sha2-256"
|
||||||
cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
|
defaultCipher := "aes128-ctr"
|
||||||
defer delete(cipherModes, aes128cbcID)
|
|
||||||
|
|
||||||
for cipher := range cipherModes {
|
for cipher := range cipherModes {
|
||||||
for mac := range macModes {
|
t.Run("cipher="+cipher,
|
||||||
kr := &kexResult{Hash: crypto.SHA1}
|
func(t *testing.T) { testPacketCipher(t, cipher, defaultMac) })
|
||||||
algs := directionAlgorithms{
|
}
|
||||||
Cipher: cipher,
|
for mac := range macModes {
|
||||||
MAC: mac,
|
t.Run("mac="+mac,
|
||||||
Compression: "none",
|
func(t *testing.T) { testPacketCipher(t, defaultCipher, mac) })
|
||||||
}
|
}
|
||||||
client, err := newPacketCipher(clientKeys, algs, kr)
|
}
|
||||||
if err != nil {
|
|
||||||
t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
server, err := newPacketCipher(clientKeys, algs, kr)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
want := "bla bla"
|
func testPacketCipher(t *testing.T, cipher, mac string) {
|
||||||
input := []byte(want)
|
kr := &kexResult{Hash: crypto.SHA1}
|
||||||
buf := &bytes.Buffer{}
|
algs := directionAlgorithms{
|
||||||
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
Cipher: cipher,
|
||||||
t.Errorf("writePacket(%q, %q): %v", cipher, mac, err)
|
MAC: mac,
|
||||||
continue
|
Compression: "none",
|
||||||
}
|
}
|
||||||
|
client, err := newPacketCipher(clientKeys, algs, kr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
|
||||||
|
}
|
||||||
|
server, err := newPacketCipher(clientKeys, algs, kr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err)
|
||||||
|
}
|
||||||
|
|
||||||
packet, err := server.readPacket(0, buf)
|
want := "bla bla"
|
||||||
if err != nil {
|
input := []byte(want)
|
||||||
t.Errorf("readPacket(%q, %q): %v", cipher, mac, err)
|
buf := &bytes.Buffer{}
|
||||||
continue
|
if err := client.writePacket(0, buf, rand.Reader, input); err != nil {
|
||||||
}
|
t.Fatalf("writePacket(%q, %q): %v", cipher, mac, err)
|
||||||
|
}
|
||||||
|
|
||||||
if string(packet) != want {
|
packet, err := server.readPacket(0, buf)
|
||||||
t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want)
|
if err != nil {
|
||||||
}
|
t.Fatalf("readPacket(%q, %q): %v", cipher, mac, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if string(packet) != want {
|
||||||
|
t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCBCOracleCounterMeasure(t *testing.T) {
|
func TestCBCOracleCounterMeasure(t *testing.T) {
|
||||||
cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil}
|
|
||||||
defer delete(cipherModes, aes128cbcID)
|
|
||||||
|
|
||||||
kr := &kexResult{Hash: crypto.SHA1}
|
kr := &kexResult{Hash: crypto.SHA1}
|
||||||
algs := directionAlgorithms{
|
algs := directionAlgorithms{
|
||||||
Cipher: aes128cbcID,
|
Cipher: aes128cbcID,
|
||||||
|
|
92
vendor/golang.org/x/crypto/ssh/client_test.go
generated
vendored
92
vendor/golang.org/x/crypto/ssh/client_test.go
generated
vendored
|
@ -5,41 +5,77 @@
|
||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testClientVersion(t *testing.T, config *ClientConfig, expected string) {
|
func TestClientVersion(t *testing.T) {
|
||||||
clientConn, serverConn := net.Pipe()
|
for _, tt := range []struct {
|
||||||
defer clientConn.Close()
|
name string
|
||||||
receivedVersion := make(chan string, 1)
|
version string
|
||||||
config.HostKeyCallback = InsecureIgnoreHostKey()
|
multiLine string
|
||||||
go func() {
|
wantErr bool
|
||||||
version, err := readVersion(serverConn)
|
}{
|
||||||
if err != nil {
|
{
|
||||||
receivedVersion <- ""
|
name: "default version",
|
||||||
} else {
|
version: packageVersion,
|
||||||
receivedVersion <- string(version)
|
},
|
||||||
}
|
{
|
||||||
serverConn.Close()
|
name: "custom version",
|
||||||
}()
|
version: "SSH-2.0-CustomClientVersionString",
|
||||||
NewClientConn(clientConn, "", config)
|
},
|
||||||
actual := <-receivedVersion
|
{
|
||||||
if actual != expected {
|
name: "good multi line version",
|
||||||
t.Fatalf("got %s; want %s", actual, expected)
|
version: packageVersion,
|
||||||
|
multiLine: strings.Repeat("ignored\r\n", 20),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bad multi line version",
|
||||||
|
version: packageVersion,
|
||||||
|
multiLine: "bad multi line version",
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "long multi line version",
|
||||||
|
version: packageVersion,
|
||||||
|
multiLine: strings.Repeat("long multi line version\r\n", 50)[:256],
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
c1, c2, err := netPipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("netPipe: %v", err)
|
||||||
|
}
|
||||||
|
defer c1.Close()
|
||||||
|
defer c2.Close()
|
||||||
|
go func() {
|
||||||
|
if tt.multiLine != "" {
|
||||||
|
c1.Write([]byte(tt.multiLine))
|
||||||
|
}
|
||||||
|
NewClientConn(c1, "", &ClientConfig{
|
||||||
|
ClientVersion: tt.version,
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
})
|
||||||
|
c1.Close()
|
||||||
|
}()
|
||||||
|
conf := &ServerConfig{NoClientAuth: true}
|
||||||
|
conf.AddHostKey(testSigners["rsa"])
|
||||||
|
conn, _, _, err := NewServerConn(c2, conf)
|
||||||
|
if err == nil == tt.wantErr {
|
||||||
|
t.Fatalf("got err %v; wantErr %t", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
if tt.wantErr {
|
||||||
|
// Don't verify the version on an expected error.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got := string(conn.ClientVersion()); got != tt.version {
|
||||||
|
t.Fatalf("got %q; want %q", got, tt.version)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCustomClientVersion(t *testing.T) {
|
|
||||||
version := "Test-Client-Version-0.0"
|
|
||||||
testClientVersion(t, &ClientConfig{ClientVersion: version}, version)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDefaultClientVersion(t *testing.T) {
|
|
||||||
testClientVersion(t, &ClientConfig{}, packageVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHostKeyCheck(t *testing.T) {
|
func TestHostKeyCheck(t *testing.T) {
|
||||||
for _, tt := range []struct {
|
for _, tt := range []struct {
|
||||||
name string
|
name string
|
||||||
|
|
16
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
16
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 {
|
||||||
|
|
2
vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go
generated
vendored
|
@ -414,7 +414,7 @@ func (db *hostKeyDB) Read(r io.Reader, filename string) error {
|
||||||
|
|
||||||
// New creates a host key callback from the given OpenSSH host key
|
// New creates a host key callback from the given OpenSSH host key
|
||||||
// files. The returned callback is for use in
|
// files. The returned callback is for use in
|
||||||
// ssh.ClientConfig.HostKeyCallback. Hashed hostnames are not supported.
|
// ssh.ClientConfig.HostKeyCallback.
|
||||||
func New(files ...string) (ssh.HostKeyCallback, error) {
|
func New(files ...string) (ssh.HostKeyCallback, error) {
|
||||||
db := newHostKeyDB()
|
db := newHostKeyDB()
|
||||||
for _, fn := range files {
|
for _, fn := range files {
|
||||||
|
|
2
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
|
@ -256,7 +256,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
|
||||||
func isAcceptableAlgo(algo string) bool {
|
func isAcceptableAlgo(algo string) bool {
|
||||||
switch algo {
|
switch algo {
|
||||||
case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
|
case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
|
||||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
|
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
10
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
generated
vendored
10
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
generated
vendored
|
@ -93,5 +93,13 @@ func ReadPassword(fd int) ([]byte, error) {
|
||||||
windows.SetConsoleMode(windows.Handle(fd), old)
|
windows.SetConsoleMode(windows.Handle(fd), old)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return readPasswordLine(os.NewFile(uintptr(fd), "stdin"))
|
var h windows.Handle
|
||||||
|
p, _ := windows.GetCurrentProcess()
|
||||||
|
if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
f := os.NewFile(uintptr(h), "stdin")
|
||||||
|
defer f.Close()
|
||||||
|
return readPasswordLine(f)
|
||||||
}
|
}
|
||||||
|
|
62
vendor/golang.org/x/crypto/ssh/test/session_test.go
generated
vendored
62
vendor/golang.org/x/crypto/ssh/test/session_test.go
generated
vendored
|
@ -11,6 +11,7 @@ package test
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -324,27 +325,56 @@ func TestWindowChange(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testOneCipher(t *testing.T, cipher string, cipherOrder []string) {
|
||||||
|
server := newServer(t)
|
||||||
|
defer server.Shutdown()
|
||||||
|
conf := clientConfig()
|
||||||
|
conf.Ciphers = []string{cipher}
|
||||||
|
// Don't fail if sshd doesn't have the cipher.
|
||||||
|
conf.Ciphers = append(conf.Ciphers, cipherOrder...)
|
||||||
|
conn, err := server.TryDial(conf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TryDial: %v", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
numBytes := 4096
|
||||||
|
|
||||||
|
// Exercise sending data to the server
|
||||||
|
if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil {
|
||||||
|
t.Fatalf("SendRequest: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise receiving data from the server
|
||||||
|
session, err := conn.NewSession()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewSession: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := session.Output(fmt.Sprintf("dd if=/dev/zero of=/dev/stdout bs=%d count=1", numBytes))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Output: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(out) != numBytes {
|
||||||
|
t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var deprecatedCiphers = []string{
|
||||||
|
"aes128-cbc", "3des-cbc",
|
||||||
|
"arcfour128", "arcfour256",
|
||||||
|
}
|
||||||
|
|
||||||
func TestCiphers(t *testing.T) {
|
func TestCiphers(t *testing.T) {
|
||||||
var config ssh.Config
|
var config ssh.Config
|
||||||
config.SetDefaults()
|
config.SetDefaults()
|
||||||
cipherOrder := config.Ciphers
|
cipherOrder := append(config.Ciphers, deprecatedCiphers...)
|
||||||
// These ciphers will not be tested when commented out in cipher.go it will
|
|
||||||
// fallback to the next available as per line 292.
|
|
||||||
cipherOrder = append(cipherOrder, "aes128-cbc", "3des-cbc")
|
|
||||||
|
|
||||||
for _, ciph := range cipherOrder {
|
for _, ciph := range cipherOrder {
|
||||||
server := newServer(t)
|
t.Run(ciph, func(t *testing.T) {
|
||||||
defer server.Shutdown()
|
testOneCipher(t, ciph, cipherOrder)
|
||||||
conf := clientConfig()
|
})
|
||||||
conf.Ciphers = []string{ciph}
|
|
||||||
// Don't fail if sshd doesn't have the cipher.
|
|
||||||
conf.Ciphers = append(conf.Ciphers, cipherOrder...)
|
|
||||||
conn, err := server.TryDial(conf)
|
|
||||||
if err == nil {
|
|
||||||
conn.Close()
|
|
||||||
} else {
|
|
||||||
t.Fatalf("failed for cipher %q", ciph)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
vendor/golang.org/x/crypto/ssh/testdata/keys.go
generated
vendored
21
vendor/golang.org/x/crypto/ssh/testdata/keys.go
generated
vendored
|
@ -23,6 +23,27 @@ MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49
|
||||||
AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+
|
AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+
|
||||||
6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA==
|
6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA==
|
||||||
-----END EC PRIVATE KEY-----
|
-----END EC PRIVATE KEY-----
|
||||||
|
`),
|
||||||
|
"ecdsap256": []byte(`-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIAPCE25zK0PQSnsgVcEbM1mbKTASH4pqb5QJajplDwDZoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAEWy8TxGcIHRh5XGpO4dFVfDjeNY+VkgubQrf/eyFJZHxAn1SKraXU
|
||||||
|
qJUjTKj1z622OxYtJ5P7s9CfAEVsTzLCzg==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
|
`),
|
||||||
|
"ecdsap384": []byte(`-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MIGkAgEBBDBWfSnMuNKq8J9rQLzzEkx3KAoEohSXqhE/4CdjEYtoU2i22HW80DDS
|
||||||
|
qQhYNHRAduygBwYFK4EEACKhZANiAAQWaDMAd0HUd8ZiXCX7mYDDnC54gwH/nG43
|
||||||
|
VhCUEYmF7HMZm/B9Yn3GjFk3qYEDEvuF/52+NvUKBKKaLbh32AWxMv0ibcoba4cz
|
||||||
|
hL9+hWYhUD9XIUlzMWiZ2y6eBE9PdRI=
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
|
`),
|
||||||
|
"ecdsap521": []byte(`-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MIHcAgEBBEIBrkYpQcy8KTVHNiAkjlFZwee90224Bu6wz94R4OBo+Ts0eoAQG7SF
|
||||||
|
iaygEDMUbx6kTgXTBcKZ0jrWPKakayNZ/kigBwYFK4EEACOhgYkDgYYABADFuvLV
|
||||||
|
UoaCDGHcw5uNfdRIsvaLKuWSpLsl48eWGZAwdNG432GDVKduO+pceuE+8XzcyJb+
|
||||||
|
uMv+D2b11Q/LQUcHJwE6fqbm8m3EtDKPsoKs0u/XUJb0JsH4J8lkZzbUTjvGYamn
|
||||||
|
FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
`),
|
`),
|
||||||
"rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
|
"rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||||
MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2
|
MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2
|
||||||
|
|
58
vendor/golang.org/x/crypto/ssh/transport.go
generated
vendored
58
vendor/golang.org/x/crypto/ssh/transport.go
generated
vendored
|
@ -6,6 +6,7 @@ package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
@ -232,52 +233,22 @@ var (
|
||||||
clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
|
clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
|
||||||
)
|
)
|
||||||
|
|
||||||
// generateKeys generates key material for IV, MAC and encryption.
|
|
||||||
func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) {
|
|
||||||
cipherMode := cipherModes[algs.Cipher]
|
|
||||||
macMode := macModes[algs.MAC]
|
|
||||||
|
|
||||||
iv = make([]byte, cipherMode.ivSize)
|
|
||||||
key = make([]byte, cipherMode.keySize)
|
|
||||||
macKey = make([]byte, macMode.keySize)
|
|
||||||
|
|
||||||
generateKeyMaterial(iv, d.ivTag, kex)
|
|
||||||
generateKeyMaterial(key, d.keyTag, kex)
|
|
||||||
generateKeyMaterial(macKey, d.macKeyTag, kex)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
|
// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
|
||||||
// described in RFC 4253, section 6.4. direction should either be serverKeys
|
// described in RFC 4253, section 6.4. direction should either be serverKeys
|
||||||
// (to setup server->client keys) or clientKeys (for client->server keys).
|
// (to setup server->client keys) or clientKeys (for client->server keys).
|
||||||
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
|
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
|
||||||
iv, key, macKey := generateKeys(d, algs, kex)
|
cipherMode := cipherModes[algs.Cipher]
|
||||||
|
macMode := macModes[algs.MAC]
|
||||||
|
|
||||||
if algs.Cipher == gcmCipherID {
|
iv := make([]byte, cipherMode.ivSize)
|
||||||
return newGCMCipher(iv, key)
|
key := make([]byte, cipherMode.keySize)
|
||||||
}
|
macKey := make([]byte, macMode.keySize)
|
||||||
|
|
||||||
if algs.Cipher == aes128cbcID {
|
generateKeyMaterial(iv, d.ivTag, kex)
|
||||||
return newAESCBCCipher(iv, key, macKey, algs)
|
generateKeyMaterial(key, d.keyTag, kex)
|
||||||
}
|
generateKeyMaterial(macKey, d.macKeyTag, kex)
|
||||||
|
|
||||||
if algs.Cipher == tripledescbcID {
|
return cipherModes[algs.Cipher].create(key, iv, macKey, algs)
|
||||||
return newTripleDESCBCCipher(iv, key, macKey, algs)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &streamPacketCipher{
|
|
||||||
mac: macModes[algs.MAC].new(macKey),
|
|
||||||
etm: macModes[algs.MAC].etm,
|
|
||||||
}
|
|
||||||
c.macResult = make([]byte, c.mac.Size())
|
|
||||||
|
|
||||||
var err error
|
|
||||||
c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateKeyMaterial fills out with key material generated from tag, K, H
|
// generateKeyMaterial fills out with key material generated from tag, K, H
|
||||||
|
@ -342,7 +313,7 @@ func readVersion(r io.Reader) ([]byte, error) {
|
||||||
var ok bool
|
var ok bool
|
||||||
var buf [1]byte
|
var buf [1]byte
|
||||||
|
|
||||||
for len(versionString) < maxVersionStringBytes {
|
for length := 0; length < maxVersionStringBytes; length++ {
|
||||||
_, err := io.ReadFull(r, buf[:])
|
_, err := io.ReadFull(r, buf[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -350,6 +321,13 @@ func readVersion(r io.Reader) ([]byte, error) {
|
||||||
// The RFC says that the version should be terminated with \r\n
|
// The RFC says that the version should be terminated with \r\n
|
||||||
// but several SSH servers actually only send a \n.
|
// but several SSH servers actually only send a \n.
|
||||||
if buf[0] == '\n' {
|
if buf[0] == '\n' {
|
||||||
|
if !bytes.HasPrefix(versionString, []byte("SSH-")) {
|
||||||
|
// RFC 4253 says we need to ignore all version string lines
|
||||||
|
// except the one containing the SSH version (provided that
|
||||||
|
// all the lines do not exceed 255 bytes in total).
|
||||||
|
versionString = versionString[:0]
|
||||||
|
continue
|
||||||
|
}
|
||||||
ok = true
|
ok = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
14
vendor/golang.org/x/crypto/ssh/transport_test.go
generated
vendored
14
vendor/golang.org/x/crypto/ssh/transport_test.go
generated
vendored
|
@ -13,11 +13,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadVersion(t *testing.T) {
|
func TestReadVersion(t *testing.T) {
|
||||||
longversion := strings.Repeat("SSH-2.0-bla", 50)[:253]
|
longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253]
|
||||||
|
multiLineVersion := strings.Repeat("ignored\r\n", 20) + "SSH-2.0-bla\r\n"
|
||||||
cases := map[string]string{
|
cases := map[string]string{
|
||||||
"SSH-2.0-bla\r\n": "SSH-2.0-bla",
|
"SSH-2.0-bla\r\n": "SSH-2.0-bla",
|
||||||
"SSH-2.0-bla\n": "SSH-2.0-bla",
|
"SSH-2.0-bla\n": "SSH-2.0-bla",
|
||||||
longversion + "\r\n": longversion,
|
multiLineVersion: "SSH-2.0-bla",
|
||||||
|
longVersion + "\r\n": longVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
for in, want := range cases {
|
for in, want := range cases {
|
||||||
|
@ -33,9 +35,11 @@ func TestReadVersion(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadVersionError(t *testing.T) {
|
func TestReadVersionError(t *testing.T) {
|
||||||
longversion := strings.Repeat("SSH-2.0-bla", 50)[:253]
|
longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253]
|
||||||
|
multiLineVersion := strings.Repeat("ignored\r\n", 50) + "SSH-2.0-bla\r\n"
|
||||||
cases := []string{
|
cases := []string{
|
||||||
longversion + "too-long\r\n",
|
longVersion + "too-long\r\n",
|
||||||
|
multiLineVersion,
|
||||||
}
|
}
|
||||||
for _, in := range cases {
|
for _, in := range cases {
|
||||||
if _, err := readVersion(bytes.NewBufferString(in)); err == nil {
|
if _, err := readVersion(bytes.NewBufferString(in)); err == nil {
|
||||||
|
@ -60,7 +64,7 @@ func TestExchangeVersionsBasic(t *testing.T) {
|
||||||
func TestExchangeVersions(t *testing.T) {
|
func TestExchangeVersions(t *testing.T) {
|
||||||
cases := []string{
|
cases := []string{
|
||||||
"not\x000allowed",
|
"not\x000allowed",
|
||||||
"not allowed\n",
|
"not allowed\x01\r\n",
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
buf := bytes.NewBufferString("SSH-2.0-bla\r\n")
|
buf := bytes.NewBufferString("SSH-2.0-bla\r\n")
|
||||||
|
|
Loading…
Reference in a new issue