aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/golang.org
diff options
context:
space:
mode:
authorFluf <36822577+flufmonster@users.noreply.github.com>2018-08-21 09:56:50 -0400
committertechknowlogick <techknowlogick@users.noreply.github.com>2018-08-21 09:56:50 -0400
commitb82c14b3d2259912b47fa292b85772ba1d2493d0 (patch)
treee4cca15b19a1549961543779f9a11c9127e7475c /vendor/golang.org
parent6c1a31ffaaddf8ced7c30bf5b1e6e82d66f8c6ee (diff)
downloadgitea-b82c14b3d2259912b47fa292b85772ba1d2493d0.tar.gz
gitea-b82c14b3d2259912b47fa292b85772ba1d2493d0.zip
add letsencrypt to Gitea (#4189)
Diffstat (limited to 'vendor/golang.org')
-rw-r--r--vendor/golang.org/x/crypto/acme/acme.go1065
-rw-r--r--vendor/golang.org/x/crypto/acme/autocert/autocert.go962
-rw-r--r--vendor/golang.org/x/crypto/acme/autocert/cache.go130
-rw-r--r--vendor/golang.org/x/crypto/acme/autocert/listener.go160
-rw-r--r--vendor/golang.org/x/crypto/acme/autocert/renewal.go141
-rw-r--r--vendor/golang.org/x/crypto/acme/jws.go153
-rw-r--r--vendor/golang.org/x/crypto/acme/types.go329
-rw-r--r--vendor/golang.org/x/crypto/ed25519/ed25519.go13
-rw-r--r--vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go22
-rw-r--r--vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go223
-rw-r--r--vendor/golang.org/x/crypto/internal/chacha20/xor.go43
-rw-r--r--vendor/golang.org/x/crypto/poly1305/poly1305.go33
-rw-r--r--vendor/golang.org/x/crypto/poly1305/sum_amd64.go22
-rw-r--r--vendor/golang.org/x/crypto/poly1305/sum_amd64.s125
-rw-r--r--vendor/golang.org/x/crypto/poly1305/sum_arm.go22
-rw-r--r--vendor/golang.org/x/crypto/poly1305/sum_arm.s427
-rw-r--r--vendor/golang.org/x/crypto/poly1305/sum_ref.go141
-rw-r--r--vendor/golang.org/x/crypto/ssh/certs.go8
-rw-r--r--vendor/golang.org/x/crypto/ssh/channel.go142
-rw-r--r--vendor/golang.org/x/crypto/ssh/cipher.go248
-rw-r--r--vendor/golang.org/x/crypto/ssh/client_auth.go95
-rw-r--r--vendor/golang.org/x/crypto/ssh/common.go20
-rw-r--r--vendor/golang.org/x/crypto/ssh/kex.go24
-rw-r--r--vendor/golang.org/x/crypto/ssh/keys.go47
-rw-r--r--vendor/golang.org/x/crypto/ssh/messages.go22
-rw-r--r--vendor/golang.org/x/crypto/ssh/mux.go6
-rw-r--r--vendor/golang.org/x/crypto/ssh/server.go27
-rw-r--r--vendor/golang.org/x/crypto/ssh/session.go2
-rw-r--r--vendor/golang.org/x/crypto/ssh/transport.go70
29 files changed, 4444 insertions, 278 deletions
diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go
new file mode 100644
index 0000000000..1f4fb69edd
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/acme.go
@@ -0,0 +1,1065 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package acme provides an implementation of the
+// Automatic Certificate Management Environment (ACME) spec.
+// See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details.
+//
+// Most common scenarios will want to use autocert subdirectory instead,
+// which provides automatic access to certificates from Let's Encrypt
+// and any other ACME-based CA.
+//
+// This package is a work in progress and makes no API stability promises.
+package acme
+
+import (
+ "bytes"
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/sha256"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/json"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math/big"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
+const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
+
+const (
+ maxChainLen = 5 // max depth and breadth of a certificate chain
+ maxCertSize = 1 << 20 // max size of a certificate, in bytes
+
+ // Max number of collected nonces kept in memory.
+ // Expect usual peak of 1 or 2.
+ maxNonces = 100
+)
+
+// Client is an ACME client.
+// The only required field is Key. An example of creating a client with a new key
+// is as follows:
+//
+// key, err := rsa.GenerateKey(rand.Reader, 2048)
+// if err != nil {
+// log.Fatal(err)
+// }
+// client := &Client{Key: key}
+//
+type Client struct {
+ // Key is the account key used to register with a CA and sign requests.
+ // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey.
+ Key crypto.Signer
+
+ // HTTPClient optionally specifies an HTTP client to use
+ // instead of http.DefaultClient.
+ HTTPClient *http.Client
+
+ // DirectoryURL points to the CA directory endpoint.
+ // If empty, LetsEncryptURL is used.
+ // Mutating this value after a successful call of Client's Discover method
+ // will have no effect.
+ DirectoryURL string
+
+ dirMu sync.Mutex // guards writes to dir
+ dir *Directory // cached result of Client's Discover method
+
+ noncesMu sync.Mutex
+ nonces map[string]struct{} // nonces collected from previous responses
+}
+
+// Discover performs ACME server discovery using c.DirectoryURL.
+//
+// It caches successful result. So, subsequent calls will not result in
+// a network round-trip. This also means mutating c.DirectoryURL after successful call
+// of this method will have no effect.
+func (c *Client) Discover(ctx context.Context) (Directory, error) {
+ c.dirMu.Lock()
+ defer c.dirMu.Unlock()
+ if c.dir != nil {
+ return *c.dir, nil
+ }
+
+ dirURL := c.DirectoryURL
+ if dirURL == "" {
+ dirURL = LetsEncryptURL
+ }
+ res, err := c.get(ctx, dirURL)
+ if err != nil {
+ return Directory{}, err
+ }
+ defer res.Body.Close()
+ c.addNonce(res.Header)
+ if res.StatusCode != http.StatusOK {
+ return Directory{}, responseError(res)
+ }
+
+ var v struct {
+ Reg string `json:"new-reg"`
+ Authz string `json:"new-authz"`
+ Cert string `json:"new-cert"`
+ Revoke string `json:"revoke-cert"`
+ Meta struct {
+ Terms string `json:"terms-of-service"`
+ Website string `json:"website"`
+ CAA []string `json:"caa-identities"`
+ }
+ }
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return Directory{}, err
+ }
+ c.dir = &Directory{
+ RegURL: v.Reg,
+ AuthzURL: v.Authz,
+ CertURL: v.Cert,
+ RevokeURL: v.Revoke,
+ Terms: v.Meta.Terms,
+ Website: v.Meta.Website,
+ CAA: v.Meta.CAA,
+ }
+ return *c.dir, nil
+}
+
+// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format.
+// The exp argument indicates the desired certificate validity duration. CA may issue a certificate
+// with a different duration.
+// If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain.
+//
+// In the case where CA server does not provide the issued certificate in the response,
+// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips.
+// In such a scenario, the caller can cancel the polling with ctx.
+//
+// CreateCert returns an error if the CA's response or chain was unreasonably large.
+// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features.
+func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, "", err
+ }
+
+ req := struct {
+ Resource string `json:"resource"`
+ CSR string `json:"csr"`
+ NotBefore string `json:"notBefore,omitempty"`
+ NotAfter string `json:"notAfter,omitempty"`
+ }{
+ Resource: "new-cert",
+ CSR: base64.RawURLEncoding.EncodeToString(csr),
+ }
+ now := timeNow()
+ req.NotBefore = now.Format(time.RFC3339)
+ if exp > 0 {
+ req.NotAfter = now.Add(exp).Format(time.RFC3339)
+ }
+
+ res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req)
+ if err != nil {
+ return nil, "", err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusCreated {
+ return nil, "", responseError(res)
+ }
+
+ curl := res.Header.Get("Location") // cert permanent URL
+ if res.ContentLength == 0 {
+ // no cert in the body; poll until we get it
+ cert, err := c.FetchCert(ctx, curl, bundle)
+ return cert, curl, err
+ }
+ // slurp issued cert and CA chain, if requested
+ cert, err := c.responseCert(ctx, res, bundle)
+ return cert, curl, err
+}
+
+// FetchCert retrieves already issued certificate from the given url, in DER format.
+// It retries the request until the certificate is successfully retrieved,
+// context is cancelled by the caller or an error response is received.
+//
+// The returned value will also contain the CA (issuer) certificate if the bundle argument is true.
+//
+// FetchCert returns an error if the CA's response or chain was unreasonably large.
+// Callers are encouraged to parse the returned value to ensure the certificate is valid
+// and has expected features.
+func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
+ for {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode == http.StatusOK {
+ return c.responseCert(ctx, res, bundle)
+ }
+ if res.StatusCode > 299 {
+ return nil, responseError(res)
+ }
+ d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second)
+ select {
+ case <-time.After(d):
+ // retry
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+}
+
+// RevokeCert revokes a previously issued certificate cert, provided in DER format.
+//
+// The key argument, used to sign the request, must be authorized
+// to revoke the certificate. It's up to the CA to decide which keys are authorized.
+// For instance, the key pair of the certificate may be authorized.
+// If the key is nil, c.Key is used instead.
+func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error {
+ if _, err := c.Discover(ctx); err != nil {
+ return err
+ }
+
+ body := &struct {
+ Resource string `json:"resource"`
+ Cert string `json:"certificate"`
+ Reason int `json:"reason"`
+ }{
+ Resource: "revoke-cert",
+ Cert: base64.RawURLEncoding.EncodeToString(cert),
+ Reason: int(reason),
+ }
+ if key == nil {
+ key = c.Key
+ }
+ res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return responseError(res)
+ }
+ return nil
+}
+
+// AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service
+// during account registration. See Register method of Client for more details.
+func AcceptTOS(tosURL string) bool { return true }
+
+// Register creates a new account registration by following the "new-reg" flow.
+// It returns the registered account. The account is not modified.
+//
+// The registration may require the caller to agree to the CA's Terms of Service (TOS).
+// If so, and the account has not indicated the acceptance of the terms (see Account for details),
+// Register calls prompt with a TOS URL provided by the CA. Prompt should report
+// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS.
+func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, err
+ }
+
+ var err error
+ if a, err = c.doReg(ctx, c.dir.RegURL, "new-reg", a); err != nil {
+ return nil, err
+ }
+ var accept bool
+ if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms {
+ accept = prompt(a.CurrentTerms)
+ }
+ if accept {
+ a.AgreedTerms = a.CurrentTerms
+ a, err = c.UpdateReg(ctx, a)
+ }
+ return a, err
+}
+
+// GetReg retrieves an existing registration.
+// The url argument is an Account URI.
+func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) {
+ a, err := c.doReg(ctx, url, "reg", nil)
+ if err != nil {
+ return nil, err
+ }
+ a.URI = url
+ return a, nil
+}
+
+// UpdateReg updates an existing registration.
+// It returns an updated account copy. The provided account is not modified.
+func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
+ uri := a.URI
+ a, err := c.doReg(ctx, uri, "reg", a)
+ if err != nil {
+ return nil, err
+ }
+ a.URI = uri
+ return a, nil
+}
+
+// Authorize performs the initial step in an authorization flow.
+// The caller will then need to choose from and perform a set of returned
+// challenges using c.Accept in order to successfully complete authorization.
+//
+// If an authorization has been previously granted, the CA may return
+// a valid authorization (Authorization.Status is StatusValid). If so, the caller
+// need not fulfill any challenge and can proceed to requesting a certificate.
+func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
+ if _, err := c.Discover(ctx); err != nil {
+ return nil, err
+ }
+
+ type authzID struct {
+ Type string `json:"type"`
+ Value string `json:"value"`
+ }
+ req := struct {
+ Resource string `json:"resource"`
+ Identifier authzID `json:"identifier"`
+ }{
+ Resource: "new-authz",
+ Identifier: authzID{Type: "dns", Value: domain},
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusCreated {
+ return nil, responseError(res)
+ }
+
+ var v wireAuthz
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ if v.Status != StatusPending && v.Status != StatusValid {
+ return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
+ }
+ return v.authorization(res.Header.Get("Location")), nil
+}
+
+// GetAuthorization retrieves an authorization identified by the given URL.
+//
+// If a caller needs to poll an authorization until its status is final,
+// see the WaitAuthorization method.
+func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+ var v wireAuthz
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.authorization(url), nil
+}
+
+// RevokeAuthorization relinquishes an existing authorization identified
+// by the given URL.
+// The url argument is an Authorization.URI value.
+//
+// If successful, the caller will be required to obtain a new authorization
+// using the Authorize method before being able to request a new certificate
+// for the domain associated with the authorization.
+//
+// It does not revoke existing certificates.
+func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
+ req := struct {
+ Resource string `json:"resource"`
+ Status string `json:"status"`
+ Delete bool `json:"delete"`
+ }{
+ Resource: "authz",
+ Status: "deactivated",
+ Delete: true,
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, url, req)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return responseError(res)
+ }
+ return nil
+}
+
+// WaitAuthorization polls an authorization at the given URL
+// until it is in one of the final states, StatusValid or StatusInvalid,
+// the ACME CA responded with a 4xx error code, or the context is done.
+//
+// It returns a non-nil Authorization only if its Status is StatusValid.
+// In all other cases WaitAuthorization returns an error.
+// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
+func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
+ sleep := sleeper(ctx)
+ for {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ if res.StatusCode >= 400 && res.StatusCode <= 499 {
+ // Non-retriable error. For instance, Let's Encrypt may return 404 Not Found
+ // when requesting an expired authorization.
+ defer res.Body.Close()
+ return nil, responseError(res)
+ }
+
+ retry := res.Header.Get("Retry-After")
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ res.Body.Close()
+ if err := sleep(retry, 1); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ var raw wireAuthz
+ err = json.NewDecoder(res.Body).Decode(&raw)
+ res.Body.Close()
+ if err != nil {
+ if err := sleep(retry, 0); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ if raw.Status == StatusValid {
+ return raw.authorization(url), nil
+ }
+ if raw.Status == StatusInvalid {
+ return nil, raw.error(url)
+ }
+ if err := sleep(retry, 0); err != nil {
+ return nil, err
+ }
+ }
+}
+
+// GetChallenge retrieves the current status of an challenge.
+//
+// A client typically polls a challenge status using this method.
+func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+ v := wireChallenge{URI: url}
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.challenge(), nil
+}
+
+// Accept informs the server that the client accepts one of its challenges
+// previously obtained with c.Authorize.
+//
+// The server will then perform the validation asynchronously.
+func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) {
+ auth, err := keyAuth(c.Key.Public(), chal.Token)
+ if err != nil {
+ return nil, err
+ }
+
+ req := struct {
+ Resource string `json:"resource"`
+ Type string `json:"type"`
+ Auth string `json:"keyAuthorization"`
+ }{
+ Resource: "challenge",
+ Type: chal.Type,
+ Auth: auth,
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ // Note: the protocol specifies 200 as the expected response code, but
+ // letsencrypt seems to be returning 202.
+ if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
+ return nil, responseError(res)
+ }
+
+ var v wireChallenge
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ return v.challenge(), nil
+}
+
+// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response.
+// A TXT record containing the returned value must be provisioned under
+// "_acme-challenge" name of the domain being validated.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) DNS01ChallengeRecord(token string) (string, error) {
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return "", err
+ }
+ b := sha256.Sum256([]byte(ka))
+ return base64.RawURLEncoding.EncodeToString(b[:]), nil
+}
+
+// HTTP01ChallengeResponse returns the response for an http-01 challenge.
+// Servers should respond with the value to HTTP requests at the URL path
+// provided by HTTP01ChallengePath to validate the challenge and prove control
+// over a domain name.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
+ return keyAuth(c.Key.Public(), token)
+}
+
+// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge
+// should be provided by the servers.
+// The response value can be obtained with HTTP01ChallengeResponse.
+//
+// The token argument is a Challenge.Token value.
+func (c *Client) HTTP01ChallengePath(token string) string {
+ return "/.well-known/acme-challenge/" + token
+}
+
+// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
+// Servers can present the certificate to validate the challenge and prove control
+// over a domain name.
+//
+// The implementation is incomplete in that the returned value is a single certificate,
+// computed only for Z0 of the key authorization. ACME CAs are expected to update
+// their implementations to use the newer version, TLS-SNI-02.
+// For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3.
+//
+// The token argument is a Challenge.Token value.
+// If a WithKey option is provided, its private part signs the returned cert,
+// and the public part is used to specify the signee.
+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
+//
+// The returned certificate is valid for the next 24 hours and must be presented only when
+// the server name of the client hello matches exactly the returned name value.
+func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ b := sha256.Sum256([]byte(ka))
+ h := hex.EncodeToString(b[:])
+ name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:])
+ cert, err = tlsChallengeCert([]string{name}, opt)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ return cert, name, nil
+}
+
+// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response.
+// Servers can present the certificate to validate the challenge and prove control
+// over a domain name. For more details on TLS-SNI-02 see
+// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3.
+//
+// The token argument is a Challenge.Token value.
+// If a WithKey option is provided, its private part signs the returned cert,
+// and the public part is used to specify the signee.
+// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
+//
+// The returned certificate is valid for the next 24 hours and must be presented only when
+// the server name in the client hello matches exactly the returned name value.
+func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
+ b := sha256.Sum256([]byte(token))
+ h := hex.EncodeToString(b[:])
+ sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:])
+
+ ka, err := keyAuth(c.Key.Public(), token)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ b = sha256.Sum256([]byte(ka))
+ h = hex.EncodeToString(b[:])
+ sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:])
+
+ cert, err = tlsChallengeCert([]string{sanA, sanB}, opt)
+ if err != nil {
+ return tls.Certificate{}, "", err
+ }
+ return cert, sanA, nil
+}
+
+// doReg sends all types of registration requests.
+// The type of request is identified by typ argument, which is a "resource"
+// in the ACME spec terms.
+//
+// A non-nil acct argument indicates whether the intention is to mutate data
+// of the Account. Only Contact and Agreement of its fields are used
+// in such cases.
+func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Account) (*Account, error) {
+ req := struct {
+ Resource string `json:"resource"`
+ Contact []string `json:"contact,omitempty"`
+ Agreement string `json:"agreement,omitempty"`
+ }{
+ Resource: typ,
+ }
+ if acct != nil {
+ req.Contact = acct.Contact
+ req.Agreement = acct.AgreedTerms
+ }
+ res, err := c.retryPostJWS(ctx, c.Key, url, req)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode < 200 || res.StatusCode > 299 {
+ return nil, responseError(res)
+ }
+
+ var v struct {
+ Contact []string
+ Agreement string
+ Authorizations string
+ Certificates string
+ }
+ if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
+ return nil, fmt.Errorf("acme: invalid response: %v", err)
+ }
+ var tos string
+ if v := linkHeader(res.Header, "terms-of-service"); len(v) > 0 {
+ tos = v[0]
+ }
+ var authz string
+ if v := linkHeader(res.Header, "next"); len(v) > 0 {
+ authz = v[0]
+ }
+ return &Account{
+ URI: res.Header.Get("Location"),
+ Contact: v.Contact,
+ AgreedTerms: v.Agreement,
+ CurrentTerms: tos,
+ Authz: authz,
+ Authorizations: v.Authorizations,
+ Certificates: v.Certificates,
+ }, nil
+}
+
+// retryPostJWS will retry calls to postJWS if there is a badNonce error,
+// clearing the stored nonces after each error.
+// If the response was 4XX-5XX, then responseError is called on the body,
+// the body is closed, and the error returned.
+func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ sleep := sleeper(ctx)
+ for {
+ res, err := c.postJWS(ctx, key, url, body)
+ if err != nil {
+ return nil, err
+ }
+ // handle errors 4XX-5XX with responseError
+ if res.StatusCode >= 400 && res.StatusCode <= 599 {
+ err := responseError(res)
+ res.Body.Close()
+ // according to spec badNonce is urn:ietf:params:acme:error:badNonce
+ // however, acme servers in the wild return their version of the error
+ // https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4
+ if ae, ok := err.(*Error); ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") {
+ // clear any nonces that we might've stored that might now be
+ // considered bad
+ c.clearNonces()
+ retry := res.Header.Get("Retry-After")
+ if err := sleep(retry, 1); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ return nil, err
+ }
+ return res, nil
+ }
+}
+
+// postJWS signs the body with the given key and POSTs it to the provided url.
+// The body argument must be JSON-serializable.
+func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) {
+ nonce, err := c.popNonce(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ b, err := jwsEncodeJSON(body, key, nonce)
+ if err != nil {
+ return nil, err
+ }
+ res, err := c.post(ctx, url, "application/jose+json", bytes.NewReader(b))
+ if err != nil {
+ return nil, err
+ }
+ c.addNonce(res.Header)
+ return res, nil
+}
+
+// popNonce returns a nonce value previously stored with c.addNonce
+// or fetches a fresh one from the given URL.
+func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) == 0 {
+ return c.fetchNonce(ctx, url)
+ }
+ var nonce string
+ for nonce = range c.nonces {
+ delete(c.nonces, nonce)
+ break
+ }
+ return nonce, nil
+}
+
+// clearNonces clears any stored nonces
+func (c *Client) clearNonces() {
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ c.nonces = make(map[string]struct{})
+}
+
+// addNonce stores a nonce value found in h (if any) for future use.
+func (c *Client) addNonce(h http.Header) {
+ v := nonceFromHeader(h)
+ if v == "" {
+ return
+ }
+ c.noncesMu.Lock()
+ defer c.noncesMu.Unlock()
+ if len(c.nonces) >= maxNonces {
+ return
+ }
+ if c.nonces == nil {
+ c.nonces = make(map[string]struct{})
+ }
+ c.nonces[v] = struct{}{}
+}
+
+func (c *Client) httpClient() *http.Client {
+ if c.HTTPClient != nil {
+ return c.HTTPClient
+ }
+ return http.DefaultClient
+}
+
+func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", urlStr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return c.do(ctx, req)
+}
+
+func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", urlStr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return c.do(ctx, req)
+}
+
+func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", urlStr, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", contentType)
+ return c.do(ctx, req)
+}
+
+func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) {
+ res, err := c.httpClient().Do(req.WithContext(ctx))
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ // Prefer the unadorned context error.
+ // (The acme package had tests assuming this, previously from ctxhttp's
+ // behavior, predating net/http supporting contexts natively)
+ // TODO(bradfitz): reconsider this in the future. But for now this
+ // requires no test updates.
+ return nil, ctx.Err()
+ default:
+ return nil, err
+ }
+ }
+ return res, nil
+}
+
+func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
+ resp, err := c.head(ctx, url)
+ if err != nil {
+ return "", err
+ }
+ defer resp.Body.Close()
+ nonce := nonceFromHeader(resp.Header)
+ if nonce == "" {
+ if resp.StatusCode > 299 {
+ return "", responseError(resp)
+ }
+ return "", errors.New("acme: nonce not found")
+ }
+ return nonce, nil
+}
+
+func nonceFromHeader(h http.Header) string {
+ return h.Get("Replay-Nonce")
+}
+
+func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bool) ([][]byte, error) {
+ b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
+ if err != nil {
+ return nil, fmt.Errorf("acme: response stream: %v", err)
+ }
+ if len(b) > maxCertSize {
+ return nil, errors.New("acme: certificate is too big")
+ }
+ cert := [][]byte{b}
+ if !bundle {
+ return cert, nil
+ }
+
+ // Append CA chain cert(s).
+ // At least one is required according to the spec:
+ // https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-6.3.1
+ up := linkHeader(res.Header, "up")
+ if len(up) == 0 {
+ return nil, errors.New("acme: rel=up link not found")
+ }
+ if len(up) > maxChainLen {
+ return nil, errors.New("acme: rel=up link is too large")
+ }
+ for _, url := range up {
+ cc, err := c.chainCert(ctx, url, 0)
+ if err != nil {
+ return nil, err
+ }
+ cert = append(cert, cc...)
+ }
+ return cert, nil
+}
+
+// responseError creates an error of Error type from resp.
+func responseError(resp *http.Response) error {
+ // don't care if ReadAll returns an error:
+ // json.Unmarshal will fail in that case anyway
+ b, _ := ioutil.ReadAll(resp.Body)
+ e := &wireError{Status: resp.StatusCode}
+ if err := json.Unmarshal(b, e); err != nil {
+ // this is not a regular error response:
+ // populate detail with anything we received,
+ // e.Status will already contain HTTP response code value
+ e.Detail = string(b)
+ if e.Detail == "" {
+ e.Detail = resp.Status
+ }
+ }
+ return e.error(resp.Header)
+}
+
+// chainCert fetches CA certificate chain recursively by following "up" links.
+// Each recursive call increments the depth by 1, resulting in an error
+// if the recursion level reaches maxChainLen.
+//
+// First chainCert call starts with depth of 0.
+func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte, error) {
+ if depth >= maxChainLen {
+ return nil, errors.New("acme: certificate chain is too deep")
+ }
+
+ res, err := c.get(ctx, url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if res.StatusCode != http.StatusOK {
+ return nil, responseError(res)
+ }
+ b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
+ if err != nil {
+ return nil, err
+ }
+ if len(b) > maxCertSize {
+ return nil, errors.New("acme: certificate is too big")
+ }
+ chain := [][]byte{b}
+
+ uplink := linkHeader(res.Header, "up")
+ if len(uplink) > maxChainLen {
+ return nil, errors.New("acme: certificate chain is too large")
+ }
+ for _, up := range uplink {
+ cc, err := c.chainCert(ctx, up, depth+1)
+ if err != nil {
+ return nil, err
+ }
+ chain = append(chain, cc...)
+ }
+
+ return chain, nil
+}
+
+// linkHeader returns URI-Reference values of all Link headers
+// with relation-type rel.
+// See https://tools.ietf.org/html/rfc5988#section-5 for details.
+func linkHeader(h http.Header, rel string) []string {
+ var links []string
+ for _, v := range h["Link"] {
+ parts := strings.Split(v, ";")
+ for _, p := range parts {
+ p = strings.TrimSpace(p)
+ if !strings.HasPrefix(p, "rel=") {
+ continue
+ }
+ if v := strings.Trim(p[4:], `"`); v == rel {
+ links = append(links, strings.Trim(parts[0], "<>"))
+ }
+ }
+ }
+ return links
+}
+
+// sleeper returns a function that accepts the Retry-After HTTP header value
+// and an increment that's used with backoff to increasingly sleep on
+// consecutive calls until the context is done. If the Retry-After header
+// cannot be parsed, then backoff is used with a maximum sleep time of 10
+// seconds.
+func sleeper(ctx context.Context) func(ra string, inc int) error {
+ var count int
+ return func(ra string, inc int) error {
+ count += inc
+ d := backoff(count, 10*time.Second)
+ d = retryAfter(ra, d)
+ wakeup := time.NewTimer(d)
+ defer wakeup.Stop()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-wakeup.C:
+ return nil
+ }
+ }
+}
+
+// retryAfter parses a Retry-After HTTP header value,
+// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
+// It returns d if v cannot be parsed.
+func retryAfter(v string, d time.Duration) time.Duration {
+ if i, err := strconv.Atoi(v); err == nil {
+ return time.Duration(i) * time.Second
+ }
+ t, err := http.ParseTime(v)
+ if err != nil {
+ return d
+ }
+ return t.Sub(timeNow())
+}
+
+// backoff computes a duration after which an n+1 retry iteration should occur
+// using truncated exponential backoff algorithm.
+//
+// The n argument is always bounded between 0 and 30.
+// The max argument defines upper bound for the returned value.
+func backoff(n int, max time.Duration) time.Duration {
+ if n < 0 {
+ n = 0
+ }
+ if n > 30 {
+ n = 30
+ }
+ var d time.Duration
+ if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
+ d = time.Duration(x.Int64()) * time.Millisecond
+ }
+ d += time.Duration(1<<uint(n)) * time.Second
+ if d > max {
+ return max
+ }
+ return d
+}
+
+// keyAuth generates a key authorization string for a given token.
+func keyAuth(pub crypto.PublicKey, token string) (string, error) {
+ th, err := JWKThumbprint(pub)
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%s.%s", token, th), nil
+}
+
+// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
+// with the given SANs and auto-generated public/private key pair.
+// The Subject Common Name is set to the first SAN to aid debugging.
+// To create a cert with a custom key pair, specify WithKey option.
+func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
+ var (
+ key crypto.Signer
+ tmpl *x509.Certificate
+ )
+ for _, o := range opt {
+ switch o := o.(type) {
+ case *certOptKey:
+ if key != nil {
+ return tls.Certificate{}, errors.New("acme: duplicate key option")
+ }
+ key = o.key
+ case *certOptTemplate:
+ var t = *(*x509.Certificate)(o) // shallow copy is ok
+ tmpl = &t
+ default:
+ // package's fault, if we let this happen:
+ panic(fmt.Sprintf("unsupported option type %T", o))
+ }
+ }
+ if key == nil {
+ var err error
+ if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
+ return tls.Certificate{}, err
+ }
+ }
+ if tmpl == nil {
+ tmpl = &x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ NotBefore: time.Now(),
+ NotAfter: time.Now().Add(24 * time.Hour),
+ BasicConstraintsValid: true,
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ }
+ }
+ tmpl.DNSNames = san
+ if len(san) > 0 {
+ tmpl.Subject.CommonName = san[0]
+ }
+
+ der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
+ if err != nil {
+ return tls.Certificate{}, err
+ }
+ return tls.Certificate{
+ Certificate: [][]byte{der},
+ PrivateKey: key,
+ }, nil
+}
+
+// encodePEM returns b encoded as PEM with block of type typ.
+func encodePEM(typ string, b []byte) []byte {
+ pb := &pem.Block{Type: typ, Bytes: b}
+ return pem.EncodeToMemory(pb)
+}
+
+// timeNow is useful for testing for fixed current time.
+var timeNow = time.Now
diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/vendor/golang.org/x/crypto/acme/autocert/autocert.go
new file mode 100644
index 0000000000..263b291331
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/autocert.go
@@ -0,0 +1,962 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package autocert provides automatic access to certificates from Let's Encrypt
+// and any other ACME-based CA.
+//
+// This package is a work in progress and makes no API stability promises.
+package autocert
+
+import (
+ "bytes"
+ "context"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/tls"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ mathrand "math/rand"
+ "net"
+ "net/http"
+ "path"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/crypto/acme"
+)
+
+// createCertRetryAfter is how much time to wait before removing a failed state
+// entry due to an unsuccessful createCert call.
+// This is a variable instead of a const for testing.
+// TODO: Consider making it configurable or an exp backoff?
+var createCertRetryAfter = time.Minute
+
+// pseudoRand is safe for concurrent use.
+var pseudoRand *lockedMathRand
+
+func init() {
+ src := mathrand.NewSource(timeNow().UnixNano())
+ pseudoRand = &lockedMathRand{rnd: mathrand.New(src)}
+}
+
+// AcceptTOS is a Manager.Prompt function that always returns true to
+// indicate acceptance of the CA's Terms of Service during account
+// registration.
+func AcceptTOS(tosURL string) bool { return true }
+
+// HostPolicy specifies which host names the Manager is allowed to respond to.
+// It returns a non-nil error if the host should be rejected.
+// The returned error is accessible via tls.Conn.Handshake and its callers.
+// See Manager's HostPolicy field and GetCertificate method docs for more details.
+type HostPolicy func(ctx context.Context, host string) error
+
+// HostWhitelist returns a policy where only the specified host names are allowed.
+// Only exact matches are currently supported. Subdomains, regexp or wildcard
+// will not match.
+func HostWhitelist(hosts ...string) HostPolicy {
+ whitelist := make(map[string]bool, len(hosts))
+ for _, h := range hosts {
+ whitelist[h] = true
+ }
+ return func(_ context.Context, host string) error {
+ if !whitelist[host] {
+ return errors.New("acme/autocert: host not configured")
+ }
+ return nil
+ }
+}
+
+// defaultHostPolicy is used when Manager.HostPolicy is not set.
+func defaultHostPolicy(context.Context, string) error {
+ return nil
+}
+
+// Manager is a stateful certificate manager built on top of acme.Client.
+// It obtains and refreshes certificates automatically using "tls-sni-01",
+// "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,
+// to reuse obtained certificates across program restarts.
+// Otherwise your server is very likely to exceed the certificate
+// issuer's request rate limits.
+type Manager struct {
+ // Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS).
+ // The registration may require the caller to agree to the CA's TOS.
+ // If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report
+ // whether the caller agrees to the terms.
+ //
+ // To always accept the terms, the callers can use AcceptTOS.
+ Prompt func(tosURL string) bool
+
+ // Cache optionally stores and retrieves previously-obtained certificates.
+ // If nil, certs will only be cached for the lifetime of the Manager.
+ //
+ // Manager passes the Cache certificates data encoded in PEM, with private/public
+ // parts combined in a single Cache.Put call, private key first.
+ Cache Cache
+
+ // HostPolicy controls which domains the Manager will attempt
+ // to retrieve new certificates for. It does not affect cached certs.
+ //
+ // If non-nil, HostPolicy is called before requesting a new cert.
+ // If nil, all hosts are currently allowed. This is not recommended,
+ // as it opens a potential attack where clients connect to a server
+ // by IP address and pretend to be asking for an incorrect host name.
+ // Manager will attempt to obtain a certificate for that host, incorrectly,
+ // eventually reaching the CA's rate limit for certificate requests
+ // and making it impossible to obtain actual certificates.
+ //
+ // See GetCertificate for more details.
+ HostPolicy HostPolicy
+
+ // RenewBefore optionally specifies how early certificates should
+ // be renewed before they expire.
+ //
+ // If zero, they're renewed 30 days before expiration.
+ RenewBefore time.Duration
+
+ // Client is used to perform low-level operations, such as account registration
+ // and requesting new certificates.
+ // If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL
+ // directory endpoint and a newly-generated ECDSA P-256 key.
+ //
+ // Mutating the field after the first call of GetCertificate method will have no effect.
+ Client *acme.Client
+
+ // Email optionally specifies a contact email address.
+ // This is used by CAs, such as Let's Encrypt, to notify about problems
+ // with issued certificates.
+ //
+ // If the Client's account key is already registered, Email is not used.
+ Email string
+
+ // ForceRSA makes the Manager generate certificates with 2048-bit RSA keys.
+ //
+ // If false, a default is used. Currently the default
+ // is EC-based keys using the P-256 curve.
+ ForceRSA bool
+
+ clientMu sync.Mutex
+ client *acme.Client // initialized by acmeClient method
+
+ stateMu sync.Mutex
+ state map[string]*certState // keyed by domain name
+
+ // renewal tracks the set of domains currently running renewal timers.
+ // It is keyed by domain name.
+ renewalMu sync.Mutex
+ 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.
+// It provides a TLS certificate for hello.ServerName host, including answering
+// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored.
+//
+// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting
+// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation.
+// The error is propagated back to the caller of GetCertificate and is user-visible.
+// This does not affect cached certs. See HostPolicy field description for more details.
+func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
+ if m.Prompt == nil {
+ return nil, errors.New("acme/autocert: Manager.Prompt not set")
+ }
+
+ name := hello.ServerName
+ if name == "" {
+ return nil, errors.New("acme/autocert: missing server name")
+ }
+ if !strings.Contains(strings.Trim(name, "."), ".") {
+ return nil, errors.New("acme/autocert: server name component count invalid")
+ }
+ if strings.ContainsAny(name, `/\`) {
+ 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)
+ defer cancel()
+
+ // check whether this is a token cert requested for TLS-SNI challenge
+ if strings.HasSuffix(name, ".acme.invalid") {
+ m.tokensMu.RLock()
+ defer m.tokensMu.RUnlock()
+ if cert := m.certTokens[name]; cert != nil {
+ return cert, nil
+ }
+ if cert, err := m.cacheGet(ctx, name); err == nil {
+ return cert, nil
+ }
+ // TODO: cache error results?
+ return nil, fmt.Errorf("acme/autocert: no token cert for %q", name)
+ }
+
+ // regular domain
+ name = strings.TrimSuffix(name, ".") // golang.org/issue/18114
+ cert, err := m.cert(ctx, name)
+ if err == nil {
+ return cert, nil
+ }
+ if err != ErrCacheMiss {
+ return nil, err
+ }
+
+ // first-time
+ if err := m.hostPolicy()(ctx, name); err != nil {
+ return nil, err
+ }
+ cert, err = m.createCert(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ m.cachePut(ctx, name, cert)
+ 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.
+// If a certificate is found in cache but not in m.state, the latter will be filled
+// with the cached value.
+func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) {
+ m.stateMu.Lock()
+ if s, ok := m.state[name]; ok {
+ m.stateMu.Unlock()
+ s.RLock()
+ defer s.RUnlock()
+ return s.tlscert()
+ }
+ defer m.stateMu.Unlock()
+ cert, err := m.cacheGet(ctx, name)
+ if err != nil {
+ return nil, err
+ }
+ signer, ok := cert.PrivateKey.(crypto.Signer)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key cannot sign")
+ }
+ if m.state == nil {
+ m.state = make(map[string]*certState)
+ }
+ s := &certState{
+ key: signer,
+ cert: cert.Certificate,
+ leaf: cert.Leaf,
+ }
+ m.state[name] = s
+ go m.renew(name, s.key, s.leaf.NotAfter)
+ return cert, nil
+}
+
+// cacheGet always returns a valid certificate, or an error otherwise.
+// If a cached certficate exists but is not valid, ErrCacheMiss is returned.
+func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) {
+ if m.Cache == nil {
+ return nil, ErrCacheMiss
+ }
+ data, err := m.Cache.Get(ctx, domain)
+ if err != nil {
+ return nil, err
+ }
+
+ // private
+ priv, pub := pem.Decode(data)
+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
+ return nil, ErrCacheMiss
+ }
+ privKey, err := parsePrivateKey(priv.Bytes)
+ if err != nil {
+ return nil, err
+ }
+
+ // public
+ var pubDER [][]byte
+ for len(pub) > 0 {
+ var b *pem.Block
+ b, pub = pem.Decode(pub)
+ if b == nil {
+ break
+ }
+ pubDER = append(pubDER, b.Bytes)
+ }
+ if len(pub) > 0 {
+ // Leftover content not consumed by pem.Decode. Corrupt. Ignore.
+ return nil, ErrCacheMiss
+ }
+
+ // verify and create TLS cert
+ leaf, err := validCert(domain, pubDER, privKey)
+ if err != nil {
+ return nil, ErrCacheMiss
+ }
+ tlscert := &tls.Certificate{
+ Certificate: pubDER,
+ PrivateKey: privKey,
+ Leaf: leaf,
+ }
+ return tlscert, nil
+}
+
+func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error {
+ if m.Cache == nil {
+ return nil
+ }
+
+ // contains PEM-encoded data
+ var buf bytes.Buffer
+
+ // private
+ switch key := tlscert.PrivateKey.(type) {
+ case *ecdsa.PrivateKey:
+ if err := encodeECDSAKey(&buf, key); err != nil {
+ return err
+ }
+ case *rsa.PrivateKey:
+ b := x509.MarshalPKCS1PrivateKey(key)
+ pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b}
+ if err := pem.Encode(&buf, pb); err != nil {
+ return err
+ }
+ default:
+ return errors.New("acme/autocert: unknown private key type")
+ }
+
+ // public
+ for _, b := range tlscert.Certificate {
+ pb := &pem.Block{Type: "CERTIFICATE", Bytes: b}
+ if err := pem.Encode(&buf, pb); err != nil {
+ return err
+ }
+ }
+
+ return m.Cache.Put(ctx, domain, buf.Bytes())
+}
+
+func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
+ b, err := x509.MarshalECPrivateKey(key)
+ if err != nil {
+ return err
+ }
+ pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
+ return pem.Encode(w, pb)
+}
+
+// createCert starts the domain ownership verification and returns a certificate
+// for that domain upon success.
+//
+// If the domain is already being verified, it waits for the existing verification to complete.
+// Either way, createCert blocks for the duration of the whole process.
+func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) {
+ // TODO: maybe rewrite this whole piece using sync.Once
+ state, err := m.certState(domain)
+ if err != nil {
+ return nil, err
+ }
+ // state may exist if another goroutine is already working on it
+ // in which case just wait for it to finish
+ if !state.locked {
+ state.RLock()
+ defer state.RUnlock()
+ return state.tlscert()
+ }
+
+ // We are the first; state is locked.
+ // Unblock the readers when domain ownership is verified
+ // and we got the cert or the process failed.
+ defer state.Unlock()
+ state.locked = false
+
+ der, leaf, err := m.authorizedCert(ctx, state.key, domain)
+ if err != nil {
+ // Remove the failed state after some time,
+ // making the manager call createCert again on the following TLS hello.
+ time.AfterFunc(createCertRetryAfter, func() {
+ defer testDidRemoveState(domain)
+ m.stateMu.Lock()
+ defer m.stateMu.Unlock()
+ // Verify the state hasn't changed and it's still invalid
+ // before deleting.
+ s, ok := m.state[domain]
+ if !ok {
+ return
+ }
+ if _, err := validCert(domain, s.cert, s.key); err == nil {
+ return
+ }
+ delete(m.state, domain)
+ })
+ return nil, err
+ }
+ state.cert = der
+ state.leaf = leaf
+ go m.renew(domain, state.key, state.leaf.NotAfter)
+ return state.tlscert()
+}
+
+// certState returns a new or existing certState.
+// If a new certState is returned, state.exist is false and the state is locked.
+// The returned error is non-nil only in the case where a new state could not be created.
+func (m *Manager) certState(domain string) (*certState, error) {
+ m.stateMu.Lock()
+ defer m.stateMu.Unlock()
+ if m.state == nil {
+ m.state = make(map[string]*certState)
+ }
+ // existing state
+ if state, ok := m.state[domain]; ok {
+ return state, nil
+ }
+
+ // new locked state
+ var (
+ err error
+ key crypto.Signer
+ )
+ if m.ForceRSA {
+ key, err = rsa.GenerateKey(rand.Reader, 2048)
+ } else {
+ key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ state := &certState{
+ key: key,
+ locked: true,
+ }
+ state.Lock() // will be unlocked by m.certState caller
+ m.state[domain] = state
+ return state, nil
+}
+
+// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
+// 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) {
+ client, err := m.acmeClient(ctx)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if err := m.verify(ctx, client, domain); err != nil {
+ return nil, nil, err
+ }
+ csr, err := certRequest(key, domain)
+ if err != nil {
+ return nil, nil, err
+ }
+ der, _, err = client.CreateCert(ctx, csr, 0, true)
+ if err != nil {
+ return nil, nil, err
+ }
+ leaf, err = validCert(domain, der, key)
+ if err != nil {
+ return nil, nil, err
+ }
+ return der, leaf, nil
+}
+
+// verify runs the identifier (domain) authorization flow
+// using each applicable ACME challenge type.
+func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error {
+ // The list of challenge types we'll try to fulfill
+ // in this specific order.
+ challengeTypes := []string{"tls-sni-02", "tls-sni-01"}
+ m.tokensMu.RLock()
+ if m.tryHTTP01 {
+ challengeTypes = append(challengeTypes, "http-01")
+ }
+ m.tokensMu.RUnlock()
+
+ var nextTyp int // challengeType index of the next challenge type to try
+ for {
+ // Start domain authorization and get the challenge.
+ authz, err := client.Authorize(ctx, domain)
+ if err != nil {
+ return err
+ }
+ // No point in accepting challenges if the authorization status
+ // 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
+ }
+ }
+}
+
+// fulfill provisions a response to the challenge chal.
+// The cleanup is non-nil only if provisioning succeeded.
+func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge) (cleanup func(), err error) {
+ switch chal.Type {
+ case "tls-sni-01":
+ cert, name, err := client.TLSSNI01ChallengeCert(chal.Token)
+ 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
+ }
+ 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)
+}
+
+// deleteCertToken removes the token certificate for the specified domain name
+// from both m.certTokens map and m.Cache.
+func (m *Manager) deleteCertToken(name string) {
+ m.tokensMu.Lock()
+ defer m.tokensMu.Unlock()
+ delete(m.certTokens, name)
+ if m.Cache != nil {
+ 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.
+//
+// The loop is scheduled in two cases:
+// - a cert was fetched from cache for the first time (wasn't in m.state)
+// - a new cert was created by m.createCert
+//
+// The key argument is a certificate private key.
+// The exp argument is the cert expiration time (NotAfter).
+func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) {
+ m.renewalMu.Lock()
+ defer m.renewalMu.Unlock()
+ if m.renewal[domain] != nil {
+ // another goroutine is already on it
+ return
+ }
+ if m.renewal == nil {
+ m.renewal = make(map[string]*domainRenewal)
+ }
+ dr := &domainRenewal{m: m, domain: domain, key: key}
+ m.renewal[domain] = dr
+ dr.start(exp)
+}
+
+// stopRenew stops all currently running cert renewal timers.
+// The timers are not restarted during the lifetime of the Manager.
+func (m *Manager) stopRenew() {
+ m.renewalMu.Lock()
+ defer m.renewalMu.Unlock()
+ for name, dr := range m.renewal {
+ delete(m.renewal, name)
+ dr.stop()
+ }
+}
+
+func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) {
+ const keyName = "acme_account.key"
+
+ genKey := func() (*ecdsa.PrivateKey, error) {
+ return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ }
+
+ if m.Cache == nil {
+ return genKey()
+ }
+
+ data, err := m.Cache.Get(ctx, keyName)
+ if err == ErrCacheMiss {
+ key, err := genKey()
+ if err != nil {
+ return nil, err
+ }
+ var buf bytes.Buffer
+ if err := encodeECDSAKey(&buf, key); err != nil {
+ return nil, err
+ }
+ if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil {
+ return nil, err
+ }
+ return key, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ priv, _ := pem.Decode(data)
+ if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
+ return nil, errors.New("acme/autocert: invalid account key found in cache")
+ }
+ return parsePrivateKey(priv.Bytes)
+}
+
+func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) {
+ m.clientMu.Lock()
+ defer m.clientMu.Unlock()
+ if m.client != nil {
+ return m.client, nil
+ }
+
+ client := m.Client
+ if client == nil {
+ client = &acme.Client{DirectoryURL: acme.LetsEncryptURL}
+ }
+ if client.Key == nil {
+ var err error
+ client.Key, err = m.accountKey(ctx)
+ if err != nil {
+ return nil, err
+ }
+ }
+ var contact []string
+ if m.Email != "" {
+ contact = []string{"mailto:" + m.Email}
+ }
+ a := &acme.Account{Contact: contact}
+ _, err := client.Register(ctx, a, m.Prompt)
+ if ae, ok := err.(*acme.Error); err == nil || ok && ae.StatusCode == http.StatusConflict {
+ // conflict indicates the key is already registered
+ m.client = client
+ err = nil
+ }
+ return m.client, err
+}
+
+func (m *Manager) hostPolicy() HostPolicy {
+ if m.HostPolicy != nil {
+ return m.HostPolicy
+ }
+ return defaultHostPolicy
+}
+
+func (m *Manager) renewBefore() time.Duration {
+ if m.RenewBefore > renewJitter {
+ return m.RenewBefore
+ }
+ return 720 * time.Hour // 30 days
+}
+
+// certState is ready when its mutex is unlocked for reading.
+type certState struct {
+ sync.RWMutex
+ locked bool // locked for read/write
+ key crypto.Signer // private key for cert
+ cert [][]byte // DER encoding
+ leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil
+}
+
+// tlscert creates a tls.Certificate from s.key and s.cert.
+// Callers should wrap it in s.RLock() and s.RUnlock().
+func (s *certState) tlscert() (*tls.Certificate, error) {
+ if s.key == nil {
+ return nil, errors.New("acme/autocert: missing signer")
+ }
+ if len(s.cert) == 0 {
+ return nil, errors.New("acme/autocert: missing certificate")
+ }
+ return &tls.Certificate{
+ PrivateKey: s.key,
+ Certificate: s.cert,
+ Leaf: s.leaf,
+ }, nil
+}
+
+// certRequest creates a certificate request for the given common name cn
+// and optional SANs.
+func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) {
+ req := &x509.CertificateRequest{
+ Subject: pkix.Name{CommonName: cn},
+ DNSNames: san,
+ }
+ return x509.CreateCertificateRequest(rand.Reader, req, key)
+}
+
+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
+// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
+//
+// Inspired by parsePrivateKey in crypto/tls/tls.go.
+func parsePrivateKey(der []byte) (crypto.Signer, error) {
+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+ return key, nil
+ }
+ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return key, nil
+ case *ecdsa.PrivateKey:
+ return key, nil
+ default:
+ return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping")
+ }
+ }
+ if key, err := x509.ParseECPrivateKey(der); err == nil {
+ return key, nil
+ }
+
+ return nil, errors.New("acme/autocert: failed to parse private key")
+}
+
+// validCert parses a cert chain provided as der argument and verifies the leaf, der[0],
+// corresponds to the private key, as well as the domain match and expiration dates.
+// It doesn't do any revocation checking.
+//
+// The returned value is the verified leaf cert.
+func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) {
+ // parse public part(s)
+ var n int
+ for _, b := range der {
+ n += len(b)
+ }
+ pub := make([]byte, n)
+ n = 0
+ for _, b := range der {
+ n += copy(pub[n:], b)
+ }
+ x509Cert, err := x509.ParseCertificates(pub)
+ if len(x509Cert) == 0 {
+ return nil, errors.New("acme/autocert: no public key found")
+ }
+ // verify the leaf is not expired and matches the domain name
+ leaf = x509Cert[0]
+ now := timeNow()
+ if now.Before(leaf.NotBefore) {
+ return nil, errors.New("acme/autocert: certificate is not valid yet")
+ }
+ if now.After(leaf.NotAfter) {
+ return nil, errors.New("acme/autocert: expired certificate")
+ }
+ if err := leaf.VerifyHostname(domain); err != nil {
+ return nil, err
+ }
+ // ensure the leaf corresponds to the private key
+ switch pub := leaf.PublicKey.(type) {
+ case *rsa.PublicKey:
+ prv, ok := key.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key type does not match public key type")
+ }
+ if pub.N.Cmp(prv.N) != 0 {
+ return nil, errors.New("acme/autocert: private key does not match public key")
+ }
+ case *ecdsa.PublicKey:
+ prv, ok := key.(*ecdsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("acme/autocert: private key type does not match public key type")
+ }
+ if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 {
+ return nil, errors.New("acme/autocert: private key does not match public key")
+ }
+ default:
+ return nil, errors.New("acme/autocert: unknown public key algorithm")
+ }
+ return leaf, nil
+}
+
+type lockedMathRand struct {
+ sync.Mutex
+ rnd *mathrand.Rand
+}
+
+func (r *lockedMathRand) int63n(max int64) int64 {
+ r.Lock()
+ n := r.rnd.Int63n(max)
+ r.Unlock()
+ return n
+}
+
+// For easier testing.
+var (
+ timeNow = time.Now
+
+ // Called when a state is removed.
+ testDidRemoveState = func(domain string) {}
+)
diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/golang.org/x/crypto/acme/autocert/cache.go
new file mode 100644
index 0000000000..61a5fd239a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/cache.go
@@ -0,0 +1,130 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert
+
+import (
+ "context"
+ "errors"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+// ErrCacheMiss is returned when a certificate is not found in cache.
+var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
+
+// Cache is used by Manager to store and retrieve previously obtained certificates
+// as opaque data.
+//
+// The key argument of the methods refers to a domain name but need not be an FQDN.
+// Cache implementations should not rely on the key naming pattern.
+type Cache interface {
+ // Get returns a certificate data for the specified key.
+ // If there's no such key, Get returns ErrCacheMiss.
+ Get(ctx context.Context, key string) ([]byte, error)
+
+ // Put stores the data in the cache under the specified key.
+ // Underlying implementations may use any data storage format,
+ // as long as the reverse operation, Get, results in the original data.
+ Put(ctx context.Context, key string, data []byte) error
+
+ // Delete removes a certificate data from the cache under the specified key.
+ // If there's no such key in the cache, Delete returns nil.
+ Delete(ctx context.Context, key string) error
+}
+
+// DirCache implements Cache using a directory on the local filesystem.
+// If the directory does not exist, it will be created with 0700 permissions.
+type DirCache string
+
+// Get reads a certificate data from the specified file name.
+func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
+ name = filepath.Join(string(d), name)
+ var (
+ data []byte
+ err error
+ done = make(chan struct{})
+ )
+ go func() {
+ data, err = ioutil.ReadFile(name)
+ close(done)
+ }()
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case <-done:
+ }
+ if os.IsNotExist(err) {
+ return nil, ErrCacheMiss
+ }
+ return data, err
+}
+
+// Put writes the certificate data to the specified file name.
+// The file will be created with 0600 permissions.
+func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
+ if err := os.MkdirAll(string(d), 0700); err != nil {
+ return err
+ }
+
+ done := make(chan struct{})
+ var err error
+ go func() {
+ defer close(done)
+ var tmp string
+ if tmp, err = d.writeTempFile(name, data); err != nil {
+ return
+ }
+ select {
+ case <-ctx.Done():
+ // Don't overwrite the file if the context was canceled.
+ default:
+ newName := filepath.Join(string(d), name)
+ err = os.Rename(tmp, newName)
+ }
+ }()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-done:
+ }
+ return err
+}
+
+// Delete removes the specified file name.
+func (d DirCache) Delete(ctx context.Context, name string) error {
+ name = filepath.Join(string(d), name)
+ var (
+ err error
+ done = make(chan struct{})
+ )
+ go func() {
+ err = os.Remove(name)
+ close(done)
+ }()
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-done:
+ }
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ return nil
+}
+
+// writeTempFile writes b to a temporary file, closes the file and returns its path.
+func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
+ // TempFile uses 0600 permissions
+ f, err := ioutil.TempFile(string(d), prefix)
+ if err != nil {
+ return "", err
+ }
+ if _, err := f.Write(b); err != nil {
+ f.Close()
+ return "", err
+ }
+ return f.Name(), f.Close()
+}
diff --git a/vendor/golang.org/x/crypto/acme/autocert/listener.go b/vendor/golang.org/x/crypto/acme/autocert/listener.go
new file mode 100644
index 0000000000..d744df0ed0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/listener.go
@@ -0,0 +1,160 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert
+
+import (
+ "crypto/tls"
+ "log"
+ "net"
+ "os"
+ "path/filepath"
+ "runtime"
+ "time"
+)
+
+// NewListener returns a net.Listener that listens on the standard TLS
+// port (443) on all interfaces and returns *tls.Conn connections with
+// LetsEncrypt certificates for the provided domain or domains.
+//
+// It enables one-line HTTPS servers:
+//
+// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))
+//
+// NewListener is a convenience function for a common configuration.
+// More complex or custom configurations can use the autocert.Manager
+// type instead.
+//
+// Use of this function implies acceptance of the LetsEncrypt Terms of
+// Service. If domains is not empty, the provided domains are passed
+// to HostWhitelist. If domains is empty, the listener will do
+// LetsEncrypt challenges for any requested domain, which is not
+// recommended.
+//
+// Certificates are cached in a "golang-autocert" directory under an
+// operating system-specific cache or temp directory. This may not
+// be suitable for servers spanning multiple machines.
+//
+// The returned listener uses a *tls.Config that enables HTTP/2, and
+// should only be used with servers that support HTTP/2.
+//
+// The returned Listener also enables TCP keep-alives on the accepted
+// connections. The returned *tls.Conn are returned before their TLS
+// handshake has completed.
+func NewListener(domains ...string) net.Listener {
+ m := &Manager{
+ Prompt: AcceptTOS,
+ }
+ if len(domains) > 0 {
+ m.HostPolicy = HostWhitelist(domains...)
+ }
+ dir := cacheDir()
+ if err := os.MkdirAll(dir, 0700); err != nil {
+ log.Printf("warning: autocert.NewListener not using a cache: %v", err)
+ } else {
+ m.Cache = DirCache(dir)
+ }
+ return m.Listener()
+}
+
+// Listener listens on the standard TLS port (443) on all interfaces
+// and returns a net.Listener returning *tls.Conn connections.
+//
+// The returned listener uses a *tls.Config that enables HTTP/2, and
+// should only be used with servers that support HTTP/2.
+//
+// The returned Listener also enables TCP keep-alives on the accepted
+// connections. The returned *tls.Conn are returned before their TLS
+// handshake has completed.
+//
+// Unlike NewListener, it is the caller's responsibility to initialize
+// the Manager m's Prompt, Cache, HostPolicy, and other desired options.
+func (m *Manager) Listener() net.Listener {
+ ln := &listener{
+ m: m,
+ conf: &tls.Config{
+ GetCertificate: m.GetCertificate, // bonus: panic on nil m
+ NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
+ },
+ }
+ ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
+ return ln
+}
+
+type listener struct {
+ m *Manager
+ conf *tls.Config
+
+ tcpListener net.Listener
+ tcpListenErr error
+}
+
+func (ln *listener) Accept() (net.Conn, error) {
+ if ln.tcpListenErr != nil {
+ return nil, ln.tcpListenErr
+ }
+ conn, err := ln.tcpListener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ tcpConn := conn.(*net.TCPConn)
+
+ // Because Listener is a convenience function, help out with
+ // this too. This is not possible for the caller to set once
+ // we return a *tcp.Conn wrapping an inaccessible net.Conn.
+ // If callers don't want this, they can do things the manual
+ // way and tweak as needed. But this is what net/http does
+ // itself, so copy that. If net/http changes, we can change
+ // here too.
+ tcpConn.SetKeepAlive(true)
+ tcpConn.SetKeepAlivePeriod(3 * time.Minute)
+
+ return tls.Server(tcpConn, ln.conf), nil
+}
+
+func (ln *listener) Addr() net.Addr {
+ if ln.tcpListener != nil {
+ return ln.tcpListener.Addr()
+ }
+ // net.Listen failed. Return something non-nil in case callers
+ // call Addr before Accept:
+ return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443}
+}
+
+func (ln *listener) Close() error {
+ if ln.tcpListenErr != nil {
+ return ln.tcpListenErr
+ }
+ return ln.tcpListener.Close()
+}
+
+func homeDir() string {
+ if runtime.GOOS == "windows" {
+ return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
+ }
+ if h := os.Getenv("HOME"); h != "" {
+ return h
+ }
+ return "/"
+}
+
+func cacheDir() string {
+ const base = "golang-autocert"
+ switch runtime.GOOS {
+ case "darwin":
+ return filepath.Join(homeDir(), "Library", "Caches", base)
+ case "windows":
+ for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
+ if v := os.Getenv(ev); v != "" {
+ return filepath.Join(v, base)
+ }
+ }
+ // Worst case:
+ return filepath.Join(homeDir(), base)
+ }
+ if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
+ return filepath.Join(xdg, base)
+ }
+ return filepath.Join(homeDir(), ".cache", base)
+}
diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal.go b/vendor/golang.org/x/crypto/acme/autocert/renewal.go
new file mode 100644
index 0000000000..3fa4d61a22
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/autocert/renewal.go
@@ -0,0 +1,141 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert
+
+import (
+ "context"
+ "crypto"
+ "sync"
+ "time"
+)
+
+// renewJitter is the maximum deviation from Manager.RenewBefore.
+const renewJitter = time.Hour
+
+// domainRenewal tracks the state used by the periodic timers
+// renewing a single domain's cert.
+type domainRenewal struct {
+ m *Manager
+ domain string
+ key crypto.Signer
+
+ timerMu sync.Mutex
+ timer *time.Timer
+}
+
+// start starts a cert renewal timer at the time
+// defined by the certificate expiration time exp.
+//
+// If the timer is already started, calling start is a noop.
+func (dr *domainRenewal) start(exp time.Time) {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer != nil {
+ return
+ }
+ dr.timer = time.AfterFunc(dr.next(exp), dr.renew)
+}
+
+// stop stops the cert renewal timer.
+// If the timer is already stopped, calling stop is a noop.
+func (dr *domainRenewal) stop() {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer == nil {
+ return
+ }
+ dr.timer.Stop()
+ dr.timer = nil
+}
+
+// renew is called periodically by a timer.
+// The first renew call is kicked off by dr.start.
+func (dr *domainRenewal) renew() {
+ dr.timerMu.Lock()
+ defer dr.timerMu.Unlock()
+ if dr.timer == nil {
+ return
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
+ defer cancel()
+ // TODO: rotate dr.key at some point?
+ next, err := dr.do(ctx)
+ if err != nil {
+ next = renewJitter / 2
+ next += time.Duration(pseudoRand.int63n(int64(next)))
+ }
+ dr.timer = time.AfterFunc(next, dr.renew)
+ testDidRenewLoop(next, err)
+}
+
+// updateState locks and replaces the relevant Manager.state item with the given
+// state. It additionally updates dr.key with the given state's key.
+func (dr *domainRenewal) updateState(state *certState) {
+ dr.m.stateMu.Lock()
+ defer dr.m.stateMu.Unlock()
+ dr.key = state.key
+ dr.m.state[dr.domain] = state
+}
+
+// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
+// Instead, it requests a new certificate independently and, upon success,
+// replaces dr.m.state item with a new one and updates cache for the given domain.
+//
+// It may lock and update the Manager.state if the expiration date of the currently
+// cached cert is far enough in the future.
+//
+// The returned value is a time interval after which the renewal should occur again.
+func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
+ // a race is likely unavoidable in a distributed environment
+ // but we try nonetheless
+ if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil {
+ next := dr.next(tlscert.Leaf.NotAfter)
+ if next > dr.m.renewBefore()+renewJitter {
+ signer, ok := tlscert.PrivateKey.(crypto.Signer)
+ if ok {
+ state := &certState{
+ key: signer,
+ cert: tlscert.Certificate,
+ leaf: tlscert.Leaf,
+ }
+ dr.updateState(state)
+ return next, nil
+ }
+ }
+ }
+
+ der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain)
+ if err != nil {
+ return 0, err
+ }
+ state := &certState{
+ key: dr.key,
+ cert: der,
+ leaf: leaf,
+ }
+ tlscert, err := state.tlscert()
+ if err != nil {
+ return 0, err
+ }
+ if err := dr.m.cachePut(ctx, dr.domain, tlscert); err != nil {
+ return 0, err
+ }
+ dr.updateState(state)
+ return dr.next(leaf.NotAfter), nil
+}
+
+func (dr *domainRenewal) next(expiry time.Time) time.Duration {
+ d := expiry.Sub(timeNow()) - dr.m.renewBefore()
+ // add a bit of randomness to renew deadline
+ n := pseudoRand.int63n(int64(renewJitter))
+ d -= time.Duration(n)
+ if d < 0 {
+ return 0
+ }
+ return d
+}
+
+var testDidRenewLoop = func(next time.Duration, err error) {}
diff --git a/vendor/golang.org/x/crypto/acme/jws.go b/vendor/golang.org/x/crypto/acme/jws.go
new file mode 100644
index 0000000000..6cbca25de9
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/jws.go
@@ -0,0 +1,153 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package acme
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ _ "crypto/sha512" // need for EC keys
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "math/big"
+)
+
+// jwsEncodeJSON signs claimset using provided key and a nonce.
+// The result is serialized in JSON format.
+// See https://tools.ietf.org/html/rfc7515#section-7.
+func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
+ jwk, err := jwkEncode(key.Public())
+ if err != nil {
+ return nil, err
+ }
+ alg, sha := jwsHasher(key)
+ if alg == "" || !sha.Available() {
+ return nil, ErrUnsupportedKey
+ }
+ phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce)
+ phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
+ cs, err := json.Marshal(claimset)
+ if err != nil {
+ return nil, err
+ }
+ payload := base64.RawURLEncoding.EncodeToString(cs)
+ hash := sha.New()
+ hash.Write([]byte(phead + "." + payload))
+ sig, err := jwsSign(key, sha, hash.Sum(nil))
+ if err != nil {
+ return nil, err
+ }
+
+ enc := struct {
+ Protected string `json:"protected"`
+ Payload string `json:"payload"`
+ Sig string `json:"signature"`
+ }{
+ Protected: phead,
+ Payload: payload,
+ Sig: base64.RawURLEncoding.EncodeToString(sig),
+ }
+ return json.Marshal(&enc)
+}
+
+// jwkEncode encodes public part of an RSA or ECDSA key into a JWK.
+// The result is also suitable for creating a JWK thumbprint.
+// https://tools.ietf.org/html/rfc7517
+func jwkEncode(pub crypto.PublicKey) (string, error) {
+ switch pub := pub.(type) {
+ case *rsa.PublicKey:
+ // https://tools.ietf.org/html/rfc7518#section-6.3.1
+ n := pub.N
+ e := big.NewInt(int64(pub.E))
+ // Field order is important.
+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
+ return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`,
+ base64.RawURLEncoding.EncodeToString(e.Bytes()),
+ base64.RawURLEncoding.EncodeToString(n.Bytes()),
+ ), nil
+ case *ecdsa.PublicKey:
+ // https://tools.ietf.org/html/rfc7518#section-6.2.1
+ p := pub.Curve.Params()
+ n := p.BitSize / 8
+ if p.BitSize%8 != 0 {
+ n++
+ }
+ x := pub.X.Bytes()
+ if n > len(x) {
+ x = append(make([]byte, n-len(x)), x...)
+ }
+ y := pub.Y.Bytes()
+ if n > len(y) {
+ y = append(make([]byte, n-len(y)), y...)
+ }
+ // Field order is important.
+ // See https://tools.ietf.org/html/rfc7638#section-3.3 for details.
+ return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`,
+ p.Name,
+ base64.RawURLEncoding.EncodeToString(x),
+ base64.RawURLEncoding.EncodeToString(y),
+ ), nil
+ }
+ return "", ErrUnsupportedKey
+}
+
+// jwsSign signs the digest using the given key.
+// It returns ErrUnsupportedKey if the key type is unknown.
+// The hash is used only for RSA keys.
+func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return key.Sign(rand.Reader, digest, hash)
+ case *ecdsa.PrivateKey:
+ r, s, err := ecdsa.Sign(rand.Reader, key, digest)
+ if err != nil {
+ return nil, err
+ }
+ rb, sb := r.Bytes(), s.Bytes()
+ size := key.Params().BitSize / 8
+ if size%8 > 0 {
+ size++
+ }
+ sig := make([]byte, size*2)
+ copy(sig[size-len(rb):], rb)
+ copy(sig[size*2-len(sb):], sb)
+ return sig, nil
+ }
+ return nil, ErrUnsupportedKey
+}
+
+// jwsHasher indicates suitable JWS algorithm name and a hash function
+// to use for signing a digest with the provided key.
+// It returns ("", 0) if the key is not supported.
+func jwsHasher(key crypto.Signer) (string, crypto.Hash) {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return "RS256", crypto.SHA256
+ case *ecdsa.PrivateKey:
+ switch key.Params().Name {
+ case "P-256":
+ return "ES256", crypto.SHA256
+ case "P-384":
+ return "ES384", crypto.SHA384
+ case "P-521":
+ return "ES512", crypto.SHA512
+ }
+ }
+ return "", 0
+}
+
+// JWKThumbprint creates a JWK thumbprint out of pub
+// as specified in https://tools.ietf.org/html/rfc7638.
+func JWKThumbprint(pub crypto.PublicKey) (string, error) {
+ jwk, err := jwkEncode(pub)
+ if err != nil {
+ return "", err
+ }
+ b := sha256.Sum256([]byte(jwk))
+ return base64.RawURLEncoding.EncodeToString(b[:]), nil
+}
diff --git a/vendor/golang.org/x/crypto/acme/types.go b/vendor/golang.org/x/crypto/acme/types.go
new file mode 100644
index 0000000000..3e199749ec
--- /dev/null
+++ b/vendor/golang.org/x/crypto/acme/types.go
@@ -0,0 +1,329 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package acme
+
+import (
+ "crypto"
+ "crypto/x509"
+ "errors"
+ "fmt"
+ "net/http"
+ "strings"
+ "time"
+)
+
+// ACME server response statuses used to describe Authorization and Challenge states.
+const (
+ StatusUnknown = "unknown"
+ StatusPending = "pending"
+ StatusProcessing = "processing"
+ StatusValid = "valid"
+ StatusInvalid = "invalid"
+ StatusRevoked = "revoked"
+)
+
+// CRLReasonCode identifies the reason for a certificate revocation.
+type CRLReasonCode int
+
+// CRL reason codes as defined in RFC 5280.
+const (
+ CRLReasonUnspecified CRLReasonCode = 0
+ CRLReasonKeyCompromise CRLReasonCode = 1
+ CRLReasonCACompromise CRLReasonCode = 2
+ CRLReasonAffiliationChanged CRLReasonCode = 3
+ CRLReasonSuperseded CRLReasonCode = 4
+ CRLReasonCessationOfOperation CRLReasonCode = 5
+ CRLReasonCertificateHold CRLReasonCode = 6
+ CRLReasonRemoveFromCRL CRLReasonCode = 8
+ CRLReasonPrivilegeWithdrawn CRLReasonCode = 9
+ CRLReasonAACompromise CRLReasonCode = 10
+)
+
+// ErrUnsupportedKey is returned when an unsupported key type is encountered.
+var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported")
+
+// Error is an ACME error, defined in Problem Details for HTTP APIs doc
+// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem.
+type Error struct {
+ // StatusCode is The HTTP status code generated by the origin server.
+ StatusCode int
+ // ProblemType is a URI reference that identifies the problem type,
+ // typically in a "urn:acme:error:xxx" form.
+ ProblemType string
+ // Detail is a human-readable explanation specific to this occurrence of the problem.
+ Detail string
+ // Header is the original server error response headers.
+ // It may be nil.
+ Header http.Header
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail)
+}
+
+// AuthorizationError indicates that an authorization for an identifier
+// did not succeed.
+// It contains all errors from Challenge items of the failed Authorization.
+type AuthorizationError struct {
+ // URI uniquely identifies the failed Authorization.
+ URI string
+
+ // Identifier is an AuthzID.Value of the failed Authorization.
+ Identifier string
+
+ // Errors is a collection of non-nil error values of Challenge items
+ // of the failed Authorization.
+ Errors []error
+}
+
+func (a *AuthorizationError) Error() string {
+ e := make([]string, len(a.Errors))
+ for i, err := range a.Errors {
+ e[i] = err.Error()
+ }
+ return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; "))
+}
+
+// RateLimit reports whether err represents a rate limit error and
+// any Retry-After duration returned by the server.
+//
+// See the following for more details on rate limiting:
+// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6
+func RateLimit(err error) (time.Duration, bool) {
+ e, ok := err.(*Error)
+ if !ok {
+ return 0, false
+ }
+ // Some CA implementations may return incorrect values.
+ // Use case-insensitive comparison.
+ if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") {
+ return 0, false
+ }
+ if e.Header == nil {
+ return 0, true
+ }
+ return retryAfter(e.Header.Get("Retry-After"), 0), true
+}
+
+// Account is a user account. It is associated with a private key.
+type Account struct {
+ // URI is the account unique ID, which is also a URL used to retrieve
+ // account data from the CA.
+ URI string
+
+ // Contact is a slice of contact info used during registration.
+ Contact []string
+
+ // The terms user has agreed to.
+ // A value not matching CurrentTerms indicates that the user hasn't agreed
+ // to the actual Terms of Service of the CA.
+ AgreedTerms string
+
+ // Actual terms of a CA.
+ CurrentTerms string
+
+ // Authz is the authorization URL used to initiate a new authz flow.
+ Authz string
+
+ // Authorizations is a URI from which a list of authorizations
+ // granted to this account can be fetched via a GET request.
+ Authorizations string
+
+ // Certificates is a URI from which a list of certificates
+ // issued for this account can be fetched via a GET request.
+ Certificates string
+}
+
+// Directory is ACME server discovery data.
+type Directory struct {
+ // RegURL is an account endpoint URL, allowing for creating new
+ // and modifying existing accounts.
+ RegURL string
+
+ // AuthzURL is used to initiate Identifier Authorization flow.
+ AuthzURL string
+
+ // CertURL is a new certificate issuance endpoint URL.
+ CertURL string
+
+ // RevokeURL is used to initiate a certificate revocation flow.
+ RevokeURL string
+
+ // Term is a URI identifying the current terms of service.
+ Terms string
+
+ // Website is an HTTP or HTTPS URL locating a website
+ // providing more information about the ACME server.
+ Website string
+
+ // CAA consists of lowercase hostname elements, which the ACME server
+ // recognises as referring to itself for the purposes of CAA record validation
+ // as defined in RFC6844.
+ CAA []string
+}
+
+// Challenge encodes a returned CA challenge.
+// Its Error field may be non-nil if the challenge is part of an Authorization
+// with StatusInvalid.
+type Challenge struct {
+ // Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01".
+ Type string
+
+ // URI is where a challenge response can be posted to.
+ URI string
+
+ // Token is a random value that uniquely identifies the challenge.
+ Token string
+
+ // Status identifies the status of this challenge.
+ Status string
+
+ // Error indicates the reason for an authorization failure
+ // when this challenge was used.
+ // The type of a non-nil value is *Error.
+ Error error
+}
+
+// Authorization encodes an authorization response.
+type Authorization struct {
+ // URI uniquely identifies a authorization.
+ URI string
+
+ // Status identifies the status of an authorization.
+ Status string
+
+ // Identifier is what the account is authorized to represent.
+ Identifier AuthzID
+
+ // Challenges that the client needs to fulfill in order to prove possession
+ // of the identifier (for pending authorizations).
+ // For final authorizations, the challenges that were used.
+ Challenges []*Challenge
+
+ // A collection of sets of challenges, each of which would be sufficient
+ // to prove possession of the identifier.
+ // Clients must complete a set of challenges that covers at least one set.
+ // Challenges are identified by their indices in the challenges array.
+ // If this field is empty, the client needs to complete all challenges.
+ Combinations [][]int
+}
+
+// AuthzID is an identifier that an account is authorized to represent.
+type AuthzID struct {
+ Type string // The type of identifier, e.g. "dns".
+ Value string // The identifier itself, e.g. "example.org".
+}
+
+// wireAuthz is ACME JSON representation of Authorization objects.
+type wireAuthz struct {
+ Status string
+ Challenges []wireChallenge
+ Combinations [][]int
+ Identifier struct {
+ Type string
+ Value string
+ }
+}
+
+func (z *wireAuthz) authorization(uri string) *Authorization {
+ a := &Authorization{
+ URI: uri,
+ Status: z.Status,
+ Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
+ Combinations: z.Combinations, // shallow copy
+ Challenges: make([]*Challenge, len(z.Challenges)),
+ }
+ for i, v := range z.Challenges {
+ a.Challenges[i] = v.challenge()
+ }
+ return a
+}
+
+func (z *wireAuthz) error(uri string) *AuthorizationError {
+ err := &AuthorizationError{
+ URI: uri,
+ Identifier: z.Identifier.Value,
+ }
+ for _, raw := range z.Challenges {
+ if raw.Error != nil {
+ err.Errors = append(err.Errors, raw.Error.error(nil))
+ }
+ }
+ return err
+}
+
+// wireChallenge is ACME JSON challenge representation.
+type wireChallenge struct {
+ URI string `json:"uri"`
+ Type string
+ Token string
+ Status string
+ Error *wireError
+}
+
+func (c *wireChallenge) challenge() *Challenge {
+ v := &Challenge{
+ URI: c.URI,
+ Type: c.Type,
+ Token: c.Token,
+ Status: c.Status,
+ }
+ if v.Status == "" {
+ v.Status = StatusPending
+ }
+ if c.Error != nil {
+ v.Error = c.Error.error(nil)
+ }
+ return v
+}
+
+// wireError is a subset of fields of the Problem Details object
+// as described in https://tools.ietf.org/html/rfc7807#section-3.1.
+type wireError struct {
+ Status int
+ Type string
+ Detail string
+}
+
+func (e *wireError) error(h http.Header) *Error {
+ return &Error{
+ StatusCode: e.Status,
+ ProblemType: e.Type,
+ Detail: e.Detail,
+ Header: h,
+ }
+}
+
+// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for
+// customizing a temporary certificate for TLS-SNI challenges.
+type CertOption interface {
+ privateCertOpt()
+}
+
+// WithKey creates an option holding a private/public key pair.
+// The private part signs a certificate, and the public part represents the signee.
+func WithKey(key crypto.Signer) CertOption {
+ return &certOptKey{key}
+}
+
+type certOptKey struct {
+ key crypto.Signer
+}
+
+func (*certOptKey) privateCertOpt() {}
+
+// WithTemplate creates an option for specifying a certificate template.
+// See x509.CreateCertificate for template usage details.
+//
+// In TLSSNIxChallengeCert methods, the template is also used as parent,
+// resulting in a self-signed certificate.
+// The DNSNames field of t is always overwritten for tls-sni challenge certs.
+func WithTemplate(t *x509.Certificate) CertOption {
+ return (*certOptTemplate)(t)
+}
+
+type certOptTemplate x509.Certificate
+
+func (*certOptTemplate) privateCertOpt() {}
diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go
index 4f26b49b6a..a57771a1ed 100644
--- a/vendor/golang.org/x/crypto/ed25519/ed25519.go
+++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go
@@ -171,9 +171,16 @@ func Verify(publicKey PublicKey, message, sig []byte) bool {
edwards25519.ScReduce(&hReduced, &digest)
var R edwards25519.ProjectiveGroupElement
- var b [32]byte
- copy(b[:], sig[32:])
- edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
+ var s [32]byte
+ copy(s[:], sig[32:])
+
+ // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
+ // the range [0, order) in order to prevent signature malleability.
+ if !edwards25519.ScMinimal(&s) {
+ return false
+ }
+
+ edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
var checkR [32]byte
R.ToBytes(&checkR)
diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
index 5f8b994787..fd03c252af 100644
--- a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
+++ b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
@@ -4,6 +4,8 @@
package edwards25519
+import "encoding/binary"
+
// This code is a port of the public domain, “ref10” implementation of ed25519
// from SUPERCOP.
@@ -1769,3 +1771,23 @@ func ScReduce(out *[32]byte, s *[64]byte) {
out[30] = byte(s11 >> 9)
out[31] = byte(s11 >> 17)
}
+
+// order is the order of Curve25519 in little-endian form.
+var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000}
+
+// ScMinimal returns true if the given scalar is less than the order of the
+// curve.
+func ScMinimal(scalar *[32]byte) bool {
+ for i := 3; ; i-- {
+ v := binary.LittleEndian.Uint64(scalar[i*8:])
+ if v > order[i] {
+ return false
+ } else if v < order[i] {
+ break
+ } else if i == 0 {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
new file mode 100644
index 0000000000..7c7269676a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
@@ -0,0 +1,223 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ChaCha20 implements the core ChaCha20 function as specified
+// in https://tools.ietf.org/html/rfc7539#section-2.3.
+package chacha20
+
+import (
+ "crypto/cipher"
+ "encoding/binary"
+)
+
+// assert that *Cipher implements cipher.Stream
+var _ cipher.Stream = (*Cipher)(nil)
+
+// Cipher is a stateful instance of ChaCha20 using a particular key
+// and nonce. A *Cipher implements the cipher.Stream interface.
+type Cipher struct {
+ key [8]uint32
+ nonce [3]uint32
+ counter uint32 // incremented after each block
+ buf [64]byte // buffer for unused keystream bytes
+ len int // number of unused keystream bytes at end of buf
+}
+
+// New creates a new ChaCha20 stream cipher with the given key and nonce.
+// The initial counter value is set to 0.
+func New(key [8]uint32, nonce [3]uint32) *Cipher {
+ return &Cipher{key: key, nonce: nonce}
+}
+
+// XORKeyStream XORs each byte in the given slice with a byte from the
+// cipher's key stream. Dst and src must overlap entirely or not at all.
+//
+// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
+// to pass a dst bigger than src, and in that case, XORKeyStream will
+// only update dst[:len(src)] and will not touch the rest of dst.
+//
+// Multiple calls to XORKeyStream behave as if the concatenation of
+// the src buffers was passed in a single run. That is, Cipher
+// maintains state and does not reset at each XORKeyStream call.
+func (s *Cipher) XORKeyStream(dst, src []byte) {
+ // xor src with buffered keystream first
+ if s.len != 0 {
+ buf := s.buf[len(s.buf)-s.len:]
+ if len(src) < len(buf) {
+ buf = buf[:len(src)]
+ }
+ td, ts := dst[:len(buf)], src[:len(buf)] // BCE hint
+ for i, b := range buf {
+ td[i] = ts[i] ^ b
+ }
+ s.len -= len(buf)
+ if s.len != 0 {
+ return
+ }
+ s.buf = [len(s.buf)]byte{} // zero the empty buffer
+ src = src[len(buf):]
+ dst = dst[len(buf):]
+ }
+
+ if len(src) == 0 {
+ return
+ }
+
+ // set up a 64-byte buffer to pad out the final block if needed
+ // (hoisted out of the main loop to avoid spills)
+ rem := len(src) % 64 // length of final block
+ fin := len(src) - rem // index of final block
+ if rem > 0 {
+ copy(s.buf[len(s.buf)-64:], src[fin:])
+ }
+
+ // qr calculates a quarter round
+ qr := func(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
+ a += b
+ d ^= a
+ d = (d << 16) | (d >> 16)
+ c += d
+ b ^= c
+ b = (b << 12) | (b >> 20)
+ a += b
+ d ^= a
+ d = (d << 8) | (d >> 24)
+ c += d
+ b ^= c
+ b = (b << 7) | (b >> 25)
+ return a, b, c, d
+ }
+
+ // ChaCha20 constants
+ const (
+ j0 = 0x61707865
+ j1 = 0x3320646e
+ j2 = 0x79622d32
+ j3 = 0x6b206574
+ )
+
+ // pre-calculate most of the first round
+ s1, s5, s9, s13 := qr(j1, s.key[1], s.key[5], s.nonce[0])
+ s2, s6, s10, s14 := qr(j2, s.key[2], s.key[6], s.nonce[1])
+ s3, s7, s11, s15 := qr(j3, s.key[3], s.key[7], s.nonce[2])
+
+ n := len(src)
+ src, dst = src[:n:n], dst[:n:n] // BCE hint
+ for i := 0; i < n; i += 64 {
+ // calculate the remainder of the first round
+ s0, s4, s8, s12 := qr(j0, s.key[0], s.key[4], s.counter)
+
+ // execute the second round
+ x0, x5, x10, x15 := qr(s0, s5, s10, s15)
+ x1, x6, x11, x12 := qr(s1, s6, s11, s12)
+ x2, x7, x8, x13 := qr(s2, s7, s8, s13)
+ x3, x4, x9, x14 := qr(s3, s4, s9, s14)
+
+ // execute the remaining 18 rounds
+ for i := 0; i < 9; i++ {
+ x0, x4, x8, x12 = qr(x0, x4, x8, x12)
+ x1, x5, x9, x13 = qr(x1, x5, x9, x13)
+ x2, x6, x10, x14 = qr(x2, x6, x10, x14)
+ x3, x7, x11, x15 = qr(x3, x7, x11, x15)
+
+ x0, x5, x10, x15 = qr(x0, x5, x10, x15)
+ x1, x6, x11, x12 = qr(x1, x6, x11, x12)
+ x2, x7, x8, x13 = qr(x2, x7, x8, x13)
+ x3, x4, x9, x14 = qr(x3, x4, x9, x14)
+ }
+
+ x0 += j0
+ x1 += j1
+ x2 += j2
+ x3 += j3
+
+ x4 += s.key[0]
+ x5 += s.key[1]
+ x6 += s.key[2]
+ x7 += s.key[3]
+ x8 += s.key[4]
+ x9 += s.key[5]
+ x10 += s.key[6]
+ x11 += s.key[7]
+
+ x12 += s.counter
+ x13 += s.nonce[0]
+ x14 += s.nonce[1]
+ x15 += s.nonce[2]
+
+ // increment the counter
+ s.counter += 1
+ if s.counter == 0 {
+ panic("chacha20: counter overflow")
+ }
+
+ // pad to 64 bytes if needed
+ in, out := src[i:], dst[i:]
+ if i == fin {
+ // src[fin:] has already been copied into s.buf before
+ // the main loop
+ in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:]
+ }
+ in, out = in[:64], out[:64] // BCE hint
+
+ // XOR the key stream with the source and write out the result
+ xor(out[0:], in[0:], x0)
+ xor(out[4:], in[4:], x1)
+ xor(out[8:], in[8:], x2)
+ xor(out[12:], in[12:], x3)
+ xor(out[16:], in[16:], x4)
+ xor(out[20:], in[20:], x5)
+ xor(out[24:], in[24:], x6)
+ xor(out[28:], in[28:], x7)
+ xor(out[32:], in[32:], x8)
+ xor(out[36:], in[36:], x9)
+ xor(out[40:], in[40:], x10)
+ xor(out[44:], in[44:], x11)
+ xor(out[48:], in[48:], x12)
+ xor(out[52:], in[52:], x13)
+ xor(out[56:], in[56:], x14)
+ xor(out[60:], in[60:], x15)
+ }
+ // copy any trailing bytes out of the buffer and into dst
+ if rem != 0 {
+ s.len = 64 - rem
+ copy(dst[fin:], s.buf[len(s.buf)-64:])
+ }
+}
+
+// Advance discards bytes in the key stream until the next 64 byte block
+// boundary is reached and updates the counter accordingly. If the key
+// stream is already at a block boundary no bytes will be discarded and
+// the counter will be unchanged.
+func (s *Cipher) Advance() {
+ s.len -= s.len % 64
+ if s.len == 0 {
+ s.buf = [len(s.buf)]byte{}
+ }
+}
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out must overlap entirely or not at all. Counter contains the raw
+// ChaCha20 counter bytes (i.e. block counter followed by nonce).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+ s := Cipher{
+ key: [8]uint32{
+ binary.LittleEndian.Uint32(key[0:4]),
+ binary.LittleEndian.Uint32(key[4:8]),
+ binary.LittleEndian.Uint32(key[8:12]),
+ binary.LittleEndian.Uint32(key[12:16]),
+ binary.LittleEndian.Uint32(key[16:20]),
+ binary.LittleEndian.Uint32(key[20:24]),
+ binary.LittleEndian.Uint32(key[24:28]),
+ binary.LittleEndian.Uint32(key[28:32]),
+ },
+ nonce: [3]uint32{
+ binary.LittleEndian.Uint32(counter[4:8]),
+ binary.LittleEndian.Uint32(counter[8:12]),
+ binary.LittleEndian.Uint32(counter[12:16]),
+ },
+ counter: binary.LittleEndian.Uint32(counter[0:4]),
+ }
+ s.XORKeyStream(out, in)
+}
diff --git a/vendor/golang.org/x/crypto/internal/chacha20/xor.go b/vendor/golang.org/x/crypto/internal/chacha20/xor.go
new file mode 100644
index 0000000000..9c5ba0b33a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/internal/chacha20/xor.go
@@ -0,0 +1,43 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found src the LICENSE file.
+
+package chacha20
+
+import (
+ "runtime"
+)
+
+// Platforms that have fast unaligned 32-bit little endian accesses.
+const unaligned = runtime.GOARCH == "386" ||
+ runtime.GOARCH == "amd64" ||
+ runtime.GOARCH == "arm64" ||
+ runtime.GOARCH == "ppc64le" ||
+ runtime.GOARCH == "s390x"
+
+// xor reads a little endian uint32 from src, XORs it with u and
+// places the result in little endian byte order in dst.
+func xor(dst, src []byte, u uint32) {
+ _, _ = src[3], dst[3] // eliminate bounds checks
+ if unaligned {
+ // The compiler should optimize this code into
+ // 32-bit unaligned little endian loads and stores.
+ // TODO: delete once the compiler does a reliably
+ // good job with the generic code below.
+ // See issue #25111 for more details.
+ v := uint32(src[0])
+ v |= uint32(src[1]) << 8
+ v |= uint32(src[2]) << 16
+ v |= uint32(src[3]) << 24
+ v ^= u
+ dst[0] = byte(v)
+ dst[1] = byte(v >> 8)
+ dst[2] = byte(v >> 16)
+ dst[3] = byte(v >> 24)
+ } else {
+ dst[0] = src[0] ^ byte(u)
+ dst[1] = src[1] ^ byte(u>>8)
+ dst[2] = src[2] ^ byte(u>>16)
+ dst[3] = src[3] ^ byte(u>>24)
+ }
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/golang.org/x/crypto/poly1305/poly1305.go
new file mode 100644
index 0000000000..f562fa5712
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/poly1305.go
@@ -0,0 +1,33 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package poly1305 implements Poly1305 one-time message authentication code as
+specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
+
+Poly1305 is a fast, one-time authentication function. It is infeasible for an
+attacker to generate an authenticator for a message without the key. However, a
+key must only be used for a single message. Authenticating two different
+messages with the same key allows an attacker to forge authenticators for other
+messages with the same key.
+
+Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
+used with a fixed key in order to generate one-time keys from an nonce.
+However, in this package AES isn't used and the one-time key is specified
+directly.
+*/
+package poly1305 // import "golang.org/x/crypto/poly1305"
+
+import "crypto/subtle"
+
+// TagSize is the size, in bytes, of a poly1305 authenticator.
+const TagSize = 16
+
+// Verify returns true if mac is a valid authenticator for m with the given
+// key.
+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
+ var tmp [16]byte
+ Sum(&tmp, m, key)
+ return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go
new file mode 100644
index 0000000000..4dd72fe799
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go
@@ -0,0 +1,22 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo,!appengine
+
+package poly1305
+
+// This function is implemented in sum_amd64.s
+//go:noescape
+func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ var mPtr *byte
+ if len(m) > 0 {
+ mPtr = &m[0]
+ }
+ poly1305(out, mPtr, uint64(len(m)), key)
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/poly1305/sum_amd64.s
new file mode 100644
index 0000000000..2edae63828
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.s
@@ -0,0 +1,125 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo,!appengine
+
+#include "textflag.h"
+
+#define POLY1305_ADD(msg, h0, h1, h2) \
+ ADDQ 0(msg), h0; \
+ ADCQ 8(msg), h1; \
+ ADCQ $1, h2; \
+ LEAQ 16(msg), msg
+
+#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \
+ MOVQ r0, AX; \
+ MULQ h0; \
+ MOVQ AX, t0; \
+ MOVQ DX, t1; \
+ MOVQ r0, AX; \
+ MULQ h1; \
+ ADDQ AX, t1; \
+ ADCQ $0, DX; \
+ MOVQ r0, t2; \
+ IMULQ h2, t2; \
+ ADDQ DX, t2; \
+ \
+ MOVQ r1, AX; \
+ MULQ h0; \
+ ADDQ AX, t1; \
+ ADCQ $0, DX; \
+ MOVQ DX, h0; \
+ MOVQ r1, t3; \
+ IMULQ h2, t3; \
+ MOVQ r1, AX; \
+ MULQ h1; \
+ ADDQ AX, t2; \
+ ADCQ DX, t3; \
+ ADDQ h0, t2; \
+ ADCQ $0, t3; \
+ \
+ MOVQ t0, h0; \
+ MOVQ t1, h1; \
+ MOVQ t2, h2; \
+ ANDQ $3, h2; \
+ MOVQ t2, t0; \
+ ANDQ $0xFFFFFFFFFFFFFFFC, t0; \
+ ADDQ t0, h0; \
+ ADCQ t3, h1; \
+ ADCQ $0, h2; \
+ SHRQ $2, t3, t2; \
+ SHRQ $2, t3; \
+ ADDQ t2, h0; \
+ ADCQ t3, h1; \
+ ADCQ $0, h2
+
+DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
+DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
+GLOBL ·poly1305Mask<>(SB), RODATA, $16
+
+// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
+TEXT ·poly1305(SB), $0-32
+ MOVQ out+0(FP), DI
+ MOVQ m+8(FP), SI
+ MOVQ mlen+16(FP), R15
+ MOVQ key+24(FP), AX
+
+ MOVQ 0(AX), R11
+ MOVQ 8(AX), R12
+ ANDQ ·poly1305Mask<>(SB), R11 // r0
+ ANDQ ·poly1305Mask<>+8(SB), R12 // r1
+ XORQ R8, R8 // h0
+ XORQ R9, R9 // h1
+ XORQ R10, R10 // h2
+
+ CMPQ R15, $16
+ JB bytes_between_0_and_15
+
+loop:
+ POLY1305_ADD(SI, R8, R9, R10)
+
+multiply:
+ POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14)
+ SUBQ $16, R15
+ CMPQ R15, $16
+ JAE loop
+
+bytes_between_0_and_15:
+ TESTQ R15, R15
+ JZ done
+ MOVQ $1, BX
+ XORQ CX, CX
+ XORQ R13, R13
+ ADDQ R15, SI
+
+flush_buffer:
+ SHLQ $8, BX, CX
+ SHLQ $8, BX
+ MOVB -1(SI), R13
+ XORQ R13, BX
+ DECQ SI
+ DECQ R15
+ JNZ flush_buffer
+
+ ADDQ BX, R8
+ ADCQ CX, R9
+ ADCQ $0, R10
+ MOVQ $16, R15
+ JMP multiply
+
+done:
+ MOVQ R8, AX
+ MOVQ R9, BX
+ SUBQ $0xFFFFFFFFFFFFFFFB, AX
+ SBBQ $0xFFFFFFFFFFFFFFFF, BX
+ SBBQ $3, R10
+ CMOVQCS R8, AX
+ CMOVQCS R9, BX
+ MOVQ key+24(FP), R8
+ ADDQ 16(R8), AX
+ ADCQ 24(R8), BX
+
+ MOVQ AX, 0(DI)
+ MOVQ BX, 8(DI)
+ RET
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.go b/vendor/golang.org/x/crypto/poly1305/sum_arm.go
new file mode 100644
index 0000000000..5dc321c2f3
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_arm.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build arm,!gccgo,!appengine,!nacl
+
+package poly1305
+
+// This function is implemented in sum_arm.s
+//go:noescape
+func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ var mPtr *byte
+ if len(m) > 0 {
+ mPtr = &m[0]
+ }
+ poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.s b/vendor/golang.org/x/crypto/poly1305/sum_arm.s
new file mode 100644
index 0000000000..f70b4ac484
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_arm.s
@@ -0,0 +1,427 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build arm,!gccgo,!appengine,!nacl
+
+#include "textflag.h"
+
+// This code was translated into a form compatible with 5a from the public
+// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
+
+DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
+DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
+DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
+DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
+DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
+GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
+
+// Warning: the linker may use R11 to synthesize certain instructions. Please
+// take care and verify that no synthetic instructions use it.
+
+TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
+ // Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It
+ // might look like it's only 60 bytes of space but the final four bytes
+ // will be written by another function.) We need to skip over four
+ // bytes of stack because that's saving the value of 'g'.
+ ADD $4, R13, R8
+ MOVM.IB [R4-R7], (R8)
+ MOVM.IA.W (R1), [R2-R5]
+ MOVW $·poly1305_init_constants_armv6<>(SB), R7
+ MOVW R2, R8
+ MOVW R2>>26, R9
+ MOVW R3>>20, g
+ MOVW R4>>14, R11
+ MOVW R5>>8, R12
+ ORR R3<<6, R9, R9
+ ORR R4<<12, g, g
+ ORR R5<<18, R11, R11
+ MOVM.IA (R7), [R2-R6]
+ AND R8, R2, R2
+ AND R9, R3, R3
+ AND g, R4, R4
+ AND R11, R5, R5
+ AND R12, R6, R6
+ MOVM.IA.W [R2-R6], (R0)
+ EOR R2, R2, R2
+ EOR R3, R3, R3
+ EOR R4, R4, R4
+ EOR R5, R5, R5
+ EOR R6, R6, R6
+ MOVM.IA.W [R2-R6], (R0)
+ MOVM.IA.W (R1), [R2-R5]
+ MOVM.IA [R2-R6], (R0)
+ ADD $20, R13, R0
+ MOVM.DA (R0), [R4-R7]
+ RET
+
+#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
+ MOVBU (offset+0)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+0)(Rdst); \
+ MOVBU (offset+1)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+1)(Rdst); \
+ MOVBU (offset+2)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+2)(Rdst); \
+ MOVBU (offset+3)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+3)(Rdst)
+
+TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0
+ // Needs 24 bytes of stack for saved registers and then 88 bytes of
+ // scratch space after that. We assume that 24 bytes at (R13) have
+ // already been used: four bytes for the link register saved in the
+ // prelude of poly1305_auth_armv6, four bytes for saving the value of g
+ // in that function and 16 bytes of scratch space used around
+ // poly1305_finish_ext_armv6_skip1.
+ ADD $24, R13, R12
+ MOVM.IB [R4-R8, R14], (R12)
+ MOVW R0, 88(R13)
+ MOVW R1, 92(R13)
+ MOVW R2, 96(R13)
+ MOVW R1, R14
+ MOVW R2, R12
+ MOVW 56(R0), R8
+ WORD $0xe1180008 // TST R8, R8 not working see issue 5921
+ EOR R6, R6, R6
+ MOVW.EQ $(1<<24), R6
+ MOVW R6, 84(R13)
+ ADD $116, R13, g
+ MOVM.IA (R0), [R0-R9]
+ MOVM.IA [R0-R4], (g)
+ CMP $16, R12
+ BLO poly1305_blocks_armv6_done
+
+poly1305_blocks_armv6_mainloop:
+ WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
+ BEQ poly1305_blocks_armv6_mainloop_aligned
+ ADD $100, R13, g
+ MOVW_UNALIGNED(R14, g, R0, 0)
+ MOVW_UNALIGNED(R14, g, R0, 4)
+ MOVW_UNALIGNED(R14, g, R0, 8)
+ MOVW_UNALIGNED(R14, g, R0, 12)
+ MOVM.IA (g), [R0-R3]
+ ADD $16, R14
+ B poly1305_blocks_armv6_mainloop_loaded
+
+poly1305_blocks_armv6_mainloop_aligned:
+ MOVM.IA.W (R14), [R0-R3]
+
+poly1305_blocks_armv6_mainloop_loaded:
+ MOVW R0>>26, g
+ MOVW R1>>20, R11
+ MOVW R2>>14, R12
+ MOVW R14, 92(R13)
+ MOVW R3>>8, R4
+ ORR R1<<6, g, g
+ ORR R2<<12, R11, R11
+ ORR R3<<18, R12, R12
+ BIC $0xfc000000, R0, R0
+ BIC $0xfc000000, g, g
+ MOVW 84(R13), R3
+ BIC $0xfc000000, R11, R11
+ BIC $0xfc000000, R12, R12
+ ADD R0, R5, R5
+ ADD g, R6, R6
+ ORR R3, R4, R4
+ ADD R11, R7, R7
+ ADD $116, R13, R14
+ ADD R12, R8, R8
+ ADD R4, R9, R9
+ MOVM.IA (R14), [R0-R4]
+ MULLU R4, R5, (R11, g)
+ MULLU R3, R5, (R14, R12)
+ MULALU R3, R6, (R11, g)
+ MULALU R2, R6, (R14, R12)
+ MULALU R2, R7, (R11, g)
+ MULALU R1, R7, (R14, R12)
+ ADD R4<<2, R4, R4
+ ADD R3<<2, R3, R3
+ MULALU R1, R8, (R11, g)
+ MULALU R0, R8, (R14, R12)
+ MULALU R0, R9, (R11, g)
+ MULALU R4, R9, (R14, R12)
+ MOVW g, 76(R13)
+ MOVW R11, 80(R13)
+ MOVW R12, 68(R13)
+ MOVW R14, 72(R13)
+ MULLU R2, R5, (R11, g)
+ MULLU R1, R5, (R14, R12)
+ MULALU R1, R6, (R11, g)
+ MULALU R0, R6, (R14, R12)
+ MULALU R0, R7, (R11, g)
+ MULALU R4, R7, (R14, R12)
+ ADD R2<<2, R2, R2
+ ADD R1<<2, R1, R1
+ MULALU R4, R8, (R11, g)
+ MULALU R3, R8, (R14, R12)
+ MULALU R3, R9, (R11, g)
+ MULALU R2, R9, (R14, R12)
+ MOVW g, 60(R13)
+ MOVW R11, 64(R13)
+ MOVW R12, 52(R13)
+ MOVW R14, 56(R13)
+ MULLU R0, R5, (R11, g)
+ MULALU R4, R6, (R11, g)
+ MULALU R3, R7, (R11, g)
+ MULALU R2, R8, (R11, g)
+ MULALU R1, R9, (R11, g)
+ ADD $52, R13, R0
+ MOVM.IA (R0), [R0-R7]
+ MOVW g>>26, R12
+ MOVW R4>>26, R14
+ ORR R11<<6, R12, R12
+ ORR R5<<6, R14, R14
+ BIC $0xfc000000, g, g
+ BIC $0xfc000000, R4, R4
+ ADD.S R12, R0, R0
+ ADC $0, R1, R1
+ ADD.S R14, R6, R6
+ ADC $0, R7, R7
+ MOVW R0>>26, R12
+ MOVW R6>>26, R14
+ ORR R1<<6, R12, R12
+ ORR R7<<6, R14, R14
+ BIC $0xfc000000, R0, R0
+ BIC $0xfc000000, R6, R6
+ ADD R14<<2, R14, R14
+ ADD.S R12, R2, R2
+ ADC $0, R3, R3
+ ADD R14, g, g
+ MOVW R2>>26, R12
+ MOVW g>>26, R14
+ ORR R3<<6, R12, R12
+ BIC $0xfc000000, g, R5
+ BIC $0xfc000000, R2, R7
+ ADD R12, R4, R4
+ ADD R14, R0, R0
+ MOVW R4>>26, R12
+ BIC $0xfc000000, R4, R8
+ ADD R12, R6, R9
+ MOVW 96(R13), R12
+ MOVW 92(R13), R14
+ MOVW R0, R6
+ CMP $32, R12
+ SUB $16, R12, R12
+ MOVW R12, 96(R13)
+ BHS poly1305_blocks_armv6_mainloop
+
+poly1305_blocks_armv6_done:
+ MOVW 88(R13), R12
+ MOVW R5, 20(R12)
+ MOVW R6, 24(R12)
+ MOVW R7, 28(R12)
+ MOVW R8, 32(R12)
+ MOVW R9, 36(R12)
+ ADD $48, R13, R0
+ MOVM.DA (R0), [R4-R8, R14]
+ RET
+
+#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
+ MOVBU.P 1(Rsrc), Rtmp; \
+ MOVBU.P Rtmp, 1(Rdst); \
+ MOVBU.P 1(Rsrc), Rtmp; \
+ MOVBU.P Rtmp, 1(Rdst)
+
+#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \
+ MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
+ MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
+
+// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
+TEXT ·poly1305_auth_armv6(SB), $196-16
+ // The value 196, just above, is the sum of 64 (the size of the context
+ // structure) and 132 (the amount of stack needed).
+ //
+ // At this point, the stack pointer (R13) has been moved down. It
+ // points to the saved link register and there's 196 bytes of free
+ // space above it.
+ //
+ // The stack for this function looks like:
+ //
+ // +---------------------
+ // |
+ // | 64 bytes of context structure
+ // |
+ // +---------------------
+ // |
+ // | 112 bytes for poly1305_blocks_armv6
+ // |
+ // +---------------------
+ // | 16 bytes of final block, constructed at
+ // | poly1305_finish_ext_armv6_skip8
+ // +---------------------
+ // | four bytes of saved 'g'
+ // +---------------------
+ // | lr, saved by prelude <- R13 points here
+ // +---------------------
+ MOVW g, 4(R13)
+
+ MOVW out+0(FP), R4
+ MOVW m+4(FP), R5
+ MOVW mlen+8(FP), R6
+ MOVW key+12(FP), R7
+
+ ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112
+ MOVW R7, R1
+
+ // poly1305_init_ext_armv6 will write to the stack from R13+4, but
+ // that's ok because none of the other values have been written yet.
+ BL poly1305_init_ext_armv6<>(SB)
+ BIC.S $15, R6, R2
+ BEQ poly1305_auth_armv6_noblocks
+ ADD $136, R13, R0
+ MOVW R5, R1
+ ADD R2, R5, R5
+ SUB R2, R6, R6
+ BL poly1305_blocks_armv6<>(SB)
+
+poly1305_auth_armv6_noblocks:
+ ADD $136, R13, R0
+ MOVW R5, R1
+ MOVW R6, R2
+ MOVW R4, R3
+
+ MOVW R0, R5
+ MOVW R1, R6
+ MOVW R2, R7
+ MOVW R3, R8
+ AND.S R2, R2, R2
+ BEQ poly1305_finish_ext_armv6_noremaining
+ EOR R0, R0
+ ADD $8, R13, R9 // 8 = offset to 16 byte scratch space
+ MOVW R0, (R9)
+ MOVW R0, 4(R9)
+ MOVW R0, 8(R9)
+ MOVW R0, 12(R9)
+ WORD $0xe3110003 // TST R1, #3 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_aligned
+ WORD $0xe3120008 // TST R2, #8 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip8
+ MOVWP_UNALIGNED(R1, R9, g)
+ MOVWP_UNALIGNED(R1, R9, g)
+
+poly1305_finish_ext_armv6_skip8:
+ WORD $0xe3120004 // TST $4, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip4
+ MOVWP_UNALIGNED(R1, R9, g)
+
+poly1305_finish_ext_armv6_skip4:
+ WORD $0xe3120002 // TST $2, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip2
+ MOVHUP_UNALIGNED(R1, R9, g)
+ B poly1305_finish_ext_armv6_skip2
+
+poly1305_finish_ext_armv6_aligned:
+ WORD $0xe3120008 // TST R2, #8 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip8_aligned
+ MOVM.IA.W (R1), [g-R11]
+ MOVM.IA.W [g-R11], (R9)
+
+poly1305_finish_ext_armv6_skip8_aligned:
+ WORD $0xe3120004 // TST $4, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip4_aligned
+ MOVW.P 4(R1), g
+ MOVW.P g, 4(R9)
+
+poly1305_finish_ext_armv6_skip4_aligned:
+ WORD $0xe3120002 // TST $2, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip2
+ MOVHU.P 2(R1), g
+ MOVH.P g, 2(R9)
+
+poly1305_finish_ext_armv6_skip2:
+ WORD $0xe3120001 // TST $1, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip1
+ MOVBU.P 1(R1), g
+ MOVBU.P g, 1(R9)
+
+poly1305_finish_ext_armv6_skip1:
+ MOVW $1, R11
+ MOVBU R11, 0(R9)
+ MOVW R11, 56(R5)
+ MOVW R5, R0
+ ADD $8, R13, R1
+ MOVW $16, R2
+ BL poly1305_blocks_armv6<>(SB)
+
+poly1305_finish_ext_armv6_noremaining:
+ MOVW 20(R5), R0
+ MOVW 24(R5), R1
+ MOVW 28(R5), R2
+ MOVW 32(R5), R3
+ MOVW 36(R5), R4
+ MOVW R4>>26, R12
+ BIC $0xfc000000, R4, R4
+ ADD R12<<2, R12, R12
+ ADD R12, R0, R0
+ MOVW R0>>26, R12
+ BIC $0xfc000000, R0, R0
+ ADD R12, R1, R1
+ MOVW R1>>26, R12
+ BIC $0xfc000000, R1, R1
+ ADD R12, R2, R2
+ MOVW R2>>26, R12
+ BIC $0xfc000000, R2, R2
+ ADD R12, R3, R3
+ MOVW R3>>26, R12
+ BIC $0xfc000000, R3, R3
+ ADD R12, R4, R4
+ ADD $5, R0, R6
+ MOVW R6>>26, R12
+ BIC $0xfc000000, R6, R6
+ ADD R12, R1, R7
+ MOVW R7>>26, R12
+ BIC $0xfc000000, R7, R7
+ ADD R12, R2, g
+ MOVW g>>26, R12
+ BIC $0xfc000000, g, g
+ ADD R12, R3, R11
+ MOVW $-(1<<26), R12
+ ADD R11>>26, R12, R12
+ BIC $0xfc000000, R11, R11
+ ADD R12, R4, R9
+ MOVW R9>>31, R12
+ SUB $1, R12
+ AND R12, R6, R6
+ AND R12, R7, R7
+ AND R12, g, g
+ AND R12, R11, R11
+ AND R12, R9, R9
+ MVN R12, R12
+ AND R12, R0, R0
+ AND R12, R1, R1
+ AND R12, R2, R2
+ AND R12, R3, R3
+ AND R12, R4, R4
+ ORR R6, R0, R0
+ ORR R7, R1, R1
+ ORR g, R2, R2
+ ORR R11, R3, R3
+ ORR R9, R4, R4
+ ORR R1<<26, R0, R0
+ MOVW R1>>6, R1
+ ORR R2<<20, R1, R1
+ MOVW R2>>12, R2
+ ORR R3<<14, R2, R2
+ MOVW R3>>18, R3
+ ORR R4<<8, R3, R3
+ MOVW 40(R5), R6
+ MOVW 44(R5), R7
+ MOVW 48(R5), g
+ MOVW 52(R5), R11
+ ADD.S R6, R0, R0
+ ADC.S R7, R1, R1
+ ADC.S g, R2, R2
+ ADC.S R11, R3, R3
+ MOVM.IA [R0-R3], (R8)
+ MOVW R5, R12
+ EOR R0, R0, R0
+ EOR R1, R1, R1
+ EOR R2, R2, R2
+ EOR R3, R3, R3
+ EOR R4, R4, R4
+ EOR R5, R5, R5
+ EOR R6, R6, R6
+ EOR R7, R7, R7
+ MOVM.IA.W [R0-R7], (R12)
+ MOVM.IA [R0-R7], (R12)
+ MOVW 4(R13), g
+ RET
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
new file mode 100644
index 0000000000..b2805a5ca1
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
@@ -0,0 +1,141 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64,!arm gccgo appengine nacl
+
+package poly1305
+
+import "encoding/binary"
+
+// Sum generates an authenticator for msg using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
+ var (
+ h0, h1, h2, h3, h4 uint32 // the hash accumulators
+ r0, r1, r2, r3, r4 uint64 // the r part of the key
+ )
+
+ r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff)
+ r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03)
+ r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff)
+ r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff)
+ r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff)
+
+ R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
+
+ for len(msg) >= TagSize {
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24)
+
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
+
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
+
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
+
+ msg = msg[TagSize:]
+ }
+
+ if len(msg) > 0 {
+ var block [TagSize]byte
+ off := copy(block[:], msg)
+ block[off] = 0x01
+
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8)
+
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
+
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
+
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
+ }
+
+ // h %= p reduction
+ h2 += h1 >> 26
+ h1 &= 0x3ffffff
+ h3 += h2 >> 26
+ h2 &= 0x3ffffff
+ h4 += h3 >> 26
+ h3 &= 0x3ffffff
+ h0 += 5 * (h4 >> 26)
+ h4 &= 0x3ffffff
+ h1 += h0 >> 26
+ h0 &= 0x3ffffff
+
+ // h - p
+ t0 := h0 + 5
+ t1 := h1 + (t0 >> 26)
+ t2 := h2 + (t1 >> 26)
+ t3 := h3 + (t2 >> 26)
+ t4 := h4 + (t3 >> 26) - (1 << 26)
+ t0 &= 0x3ffffff
+ t1 &= 0x3ffffff
+ t2 &= 0x3ffffff
+ t3 &= 0x3ffffff
+
+ // select h if h < p else h - p
+ t_mask := (t4 >> 31) - 1
+ h_mask := ^t_mask
+ h0 = (h0 & h_mask) | (t0 & t_mask)
+ h1 = (h1 & h_mask) | (t1 & t_mask)
+ h2 = (h2 & h_mask) | (t2 & t_mask)
+ h3 = (h3 & h_mask) | (t3 & t_mask)
+ h4 = (h4 & h_mask) | (t4 & t_mask)
+
+ // h %= 2^128
+ h0 |= h1 << 26
+ h1 = ((h1 >> 6) | (h2 << 20))
+ h2 = ((h2 >> 12) | (h3 << 14))
+ h3 = ((h3 >> 18) | (h4 << 8))
+
+ // s: the s part of the key
+ // tag = (h + s) % (2^128)
+ t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:]))
+ h0 = uint32(t)
+ t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32)
+ h1 = uint32(t)
+ t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32)
+ h2 = uint32(t)
+ t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32)
+ h3 = uint32(t)
+
+ binary.LittleEndian.PutUint32(out[0:], h0)
+ binary.LittleEndian.PutUint32(out[4:], h1)
+ binary.LittleEndian.PutUint32(out[8:], h2)
+ binary.LittleEndian.PutUint32(out[12:], h3)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
index b1f0220781..42106f3f2c 100644
--- a/vendor/golang.org/x/crypto/ssh/certs.go
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -44,7 +44,9 @@ type Signature struct {
const CertTimeInfinity = 1<<64 - 1
// An Certificate represents an OpenSSH certificate as defined in
-// [PROTOCOL.certkeys]?rev=1.8.
+// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the
+// PublicKey interface, so it can be unmarshaled using
+// ParsePublicKey.
type Certificate struct {
Nonce []byte
Key PublicKey
@@ -340,10 +342,10 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis
// the signature of the certificate.
func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
if c.IsRevoked != nil && c.IsRevoked(cert) {
- return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial)
+ return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial)
}
- for opt, _ := range cert.CriticalOptions {
+ for opt := range cert.CriticalOptions {
// sourceAddressCriticalOption will be enforced by
// serverAuthenticate
if opt == sourceAddressCriticalOption {
diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go
index 195530ea0d..c0834c00df 100644
--- a/vendor/golang.org/x/crypto/ssh/channel.go
+++ b/vendor/golang.org/x/crypto/ssh/channel.go
@@ -205,32 +205,32 @@ type channel struct {
// writePacket sends a packet. If the packet is a channel close, it updates
// sentClose. This method takes the lock c.writeMu.
-func (c *channel) writePacket(packet []byte) error {
- c.writeMu.Lock()
- if c.sentClose {
- c.writeMu.Unlock()
+func (ch *channel) writePacket(packet []byte) error {
+ ch.writeMu.Lock()
+ if ch.sentClose {
+ ch.writeMu.Unlock()
return io.EOF
}
- c.sentClose = (packet[0] == msgChannelClose)
- err := c.mux.conn.writePacket(packet)
- c.writeMu.Unlock()
+ ch.sentClose = (packet[0] == msgChannelClose)
+ err := ch.mux.conn.writePacket(packet)
+ ch.writeMu.Unlock()
return err
}
-func (c *channel) sendMessage(msg interface{}) error {
+func (ch *channel) sendMessage(msg interface{}) error {
if debugMux {
- log.Printf("send(%d): %#v", c.mux.chanList.offset, msg)
+ log.Printf("send(%d): %#v", ch.mux.chanList.offset, msg)
}
p := Marshal(msg)
- binary.BigEndian.PutUint32(p[1:], c.remoteId)
- return c.writePacket(p)
+ binary.BigEndian.PutUint32(p[1:], ch.remoteId)
+ return ch.writePacket(p)
}
// WriteExtended writes data to a specific extended stream. These streams are
// used, for example, for stderr.
-func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) {
- if c.sentEOF {
+func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) {
+ if ch.sentEOF {
return 0, io.EOF
}
// 1 byte message type, 4 bytes remoteId, 4 bytes data length
@@ -241,16 +241,16 @@ func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err er
opCode = msgChannelExtendedData
}
- c.writeMu.Lock()
- packet := c.packetPool[extendedCode]
+ ch.writeMu.Lock()
+ packet := ch.packetPool[extendedCode]
// We don't remove the buffer from packetPool, so
// WriteExtended calls from different goroutines will be
// flagged as errors by the race detector.
- c.writeMu.Unlock()
+ ch.writeMu.Unlock()
for len(data) > 0 {
- space := min(c.maxRemotePayload, len(data))
- if space, err = c.remoteWin.reserve(space); err != nil {
+ space := min(ch.maxRemotePayload, len(data))
+ if space, err = ch.remoteWin.reserve(space); err != nil {
return n, err
}
if want := headerLength + space; uint32(cap(packet)) < want {
@@ -262,13 +262,13 @@ func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err er
todo := data[:space]
packet[0] = opCode
- binary.BigEndian.PutUint32(packet[1:], c.remoteId)
+ binary.BigEndian.PutUint32(packet[1:], ch.remoteId)
if extendedCode > 0 {
binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode))
}
binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo)))
copy(packet[headerLength:], todo)
- if err = c.writePacket(packet); err != nil {
+ if err = ch.writePacket(packet); err != nil {
return n, err
}
@@ -276,14 +276,14 @@ func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err er
data = data[len(todo):]
}
- c.writeMu.Lock()
- c.packetPool[extendedCode] = packet
- c.writeMu.Unlock()
+ ch.writeMu.Lock()
+ ch.packetPool[extendedCode] = packet
+ ch.writeMu.Unlock()
return n, err
}
-func (c *channel) handleData(packet []byte) error {
+func (ch *channel) handleData(packet []byte) error {
headerLen := 9
isExtendedData := packet[0] == msgChannelExtendedData
if isExtendedData {
@@ -303,7 +303,7 @@ func (c *channel) handleData(packet []byte) error {
if length == 0 {
return nil
}
- if length > c.maxIncomingPayload {
+ if length > ch.maxIncomingPayload {
// TODO(hanwen): should send Disconnect?
return errors.New("ssh: incoming packet exceeds maximum payload size")
}
@@ -313,21 +313,21 @@ func (c *channel) handleData(packet []byte) error {
return errors.New("ssh: wrong packet length")
}
- c.windowMu.Lock()
- if c.myWindow < length {
- c.windowMu.Unlock()
+ ch.windowMu.Lock()
+ if ch.myWindow < length {
+ ch.windowMu.Unlock()
// TODO(hanwen): should send Disconnect with reason?
return errors.New("ssh: remote side wrote too much")
}
- c.myWindow -= length
- c.windowMu.Unlock()
+ ch.myWindow -= length
+ ch.windowMu.Unlock()
if extended == 1 {
- c.extPending.write(data)
+ ch.extPending.write(data)
} else if extended > 0 {
// discard other extended data.
} else {
- c.pending.write(data)
+ ch.pending.write(data)
}
return nil
}
@@ -384,31 +384,31 @@ func (c *channel) close() {
// responseMessageReceived is called when a success or failure message is
// received on a channel to check that such a message is reasonable for the
// given channel.
-func (c *channel) responseMessageReceived() error {
- if c.direction == channelInbound {
+func (ch *channel) responseMessageReceived() error {
+ if ch.direction == channelInbound {
return errors.New("ssh: channel response message received on inbound channel")
}
- if c.decided {
+ if ch.decided {
return errors.New("ssh: duplicate response received for channel")
}
- c.decided = true
+ ch.decided = true
return nil
}
-func (c *channel) handlePacket(packet []byte) error {
+func (ch *channel) handlePacket(packet []byte) error {
switch packet[0] {
case msgChannelData, msgChannelExtendedData:
- return c.handleData(packet)
+ return ch.handleData(packet)
case msgChannelClose:
- c.sendMessage(channelCloseMsg{PeersId: c.remoteId})
- c.mux.chanList.remove(c.localId)
- c.close()
+ ch.sendMessage(channelCloseMsg{PeersID: ch.remoteId})
+ ch.mux.chanList.remove(ch.localId)
+ ch.close()
return nil
case msgChannelEOF:
// RFC 4254 is mute on how EOF affects dataExt messages but
// it is logical to signal EOF at the same time.
- c.extPending.eof()
- c.pending.eof()
+ ch.extPending.eof()
+ ch.pending.eof()
return nil
}
@@ -419,24 +419,24 @@ func (c *channel) handlePacket(packet []byte) error {
switch msg := decoded.(type) {
case *channelOpenFailureMsg:
- if err := c.responseMessageReceived(); err != nil {
+ if err := ch.responseMessageReceived(); err != nil {
return err
}
- c.mux.chanList.remove(msg.PeersId)
- c.msg <- msg
+ ch.mux.chanList.remove(msg.PeersID)
+ ch.msg <- msg
case *channelOpenConfirmMsg:
- if err := c.responseMessageReceived(); err != nil {
+ if err := ch.responseMessageReceived(); err != nil {
return err
}
if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize)
}
- c.remoteId = msg.MyId
- c.maxRemotePayload = msg.MaxPacketSize
- c.remoteWin.add(msg.MyWindow)
- c.msg <- msg
+ ch.remoteId = msg.MyID
+ ch.maxRemotePayload = msg.MaxPacketSize
+ ch.remoteWin.add(msg.MyWindow)
+ ch.msg <- msg
case *windowAdjustMsg:
- if !c.remoteWin.add(msg.AdditionalBytes) {
+ if !ch.remoteWin.add(msg.AdditionalBytes) {
return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes)
}
case *channelRequestMsg:
@@ -444,12 +444,12 @@ func (c *channel) handlePacket(packet []byte) error {
Type: msg.Request,
WantReply: msg.WantReply,
Payload: msg.RequestSpecificData,
- ch: c,
+ ch: ch,
}
- c.incomingRequests <- &req
+ ch.incomingRequests <- &req
default:
- c.msg <- msg
+ ch.msg <- msg
}
return nil
}
@@ -488,23 +488,23 @@ func (e *extChannel) Read(data []byte) (n int, err error) {
return e.ch.ReadExtended(data, e.code)
}
-func (c *channel) Accept() (Channel, <-chan *Request, error) {
- if c.decided {
+func (ch *channel) Accept() (Channel, <-chan *Request, error) {
+ if ch.decided {
return nil, nil, errDecidedAlready
}
- c.maxIncomingPayload = channelMaxPacket
+ ch.maxIncomingPayload = channelMaxPacket
confirm := channelOpenConfirmMsg{
- PeersId: c.remoteId,
- MyId: c.localId,
- MyWindow: c.myWindow,
- MaxPacketSize: c.maxIncomingPayload,
+ PeersID: ch.remoteId,
+ MyID: ch.localId,
+ MyWindow: ch.myWindow,
+ MaxPacketSize: ch.maxIncomingPayload,
}
- c.decided = true
- if err := c.sendMessage(confirm); err != nil {
+ ch.decided = true
+ if err := ch.sendMessage(confirm); err != nil {
return nil, nil, err
}
- return c, c.incomingRequests, nil
+ return ch, ch.incomingRequests, nil
}
func (ch *channel) Reject(reason RejectionReason, message string) error {
@@ -512,7 +512,7 @@ func (ch *channel) Reject(reason RejectionReason, message string) error {
return errDecidedAlready
}
reject := channelOpenFailureMsg{
- PeersId: ch.remoteId,
+ PeersID: ch.remoteId,
Reason: reason,
Message: message,
Language: "en",
@@ -541,7 +541,7 @@ func (ch *channel) CloseWrite() error {
}
ch.sentEOF = true
return ch.sendMessage(channelEOFMsg{
- PeersId: ch.remoteId})
+ PeersID: ch.remoteId})
}
func (ch *channel) Close() error {
@@ -550,7 +550,7 @@ func (ch *channel) Close() error {
}
return ch.sendMessage(channelCloseMsg{
- PeersId: ch.remoteId})
+ PeersID: ch.remoteId})
}
// Extended returns an io.ReadWriter that sends and receives data on the given,
@@ -577,7 +577,7 @@ func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (boo
}
msg := channelRequestMsg{
- PeersId: ch.remoteId,
+ PeersID: ch.remoteId,
Request: name,
WantReply: wantReply,
RequestSpecificData: payload,
@@ -614,11 +614,11 @@ func (ch *channel) ackRequest(ok bool) error {
var msg interface{}
if !ok {
msg = channelRequestFailureMsg{
- PeersId: ch.remoteId,
+ PeersID: ch.remoteId,
}
} else {
msg = channelRequestSuccessMsg{
- PeersId: ch.remoteId,
+ PeersID: ch.remoteId,
}
}
return ch.sendMessage(msg)
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
index aed2b1f017..30a49fdf27 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -16,6 +16,9 @@ import (
"hash"
"io"
"io/ioutil"
+
+ "golang.org/x/crypto/internal/chacha20"
+ "golang.org/x/crypto/poly1305"
)
const (
@@ -53,78 +56,78 @@ func newRC4(key, iv []byte) (cipher.Stream, error) {
return rc4.NewCipher(key)
}
-type streamCipherMode struct {
- keySize int
- ivSize int
- skip int
- createFunc func(key, iv []byte) (cipher.Stream, error)
+type cipherMode struct {
+ keySize int
+ ivSize int
+ create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error)
}
-func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) {
- if len(key) < c.keySize {
- panic("ssh: key length too small for cipher")
- }
- if len(iv) < c.ivSize {
- panic("ssh: iv too small for cipher")
- }
-
- stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize])
- if err != nil {
- return nil, err
- }
+func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ stream, err := createFunc(key, iv)
+ if err != nil {
+ return nil, err
+ }
- var streamDump []byte
- if c.skip > 0 {
- streamDump = make([]byte, 512)
- }
+ var streamDump []byte
+ if skip > 0 {
+ streamDump = make([]byte, 512)
+ }
- for remainingToDump := c.skip; remainingToDump > 0; {
- dumpThisTime := remainingToDump
- if dumpThisTime > len(streamDump) {
- dumpThisTime = len(streamDump)
+ for remainingToDump := skip; remainingToDump > 0; {
+ dumpThisTime := remainingToDump
+ if dumpThisTime > len(streamDump) {
+ dumpThisTime = len(streamDump)
+ }
+ stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
+ remainingToDump -= dumpThisTime
}
- stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
- remainingToDump -= dumpThisTime
- }
- return stream, nil
+ 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
// are not supported and will not be negotiated, even if explicitly requested in
// ClientConfig.Crypto.Ciphers.
-var cipherModes = map[string]*streamCipherMode{
+var cipherModes = map[string]*cipherMode{
// Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
// are defined in the order specified in the RFC.
- "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
- "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
- "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
+ "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
+ "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
+ "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
// Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
// They are defined in the order specified in the RFC.
- "arcfour128": {16, 0, 1536, newRC4},
- "arcfour256": {32, 0, 1536, newRC4},
+ "arcfour128": {16, 0, streamCipherMode(1536, newRC4)},
+ "arcfour256": {32, 0, streamCipherMode(1536, newRC4)},
// 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
// RC4) has problems with weak keys, and should be used with caution."
// 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
- // special case. If we add any more non-stream ciphers, we
- // should invest a cleaner way to do this.
- gcmCipherID: {16, 12, 0, nil},
+ // AEAD ciphers
+ gcmCipherID: {16, 12, newGCMCipher},
+ chacha20Poly1305ID: {64, 0, newChaCha20Cipher},
// 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
// needed, it's possible to specify a custom Config to enable it.
// You should expect that an active attacker can recover plaintext if
// you do.
- aes128cbcID: {16, aes.BlockSize, 0, nil},
+ aes128cbcID: {16, aes.BlockSize, newAESCBCCipher},
- // 3des-cbc is insecure and is disabled by default.
- tripledescbcID: {24, des.BlockSize, 0, nil},
+ // 3des-cbc is insecure and is not included in the default
+ // config.
+ tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher},
}
// prefixLen is the length of the packet prefix that contains the packet length
@@ -304,7 +307,7 @@ type gcmCipher struct {
buf []byte
}
-func newGCMCipher(iv, key []byte) (packetCipher, error) {
+func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
c, err := aes.NewCipher(key)
if err != nil {
return nil, err
@@ -372,7 +375,7 @@ func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
}
length := binary.BigEndian.Uint32(c.prefix[:])
if length > maxPacket {
- return nil, errors.New("ssh: max packet length exceeded.")
+ return nil, errors.New("ssh: max packet length exceeded")
}
if cap(c.buf) < int(length+gcmTagSize) {
@@ -422,7 +425,7 @@ type cbcCipher struct {
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{
mac: macModes[algs.MAC].new(macKey),
decrypter: cipher.NewCBCDecrypter(c, iv),
@@ -436,13 +439,13 @@ func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorith
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)
if err != nil {
return nil, err
}
- cbc, err := newCBCCipher(c, iv, key, macKey, algs)
+ cbc, err := newCBCCipher(c, key, iv, macKey, algs)
if err != nil {
return nil, err
}
@@ -450,13 +453,13 @@ func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCi
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)
if err != nil {
return nil, err
}
- cbc, err := newCBCCipher(c, iv, key, macKey, algs)
+ cbc, err := newCBCCipher(c, key, iv, macKey, algs)
if err != nil {
return nil, err
}
@@ -548,11 +551,11 @@ func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error)
c.packetData = c.packetData[:entirePacketSize]
}
- if n, err := io.ReadFull(r, c.packetData[firstBlockLength:]); err != nil {
+ n, err := io.ReadFull(r, c.packetData[firstBlockLength:])
+ if err != nil {
return nil, err
- } else {
- c.oracleCamouflage -= uint32(n)
}
+ c.oracleCamouflage -= uint32(n)
remainingCrypted := c.packetData[firstBlockLength:macStart]
c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted)
@@ -627,3 +630,142 @@ func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, pack
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
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
index a1252cb9be..5f44b77403 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -11,6 +11,14 @@ import (
"io"
)
+type authResult int
+
+const (
+ authFailure authResult = iota
+ authPartialSuccess
+ authSuccess
+)
+
// clientAuthenticate authenticates with the remote server. See RFC 4252.
func (c *connection) clientAuthenticate(config *ClientConfig) error {
// initiate user auth session
@@ -37,11 +45,12 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
if err != nil {
return err
}
- if ok {
+ if ok == authSuccess {
// success
return nil
+ } else if ok == authFailure {
+ tried[auth.method()] = true
}
- tried[auth.method()] = true
if methods == nil {
methods = lastMethods
}
@@ -82,7 +91,7 @@ type AuthMethod interface {
// If authentication is not successful, a []string of alternative
// method names is returned. If the slice is nil, it will be ignored
// and the previous set of possible methods will be reused.
- auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)
+ auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error)
// method returns the RFC 4252 method name.
method() string
@@ -91,13 +100,13 @@ type AuthMethod interface {
// "none" authentication, RFC 4252 section 5.2.
type noneAuth int
-func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
if err := c.writePacket(Marshal(&userAuthRequestMsg{
User: user,
Service: serviceSSH,
Method: "none",
})); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
return handleAuthResponse(c)
@@ -111,7 +120,7 @@ func (n *noneAuth) method() string {
// a function call, e.g. by prompting the user.
type passwordCallback func() (password string, err error)
-func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
type passwordAuthMsg struct {
User string `sshtype:"50"`
Service string
@@ -125,7 +134,7 @@ func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand
// The program may only find out that the user doesn't have a password
// when prompting.
if err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
if err := c.writePacket(Marshal(&passwordAuthMsg{
@@ -135,7 +144,7 @@ func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand
Reply: false,
Password: pw,
})); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
return handleAuthResponse(c)
@@ -178,7 +187,7 @@ func (cb publicKeyCallback) method() string {
return "publickey"
}
-func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
// Authentication is performed by sending an enquiry to test if a key is
// acceptable to the remote. If the key is acceptable, the client will
// attempt to authenticate with the valid key. If not the client will repeat
@@ -186,13 +195,13 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
signers, err := cb()
if err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
var methods []string
for _, signer := range signers {
ok, err := validateKey(signer.PublicKey(), user, c)
if err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
if !ok {
continue
@@ -206,7 +215,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
Method: cb.method(),
}, []byte(pub.Type()), pubKey))
if err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
// manually wrap the serialized signature in a string
@@ -224,24 +233,24 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
}
p := Marshal(&msg)
if err := c.writePacket(p); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
- var success bool
+ var success authResult
success, methods, err = handleAuthResponse(c)
if err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
// If authentication succeeds or the list of available methods does not
// contain the "publickey" method, do not attempt to authenticate with any
// other keys. According to RFC 4252 Section 7, the latter can occur when
// additional authentication methods are required.
- if success || !containsMethod(methods, cb.method()) {
+ if success == authSuccess || !containsMethod(methods, cb.method()) {
return success, methods, err
}
}
- return false, methods, nil
+ return authFailure, methods, nil
}
func containsMethod(methods []string, method string) bool {
@@ -318,28 +327,31 @@ func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMet
// handleAuthResponse returns whether the preceding authentication request succeeded
// along with a list of remaining authentication methods to try next and
// an error if an unexpected response was received.
-func handleAuthResponse(c packetConn) (bool, []string, error) {
+func handleAuthResponse(c packetConn) (authResult, []string, error) {
for {
packet, err := c.readPacket()
if err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
switch packet[0] {
case msgUserAuthBanner:
if err := handleBannerResponse(c, packet); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
case msgUserAuthFailure:
var msg userAuthFailureMsg
if err := Unmarshal(packet, &msg); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
- return false, msg.Methods, nil
+ if msg.PartialSuccess {
+ return authPartialSuccess, msg.Methods, nil
+ }
+ return authFailure, msg.Methods, nil
case msgUserAuthSuccess:
- return true, nil, nil
+ return authSuccess, nil, nil
default:
- return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+ return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
}
}
}
@@ -381,7 +393,7 @@ func (cb KeyboardInteractiveChallenge) method() string {
return "keyboard-interactive"
}
-func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
type initiateMsg struct {
User string `sshtype:"50"`
Service string
@@ -395,20 +407,20 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
Service: serviceSSH,
Method: "keyboard-interactive",
})); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
for {
packet, err := c.readPacket()
if err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
// like handleAuthResponse, but with less options.
switch packet[0] {
case msgUserAuthBanner:
if err := handleBannerResponse(c, packet); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
continue
case msgUserAuthInfoRequest:
@@ -416,18 +428,21 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
case msgUserAuthFailure:
var msg userAuthFailureMsg
if err := Unmarshal(packet, &msg); err != nil {
- return false, nil, err
+ return authFailure, nil, err
+ }
+ if msg.PartialSuccess {
+ return authPartialSuccess, msg.Methods, nil
}
- return false, msg.Methods, nil
+ return authFailure, msg.Methods, nil
case msgUserAuthSuccess:
- return true, nil, nil
+ return authSuccess, nil, nil
default:
- return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
+ return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
}
var msg userAuthInfoRequestMsg
if err := Unmarshal(packet, &msg); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
// Manually unpack the prompt/echo pairs.
@@ -437,7 +452,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
for i := 0; i < int(msg.NumPrompts); i++ {
prompt, r, ok := parseString(rest)
if !ok || len(r) == 0 {
- return false, nil, errors.New("ssh: prompt format error")
+ return authFailure, nil, errors.New("ssh: prompt format error")
}
prompts = append(prompts, string(prompt))
echos = append(echos, r[0] != 0)
@@ -445,16 +460,16 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
}
if len(rest) != 0 {
- return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
+ return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
}
answers, err := cb(msg.User, msg.Instruction, prompts, echos)
if err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
if len(answers) != len(prompts) {
- return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
+ return authFailure, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
}
responseLength := 1 + 4
for _, a := range answers {
@@ -470,7 +485,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe
}
if err := c.writePacket(serialized); err != nil {
- return false, nil, err
+ return authFailure, nil, err
}
}
}
@@ -480,10 +495,10 @@ type retryableAuthMethod struct {
maxTries int
}
-func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) {
+func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) {
for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
ok, methods, err = r.authMethod.auth(session, user, c, rand)
- if ok || err != nil { // either success or error terminate
+ if ok != authFailure || err != nil { // either success, partial success or error terminate
return ok, methods, err
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
index dc39e4d231..04f3620b3d 100644
--- a/vendor/golang.org/x/crypto/ssh/common.go
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -24,11 +24,21 @@ const (
serviceSSH = "ssh-connection"
)
-// supportedCiphers specifies the supported ciphers in preference order.
+// supportedCiphers lists ciphers we support but might not recommend.
var supportedCiphers = []string{
"aes128-ctr", "aes192-ctr", "aes256-ctr",
"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
@@ -211,7 +221,7 @@ func (c *Config) SetDefaults() {
c.Rand = rand.Reader
}
if c.Ciphers == nil {
- c.Ciphers = supportedCiphers
+ c.Ciphers = preferredCiphers
}
var ciphers []string
for _, c := range c.Ciphers {
@@ -242,7 +252,7 @@ func (c *Config) SetDefaults() {
// buildDataSignedForAuth returns the data that is signed in order to prove
// possession of a private key. See RFC 4252, section 7.
-func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
+func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
data := struct {
Session []byte
Type byte
@@ -253,7 +263,7 @@ func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubK
Algo []byte
PubKey []byte
}{
- sessionId,
+ sessionID,
msgUserAuthRequest,
req.User,
req.Service,
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
index f91c2770ed..f34bcc0133 100644
--- a/vendor/golang.org/x/crypto/ssh/kex.go
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -119,7 +119,7 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha
return nil, err
}
- kInt, err := group.diffieHellman(kexDHReply.Y, x)
+ ki, err := group.diffieHellman(kexDHReply.Y, x)
if err != nil {
return nil, err
}
@@ -129,8 +129,8 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha
writeString(h, kexDHReply.HostKey)
writeInt(h, X)
writeInt(h, kexDHReply.Y)
- K := make([]byte, intLength(kInt))
- marshalInt(K, kInt)
+ K := make([]byte, intLength(ki))
+ marshalInt(K, ki)
h.Write(K)
return &kexResult{
@@ -164,7 +164,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
}
Y := new(big.Int).Exp(group.g, y, group.p)
- kInt, err := group.diffieHellman(kexDHInit.X, y)
+ ki, err := group.diffieHellman(kexDHInit.X, y)
if err != nil {
return nil, err
}
@@ -177,8 +177,8 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
writeInt(h, kexDHInit.X)
writeInt(h, Y)
- K := make([]byte, intLength(kInt))
- marshalInt(K, kInt)
+ K := make([]byte, intLength(ki))
+ marshalInt(K, ki)
h.Write(K)
H := h.Sum(nil)
@@ -462,9 +462,9 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh
writeString(h, kp.pub[:])
writeString(h, reply.EphemeralPubKey)
- kInt := new(big.Int).SetBytes(secret[:])
- K := make([]byte, intLength(kInt))
- marshalInt(K, kInt)
+ ki := new(big.Int).SetBytes(secret[:])
+ K := make([]byte, intLength(ki))
+ marshalInt(K, ki)
h.Write(K)
return &kexResult{
@@ -510,9 +510,9 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
writeString(h, kexInit.ClientPubKey)
writeString(h, kp.pub[:])
- kInt := new(big.Int).SetBytes(secret[:])
- K := make([]byte, intLength(kInt))
- marshalInt(K, kInt)
+ ki := new(big.Int).SetBytes(secret[:])
+ K := make([]byte, intLength(ki))
+ marshalInt(K, ki)
h.Write(K)
H := h.Sum(nil)
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
index b682c1741b..73697deda6 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -276,7 +276,8 @@ type PublicKey interface {
Type() string
// Marshal returns the serialized key data in SSH wire format,
- // with the name prefix.
+ // with the name prefix. To unmarshal the returned data, use
+ // the ParsePublicKey function.
Marshal() []byte
// Verify that sig is a signature on the given data using this
@@ -363,7 +364,7 @@ func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
type dsaPublicKey dsa.PublicKey
-func (r *dsaPublicKey) Type() string {
+func (k *dsaPublicKey) Type() string {
return "ssh-dss"
}
@@ -481,12 +482,12 @@ func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
type ecdsaPublicKey ecdsa.PublicKey
-func (key *ecdsaPublicKey) Type() string {
- return "ecdsa-sha2-" + key.nistID()
+func (k *ecdsaPublicKey) Type() string {
+ return "ecdsa-sha2-" + k.nistID()
}
-func (key *ecdsaPublicKey) nistID() string {
- switch key.Params().BitSize {
+func (k *ecdsaPublicKey) nistID() string {
+ switch k.Params().BitSize {
case 256:
return "nistp256"
case 384:
@@ -499,7 +500,7 @@ func (key *ecdsaPublicKey) nistID() string {
type ed25519PublicKey ed25519.PublicKey
-func (key ed25519PublicKey) Type() string {
+func (k ed25519PublicKey) Type() string {
return KeyAlgoED25519
}
@@ -518,23 +519,23 @@ func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
return (ed25519PublicKey)(key), w.Rest, nil
}
-func (key ed25519PublicKey) Marshal() []byte {
+func (k ed25519PublicKey) Marshal() []byte {
w := struct {
Name string
KeyBytes []byte
}{
KeyAlgoED25519,
- []byte(key),
+ []byte(k),
}
return Marshal(&w)
}
-func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error {
- if sig.Format != key.Type() {
- return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
+func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error {
+ if sig.Format != k.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
- edKey := (ed25519.PublicKey)(key)
+ edKey := (ed25519.PublicKey)(k)
if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
return errors.New("ssh: signature did not verify")
}
@@ -595,9 +596,9 @@ func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
return (*ecdsaPublicKey)(key), w.Rest, nil
}
-func (key *ecdsaPublicKey) Marshal() []byte {
+func (k *ecdsaPublicKey) Marshal() []byte {
// See RFC 5656, section 3.1.
- keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
+ keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
// ECDSA publickey struct layout should match the struct used by
// parseECDSACert in the x/crypto/ssh/agent package.
w := struct {
@@ -605,20 +606,20 @@ func (key *ecdsaPublicKey) Marshal() []byte {
ID string
Key []byte
}{
- key.Type(),
- key.nistID(),
+ k.Type(),
+ k.nistID(),
keyBytes,
}
return Marshal(&w)
}
-func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
- if sig.Format != key.Type() {
- return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
+func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != k.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
- h := ecHash(key.Curve).New()
+ h := ecHash(k.Curve).New()
h.Write(data)
digest := h.Sum(nil)
@@ -635,7 +636,7 @@ func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
return err
}
- if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
+ if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) {
return nil
}
return errors.New("ssh: signature did not verify")
@@ -758,7 +759,7 @@ func NewPublicKey(key interface{}) (PublicKey, error) {
return (*rsaPublicKey)(key), nil
case *ecdsa.PublicKey:
if !supportedEllipticCurve(key.Curve) {
- return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.")
+ return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported")
}
return (*ecdsaPublicKey)(key), nil
case *dsa.PublicKey:
diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go
index c96e1bec59..08d2811730 100644
--- a/vendor/golang.org/x/crypto/ssh/messages.go
+++ b/vendor/golang.org/x/crypto/ssh/messages.go
@@ -162,7 +162,7 @@ const msgChannelOpen = 90
type channelOpenMsg struct {
ChanType string `sshtype:"90"`
- PeersId uint32
+ PeersID uint32
PeersWindow uint32
MaxPacketSize uint32
TypeSpecificData []byte `ssh:"rest"`
@@ -173,7 +173,7 @@ const msgChannelData = 94
// Used for debug print outs of packets.
type channelDataMsg struct {
- PeersId uint32 `sshtype:"94"`
+ PeersID uint32 `sshtype:"94"`
Length uint32
Rest []byte `ssh:"rest"`
}
@@ -182,8 +182,8 @@ type channelDataMsg struct {
const msgChannelOpenConfirm = 91
type channelOpenConfirmMsg struct {
- PeersId uint32 `sshtype:"91"`
- MyId uint32
+ PeersID uint32 `sshtype:"91"`
+ MyID uint32
MyWindow uint32
MaxPacketSize uint32
TypeSpecificData []byte `ssh:"rest"`
@@ -193,7 +193,7 @@ type channelOpenConfirmMsg struct {
const msgChannelOpenFailure = 92
type channelOpenFailureMsg struct {
- PeersId uint32 `sshtype:"92"`
+ PeersID uint32 `sshtype:"92"`
Reason RejectionReason
Message string
Language string
@@ -202,7 +202,7 @@ type channelOpenFailureMsg struct {
const msgChannelRequest = 98
type channelRequestMsg struct {
- PeersId uint32 `sshtype:"98"`
+ PeersID uint32 `sshtype:"98"`
Request string
WantReply bool
RequestSpecificData []byte `ssh:"rest"`
@@ -212,28 +212,28 @@ type channelRequestMsg struct {
const msgChannelSuccess = 99
type channelRequestSuccessMsg struct {
- PeersId uint32 `sshtype:"99"`
+ PeersID uint32 `sshtype:"99"`
}
// See RFC 4254, section 5.4.
const msgChannelFailure = 100
type channelRequestFailureMsg struct {
- PeersId uint32 `sshtype:"100"`
+ PeersID uint32 `sshtype:"100"`
}
// See RFC 4254, section 5.3
const msgChannelClose = 97
type channelCloseMsg struct {
- PeersId uint32 `sshtype:"97"`
+ PeersID uint32 `sshtype:"97"`
}
// See RFC 4254, section 5.3
const msgChannelEOF = 96
type channelEOFMsg struct {
- PeersId uint32 `sshtype:"96"`
+ PeersID uint32 `sshtype:"96"`
}
// See RFC 4254, section 4
@@ -263,7 +263,7 @@ type globalRequestFailureMsg struct {
const msgChannelWindowAdjust = 93
type windowAdjustMsg struct {
- PeersId uint32 `sshtype:"93"`
+ PeersID uint32 `sshtype:"93"`
AdditionalBytes uint32
}
diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go
index 27a527c106..f19016270e 100644
--- a/vendor/golang.org/x/crypto/ssh/mux.go
+++ b/vendor/golang.org/x/crypto/ssh/mux.go
@@ -278,7 +278,7 @@ func (m *mux) handleChannelOpen(packet []byte) error {
if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
failMsg := channelOpenFailureMsg{
- PeersId: msg.PeersId,
+ PeersID: msg.PeersID,
Reason: ConnectionFailed,
Message: "invalid request",
Language: "en_US.UTF-8",
@@ -287,7 +287,7 @@ func (m *mux) handleChannelOpen(packet []byte) error {
}
c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData)
- c.remoteId = msg.PeersId
+ c.remoteId = msg.PeersID
c.maxRemotePayload = msg.MaxPacketSize
c.remoteWin.add(msg.PeersWindow)
m.incomingChannels <- c
@@ -313,7 +313,7 @@ func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {
PeersWindow: ch.myWindow,
MaxPacketSize: ch.maxIncomingPayload,
TypeSpecificData: extra,
- PeersId: ch.localId,
+ PeersID: ch.localId,
}
if err := m.sendMessage(open); err != nil {
return nil, err
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 148d2cb245..d0f4825319 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -166,6 +166,9 @@ type ServerConn struct {
// unsuccessful, it closes the connection and returns an error. The
// Request and NewChannel channels must be serviced, or the connection
// will hang.
+//
+// The returned error may be of type *ServerAuthError for
+// authentication errors.
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
fullConf := *config
fullConf.SetDefaults()
@@ -256,7 +259,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
func isAcceptableAlgo(algo string) bool {
switch algo {
case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
- CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
+ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
return true
}
return false
@@ -292,12 +295,13 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
}
-// ServerAuthError implements the error interface. It appends any authentication
-// errors that may occur, and is returned if all of the authentication methods
-// provided by the user failed to authenticate.
+// ServerAuthError represents server authentication errors and is
+// sometimes returned by NewServerConn. It appends any authentication
+// errors that may occur, and is returned if all of the authentication
+// methods provided by the user failed to authenticate.
type ServerAuthError struct {
// Errors contains authentication errors returned by the authentication
- // callback methods.
+ // callback methods. The first entry is typically ErrNoAuth.
Errors []error
}
@@ -309,6 +313,13 @@ func (l ServerAuthError) Error() string {
return "[" + strings.Join(errs, ", ") + "]"
}
+// ErrNoAuth is the error value returned if no
+// authentication method has been passed yet. This happens as a normal
+// part of the authentication loop, since the client first tries
+// 'none' authentication to discover available methods.
+// It is returned in ServerAuthError.Errors from NewServerConn.
+var ErrNoAuth = errors.New("ssh: no auth passed yet")
+
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
sessionID := s.transport.getSessionID()
var cache pubKeyCache
@@ -316,6 +327,7 @@ func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, err
authFailures := 0
var authErrs []error
+ var displayedBanner bool
userAuthLoop:
for {
@@ -348,7 +360,8 @@ userAuthLoop:
s.user = userAuthReq.User
- if authFailures == 0 && config.BannerCallback != nil {
+ if !displayedBanner && config.BannerCallback != nil {
+ displayedBanner = true
msg := config.BannerCallback(s)
if msg != "" {
bannerMsg := &userAuthBannerMsg{
@@ -361,7 +374,7 @@ userAuthLoop:
}
perms = nil
- authErr := errors.New("no auth passed yet")
+ authErr := ErrNoAuth
switch userAuthReq.Method {
case "none":
diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go
index cc06e03f5c..d3321f6b78 100644
--- a/vendor/golang.org/x/crypto/ssh/session.go
+++ b/vendor/golang.org/x/crypto/ssh/session.go
@@ -406,7 +406,7 @@ func (s *Session) Wait() error {
s.stdinPipeWriter.Close()
}
var copyError error
- for _ = range s.copyFuncs {
+ for range s.copyFuncs {
if err := <-s.errors; err != nil && copyError == nil {
copyError = err
}
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
index ab2b88765a..f6fae1db46 100644
--- a/vendor/golang.org/x/crypto/ssh/transport.go
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -6,6 +6,7 @@ package ssh
import (
"bufio"
+ "bytes"
"errors"
"io"
"log"
@@ -76,17 +77,17 @@ type connectionState struct {
// both directions are triggered by reading and writing a msgNewKey packet
// respectively.
func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error {
- if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil {
+ ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult)
+ if err != nil {
return err
- } else {
- t.reader.pendingKeyChange <- ciph
}
+ t.reader.pendingKeyChange <- ciph
- if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil {
+ ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult)
+ if err != nil {
return err
- } else {
- t.writer.pendingKeyChange <- ciph
}
+ t.writer.pendingKeyChange <- ciph
return nil
}
@@ -139,7 +140,7 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
case cipher := <-s.pendingKeyChange:
s.packetCipher = cipher
default:
- return nil, errors.New("ssh: got bogus newkeys message.")
+ return nil, errors.New("ssh: got bogus newkeys message")
}
case msgDisconnect:
@@ -232,52 +233,22 @@ var (
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) {
+// 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
+// (to setup server->client keys) or clientKeys (for client->server keys).
+func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
cipherMode := cipherModes[algs.Cipher]
macMode := macModes[algs.MAC]
- iv = make([]byte, cipherMode.ivSize)
- key = make([]byte, cipherMode.keySize)
- macKey = make([]byte, macMode.keySize)
+ 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
-// described in RFC 4253, section 6.4. direction should either be serverKeys
-// (to setup server->client keys) or clientKeys (for client->server keys).
-func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
- iv, key, macKey := generateKeys(d, algs, kex)
-
- if algs.Cipher == gcmCipherID {
- return newGCMCipher(iv, key)
- }
-
- if algs.Cipher == aes128cbcID {
- return newAESCBCCipher(iv, key, macKey, algs)
- }
-
- if algs.Cipher == tripledescbcID {
- 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
+ return cipherModes[algs.Cipher].create(key, iv, macKey, algs)
}
// 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 buf [1]byte
- for len(versionString) < maxVersionStringBytes {
+ for length := 0; length < maxVersionStringBytes; length++ {
_, err := io.ReadFull(r, buf[:])
if err != nil {
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
// but several SSH servers actually only send a \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
break
}