downgrade cypto lib
This commit is contained in:
parent
aa3fccbe3c
commit
2771df70ae
4
Gopkg.lock
generated
4
Gopkg.lock
generated
|
|
@ -744,7 +744,7 @@
|
||||||
"poly1305",
|
"poly1305",
|
||||||
"ssh"
|
"ssh"
|
||||||
]
|
]
|
||||||
revision = "8ac0e0d97ce45cd83d1d7243c060cb8461dda5e9"
|
revision = "12dd70caea0268ac0d6c2707d0611ef601e7c64e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
|
|
@ -877,6 +877,6 @@
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "801b56b8fc5ac5bb05f2526ad196f82892e7cee82e0e6a56e6b1a4840d028805"
|
inputs-digest = "55985dd30c146a67f26c28177e140cf6fe4d02bcb5f40f82be75748540d56dc6"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ ignored = ["google.golang.org/appengine*"]
|
||||||
name = "code.gitea.io/sdk"
|
name = "code.gitea.io/sdk"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
revision = "8ac0e0d97ce45cd83d1d7243c060cb8461dda5e9"
|
revision = "12dd70caea0268ac0d6c2707d0611ef601e7c64e"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
|
|
|
||||||
418
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
418
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
|
|
@ -14,6 +14,7 @@
|
||||||
package acme
|
package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
|
@ -22,8 +23,6 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/asn1"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
@ -34,6 +33,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -42,9 +42,6 @@ import (
|
||||||
// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
|
// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA.
|
||||||
const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
|
const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory"
|
||||||
|
|
||||||
// idPeACMEIdentifierV1 is the OID for the ACME extension for the TLS-ALPN challenge.
|
|
||||||
var idPeACMEIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
maxChainLen = 5 // max depth and breadth of a certificate chain
|
maxChainLen = 5 // max depth and breadth of a certificate chain
|
||||||
maxCertSize = 1 << 20 // max size of a certificate, in bytes
|
maxCertSize = 1 << 20 // max size of a certificate, in bytes
|
||||||
|
|
@ -79,22 +76,6 @@ type Client struct {
|
||||||
// will have no effect.
|
// will have no effect.
|
||||||
DirectoryURL string
|
DirectoryURL string
|
||||||
|
|
||||||
// RetryBackoff computes the duration after which the nth retry of a failed request
|
|
||||||
// should occur. The value of n for the first call on failure is 1.
|
|
||||||
// The values of r and resp are the request and response of the last failed attempt.
|
|
||||||
// If the returned value is negative or zero, no more retries are done and an error
|
|
||||||
// is returned to the caller of the original method.
|
|
||||||
//
|
|
||||||
// Requests which result in a 4xx client error are not retried,
|
|
||||||
// except for 400 Bad Request due to "bad nonce" errors and 429 Too Many Requests.
|
|
||||||
//
|
|
||||||
// If RetryBackoff is nil, a truncated exponential backoff algorithm
|
|
||||||
// with the ceiling of 10 seconds is used, where each subsequent retry n
|
|
||||||
// is done after either ("Retry-After" + jitter) or (2^n seconds + jitter),
|
|
||||||
// preferring the former if "Retry-After" header is found in the resp.
|
|
||||||
// The jitter is a random value up to 1 second.
|
|
||||||
RetryBackoff func(n int, r *http.Request, resp *http.Response) time.Duration
|
|
||||||
|
|
||||||
dirMu sync.Mutex // guards writes to dir
|
dirMu sync.Mutex // guards writes to dir
|
||||||
dir *Directory // cached result of Client's Discover method
|
dir *Directory // cached result of Client's Discover method
|
||||||
|
|
||||||
|
|
@ -118,12 +99,15 @@ func (c *Client) Discover(ctx context.Context) (Directory, error) {
|
||||||
if dirURL == "" {
|
if dirURL == "" {
|
||||||
dirURL = LetsEncryptURL
|
dirURL = LetsEncryptURL
|
||||||
}
|
}
|
||||||
res, err := c.get(ctx, dirURL, wantStatus(http.StatusOK))
|
res, err := c.get(ctx, dirURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Directory{}, err
|
return Directory{}, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
c.addNonce(res.Header)
|
c.addNonce(res.Header)
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
return Directory{}, responseError(res)
|
||||||
|
}
|
||||||
|
|
||||||
var v struct {
|
var v struct {
|
||||||
Reg string `json:"new-reg"`
|
Reg string `json:"new-reg"`
|
||||||
|
|
@ -182,11 +166,14 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
|
||||||
req.NotAfter = now.Add(exp).Format(time.RFC3339)
|
req.NotAfter = now.Add(exp).Format(time.RFC3339)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.post(ctx, c.Key, c.dir.CertURL, req, wantStatus(http.StatusCreated))
|
res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != http.StatusCreated {
|
||||||
|
return nil, "", responseError(res)
|
||||||
|
}
|
||||||
|
|
||||||
curl := res.Header.Get("Location") // cert permanent URL
|
curl := res.Header.Get("Location") // cert permanent URL
|
||||||
if res.ContentLength == 0 {
|
if res.ContentLength == 0 {
|
||||||
|
|
@ -209,11 +196,26 @@ func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration,
|
||||||
// Callers are encouraged to parse the returned value to ensure the certificate is valid
|
// Callers are encouraged to parse the returned value to ensure the certificate is valid
|
||||||
// and has expected features.
|
// and has expected features.
|
||||||
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
|
func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK))
|
for {
|
||||||
if err != nil {
|
res, err := c.get(ctx, url)
|
||||||
return nil, err
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return c.responseCert(ctx, res, bundle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RevokeCert revokes a previously issued certificate cert, provided in DER format.
|
// RevokeCert revokes a previously issued certificate cert, provided in DER format.
|
||||||
|
|
@ -239,11 +241,14 @@ func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte,
|
||||||
if key == nil {
|
if key == nil {
|
||||||
key = c.Key
|
key = c.Key
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, key, c.dir.RevokeURL, body, wantStatus(http.StatusOK))
|
res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
return responseError(res)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,11 +329,14 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
|
||||||
Resource: "new-authz",
|
Resource: "new-authz",
|
||||||
Identifier: authzID{Type: "dns", Value: domain},
|
Identifier: authzID{Type: "dns", Value: domain},
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, c.Key, c.dir.AuthzURL, req, wantStatus(http.StatusCreated))
|
res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != http.StatusCreated {
|
||||||
|
return nil, responseError(res)
|
||||||
|
}
|
||||||
|
|
||||||
var v wireAuthz
|
var v wireAuthz
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||||
|
|
@ -345,11 +353,14 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
|
||||||
// If a caller needs to poll an authorization until its status is final,
|
// If a caller needs to poll an authorization until its status is final,
|
||||||
// see the WaitAuthorization method.
|
// see the WaitAuthorization method.
|
||||||
func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
res, err := c.get(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||||
|
return nil, responseError(res)
|
||||||
|
}
|
||||||
var v wireAuthz
|
var v wireAuthz
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||||
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
||||||
|
|
@ -376,11 +387,14 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
|
||||||
Status: "deactivated",
|
Status: "deactivated",
|
||||||
Delete: true,
|
Delete: true,
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, c.Key, url, req, wantStatus(http.StatusOK))
|
res, err := c.retryPostJWS(ctx, c.Key, url, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
return responseError(res)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -392,42 +406,44 @@ func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
|
||||||
// In all other cases WaitAuthorization returns an error.
|
// In all other cases WaitAuthorization returns an error.
|
||||||
// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
|
// If the Status is StatusInvalid, the returned error is of type *AuthorizationError.
|
||||||
func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
||||||
|
sleep := sleeper(ctx)
|
||||||
for {
|
for {
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
res, err := c.get(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
var raw wireAuthz
|
||||||
err = json.NewDecoder(res.Body).Decode(&raw)
|
err = json.NewDecoder(res.Body).Decode(&raw)
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
switch {
|
if err != nil {
|
||||||
case err != nil:
|
if err := sleep(retry, 0); err != nil {
|
||||||
// Skip and retry.
|
return nil, err
|
||||||
case raw.Status == StatusValid:
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if raw.Status == StatusValid {
|
||||||
return raw.authorization(url), nil
|
return raw.authorization(url), nil
|
||||||
case raw.Status == StatusInvalid:
|
}
|
||||||
|
if raw.Status == StatusInvalid {
|
||||||
return nil, raw.error(url)
|
return nil, raw.error(url)
|
||||||
}
|
}
|
||||||
|
if err := sleep(retry, 0); err != nil {
|
||||||
// Exponential backoff is implemented in c.get above.
|
return nil, err
|
||||||
// This is just to prevent continuously hitting the CA
|
|
||||||
// while waiting for a final authorization status.
|
|
||||||
d := retryAfter(res.Header.Get("Retry-After"))
|
|
||||||
if d == 0 {
|
|
||||||
// Given that the fastest challenges TLS-SNI and HTTP-01
|
|
||||||
// require a CA to make at least 1 network round trip
|
|
||||||
// and most likely persist a challenge state,
|
|
||||||
// this default delay seems reasonable.
|
|
||||||
d = time.Second
|
|
||||||
}
|
|
||||||
t := time.NewTimer(d)
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
t.Stop()
|
|
||||||
return nil, ctx.Err()
|
|
||||||
case <-t.C:
|
|
||||||
// Retry.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -436,11 +452,14 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
|
||||||
//
|
//
|
||||||
// A client typically polls a challenge status using this method.
|
// A client typically polls a challenge status using this method.
|
||||||
func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
|
func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) {
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK, http.StatusAccepted))
|
res, err := c.get(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||||
|
return nil, responseError(res)
|
||||||
|
}
|
||||||
v := wireChallenge{URI: url}
|
v := wireChallenge{URI: url}
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||||
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
return nil, fmt.Errorf("acme: invalid response: %v", err)
|
||||||
|
|
@ -467,14 +486,16 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error
|
||||||
Type: chal.Type,
|
Type: chal.Type,
|
||||||
Auth: auth,
|
Auth: auth,
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, c.Key, chal.URI, req, wantStatus(
|
res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req)
|
||||||
http.StatusOK, // according to the spec
|
|
||||||
http.StatusAccepted, // Let's Encrypt: see https://goo.gl/WsJ7VT (acme-divergences.md)
|
|
||||||
))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
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
|
var v wireChallenge
|
||||||
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
|
||||||
|
|
@ -531,7 +552,7 @@ func (c *Client) HTTP01ChallengePath(token string) string {
|
||||||
// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
|
// 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 returned certificate is valid for the next 24 hours and must be presented only when
|
||||||
// the server name of the TLS ClientHello matches exactly the returned name value.
|
// 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) {
|
func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
|
||||||
ka, err := keyAuth(c.Key.Public(), token)
|
ka, err := keyAuth(c.Key.Public(), token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -558,7 +579,7 @@ func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tl
|
||||||
// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve.
|
// 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 returned certificate is valid for the next 24 hours and must be presented only when
|
||||||
// the server name in the TLS ClientHello matches exactly the returned name value.
|
// 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) {
|
func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) {
|
||||||
b := sha256.Sum256([]byte(token))
|
b := sha256.Sum256([]byte(token))
|
||||||
h := hex.EncodeToString(b[:])
|
h := hex.EncodeToString(b[:])
|
||||||
|
|
@ -579,48 +600,6 @@ func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tl
|
||||||
return cert, sanA, nil
|
return cert, sanA, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TLSALPN01ChallengeCert creates a certificate for TLS-ALPN-01 challenge response.
|
|
||||||
// Servers can present the certificate to validate the challenge and prove control
|
|
||||||
// over a domain name. For more details on TLS-ALPN-01 see
|
|
||||||
// https://tools.ietf.org/html/draft-shoemaker-acme-tls-alpn-00#section-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 TLS ClientHello matches the domain, and the special acme-tls/1 ALPN protocol
|
|
||||||
// has been specified.
|
|
||||||
func (c *Client) TLSALPN01ChallengeCert(token, domain string, opt ...CertOption) (cert tls.Certificate, err error) {
|
|
||||||
ka, err := keyAuth(c.Key.Public(), token)
|
|
||||||
if err != nil {
|
|
||||||
return tls.Certificate{}, err
|
|
||||||
}
|
|
||||||
shasum := sha256.Sum256([]byte(ka))
|
|
||||||
acmeExtension := pkix.Extension{
|
|
||||||
Id: idPeACMEIdentifierV1,
|
|
||||||
Critical: true,
|
|
||||||
Value: shasum[:],
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl := defaultTLSChallengeCertTemplate()
|
|
||||||
|
|
||||||
var newOpt []CertOption
|
|
||||||
for _, o := range opt {
|
|
||||||
switch o := o.(type) {
|
|
||||||
case *certOptTemplate:
|
|
||||||
t := *(*x509.Certificate)(o) // shallow copy is ok
|
|
||||||
tmpl = &t
|
|
||||||
default:
|
|
||||||
newOpt = append(newOpt, o)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmpl.ExtraExtensions = append(tmpl.ExtraExtensions, acmeExtension)
|
|
||||||
newOpt = append(newOpt, WithTemplate(tmpl))
|
|
||||||
return tlsChallengeCert([]string{domain}, newOpt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// doReg sends all types of registration requests.
|
// doReg sends all types of registration requests.
|
||||||
// The type of request is identified by typ argument, which is a "resource"
|
// The type of request is identified by typ argument, which is a "resource"
|
||||||
// in the ACME spec terms.
|
// in the ACME spec terms.
|
||||||
|
|
@ -640,14 +619,14 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
|
||||||
req.Contact = acct.Contact
|
req.Contact = acct.Contact
|
||||||
req.Agreement = acct.AgreedTerms
|
req.Agreement = acct.AgreedTerms
|
||||||
}
|
}
|
||||||
res, err := c.post(ctx, c.Key, url, req, wantStatus(
|
res, err := c.retryPostJWS(ctx, c.Key, url, req)
|
||||||
http.StatusOK, // updates and deletes
|
|
||||||
http.StatusCreated, // new account creation
|
|
||||||
))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||||
|
return nil, responseError(res)
|
||||||
|
}
|
||||||
|
|
||||||
var v struct {
|
var v struct {
|
||||||
Contact []string
|
Contact []string
|
||||||
|
|
@ -677,6 +656,59 @@ func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Accoun
|
||||||
}, nil
|
}, 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
|
// popNonce returns a nonce value previously stored with c.addNonce
|
||||||
// or fetches a fresh one from the given URL.
|
// or fetches a fresh one from the given URL.
|
||||||
func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
|
func (c *Client) popNonce(ctx context.Context, url string) (string, error) {
|
||||||
|
|
@ -717,12 +749,58 @@ func (c *Client) addNonce(h http.Header) {
|
||||||
c.nonces[v] = struct{}{}
|
c.nonces[v] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) {
|
func (c *Client) httpClient() *http.Client {
|
||||||
r, err := http.NewRequest("HEAD", url, nil)
|
if c.HTTPClient != nil {
|
||||||
if err != nil {
|
return c.HTTPClient
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
resp, err := c.doNoRetry(ctx, r)
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -774,6 +852,24 @@ func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bo
|
||||||
return cert, nil
|
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.
|
// chainCert fetches CA certificate chain recursively by following "up" links.
|
||||||
// Each recursive call increments the depth by 1, resulting in an error
|
// Each recursive call increments the depth by 1, resulting in an error
|
||||||
// if the recursion level reaches maxChainLen.
|
// if the recursion level reaches maxChainLen.
|
||||||
|
|
@ -784,11 +880,14 @@ func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte
|
||||||
return nil, errors.New("acme: certificate chain is too deep")
|
return nil, errors.New("acme: certificate chain is too deep")
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.get(ctx, url, wantStatus(http.StatusOK))
|
res, err := c.get(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != http.StatusOK {
|
||||||
|
return nil, responseError(res)
|
||||||
|
}
|
||||||
b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
|
b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -833,6 +932,65 @@ func linkHeader(h http.Header, rel string) []string {
|
||||||
return links
|
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.
|
// keyAuth generates a key authorization string for a given token.
|
||||||
func keyAuth(pub crypto.PublicKey, token string) (string, error) {
|
func keyAuth(pub crypto.PublicKey, token string) (string, error) {
|
||||||
th, err := JWKThumbprint(pub)
|
th, err := JWKThumbprint(pub)
|
||||||
|
|
@ -842,25 +1000,15 @@ func keyAuth(pub crypto.PublicKey, token string) (string, error) {
|
||||||
return fmt.Sprintf("%s.%s", token, th), nil
|
return fmt.Sprintf("%s.%s", token, th), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultTLSChallengeCertTemplate is a template used to create challenge certs for TLS challenges.
|
|
||||||
func defaultTLSChallengeCertTemplate() *x509.Certificate {
|
|
||||||
return &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},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
|
// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
|
||||||
// with the given SANs and auto-generated public/private key pair.
|
// with the given SANs and auto-generated public/private key pair.
|
||||||
// The Subject Common Name is set to the first SAN to aid debugging.
|
// 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.
|
// To create a cert with a custom key pair, specify WithKey option.
|
||||||
func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
|
func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
|
||||||
var key crypto.Signer
|
var (
|
||||||
tmpl := defaultTLSChallengeCertTemplate()
|
key crypto.Signer
|
||||||
|
tmpl *x509.Certificate
|
||||||
|
)
|
||||||
for _, o := range opt {
|
for _, o := range opt {
|
||||||
switch o := o.(type) {
|
switch o := o.(type) {
|
||||||
case *certOptKey:
|
case *certOptKey:
|
||||||
|
|
@ -869,7 +1017,7 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
|
||||||
}
|
}
|
||||||
key = o.key
|
key = o.key
|
||||||
case *certOptTemplate:
|
case *certOptTemplate:
|
||||||
t := *(*x509.Certificate)(o) // shallow copy is ok
|
var t = *(*x509.Certificate)(o) // shallow copy is ok
|
||||||
tmpl = &t
|
tmpl = &t
|
||||||
default:
|
default:
|
||||||
// package's fault, if we let this happen:
|
// package's fault, if we let this happen:
|
||||||
|
|
@ -882,6 +1030,16 @@ func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
|
||||||
return tls.Certificate{}, err
|
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
|
tmpl.DNSNames = san
|
||||||
if len(san) > 0 {
|
if len(san) > 0 {
|
||||||
tmpl.Subject.CommonName = san[0]
|
tmpl.Subject.CommonName = san[0]
|
||||||
|
|
|
||||||
262
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
262
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
|
|
@ -98,11 +98,11 @@ type Manager struct {
|
||||||
// To always accept the terms, the callers can use AcceptTOS.
|
// To always accept the terms, the callers can use AcceptTOS.
|
||||||
Prompt func(tosURL string) bool
|
Prompt func(tosURL string) bool
|
||||||
|
|
||||||
// Cache optionally stores and retrieves previously-obtained certificates
|
// Cache optionally stores and retrieves previously-obtained certificates.
|
||||||
// and other state. If nil, certs will only be cached for the lifetime of
|
// If nil, certs will only be cached for the lifetime of the Manager.
|
||||||
// the Manager. Multiple Managers can share the same Cache.
|
|
||||||
//
|
//
|
||||||
// Using a persistent Cache, such as DirCache, is strongly recommended.
|
// 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
|
Cache Cache
|
||||||
|
|
||||||
// HostPolicy controls which domains the Manager will attempt
|
// HostPolicy controls which domains the Manager will attempt
|
||||||
|
|
@ -127,10 +127,8 @@ type Manager struct {
|
||||||
|
|
||||||
// Client is used to perform low-level operations, such as account registration
|
// Client is used to perform low-level operations, such as account registration
|
||||||
// and requesting new certificates.
|
// and requesting new certificates.
|
||||||
//
|
|
||||||
// If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL
|
// If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL
|
||||||
// as directory endpoint. If the Client.Key is nil, a new ECDSA P-256 key is
|
// directory endpoint and a newly-generated ECDSA P-256 key.
|
||||||
// generated and, if Cache is not nil, stored in cache.
|
|
||||||
//
|
//
|
||||||
// Mutating the field after the first call of GetCertificate method will have no effect.
|
// Mutating the field after the first call of GetCertificate method will have no effect.
|
||||||
Client *acme.Client
|
Client *acme.Client
|
||||||
|
|
@ -142,30 +140,22 @@ type Manager struct {
|
||||||
// If the Client's account key is already registered, Email is not used.
|
// If the Client's account key is already registered, Email is not used.
|
||||||
Email string
|
Email string
|
||||||
|
|
||||||
// ForceRSA used to make the Manager generate RSA certificates. It is now ignored.
|
// ForceRSA makes the Manager generate certificates with 2048-bit RSA keys.
|
||||||
//
|
//
|
||||||
// Deprecated: the Manager will request the correct type of certificate based
|
// If false, a default is used. Currently the default
|
||||||
// on what each client supports.
|
// is EC-based keys using the P-256 curve.
|
||||||
ForceRSA bool
|
ForceRSA bool
|
||||||
|
|
||||||
// ExtraExtensions are used when generating a new CSR (Certificate Request),
|
|
||||||
// thus allowing customization of the resulting certificate.
|
|
||||||
// For instance, TLS Feature Extension (RFC 7633) can be used
|
|
||||||
// to prevent an OCSP downgrade attack.
|
|
||||||
//
|
|
||||||
// The field value is passed to crypto/x509.CreateCertificateRequest
|
|
||||||
// in the template's ExtraExtensions field as is.
|
|
||||||
ExtraExtensions []pkix.Extension
|
|
||||||
|
|
||||||
clientMu sync.Mutex
|
clientMu sync.Mutex
|
||||||
client *acme.Client // initialized by acmeClient method
|
client *acme.Client // initialized by acmeClient method
|
||||||
|
|
||||||
stateMu sync.Mutex
|
stateMu sync.Mutex
|
||||||
state map[certKey]*certState
|
state map[string]*certState // keyed by domain name
|
||||||
|
|
||||||
// renewal tracks the set of domains currently running renewal timers.
|
// renewal tracks the set of domains currently running renewal timers.
|
||||||
|
// It is keyed by domain name.
|
||||||
renewalMu sync.Mutex
|
renewalMu sync.Mutex
|
||||||
renewal map[certKey]*domainRenewal
|
renewal map[string]*domainRenewal
|
||||||
|
|
||||||
// tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens.
|
// tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens.
|
||||||
tokensMu sync.RWMutex
|
tokensMu sync.RWMutex
|
||||||
|
|
@ -184,23 +174,6 @@ type Manager struct {
|
||||||
certTokens map[string]*tls.Certificate
|
certTokens map[string]*tls.Certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
// certKey is the key by which certificates are tracked in state, renewal and cache.
|
|
||||||
type certKey struct {
|
|
||||||
domain string // without trailing dot
|
|
||||||
isRSA bool // RSA cert for legacy clients (as opposed to default ECDSA)
|
|
||||||
isToken bool // tls-sni challenge token cert; key type is undefined regardless of isRSA
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c certKey) String() string {
|
|
||||||
if c.isToken {
|
|
||||||
return c.domain + "+token"
|
|
||||||
}
|
|
||||||
if c.isRSA {
|
|
||||||
return c.domain + "+rsa"
|
|
||||||
}
|
|
||||||
return c.domain
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCertificate implements the tls.Config.GetCertificate hook.
|
// GetCertificate implements the tls.Config.GetCertificate hook.
|
||||||
// It provides a TLS certificate for hello.ServerName host, including answering
|
// It provides a TLS certificate for hello.ServerName host, including answering
|
||||||
// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored.
|
// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored.
|
||||||
|
|
@ -221,7 +194,7 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
||||||
if !strings.Contains(strings.Trim(name, "."), ".") {
|
if !strings.Contains(strings.Trim(name, "."), ".") {
|
||||||
return nil, errors.New("acme/autocert: server name component count invalid")
|
return nil, errors.New("acme/autocert: server name component count invalid")
|
||||||
}
|
}
|
||||||
if strings.ContainsAny(name, `+/\`) {
|
if strings.ContainsAny(name, `/\`) {
|
||||||
return nil, errors.New("acme/autocert: server name contains invalid character")
|
return nil, errors.New("acme/autocert: server name contains invalid character")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,7 +210,7 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
||||||
if cert := m.certTokens[name]; cert != nil {
|
if cert := m.certTokens[name]; cert != nil {
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
if cert, err := m.cacheGet(ctx, certKey{domain: name, isToken: true}); err == nil {
|
if cert, err := m.cacheGet(ctx, name); err == nil {
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
// TODO: cache error results?
|
// TODO: cache error results?
|
||||||
|
|
@ -245,11 +218,8 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
||||||
}
|
}
|
||||||
|
|
||||||
// regular domain
|
// regular domain
|
||||||
ck := certKey{
|
name = strings.TrimSuffix(name, ".") // golang.org/issue/18114
|
||||||
domain: strings.TrimSuffix(name, "."), // golang.org/issue/18114
|
cert, err := m.cert(ctx, name)
|
||||||
isRSA: !supportsECDSA(hello),
|
|
||||||
}
|
|
||||||
cert, err := m.cert(ctx, ck)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
|
|
@ -261,60 +231,14 @@ func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
||||||
if err := m.hostPolicy()(ctx, name); err != nil {
|
if err := m.hostPolicy()(ctx, name); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cert, err = m.createCert(ctx, ck)
|
cert, err = m.createCert(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
m.cachePut(ctx, ck, cert)
|
m.cachePut(ctx, name, cert)
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func supportsECDSA(hello *tls.ClientHelloInfo) bool {
|
|
||||||
// The "signature_algorithms" extension, if present, limits the key exchange
|
|
||||||
// algorithms allowed by the cipher suites. See RFC 5246, section 7.4.1.4.1.
|
|
||||||
if hello.SignatureSchemes != nil {
|
|
||||||
ecdsaOK := false
|
|
||||||
schemeLoop:
|
|
||||||
for _, scheme := range hello.SignatureSchemes {
|
|
||||||
const tlsECDSAWithSHA1 tls.SignatureScheme = 0x0203 // constant added in Go 1.10
|
|
||||||
switch scheme {
|
|
||||||
case tlsECDSAWithSHA1, tls.ECDSAWithP256AndSHA256,
|
|
||||||
tls.ECDSAWithP384AndSHA384, tls.ECDSAWithP521AndSHA512:
|
|
||||||
ecdsaOK = true
|
|
||||||
break schemeLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ecdsaOK {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if hello.SupportedCurves != nil {
|
|
||||||
ecdsaOK := false
|
|
||||||
for _, curve := range hello.SupportedCurves {
|
|
||||||
if curve == tls.CurveP256 {
|
|
||||||
ecdsaOK = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ecdsaOK {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, suite := range hello.CipherSuites {
|
|
||||||
switch suite {
|
|
||||||
case tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPHandler configures the Manager to provision ACME "http-01" challenge responses.
|
// HTTPHandler configures the Manager to provision ACME "http-01" challenge responses.
|
||||||
// It returns an http.Handler that responds to the challenges and must be
|
// 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,
|
// running on port 80. If it receives a request that is not an ACME challenge,
|
||||||
|
|
@ -380,16 +304,16 @@ func stripPort(hostport string) string {
|
||||||
// cert returns an existing certificate either from m.state or cache.
|
// cert returns an existing certificate either from m.state or cache.
|
||||||
// If a certificate is found in cache but not in m.state, the latter will be filled
|
// If a certificate is found in cache but not in m.state, the latter will be filled
|
||||||
// with the cached value.
|
// with the cached value.
|
||||||
func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error) {
|
func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) {
|
||||||
m.stateMu.Lock()
|
m.stateMu.Lock()
|
||||||
if s, ok := m.state[ck]; ok {
|
if s, ok := m.state[name]; ok {
|
||||||
m.stateMu.Unlock()
|
m.stateMu.Unlock()
|
||||||
s.RLock()
|
s.RLock()
|
||||||
defer s.RUnlock()
|
defer s.RUnlock()
|
||||||
return s.tlscert()
|
return s.tlscert()
|
||||||
}
|
}
|
||||||
defer m.stateMu.Unlock()
|
defer m.stateMu.Unlock()
|
||||||
cert, err := m.cacheGet(ctx, ck)
|
cert, err := m.cacheGet(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -398,25 +322,25 @@ func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error
|
||||||
return nil, errors.New("acme/autocert: private key cannot sign")
|
return nil, errors.New("acme/autocert: private key cannot sign")
|
||||||
}
|
}
|
||||||
if m.state == nil {
|
if m.state == nil {
|
||||||
m.state = make(map[certKey]*certState)
|
m.state = make(map[string]*certState)
|
||||||
}
|
}
|
||||||
s := &certState{
|
s := &certState{
|
||||||
key: signer,
|
key: signer,
|
||||||
cert: cert.Certificate,
|
cert: cert.Certificate,
|
||||||
leaf: cert.Leaf,
|
leaf: cert.Leaf,
|
||||||
}
|
}
|
||||||
m.state[ck] = s
|
m.state[name] = s
|
||||||
go m.renew(ck, s.key, s.leaf.NotAfter)
|
go m.renew(name, s.key, s.leaf.NotAfter)
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// cacheGet always returns a valid certificate, or an error otherwise.
|
// cacheGet always returns a valid certificate, or an error otherwise.
|
||||||
// If a cached certificate exists but is not valid, ErrCacheMiss is returned.
|
// If a cached certficate exists but is not valid, ErrCacheMiss is returned.
|
||||||
func (m *Manager) cacheGet(ctx context.Context, ck certKey) (*tls.Certificate, error) {
|
func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) {
|
||||||
if m.Cache == nil {
|
if m.Cache == nil {
|
||||||
return nil, ErrCacheMiss
|
return nil, ErrCacheMiss
|
||||||
}
|
}
|
||||||
data, err := m.Cache.Get(ctx, ck.String())
|
data, err := m.Cache.Get(ctx, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -447,7 +371,7 @@ func (m *Manager) cacheGet(ctx context.Context, ck certKey) (*tls.Certificate, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify and create TLS cert
|
// verify and create TLS cert
|
||||||
leaf, err := validCert(ck, pubDER, privKey)
|
leaf, err := validCert(domain, pubDER, privKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrCacheMiss
|
return nil, ErrCacheMiss
|
||||||
}
|
}
|
||||||
|
|
@ -459,7 +383,7 @@ func (m *Manager) cacheGet(ctx context.Context, ck certKey) (*tls.Certificate, e
|
||||||
return tlscert, nil
|
return tlscert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) cachePut(ctx context.Context, ck certKey, tlscert *tls.Certificate) error {
|
func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error {
|
||||||
if m.Cache == nil {
|
if m.Cache == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -491,7 +415,7 @@ func (m *Manager) cachePut(ctx context.Context, ck certKey, tlscert *tls.Certifi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.Cache.Put(ctx, ck.String(), buf.Bytes())
|
return m.Cache.Put(ctx, domain, buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
|
func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
|
||||||
|
|
@ -508,9 +432,9 @@ func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
|
||||||
//
|
//
|
||||||
// If the domain is already being verified, it waits for the existing verification to complete.
|
// 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.
|
// Either way, createCert blocks for the duration of the whole process.
|
||||||
func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate, error) {
|
func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) {
|
||||||
// TODO: maybe rewrite this whole piece using sync.Once
|
// TODO: maybe rewrite this whole piece using sync.Once
|
||||||
state, err := m.certState(ck)
|
state, err := m.certState(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -528,44 +452,44 @@ func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate,
|
||||||
defer state.Unlock()
|
defer state.Unlock()
|
||||||
state.locked = false
|
state.locked = false
|
||||||
|
|
||||||
der, leaf, err := m.authorizedCert(ctx, state.key, ck)
|
der, leaf, err := m.authorizedCert(ctx, state.key, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Remove the failed state after some time,
|
// Remove the failed state after some time,
|
||||||
// making the manager call createCert again on the following TLS hello.
|
// making the manager call createCert again on the following TLS hello.
|
||||||
time.AfterFunc(createCertRetryAfter, func() {
|
time.AfterFunc(createCertRetryAfter, func() {
|
||||||
defer testDidRemoveState(ck)
|
defer testDidRemoveState(domain)
|
||||||
m.stateMu.Lock()
|
m.stateMu.Lock()
|
||||||
defer m.stateMu.Unlock()
|
defer m.stateMu.Unlock()
|
||||||
// Verify the state hasn't changed and it's still invalid
|
// Verify the state hasn't changed and it's still invalid
|
||||||
// before deleting.
|
// before deleting.
|
||||||
s, ok := m.state[ck]
|
s, ok := m.state[domain]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := validCert(ck, s.cert, s.key); err == nil {
|
if _, err := validCert(domain, s.cert, s.key); err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
delete(m.state, ck)
|
delete(m.state, domain)
|
||||||
})
|
})
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
state.cert = der
|
state.cert = der
|
||||||
state.leaf = leaf
|
state.leaf = leaf
|
||||||
go m.renew(ck, state.key, state.leaf.NotAfter)
|
go m.renew(domain, state.key, state.leaf.NotAfter)
|
||||||
return state.tlscert()
|
return state.tlscert()
|
||||||
}
|
}
|
||||||
|
|
||||||
// certState returns a new or existing certState.
|
// certState returns a new or existing certState.
|
||||||
// If a new certState is returned, state.exist is false and the state is locked.
|
// 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.
|
// The returned error is non-nil only in the case where a new state could not be created.
|
||||||
func (m *Manager) certState(ck certKey) (*certState, error) {
|
func (m *Manager) certState(domain string) (*certState, error) {
|
||||||
m.stateMu.Lock()
|
m.stateMu.Lock()
|
||||||
defer m.stateMu.Unlock()
|
defer m.stateMu.Unlock()
|
||||||
if m.state == nil {
|
if m.state == nil {
|
||||||
m.state = make(map[certKey]*certState)
|
m.state = make(map[string]*certState)
|
||||||
}
|
}
|
||||||
// existing state
|
// existing state
|
||||||
if state, ok := m.state[ck]; ok {
|
if state, ok := m.state[domain]; ok {
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -574,7 +498,7 @@ func (m *Manager) certState(ck certKey) (*certState, error) {
|
||||||
err error
|
err error
|
||||||
key crypto.Signer
|
key crypto.Signer
|
||||||
)
|
)
|
||||||
if ck.isRSA {
|
if m.ForceRSA {
|
||||||
key, err = rsa.GenerateKey(rand.Reader, 2048)
|
key, err = rsa.GenerateKey(rand.Reader, 2048)
|
||||||
} else {
|
} else {
|
||||||
key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
|
@ -588,22 +512,22 @@ func (m *Manager) certState(ck certKey) (*certState, error) {
|
||||||
locked: true,
|
locked: true,
|
||||||
}
|
}
|
||||||
state.Lock() // will be unlocked by m.certState caller
|
state.Lock() // will be unlocked by m.certState caller
|
||||||
m.state[ck] = state
|
m.state[domain] = state
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
|
// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
|
||||||
// The key argument is the certificate private key.
|
// The key argument is the certificate private key.
|
||||||
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck certKey) (der [][]byte, leaf *x509.Certificate, err error) {
|
func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
|
||||||
client, err := m.acmeClient(ctx)
|
client, err := m.acmeClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.verify(ctx, client, ck.domain); err != nil {
|
if err := m.verify(ctx, client, domain); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
csr, err := certRequest(key, ck.domain, m.ExtraExtensions)
|
csr, err := certRequest(key, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -611,25 +535,13 @@ func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, ck cert
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
leaf, err = validCert(ck, der, key)
|
leaf, err = validCert(domain, der, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return der, leaf, nil
|
return der, leaf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// revokePendingAuthz revokes all authorizations idenfied by the elements of uri slice.
|
|
||||||
// It ignores revocation errors.
|
|
||||||
func (m *Manager) revokePendingAuthz(ctx context.Context, uri []string) {
|
|
||||||
client, err := m.acmeClient(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, u := range uri {
|
|
||||||
client.RevokeAuthorization(ctx, u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify runs the identifier (domain) authorization flow
|
// verify runs the identifier (domain) authorization flow
|
||||||
// using each applicable ACME challenge type.
|
// using each applicable ACME challenge type.
|
||||||
func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error {
|
func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error {
|
||||||
|
|
@ -642,22 +554,6 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string
|
||||||
}
|
}
|
||||||
m.tokensMu.RUnlock()
|
m.tokensMu.RUnlock()
|
||||||
|
|
||||||
// Keep track of pending authzs and revoke the ones that did not validate.
|
|
||||||
pendingAuthzs := make(map[string]bool)
|
|
||||||
defer func() {
|
|
||||||
var uri []string
|
|
||||||
for k, pending := range pendingAuthzs {
|
|
||||||
if pending {
|
|
||||||
uri = append(uri, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(uri) > 0 {
|
|
||||||
// Use "detached" background context.
|
|
||||||
// The revocations need not happen in the current verification flow.
|
|
||||||
go m.revokePendingAuthz(context.Background(), uri)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var nextTyp int // challengeType index of the next challenge type to try
|
var nextTyp int // challengeType index of the next challenge type to try
|
||||||
for {
|
for {
|
||||||
// Start domain authorization and get the challenge.
|
// Start domain authorization and get the challenge.
|
||||||
|
|
@ -674,8 +570,6 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string
|
||||||
return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI)
|
return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI)
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingAuthzs[authz.URI] = true
|
|
||||||
|
|
||||||
// Pick the next preferred challenge.
|
// Pick the next preferred challenge.
|
||||||
var chal *acme.Challenge
|
var chal *acme.Challenge
|
||||||
for chal == nil && nextTyp < len(challengeTypes) {
|
for chal == nil && nextTyp < len(challengeTypes) {
|
||||||
|
|
@ -696,7 +590,6 @@ func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string
|
||||||
|
|
||||||
// A challenge is fulfilled and accepted: wait for the CA to validate.
|
// A challenge is fulfilled and accepted: wait for the CA to validate.
|
||||||
if _, err := client.WaitAuthorization(ctx, authz.URI); err == nil {
|
if _, err := client.WaitAuthorization(ctx, authz.URI); err == nil {
|
||||||
delete(pendingAuthzs, authz.URI)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -741,8 +634,8 @@ func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// putCertToken stores the token certificate with the specified name
|
// putCertToken stores the cert under the named key in both m.certTokens map
|
||||||
// in both m.certTokens map and m.Cache.
|
// and m.Cache.
|
||||||
func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) {
|
func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) {
|
||||||
m.tokensMu.Lock()
|
m.tokensMu.Lock()
|
||||||
defer m.tokensMu.Unlock()
|
defer m.tokensMu.Unlock()
|
||||||
|
|
@ -750,18 +643,17 @@ func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certi
|
||||||
m.certTokens = make(map[string]*tls.Certificate)
|
m.certTokens = make(map[string]*tls.Certificate)
|
||||||
}
|
}
|
||||||
m.certTokens[name] = cert
|
m.certTokens[name] = cert
|
||||||
m.cachePut(ctx, certKey{domain: name, isToken: true}, cert)
|
m.cachePut(ctx, name, cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteCertToken removes the token certificate with the specified name
|
// deleteCertToken removes the token certificate for the specified domain name
|
||||||
// from both m.certTokens map and m.Cache.
|
// from both m.certTokens map and m.Cache.
|
||||||
func (m *Manager) deleteCertToken(name string) {
|
func (m *Manager) deleteCertToken(name string) {
|
||||||
m.tokensMu.Lock()
|
m.tokensMu.Lock()
|
||||||
defer m.tokensMu.Unlock()
|
defer m.tokensMu.Unlock()
|
||||||
delete(m.certTokens, name)
|
delete(m.certTokens, name)
|
||||||
if m.Cache != nil {
|
if m.Cache != nil {
|
||||||
ck := certKey{domain: name, isToken: true}
|
m.Cache.Delete(context.Background(), name)
|
||||||
m.Cache.Delete(context.Background(), ck.String())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -812,7 +704,7 @@ func (m *Manager) deleteHTTPToken(tokenPath string) {
|
||||||
// httpTokenCacheKey returns a key at which an http-01 token value may be stored
|
// httpTokenCacheKey returns a key at which an http-01 token value may be stored
|
||||||
// in the Manager's optional Cache.
|
// in the Manager's optional Cache.
|
||||||
func httpTokenCacheKey(tokenPath string) string {
|
func httpTokenCacheKey(tokenPath string) string {
|
||||||
return path.Base(tokenPath) + "+http-01"
|
return "http-01-" + path.Base(tokenPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// renew starts a cert renewal timer loop, one per domain.
|
// renew starts a cert renewal timer loop, one per domain.
|
||||||
|
|
@ -823,18 +715,18 @@ func httpTokenCacheKey(tokenPath string) string {
|
||||||
//
|
//
|
||||||
// The key argument is a certificate private key.
|
// The key argument is a certificate private key.
|
||||||
// The exp argument is the cert expiration time (NotAfter).
|
// The exp argument is the cert expiration time (NotAfter).
|
||||||
func (m *Manager) renew(ck certKey, key crypto.Signer, exp time.Time) {
|
func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) {
|
||||||
m.renewalMu.Lock()
|
m.renewalMu.Lock()
|
||||||
defer m.renewalMu.Unlock()
|
defer m.renewalMu.Unlock()
|
||||||
if m.renewal[ck] != nil {
|
if m.renewal[domain] != nil {
|
||||||
// another goroutine is already on it
|
// another goroutine is already on it
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if m.renewal == nil {
|
if m.renewal == nil {
|
||||||
m.renewal = make(map[certKey]*domainRenewal)
|
m.renewal = make(map[string]*domainRenewal)
|
||||||
}
|
}
|
||||||
dr := &domainRenewal{m: m, ck: ck, key: key}
|
dr := &domainRenewal{m: m, domain: domain, key: key}
|
||||||
m.renewal[ck] = dr
|
m.renewal[domain] = dr
|
||||||
dr.start(exp)
|
dr.start(exp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -850,10 +742,7 @@ func (m *Manager) stopRenew() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) {
|
func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) {
|
||||||
const keyName = "acme_account+key"
|
const keyName = "acme_account.key"
|
||||||
|
|
||||||
// Previous versions of autocert stored the value under a different key.
|
|
||||||
const legacyKeyName = "acme_account.key"
|
|
||||||
|
|
||||||
genKey := func() (*ecdsa.PrivateKey, error) {
|
genKey := func() (*ecdsa.PrivateKey, error) {
|
||||||
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
|
@ -864,9 +753,6 @@ func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := m.Cache.Get(ctx, keyName)
|
data, err := m.Cache.Get(ctx, keyName)
|
||||||
if err == ErrCacheMiss {
|
|
||||||
data, err = m.Cache.Get(ctx, legacyKeyName)
|
|
||||||
}
|
|
||||||
if err == ErrCacheMiss {
|
if err == ErrCacheMiss {
|
||||||
key, err := genKey()
|
key, err := genKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -963,12 +849,12 @@ func (s *certState) tlscert() (*tls.Certificate, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// certRequest generates a CSR for the given common name cn and optional SANs.
|
// certRequest creates a certificate request for the given common name cn
|
||||||
func certRequest(key crypto.Signer, cn string, ext []pkix.Extension, san ...string) ([]byte, error) {
|
// and optional SANs.
|
||||||
|
func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) {
|
||||||
req := &x509.CertificateRequest{
|
req := &x509.CertificateRequest{
|
||||||
Subject: pkix.Name{CommonName: cn},
|
Subject: pkix.Name{CommonName: cn},
|
||||||
DNSNames: san,
|
DNSNames: san,
|
||||||
ExtraExtensions: ext,
|
|
||||||
}
|
}
|
||||||
return x509.CreateCertificateRequest(rand.Reader, req, key)
|
return x509.CreateCertificateRequest(rand.Reader, req, key)
|
||||||
}
|
}
|
||||||
|
|
@ -999,12 +885,12 @@ func parsePrivateKey(der []byte) (crypto.Signer, error) {
|
||||||
return nil, errors.New("acme/autocert: failed to parse private key")
|
return nil, errors.New("acme/autocert: failed to parse private key")
|
||||||
}
|
}
|
||||||
|
|
||||||
// validCert parses a cert chain provided as der argument and verifies the leaf and der[0]
|
// validCert parses a cert chain provided as der argument and verifies the leaf, der[0],
|
||||||
// correspond to the private key, the domain and key type match, and expiration dates
|
// corresponds to the private key, as well as the domain match and expiration dates.
|
||||||
// are valid. It doesn't do any revocation checking.
|
// It doesn't do any revocation checking.
|
||||||
//
|
//
|
||||||
// The returned value is the verified leaf cert.
|
// The returned value is the verified leaf cert.
|
||||||
func validCert(ck certKey, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) {
|
func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) {
|
||||||
// parse public part(s)
|
// parse public part(s)
|
||||||
var n int
|
var n int
|
||||||
for _, b := range der {
|
for _, b := range der {
|
||||||
|
|
@ -1016,7 +902,7 @@ func validCert(ck certKey, der [][]byte, key crypto.Signer) (leaf *x509.Certific
|
||||||
n += copy(pub[n:], b)
|
n += copy(pub[n:], b)
|
||||||
}
|
}
|
||||||
x509Cert, err := x509.ParseCertificates(pub)
|
x509Cert, err := x509.ParseCertificates(pub)
|
||||||
if err != nil || len(x509Cert) == 0 {
|
if len(x509Cert) == 0 {
|
||||||
return nil, errors.New("acme/autocert: no public key found")
|
return nil, errors.New("acme/autocert: no public key found")
|
||||||
}
|
}
|
||||||
// verify the leaf is not expired and matches the domain name
|
// verify the leaf is not expired and matches the domain name
|
||||||
|
|
@ -1028,10 +914,10 @@ func validCert(ck certKey, der [][]byte, key crypto.Signer) (leaf *x509.Certific
|
||||||
if now.After(leaf.NotAfter) {
|
if now.After(leaf.NotAfter) {
|
||||||
return nil, errors.New("acme/autocert: expired certificate")
|
return nil, errors.New("acme/autocert: expired certificate")
|
||||||
}
|
}
|
||||||
if err := leaf.VerifyHostname(ck.domain); err != nil {
|
if err := leaf.VerifyHostname(domain); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// ensure the leaf corresponds to the private key and matches the certKey type
|
// ensure the leaf corresponds to the private key
|
||||||
switch pub := leaf.PublicKey.(type) {
|
switch pub := leaf.PublicKey.(type) {
|
||||||
case *rsa.PublicKey:
|
case *rsa.PublicKey:
|
||||||
prv, ok := key.(*rsa.PrivateKey)
|
prv, ok := key.(*rsa.PrivateKey)
|
||||||
|
|
@ -1041,9 +927,6 @@ func validCert(ck certKey, der [][]byte, key crypto.Signer) (leaf *x509.Certific
|
||||||
if pub.N.Cmp(prv.N) != 0 {
|
if pub.N.Cmp(prv.N) != 0 {
|
||||||
return nil, errors.New("acme/autocert: private key does not match public key")
|
return nil, errors.New("acme/autocert: private key does not match public key")
|
||||||
}
|
}
|
||||||
if !ck.isRSA && !ck.isToken {
|
|
||||||
return nil, errors.New("acme/autocert: key type does not match expected value")
|
|
||||||
}
|
|
||||||
case *ecdsa.PublicKey:
|
case *ecdsa.PublicKey:
|
||||||
prv, ok := key.(*ecdsa.PrivateKey)
|
prv, ok := key.(*ecdsa.PrivateKey)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -1052,9 +935,6 @@ func validCert(ck certKey, der [][]byte, key crypto.Signer) (leaf *x509.Certific
|
||||||
if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 {
|
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")
|
return nil, errors.New("acme/autocert: private key does not match public key")
|
||||||
}
|
}
|
||||||
if ck.isRSA && !ck.isToken {
|
|
||||||
return nil, errors.New("acme/autocert: key type does not match expected value")
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("acme/autocert: unknown public key algorithm")
|
return nil, errors.New("acme/autocert: unknown public key algorithm")
|
||||||
}
|
}
|
||||||
|
|
@ -1078,5 +958,5 @@ var (
|
||||||
timeNow = time.Now
|
timeNow = time.Now
|
||||||
|
|
||||||
// Called when a state is removed.
|
// Called when a state is removed.
|
||||||
testDidRemoveState = func(certKey) {}
|
testDidRemoveState = func(domain string) {}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
6
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
6
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
|
|
@ -16,10 +16,10 @@ import (
|
||||||
var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
|
var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
|
||||||
|
|
||||||
// Cache is used by Manager to store and retrieve previously obtained certificates
|
// Cache is used by Manager to store and retrieve previously obtained certificates
|
||||||
// and other account data as opaque blobs.
|
// as opaque data.
|
||||||
//
|
//
|
||||||
// Cache implementations should not rely on the key naming pattern. Keys can
|
// The key argument of the methods refers to a domain name but need not be an FQDN.
|
||||||
// include any printable ASCII characters, except the following: \/:*?"<>|
|
// Cache implementations should not rely on the key naming pattern.
|
||||||
type Cache interface {
|
type Cache interface {
|
||||||
// Get returns a certificate data for the specified key.
|
// Get returns a certificate data for the specified key.
|
||||||
// If there's no such key, Get returns ErrCacheMiss.
|
// If there's no such key, Get returns ErrCacheMiss.
|
||||||
|
|
|
||||||
14
vendor/golang.org/x/crypto/acme/autocert/renewal.go
generated
vendored
14
vendor/golang.org/x/crypto/acme/autocert/renewal.go
generated
vendored
|
|
@ -17,9 +17,9 @@ const renewJitter = time.Hour
|
||||||
// domainRenewal tracks the state used by the periodic timers
|
// domainRenewal tracks the state used by the periodic timers
|
||||||
// renewing a single domain's cert.
|
// renewing a single domain's cert.
|
||||||
type domainRenewal struct {
|
type domainRenewal struct {
|
||||||
m *Manager
|
m *Manager
|
||||||
ck certKey
|
domain string
|
||||||
key crypto.Signer
|
key crypto.Signer
|
||||||
|
|
||||||
timerMu sync.Mutex
|
timerMu sync.Mutex
|
||||||
timer *time.Timer
|
timer *time.Timer
|
||||||
|
|
@ -77,7 +77,7 @@ func (dr *domainRenewal) updateState(state *certState) {
|
||||||
dr.m.stateMu.Lock()
|
dr.m.stateMu.Lock()
|
||||||
defer dr.m.stateMu.Unlock()
|
defer dr.m.stateMu.Unlock()
|
||||||
dr.key = state.key
|
dr.key = state.key
|
||||||
dr.m.state[dr.ck] = state
|
dr.m.state[dr.domain] = state
|
||||||
}
|
}
|
||||||
|
|
||||||
// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
|
// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
|
||||||
|
|
@ -91,7 +91,7 @@ func (dr *domainRenewal) updateState(state *certState) {
|
||||||
func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
|
func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
|
||||||
// a race is likely unavoidable in a distributed environment
|
// a race is likely unavoidable in a distributed environment
|
||||||
// but we try nonetheless
|
// but we try nonetheless
|
||||||
if tlscert, err := dr.m.cacheGet(ctx, dr.ck); err == nil {
|
if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil {
|
||||||
next := dr.next(tlscert.Leaf.NotAfter)
|
next := dr.next(tlscert.Leaf.NotAfter)
|
||||||
if next > dr.m.renewBefore()+renewJitter {
|
if next > dr.m.renewBefore()+renewJitter {
|
||||||
signer, ok := tlscert.PrivateKey.(crypto.Signer)
|
signer, ok := tlscert.PrivateKey.(crypto.Signer)
|
||||||
|
|
@ -107,7 +107,7 @@ func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.ck)
|
der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +120,7 @@ func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if err := dr.m.cachePut(ctx, dr.ck, tlscert); err != nil {
|
if err := dr.m.cachePut(ctx, dr.domain, tlscert); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
dr.updateState(state)
|
dr.updateState(state)
|
||||||
|
|
|
||||||
276
vendor/golang.org/x/crypto/acme/http.go
generated
vendored
276
vendor/golang.org/x/crypto/acme/http.go
generated
vendored
|
|
@ -1,276 +0,0 @@
|
||||||
// Copyright 2018 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 (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"crypto"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"math/big"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// retryTimer encapsulates common logic for retrying unsuccessful requests.
|
|
||||||
// It is not safe for concurrent use.
|
|
||||||
type retryTimer struct {
|
|
||||||
// backoffFn provides backoff delay sequence for retries.
|
|
||||||
// See Client.RetryBackoff doc comment.
|
|
||||||
backoffFn func(n int, r *http.Request, res *http.Response) time.Duration
|
|
||||||
// n is the current retry attempt.
|
|
||||||
n int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *retryTimer) inc() {
|
|
||||||
t.n++
|
|
||||||
}
|
|
||||||
|
|
||||||
// backoff pauses the current goroutine as described in Client.RetryBackoff.
|
|
||||||
func (t *retryTimer) backoff(ctx context.Context, r *http.Request, res *http.Response) error {
|
|
||||||
d := t.backoffFn(t.n, r, res)
|
|
||||||
if d <= 0 {
|
|
||||||
return fmt.Errorf("acme: no more retries for %s; tried %d time(s)", r.URL, t.n)
|
|
||||||
}
|
|
||||||
wakeup := time.NewTimer(d)
|
|
||||||
defer wakeup.Stop()
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
|
||||||
case <-wakeup.C:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) retryTimer() *retryTimer {
|
|
||||||
f := c.RetryBackoff
|
|
||||||
if f == nil {
|
|
||||||
f = defaultBackoff
|
|
||||||
}
|
|
||||||
return &retryTimer{backoffFn: f}
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultBackoff provides default Client.RetryBackoff implementation
|
|
||||||
// using a truncated exponential backoff algorithm,
|
|
||||||
// as described in Client.RetryBackoff.
|
|
||||||
//
|
|
||||||
// The n argument is always bounded between 1 and 30.
|
|
||||||
// The returned value is always greater than 0.
|
|
||||||
func defaultBackoff(n int, r *http.Request, res *http.Response) time.Duration {
|
|
||||||
const max = 10 * time.Second
|
|
||||||
var jitter time.Duration
|
|
||||||
if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil {
|
|
||||||
// Set the minimum to 1ms to avoid a case where
|
|
||||||
// an invalid Retry-After value is parsed into 0 below,
|
|
||||||
// resulting in the 0 returned value which would unintentionally
|
|
||||||
// stop the retries.
|
|
||||||
jitter = (1 + time.Duration(x.Int64())) * time.Millisecond
|
|
||||||
}
|
|
||||||
if v, ok := res.Header["Retry-After"]; ok {
|
|
||||||
return retryAfter(v[0]) + jitter
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < 1 {
|
|
||||||
n = 1
|
|
||||||
}
|
|
||||||
if n > 30 {
|
|
||||||
n = 30
|
|
||||||
}
|
|
||||||
d := time.Duration(1<<uint(n-1))*time.Second + jitter
|
|
||||||
if d > max {
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
// retryAfter parses a Retry-After HTTP header value,
|
|
||||||
// trying to convert v into an int (seconds) or use http.ParseTime otherwise.
|
|
||||||
// It returns zero value if v cannot be parsed.
|
|
||||||
func retryAfter(v string) 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 0
|
|
||||||
}
|
|
||||||
return t.Sub(timeNow())
|
|
||||||
}
|
|
||||||
|
|
||||||
// resOkay is a function that reports whether the provided response is okay.
|
|
||||||
// It is expected to keep the response body unread.
|
|
||||||
type resOkay func(*http.Response) bool
|
|
||||||
|
|
||||||
// wantStatus returns a function which reports whether the code
|
|
||||||
// matches the status code of a response.
|
|
||||||
func wantStatus(codes ...int) resOkay {
|
|
||||||
return func(res *http.Response) bool {
|
|
||||||
for _, code := range codes {
|
|
||||||
if code == res.StatusCode {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get issues an unsigned GET request to the specified URL.
|
|
||||||
// It returns a non-error value only when ok reports true.
|
|
||||||
//
|
|
||||||
// get retries unsuccessful attempts according to c.RetryBackoff
|
|
||||||
// until the context is done or a non-retriable error is received.
|
|
||||||
func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Response, error) {
|
|
||||||
retry := c.retryTimer()
|
|
||||||
for {
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
res, err := c.doNoRetry(ctx, req)
|
|
||||||
switch {
|
|
||||||
case err != nil:
|
|
||||||
return nil, err
|
|
||||||
case ok(res):
|
|
||||||
return res, nil
|
|
||||||
case isRetriable(res.StatusCode):
|
|
||||||
res.Body.Close()
|
|
||||||
retry.inc()
|
|
||||||
if err := retry.backoff(ctx, req, res); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
defer res.Body.Close()
|
|
||||||
return nil, responseError(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// post issues a signed POST request in JWS format using the provided key
|
|
||||||
// to the specified URL.
|
|
||||||
// It returns a non-error value only when ok reports true.
|
|
||||||
//
|
|
||||||
// post retries unsuccessful attempts according to c.RetryBackoff
|
|
||||||
// until the context is done or a non-retriable error is received.
|
|
||||||
// It uses postNoRetry to make individual requests.
|
|
||||||
func (c *Client) post(ctx context.Context, key crypto.Signer, url string, body interface{}, ok resOkay) (*http.Response, error) {
|
|
||||||
retry := c.retryTimer()
|
|
||||||
for {
|
|
||||||
res, req, err := c.postNoRetry(ctx, key, url, body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if ok(res) {
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
err = responseError(res)
|
|
||||||
res.Body.Close()
|
|
||||||
switch {
|
|
||||||
// Check for bad nonce before isRetriable because it may have been returned
|
|
||||||
// with an unretriable response code such as 400 Bad Request.
|
|
||||||
case isBadNonce(err):
|
|
||||||
// Consider any previously stored nonce values to be invalid.
|
|
||||||
c.clearNonces()
|
|
||||||
case !isRetriable(res.StatusCode):
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
retry.inc()
|
|
||||||
if err := retry.backoff(ctx, req, res); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// postNoRetry signs the body with the given key and POSTs it to the provided url.
|
|
||||||
// The body argument must be JSON-serializable.
|
|
||||||
// It is used by c.post to retry unsuccessful attempts.
|
|
||||||
func (c *Client) postNoRetry(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, *http.Request, error) {
|
|
||||||
nonce, err := c.popNonce(ctx, url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
b, err := jwsEncodeJSON(body, key, nonce)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewReader(b))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/jose+json")
|
|
||||||
res, err := c.doNoRetry(ctx, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
c.addNonce(res.Header)
|
|
||||||
return res, req, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// doNoRetry issues a request req, replacing its context (if any) with ctx.
|
|
||||||
func (c *Client) doNoRetry(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) httpClient() *http.Client {
|
|
||||||
if c.HTTPClient != nil {
|
|
||||||
return c.HTTPClient
|
|
||||||
}
|
|
||||||
return http.DefaultClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// isBadNonce reports whether err is an ACME "badnonce" error.
|
|
||||||
func isBadNonce(err error) bool {
|
|
||||||
// According to the spec badNonce is urn:ietf:params:acme:error:badNonce.
|
|
||||||
// However, ACME servers in the wild return their versions of the error.
|
|
||||||
// See https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4
|
|
||||||
// and https://github.com/letsencrypt/boulder/blob/0e07eacb/docs/acme-divergences.md#section-66.
|
|
||||||
ae, ok := err.(*Error)
|
|
||||||
return ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce")
|
|
||||||
}
|
|
||||||
|
|
||||||
// isRetriable reports whether a request can be retried
|
|
||||||
// based on the response status code.
|
|
||||||
//
|
|
||||||
// Note that a "bad nonce" error is returned with a non-retriable 400 Bad Request code.
|
|
||||||
// Callers should parse the response and check with isBadNonce.
|
|
||||||
func isRetriable(code int) bool {
|
|
||||||
return code <= 399 || code >= 500 || code == http.StatusTooManyRequests
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
8
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
8
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
|
|
@ -104,7 +104,7 @@ func RateLimit(err error) (time.Duration, bool) {
|
||||||
if e.Header == nil {
|
if e.Header == nil {
|
||||||
return 0, true
|
return 0, true
|
||||||
}
|
}
|
||||||
return retryAfter(e.Header.Get("Retry-After")), true
|
return retryAfter(e.Header.Get("Retry-After"), 0), true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account is a user account. It is associated with a private key.
|
// Account is a user account. It is associated with a private key.
|
||||||
|
|
@ -296,8 +296,8 @@ func (e *wireError) error(h http.Header) *Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CertOption is an optional argument type for the TLS ChallengeCert methods for
|
// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for
|
||||||
// customizing a temporary certificate for TLS-based challenges.
|
// customizing a temporary certificate for TLS-SNI challenges.
|
||||||
type CertOption interface {
|
type CertOption interface {
|
||||||
privateCertOpt()
|
privateCertOpt()
|
||||||
}
|
}
|
||||||
|
|
@ -317,7 +317,7 @@ func (*certOptKey) privateCertOpt() {}
|
||||||
// WithTemplate creates an option for specifying a certificate template.
|
// WithTemplate creates an option for specifying a certificate template.
|
||||||
// See x509.CreateCertificate for template usage details.
|
// See x509.CreateCertificate for template usage details.
|
||||||
//
|
//
|
||||||
// In TLS ChallengeCert methods, the template is also used as parent,
|
// In TLSSNIxChallengeCert methods, the template is also used as parent,
|
||||||
// resulting in a self-signed certificate.
|
// resulting in a self-signed certificate.
|
||||||
// The DNSNames field of t is always overwritten for tls-sni challenge certs.
|
// The DNSNames field of t is always overwritten for tls-sni challenge certs.
|
||||||
func WithTemplate(t *x509.Certificate) CertOption {
|
func WithTemplate(t *x509.Certificate) CertOption {
|
||||||
|
|
|
||||||
47
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
47
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
|
|
@ -6,10 +6,7 @@
|
||||||
// https://ed25519.cr.yp.to/.
|
// https://ed25519.cr.yp.to/.
|
||||||
//
|
//
|
||||||
// These functions are also compatible with the “Ed25519” function defined in
|
// These functions are also compatible with the “Ed25519” function defined in
|
||||||
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
|
// RFC 8032.
|
||||||
// representation includes a public key suffix to make multiple signing
|
|
||||||
// operations with the same key more efficient. This package refers to the RFC
|
|
||||||
// 8032 private key as the “seed”.
|
|
||||||
package ed25519
|
package ed25519
|
||||||
|
|
||||||
// This code is a port of the public domain, “ref10” implementation of ed25519
|
// This code is a port of the public domain, “ref10” implementation of ed25519
|
||||||
|
|
@ -34,8 +31,6 @@ const (
|
||||||
PrivateKeySize = 64
|
PrivateKeySize = 64
|
||||||
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
||||||
SignatureSize = 64
|
SignatureSize = 64
|
||||||
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
|
|
||||||
SeedSize = 32
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PublicKey is the type of Ed25519 public keys.
|
// PublicKey is the type of Ed25519 public keys.
|
||||||
|
|
@ -51,15 +46,6 @@ func (priv PrivateKey) Public() crypto.PublicKey {
|
||||||
return PublicKey(publicKey)
|
return PublicKey(publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seed returns the private key seed corresponding to priv. It is provided for
|
|
||||||
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
|
|
||||||
// in this package.
|
|
||||||
func (priv PrivateKey) Seed() []byte {
|
|
||||||
seed := make([]byte, SeedSize)
|
|
||||||
copy(seed, priv[:32])
|
|
||||||
return seed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign signs the given message with priv.
|
// Sign signs the given message with priv.
|
||||||
// Ed25519 performs two passes over messages to be signed and therefore cannot
|
// Ed25519 performs two passes over messages to be signed and therefore cannot
|
||||||
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
|
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
|
||||||
|
|
@ -75,33 +61,19 @@ func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOp
|
||||||
|
|
||||||
// GenerateKey generates a public/private key pair using entropy from rand.
|
// GenerateKey generates a public/private key pair using entropy from rand.
|
||||||
// If rand is nil, crypto/rand.Reader will be used.
|
// If rand is nil, crypto/rand.Reader will be used.
|
||||||
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
|
func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
|
||||||
if rand == nil {
|
if rand == nil {
|
||||||
rand = cryptorand.Reader
|
rand = cryptorand.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
seed := make([]byte, SeedSize)
|
privateKey = make([]byte, PrivateKeySize)
|
||||||
if _, err := io.ReadFull(rand, seed); err != nil {
|
publicKey = make([]byte, PublicKeySize)
|
||||||
|
_, err = io.ReadFull(rand, privateKey[:32])
|
||||||
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
privateKey := NewKeyFromSeed(seed)
|
digest := sha512.Sum512(privateKey[:32])
|
||||||
publicKey := make([]byte, PublicKeySize)
|
|
||||||
copy(publicKey, privateKey[32:])
|
|
||||||
|
|
||||||
return publicKey, privateKey, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewKeyFromSeed calculates a private key from a seed. It will panic if
|
|
||||||
// len(seed) is not SeedSize. This function is provided for interoperability
|
|
||||||
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
|
|
||||||
// package.
|
|
||||||
func NewKeyFromSeed(seed []byte) PrivateKey {
|
|
||||||
if l := len(seed); l != SeedSize {
|
|
||||||
panic("ed25519: bad seed length: " + strconv.Itoa(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
digest := sha512.Sum512(seed)
|
|
||||||
digest[0] &= 248
|
digest[0] &= 248
|
||||||
digest[31] &= 127
|
digest[31] &= 127
|
||||||
digest[31] |= 64
|
digest[31] |= 64
|
||||||
|
|
@ -113,11 +85,10 @@ func NewKeyFromSeed(seed []byte) PrivateKey {
|
||||||
var publicKeyBytes [32]byte
|
var publicKeyBytes [32]byte
|
||||||
A.ToBytes(&publicKeyBytes)
|
A.ToBytes(&publicKeyBytes)
|
||||||
|
|
||||||
privateKey := make([]byte, PrivateKeySize)
|
|
||||||
copy(privateKey, seed)
|
|
||||||
copy(privateKey[32:], publicKeyBytes[:])
|
copy(privateKey[32:], publicKeyBytes[:])
|
||||||
|
copy(publicKey, publicKeyBytes[:])
|
||||||
|
|
||||||
return privateKey
|
return publicKey, privateKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign signs the message with privateKey and returns a signature. It will
|
// Sign signs the message with privateKey and returns a signature. It will
|
||||||
|
|
|
||||||
283
vendor/golang.org/x/crypto/internal/chacha20/asm_s390x.s
generated
vendored
283
vendor/golang.org/x/crypto/internal/chacha20/asm_s390x.s
generated
vendored
|
|
@ -1,283 +0,0 @@
|
||||||
// Copyright 2018 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 s390x,!gccgo,!appengine
|
|
||||||
|
|
||||||
#include "go_asm.h"
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
// This is an implementation of the ChaCha20 encryption algorithm as
|
|
||||||
// specified in RFC 7539. It uses vector instructions to compute
|
|
||||||
// 4 keystream blocks in parallel (256 bytes) which are then XORed
|
|
||||||
// with the bytes in the input slice.
|
|
||||||
|
|
||||||
GLOBL ·constants<>(SB), RODATA|NOPTR, $32
|
|
||||||
// BSWAP: swap bytes in each 4-byte element
|
|
||||||
DATA ·constants<>+0x00(SB)/4, $0x03020100
|
|
||||||
DATA ·constants<>+0x04(SB)/4, $0x07060504
|
|
||||||
DATA ·constants<>+0x08(SB)/4, $0x0b0a0908
|
|
||||||
DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c
|
|
||||||
// J0: [j0, j1, j2, j3]
|
|
||||||
DATA ·constants<>+0x10(SB)/4, $0x61707865
|
|
||||||
DATA ·constants<>+0x14(SB)/4, $0x3320646e
|
|
||||||
DATA ·constants<>+0x18(SB)/4, $0x79622d32
|
|
||||||
DATA ·constants<>+0x1c(SB)/4, $0x6b206574
|
|
||||||
|
|
||||||
// EXRL targets:
|
|
||||||
TEXT ·mvcSrcToBuf(SB), NOFRAME|NOSPLIT, $0
|
|
||||||
MVC $1, (R1), (R8)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·mvcBufToDst(SB), NOFRAME|NOSPLIT, $0
|
|
||||||
MVC $1, (R8), (R9)
|
|
||||||
RET
|
|
||||||
|
|
||||||
#define BSWAP V5
|
|
||||||
#define J0 V6
|
|
||||||
#define KEY0 V7
|
|
||||||
#define KEY1 V8
|
|
||||||
#define NONCE V9
|
|
||||||
#define CTR V10
|
|
||||||
#define M0 V11
|
|
||||||
#define M1 V12
|
|
||||||
#define M2 V13
|
|
||||||
#define M3 V14
|
|
||||||
#define INC V15
|
|
||||||
#define X0 V16
|
|
||||||
#define X1 V17
|
|
||||||
#define X2 V18
|
|
||||||
#define X3 V19
|
|
||||||
#define X4 V20
|
|
||||||
#define X5 V21
|
|
||||||
#define X6 V22
|
|
||||||
#define X7 V23
|
|
||||||
#define X8 V24
|
|
||||||
#define X9 V25
|
|
||||||
#define X10 V26
|
|
||||||
#define X11 V27
|
|
||||||
#define X12 V28
|
|
||||||
#define X13 V29
|
|
||||||
#define X14 V30
|
|
||||||
#define X15 V31
|
|
||||||
|
|
||||||
#define NUM_ROUNDS 20
|
|
||||||
|
|
||||||
#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \
|
|
||||||
VAF a1, a0, a0 \
|
|
||||||
VAF b1, b0, b0 \
|
|
||||||
VAF c1, c0, c0 \
|
|
||||||
VAF d1, d0, d0 \
|
|
||||||
VX a0, a2, a2 \
|
|
||||||
VX b0, b2, b2 \
|
|
||||||
VX c0, c2, c2 \
|
|
||||||
VX d0, d2, d2 \
|
|
||||||
VERLLF $16, a2, a2 \
|
|
||||||
VERLLF $16, b2, b2 \
|
|
||||||
VERLLF $16, c2, c2 \
|
|
||||||
VERLLF $16, d2, d2 \
|
|
||||||
VAF a2, a3, a3 \
|
|
||||||
VAF b2, b3, b3 \
|
|
||||||
VAF c2, c3, c3 \
|
|
||||||
VAF d2, d3, d3 \
|
|
||||||
VX a3, a1, a1 \
|
|
||||||
VX b3, b1, b1 \
|
|
||||||
VX c3, c1, c1 \
|
|
||||||
VX d3, d1, d1 \
|
|
||||||
VERLLF $12, a1, a1 \
|
|
||||||
VERLLF $12, b1, b1 \
|
|
||||||
VERLLF $12, c1, c1 \
|
|
||||||
VERLLF $12, d1, d1 \
|
|
||||||
VAF a1, a0, a0 \
|
|
||||||
VAF b1, b0, b0 \
|
|
||||||
VAF c1, c0, c0 \
|
|
||||||
VAF d1, d0, d0 \
|
|
||||||
VX a0, a2, a2 \
|
|
||||||
VX b0, b2, b2 \
|
|
||||||
VX c0, c2, c2 \
|
|
||||||
VX d0, d2, d2 \
|
|
||||||
VERLLF $8, a2, a2 \
|
|
||||||
VERLLF $8, b2, b2 \
|
|
||||||
VERLLF $8, c2, c2 \
|
|
||||||
VERLLF $8, d2, d2 \
|
|
||||||
VAF a2, a3, a3 \
|
|
||||||
VAF b2, b3, b3 \
|
|
||||||
VAF c2, c3, c3 \
|
|
||||||
VAF d2, d3, d3 \
|
|
||||||
VX a3, a1, a1 \
|
|
||||||
VX b3, b1, b1 \
|
|
||||||
VX c3, c1, c1 \
|
|
||||||
VX d3, d1, d1 \
|
|
||||||
VERLLF $7, a1, a1 \
|
|
||||||
VERLLF $7, b1, b1 \
|
|
||||||
VERLLF $7, c1, c1 \
|
|
||||||
VERLLF $7, d1, d1
|
|
||||||
|
|
||||||
#define PERMUTE(mask, v0, v1, v2, v3) \
|
|
||||||
VPERM v0, v0, mask, v0 \
|
|
||||||
VPERM v1, v1, mask, v1 \
|
|
||||||
VPERM v2, v2, mask, v2 \
|
|
||||||
VPERM v3, v3, mask, v3
|
|
||||||
|
|
||||||
#define ADDV(x, v0, v1, v2, v3) \
|
|
||||||
VAF x, v0, v0 \
|
|
||||||
VAF x, v1, v1 \
|
|
||||||
VAF x, v2, v2 \
|
|
||||||
VAF x, v3, v3
|
|
||||||
|
|
||||||
#define XORV(off, dst, src, v0, v1, v2, v3) \
|
|
||||||
VLM off(src), M0, M3 \
|
|
||||||
PERMUTE(BSWAP, v0, v1, v2, v3) \
|
|
||||||
VX v0, M0, M0 \
|
|
||||||
VX v1, M1, M1 \
|
|
||||||
VX v2, M2, M2 \
|
|
||||||
VX v3, M3, M3 \
|
|
||||||
VSTM M0, M3, off(dst)
|
|
||||||
|
|
||||||
#define SHUFFLE(a, b, c, d, t, u, v, w) \
|
|
||||||
VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]}
|
|
||||||
VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]}
|
|
||||||
VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]}
|
|
||||||
VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]}
|
|
||||||
VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]}
|
|
||||||
VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]}
|
|
||||||
VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]}
|
|
||||||
VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]}
|
|
||||||
|
|
||||||
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int)
|
|
||||||
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
|
|
||||||
MOVD $·constants<>(SB), R1
|
|
||||||
MOVD dst+0(FP), R2 // R2=&dst[0]
|
|
||||||
LMG src+24(FP), R3, R4 // R3=&src[0] R4=len(src)
|
|
||||||
MOVD key+48(FP), R5 // R5=key
|
|
||||||
MOVD nonce+56(FP), R6 // R6=nonce
|
|
||||||
MOVD counter+64(FP), R7 // R7=counter
|
|
||||||
MOVD buf+72(FP), R8 // R8=buf
|
|
||||||
MOVD len+80(FP), R9 // R9=len
|
|
||||||
|
|
||||||
// load BSWAP and J0
|
|
||||||
VLM (R1), BSWAP, J0
|
|
||||||
|
|
||||||
// set up tail buffer
|
|
||||||
ADD $-1, R4, R12
|
|
||||||
MOVBZ R12, R12
|
|
||||||
CMPUBEQ R12, $255, aligned
|
|
||||||
MOVD R4, R1
|
|
||||||
AND $~255, R1
|
|
||||||
MOVD $(R3)(R1*1), R1
|
|
||||||
EXRL $·mvcSrcToBuf(SB), R12
|
|
||||||
MOVD $255, R0
|
|
||||||
SUB R12, R0
|
|
||||||
MOVD R0, (R9) // update len
|
|
||||||
|
|
||||||
aligned:
|
|
||||||
// setup
|
|
||||||
MOVD $95, R0
|
|
||||||
VLM (R5), KEY0, KEY1
|
|
||||||
VLL R0, (R6), NONCE
|
|
||||||
VZERO M0
|
|
||||||
VLEIB $7, $32, M0
|
|
||||||
VSRLB M0, NONCE, NONCE
|
|
||||||
|
|
||||||
// initialize counter values
|
|
||||||
VLREPF (R7), CTR
|
|
||||||
VZERO INC
|
|
||||||
VLEIF $1, $1, INC
|
|
||||||
VLEIF $2, $2, INC
|
|
||||||
VLEIF $3, $3, INC
|
|
||||||
VAF INC, CTR, CTR
|
|
||||||
VREPIF $4, INC
|
|
||||||
|
|
||||||
chacha:
|
|
||||||
VREPF $0, J0, X0
|
|
||||||
VREPF $1, J0, X1
|
|
||||||
VREPF $2, J0, X2
|
|
||||||
VREPF $3, J0, X3
|
|
||||||
VREPF $0, KEY0, X4
|
|
||||||
VREPF $1, KEY0, X5
|
|
||||||
VREPF $2, KEY0, X6
|
|
||||||
VREPF $3, KEY0, X7
|
|
||||||
VREPF $0, KEY1, X8
|
|
||||||
VREPF $1, KEY1, X9
|
|
||||||
VREPF $2, KEY1, X10
|
|
||||||
VREPF $3, KEY1, X11
|
|
||||||
VLR CTR, X12
|
|
||||||
VREPF $1, NONCE, X13
|
|
||||||
VREPF $2, NONCE, X14
|
|
||||||
VREPF $3, NONCE, X15
|
|
||||||
|
|
||||||
MOVD $(NUM_ROUNDS/2), R1
|
|
||||||
|
|
||||||
loop:
|
|
||||||
ROUND4(X0, X4, X12, X8, X1, X5, X13, X9, X2, X6, X14, X10, X3, X7, X15, X11)
|
|
||||||
ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8, X3, X4, X14, X9)
|
|
||||||
|
|
||||||
ADD $-1, R1
|
|
||||||
BNE loop
|
|
||||||
|
|
||||||
// decrement length
|
|
||||||
ADD $-256, R4
|
|
||||||
BLT tail
|
|
||||||
|
|
||||||
continue:
|
|
||||||
// rearrange vectors
|
|
||||||
SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3)
|
|
||||||
ADDV(J0, X0, X1, X2, X3)
|
|
||||||
SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3)
|
|
||||||
ADDV(KEY0, X4, X5, X6, X7)
|
|
||||||
SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3)
|
|
||||||
ADDV(KEY1, X8, X9, X10, X11)
|
|
||||||
VAF CTR, X12, X12
|
|
||||||
SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3)
|
|
||||||
ADDV(NONCE, X12, X13, X14, X15)
|
|
||||||
|
|
||||||
// increment counters
|
|
||||||
VAF INC, CTR, CTR
|
|
||||||
|
|
||||||
// xor keystream with plaintext
|
|
||||||
XORV(0*64, R2, R3, X0, X4, X8, X12)
|
|
||||||
XORV(1*64, R2, R3, X1, X5, X9, X13)
|
|
||||||
XORV(2*64, R2, R3, X2, X6, X10, X14)
|
|
||||||
XORV(3*64, R2, R3, X3, X7, X11, X15)
|
|
||||||
|
|
||||||
// increment pointers
|
|
||||||
MOVD $256(R2), R2
|
|
||||||
MOVD $256(R3), R3
|
|
||||||
|
|
||||||
CMPBNE R4, $0, chacha
|
|
||||||
CMPUBEQ R12, $255, return
|
|
||||||
EXRL $·mvcBufToDst(SB), R12 // len was updated during setup
|
|
||||||
|
|
||||||
return:
|
|
||||||
VSTEF $0, CTR, (R7)
|
|
||||||
RET
|
|
||||||
|
|
||||||
tail:
|
|
||||||
MOVD R2, R9
|
|
||||||
MOVD R8, R2
|
|
||||||
MOVD R8, R3
|
|
||||||
MOVD $0, R4
|
|
||||||
JMP continue
|
|
||||||
|
|
||||||
// func hasVectorFacility() bool
|
|
||||||
TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1
|
|
||||||
MOVD $x-24(SP), R1
|
|
||||||
XC $24, 0(R1), 0(R1) // clear the storage
|
|
||||||
MOVD $2, R0 // R0 is the number of double words stored -1
|
|
||||||
WORD $0xB2B01000 // STFLE 0(R1)
|
|
||||||
XOR R0, R0 // reset the value of R0
|
|
||||||
MOVBZ z-8(SP), R1
|
|
||||||
AND $0x40, R1
|
|
||||||
BEQ novector
|
|
||||||
|
|
||||||
vectorinstalled:
|
|
||||||
// check if the vector instruction has been enabled
|
|
||||||
VLEIB $0, $0xF, V16
|
|
||||||
VLGVB $0, V16, R1
|
|
||||||
CMPBNE R1, $0xF, novector
|
|
||||||
MOVB $1, ret+0(FP) // have vx
|
|
||||||
RET
|
|
||||||
|
|
||||||
novector:
|
|
||||||
MOVB $0, ret+0(FP) // no vx
|
|
||||||
RET
|
|
||||||
10
vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
generated
vendored
10
vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go
generated
vendored
|
|
@ -18,10 +18,10 @@ var _ cipher.Stream = (*Cipher)(nil)
|
||||||
// and nonce. A *Cipher implements the cipher.Stream interface.
|
// and nonce. A *Cipher implements the cipher.Stream interface.
|
||||||
type Cipher struct {
|
type Cipher struct {
|
||||||
key [8]uint32
|
key [8]uint32
|
||||||
counter uint32 // incremented after each block
|
|
||||||
nonce [3]uint32
|
nonce [3]uint32
|
||||||
buf [bufSize]byte // buffer for unused keystream bytes
|
counter uint32 // incremented after each block
|
||||||
len int // number of unused keystream bytes at end of buf
|
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.
|
// New creates a new ChaCha20 stream cipher with the given key and nonce.
|
||||||
|
|
@ -63,10 +63,6 @@ func (s *Cipher) XORKeyStream(dst, src []byte) {
|
||||||
if len(src) == 0 {
|
if len(src) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if haveAsm {
|
|
||||||
s.xorKeyStreamAsm(dst, src)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up a 64-byte buffer to pad out the final block if needed
|
// set up a 64-byte buffer to pad out the final block if needed
|
||||||
// (hoisted out of the main loop to avoid spills)
|
// (hoisted out of the main loop to avoid spills)
|
||||||
|
|
|
||||||
16
vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
generated
vendored
16
vendor/golang.org/x/crypto/internal/chacha20/chacha_noasm.go
generated
vendored
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright 2018 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 !s390x gccgo appengine
|
|
||||||
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
const (
|
|
||||||
bufSize = 64
|
|
||||||
haveAsm = false
|
|
||||||
)
|
|
||||||
|
|
||||||
func (*Cipher) xorKeyStreamAsm(dst, src []byte) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
30
vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go
generated
vendored
30
vendor/golang.org/x/crypto/internal/chacha20/chacha_s390x.go
generated
vendored
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright 2018 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 s390x,!gccgo,!appengine
|
|
||||||
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
var haveAsm = hasVectorFacility()
|
|
||||||
|
|
||||||
const bufSize = 256
|
|
||||||
|
|
||||||
// hasVectorFacility reports whether the machine supports the vector
|
|
||||||
// facility (vx).
|
|
||||||
// Implementation in asm_s390x.s.
|
|
||||||
func hasVectorFacility() bool
|
|
||||||
|
|
||||||
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
|
|
||||||
// be called when the vector facility is available.
|
|
||||||
// Implementation in asm_s390x.s.
|
|
||||||
//go:noescape
|
|
||||||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int)
|
|
||||||
|
|
||||||
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
|
|
||||||
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter, &c.buf, &c.len)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXRL targets, DO NOT CALL!
|
|
||||||
func mvcSrcToBuf()
|
|
||||||
func mvcBufToDst()
|
|
||||||
14
vendor/golang.org/x/crypto/poly1305/sum_noasm.go
generated
vendored
14
vendor/golang.org/x/crypto/poly1305/sum_noasm.go
generated
vendored
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright 2018 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 s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl
|
|
||||||
|
|
||||||
package poly1305
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
sumGeneric(out, msg, key)
|
|
||||||
}
|
|
||||||
10
vendor/golang.org/x/crypto/poly1305/sum_ref.go
generated
vendored
10
vendor/golang.org/x/crypto/poly1305/sum_ref.go
generated
vendored
|
|
@ -2,14 +2,16 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !amd64,!arm gccgo appengine nacl
|
||||||
|
|
||||||
package poly1305
|
package poly1305
|
||||||
|
|
||||||
import "encoding/binary"
|
import "encoding/binary"
|
||||||
|
|
||||||
// sumGeneric generates an authenticator for msg using a one-time key and
|
// Sum generates an authenticator for msg using a one-time key and puts the
|
||||||
// puts the 16-byte result into out. This is the generic implementation of
|
// 16-byte result into out. Authenticating two different messages with the same
|
||||||
// Sum and should be called if no assembly implementation is available.
|
// key allows an attacker to forge messages at will.
|
||||||
func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) {
|
func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
|
||||||
var (
|
var (
|
||||||
h0, h1, h2, h3, h4 uint32 // the hash accumulators
|
h0, h1, h2, h3, h4 uint32 // the hash accumulators
|
||||||
r0, r1, r2, r3, r4 uint64 // the r part of the key
|
r0, r1, r2, r3, r4 uint64 // the r part of the key
|
||||||
|
|
|
||||||
49
vendor/golang.org/x/crypto/poly1305/sum_s390x.go
generated
vendored
49
vendor/golang.org/x/crypto/poly1305/sum_s390x.go
generated
vendored
|
|
@ -1,49 +0,0 @@
|
||||||
// Copyright 2018 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 s390x,go1.11,!gccgo,!appengine
|
|
||||||
|
|
||||||
package poly1305
|
|
||||||
|
|
||||||
// hasVectorFacility reports whether the machine supports
|
|
||||||
// the vector facility (vx).
|
|
||||||
func hasVectorFacility() bool
|
|
||||||
|
|
||||||
// hasVMSLFacility reports whether the machine supports
|
|
||||||
// Vector Multiply Sum Logical (VMSL).
|
|
||||||
func hasVMSLFacility() bool
|
|
||||||
|
|
||||||
var hasVX = hasVectorFacility()
|
|
||||||
var hasVMSL = hasVMSLFacility()
|
|
||||||
|
|
||||||
// poly1305vx is an assembly implementation of Poly1305 that uses vector
|
|
||||||
// instructions. It must only be called if the vector facility (vx) is
|
|
||||||
// available.
|
|
||||||
//go:noescape
|
|
||||||
func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
|
|
||||||
|
|
||||||
// poly1305vmsl is an assembly implementation of Poly1305 that uses vector
|
|
||||||
// instructions, including VMSL. It must only be called if the vector facility (vx) is
|
|
||||||
// available and if VMSL is supported.
|
|
||||||
//go:noescape
|
|
||||||
func poly1305vmsl(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) {
|
|
||||||
if hasVX {
|
|
||||||
var mPtr *byte
|
|
||||||
if len(m) > 0 {
|
|
||||||
mPtr = &m[0]
|
|
||||||
}
|
|
||||||
if hasVMSL && len(m) > 256 {
|
|
||||||
poly1305vmsl(out, mPtr, uint64(len(m)), key)
|
|
||||||
} else {
|
|
||||||
poly1305vx(out, mPtr, uint64(len(m)), key)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sumGeneric(out, m, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
400
vendor/golang.org/x/crypto/poly1305/sum_s390x.s
generated
vendored
400
vendor/golang.org/x/crypto/poly1305/sum_s390x.s
generated
vendored
|
|
@ -1,400 +0,0 @@
|
||||||
// Copyright 2018 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 s390x,go1.11,!gccgo,!appengine
|
|
||||||
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
// Implementation of Poly1305 using the vector facility (vx).
|
|
||||||
|
|
||||||
// constants
|
|
||||||
#define MOD26 V0
|
|
||||||
#define EX0 V1
|
|
||||||
#define EX1 V2
|
|
||||||
#define EX2 V3
|
|
||||||
|
|
||||||
// temporaries
|
|
||||||
#define T_0 V4
|
|
||||||
#define T_1 V5
|
|
||||||
#define T_2 V6
|
|
||||||
#define T_3 V7
|
|
||||||
#define T_4 V8
|
|
||||||
|
|
||||||
// key (r)
|
|
||||||
#define R_0 V9
|
|
||||||
#define R_1 V10
|
|
||||||
#define R_2 V11
|
|
||||||
#define R_3 V12
|
|
||||||
#define R_4 V13
|
|
||||||
#define R5_1 V14
|
|
||||||
#define R5_2 V15
|
|
||||||
#define R5_3 V16
|
|
||||||
#define R5_4 V17
|
|
||||||
#define RSAVE_0 R5
|
|
||||||
#define RSAVE_1 R6
|
|
||||||
#define RSAVE_2 R7
|
|
||||||
#define RSAVE_3 R8
|
|
||||||
#define RSAVE_4 R9
|
|
||||||
#define R5SAVE_1 V28
|
|
||||||
#define R5SAVE_2 V29
|
|
||||||
#define R5SAVE_3 V30
|
|
||||||
#define R5SAVE_4 V31
|
|
||||||
|
|
||||||
// message block
|
|
||||||
#define F_0 V18
|
|
||||||
#define F_1 V19
|
|
||||||
#define F_2 V20
|
|
||||||
#define F_3 V21
|
|
||||||
#define F_4 V22
|
|
||||||
|
|
||||||
// accumulator
|
|
||||||
#define H_0 V23
|
|
||||||
#define H_1 V24
|
|
||||||
#define H_2 V25
|
|
||||||
#define H_3 V26
|
|
||||||
#define H_4 V27
|
|
||||||
|
|
||||||
GLOBL ·keyMask<>(SB), RODATA, $16
|
|
||||||
DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f
|
|
||||||
DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f
|
|
||||||
|
|
||||||
GLOBL ·bswapMask<>(SB), RODATA, $16
|
|
||||||
DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908
|
|
||||||
DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100
|
|
||||||
|
|
||||||
GLOBL ·constants<>(SB), RODATA, $64
|
|
||||||
// MOD26
|
|
||||||
DATA ·constants<>+0(SB)/8, $0x3ffffff
|
|
||||||
DATA ·constants<>+8(SB)/8, $0x3ffffff
|
|
||||||
// EX0
|
|
||||||
DATA ·constants<>+16(SB)/8, $0x0006050403020100
|
|
||||||
DATA ·constants<>+24(SB)/8, $0x1016151413121110
|
|
||||||
// EX1
|
|
||||||
DATA ·constants<>+32(SB)/8, $0x060c0b0a09080706
|
|
||||||
DATA ·constants<>+40(SB)/8, $0x161c1b1a19181716
|
|
||||||
// EX2
|
|
||||||
DATA ·constants<>+48(SB)/8, $0x0d0d0d0d0d0f0e0d
|
|
||||||
DATA ·constants<>+56(SB)/8, $0x1d1d1d1d1d1f1e1d
|
|
||||||
|
|
||||||
// h = (f*g) % (2**130-5) [partial reduction]
|
|
||||||
#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \
|
|
||||||
VMLOF f0, g0, h0 \
|
|
||||||
VMLOF f0, g1, h1 \
|
|
||||||
VMLOF f0, g2, h2 \
|
|
||||||
VMLOF f0, g3, h3 \
|
|
||||||
VMLOF f0, g4, h4 \
|
|
||||||
VMLOF f1, g54, T_0 \
|
|
||||||
VMLOF f1, g0, T_1 \
|
|
||||||
VMLOF f1, g1, T_2 \
|
|
||||||
VMLOF f1, g2, T_3 \
|
|
||||||
VMLOF f1, g3, T_4 \
|
|
||||||
VMALOF f2, g53, h0, h0 \
|
|
||||||
VMALOF f2, g54, h1, h1 \
|
|
||||||
VMALOF f2, g0, h2, h2 \
|
|
||||||
VMALOF f2, g1, h3, h3 \
|
|
||||||
VMALOF f2, g2, h4, h4 \
|
|
||||||
VMALOF f3, g52, T_0, T_0 \
|
|
||||||
VMALOF f3, g53, T_1, T_1 \
|
|
||||||
VMALOF f3, g54, T_2, T_2 \
|
|
||||||
VMALOF f3, g0, T_3, T_3 \
|
|
||||||
VMALOF f3, g1, T_4, T_4 \
|
|
||||||
VMALOF f4, g51, h0, h0 \
|
|
||||||
VMALOF f4, g52, h1, h1 \
|
|
||||||
VMALOF f4, g53, h2, h2 \
|
|
||||||
VMALOF f4, g54, h3, h3 \
|
|
||||||
VMALOF f4, g0, h4, h4 \
|
|
||||||
VAG T_0, h0, h0 \
|
|
||||||
VAG T_1, h1, h1 \
|
|
||||||
VAG T_2, h2, h2 \
|
|
||||||
VAG T_3, h3, h3 \
|
|
||||||
VAG T_4, h4, h4
|
|
||||||
|
|
||||||
// carry h0->h1 h3->h4, h1->h2 h4->h0, h0->h1 h2->h3, h3->h4
|
|
||||||
#define REDUCE(h0, h1, h2, h3, h4) \
|
|
||||||
VESRLG $26, h0, T_0 \
|
|
||||||
VESRLG $26, h3, T_1 \
|
|
||||||
VN MOD26, h0, h0 \
|
|
||||||
VN MOD26, h3, h3 \
|
|
||||||
VAG T_0, h1, h1 \
|
|
||||||
VAG T_1, h4, h4 \
|
|
||||||
VESRLG $26, h1, T_2 \
|
|
||||||
VESRLG $26, h4, T_3 \
|
|
||||||
VN MOD26, h1, h1 \
|
|
||||||
VN MOD26, h4, h4 \
|
|
||||||
VESLG $2, T_3, T_4 \
|
|
||||||
VAG T_3, T_4, T_4 \
|
|
||||||
VAG T_2, h2, h2 \
|
|
||||||
VAG T_4, h0, h0 \
|
|
||||||
VESRLG $26, h2, T_0 \
|
|
||||||
VESRLG $26, h0, T_1 \
|
|
||||||
VN MOD26, h2, h2 \
|
|
||||||
VN MOD26, h0, h0 \
|
|
||||||
VAG T_0, h3, h3 \
|
|
||||||
VAG T_1, h1, h1 \
|
|
||||||
VESRLG $26, h3, T_2 \
|
|
||||||
VN MOD26, h3, h3 \
|
|
||||||
VAG T_2, h4, h4
|
|
||||||
|
|
||||||
// expand in0 into d[0] and in1 into d[1]
|
|
||||||
#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \
|
|
||||||
VGBM $0x0707, d1 \ // d1=tmp
|
|
||||||
VPERM in0, in1, EX2, d4 \
|
|
||||||
VPERM in0, in1, EX0, d0 \
|
|
||||||
VPERM in0, in1, EX1, d2 \
|
|
||||||
VN d1, d4, d4 \
|
|
||||||
VESRLG $26, d0, d1 \
|
|
||||||
VESRLG $30, d2, d3 \
|
|
||||||
VESRLG $4, d2, d2 \
|
|
||||||
VN MOD26, d0, d0 \
|
|
||||||
VN MOD26, d1, d1 \
|
|
||||||
VN MOD26, d2, d2 \
|
|
||||||
VN MOD26, d3, d3
|
|
||||||
|
|
||||||
// pack h4:h0 into h1:h0 (no carry)
|
|
||||||
#define PACK(h0, h1, h2, h3, h4) \
|
|
||||||
VESLG $26, h1, h1 \
|
|
||||||
VESLG $26, h3, h3 \
|
|
||||||
VO h0, h1, h0 \
|
|
||||||
VO h2, h3, h2 \
|
|
||||||
VESLG $4, h2, h2 \
|
|
||||||
VLEIB $7, $48, h1 \
|
|
||||||
VSLB h1, h2, h2 \
|
|
||||||
VO h0, h2, h0 \
|
|
||||||
VLEIB $7, $104, h1 \
|
|
||||||
VSLB h1, h4, h3 \
|
|
||||||
VO h3, h0, h0 \
|
|
||||||
VLEIB $7, $24, h1 \
|
|
||||||
VSRLB h1, h4, h1
|
|
||||||
|
|
||||||
// if h > 2**130-5 then h -= 2**130-5
|
|
||||||
#define MOD(h0, h1, t0, t1, t2) \
|
|
||||||
VZERO t0 \
|
|
||||||
VLEIG $1, $5, t0 \
|
|
||||||
VACCQ h0, t0, t1 \
|
|
||||||
VAQ h0, t0, t0 \
|
|
||||||
VONE t2 \
|
|
||||||
VLEIG $1, $-4, t2 \
|
|
||||||
VAQ t2, t1, t1 \
|
|
||||||
VACCQ h1, t1, t1 \
|
|
||||||
VONE t2 \
|
|
||||||
VAQ t2, t1, t1 \
|
|
||||||
VN h0, t1, t2 \
|
|
||||||
VNC t0, t1, t1 \
|
|
||||||
VO t1, t2, h0
|
|
||||||
|
|
||||||
// func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
|
||||||
TEXT ·poly1305vx(SB), $0-32
|
|
||||||
// This code processes up to 2 blocks (32 bytes) per iteration
|
|
||||||
// using the algorithm described in:
|
|
||||||
// NEON crypto, Daniel J. Bernstein & Peter Schwabe
|
|
||||||
// https://cryptojedi.org/papers/neoncrypto-20120320.pdf
|
|
||||||
LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key
|
|
||||||
|
|
||||||
// load MOD26, EX0, EX1 and EX2
|
|
||||||
MOVD $·constants<>(SB), R5
|
|
||||||
VLM (R5), MOD26, EX2
|
|
||||||
|
|
||||||
// setup r
|
|
||||||
VL (R4), T_0
|
|
||||||
MOVD $·keyMask<>(SB), R6
|
|
||||||
VL (R6), T_1
|
|
||||||
VN T_0, T_1, T_0
|
|
||||||
EXPAND(T_0, T_0, R_0, R_1, R_2, R_3, R_4)
|
|
||||||
|
|
||||||
// setup r*5
|
|
||||||
VLEIG $0, $5, T_0
|
|
||||||
VLEIG $1, $5, T_0
|
|
||||||
|
|
||||||
// store r (for final block)
|
|
||||||
VMLOF T_0, R_1, R5SAVE_1
|
|
||||||
VMLOF T_0, R_2, R5SAVE_2
|
|
||||||
VMLOF T_0, R_3, R5SAVE_3
|
|
||||||
VMLOF T_0, R_4, R5SAVE_4
|
|
||||||
VLGVG $0, R_0, RSAVE_0
|
|
||||||
VLGVG $0, R_1, RSAVE_1
|
|
||||||
VLGVG $0, R_2, RSAVE_2
|
|
||||||
VLGVG $0, R_3, RSAVE_3
|
|
||||||
VLGVG $0, R_4, RSAVE_4
|
|
||||||
|
|
||||||
// skip r**2 calculation
|
|
||||||
CMPBLE R3, $16, skip
|
|
||||||
|
|
||||||
// calculate r**2
|
|
||||||
MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5SAVE_1, R5SAVE_2, R5SAVE_3, R5SAVE_4, H_0, H_1, H_2, H_3, H_4)
|
|
||||||
REDUCE(H_0, H_1, H_2, H_3, H_4)
|
|
||||||
VLEIG $0, $5, T_0
|
|
||||||
VLEIG $1, $5, T_0
|
|
||||||
VMLOF T_0, H_1, R5_1
|
|
||||||
VMLOF T_0, H_2, R5_2
|
|
||||||
VMLOF T_0, H_3, R5_3
|
|
||||||
VMLOF T_0, H_4, R5_4
|
|
||||||
VLR H_0, R_0
|
|
||||||
VLR H_1, R_1
|
|
||||||
VLR H_2, R_2
|
|
||||||
VLR H_3, R_3
|
|
||||||
VLR H_4, R_4
|
|
||||||
|
|
||||||
// initialize h
|
|
||||||
VZERO H_0
|
|
||||||
VZERO H_1
|
|
||||||
VZERO H_2
|
|
||||||
VZERO H_3
|
|
||||||
VZERO H_4
|
|
||||||
|
|
||||||
loop:
|
|
||||||
CMPBLE R3, $32, b2
|
|
||||||
VLM (R2), T_0, T_1
|
|
||||||
SUB $32, R3
|
|
||||||
MOVD $32(R2), R2
|
|
||||||
EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
|
|
||||||
VLEIB $4, $1, F_4
|
|
||||||
VLEIB $12, $1, F_4
|
|
||||||
|
|
||||||
multiply:
|
|
||||||
VAG H_0, F_0, F_0
|
|
||||||
VAG H_1, F_1, F_1
|
|
||||||
VAG H_2, F_2, F_2
|
|
||||||
VAG H_3, F_3, F_3
|
|
||||||
VAG H_4, F_4, F_4
|
|
||||||
MULTIPLY(F_0, F_1, F_2, F_3, F_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4)
|
|
||||||
REDUCE(H_0, H_1, H_2, H_3, H_4)
|
|
||||||
CMPBNE R3, $0, loop
|
|
||||||
|
|
||||||
finish:
|
|
||||||
// sum vectors
|
|
||||||
VZERO T_0
|
|
||||||
VSUMQG H_0, T_0, H_0
|
|
||||||
VSUMQG H_1, T_0, H_1
|
|
||||||
VSUMQG H_2, T_0, H_2
|
|
||||||
VSUMQG H_3, T_0, H_3
|
|
||||||
VSUMQG H_4, T_0, H_4
|
|
||||||
|
|
||||||
// h may be >= 2*(2**130-5) so we need to reduce it again
|
|
||||||
REDUCE(H_0, H_1, H_2, H_3, H_4)
|
|
||||||
|
|
||||||
// carry h1->h4
|
|
||||||
VESRLG $26, H_1, T_1
|
|
||||||
VN MOD26, H_1, H_1
|
|
||||||
VAQ T_1, H_2, H_2
|
|
||||||
VESRLG $26, H_2, T_2
|
|
||||||
VN MOD26, H_2, H_2
|
|
||||||
VAQ T_2, H_3, H_3
|
|
||||||
VESRLG $26, H_3, T_3
|
|
||||||
VN MOD26, H_3, H_3
|
|
||||||
VAQ T_3, H_4, H_4
|
|
||||||
|
|
||||||
// h is now < 2*(2**130-5)
|
|
||||||
// pack h into h1 (hi) and h0 (lo)
|
|
||||||
PACK(H_0, H_1, H_2, H_3, H_4)
|
|
||||||
|
|
||||||
// if h > 2**130-5 then h -= 2**130-5
|
|
||||||
MOD(H_0, H_1, T_0, T_1, T_2)
|
|
||||||
|
|
||||||
// h += s
|
|
||||||
MOVD $·bswapMask<>(SB), R5
|
|
||||||
VL (R5), T_1
|
|
||||||
VL 16(R4), T_0
|
|
||||||
VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big)
|
|
||||||
VAQ T_0, H_0, H_0
|
|
||||||
VPERM H_0, H_0, T_1, H_0 // reverse bytes (to little)
|
|
||||||
VST H_0, (R1)
|
|
||||||
|
|
||||||
RET
|
|
||||||
|
|
||||||
b2:
|
|
||||||
CMPBLE R3, $16, b1
|
|
||||||
|
|
||||||
// 2 blocks remaining
|
|
||||||
SUB $17, R3
|
|
||||||
VL (R2), T_0
|
|
||||||
VLL R3, 16(R2), T_1
|
|
||||||
ADD $1, R3
|
|
||||||
MOVBZ $1, R0
|
|
||||||
CMPBEQ R3, $16, 2(PC)
|
|
||||||
VLVGB R3, R0, T_1
|
|
||||||
EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
|
|
||||||
CMPBNE R3, $16, 2(PC)
|
|
||||||
VLEIB $12, $1, F_4
|
|
||||||
VLEIB $4, $1, F_4
|
|
||||||
|
|
||||||
// setup [r²,r]
|
|
||||||
VLVGG $1, RSAVE_0, R_0
|
|
||||||
VLVGG $1, RSAVE_1, R_1
|
|
||||||
VLVGG $1, RSAVE_2, R_2
|
|
||||||
VLVGG $1, RSAVE_3, R_3
|
|
||||||
VLVGG $1, RSAVE_4, R_4
|
|
||||||
VPDI $0, R5_1, R5SAVE_1, R5_1
|
|
||||||
VPDI $0, R5_2, R5SAVE_2, R5_2
|
|
||||||
VPDI $0, R5_3, R5SAVE_3, R5_3
|
|
||||||
VPDI $0, R5_4, R5SAVE_4, R5_4
|
|
||||||
|
|
||||||
MOVD $0, R3
|
|
||||||
BR multiply
|
|
||||||
|
|
||||||
skip:
|
|
||||||
VZERO H_0
|
|
||||||
VZERO H_1
|
|
||||||
VZERO H_2
|
|
||||||
VZERO H_3
|
|
||||||
VZERO H_4
|
|
||||||
|
|
||||||
CMPBEQ R3, $0, finish
|
|
||||||
|
|
||||||
b1:
|
|
||||||
// 1 block remaining
|
|
||||||
SUB $1, R3
|
|
||||||
VLL R3, (R2), T_0
|
|
||||||
ADD $1, R3
|
|
||||||
MOVBZ $1, R0
|
|
||||||
CMPBEQ R3, $16, 2(PC)
|
|
||||||
VLVGB R3, R0, T_0
|
|
||||||
VZERO T_1
|
|
||||||
EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
|
|
||||||
CMPBNE R3, $16, 2(PC)
|
|
||||||
VLEIB $4, $1, F_4
|
|
||||||
VLEIG $1, $1, R_0
|
|
||||||
VZERO R_1
|
|
||||||
VZERO R_2
|
|
||||||
VZERO R_3
|
|
||||||
VZERO R_4
|
|
||||||
VZERO R5_1
|
|
||||||
VZERO R5_2
|
|
||||||
VZERO R5_3
|
|
||||||
VZERO R5_4
|
|
||||||
|
|
||||||
// setup [r, 1]
|
|
||||||
VLVGG $0, RSAVE_0, R_0
|
|
||||||
VLVGG $0, RSAVE_1, R_1
|
|
||||||
VLVGG $0, RSAVE_2, R_2
|
|
||||||
VLVGG $0, RSAVE_3, R_3
|
|
||||||
VLVGG $0, RSAVE_4, R_4
|
|
||||||
VPDI $0, R5SAVE_1, R5_1, R5_1
|
|
||||||
VPDI $0, R5SAVE_2, R5_2, R5_2
|
|
||||||
VPDI $0, R5SAVE_3, R5_3, R5_3
|
|
||||||
VPDI $0, R5SAVE_4, R5_4, R5_4
|
|
||||||
|
|
||||||
MOVD $0, R3
|
|
||||||
BR multiply
|
|
||||||
|
|
||||||
TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1
|
|
||||||
MOVD $x-24(SP), R1
|
|
||||||
XC $24, 0(R1), 0(R1) // clear the storage
|
|
||||||
MOVD $2, R0 // R0 is the number of double words stored -1
|
|
||||||
WORD $0xB2B01000 // STFLE 0(R1)
|
|
||||||
XOR R0, R0 // reset the value of R0
|
|
||||||
MOVBZ z-8(SP), R1
|
|
||||||
AND $0x40, R1
|
|
||||||
BEQ novector
|
|
||||||
|
|
||||||
vectorinstalled:
|
|
||||||
// check if the vector instruction has been enabled
|
|
||||||
VLEIB $0, $0xF, V16
|
|
||||||
VLGVB $0, V16, R1
|
|
||||||
CMPBNE R1, $0xF, novector
|
|
||||||
MOVB $1, ret+0(FP) // have vx
|
|
||||||
RET
|
|
||||||
|
|
||||||
novector:
|
|
||||||
MOVB $0, ret+0(FP) // no vx
|
|
||||||
RET
|
|
||||||
931
vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s
generated
vendored
931
vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s
generated
vendored
|
|
@ -1,931 +0,0 @@
|
||||||
// Copyright 2018 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 s390x,go1.11,!gccgo,!appengine
|
|
||||||
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
// Implementation of Poly1305 using the vector facility (vx) and the VMSL instruction.
|
|
||||||
|
|
||||||
// constants
|
|
||||||
#define EX0 V1
|
|
||||||
#define EX1 V2
|
|
||||||
#define EX2 V3
|
|
||||||
|
|
||||||
// temporaries
|
|
||||||
#define T_0 V4
|
|
||||||
#define T_1 V5
|
|
||||||
#define T_2 V6
|
|
||||||
#define T_3 V7
|
|
||||||
#define T_4 V8
|
|
||||||
#define T_5 V9
|
|
||||||
#define T_6 V10
|
|
||||||
#define T_7 V11
|
|
||||||
#define T_8 V12
|
|
||||||
#define T_9 V13
|
|
||||||
#define T_10 V14
|
|
||||||
|
|
||||||
// r**2 & r**4
|
|
||||||
#define R_0 V15
|
|
||||||
#define R_1 V16
|
|
||||||
#define R_2 V17
|
|
||||||
#define R5_1 V18
|
|
||||||
#define R5_2 V19
|
|
||||||
// key (r)
|
|
||||||
#define RSAVE_0 R7
|
|
||||||
#define RSAVE_1 R8
|
|
||||||
#define RSAVE_2 R9
|
|
||||||
#define R5SAVE_1 R10
|
|
||||||
#define R5SAVE_2 R11
|
|
||||||
|
|
||||||
// message block
|
|
||||||
#define M0 V20
|
|
||||||
#define M1 V21
|
|
||||||
#define M2 V22
|
|
||||||
#define M3 V23
|
|
||||||
#define M4 V24
|
|
||||||
#define M5 V25
|
|
||||||
|
|
||||||
// accumulator
|
|
||||||
#define H0_0 V26
|
|
||||||
#define H1_0 V27
|
|
||||||
#define H2_0 V28
|
|
||||||
#define H0_1 V29
|
|
||||||
#define H1_1 V30
|
|
||||||
#define H2_1 V31
|
|
||||||
|
|
||||||
GLOBL ·keyMask<>(SB), RODATA, $16
|
|
||||||
DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f
|
|
||||||
DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f
|
|
||||||
|
|
||||||
GLOBL ·bswapMask<>(SB), RODATA, $16
|
|
||||||
DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908
|
|
||||||
DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100
|
|
||||||
|
|
||||||
GLOBL ·constants<>(SB), RODATA, $48
|
|
||||||
// EX0
|
|
||||||
DATA ·constants<>+0(SB)/8, $0x18191a1b1c1d1e1f
|
|
||||||
DATA ·constants<>+8(SB)/8, $0x0000050403020100
|
|
||||||
// EX1
|
|
||||||
DATA ·constants<>+16(SB)/8, $0x18191a1b1c1d1e1f
|
|
||||||
DATA ·constants<>+24(SB)/8, $0x00000a0908070605
|
|
||||||
// EX2
|
|
||||||
DATA ·constants<>+32(SB)/8, $0x18191a1b1c1d1e1f
|
|
||||||
DATA ·constants<>+40(SB)/8, $0x0000000f0e0d0c0b
|
|
||||||
|
|
||||||
GLOBL ·c<>(SB), RODATA, $48
|
|
||||||
// EX0
|
|
||||||
DATA ·c<>+0(SB)/8, $0x0000050403020100
|
|
||||||
DATA ·c<>+8(SB)/8, $0x0000151413121110
|
|
||||||
// EX1
|
|
||||||
DATA ·c<>+16(SB)/8, $0x00000a0908070605
|
|
||||||
DATA ·c<>+24(SB)/8, $0x00001a1918171615
|
|
||||||
// EX2
|
|
||||||
DATA ·c<>+32(SB)/8, $0x0000000f0e0d0c0b
|
|
||||||
DATA ·c<>+40(SB)/8, $0x0000001f1e1d1c1b
|
|
||||||
|
|
||||||
GLOBL ·reduce<>(SB), RODATA, $32
|
|
||||||
// 44 bit
|
|
||||||
DATA ·reduce<>+0(SB)/8, $0x0
|
|
||||||
DATA ·reduce<>+8(SB)/8, $0xfffffffffff
|
|
||||||
// 42 bit
|
|
||||||
DATA ·reduce<>+16(SB)/8, $0x0
|
|
||||||
DATA ·reduce<>+24(SB)/8, $0x3ffffffffff
|
|
||||||
|
|
||||||
// h = (f*g) % (2**130-5) [partial reduction]
|
|
||||||
// uses T_0...T_9 temporary registers
|
|
||||||
// input: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2
|
|
||||||
// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
|
|
||||||
// output: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2
|
|
||||||
#define MULTIPLY(m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
|
|
||||||
\ // Eliminate the dependency for the last 2 VMSLs
|
|
||||||
VMSLG m02_0, r_2, m4_2, m4_2 \
|
|
||||||
VMSLG m13_0, r_2, m5_2, m5_2 \ // 8 VMSLs pipelined
|
|
||||||
VMSLG m02_0, r_0, m4_0, m4_0 \
|
|
||||||
VMSLG m02_1, r5_2, V0, T_0 \
|
|
||||||
VMSLG m02_0, r_1, m4_1, m4_1 \
|
|
||||||
VMSLG m02_1, r_0, V0, T_1 \
|
|
||||||
VMSLG m02_1, r_1, V0, T_2 \
|
|
||||||
VMSLG m02_2, r5_1, V0, T_3 \
|
|
||||||
VMSLG m02_2, r5_2, V0, T_4 \
|
|
||||||
VMSLG m13_0, r_0, m5_0, m5_0 \
|
|
||||||
VMSLG m13_1, r5_2, V0, T_5 \
|
|
||||||
VMSLG m13_0, r_1, m5_1, m5_1 \
|
|
||||||
VMSLG m13_1, r_0, V0, T_6 \
|
|
||||||
VMSLG m13_1, r_1, V0, T_7 \
|
|
||||||
VMSLG m13_2, r5_1, V0, T_8 \
|
|
||||||
VMSLG m13_2, r5_2, V0, T_9 \
|
|
||||||
VMSLG m02_2, r_0, m4_2, m4_2 \
|
|
||||||
VMSLG m13_2, r_0, m5_2, m5_2 \
|
|
||||||
VAQ m4_0, T_0, m02_0 \
|
|
||||||
VAQ m4_1, T_1, m02_1 \
|
|
||||||
VAQ m5_0, T_5, m13_0 \
|
|
||||||
VAQ m5_1, T_6, m13_1 \
|
|
||||||
VAQ m02_0, T_3, m02_0 \
|
|
||||||
VAQ m02_1, T_4, m02_1 \
|
|
||||||
VAQ m13_0, T_8, m13_0 \
|
|
||||||
VAQ m13_1, T_9, m13_1 \
|
|
||||||
VAQ m4_2, T_2, m02_2 \
|
|
||||||
VAQ m5_2, T_7, m13_2 \
|
|
||||||
|
|
||||||
// SQUARE uses three limbs of r and r_2*5 to output square of r
|
|
||||||
// uses T_1, T_5 and T_7 temporary registers
|
|
||||||
// input: r_0, r_1, r_2, r5_2
|
|
||||||
// temp: TEMP0, TEMP1, TEMP2
|
|
||||||
// output: p0, p1, p2
|
|
||||||
#define SQUARE(r_0, r_1, r_2, r5_2, p0, p1, p2, TEMP0, TEMP1, TEMP2) \
|
|
||||||
VMSLG r_0, r_0, p0, p0 \
|
|
||||||
VMSLG r_1, r5_2, V0, TEMP0 \
|
|
||||||
VMSLG r_2, r5_2, p1, p1 \
|
|
||||||
VMSLG r_0, r_1, V0, TEMP1 \
|
|
||||||
VMSLG r_1, r_1, p2, p2 \
|
|
||||||
VMSLG r_0, r_2, V0, TEMP2 \
|
|
||||||
VAQ TEMP0, p0, p0 \
|
|
||||||
VAQ TEMP1, p1, p1 \
|
|
||||||
VAQ TEMP2, p2, p2 \
|
|
||||||
VAQ TEMP0, p0, p0 \
|
|
||||||
VAQ TEMP1, p1, p1 \
|
|
||||||
VAQ TEMP2, p2, p2 \
|
|
||||||
|
|
||||||
// carry h0->h1->h2->h0 || h3->h4->h5->h3
|
|
||||||
// uses T_2, T_4, T_5, T_7, T_8, T_9
|
|
||||||
// t6, t7, t8, t9, t10, t11
|
|
||||||
// input: h0, h1, h2, h3, h4, h5
|
|
||||||
// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11
|
|
||||||
// output: h0, h1, h2, h3, h4, h5
|
|
||||||
#define REDUCE(h0, h1, h2, h3, h4, h5, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \
|
|
||||||
VLM (R12), t6, t7 \ // 44 and 42 bit clear mask
|
|
||||||
VLEIB $7, $0x28, t10 \ // 5 byte shift mask
|
|
||||||
VREPIB $4, t8 \ // 4 bit shift mask
|
|
||||||
VREPIB $2, t11 \ // 2 bit shift mask
|
|
||||||
VSRLB t10, h0, t0 \ // h0 byte shift
|
|
||||||
VSRLB t10, h1, t1 \ // h1 byte shift
|
|
||||||
VSRLB t10, h2, t2 \ // h2 byte shift
|
|
||||||
VSRLB t10, h3, t3 \ // h3 byte shift
|
|
||||||
VSRLB t10, h4, t4 \ // h4 byte shift
|
|
||||||
VSRLB t10, h5, t5 \ // h5 byte shift
|
|
||||||
VSRL t8, t0, t0 \ // h0 bit shift
|
|
||||||
VSRL t8, t1, t1 \ // h2 bit shift
|
|
||||||
VSRL t11, t2, t2 \ // h2 bit shift
|
|
||||||
VSRL t8, t3, t3 \ // h3 bit shift
|
|
||||||
VSRL t8, t4, t4 \ // h4 bit shift
|
|
||||||
VESLG $2, t2, t9 \ // h2 carry x5
|
|
||||||
VSRL t11, t5, t5 \ // h5 bit shift
|
|
||||||
VN t6, h0, h0 \ // h0 clear carry
|
|
||||||
VAQ t2, t9, t2 \ // h2 carry x5
|
|
||||||
VESLG $2, t5, t9 \ // h5 carry x5
|
|
||||||
VN t6, h1, h1 \ // h1 clear carry
|
|
||||||
VN t7, h2, h2 \ // h2 clear carry
|
|
||||||
VAQ t5, t9, t5 \ // h5 carry x5
|
|
||||||
VN t6, h3, h3 \ // h3 clear carry
|
|
||||||
VN t6, h4, h4 \ // h4 clear carry
|
|
||||||
VN t7, h5, h5 \ // h5 clear carry
|
|
||||||
VAQ t0, h1, h1 \ // h0->h1
|
|
||||||
VAQ t3, h4, h4 \ // h3->h4
|
|
||||||
VAQ t1, h2, h2 \ // h1->h2
|
|
||||||
VAQ t4, h5, h5 \ // h4->h5
|
|
||||||
VAQ t2, h0, h0 \ // h2->h0
|
|
||||||
VAQ t5, h3, h3 \ // h5->h3
|
|
||||||
VREPG $1, t6, t6 \ // 44 and 42 bit masks across both halves
|
|
||||||
VREPG $1, t7, t7 \
|
|
||||||
VSLDB $8, h0, h0, h0 \ // set up [h0/1/2, h3/4/5]
|
|
||||||
VSLDB $8, h1, h1, h1 \
|
|
||||||
VSLDB $8, h2, h2, h2 \
|
|
||||||
VO h0, h3, h3 \
|
|
||||||
VO h1, h4, h4 \
|
|
||||||
VO h2, h5, h5 \
|
|
||||||
VESRLG $44, h3, t0 \ // 44 bit shift right
|
|
||||||
VESRLG $44, h4, t1 \
|
|
||||||
VESRLG $42, h5, t2 \
|
|
||||||
VN t6, h3, h3 \ // clear carry bits
|
|
||||||
VN t6, h4, h4 \
|
|
||||||
VN t7, h5, h5 \
|
|
||||||
VESLG $2, t2, t9 \ // multiply carry by 5
|
|
||||||
VAQ t9, t2, t2 \
|
|
||||||
VAQ t0, h4, h4 \
|
|
||||||
VAQ t1, h5, h5 \
|
|
||||||
VAQ t2, h3, h3 \
|
|
||||||
|
|
||||||
// carry h0->h1->h2->h0
|
|
||||||
// input: h0, h1, h2
|
|
||||||
// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8
|
|
||||||
// output: h0, h1, h2
|
|
||||||
#define REDUCE2(h0, h1, h2, t0, t1, t2, t3, t4, t5, t6, t7, t8) \
|
|
||||||
VLEIB $7, $0x28, t3 \ // 5 byte shift mask
|
|
||||||
VREPIB $4, t4 \ // 4 bit shift mask
|
|
||||||
VREPIB $2, t7 \ // 2 bit shift mask
|
|
||||||
VGBM $0x003F, t5 \ // mask to clear carry bits
|
|
||||||
VSRLB t3, h0, t0 \
|
|
||||||
VSRLB t3, h1, t1 \
|
|
||||||
VSRLB t3, h2, t2 \
|
|
||||||
VESRLG $4, t5, t5 \ // 44 bit clear mask
|
|
||||||
VSRL t4, t0, t0 \
|
|
||||||
VSRL t4, t1, t1 \
|
|
||||||
VSRL t7, t2, t2 \
|
|
||||||
VESRLG $2, t5, t6 \ // 42 bit clear mask
|
|
||||||
VESLG $2, t2, t8 \
|
|
||||||
VAQ t8, t2, t2 \
|
|
||||||
VN t5, h0, h0 \
|
|
||||||
VN t5, h1, h1 \
|
|
||||||
VN t6, h2, h2 \
|
|
||||||
VAQ t0, h1, h1 \
|
|
||||||
VAQ t1, h2, h2 \
|
|
||||||
VAQ t2, h0, h0 \
|
|
||||||
VSRLB t3, h0, t0 \
|
|
||||||
VSRLB t3, h1, t1 \
|
|
||||||
VSRLB t3, h2, t2 \
|
|
||||||
VSRL t4, t0, t0 \
|
|
||||||
VSRL t4, t1, t1 \
|
|
||||||
VSRL t7, t2, t2 \
|
|
||||||
VN t5, h0, h0 \
|
|
||||||
VN t5, h1, h1 \
|
|
||||||
VESLG $2, t2, t8 \
|
|
||||||
VN t6, h2, h2 \
|
|
||||||
VAQ t0, h1, h1 \
|
|
||||||
VAQ t8, t2, t2 \
|
|
||||||
VAQ t1, h2, h2 \
|
|
||||||
VAQ t2, h0, h0 \
|
|
||||||
|
|
||||||
// expands two message blocks into the lower halfs of the d registers
|
|
||||||
// moves the contents of the d registers into upper halfs
|
|
||||||
// input: in1, in2, d0, d1, d2, d3, d4, d5
|
|
||||||
// temp: TEMP0, TEMP1, TEMP2, TEMP3
|
|
||||||
// output: d0, d1, d2, d3, d4, d5
|
|
||||||
#define EXPACC(in1, in2, d0, d1, d2, d3, d4, d5, TEMP0, TEMP1, TEMP2, TEMP3) \
|
|
||||||
VGBM $0xff3f, TEMP0 \
|
|
||||||
VGBM $0xff1f, TEMP1 \
|
|
||||||
VESLG $4, d1, TEMP2 \
|
|
||||||
VESLG $4, d4, TEMP3 \
|
|
||||||
VESRLG $4, TEMP0, TEMP0 \
|
|
||||||
VPERM in1, d0, EX0, d0 \
|
|
||||||
VPERM in2, d3, EX0, d3 \
|
|
||||||
VPERM in1, d2, EX2, d2 \
|
|
||||||
VPERM in2, d5, EX2, d5 \
|
|
||||||
VPERM in1, TEMP2, EX1, d1 \
|
|
||||||
VPERM in2, TEMP3, EX1, d4 \
|
|
||||||
VN TEMP0, d0, d0 \
|
|
||||||
VN TEMP0, d3, d3 \
|
|
||||||
VESRLG $4, d1, d1 \
|
|
||||||
VESRLG $4, d4, d4 \
|
|
||||||
VN TEMP1, d2, d2 \
|
|
||||||
VN TEMP1, d5, d5 \
|
|
||||||
VN TEMP0, d1, d1 \
|
|
||||||
VN TEMP0, d4, d4 \
|
|
||||||
|
|
||||||
// expands one message block into the lower halfs of the d registers
|
|
||||||
// moves the contents of the d registers into upper halfs
|
|
||||||
// input: in, d0, d1, d2
|
|
||||||
// temp: TEMP0, TEMP1, TEMP2
|
|
||||||
// output: d0, d1, d2
|
|
||||||
#define EXPACC2(in, d0, d1, d2, TEMP0, TEMP1, TEMP2) \
|
|
||||||
VGBM $0xff3f, TEMP0 \
|
|
||||||
VESLG $4, d1, TEMP2 \
|
|
||||||
VGBM $0xff1f, TEMP1 \
|
|
||||||
VPERM in, d0, EX0, d0 \
|
|
||||||
VESRLG $4, TEMP0, TEMP0 \
|
|
||||||
VPERM in, d2, EX2, d2 \
|
|
||||||
VPERM in, TEMP2, EX1, d1 \
|
|
||||||
VN TEMP0, d0, d0 \
|
|
||||||
VN TEMP1, d2, d2 \
|
|
||||||
VESRLG $4, d1, d1 \
|
|
||||||
VN TEMP0, d1, d1 \
|
|
||||||
|
|
||||||
// pack h2:h0 into h1:h0 (no carry)
|
|
||||||
// input: h0, h1, h2
|
|
||||||
// output: h0, h1, h2
|
|
||||||
#define PACK(h0, h1, h2) \
|
|
||||||
VMRLG h1, h2, h2 \ // copy h1 to upper half h2
|
|
||||||
VESLG $44, h1, h1 \ // shift limb 1 44 bits, leaving 20
|
|
||||||
VO h0, h1, h0 \ // combine h0 with 20 bits from limb 1
|
|
||||||
VESRLG $20, h2, h1 \ // put top 24 bits of limb 1 into h1
|
|
||||||
VLEIG $1, $0, h1 \ // clear h2 stuff from lower half of h1
|
|
||||||
VO h0, h1, h0 \ // h0 now has 88 bits (limb 0 and 1)
|
|
||||||
VLEIG $0, $0, h2 \ // clear upper half of h2
|
|
||||||
VESRLG $40, h2, h1 \ // h1 now has upper two bits of result
|
|
||||||
VLEIB $7, $88, h1 \ // for byte shift (11 bytes)
|
|
||||||
VSLB h1, h2, h2 \ // shift h2 11 bytes to the left
|
|
||||||
VO h0, h2, h0 \ // combine h0 with 20 bits from limb 1
|
|
||||||
VLEIG $0, $0, h1 \ // clear upper half of h1
|
|
||||||
|
|
||||||
// if h > 2**130-5 then h -= 2**130-5
|
|
||||||
// input: h0, h1
|
|
||||||
// temp: t0, t1, t2
|
|
||||||
// output: h0
|
|
||||||
#define MOD(h0, h1, t0, t1, t2) \
|
|
||||||
VZERO t0 \
|
|
||||||
VLEIG $1, $5, t0 \
|
|
||||||
VACCQ h0, t0, t1 \
|
|
||||||
VAQ h0, t0, t0 \
|
|
||||||
VONE t2 \
|
|
||||||
VLEIG $1, $-4, t2 \
|
|
||||||
VAQ t2, t1, t1 \
|
|
||||||
VACCQ h1, t1, t1 \
|
|
||||||
VONE t2 \
|
|
||||||
VAQ t2, t1, t1 \
|
|
||||||
VN h0, t1, t2 \
|
|
||||||
VNC t0, t1, t1 \
|
|
||||||
VO t1, t2, h0 \
|
|
||||||
|
|
||||||
// func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
|
||||||
TEXT ·poly1305vmsl(SB), $0-32
|
|
||||||
// This code processes 6 + up to 4 blocks (32 bytes) per iteration
|
|
||||||
// using the algorithm described in:
|
|
||||||
// NEON crypto, Daniel J. Bernstein & Peter Schwabe
|
|
||||||
// https://cryptojedi.org/papers/neoncrypto-20120320.pdf
|
|
||||||
// And as moddified for VMSL as described in
|
|
||||||
// Accelerating Poly1305 Cryptographic Message Authentication on the z14
|
|
||||||
// O'Farrell et al, CASCON 2017, p48-55
|
|
||||||
// https://ibm.ent.box.com/s/jf9gedj0e9d2vjctfyh186shaztavnht
|
|
||||||
|
|
||||||
LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key
|
|
||||||
VZERO V0 // c
|
|
||||||
|
|
||||||
// load EX0, EX1 and EX2
|
|
||||||
MOVD $·constants<>(SB), R5
|
|
||||||
VLM (R5), EX0, EX2 // c
|
|
||||||
|
|
||||||
// setup r
|
|
||||||
VL (R4), T_0
|
|
||||||
MOVD $·keyMask<>(SB), R6
|
|
||||||
VL (R6), T_1
|
|
||||||
VN T_0, T_1, T_0
|
|
||||||
VZERO T_2 // limbs for r
|
|
||||||
VZERO T_3
|
|
||||||
VZERO T_4
|
|
||||||
EXPACC2(T_0, T_2, T_3, T_4, T_1, T_5, T_7)
|
|
||||||
|
|
||||||
// T_2, T_3, T_4: [0, r]
|
|
||||||
|
|
||||||
// setup r*20
|
|
||||||
VLEIG $0, $0, T_0
|
|
||||||
VLEIG $1, $20, T_0 // T_0: [0, 20]
|
|
||||||
VZERO T_5
|
|
||||||
VZERO T_6
|
|
||||||
VMSLG T_0, T_3, T_5, T_5
|
|
||||||
VMSLG T_0, T_4, T_6, T_6
|
|
||||||
|
|
||||||
// store r for final block in GR
|
|
||||||
VLGVG $1, T_2, RSAVE_0 // c
|
|
||||||
VLGVG $1, T_3, RSAVE_1 // c
|
|
||||||
VLGVG $1, T_4, RSAVE_2 // c
|
|
||||||
VLGVG $1, T_5, R5SAVE_1 // c
|
|
||||||
VLGVG $1, T_6, R5SAVE_2 // c
|
|
||||||
|
|
||||||
// initialize h
|
|
||||||
VZERO H0_0
|
|
||||||
VZERO H1_0
|
|
||||||
VZERO H2_0
|
|
||||||
VZERO H0_1
|
|
||||||
VZERO H1_1
|
|
||||||
VZERO H2_1
|
|
||||||
|
|
||||||
// initialize pointer for reduce constants
|
|
||||||
MOVD $·reduce<>(SB), R12
|
|
||||||
|
|
||||||
// calculate r**2 and 20*(r**2)
|
|
||||||
VZERO R_0
|
|
||||||
VZERO R_1
|
|
||||||
VZERO R_2
|
|
||||||
SQUARE(T_2, T_3, T_4, T_6, R_0, R_1, R_2, T_1, T_5, T_7)
|
|
||||||
REDUCE2(R_0, R_1, R_2, M0, M1, M2, M3, M4, R5_1, R5_2, M5, T_1)
|
|
||||||
VZERO R5_1
|
|
||||||
VZERO R5_2
|
|
||||||
VMSLG T_0, R_1, R5_1, R5_1
|
|
||||||
VMSLG T_0, R_2, R5_2, R5_2
|
|
||||||
|
|
||||||
// skip r**4 calculation if 3 blocks or less
|
|
||||||
CMPBLE R3, $48, b4
|
|
||||||
|
|
||||||
// calculate r**4 and 20*(r**4)
|
|
||||||
VZERO T_8
|
|
||||||
VZERO T_9
|
|
||||||
VZERO T_10
|
|
||||||
SQUARE(R_0, R_1, R_2, R5_2, T_8, T_9, T_10, T_1, T_5, T_7)
|
|
||||||
REDUCE2(T_8, T_9, T_10, M0, M1, M2, M3, M4, T_2, T_3, M5, T_1)
|
|
||||||
VZERO T_2
|
|
||||||
VZERO T_3
|
|
||||||
VMSLG T_0, T_9, T_2, T_2
|
|
||||||
VMSLG T_0, T_10, T_3, T_3
|
|
||||||
|
|
||||||
// put r**2 to the right and r**4 to the left of R_0, R_1, R_2
|
|
||||||
VSLDB $8, T_8, T_8, T_8
|
|
||||||
VSLDB $8, T_9, T_9, T_9
|
|
||||||
VSLDB $8, T_10, T_10, T_10
|
|
||||||
VSLDB $8, T_2, T_2, T_2
|
|
||||||
VSLDB $8, T_3, T_3, T_3
|
|
||||||
|
|
||||||
VO T_8, R_0, R_0
|
|
||||||
VO T_9, R_1, R_1
|
|
||||||
VO T_10, R_2, R_2
|
|
||||||
VO T_2, R5_1, R5_1
|
|
||||||
VO T_3, R5_2, R5_2
|
|
||||||
|
|
||||||
CMPBLE R3, $80, load // less than or equal to 5 blocks in message
|
|
||||||
|
|
||||||
// 6(or 5+1) blocks
|
|
||||||
SUB $81, R3
|
|
||||||
VLM (R2), M0, M4
|
|
||||||
VLL R3, 80(R2), M5
|
|
||||||
ADD $1, R3
|
|
||||||
MOVBZ $1, R0
|
|
||||||
CMPBGE R3, $16, 2(PC)
|
|
||||||
VLVGB R3, R0, M5
|
|
||||||
MOVD $96(R2), R2
|
|
||||||
EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
|
|
||||||
EXPACC(M2, M3, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
|
|
||||||
VLEIB $2, $1, H2_0
|
|
||||||
VLEIB $2, $1, H2_1
|
|
||||||
VLEIB $10, $1, H2_0
|
|
||||||
VLEIB $10, $1, H2_1
|
|
||||||
|
|
||||||
VZERO M0
|
|
||||||
VZERO M1
|
|
||||||
VZERO M2
|
|
||||||
VZERO M3
|
|
||||||
VZERO T_4
|
|
||||||
VZERO T_10
|
|
||||||
EXPACC(M4, M5, M0, M1, M2, M3, T_4, T_10, T_0, T_1, T_2, T_3)
|
|
||||||
VLR T_4, M4
|
|
||||||
VLEIB $10, $1, M2
|
|
||||||
CMPBLT R3, $16, 2(PC)
|
|
||||||
VLEIB $10, $1, T_10
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9)
|
|
||||||
VMRHG V0, H0_1, H0_0
|
|
||||||
VMRHG V0, H1_1, H1_0
|
|
||||||
VMRHG V0, H2_1, H2_0
|
|
||||||
VMRLG V0, H0_1, H0_1
|
|
||||||
VMRLG V0, H1_1, H1_1
|
|
||||||
VMRLG V0, H2_1, H2_1
|
|
||||||
|
|
||||||
SUB $16, R3
|
|
||||||
CMPBLE R3, $0, square
|
|
||||||
|
|
||||||
load:
|
|
||||||
// load EX0, EX1 and EX2
|
|
||||||
MOVD $·c<>(SB), R5
|
|
||||||
VLM (R5), EX0, EX2
|
|
||||||
|
|
||||||
loop:
|
|
||||||
CMPBLE R3, $64, add // b4 // last 4 or less blocks left
|
|
||||||
|
|
||||||
// next 4 full blocks
|
|
||||||
VLM (R2), M2, M5
|
|
||||||
SUB $64, R3
|
|
||||||
MOVD $64(R2), R2
|
|
||||||
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, T_0, T_1, T_3, T_4, T_5, T_2, T_7, T_8, T_9)
|
|
||||||
|
|
||||||
// expacc in-lined to create [m2, m3] limbs
|
|
||||||
VGBM $0x3f3f, T_0 // 44 bit clear mask
|
|
||||||
VGBM $0x1f1f, T_1 // 40 bit clear mask
|
|
||||||
VPERM M2, M3, EX0, T_3
|
|
||||||
VESRLG $4, T_0, T_0 // 44 bit clear mask ready
|
|
||||||
VPERM M2, M3, EX1, T_4
|
|
||||||
VPERM M2, M3, EX2, T_5
|
|
||||||
VN T_0, T_3, T_3
|
|
||||||
VESRLG $4, T_4, T_4
|
|
||||||
VN T_1, T_5, T_5
|
|
||||||
VN T_0, T_4, T_4
|
|
||||||
VMRHG H0_1, T_3, H0_0
|
|
||||||
VMRHG H1_1, T_4, H1_0
|
|
||||||
VMRHG H2_1, T_5, H2_0
|
|
||||||
VMRLG H0_1, T_3, H0_1
|
|
||||||
VMRLG H1_1, T_4, H1_1
|
|
||||||
VMRLG H2_1, T_5, H2_1
|
|
||||||
VLEIB $10, $1, H2_0
|
|
||||||
VLEIB $10, $1, H2_1
|
|
||||||
VPERM M4, M5, EX0, T_3
|
|
||||||
VPERM M4, M5, EX1, T_4
|
|
||||||
VPERM M4, M5, EX2, T_5
|
|
||||||
VN T_0, T_3, T_3
|
|
||||||
VESRLG $4, T_4, T_4
|
|
||||||
VN T_1, T_5, T_5
|
|
||||||
VN T_0, T_4, T_4
|
|
||||||
VMRHG V0, T_3, M0
|
|
||||||
VMRHG V0, T_4, M1
|
|
||||||
VMRHG V0, T_5, M2
|
|
||||||
VMRLG V0, T_3, M3
|
|
||||||
VMRLG V0, T_4, M4
|
|
||||||
VMRLG V0, T_5, M5
|
|
||||||
VLEIB $10, $1, M2
|
|
||||||
VLEIB $10, $1, M5
|
|
||||||
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
CMPBNE R3, $0, loop
|
|
||||||
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
|
|
||||||
VMRHG V0, H0_1, H0_0
|
|
||||||
VMRHG V0, H1_1, H1_0
|
|
||||||
VMRHG V0, H2_1, H2_0
|
|
||||||
VMRLG V0, H0_1, H0_1
|
|
||||||
VMRLG V0, H1_1, H1_1
|
|
||||||
VMRLG V0, H2_1, H2_1
|
|
||||||
|
|
||||||
// load EX0, EX1, EX2
|
|
||||||
MOVD $·constants<>(SB), R5
|
|
||||||
VLM (R5), EX0, EX2
|
|
||||||
|
|
||||||
// sum vectors
|
|
||||||
VAQ H0_0, H0_1, H0_0
|
|
||||||
VAQ H1_0, H1_1, H1_0
|
|
||||||
VAQ H2_0, H2_1, H2_0
|
|
||||||
|
|
||||||
// h may be >= 2*(2**130-5) so we need to reduce it again
|
|
||||||
// M0...M4 are used as temps here
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
|
|
||||||
|
|
||||||
next: // carry h1->h2
|
|
||||||
VLEIB $7, $0x28, T_1
|
|
||||||
VREPIB $4, T_2
|
|
||||||
VGBM $0x003F, T_3
|
|
||||||
VESRLG $4, T_3
|
|
||||||
|
|
||||||
// byte shift
|
|
||||||
VSRLB T_1, H1_0, T_4
|
|
||||||
|
|
||||||
// bit shift
|
|
||||||
VSRL T_2, T_4, T_4
|
|
||||||
|
|
||||||
// clear h1 carry bits
|
|
||||||
VN T_3, H1_0, H1_0
|
|
||||||
|
|
||||||
// add carry
|
|
||||||
VAQ T_4, H2_0, H2_0
|
|
||||||
|
|
||||||
// h is now < 2*(2**130-5)
|
|
||||||
// pack h into h1 (hi) and h0 (lo)
|
|
||||||
PACK(H0_0, H1_0, H2_0)
|
|
||||||
|
|
||||||
// if h > 2**130-5 then h -= 2**130-5
|
|
||||||
MOD(H0_0, H1_0, T_0, T_1, T_2)
|
|
||||||
|
|
||||||
// h += s
|
|
||||||
MOVD $·bswapMask<>(SB), R5
|
|
||||||
VL (R5), T_1
|
|
||||||
VL 16(R4), T_0
|
|
||||||
VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big)
|
|
||||||
VAQ T_0, H0_0, H0_0
|
|
||||||
VPERM H0_0, H0_0, T_1, H0_0 // reverse bytes (to little)
|
|
||||||
VST H0_0, (R1)
|
|
||||||
RET
|
|
||||||
|
|
||||||
add:
|
|
||||||
// load EX0, EX1, EX2
|
|
||||||
MOVD $·constants<>(SB), R5
|
|
||||||
VLM (R5), EX0, EX2
|
|
||||||
|
|
||||||
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
|
|
||||||
VMRHG V0, H0_1, H0_0
|
|
||||||
VMRHG V0, H1_1, H1_0
|
|
||||||
VMRHG V0, H2_1, H2_0
|
|
||||||
VMRLG V0, H0_1, H0_1
|
|
||||||
VMRLG V0, H1_1, H1_1
|
|
||||||
VMRLG V0, H2_1, H2_1
|
|
||||||
CMPBLE R3, $64, b4
|
|
||||||
|
|
||||||
b4:
|
|
||||||
CMPBLE R3, $48, b3 // 3 blocks or less
|
|
||||||
|
|
||||||
// 4(3+1) blocks remaining
|
|
||||||
SUB $49, R3
|
|
||||||
VLM (R2), M0, M2
|
|
||||||
VLL R3, 48(R2), M3
|
|
||||||
ADD $1, R3
|
|
||||||
MOVBZ $1, R0
|
|
||||||
CMPBEQ R3, $16, 2(PC)
|
|
||||||
VLVGB R3, R0, M3
|
|
||||||
MOVD $64(R2), R2
|
|
||||||
EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
|
|
||||||
VLEIB $10, $1, H2_0
|
|
||||||
VLEIB $10, $1, H2_1
|
|
||||||
VZERO M0
|
|
||||||
VZERO M1
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
VZERO T_4
|
|
||||||
VZERO T_10
|
|
||||||
EXPACC(M2, M3, M0, M1, M4, M5, T_4, T_10, T_0, T_1, T_2, T_3)
|
|
||||||
VLR T_4, M2
|
|
||||||
VLEIB $10, $1, M4
|
|
||||||
CMPBNE R3, $16, 2(PC)
|
|
||||||
VLEIB $10, $1, T_10
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M4, M5, M2, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
|
|
||||||
VMRHG V0, H0_1, H0_0
|
|
||||||
VMRHG V0, H1_1, H1_0
|
|
||||||
VMRHG V0, H2_1, H2_0
|
|
||||||
VMRLG V0, H0_1, H0_1
|
|
||||||
VMRLG V0, H1_1, H1_1
|
|
||||||
VMRLG V0, H2_1, H2_1
|
|
||||||
SUB $16, R3
|
|
||||||
CMPBLE R3, $0, square // this condition must always hold true!
|
|
||||||
|
|
||||||
b3:
|
|
||||||
CMPBLE R3, $32, b2
|
|
||||||
|
|
||||||
// 3 blocks remaining
|
|
||||||
|
|
||||||
// setup [r²,r]
|
|
||||||
VSLDB $8, R_0, R_0, R_0
|
|
||||||
VSLDB $8, R_1, R_1, R_1
|
|
||||||
VSLDB $8, R_2, R_2, R_2
|
|
||||||
VSLDB $8, R5_1, R5_1, R5_1
|
|
||||||
VSLDB $8, R5_2, R5_2, R5_2
|
|
||||||
|
|
||||||
VLVGG $1, RSAVE_0, R_0
|
|
||||||
VLVGG $1, RSAVE_1, R_1
|
|
||||||
VLVGG $1, RSAVE_2, R_2
|
|
||||||
VLVGG $1, R5SAVE_1, R5_1
|
|
||||||
VLVGG $1, R5SAVE_2, R5_2
|
|
||||||
|
|
||||||
// setup [h0, h1]
|
|
||||||
VSLDB $8, H0_0, H0_0, H0_0
|
|
||||||
VSLDB $8, H1_0, H1_0, H1_0
|
|
||||||
VSLDB $8, H2_0, H2_0, H2_0
|
|
||||||
VO H0_1, H0_0, H0_0
|
|
||||||
VO H1_1, H1_0, H1_0
|
|
||||||
VO H2_1, H2_0, H2_0
|
|
||||||
VZERO H0_1
|
|
||||||
VZERO H1_1
|
|
||||||
VZERO H2_1
|
|
||||||
|
|
||||||
VZERO M0
|
|
||||||
VZERO M1
|
|
||||||
VZERO M2
|
|
||||||
VZERO M3
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
|
|
||||||
// H*[r**2, r]
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, T_10, M5)
|
|
||||||
|
|
||||||
SUB $33, R3
|
|
||||||
VLM (R2), M0, M1
|
|
||||||
VLL R3, 32(R2), M2
|
|
||||||
ADD $1, R3
|
|
||||||
MOVBZ $1, R0
|
|
||||||
CMPBEQ R3, $16, 2(PC)
|
|
||||||
VLVGB R3, R0, M2
|
|
||||||
|
|
||||||
// H += m0
|
|
||||||
VZERO T_1
|
|
||||||
VZERO T_2
|
|
||||||
VZERO T_3
|
|
||||||
EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)
|
|
||||||
VLEIB $10, $1, T_3
|
|
||||||
VAG H0_0, T_1, H0_0
|
|
||||||
VAG H1_0, T_2, H1_0
|
|
||||||
VAG H2_0, T_3, H2_0
|
|
||||||
|
|
||||||
VZERO M0
|
|
||||||
VZERO M3
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
VZERO T_10
|
|
||||||
|
|
||||||
// (H+m0)*r
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M3, M4, M5, V0, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_10, H0_1, H1_1, H2_1, T_9)
|
|
||||||
|
|
||||||
// H += m1
|
|
||||||
VZERO V0
|
|
||||||
VZERO T_1
|
|
||||||
VZERO T_2
|
|
||||||
VZERO T_3
|
|
||||||
EXPACC2(M1, T_1, T_2, T_3, T_4, T_5, T_6)
|
|
||||||
VLEIB $10, $1, T_3
|
|
||||||
VAQ H0_0, T_1, H0_0
|
|
||||||
VAQ H1_0, T_2, H1_0
|
|
||||||
VAQ H2_0, T_3, H2_0
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10)
|
|
||||||
|
|
||||||
// [H, m2] * [r**2, r]
|
|
||||||
EXPACC2(M2, H0_0, H1_0, H2_0, T_1, T_2, T_3)
|
|
||||||
CMPBNE R3, $16, 2(PC)
|
|
||||||
VLEIB $10, $1, H2_0
|
|
||||||
VZERO M0
|
|
||||||
VZERO M1
|
|
||||||
VZERO M2
|
|
||||||
VZERO M3
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, M5, T_10)
|
|
||||||
SUB $16, R3
|
|
||||||
CMPBLE R3, $0, next // this condition must always hold true!
|
|
||||||
|
|
||||||
b2:
|
|
||||||
CMPBLE R3, $16, b1
|
|
||||||
|
|
||||||
// 2 blocks remaining
|
|
||||||
|
|
||||||
// setup [r²,r]
|
|
||||||
VSLDB $8, R_0, R_0, R_0
|
|
||||||
VSLDB $8, R_1, R_1, R_1
|
|
||||||
VSLDB $8, R_2, R_2, R_2
|
|
||||||
VSLDB $8, R5_1, R5_1, R5_1
|
|
||||||
VSLDB $8, R5_2, R5_2, R5_2
|
|
||||||
|
|
||||||
VLVGG $1, RSAVE_0, R_0
|
|
||||||
VLVGG $1, RSAVE_1, R_1
|
|
||||||
VLVGG $1, RSAVE_2, R_2
|
|
||||||
VLVGG $1, R5SAVE_1, R5_1
|
|
||||||
VLVGG $1, R5SAVE_2, R5_2
|
|
||||||
|
|
||||||
// setup [h0, h1]
|
|
||||||
VSLDB $8, H0_0, H0_0, H0_0
|
|
||||||
VSLDB $8, H1_0, H1_0, H1_0
|
|
||||||
VSLDB $8, H2_0, H2_0, H2_0
|
|
||||||
VO H0_1, H0_0, H0_0
|
|
||||||
VO H1_1, H1_0, H1_0
|
|
||||||
VO H2_1, H2_0, H2_0
|
|
||||||
VZERO H0_1
|
|
||||||
VZERO H1_1
|
|
||||||
VZERO H2_1
|
|
||||||
|
|
||||||
VZERO M0
|
|
||||||
VZERO M1
|
|
||||||
VZERO M2
|
|
||||||
VZERO M3
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
|
|
||||||
// H*[r**2, r]
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9)
|
|
||||||
VMRHG V0, H0_1, H0_0
|
|
||||||
VMRHG V0, H1_1, H1_0
|
|
||||||
VMRHG V0, H2_1, H2_0
|
|
||||||
VMRLG V0, H0_1, H0_1
|
|
||||||
VMRLG V0, H1_1, H1_1
|
|
||||||
VMRLG V0, H2_1, H2_1
|
|
||||||
|
|
||||||
// move h to the left and 0s at the right
|
|
||||||
VSLDB $8, H0_0, H0_0, H0_0
|
|
||||||
VSLDB $8, H1_0, H1_0, H1_0
|
|
||||||
VSLDB $8, H2_0, H2_0, H2_0
|
|
||||||
|
|
||||||
// get message blocks and append 1 to start
|
|
||||||
SUB $17, R3
|
|
||||||
VL (R2), M0
|
|
||||||
VLL R3, 16(R2), M1
|
|
||||||
ADD $1, R3
|
|
||||||
MOVBZ $1, R0
|
|
||||||
CMPBEQ R3, $16, 2(PC)
|
|
||||||
VLVGB R3, R0, M1
|
|
||||||
VZERO T_6
|
|
||||||
VZERO T_7
|
|
||||||
VZERO T_8
|
|
||||||
EXPACC2(M0, T_6, T_7, T_8, T_1, T_2, T_3)
|
|
||||||
EXPACC2(M1, T_6, T_7, T_8, T_1, T_2, T_3)
|
|
||||||
VLEIB $2, $1, T_8
|
|
||||||
CMPBNE R3, $16, 2(PC)
|
|
||||||
VLEIB $10, $1, T_8
|
|
||||||
|
|
||||||
// add [m0, m1] to h
|
|
||||||
VAG H0_0, T_6, H0_0
|
|
||||||
VAG H1_0, T_7, H1_0
|
|
||||||
VAG H2_0, T_8, H2_0
|
|
||||||
|
|
||||||
VZERO M2
|
|
||||||
VZERO M3
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
VZERO T_10
|
|
||||||
VZERO M0
|
|
||||||
|
|
||||||
// at this point R_0 .. R5_2 look like [r**2, r]
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M2, M3, M4, M5, T_10, M0, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M2, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10)
|
|
||||||
SUB $16, R3, R3
|
|
||||||
CMPBLE R3, $0, next
|
|
||||||
|
|
||||||
b1:
|
|
||||||
CMPBLE R3, $0, next
|
|
||||||
|
|
||||||
// 1 block remaining
|
|
||||||
|
|
||||||
// setup [r²,r]
|
|
||||||
VSLDB $8, R_0, R_0, R_0
|
|
||||||
VSLDB $8, R_1, R_1, R_1
|
|
||||||
VSLDB $8, R_2, R_2, R_2
|
|
||||||
VSLDB $8, R5_1, R5_1, R5_1
|
|
||||||
VSLDB $8, R5_2, R5_2, R5_2
|
|
||||||
|
|
||||||
VLVGG $1, RSAVE_0, R_0
|
|
||||||
VLVGG $1, RSAVE_1, R_1
|
|
||||||
VLVGG $1, RSAVE_2, R_2
|
|
||||||
VLVGG $1, R5SAVE_1, R5_1
|
|
||||||
VLVGG $1, R5SAVE_2, R5_2
|
|
||||||
|
|
||||||
// setup [h0, h1]
|
|
||||||
VSLDB $8, H0_0, H0_0, H0_0
|
|
||||||
VSLDB $8, H1_0, H1_0, H1_0
|
|
||||||
VSLDB $8, H2_0, H2_0, H2_0
|
|
||||||
VO H0_1, H0_0, H0_0
|
|
||||||
VO H1_1, H1_0, H1_0
|
|
||||||
VO H2_1, H2_0, H2_0
|
|
||||||
VZERO H0_1
|
|
||||||
VZERO H1_1
|
|
||||||
VZERO H2_1
|
|
||||||
|
|
||||||
VZERO M0
|
|
||||||
VZERO M1
|
|
||||||
VZERO M2
|
|
||||||
VZERO M3
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
|
|
||||||
// H*[r**2, r]
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
|
|
||||||
|
|
||||||
// set up [0, m0] limbs
|
|
||||||
SUB $1, R3
|
|
||||||
VLL R3, (R2), M0
|
|
||||||
ADD $1, R3
|
|
||||||
MOVBZ $1, R0
|
|
||||||
CMPBEQ R3, $16, 2(PC)
|
|
||||||
VLVGB R3, R0, M0
|
|
||||||
VZERO T_1
|
|
||||||
VZERO T_2
|
|
||||||
VZERO T_3
|
|
||||||
EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)// limbs: [0, m]
|
|
||||||
CMPBNE R3, $16, 2(PC)
|
|
||||||
VLEIB $10, $1, T_3
|
|
||||||
|
|
||||||
// h+m0
|
|
||||||
VAQ H0_0, T_1, H0_0
|
|
||||||
VAQ H1_0, T_2, H1_0
|
|
||||||
VAQ H2_0, T_3, H2_0
|
|
||||||
|
|
||||||
VZERO M0
|
|
||||||
VZERO M1
|
|
||||||
VZERO M2
|
|
||||||
VZERO M3
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
|
|
||||||
|
|
||||||
BR next
|
|
||||||
|
|
||||||
square:
|
|
||||||
// setup [r²,r]
|
|
||||||
VSLDB $8, R_0, R_0, R_0
|
|
||||||
VSLDB $8, R_1, R_1, R_1
|
|
||||||
VSLDB $8, R_2, R_2, R_2
|
|
||||||
VSLDB $8, R5_1, R5_1, R5_1
|
|
||||||
VSLDB $8, R5_2, R5_2, R5_2
|
|
||||||
|
|
||||||
VLVGG $1, RSAVE_0, R_0
|
|
||||||
VLVGG $1, RSAVE_1, R_1
|
|
||||||
VLVGG $1, RSAVE_2, R_2
|
|
||||||
VLVGG $1, R5SAVE_1, R5_1
|
|
||||||
VLVGG $1, R5SAVE_2, R5_2
|
|
||||||
|
|
||||||
// setup [h0, h1]
|
|
||||||
VSLDB $8, H0_0, H0_0, H0_0
|
|
||||||
VSLDB $8, H1_0, H1_0, H1_0
|
|
||||||
VSLDB $8, H2_0, H2_0, H2_0
|
|
||||||
VO H0_1, H0_0, H0_0
|
|
||||||
VO H1_1, H1_0, H1_0
|
|
||||||
VO H2_1, H2_0, H2_0
|
|
||||||
VZERO H0_1
|
|
||||||
VZERO H1_1
|
|
||||||
VZERO H2_1
|
|
||||||
|
|
||||||
VZERO M0
|
|
||||||
VZERO M1
|
|
||||||
VZERO M2
|
|
||||||
VZERO M3
|
|
||||||
VZERO M4
|
|
||||||
VZERO M5
|
|
||||||
|
|
||||||
// (h0*r**2) + (h1*r)
|
|
||||||
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
|
|
||||||
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
|
|
||||||
BR next
|
|
||||||
|
|
||||||
TEXT ·hasVMSLFacility(SB), NOSPLIT, $24-1
|
|
||||||
MOVD $x-24(SP), R1
|
|
||||||
XC $24, 0(R1), 0(R1) // clear the storage
|
|
||||||
MOVD $2, R0 // R0 is the number of double words stored -1
|
|
||||||
WORD $0xB2B01000 // STFLE 0(R1)
|
|
||||||
XOR R0, R0 // reset the value of R0
|
|
||||||
MOVBZ z-8(SP), R1
|
|
||||||
AND $0x01, R1
|
|
||||||
BEQ novmsl
|
|
||||||
|
|
||||||
vectorinstalled:
|
|
||||||
// check if the vector instruction has been enabled
|
|
||||||
VLEIB $0, $0xF, V16
|
|
||||||
VLGVB $0, V16, R1
|
|
||||||
CMPBNE R1, $0xF, novmsl
|
|
||||||
MOVB $1, ret+0(FP) // have vx
|
|
||||||
RET
|
|
||||||
|
|
||||||
novmsl:
|
|
||||||
MOVB $0, ret+0(FP) // no vx
|
|
||||||
RET
|
|
||||||
43
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
43
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
|
|
@ -16,7 +16,6 @@ import (
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/bits"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/internal/chacha20"
|
"golang.org/x/crypto/internal/chacha20"
|
||||||
"golang.org/x/crypto/poly1305"
|
"golang.org/x/crypto/poly1305"
|
||||||
|
|
@ -642,8 +641,8 @@ const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
|
||||||
// the methods here also implement padding, which RFC4253 Section 6
|
// the methods here also implement padding, which RFC4253 Section 6
|
||||||
// also requires of stream ciphers.
|
// also requires of stream ciphers.
|
||||||
type chacha20Poly1305Cipher struct {
|
type chacha20Poly1305Cipher struct {
|
||||||
lengthKey [8]uint32
|
lengthKey [32]byte
|
||||||
contentKey [8]uint32
|
contentKey [32]byte
|
||||||
buf []byte
|
buf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -656,21 +655,20 @@ func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionA
|
||||||
buf: make([]byte, 256),
|
buf: make([]byte, 256),
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range c.contentKey {
|
copy(c.contentKey[:], key[:32])
|
||||||
c.contentKey[i] = binary.LittleEndian.Uint32(key[i*4 : (i+1)*4])
|
copy(c.lengthKey[:], key[32:])
|
||||||
}
|
|
||||||
for i := range c.lengthKey {
|
|
||||||
c.lengthKey[i] = binary.LittleEndian.Uint32(key[(i+8)*4 : (i+9)*4])
|
|
||||||
}
|
|
||||||
return c, nil
|
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) {
|
func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
|
||||||
nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)}
|
var counter [16]byte
|
||||||
s := chacha20.New(c.contentKey, nonce)
|
binary.BigEndian.PutUint64(counter[8:], uint64(seqNum))
|
||||||
|
|
||||||
var polyKey [32]byte
|
var polyKey [32]byte
|
||||||
s.XORKeyStream(polyKey[:], polyKey[:])
|
chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey)
|
||||||
s.Advance() // skip next 32 bytes
|
|
||||||
|
|
||||||
encryptedLength := c.buf[:4]
|
encryptedLength := c.buf[:4]
|
||||||
if _, err := io.ReadFull(r, encryptedLength); err != nil {
|
if _, err := io.ReadFull(r, encryptedLength); err != nil {
|
||||||
|
|
@ -678,7 +676,7 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte,
|
||||||
}
|
}
|
||||||
|
|
||||||
var lenBytes [4]byte
|
var lenBytes [4]byte
|
||||||
chacha20.New(c.lengthKey, nonce).XORKeyStream(lenBytes[:], encryptedLength)
|
chacha20.XORKeyStream(lenBytes[:], encryptedLength, &counter, &c.lengthKey)
|
||||||
|
|
||||||
length := binary.BigEndian.Uint32(lenBytes[:])
|
length := binary.BigEndian.Uint32(lenBytes[:])
|
||||||
if length > maxPacket {
|
if length > maxPacket {
|
||||||
|
|
@ -704,8 +702,10 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte,
|
||||||
return nil, errors.New("ssh: MAC failure")
|
return nil, errors.New("ssh: MAC failure")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
counter[0] = 1
|
||||||
|
|
||||||
plain := c.buf[4:contentEnd]
|
plain := c.buf[4:contentEnd]
|
||||||
s.XORKeyStream(plain, plain)
|
chacha20.XORKeyStream(plain, plain, &counter, &c.contentKey)
|
||||||
|
|
||||||
padding := plain[0]
|
padding := plain[0]
|
||||||
if padding < 4 {
|
if padding < 4 {
|
||||||
|
|
@ -724,11 +724,11 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
|
func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
|
||||||
nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)}
|
var counter [16]byte
|
||||||
s := chacha20.New(c.contentKey, nonce)
|
binary.BigEndian.PutUint64(counter[8:], uint64(seqNum))
|
||||||
|
|
||||||
var polyKey [32]byte
|
var polyKey [32]byte
|
||||||
s.XORKeyStream(polyKey[:], polyKey[:])
|
chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey)
|
||||||
s.Advance() // skip next 32 bytes
|
|
||||||
|
|
||||||
// There is no blocksize, so fall back to multiple of 8 byte
|
// There is no blocksize, so fall back to multiple of 8 byte
|
||||||
// padding, as described in RFC 4253, Sec 6.
|
// padding, as described in RFC 4253, Sec 6.
|
||||||
|
|
@ -748,7 +748,7 @@ func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io
|
||||||
}
|
}
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding))
|
binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding))
|
||||||
chacha20.New(c.lengthKey, nonce).XORKeyStream(c.buf, c.buf[:4])
|
chacha20.XORKeyStream(c.buf, c.buf[:4], &counter, &c.lengthKey)
|
||||||
c.buf[4] = byte(padding)
|
c.buf[4] = byte(padding)
|
||||||
copy(c.buf[5:], payload)
|
copy(c.buf[5:], payload)
|
||||||
packetEnd := 5 + len(payload) + padding
|
packetEnd := 5 + len(payload) + padding
|
||||||
|
|
@ -756,7 +756,8 @@ func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd])
|
counter[0] = 1
|
||||||
|
chacha20.XORKeyStream(c.buf[4:], c.buf[4:packetEnd], &counter, &c.contentKey)
|
||||||
|
|
||||||
var mac [poly1305.TagSize]byte
|
var mac [poly1305.TagSize]byte
|
||||||
poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey)
|
poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey)
|
||||||
|
|
|
||||||
4
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
|
|
@ -19,8 +19,6 @@ import (
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Conn
|
Conn
|
||||||
|
|
||||||
handleForwardsOnce sync.Once // guards calling (*Client).handleForwards
|
|
||||||
|
|
||||||
forwards forwardList // forwarded tcpip connections from the remote side
|
forwards forwardList // forwarded tcpip connections from the remote side
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
channelHandlers map[string]chan NewChannel
|
channelHandlers map[string]chan NewChannel
|
||||||
|
|
@ -62,6 +60,8 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
|
||||||
conn.Wait()
|
conn.Wait()
|
||||||
conn.forwards.closeAll()
|
conn.forwards.closeAll()
|
||||||
}()
|
}()
|
||||||
|
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
|
||||||
|
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1
vendor/golang.org/x/crypto/ssh/streamlocal.go
generated
vendored
1
vendor/golang.org/x/crypto/ssh/streamlocal.go
generated
vendored
|
|
@ -32,7 +32,6 @@ type streamLocalChannelForwardMsg struct {
|
||||||
|
|
||||||
// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
|
// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
|
||||||
func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
|
func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
|
||||||
c.handleForwardsOnce.Do(c.handleForwards)
|
|
||||||
m := streamLocalChannelForwardMsg{
|
m := streamLocalChannelForwardMsg{
|
||||||
socketPath,
|
socketPath,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
vendor/golang.org/x/crypto/ssh/tcpip.go
generated
vendored
9
vendor/golang.org/x/crypto/ssh/tcpip.go
generated
vendored
|
|
@ -90,19 +90,10 @@ type channelForwardMsg struct {
|
||||||
rport uint32
|
rport uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleForwards starts goroutines handling forwarded connections.
|
|
||||||
// It's called on first use by (*Client).ListenTCP to not launch
|
|
||||||
// goroutines until needed.
|
|
||||||
func (c *Client) handleForwards() {
|
|
||||||
go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-tcpip"))
|
|
||||||
go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListenTCP requests the remote peer open a listening socket
|
// ListenTCP requests the remote peer open a listening socket
|
||||||
// on laddr. Incoming connections will be available by calling
|
// on laddr. Incoming connections will be available by calling
|
||||||
// Accept on the returned net.Listener.
|
// Accept on the returned net.Listener.
|
||||||
func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
|
func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
|
||||||
c.handleForwardsOnce.Do(c.handleForwards)
|
|
||||||
if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
|
if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
|
||||||
return c.autoPortListenWorkaround(laddr)
|
return c.autoPortListenWorkaround(laddr)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user